added pptr pointer
This commit is contained in:
parent
969cba2c16
commit
55d0d58734
|
@ -41,7 +41,8 @@ pub fn build_py_class(ast: &mut syn::DeriveInput) -> Tokens {
|
|||
const #dummy_const: () = {
|
||||
extern crate pyo3 as _pyo3;
|
||||
use std;
|
||||
use pyo3::python::PythonObjectWithToken;
|
||||
use pyo3::PythonObjectWithToken;
|
||||
use pyo3::python::PythonObjectWithCheckedDowncast;
|
||||
|
||||
#tokens
|
||||
};
|
||||
|
@ -53,7 +54,7 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident, token: Option<syn::Ident>) ->
|
|||
|
||||
let extra = if let Some(token) = token {
|
||||
Some(quote! {
|
||||
impl _pyo3::python::PythonObjectWithToken for #cls {
|
||||
impl _pyo3::PythonObjectWithToken for #cls {
|
||||
fn token<'p>(&'p self) -> _pyo3::python::Python<'p> {
|
||||
self.#token.token()
|
||||
}
|
||||
|
@ -63,9 +64,10 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident, token: Option<syn::Ident>) ->
|
|||
fn fmt(&self, f : &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||
let ptr = <#cls as _pyo3::python::ToPythonPointer>::as_ptr(self);
|
||||
let repr = unsafe {
|
||||
_pyo3::Py::<_pyo3::PyString>::cast_from_owned_nullptr(
|
||||
PyString::downcast_from_owned_ptr(
|
||||
self.token(), _pyo3::ffi::PyObject_Repr(ptr))
|
||||
.map_err(|_| std::fmt::Error)? };
|
||||
.map_err(|_| std::fmt::Error)?
|
||||
};
|
||||
f.write_str(&repr.to_string_lossy())
|
||||
}
|
||||
}
|
||||
|
@ -73,11 +75,12 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident, token: Option<syn::Ident>) ->
|
|||
impl std::fmt::Display for #cls {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||
let ptr = <#cls as _pyo3::python::ToPythonPointer>::as_ptr(self);
|
||||
let s = unsafe {
|
||||
_pyo3::Py::<_pyo3::PyString>::cast_from_owned_nullptr(
|
||||
self.token(), _pyo3::ffi::PyObject_Str(ptr)
|
||||
).map_err(|_| std::fmt::Error)?};
|
||||
f.write_str(&s.to_string_lossy())
|
||||
let str_obj = unsafe {
|
||||
PyString::downcast_from_owned_ptr(
|
||||
self.token(), _pyo3::ffi::PyObject_Str(ptr))
|
||||
.map_err(|_| std::fmt::Error)?
|
||||
};
|
||||
f.write_str(&str_obj.to_string_lossy())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
//! See also the macros `py_argparse!`, `py_fn!` and `py_method!`.
|
||||
|
||||
use ffi;
|
||||
use pyptr::{Py};
|
||||
use python::{Python, PythonObjectWithToken};
|
||||
use pyptr::Py;
|
||||
use python::Python;
|
||||
use objects::{PyObject, PyTuple, PyDict, PyString, exc};
|
||||
use conversion::RefFromPyObject;
|
||||
use err::{self, PyResult};
|
||||
|
@ -44,9 +44,9 @@ pub struct ParamDescription<'a> {
|
|||
/// Must have same length as `params` and must be initialized to `None`.
|
||||
pub fn parse_args<'p>(py: Python<'p>,
|
||||
fname: Option<&str>, params: &[ParamDescription],
|
||||
args: &'p PyTuple, kwargs: Option<&'p PyDict>,
|
||||
args: &'p PyTuple, kwargs: Option<&'p Py<'p, PyDict>>,
|
||||
accept_args: bool, accept_kwargs: bool,
|
||||
output: &mut[Option<&'p PyObject>]) -> PyResult<()>
|
||||
output: &mut[Option<PyObject<'p>>]) -> PyResult<()>
|
||||
{
|
||||
assert!(params.len() == output.len());
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@ use ::{Py, CompareOp};
|
|||
use ffi;
|
||||
use err::{PyErr, PyResult};
|
||||
use python::{Python, IntoPythonPointer};
|
||||
use objects::{exc, PyObject};
|
||||
use objects::PyObject;
|
||||
use objects::exc;
|
||||
use typeob::PyTypeInfo;
|
||||
use conversion::{ToPyObject, FromPyObject, IntoPyObject};
|
||||
use callback::{PyObjectCallbackConverter, HashConverter, BoolCallbackConverter};
|
||||
|
|
|
@ -10,7 +10,7 @@ use std::os::raw::c_int;
|
|||
use ffi;
|
||||
use err::PyResult;
|
||||
use python::Python;
|
||||
use objects::{PyObject, PyType};
|
||||
use objects::{PyType, PyObject};
|
||||
use callback::{PyObjectCallbackConverter, UnitCallbackConverter};
|
||||
use typeob::PyTypeInfo;
|
||||
use class::methods::PyMethodDef;
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
use ffi;
|
||||
use err::{PyErr, PyResult};
|
||||
use python::Python;
|
||||
use objects::{exc, PyObject};
|
||||
use objects::exc;
|
||||
use objects::PyObject;
|
||||
use callback::{PyObjectCallbackConverter, LenResultConverter};
|
||||
use conversion::{ToPyObject, FromPyObject};
|
||||
use typeob::PyTypeInfo;
|
||||
|
|
|
@ -42,3 +42,5 @@ pub enum CompareOp {
|
|||
Gt = ffi::Py_GT as isize,
|
||||
Ge = ffi::Py_GE as isize
|
||||
}
|
||||
|
||||
pub trait PyCustomObject : Sized {}
|
||||
|
|
|
@ -8,7 +8,8 @@ use std::os::raw::c_int;
|
|||
use ffi;
|
||||
use python::Python;
|
||||
use err::{PyErr, PyResult};
|
||||
use objects::{exc, PyObject};
|
||||
use objects::exc;
|
||||
use objects::PyObject;
|
||||
use callback::{PyObjectCallbackConverter, LenResultConverter, BoolCallbackConverter};
|
||||
use typeob::PyTypeInfo;
|
||||
use conversion::{ToPyObject, IntoPyObject, FromPyObject};
|
||||
|
|
|
@ -3,14 +3,14 @@ use err::PyResult;
|
|||
use pyptr::{Py, PyPtr};
|
||||
use python::{Python, ToPythonPointer};
|
||||
use objects::{PyObject, PyTuple};
|
||||
use typeob::{PyTypeInfo};
|
||||
use token::PyObjectMarker;
|
||||
|
||||
|
||||
/// Conversion trait that allows various objects to be converted into PyObject
|
||||
pub trait ToPyObject {
|
||||
|
||||
/// Converts self into a Python object.
|
||||
fn to_object<'p>(&self, py: Python<'p>) -> PyPtr<PyObject>;
|
||||
fn to_object<'p>(&self, py: Python<'p>) -> PyPtr<PyObjectMarker>;
|
||||
|
||||
/// Converts self into a Python object and calls the specified closure
|
||||
/// on the native FFI pointer underlying the Python object.
|
||||
|
@ -30,7 +30,7 @@ pub trait IntoPyObject {
|
|||
|
||||
/// Converts self into a Python object. (Consumes self)
|
||||
#[inline]
|
||||
fn into_object(self, py: Python) -> PyPtr<PyObject>
|
||||
fn into_object(self, py: Python) -> PyPtr<PyObjectMarker>
|
||||
where Self: Sized;
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ pub trait IntoPyObject {
|
|||
pub trait ToPyTuple {
|
||||
|
||||
/// Converts self into a PyTuple object.
|
||||
fn to_py_tuple<'p>(&self, py: Python<'p>) -> PyPtr<PyTuple>;
|
||||
fn to_py_tuple<'p>(&self, py: Python<'p>) -> PyTuple<'p>;
|
||||
|
||||
/// Converts self into a PyTuple object and calls the specified closure
|
||||
/// on the native FFI pointer underlying the Python object.
|
||||
|
@ -75,8 +75,7 @@ pub trait ToPyTuple {
|
|||
/// the inherent method `PyObject::extract()` can be used.
|
||||
pub trait FromPyObject<'source> : Sized {
|
||||
/// Extracts `Self` from the source `PyObject`.
|
||||
fn extract<S>(py: &'source Py<'source, S>) -> PyResult<Self>
|
||||
where S: PyTypeInfo;
|
||||
fn extract(py: &'source PyObject<'source>) -> PyResult<Self>;
|
||||
}
|
||||
|
||||
pub trait RefFromPyObject<'p> {
|
||||
|
@ -102,7 +101,7 @@ impl <'p, T: ?Sized> RefFromPyObject<'p> for T
|
|||
impl<T> IntoPyObject for T where T: ToPyObject
|
||||
{
|
||||
#[inline]
|
||||
default fn into_object(self, py: Python) -> PyPtr<PyObject> where Self: Sized
|
||||
default fn into_object(self, py: Python) -> PyPtr<PyObjectMarker>
|
||||
{
|
||||
self.to_object(py)
|
||||
}
|
||||
|
@ -114,7 +113,7 @@ impl<T> IntoPyObject for T where T: ToPyObject
|
|||
impl <'a, T: ?Sized> ToPyObject for &'a T where T: ToPyObject {
|
||||
|
||||
#[inline]
|
||||
default fn to_object(&self, py: Python) -> PyPtr<PyObject> {
|
||||
default fn to_object(&self, py: Python) -> PyPtr<PyObjectMarker> {
|
||||
<T as ToPyObject>::to_object(*self, py)
|
||||
}
|
||||
|
||||
|
@ -130,7 +129,7 @@ impl <'a, T: ?Sized> ToPyObject for &'a T where T: ToPyObject {
|
|||
/// `Option::None` is converted to Python `None`.
|
||||
impl <T> ToPyObject for Option<T> where T: ToPyObject {
|
||||
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObject> {
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObjectMarker> {
|
||||
match *self {
|
||||
Some(ref val) => val.to_object(py),
|
||||
None => py.None()
|
||||
|
@ -140,7 +139,7 @@ impl <T> ToPyObject for Option<T> where T: ToPyObject {
|
|||
|
||||
impl<T> IntoPyObject for Option<T> where T: IntoPyObject {
|
||||
|
||||
fn into_object(self, py: Python) -> PyPtr<PyObject> {
|
||||
fn into_object(self, py: Python) -> PyPtr<PyObjectMarker> {
|
||||
match self {
|
||||
Some(val) => val.into_object(py),
|
||||
None => py.None()
|
||||
|
@ -151,15 +150,14 @@ impl<T> IntoPyObject for Option<T> where T: IntoPyObject {
|
|||
|
||||
/// `()` is converted to Python `None`.
|
||||
impl ToPyObject for () {
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObject> {
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObjectMarker> {
|
||||
py.None()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl <'source, T> FromPyObject<'source> for Option<T> where T: FromPyObject<'source> {
|
||||
fn extract<S>(obj: &'source Py<'source, S>) -> PyResult<Self>
|
||||
where S: PyTypeInfo
|
||||
fn extract(obj: &'source PyObject) -> PyResult<Self>
|
||||
{
|
||||
if obj.as_ptr() == unsafe { ffi::Py_None() } {
|
||||
Ok(None)
|
||||
|
|
21
src/err.rs
21
src/err.rs
|
@ -6,8 +6,9 @@ use ffi;
|
|||
use pyptr::{Py, PyPtr};
|
||||
use python::{ToPythonPointer, IntoPythonPointer, Python};
|
||||
use objects::{PyObject, PyType, exc};
|
||||
use token::PyObjectMarker;
|
||||
use typeob::{PyTypeObject};
|
||||
use conversion::{ToPyObject, ToPyTuple};
|
||||
use conversion::{ToPyObject, ToPyTuple, IntoPyObject};
|
||||
|
||||
/**
|
||||
Defines a new exception type.
|
||||
|
@ -91,9 +92,9 @@ pub struct PyErr {
|
|||
/// a tuple of arguments to be passed to `ptype`'s constructor,
|
||||
/// or a single argument to be passed to `ptype`'s constructor.
|
||||
/// Call `PyErr::instance()` to get the exception instance in all cases.
|
||||
pub pvalue: Option<PyPtr<PyObject>>,
|
||||
pub pvalue: Option<PyPtr<PyObjectMarker>>,
|
||||
/// The `PyTraceBack` object associated with the error.
|
||||
pub ptraceback: Option<PyPtr<PyObject>>,
|
||||
pub ptraceback: Option<PyPtr<PyObjectMarker>>,
|
||||
}
|
||||
|
||||
|
||||
|
@ -184,7 +185,7 @@ impl PyErr {
|
|||
}
|
||||
}
|
||||
|
||||
fn new_helper(_py: Python, ty: PyPtr<PyType>, value: PyPtr<PyObject>) -> PyErr {
|
||||
fn new_helper(_py: Python, ty: PyPtr<PyType>, value: PyPtr<PyObjectMarker>) -> PyErr {
|
||||
assert!(unsafe { ffi::PyExceptionClass_Check(ty.as_ptr()) } != 0);
|
||||
PyErr {
|
||||
ptype: ty,
|
||||
|
@ -202,7 +203,7 @@ impl PyErr {
|
|||
PyErr::from_instance_helper(py, obj.to_object(py))
|
||||
}
|
||||
|
||||
fn from_instance_helper<'p>(py: Python, obj: PyPtr<PyObject>) -> PyErr {
|
||||
fn from_instance_helper<'p>(py: Python, obj: PyPtr<PyObjectMarker>) -> PyErr {
|
||||
if unsafe { ffi::PyExceptionInstance_Check(obj.as_ptr()) } != 0 {
|
||||
PyErr {
|
||||
ptype: unsafe { PyPtr::<PyType>::from_borrowed_ptr(
|
||||
|
@ -229,7 +230,7 @@ impl PyErr {
|
|||
/// `exc` is the exception type; usually one of the standard exceptions like `py.get_type::<exc::RuntimeError>()`.
|
||||
/// `value` is the exception instance, or a tuple of arguments to pass to the exception constructor.
|
||||
#[inline]
|
||||
pub fn new_lazy_init(exc: PyPtr<PyType>, value: Option<PyPtr<PyObject>>) -> PyErr {
|
||||
pub fn new_lazy_init(exc: PyPtr<PyType>, value: Option<PyPtr<PyObjectMarker>>) -> PyErr {
|
||||
PyErr {
|
||||
ptype: exc,
|
||||
pvalue: value,
|
||||
|
@ -248,7 +249,7 @@ impl PyErr {
|
|||
let pval = args.to_py_tuple(py);
|
||||
PyErr {
|
||||
ptype: exc.into_pptr(),
|
||||
pvalue: Some(pval.into_object()),
|
||||
pvalue: Some(pval.into_object(py)),
|
||||
ptraceback: None
|
||||
}
|
||||
}
|
||||
|
@ -307,11 +308,11 @@ impl PyErr {
|
|||
/// Retrieves the exception instance for this error.
|
||||
/// This method takes `&mut self` because the error might need
|
||||
/// to be normalized in order to create the exception instance.
|
||||
pub fn instance<'p>(&mut self, py: Python<'p>) -> Py<'p, PyObject> {
|
||||
pub fn instance<'p>(&mut self, py: Python<'p>) -> PyObject<'p> {
|
||||
self.normalize(py);
|
||||
match self.pvalue {
|
||||
Some(ref instance) => instance.as_ref(py),
|
||||
None => py.None().as_ref(py),
|
||||
Some(ref instance) => instance.as_ref(py).into_pyobject(),
|
||||
None => py.None().as_ref(py).into_pyobject(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -861,3 +861,7 @@ pub const Py_NE : c_int = 3;
|
|||
pub const Py_GT : c_int = 4;
|
||||
pub const Py_GE : c_int = 5;
|
||||
|
||||
|
||||
pub fn PyObject_Check(_arg1: *mut PyObject) -> c_int {
|
||||
1
|
||||
}
|
||||
|
|
|
@ -67,10 +67,16 @@ pub use ffi::{Py_ssize_t, Py_hash_t};
|
|||
pub mod pyptr;
|
||||
pub use pyptr::{Py, PyPtr};
|
||||
|
||||
mod ppptr;
|
||||
pub use ppptr::pptr;
|
||||
|
||||
mod token;
|
||||
pub use token::{PyObjectMarker, PythonToken, PythonObjectWithToken};
|
||||
|
||||
pub use err::{PyErr, PyResult, PyDowncastError};
|
||||
pub use objects::*;
|
||||
pub use objectprotocol::ObjectProtocol;
|
||||
pub use python::{Python, PythonToken, IntoPythonPointer, PythonObjectWithToken};
|
||||
pub use python::{Python, IntoPythonPointer};
|
||||
pub use pythonrun::{GILGuard, GILProtected, prepare_freethreaded_python};
|
||||
pub use conversion::{FromPyObject, RefFromPyObject, ToPyObject, IntoPyObject, ToPyTuple};
|
||||
pub use class::{CompareOp};
|
||||
|
@ -106,6 +112,7 @@ macro_rules! py_replace_expr {
|
|||
}
|
||||
|
||||
pub mod python;
|
||||
pub mod native;
|
||||
mod err;
|
||||
mod conversion;
|
||||
mod objects;
|
||||
|
|
31
src/native.rs
Normal file
31
src/native.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
|
||||
// use python::{Python, ToPythonPointer, PythonObjectWithCheckedDowncast};
|
||||
// use err::{PyErr, PyResult};
|
||||
// use ppptr::pptr;
|
||||
// use pyptr::Py;
|
||||
use typeob::PyTypeInfo;
|
||||
// use conversion::{ToPyObject, FromPyObject};
|
||||
|
||||
|
||||
pub trait PyNativeObject : PyTypeInfo {}
|
||||
|
||||
|
||||
/*impl<'a, T: Sized> FromPyObject<'a> for T
|
||||
where T: PyNativeObject + PythonObjectWithCheckedDowncast
|
||||
{
|
||||
/// Extracts `Self` from the source `Py<PyObject>`.
|
||||
fn extract<S>(py: &'a Py<'a, S>) -> PyResult<Self> where S: PyTypeInfo
|
||||
{
|
||||
<T as PythonObjectWithCheckedDowncast>
|
||||
::downcast_from(py.clone_ref()).map_err(|e| e.into())
|
||||
}
|
||||
}*/
|
||||
|
||||
/*impl<T> ::IntoPyObject for T where T: PyNativeObject
|
||||
{
|
||||
#[inline]
|
||||
default fn into_object(self, py: Python) -> ::PyPtr<PyObject>
|
||||
{
|
||||
unsafe { ::std::mem::transmute(self) }
|
||||
}
|
||||
}*/
|
|
@ -7,8 +7,9 @@ use std::cmp::Ordering;
|
|||
use ffi;
|
||||
use libc;
|
||||
use pyptr::{Py, PyPtr};
|
||||
use python::{Python, ToPythonPointer, PythonObjectWithToken};
|
||||
use python::{Python, ToPythonPointer};
|
||||
use objects::{PyObject, PyDict, PyString};
|
||||
use token::PythonObjectWithToken;
|
||||
use conversion::{ToPyObject, ToPyTuple};
|
||||
use typeob::PyTypeInfo;
|
||||
use err::{PyErr, PyResult, self};
|
||||
|
@ -220,7 +221,7 @@ impl<T> ObjectProtocol for T where T: PythonObjectWithToken + ToPythonPointer {
|
|||
-> PyResult<Py<PyObject>> where O: ToPyObject {
|
||||
unsafe {
|
||||
other.with_borrowed_ptr(self.token(), |other| {
|
||||
Py::cast_from_owned_nullptr(
|
||||
Py::cast_from_owned_or_err(
|
||||
self.token(), ffi::PyObject_RichCompare(
|
||||
self.as_ptr(), other, compare_op as libc::c_int))
|
||||
})
|
||||
|
@ -231,14 +232,14 @@ impl<T> ObjectProtocol for T where T: PythonObjectWithToken + ToPythonPointer {
|
|||
/// This is equivalent to the Python expression 'repr(self)'.
|
||||
#[inline]
|
||||
fn repr(&self) -> PyResult<Py<PyString>> {
|
||||
unsafe { Py::cast_from_owned_nullptr(self.token(), ffi::PyObject_Repr(self.as_ptr())) }
|
||||
unsafe { Py::cast_from_owned_or_err(self.token(), ffi::PyObject_Repr(self.as_ptr())) }
|
||||
}
|
||||
|
||||
/// Compute the string representation of self.
|
||||
/// This is equivalent to the Python expression 'str(self)'.
|
||||
#[inline]
|
||||
fn str(&self) -> PyResult<Py<PyString>> {
|
||||
unsafe { Py::cast_from_owned_nullptr(self.token(), ffi::PyObject_Str(self.as_ptr())) }
|
||||
unsafe { Py::cast_from_owned_or_err(self.token(), ffi::PyObject_Str(self.as_ptr())) }
|
||||
}
|
||||
|
||||
/// Determines whether this object is callable.
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
use ::{PyPtr, PyObject};
|
||||
use ::{pptr, PyPtr};
|
||||
use ffi;
|
||||
use python::{PythonToken, ToPythonPointer, Python};
|
||||
use conversion::{ToPyObject};
|
||||
use token::PyObjectMarker;
|
||||
use python::{ToPythonPointer, Python};
|
||||
use conversion::{ToPyObject, IntoPyObject};
|
||||
|
||||
/// Represents a Python `bool`.
|
||||
pub struct PyBool(PythonToken<PyBool>);
|
||||
pub struct PyBool<'p>(pptr<'p>);
|
||||
|
||||
pyobject_newtype!(PyBool, PyBool_Check, PyBool_Type);
|
||||
pyobject_nativetype!(PyBool, PyBool_Check, PyBool_Type);
|
||||
|
||||
impl PyBool {
|
||||
impl<'p> PyBool<'p> {
|
||||
/// Depending on `val`, returns `py.True()` or `py.False()`.
|
||||
#[inline]
|
||||
pub fn get(py: Python, val: bool) -> PyPtr<PyBool> {
|
||||
pub fn get(py: Python<'p>, val: bool) -> PyBool<'p> {
|
||||
if val { py.True() } else { py.False() }
|
||||
}
|
||||
|
||||
|
@ -25,8 +26,8 @@ impl PyBool {
|
|||
/// Converts a rust `bool` to a Python `bool`.
|
||||
impl ToPyObject for bool {
|
||||
#[inline]
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObject> {
|
||||
PyBool::get(py, *self).into_object()
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObjectMarker> {
|
||||
PyBool::get(py, *self).into_object(py)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -4,35 +4,38 @@ use std;
|
|||
use std::ptr;
|
||||
use std::os::raw::c_char;
|
||||
use ffi;
|
||||
use python::{PythonToken, ToPythonPointer, Python, PythonObjectWithToken};
|
||||
use python::{Python, ToPythonPointer};
|
||||
use objects::PyObject;
|
||||
use err::{PyResult, PyErr};
|
||||
use pyptr::Py;
|
||||
use ppptr::pptr;
|
||||
|
||||
|
||||
/// Represents a Python bytearray.
|
||||
pub struct PyByteArray(PythonToken<PyByteArray>);
|
||||
pub struct PyByteArray<'p>(pptr<'p>);
|
||||
|
||||
pyobject_newtype!(PyByteArray, PyByteArray_Check, PyByteArray_Type);
|
||||
pyobject_nativetype!(PyByteArray, PyByteArray_Check, PyByteArray_Type);
|
||||
|
||||
|
||||
impl PyByteArray {
|
||||
impl<'p> PyByteArray<'p> {
|
||||
/// Creates a new Python bytearray object.
|
||||
/// The byte string is initialized by copying the data from the `&[u8]`.
|
||||
///
|
||||
/// Panics if out of memory.
|
||||
pub fn new<'p>(py: Python<'p>, src: &[u8]) -> Py<'p, PyByteArray> {
|
||||
pub fn new<'a>(py: Python<'a>, src: &[u8]) -> PyByteArray<'a> {
|
||||
let ptr = src.as_ptr() as *const c_char;
|
||||
let len = src.len() as ffi::Py_ssize_t;
|
||||
let ptr = unsafe {ffi::PyByteArray_FromStringAndSize(ptr, len)};
|
||||
unsafe { Py::cast_from_owned_ptr_or_panic(py, ptr) }
|
||||
unsafe { PyByteArray(pptr::cast_from_owned_ptr_or_panic::<PyByteArray>(py, ptr)) }
|
||||
}
|
||||
|
||||
/// Creates a new Python bytearray object
|
||||
/// from other PyObject, that implements the buffer protocol.
|
||||
pub fn from<'p>(src: Py<'p, PyObject>) -> PyResult<Py<'p, PyByteArray>> {
|
||||
pub fn from(src: Py<'p, PyObject>) -> PyResult<PyByteArray<'p>> {
|
||||
let res = unsafe {ffi::PyByteArray_FromObject(src.as_ptr())};
|
||||
if res != ptr::null_mut() {
|
||||
Ok(unsafe{Py::cast_from_owned_ptr_or_panic(src.token(), res)})
|
||||
Ok(unsafe{ PyByteArray(
|
||||
pptr::cast_from_owned_ptr_or_panic::<PyByteArray>(src.token(), res))})
|
||||
} else {
|
||||
Err(PyErr::fetch(src.token()))
|
||||
}
|
||||
|
@ -43,15 +46,15 @@ impl PyByteArray {
|
|||
pub fn len(&self) -> usize {
|
||||
// non-negative Py_ssize_t should always fit into Rust usize
|
||||
unsafe {
|
||||
ffi::PyByteArray_Size(self.as_ptr()) as usize
|
||||
ffi::PyByteArray_Size(self.0.as_ptr()) as usize
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the Python bytearray data as byte slice.
|
||||
pub fn data(&self) -> &mut [u8] {
|
||||
unsafe {
|
||||
let buffer = ffi::PyByteArray_AsString(self.as_ptr()) as *mut u8;
|
||||
let length = ffi::PyByteArray_Size(self.as_ptr()) as usize;
|
||||
let buffer = ffi::PyByteArray_AsString(self.0.as_ptr()) as *mut u8;
|
||||
let length = ffi::PyByteArray_Size(self.0.as_ptr()) as usize;
|
||||
std::slice::from_raw_parts_mut(buffer, length)
|
||||
}
|
||||
}
|
||||
|
@ -59,11 +62,11 @@ impl PyByteArray {
|
|||
/// Resize bytearray object.
|
||||
pub fn resize(&self, len: usize) -> PyResult<()> {
|
||||
unsafe {
|
||||
let result = ffi::PyByteArray_Resize(self.as_ptr(), len as ffi::Py_ssize_t);
|
||||
let result = ffi::PyByteArray_Resize(self.0.as_ptr(), len as ffi::Py_ssize_t);
|
||||
if result == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(PyErr::fetch(self.token()))
|
||||
Err(PyErr::fetch(self.0.token()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,33 +2,37 @@
|
|||
//
|
||||
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
|
||||
|
||||
use ::pptr;
|
||||
use ffi;
|
||||
use pyptr::{Py, PyPtr};
|
||||
use python::{Python, PythonToken, ToPythonPointer, PythonObjectWithToken};
|
||||
use conversion::ToPyObject;
|
||||
use objects::{PyObject}; //, PyList};
|
||||
use pyptr::PyPtr;
|
||||
use python::{Python, ToPythonPointer};
|
||||
use conversion::{ToPyObject, IntoPyObject};
|
||||
use objects::PyObject;
|
||||
use token::{PyObjectMarker, PythonObjectWithToken}; //, PyList};
|
||||
use err::{self, PyResult, PyErr};
|
||||
use std::{mem, collections, hash, cmp};
|
||||
|
||||
/// Represents a Python `dict`.
|
||||
pub struct PyDict(PythonToken<PyDict>);
|
||||
pub struct PyDict<'p>(pptr<'p>);
|
||||
|
||||
pyobject_newtype!(PyDict, PyDict_Check, PyDict_Type);
|
||||
pyobject_nativetype!(PyDict, PyDict_Check, PyDict_Type);
|
||||
|
||||
|
||||
impl PyDict {
|
||||
impl<'p> PyDict<'p> {
|
||||
/// Creates a new empty dictionary.
|
||||
///
|
||||
/// May panic when running out of memory.
|
||||
pub fn new(py: Python) -> Py<PyDict> {
|
||||
unsafe { Py::from_owned_ptr_or_panic(py, ffi::PyDict_New()) }
|
||||
pub fn new(py: Python<'p>) -> PyDict<'p> {
|
||||
unsafe { PyDict(pptr::from_owned_ptr_or_panic(py, ffi::PyDict_New())) }
|
||||
}
|
||||
|
||||
/// Return a new dictionary that contains the same key-value pairs as self.
|
||||
/// Corresponds to `dict(self)` in Python.
|
||||
pub fn copy<'p>(&'p self) -> PyResult<PyPtr<PyDict>> {
|
||||
pub fn copy(&'p self) -> PyResult<PyDict<'p>> {
|
||||
unsafe {
|
||||
PyPtr::from_owned_ptr_or_err(self.token(), ffi::PyDict_Copy(self.as_ptr()))
|
||||
Ok(PyDict(
|
||||
pptr::from_owned_ptr_or_err(self.token(), ffi::PyDict_Copy(self.0.as_ptr()))?
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,9 +63,10 @@ impl PyDict {
|
|||
|
||||
/// Gets an item from the dictionary.
|
||||
/// Returns None if the item is not present, or if an error occurs.
|
||||
pub fn get_item<K>(&self, key: K) -> Option<&PyObject> where K: ToPyObject {
|
||||
pub fn get_item<K>(&self, key: K) -> Option<PyObject> where K: ToPyObject {
|
||||
key.with_borrowed_ptr(self.token(), |key| unsafe {
|
||||
self.token().from_owned_ptr_opt(ffi::PyDict_GetItem(self.as_ptr(), key))
|
||||
PyObject::from_owned_ptr_or_opt(
|
||||
self.token(), ffi::PyDict_GetItem(self.as_ptr(), key))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -117,12 +122,12 @@ impl <K, V> ToPyObject for collections::HashMap<K, V>
|
|||
where K: hash::Hash+cmp::Eq+ToPyObject,
|
||||
V: ToPyObject
|
||||
{
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObject> {
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObjectMarker> {
|
||||
let dict = PyDict::new(py);
|
||||
for (key, value) in self {
|
||||
dict.set_item(key, value).unwrap();
|
||||
};
|
||||
dict.into_object_pptr()
|
||||
dict.into_object(py)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,12 +135,12 @@ impl <K, V> ToPyObject for collections::BTreeMap<K, V>
|
|||
where K: cmp::Eq+ToPyObject,
|
||||
V: ToPyObject
|
||||
{
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObject> {
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObjectMarker> {
|
||||
let dict = PyDict::new(py);
|
||||
for (key, value) in self {
|
||||
dict.set_item(key, value).unwrap();
|
||||
};
|
||||
dict.into_object_pptr()
|
||||
dict.into_object(py)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,28 +2,27 @@
|
|||
//
|
||||
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
|
||||
|
||||
use pyptr::Py;
|
||||
use python::{Python, ToPythonPointer, IntoPythonPointer,
|
||||
PythonToken, PythonObjectWithToken, PythonTokenApi};
|
||||
use ::pptr;
|
||||
use pyptr::{Py, PyPtr};
|
||||
use python::{Python, ToPythonPointer, IntoPythonPointer, PythonToken, PythonObjectWithToken};
|
||||
use objects::PyObject;
|
||||
use ffi::{self, Py_ssize_t};
|
||||
use conversion::{ToPyObject, IntoPyObject};
|
||||
|
||||
/// Represents a Python `list`.
|
||||
pub struct PyList(PythonToken<PyList>);
|
||||
pub struct PyList<'p>(pptr<'p>);
|
||||
|
||||
pyobject_newtype!(PyList, PyList_Check, PyList_Type);
|
||||
pyobject_nativetype!(PyList, PyList_Check, PyList_Type);
|
||||
|
||||
impl PyList {
|
||||
impl<'p> PyList<'p> {
|
||||
/// Construct a new list with the given elements.
|
||||
pub fn new<'p, T: ToPyObject>(py: Python<'p>, elements: &[T]) -> Py<'p, PyList> {
|
||||
pub fn new<T: ToPyObject>(py: Python<'p>, elements: &[T]) -> PyList<'p> {
|
||||
unsafe {
|
||||
let ptr = ffi::PyList_New(elements.len() as Py_ssize_t);
|
||||
let t = Py::<PyList>::cast_from_owned_ptr_or_panic(py, ptr);
|
||||
for (i, e) in elements.iter().enumerate() {
|
||||
ffi::PyList_SetItem(ptr, i as Py_ssize_t, e.to_object(py).into_ptr());
|
||||
}
|
||||
t
|
||||
PyList(pptr::from_owned_ptr_or_panic(py, ptr))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,7 +50,7 @@ impl PyList {
|
|||
/// Sets the item at the specified index.
|
||||
///
|
||||
/// Panics if the index is out of range.
|
||||
pub fn set_item<'p>(&self, index: usize, item: Py<'p, PyObject>) {
|
||||
pub fn set_item(&self, index: usize, item: Py<'p, PyObject>) {
|
||||
let r = unsafe { ffi::PyList_SetItem(
|
||||
self.as_ptr(), index as Py_ssize_t, item.into_ptr()) };
|
||||
assert!(r == 0);
|
||||
|
@ -60,20 +59,20 @@ impl PyList {
|
|||
/// Inserts an item at the specified index.
|
||||
///
|
||||
/// Panics if the index is out of range.
|
||||
pub fn insert_item<'p>(&self, index: usize, item: Py<'p, PyObject>) {
|
||||
pub fn insert_item(&self, index: usize, item: Py<'p, PyObject>) {
|
||||
let r = unsafe { ffi::PyList_Insert(self.as_ptr(), index as Py_ssize_t, item.as_ptr()) };
|
||||
assert!(r == 0);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter<'p>(&'p self) -> PyListIterator<'p> {
|
||||
pub fn iter(&'p self) -> PyListIterator<'p> {
|
||||
PyListIterator { list: self, index: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
/// Used by `PyList::iter()`.
|
||||
pub struct PyListIterator<'p> {
|
||||
list: &'p PyList,
|
||||
list: &'p PyList<'p>,
|
||||
index: usize
|
||||
}
|
||||
|
||||
|
@ -81,7 +80,7 @@ impl <'p> Iterator for PyListIterator<'p> {
|
|||
type Item = Py<'p, PyObject>;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Py<'p, PyObject>> {
|
||||
fn next(&mut self) -> Option<&'p PyObject> {
|
||||
if self.index < self.list.len() {
|
||||
let item = self.list.get_item(self.index);
|
||||
self.index += 1;
|
||||
|
@ -97,22 +96,21 @@ impl <'p> Iterator for PyListIterator<'p> {
|
|||
|
||||
impl <T> ToPyObject for [T] where T: ToPyObject {
|
||||
|
||||
fn to_object<'p>(&self, py: Python<'p>) -> Py<'p, PyObject> {
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObject> {
|
||||
unsafe {
|
||||
let ptr = ffi::PyList_New(self.len() as Py_ssize_t);
|
||||
let t = Py::cast_from_owned_ptr_or_panic(py, ptr);
|
||||
for (i, e) in self.iter().enumerate() {
|
||||
let obj = e.to_object(py).into_ptr();
|
||||
ffi::PyList_SetItem(ptr, i as Py_ssize_t, obj);
|
||||
}
|
||||
t
|
||||
PyPtr::from_owned_ptr_or_panic(ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl <T> ToPyObject for Vec<T> where T: ToPyObject {
|
||||
|
||||
fn to_object<'p>(&self, py: Python<'p>) -> Py<'p, PyObject> {
|
||||
fn to_object<'p>(&self, py: Python<'p>) -> PyPtr<PyObject> {
|
||||
self.as_slice().to_object(py)
|
||||
}
|
||||
|
||||
|
@ -120,15 +118,14 @@ impl <T> ToPyObject for Vec<T> where T: ToPyObject {
|
|||
|
||||
impl <T> IntoPyObject for Vec<T> where T: IntoPyObject {
|
||||
|
||||
fn into_object<'p>(self, py: Python<'p>) -> Py<'p, PyObject> {
|
||||
fn into_object(self, py: Python) -> PyPtr<PyObject> {
|
||||
unsafe {
|
||||
let ptr = ffi::PyList_New(self.len() as Py_ssize_t);
|
||||
let t = Py::from_owned_ptr_or_panic(py, ptr);
|
||||
for (i, e) in self.into_iter().enumerate() {
|
||||
let obj = e.into_object(py).into_ptr();
|
||||
ffi::PyList_SetItem(ptr, i as Py_ssize_t, obj);
|
||||
}
|
||||
t
|
||||
PyPtr::from_owned_ptr_or_panic(ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ macro_rules! pyobject_newtype(
|
|||
}
|
||||
}
|
||||
|
||||
impl $crate::python::PythonObjectWithToken for $name {
|
||||
impl $crate::token::PythonObjectWithToken for $name {
|
||||
fn token<'p>(&'p self) -> $crate::python::Python<'p> {
|
||||
self.0.token()
|
||||
}
|
||||
|
@ -53,8 +53,8 @@ macro_rules! pyobject_newtype(
|
|||
default fn fmt(&self, f: &mut $crate::std::fmt::Formatter)
|
||||
-> Result<(), $crate::std::fmt::Error>
|
||||
{
|
||||
let py = <$name as $crate::python::PythonObjectWithToken>::token(self);
|
||||
let s = unsafe { $crate::Py::<$crate::PyString>::cast_from_owned_nullptr(
|
||||
let py = <$name as $crate::token::PythonObjectWithToken>::token(self);
|
||||
let s = unsafe { $crate::Py::<$crate::PyString>::cast_from_owned_or_err(
|
||||
py, $crate::ffi::PyObject_Repr(
|
||||
$crate::python::ToPythonPointer::as_ptr(self))) };
|
||||
let repr_obj = try!(s.map_err(|_| $crate::std::fmt::Error));
|
||||
|
@ -66,8 +66,8 @@ macro_rules! pyobject_newtype(
|
|||
fn fmt(&self, f: &mut $crate::std::fmt::Formatter)
|
||||
-> Result<(), $crate::std::fmt::Error>
|
||||
{
|
||||
let py = <$name as $crate::python::PythonObjectWithToken>::token(self);
|
||||
let s = unsafe { $crate::Py::<$crate::PyString>::cast_from_owned_nullptr(
|
||||
let py = <$name as $crate::token::PythonObjectWithToken>::token(self);
|
||||
let s = unsafe { $crate::Py::<$crate::PyString>::cast_from_owned_or_err(
|
||||
py, $crate::ffi::PyObject_Str(
|
||||
$crate::python::ToPythonPointer::as_ptr(self))) };
|
||||
let str_obj = try!(s.map_err(|_| $crate::std::fmt::Error));
|
||||
|
@ -77,13 +77,160 @@ macro_rules! pyobject_newtype(
|
|||
);
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pyobject_nativetype(
|
||||
($name: ident, $checkfunction: ident, $typeobject: ident) => (
|
||||
|
||||
impl<'p> $crate::native::PyNativeObject for $name<'p> {}
|
||||
|
||||
impl<'p> $crate::typeob::PyTypeInfo for $name<'p> {
|
||||
type Type = ();
|
||||
|
||||
#[inline]
|
||||
fn size() -> usize {
|
||||
$crate::std::mem::size_of::<ffi::PyObject>()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn offset() -> isize {
|
||||
0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn type_name() -> &'static str {
|
||||
stringify!($name)
|
||||
}
|
||||
#[inline]
|
||||
fn type_object() -> &'static mut $crate::ffi::PyTypeObject {
|
||||
unsafe { &mut $crate::ffi::$typeobject }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> $crate::token::PythonObjectWithToken for $name<'p> {
|
||||
fn token<'a>(&'a self) -> $crate::python::Python<'a> {
|
||||
self.0.token()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> $crate::python::PythonObjectWithCheckedDowncast<'p> for $name<'p>
|
||||
{
|
||||
fn downcast_from(py: $crate::Py<'p, $crate::PyObject>)
|
||||
-> Result<$name<'p>, $crate::PyDowncastError<'p>>
|
||||
{
|
||||
let inst = $name(
|
||||
$crate::pptr::cast_from_borrowed_ptr::<$name>(py.token(), py.as_ptr())?);
|
||||
Ok(inst)
|
||||
}
|
||||
|
||||
fn downcast_from_owned_ptr(py: $crate::Python<'p>, ptr: *mut $crate::ffi::PyObject)
|
||||
-> Result<$name<'p>, $crate::PyDowncastError<'p>>
|
||||
{
|
||||
Ok($name($crate::pptr::cast_from_owned_ptr::<$name>(py, ptr)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> $crate::python::ToPythonPointer for $name<'p> {
|
||||
/// Gets the underlying FFI pointer, returns a borrowed pointer.
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut $crate::ffi::PyObject {
|
||||
self.0.as_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> $crate::FromPyObject<'a> for $name<'a>
|
||||
{
|
||||
/// Extracts `Self` from the source `Py<PyObject>`.
|
||||
fn extract(py: &'a $crate::PyObject<'a>) -> $crate::PyResult<Self>
|
||||
//where S: $crate::typeob::PyTypeInfo
|
||||
{
|
||||
use $crate::token::PythonObjectWithToken;
|
||||
|
||||
Ok($name(
|
||||
$crate::pptr::cast_from_borrowed_ptr::<$name>(py.token(), py.as_ptr())?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> $crate::FromPyObject<'a> for &'a $name<'a>
|
||||
{
|
||||
/// Extracts `Self` from the source `PyObject`.
|
||||
fn extract(py: &'a $crate::PyObject<'a>) -> $crate::PyResult<Self>
|
||||
//where S: $crate::typeob::PyTypeInfo
|
||||
{
|
||||
unsafe {
|
||||
if ffi::$checkfunction(py.as_ptr()) != 0 {
|
||||
Ok($crate::std::mem::transmute(py))
|
||||
} else {
|
||||
Err($crate::PyDowncastError(
|
||||
$crate::token::PythonObjectWithToken::token(py), None).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> $crate::ToPyObject for $name<'a>
|
||||
{
|
||||
#[inline]
|
||||
default fn to_object<'p>(&self, _py: $crate::Python<'p>)
|
||||
-> $crate::PyPtr<$crate::PyObjectMarker> {
|
||||
unsafe { $crate::PyPtr::from_borrowed_ptr(self.0.as_ptr()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn with_borrowed_ptr<F, R>(&self, _py: $crate::Python, f: F) -> R
|
||||
where F: FnOnce(*mut ffi::PyObject) -> R
|
||||
{
|
||||
f(self.0.as_ptr())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> $crate::IntoPyObject for $name<'a>
|
||||
{
|
||||
#[inline]
|
||||
fn into_object(self, _py: $crate::Python) -> $crate::PyPtr<$crate::PyObjectMarker>
|
||||
{
|
||||
unsafe { $crate::std::mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> $crate::std::fmt::Debug for $name<'p> {
|
||||
default fn fmt(&self, f: &mut $crate::std::fmt::Formatter)
|
||||
-> Result<(), $crate::std::fmt::Error>
|
||||
{
|
||||
use python::PythonObjectWithCheckedDowncast;
|
||||
|
||||
let py = <$name as $crate::token::PythonObjectWithToken>::token(self);
|
||||
println!("DEBUG {:?}", self.as_ptr());
|
||||
let s = unsafe { $crate::PyString::downcast_from_owned_ptr(
|
||||
py, $crate::ffi::PyObject_Repr(
|
||||
$crate::python::ToPythonPointer::as_ptr(self))) };
|
||||
let repr_obj = try!(s.map_err(|_| $crate::std::fmt::Error));
|
||||
f.write_str(&repr_obj.to_string_lossy())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> $crate::std::fmt::Display for $name<'p> {
|
||||
fn fmt(&self, f: &mut $crate::std::fmt::Formatter)
|
||||
-> Result<(), $crate::std::fmt::Error>
|
||||
{
|
||||
let py = <$name as $crate::token::PythonObjectWithToken>::token(self);
|
||||
let s = unsafe { $crate::Py::<$crate::PyString>::cast_from_owned_or_err(
|
||||
py, $crate::ffi::PyObject_Str(
|
||||
$crate::python::ToPythonPointer::as_ptr(self))) };
|
||||
let str_obj = try!(s.map_err(|_| $crate::std::fmt::Error));
|
||||
f.write_str(&str_obj.to_string_lossy())
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
|
||||
macro_rules! pyobject_extract(
|
||||
($obj:ident to $t:ty => $body: block) => {
|
||||
impl<'source> ::conversion::FromPyObject<'source>
|
||||
for $t
|
||||
{
|
||||
fn extract<S>($obj: &'source ::Py<'source, S>) -> $crate::PyResult<Self>
|
||||
where S: ::typeob::PyTypeInfo
|
||||
fn extract($obj: &'source ::PyObject<'source>) -> $crate::PyResult<Self>
|
||||
//where S: ::typeob::PyTypeInfo
|
||||
{
|
||||
$body
|
||||
}
|
||||
|
|
|
@ -7,32 +7,39 @@ use ffi;
|
|||
use std::os::raw::c_char;
|
||||
use std::ffi::{CStr, CString};
|
||||
|
||||
use pyptr::{Py, PyPtr};
|
||||
use python::{PythonToken, ToPythonPointer, PythonObjectWithToken, Python};
|
||||
use ::pptr;
|
||||
use pyptr::PyPtr;
|
||||
use python::{ToPythonPointer, Python};
|
||||
use token::PythonObjectWithToken;
|
||||
use objects::{PyDict, PyType, exc};
|
||||
use objectprotocol::ObjectProtocol;
|
||||
use err::{PyResult, PyErr};
|
||||
|
||||
|
||||
/// Represents a Python module object.
|
||||
pub struct PyModule(PythonToken<PyModule>);
|
||||
pub struct PyModule<'p>(pptr<'p>);
|
||||
|
||||
pyobject_newtype!(PyModule, PyModule_Check, PyModule_Type);
|
||||
pyobject_nativetype!(PyModule, PyModule_Check, PyModule_Type);
|
||||
|
||||
impl PyModule {
|
||||
|
||||
impl<'p> PyModule<'p> {
|
||||
/// Create a new module object with the `__name__` attribute set to name.
|
||||
pub fn new<'p>(py: Python<'p>, name: &str) -> PyResult<Py<'p, PyModule>> {
|
||||
pub fn new(py: Python<'p>, name: &str) -> PyResult<PyModule<'p>> {
|
||||
let name = CString::new(name).unwrap();
|
||||
unsafe {
|
||||
Py::cast_from_owned_nullptr(py, ffi::PyModule_New(name.as_ptr()))
|
||||
let ptr = pptr::cast_from_owned_nullptr::<PyModule>(
|
||||
py, ffi::PyModule_New(name.as_ptr()))?;
|
||||
Ok(PyModule(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Import the Python module with the specified name.
|
||||
pub fn import<'p>(py: Python<'p>, name: &str) -> PyResult<Py<'p, PyModule>> {
|
||||
pub fn import(py: Python<'p>, name: &str) -> PyResult<PyModule<'p>> {
|
||||
let name = CString::new(name).unwrap();
|
||||
unsafe {
|
||||
Py::cast_from_owned_nullptr(py, ffi::PyImport_ImportModule(name.as_ptr()))
|
||||
let ptr = pptr::cast_from_owned_nullptr::<PyModule>(
|
||||
py, ffi::PyImport_ImportModule(name.as_ptr()))?;
|
||||
Ok(PyModule(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,7 +59,8 @@ impl PyModule {
|
|||
match std::str::from_utf8(slice) {
|
||||
Ok(s) => Ok(s),
|
||||
Err(e) => Err(PyErr::from_instance(
|
||||
self.token(), try!(exc::UnicodeDecodeError::new_utf8(self.token(), slice, e))))
|
||||
self.token(),
|
||||
try!(exc::UnicodeDecodeError::new_utf8(self.token(), slice, e))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +84,7 @@ impl PyModule {
|
|||
/// This is a convenience function that initializes the `class`,
|
||||
/// sets `new_type.__module__` to this module's name,
|
||||
/// and adds the type to this module.
|
||||
pub fn add_class<'p, T>(&self) -> PyResult<()>
|
||||
pub fn add_class<T>(&self) -> PyResult<()>
|
||||
where T: ::typeob::PyTypeInfo
|
||||
{
|
||||
let mut ty = <T as ::typeob::PyTypeInfo>::type_object();
|
||||
|
|
|
@ -7,14 +7,14 @@ extern crate num_traits;
|
|||
use self::num_traits::cast::cast;
|
||||
use std::os::raw::{c_long, c_double};
|
||||
|
||||
use ::{Py, PyPtr};
|
||||
use ::{PyPtr, pptr};
|
||||
use ffi;
|
||||
use super::exc;
|
||||
use super::PyObject;
|
||||
use typeob::PyTypeInfo;
|
||||
use python::{PythonToken, ToPythonPointer, Python};
|
||||
use objects::PyObject;
|
||||
use token::{PyObjectMarker, PythonObjectWithToken};
|
||||
use python::{ToPythonPointer, Python};
|
||||
use err::{PyResult, PyErr};
|
||||
use conversion::{ToPyObject, FromPyObject};
|
||||
use conversion::{ToPyObject, FromPyObject, IntoPyObject};
|
||||
|
||||
/// Represents a Python `int` object.
|
||||
///
|
||||
|
@ -22,8 +22,8 @@ use conversion::{ToPyObject, FromPyObject};
|
|||
/// by using [ToPyObject](trait.ToPyObject.html)
|
||||
/// and [extract](struct.PyObject.html#method.extract)
|
||||
/// with the primitive Rust integer types.
|
||||
pub struct PyLong(PythonToken<PyLong>);
|
||||
pyobject_newtype!(PyLong, PyLong_Check, PyLong_Type);
|
||||
pub struct PyLong<'p>(pptr<'p>);
|
||||
pyobject_nativetype!(PyLong, PyLong_Check, PyLong_Type);
|
||||
|
||||
/// Represents a Python `float` object.
|
||||
///
|
||||
|
@ -31,21 +31,21 @@ pyobject_newtype!(PyLong, PyLong_Check, PyLong_Type);
|
|||
/// by using [ToPyObject](trait.ToPyObject.html)
|
||||
/// and [extract](struct.PyObject.html#method.extract)
|
||||
/// with `f32`/`f64`.
|
||||
pub struct PyFloat(PythonToken<PyFloat>);
|
||||
pyobject_newtype!(PyFloat, PyFloat_Check, PyFloat_Type);
|
||||
pub struct PyFloat<'p>(pptr<'p>);
|
||||
pyobject_nativetype!(PyFloat, PyFloat_Check, PyFloat_Type);
|
||||
|
||||
|
||||
impl PyFloat {
|
||||
impl<'p> PyFloat<'p> {
|
||||
/// Creates a new Python `float` object.
|
||||
pub fn new(_py: Python, val: c_double) -> PyPtr<PyFloat> {
|
||||
pub fn new(py: Python<'p>, val: c_double) -> PyFloat<'p> {
|
||||
unsafe {
|
||||
PyPtr::from_owned_ptr_or_panic(ffi::PyFloat_FromDouble(val))
|
||||
PyFloat(pptr::from_owned_ptr_or_panic(py, ffi::PyFloat_FromDouble(val)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the value of this float.
|
||||
pub fn value(&self) -> c_double {
|
||||
unsafe { ffi::PyFloat_AsDouble(self.as_ptr()) }
|
||||
unsafe { ffi::PyFloat_AsDouble(self.0.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ impl PyFloat {
|
|||
macro_rules! int_fits_c_long(
|
||||
($rust_type:ty) => (
|
||||
impl ToPyObject for $rust_type {
|
||||
fn to_object(&self, _py: Python) -> PyPtr<PyObject> {
|
||||
fn to_object(&self, _py: Python) -> PyPtr<PyObjectMarker> {
|
||||
unsafe {
|
||||
PyPtr::from_owned_ptr_or_panic(ffi::PyLong_FromLong(*self as c_long))
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ macro_rules! int_fits_larger_int(
|
|||
($rust_type:ty, $larger_type:ty) => (
|
||||
impl ToPyObject for $rust_type {
|
||||
#[inline]
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObject> {
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObjectMarker> {
|
||||
(*self as $larger_type).to_object(py)
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ macro_rules! int_convert_u64_or_i64 (
|
|||
($rust_type:ty, $pylong_from_ll_or_ull:expr, $pylong_as_ull_or_ull:expr) => (
|
||||
impl ToPyObject for $rust_type {
|
||||
|
||||
fn to_object(&self, _py: Python) -> PyPtr<PyObject> {
|
||||
fn to_object(&self, _py: Python) -> PyPtr<PyObjectMarker> {
|
||||
unsafe {
|
||||
PyPtr::from_owned_ptr_or_panic($pylong_from_ll_or_ull(*self))
|
||||
}
|
||||
|
@ -117,8 +117,8 @@ macro_rules! int_convert_u64_or_i64 (
|
|||
}
|
||||
|
||||
impl<'source> FromPyObject<'source> for $rust_type {
|
||||
fn extract<S>(py: &'source Py<'source, S>) -> PyResult<$rust_type>
|
||||
where S: PyTypeInfo
|
||||
fn extract(py: &'source PyObject) -> PyResult<$rust_type>
|
||||
//where S: PyTypeInfo
|
||||
{
|
||||
let ptr = py.as_ptr();
|
||||
unsafe {
|
||||
|
@ -169,8 +169,8 @@ int_fits_larger_int!(usize, u64);
|
|||
int_convert_u64_or_i64!(u64, ffi::PyLong_FromUnsignedLongLong, ffi::PyLong_AsUnsignedLongLong);
|
||||
|
||||
impl ToPyObject for f64 {
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObject> {
|
||||
PyFloat::new(py, *self).into_object()
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObjectMarker> {
|
||||
PyFloat::new(py, *self).into_object(py)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,8 +188,8 @@ fn overflow_error(py: Python) -> PyErr {
|
|||
}
|
||||
|
||||
impl ToPyObject for f32 {
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObject> {
|
||||
PyFloat::new(py, *self as f64).into_object()
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObjectMarker> {
|
||||
PyFloat::new(py, *self as f64).into_object(py)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,64 +2,61 @@
|
|||
|
||||
use std;
|
||||
|
||||
use ::pptr;
|
||||
use ffi;
|
||||
use pyptr::{Py, PyPtr};
|
||||
use err::{PyDowncastError};
|
||||
use python::{PythonToken, Python, PythonObjectWithToken};
|
||||
use err::{PyResult, PyDowncastError};
|
||||
use python::{Python, ToPythonPointer};
|
||||
use token::PythonObjectWithToken;
|
||||
use typeob::PyTypeInfo;
|
||||
|
||||
pub struct PyObject(PythonToken<PyObject>);
|
||||
|
||||
pyobject_newtype!(PyObject, PyObject_Check, PyBaseObject_Type);
|
||||
pub struct PyObject<'p>(pptr<'p>);
|
||||
|
||||
impl PyObject {
|
||||
pyobject_nativetype!(PyObject, PyObject_Check, PyBaseObject_Type);
|
||||
|
||||
|
||||
impl<'p> PyObject<'p> {
|
||||
|
||||
#[inline]
|
||||
pub fn from_owned_ptr(py: Python, ptr: *mut ffi::PyObject) -> Py<PyObject> {
|
||||
unsafe { Py::from_owned_ptr(py, ptr) }
|
||||
pub fn from_owned_ptr(py: Python<'p>, ptr: *mut ffi::PyObject) -> PyObject<'p> {
|
||||
unsafe { PyObject(pptr::from_owned_ptr(py, ptr)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_borrowed_ptr(py: Python, ptr: *mut ffi::PyObject) -> Py<PyObject> {
|
||||
unsafe { Py::from_borrowed_ptr(py, ptr) }
|
||||
pub fn from_owned_ptr_or_err(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> PyResult<PyObject<'p>> {
|
||||
unsafe { Ok(PyObject(pptr::from_owned_ptr_or_err(py, ptr)?)) }
|
||||
}
|
||||
|
||||
/// Creates a PyObject instance for the given FFI pointer.
|
||||
/// This moves ownership over the pointer into the PyObject.
|
||||
/// Returns None for null pointers; undefined behavior if the pointer is invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_pptr_opt(py: Python, ptr: *mut ffi::PyObject)
|
||||
-> Option<PyPtr<PyObject>> {
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(PyObject::from_owned_ptr(py, ptr).into_pptr())
|
||||
pub fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> Option<PyObject<'p>> {
|
||||
unsafe {
|
||||
if let Some(ptr) = pptr::from_owned_ptr_or_opt(py, ptr) {
|
||||
Some(PyObject(ptr))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns None for null pointers; undefined behavior if the pointer is invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_pptr_opt(py: Python, ptr: *mut ffi::PyObject)
|
||||
-> Option<PyPtr<PyObject>> {
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(PyObject::from_borrowed_ptr(py, ptr).into_pptr())
|
||||
}
|
||||
pub fn from_borrowed_ptr(py: Python<'p>, ptr: *mut ffi::PyObject) -> PyObject<'p> {
|
||||
unsafe { PyObject(pptr::from_borrowed_ptr(py, ptr)) }
|
||||
}
|
||||
|
||||
/// Transmutes a slice of owned FFI pointers to `&[Py<'p, PyObject>]`.
|
||||
/// Undefined behavior if any pointer in the slice is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn borrow_from_owned_ptr_slice<'a>(ptr: &'a [*mut ffi::PyObject])
|
||||
-> &'a [Py<'a, PyObject>] {
|
||||
-> &'a [PyObject<'p>] {
|
||||
std::mem::transmute(ptr)
|
||||
}
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
/// Fails with `PyDowncastError` if the object is not of the expected type.
|
||||
#[inline]
|
||||
pub fn cast_as<'p, D>(&'p self) -> Result<&'p D, PyDowncastError<'p>>
|
||||
pub fn cast_as<D>(&'p self) -> Result<&'p D, PyDowncastError<'p>>
|
||||
where D: PyTypeInfo
|
||||
{
|
||||
unsafe {
|
||||
|
@ -74,4 +71,12 @@ impl PyObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extracts some type from the Python object.
|
||||
/// This is a wrapper function around `FromPyObject::extract()`.
|
||||
#[inline]
|
||||
pub fn extract<D>(&'p self) -> PyResult<D> where D: ::conversion::FromPyObject<'p>
|
||||
{
|
||||
::conversion::FromPyObject::extract(&self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use std::os::raw::c_long;
|
||||
use pyptr::{Py, PyPtr};
|
||||
use objects::PyObject;
|
||||
use python::{PythonToken, ToPythonPointer, Python, PythonObjectWithToken};
|
||||
|
||||
use ::pptr;
|
||||
use pyptr::PyPtr;
|
||||
use python::{ToPythonPointer, Python};
|
||||
use err::{PyErr, PyResult};
|
||||
use ffi::{self, Py_ssize_t};
|
||||
use conversion::ToPyObject;
|
||||
use conversion::{ToPyObject, IntoPyObject};
|
||||
use token::{PyObjectMarker, PythonObjectWithToken};
|
||||
|
||||
/// Represents a Python `slice` indices
|
||||
pub struct PySliceIndices {
|
||||
|
@ -30,18 +32,19 @@ impl PySliceIndices {
|
|||
|
||||
/// Represents a Python `slice`. Only `c_long` indeces supprted
|
||||
/// at the moment by PySlice object.
|
||||
pub struct PySlice(PythonToken<PySlice>);
|
||||
pub struct PySlice<'p>(pptr<'p>);
|
||||
|
||||
pyobject_newtype!(PySlice, PySlice_Check, PySlice_Type);
|
||||
pyobject_nativetype!(PySlice, PySlice_Check, PySlice_Type);
|
||||
|
||||
impl<'p> PySlice<'p> {
|
||||
|
||||
impl PySlice {
|
||||
/// Construct a new slice with the given elements.
|
||||
pub fn new<'p>(py: Python<'p>, start: isize, stop: isize, step: isize) -> Py<'p, PySlice> {
|
||||
pub fn new(py: Python<'p>, start: isize, stop: isize, step: isize) -> PySlice<'p> {
|
||||
unsafe {
|
||||
let ptr = ffi::PySlice_New(ffi::PyLong_FromLong(start as i64),
|
||||
ffi::PyLong_FromLong(stop as i64),
|
||||
ffi::PyLong_FromLong(step as i64));
|
||||
Py::from_owned_ptr_or_panic(py, ptr)
|
||||
PySlice(pptr::from_owned_ptr_or_panic(py, ptr))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +78,7 @@ impl PySlice {
|
|||
}
|
||||
|
||||
impl ToPyObject for PySliceIndices {
|
||||
fn to_object<'p>(&self, py: Python) -> PyPtr<PyObject> {
|
||||
PySlice::new(py, self.start, self.stop, self.step).into_object_pptr()
|
||||
fn to_object<'p>(&self, py: Python) -> PyPtr<PyObjectMarker> {
|
||||
PySlice::new(py, self.start, self.stop, self.step).into_object(py)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,22 +8,23 @@ use std::ascii::AsciiExt;
|
|||
use std::borrow::Cow;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
use ::{Py, PyPtr};
|
||||
use ::{Py, PyPtr, pptr};
|
||||
use ffi;
|
||||
use python::{PythonToken, ToPythonPointer, Python, PythonObjectWithToken};
|
||||
use python::{ToPythonPointer, Python};
|
||||
use super::{exc, PyObject};
|
||||
use token::{PyObjectMarker, PythonObjectWithToken};
|
||||
use err::{PyResult, PyErr};
|
||||
use conversion::{ToPyObject, RefFromPyObject};
|
||||
use conversion::{ToPyObject, IntoPyObject, RefFromPyObject};
|
||||
|
||||
/// Represents a Python string.
|
||||
pub struct PyString(PythonToken<PyString>);
|
||||
pub struct PyString<'p>(pptr<'p>);
|
||||
|
||||
pyobject_newtype!(PyString, PyUnicode_Check, PyUnicode_Type);
|
||||
pyobject_nativetype!(PyString, PyUnicode_Check, PyUnicode_Type);
|
||||
|
||||
/// Represents a Python byte string.
|
||||
pub struct PyBytes(PythonToken<PyBytes>);
|
||||
pub struct PyBytes<'p>(pptr<'p>);
|
||||
|
||||
pyobject_newtype!(PyBytes, PyBytes_Check, PyBytes_Type);
|
||||
pyobject_nativetype!(PyBytes, PyBytes_Check, PyBytes_Type);
|
||||
|
||||
|
||||
/// Enum of possible Python string representations.
|
||||
|
@ -133,29 +134,29 @@ impl <'a> PyStringData<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl PyString {
|
||||
impl<'p> PyString<'p> {
|
||||
|
||||
/// Creates a new Python string object.
|
||||
///
|
||||
/// On Python 2.7, this function will create a byte string if the
|
||||
/// input string is ASCII-only; and a unicode string otherwise.
|
||||
/// Use `PyUnicode::new()` to always create a unicode string.
|
||||
///
|
||||
/// Panics if out of memory.
|
||||
pub fn new<'p>(_py: Python, s: &str) -> PyPtr<PyString> {
|
||||
pub fn new(py: Python<'p>, s: &str) -> PyString<'p> {
|
||||
let ptr = s.as_ptr() as *const c_char;
|
||||
let len = s.len() as ffi::Py_ssize_t;
|
||||
unsafe {
|
||||
PyPtr::from_owned_ptr_or_panic(ffi::PyUnicode_FromStringAndSize(ptr, len))
|
||||
PyString(pptr::from_owned_ptr_or_panic(
|
||||
py, ffi::PyUnicode_FromStringAndSize(ptr, len)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_object<'p>(src: &PyObject, encoding: &str, errors: &str)
|
||||
-> PyResult<PyPtr<PyString>> {
|
||||
pub fn from_object(src: &'p PyObject, encoding: &str, errors: &str)
|
||||
-> PyResult<PyString<'p>> {
|
||||
unsafe {
|
||||
PyPtr::from_owned_ptr_or_err(
|
||||
src.token(), ffi::PyUnicode_FromEncodedObject(
|
||||
src.as_ptr(), encoding.as_ptr() as *const i8, errors.as_ptr() as *const i8))
|
||||
.map_err(|e| e.into())
|
||||
Ok(PyString(
|
||||
pptr::from_owned_ptr_or_err(
|
||||
src.token(), ffi::PyUnicode_FromEncodedObject(
|
||||
src.as_ptr(),
|
||||
encoding.as_ptr() as *const i8,
|
||||
errors.as_ptr() as *const i8))?))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,17 +192,17 @@ impl PyString {
|
|||
}
|
||||
}
|
||||
|
||||
impl PyBytes {
|
||||
impl<'p> PyBytes<'p> {
|
||||
/// Creates a new Python byte string object.
|
||||
/// The byte string is initialized by copying the data from the `&[u8]`.
|
||||
///
|
||||
/// Panics if out of memory.
|
||||
pub fn new<'p>(py: Python<'p>, s: &[u8]) -> Py<'p, PyBytes> {
|
||||
pub fn new(py: Python<'p>, s: &[u8]) -> PyBytes<'p> {
|
||||
let ptr = s.as_ptr() as *const c_char;
|
||||
let len = s.len() as ffi::Py_ssize_t;
|
||||
unsafe {
|
||||
Py::cast_from_owned_ptr_or_panic(
|
||||
py, ffi::PyBytes_FromStringAndSize(ptr, len))
|
||||
PyBytes(pptr::from_owned_ptr_or_panic(
|
||||
py, ffi::PyBytes_FromStringAndSize(ptr, len)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,8 +220,8 @@ impl PyBytes {
|
|||
/// See `PyString::new` for details on the conversion.
|
||||
impl ToPyObject for str {
|
||||
#[inline]
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObject> {
|
||||
PyString::new(py, self).into_object()
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObjectMarker> {
|
||||
PyString::new(py, self).into_object(py)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,8 +229,8 @@ impl ToPyObject for str {
|
|||
/// See `PyString::new` for details on the conversion.
|
||||
impl <'a> ToPyObject for Cow<'a, str> {
|
||||
#[inline]
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObject> {
|
||||
PyString::new(py, self).into_object()
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObjectMarker> {
|
||||
PyString::new(py, self).into_object(py)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,8 +238,8 @@ impl <'a> ToPyObject for Cow<'a, str> {
|
|||
/// See `PyString::new` for details on the conversion.
|
||||
impl ToPyObject for String {
|
||||
#[inline]
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObject> {
|
||||
PyString::new(py, self).into_object()
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObjectMarker> {
|
||||
PyString::new(py, self).into_object(py)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,38 +4,39 @@
|
|||
|
||||
use std::slice;
|
||||
|
||||
use ::{Py, PyPtr};
|
||||
use ::{PyPtr, pptr};
|
||||
use ffi::{self, Py_ssize_t};
|
||||
use python::{PythonToken, Python,
|
||||
ToPythonPointer, IntoPythonPointer, PythonObjectWithToken};
|
||||
use err::{PyErr, PyResult};
|
||||
use conversion::{FromPyObject, ToPyObject, ToPyTuple};
|
||||
use python::{Python, ToPythonPointer, IntoPythonPointer};
|
||||
use conversion::{FromPyObject, ToPyObject, ToPyTuple, IntoPyObject};
|
||||
use objects::PyObject;
|
||||
use token::{PyObjectMarker, PythonObjectWithToken};
|
||||
use super::exc;
|
||||
use super::PyObject;
|
||||
|
||||
/// Represents a Python tuple object.
|
||||
pub struct PyTuple(PythonToken<PyTuple>);
|
||||
pub struct PyTuple<'p>(pptr<'p>);
|
||||
|
||||
pyobject_newtype!(PyTuple, PyTuple_Check, PyTuple_Type);
|
||||
pyobject_nativetype!(PyTuple, PyTuple_Check, PyTuple_Type);
|
||||
|
||||
|
||||
impl<'p> PyTuple<'p> {
|
||||
|
||||
impl PyTuple {
|
||||
/// Construct a new tuple with the given elements.
|
||||
pub fn new<'p, T: ToPyObject>(py: Python, elements: &[T]) -> PyPtr<PyTuple> {
|
||||
pub fn new<T: ToPyObject>(py: Python<'p>, elements: &[T]) -> PyTuple<'p> {
|
||||
unsafe {
|
||||
let len = elements.len();
|
||||
let ptr = ffi::PyTuple_New(len as Py_ssize_t);
|
||||
let t = PyPtr::from_owned_ptr_or_panic(ptr);
|
||||
for (i, e) in elements.iter().enumerate() {
|
||||
ffi::PyTuple_SetItem(ptr, i as Py_ssize_t, e.to_object(py).into_ptr());
|
||||
}
|
||||
t
|
||||
PyTuple(pptr::from_owned_ptr_or_panic(py, ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the empty tuple.
|
||||
pub fn empty(_py: Python) -> PyPtr<PyTuple> {
|
||||
pub fn empty(py: Python<'p>) -> PyTuple<'p> {
|
||||
unsafe {
|
||||
PyPtr::from_owned_ptr_or_panic(ffi::PyTuple_New(0))
|
||||
PyTuple(pptr::from_owned_ptr_or_panic(py, ffi::PyTuple_New(0)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,18 +52,18 @@ impl PyTuple {
|
|||
/// Gets the item at the specified index.
|
||||
///
|
||||
/// Panics if the index is out of range.
|
||||
pub fn get_item<'p>(&self, index: usize) -> &PyObject {
|
||||
pub fn get_item(&'p self, index: usize) -> PyObject<'p> {
|
||||
// TODO: reconsider whether we should panic
|
||||
// It's quite inconsistent that this method takes `Python` when `len()` does not.
|
||||
assert!(index < self.len());
|
||||
unsafe {
|
||||
self.token().from_owned_ptr(
|
||||
ffi::PyTuple_GET_ITEM(self.as_ptr(), index as Py_ssize_t))
|
||||
PyObject::from_owned_ptr(
|
||||
self.token(), ffi::PyTuple_GET_ITEM(self.as_ptr(), index as Py_ssize_t))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_slice<'a>(&'a self) -> &'a [Py<'a, PyObject>] {
|
||||
pub fn as_slice<'a>(&'a self) -> &'a [PyObject] {
|
||||
// This is safe because PyObject has the same memory layout as *mut ffi::PyObject,
|
||||
// and because tuples are immutable.
|
||||
// (We don't even need a Python token, thanks to immutability)
|
||||
|
@ -81,14 +82,14 @@ impl PyTuple {
|
|||
//}
|
||||
}
|
||||
|
||||
impl<'a> ToPyTuple for Py<'a, PyTuple> {
|
||||
fn to_py_tuple(&self, _py: Python) -> PyPtr<PyTuple> {
|
||||
self.as_pptr()
|
||||
impl<'a> ToPyTuple for PyTuple<'a> {
|
||||
fn to_py_tuple<'p>(&self, py: Python<'p>) -> PyTuple<'p> {
|
||||
unsafe { PyTuple(pptr::from_owned_ptr_or_panic(py, self.0.as_ptr())) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ToPyTuple for &'a str {
|
||||
fn to_py_tuple(&self, py: Python) -> PyPtr<PyTuple> {
|
||||
fn to_py_tuple<'p>(&self, py: Python<'p>) -> PyTuple<'p> {
|
||||
PyTuple::new(py, &[py_coerce_expr!(self.to_object(py))])
|
||||
}
|
||||
}
|
||||
|
@ -102,15 +103,15 @@ fn wrong_tuple_length(py: Python, t: &PyTuple, expected_length: usize) -> PyErr
|
|||
|
||||
macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+} => {
|
||||
impl <$($T: ToPyObject),+> ToPyObject for ($($T,)+) {
|
||||
fn to_object<'p>(&self, py: Python<'p>) -> PyPtr<PyObject> {
|
||||
fn to_object<'p>(&self, py: Python<'p>) -> PyPtr<PyObjectMarker> {
|
||||
PyTuple::new(py, &[
|
||||
$(py_coerce_expr!(self.$n.to_object(py)),)+
|
||||
]).into_object()
|
||||
]).into_object(py)
|
||||
}
|
||||
}
|
||||
|
||||
impl <$($T: ToPyObject),+> ToPyTuple for ($($T,)+) {
|
||||
fn to_py_tuple<'p>(&self, py: Python<'p>) -> PyPtr<PyTuple> {
|
||||
fn to_py_tuple<'p>(&self, py: Python<'p>) -> PyTuple<'p> {
|
||||
PyTuple::new(py, &[
|
||||
$(py_coerce_expr!(self.$n.to_object(py)),)+
|
||||
])
|
||||
|
@ -118,8 +119,8 @@ macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+
|
|||
}
|
||||
|
||||
impl<'s, $($T: FromPyObject<'s>),+> FromPyObject<'s> for ($($T,)+) {
|
||||
fn extract<S>(obj: &'s Py<'s, S>) -> PyResult<Self>
|
||||
where S: ::typeob::PyTypeInfo
|
||||
fn extract(obj: &'s PyObject<'s>) -> PyResult<Self>
|
||||
//where S: ::typeob::PyTypeInfo
|
||||
{
|
||||
let t = try!(obj.cast_as::<&PyTuple>());
|
||||
let slice = t.as_slice();
|
||||
|
@ -167,15 +168,15 @@ pub struct NoArgs;
|
|||
/// Converts `NoArgs` to an empty Python tuple.
|
||||
impl ToPyObject for NoArgs {
|
||||
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObject> {
|
||||
PyTuple::empty(py).into_object()
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObjectMarker> {
|
||||
PyTuple::empty(py).into_object(py)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts `NoArgs` to an empty Python tuple.
|
||||
impl ToPyTuple for NoArgs {
|
||||
|
||||
fn to_py_tuple(&self, py: Python) -> PyPtr<PyTuple> {
|
||||
fn to_py_tuple<'p>(&self, py: Python<'p>) -> PyTuple<'p> {
|
||||
PyTuple::empty(py)
|
||||
}
|
||||
}
|
||||
|
@ -183,7 +184,7 @@ impl ToPyTuple for NoArgs {
|
|||
/// Converts `()` to an empty Python tuple.
|
||||
impl ToPyTuple for () {
|
||||
|
||||
fn to_py_tuple(&self, py: Python) -> PyPtr<PyTuple> {
|
||||
fn to_py_tuple<'p>(&self, py: Python<'p>) -> PyTuple<'p> {
|
||||
PyTuple::empty(py)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@ use std::borrow::Cow;
|
|||
|
||||
use ffi;
|
||||
use pyptr::{PyPtr};
|
||||
use python::{Python, PythonToken, ToPythonPointer, PythonObjectWithToken};
|
||||
use token::{PythonToken, PythonObjectWithToken};
|
||||
use python::{Python, ToPythonPointer};
|
||||
use conversion::ToPyTuple;
|
||||
use objects::{PyObject, PyDict};
|
||||
use err::PyResult;
|
||||
|
|
178
src/ppptr.rs
Normal file
178
src/ppptr.rs
Normal file
|
@ -0,0 +1,178 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use ffi;
|
||||
use err::{PyErr, PyResult};
|
||||
use python::{Python, ToPythonPointer};
|
||||
use typeob::{PyTypeInfo, PyObjectAlloc};
|
||||
|
||||
|
||||
pub struct pptr<'p>(Python<'p>, *mut ffi::PyObject);
|
||||
|
||||
|
||||
impl<'p> pptr<'p> {
|
||||
|
||||
/// Create new python object and move T instance under python management
|
||||
pub fn new<T>(py: Python<'p>, value: T) -> PyResult<pptr<'p>> where T: PyObjectAlloc<Type=T>
|
||||
{
|
||||
let ptr = unsafe {
|
||||
try!(<T as PyObjectAlloc>::alloc(py, value))
|
||||
};
|
||||
Ok(pptr(py, ptr))
|
||||
}
|
||||
|
||||
/// Creates a Py instance for the given FFI pointer.
|
||||
/// This moves ownership over the pointer into the Py.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr(py: Python<'p>, ptr: *mut ffi::PyObject) -> pptr<'p> {
|
||||
debug_assert!(!ptr.is_null() && ffi::Py_REFCNT(ptr) > 0);
|
||||
pptr(py, ptr)
|
||||
}
|
||||
|
||||
/// Cast from ffi::PyObject ptr to a concrete object.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr_or_panic(py: Python<'p>, ptr: *mut ffi::PyObject) -> pptr<'p>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
::err::panic_after_error();
|
||||
} else {
|
||||
pptr::from_owned_ptr(py, ptr)
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct pppt<'p> from the result of a Python FFI call that
|
||||
/// returns a new reference (owned pointer).
|
||||
/// Returns `Err(PyErr)` if the pointer is `null`.
|
||||
/// Unsafe because the pointer might be invalid.
|
||||
pub unsafe fn from_owned_ptr_or_err(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> PyResult<pptr<'p>>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(py))
|
||||
} else {
|
||||
Ok(pptr::from_owned_ptr(py, ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a pptr<'p> instance for the given FFI pointer.
|
||||
/// This moves ownership over the pointer into the pptr<'p>.
|
||||
/// Returns None for null pointers; undefined behavior if the pointer is invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> Option<pptr<'p>> {
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(pptr::from_owned_ptr(py, ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a Py instance for the given FFI pointer.
|
||||
/// Calls Py_INCREF() on the ptr.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr(py: Python<'p>, ptr: *mut ffi::PyObject) -> pptr<'p> {
|
||||
debug_assert!(!ptr.is_null() && ffi::Py_REFCNT(ptr) > 0);
|
||||
ffi::Py_INCREF(ptr);
|
||||
pptr(py, ptr)
|
||||
}
|
||||
|
||||
/// Creates a Py instance for the given FFI pointer.
|
||||
/// Calls Py_INCREF() on the ptr.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr_opt(py: Python<'p>,
|
||||
ptr: *mut ffi::PyObject) -> Option<pptr<'p>> {
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
debug_assert!(ffi::Py_REFCNT(ptr) > 0);
|
||||
ffi::Py_INCREF(ptr);
|
||||
Some(pptr(py, ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the reference count of this Py object.
|
||||
#[inline]
|
||||
pub fn get_refcnt(&self) -> usize {
|
||||
unsafe { ffi::Py_REFCNT(self.1) as usize }
|
||||
}
|
||||
|
||||
pub fn token<'a>(&'a self) -> Python<'p> {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Cast from ffi::PyObject ptr to a concrete object.
|
||||
#[inline]
|
||||
pub fn cast_from_owned_ptr<T>(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> Result<pptr<'p>, ::PyDowncastError<'p>>
|
||||
where T: PyTypeInfo
|
||||
{
|
||||
let checked = unsafe { ffi::PyObject_TypeCheck(ptr, T::type_object()) != 0 };
|
||||
|
||||
if checked {
|
||||
Ok( unsafe { pptr::from_owned_ptr(py, ptr) })
|
||||
} else {
|
||||
Err(::PyDowncastError(py, None))
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast from ffi::PyObject ptr to a concrete object.
|
||||
#[inline]
|
||||
pub fn cast_from_borrowed_ptr<T>(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> Result<pptr<'p>, ::PyDowncastError<'p>>
|
||||
where T: PyTypeInfo
|
||||
{
|
||||
let checked = unsafe { ffi::PyObject_TypeCheck(ptr, T::type_object()) != 0 };
|
||||
|
||||
if checked {
|
||||
Ok( unsafe { pptr::from_borrowed_ptr(py, ptr) })
|
||||
} else {
|
||||
Err(::PyDowncastError(py, None))
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast from ffi::PyObject ptr to a concrete object.
|
||||
#[inline]
|
||||
pub unsafe fn cast_from_owned_ptr_or_panic<T>(py: Python<'p>,
|
||||
ptr: *mut ffi::PyObject) -> pptr<'p>
|
||||
where T: PyTypeInfo
|
||||
{
|
||||
if ffi::PyObject_TypeCheck(ptr, T::type_object()) != 0 {
|
||||
pptr::from_owned_ptr(py, ptr)
|
||||
} else {
|
||||
::err::panic_after_error();
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn cast_from_owned_nullptr<T>(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> PyResult<pptr<'p>>
|
||||
where T: PyTypeInfo
|
||||
{
|
||||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(py))
|
||||
} else {
|
||||
pptr::cast_from_owned_ptr::<T>(py, ptr).map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> ToPythonPointer for pptr<'p> {
|
||||
/// Gets the underlying FFI pointer, returns a borrowed pointer.
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
self.1
|
||||
}
|
||||
}
|
||||
|
||||
/// Dropping a `pptr` instance decrements the reference count on the object by 1.
|
||||
impl<'p> Drop for pptr<'p> {
|
||||
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
println!("drop pptr: {:?} {} {:?}",
|
||||
self.1, ffi::Py_REFCNT(self.1), &self as *const _);
|
||||
}
|
||||
unsafe { ffi::Py_DECREF(self.1); }
|
||||
}
|
||||
}
|
97
src/pyptr.rs
97
src/pyptr.rs
|
@ -8,8 +8,9 @@ use std::convert::{AsRef, AsMut};
|
|||
use ffi;
|
||||
use err::{PyErr, PyResult, PyDowncastError};
|
||||
use conversion::{ToPyObject, IntoPyObject};
|
||||
use python::{Python, ToPythonPointer, IntoPythonPointer};
|
||||
use objects::PyObject;
|
||||
use python::{Python, ToPythonPointer, IntoPythonPointer};
|
||||
use token::{PyObjectMarker, PythonObjectWithToken};
|
||||
use typeob::{PyTypeInfo, PyObjectAlloc};
|
||||
|
||||
|
||||
|
@ -28,6 +29,19 @@ impl<T> PyPtr<T> {
|
|||
PyPtr {inner: ptr, _t: PhantomData}
|
||||
}
|
||||
|
||||
/// Creates a PyObject instance for the given FFI pointer.
|
||||
/// This moves ownership over the pointer into the PyObject.
|
||||
/// Returns None for null pointers; undefined behavior if the pointer is invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr_or_opt(_py: Python, ptr: *mut ffi::PyObject)
|
||||
-> Option<PyPtr<T>> {
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(PyPtr::from_owned_ptr(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct PyPtr<PyObject> from the result of a Python FFI call that
|
||||
/// returns a new reference (owned pointer).
|
||||
/// Returns `Err(PyErr)` if the pointer is `null`.
|
||||
|
@ -90,7 +104,7 @@ impl<T> PyPtr<T> {
|
|||
/// Converts PyPtr<T> -> PyPtr<PyObject>
|
||||
/// Consumes `self` without calling `Py_INCREF()`
|
||||
#[inline]
|
||||
pub fn into_object(self) -> PyPtr<PyObject> {
|
||||
pub fn into_object(self) -> PyPtr<PyObjectMarker> {
|
||||
let p = PyPtr {inner: self.inner, _t: PhantomData};
|
||||
std::mem::forget(self);
|
||||
p
|
||||
|
@ -141,7 +155,7 @@ impl<T> IntoPythonPointer for PyPtr<T> {
|
|||
impl<T> IntoPyObject for PyPtr<T> {
|
||||
|
||||
#[inline]
|
||||
fn into_object<'a>(self, _py: Python) -> PyPtr<PyObject> {
|
||||
fn into_object<'a>(self, _py: Python) -> PyPtr<PyObjectMarker> {
|
||||
self.into_object()
|
||||
}
|
||||
}
|
||||
|
@ -192,6 +206,17 @@ impl<'p, T> Py<'p, T>
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> Option<Py<'p, T>>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(Py::from_owned_ptr(py, ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct Py<'p, PyObj> from the result of a Python FFI call that
|
||||
/// returns a new reference (owned pointer).
|
||||
/// Returns `Err(PyErr)` if the pointer is `null`.
|
||||
|
@ -254,24 +279,28 @@ impl<'p, T> Py<'p, T>
|
|||
ptr
|
||||
}
|
||||
|
||||
/// Consumes a Py<T> instance and creates a PyPtr<PyObject> instance.
|
||||
/// Ownership moves over to the PyPtr<T> instance, Does not call Py_INCREF() on the ptr.
|
||||
#[inline]
|
||||
pub fn into_object_pptr(self) -> PyPtr<PyObject> {
|
||||
let ptr = PyPtr { inner: self.inner, _t: PhantomData };
|
||||
std::mem::forget(self);
|
||||
ptr
|
||||
}
|
||||
|
||||
/// Converts Py<'p, T> -> Py<'p, PyObject>
|
||||
/// Consumes `self` without calling `Py_DECREF()`
|
||||
#[inline]
|
||||
pub fn into_object(self) -> Py<'p, PyObject> {
|
||||
pub fn into_object(self) -> Py<'p, PyObjectMarker> {
|
||||
let p = Py {inner: self.inner, _t: PhantomData, py: self.py};
|
||||
std::mem::forget(self);
|
||||
p
|
||||
}
|
||||
|
||||
/// Converts Py<'p, T> -> PyObject<'p>. Calls Py_INCREF() on the ptr.
|
||||
#[inline]
|
||||
pub fn as_pyobject(&self) -> &PyObject<'p> {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Converts Py<'p, T> -> PyObject<'p>
|
||||
/// Consumes `self` without calling `Py_DECREF()`
|
||||
#[inline]
|
||||
pub fn into_pyobject(self) -> PyObject<'p> {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Unchecked downcast from other Py<S> to Py<S>.
|
||||
/// Undefined behavior if the input object does not have the expected type.
|
||||
#[inline]
|
||||
|
@ -292,7 +321,6 @@ impl<'p, T> Py<'p, T>
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'p, T> Py<'p, T> where T: PyTypeInfo
|
||||
{
|
||||
/// Create new python object and move T instance under python management
|
||||
|
@ -332,6 +360,16 @@ impl<'p, T> Py<'p, T> where T: PyTypeInfo
|
|||
}
|
||||
}
|
||||
|
||||
pub fn cast_from_owned_or_err(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> PyResult<Py<'p, T>>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(py))
|
||||
} else {
|
||||
Py::cast_from_owned_ptr(py, ptr).map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast from ffi::PyObject ptr to a concrete object.
|
||||
#[inline]
|
||||
pub unsafe fn cast_from_owned_ptr_or_panic(py: Python<'p>,
|
||||
|
@ -344,16 +382,6 @@ impl<'p, T> Py<'p, T> where T: PyTypeInfo
|
|||
}
|
||||
}
|
||||
|
||||
pub fn cast_from_owned_nullptr(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> PyResult<Py<'p, T>>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(py))
|
||||
} else {
|
||||
Py::cast_from_owned_ptr(py, ptr).map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_ref(&self) -> &T {
|
||||
let offset = <T as PyTypeInfo>::offset();
|
||||
|
@ -436,7 +464,7 @@ impl<'p, T> Py<'p, T> where T: PyTypeInfo
|
|||
#[inline]
|
||||
pub fn extract<D>(&'p self) -> PyResult<D> where D: ::conversion::FromPyObject<'p>
|
||||
{
|
||||
::conversion::FromPyObject::extract(&self)
|
||||
::conversion::FromPyObject::extract(&self.as_pyobject())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -522,8 +550,8 @@ impl<'source, T> ::FromPyObject<'source> for &'source T
|
|||
where T: PyTypeInfo
|
||||
{
|
||||
#[inline]
|
||||
default fn extract<S>(py: &'source Py<'source, S>) -> PyResult<&'source T>
|
||||
where S: PyTypeInfo
|
||||
default fn extract(py: &'source PyObject<'source>) -> PyResult<&'source T>
|
||||
//where S: PyTypeInfo
|
||||
{
|
||||
Ok(py.cast_as()?)
|
||||
}
|
||||
|
@ -532,12 +560,13 @@ impl<'source, T> ::FromPyObject<'source> for &'source T
|
|||
impl<'source, T> ::FromPyObject<'source> for Py<'source, T> where T: PyTypeInfo
|
||||
{
|
||||
#[inline]
|
||||
default fn extract<S>(py: &'source Py<'source, S>) -> PyResult<Py<'source, T>>
|
||||
where S: PyTypeInfo
|
||||
default fn extract(py: &'source PyObject<'source>) -> PyResult<Py<'source, T>>
|
||||
// where S: PyTypeInfo
|
||||
{
|
||||
let checked = unsafe { ffi::PyObject_TypeCheck(py.inner, T::type_object()) != 0 };
|
||||
let ptr = py.as_ptr();
|
||||
let checked = unsafe { ffi::PyObject_TypeCheck(ptr, T::type_object()) != 0 };
|
||||
if checked {
|
||||
Ok( unsafe { Py::<T>::from_borrowed_ptr(py.token(), py.as_ptr()) })
|
||||
Ok( unsafe { Py::<T>::from_borrowed_ptr(py.token(), ptr) })
|
||||
} else {
|
||||
Err(PyDowncastError(py.token(), None).into())
|
||||
}
|
||||
|
@ -547,7 +576,7 @@ impl<'source, T> ::FromPyObject<'source> for Py<'source, T> where T: PyTypeInfo
|
|||
impl <'a, T> ToPyObject for Py<'a, T> {
|
||||
|
||||
#[inline]
|
||||
default fn to_object<'p>(&self, _py: Python) -> PyPtr<PyObject> {
|
||||
default fn to_object<'p>(&self, _py: Python) -> PyPtr<PyObjectMarker> {
|
||||
unsafe { PyPtr::from_borrowed_ptr(self.inner) }
|
||||
}
|
||||
|
||||
|
@ -562,7 +591,7 @@ impl <'a, T> ToPyObject for Py<'a, T> {
|
|||
impl<T> ToPyObject for PyPtr<T> {
|
||||
|
||||
#[inline]
|
||||
default fn to_object(&self, _py: Python) -> PyPtr<PyObject> {
|
||||
default fn to_object(&self, _py: Python) -> PyPtr<PyObjectMarker> {
|
||||
unsafe { PyPtr::from_borrowed_ptr(self.inner) }
|
||||
}
|
||||
|
||||
|
@ -577,7 +606,7 @@ impl<T> ToPyObject for PyPtr<T> {
|
|||
impl<'p, T> IntoPyObject for Py<'p, T> {
|
||||
|
||||
#[inline]
|
||||
default fn into_object(self, _py: Python) -> PyPtr<PyObject> {
|
||||
default fn into_object(self, _py: Python) -> PyPtr<PyObjectMarker> {
|
||||
let ptr = unsafe { PyPtr::from_owned_ptr(self.inner) };
|
||||
std::mem::forget(self);
|
||||
ptr
|
||||
|
|
|
@ -9,8 +9,9 @@ use std::os::raw::c_int;
|
|||
|
||||
use ffi;
|
||||
use typeob::{PyTypeInfo, PyTypeObject, PyObjectAlloc};
|
||||
use token::{PyObjectMarker, PythonToken, PythonObjectWithToken};
|
||||
use objects::{PyObject, PyType, PyBool, PyDict, PyModule};
|
||||
use err::{PyErr, PyResult};
|
||||
use err::{PyErr, PyResult, PyDowncastError};
|
||||
use pyptr::{Py, PyPtr};
|
||||
use pythonrun::GILGuard;
|
||||
|
||||
|
@ -28,19 +29,18 @@ use pythonrun::GILGuard;
|
|||
#[derive(Copy, Clone)]
|
||||
pub struct Python<'p>(PhantomData<&'p GILGuard>);
|
||||
|
||||
pub struct PythonToken<T>(PhantomData<T>);
|
||||
|
||||
impl<T> PythonToken<T> {
|
||||
pub fn token<'p>(&'p self) -> Python<'p> {
|
||||
Python(PhantomData)
|
||||
}
|
||||
/// Trait implemented by Python object types that allow a checked downcast.
|
||||
pub trait PythonObjectWithCheckedDowncast<'p> : Sized {
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
fn downcast_from(Py<'p, PyObject>) -> Result<Self, PyDowncastError<'p>>;
|
||||
|
||||
/// Cast from ffi::PyObject to a concrete Python object type.
|
||||
fn downcast_from_owned_ptr(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> Result<Self, PyDowncastError<'p>>;
|
||||
}
|
||||
|
||||
|
||||
pub trait PythonObjectWithToken : Sized {
|
||||
fn token<'p>(&'p self) -> Python<'p>;
|
||||
}
|
||||
|
||||
pub trait PyClone : Sized {
|
||||
fn clone_ref(&self) -> PyPtr<Self>;
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ impl<'p> Python<'p> {
|
|||
/// If `globals` is `None`, it defaults to Python module `__main__`.
|
||||
/// If `locals` is `None`, it defaults to the value of `globals`.
|
||||
pub fn eval(self, code: &str, globals: Option<&PyDict>,
|
||||
locals: Option<&PyDict>) -> PyResult<PyPtr<PyObject>> {
|
||||
locals: Option<&PyDict>) -> PyResult<PyObject<'p>> {
|
||||
self.run_code(code, ffi::Py_eval_input, globals, locals)
|
||||
}
|
||||
|
||||
|
@ -174,7 +174,7 @@ impl<'p> Python<'p> {
|
|||
/// If `globals` is `None`, it defaults to Python module `__main__`.
|
||||
/// If `locals` is `None`, it defaults to the value of `globals`.
|
||||
fn run_code(self, code: &str, start: c_int,
|
||||
globals: Option<&PyDict>, locals: Option<&PyDict>) -> PyResult<PyPtr<PyObject>> {
|
||||
globals: Option<&PyDict>, locals: Option<&PyDict>) -> PyResult<PyObject<'p>> {
|
||||
let code = CString::new(code).unwrap();
|
||||
|
||||
unsafe {
|
||||
|
@ -198,7 +198,7 @@ impl<'p> Python<'p> {
|
|||
let res_ptr = ffi::PyRun_StringFlags(code.as_ptr(),
|
||||
start, globals, locals, 0 as *mut _);
|
||||
|
||||
PyPtr::from_owned_ptr_or_err(self, res_ptr)
|
||||
PyObject::from_owned_ptr_or_err(self, res_ptr)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,7 +208,7 @@ impl<'p> Python<'p> {
|
|||
}
|
||||
|
||||
/// Import the Python module with the specified name.
|
||||
pub fn import(self, name : &str) -> PyResult<Py<'p, PyModule>> {
|
||||
pub fn import(self, name : &str) -> PyResult<PyModule<'p>> {
|
||||
PyModule::import(self, name)
|
||||
}
|
||||
|
||||
|
@ -216,39 +216,34 @@ impl<'p> Python<'p> {
|
|||
where F: FnOnce(PythonToken<T>) -> T,
|
||||
T: PyTypeInfo + PyObjectAlloc<Type=T>
|
||||
{
|
||||
let value = f(PythonToken(PhantomData));
|
||||
if let Ok(ob) = Py::new(self, value) {
|
||||
ob
|
||||
} else {
|
||||
::err::panic_after_error()
|
||||
}
|
||||
::token::with_token(self, f)
|
||||
}
|
||||
|
||||
/// Gets the Python builtin value `None`.
|
||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||
#[inline]
|
||||
pub fn None(self) -> PyPtr<PyObject> {
|
||||
pub fn None(self) -> PyPtr<PyObjectMarker> {
|
||||
unsafe { PyPtr::from_borrowed_ptr(ffi::Py_None()) }
|
||||
}
|
||||
|
||||
/// Gets the Python builtin value `True`.
|
||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||
#[inline]
|
||||
pub fn True(self) -> PyPtr<PyBool> {
|
||||
unsafe { PyPtr::from_borrowed_ptr(ffi::Py_True()) }
|
||||
pub fn True(self) -> PyBool<'p> {
|
||||
PyBool::get(self, true)
|
||||
}
|
||||
|
||||
/// Gets the Python builtin value `False`.
|
||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||
#[inline]
|
||||
pub fn False(self) -> PyPtr<PyBool> {
|
||||
unsafe { PyPtr::from_borrowed_ptr(ffi::Py_False()) }
|
||||
pub fn False(self) -> PyBool<'p> {
|
||||
PyBool::get(self, false)
|
||||
}
|
||||
|
||||
/// Gets the Python builtin value `NotImplemented`.
|
||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||
#[inline]
|
||||
pub fn NotImplemented(self) -> PyPtr<PyObject> {
|
||||
pub fn NotImplemented(self) -> PyPtr<PyObjectMarker> {
|
||||
unsafe { PyPtr::from_borrowed_ptr(ffi::Py_NotImplemented()) }
|
||||
}
|
||||
|
||||
|
|
96
src/token.rs
Normal file
96
src/token.rs
Normal file
|
@ -0,0 +1,96 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use ffi;
|
||||
use pyptr::{Py, PyPtr};
|
||||
use err::{PyResult};
|
||||
use python::{Python, ToPythonPointer, PythonObjectWithCheckedDowncast};
|
||||
use objects::PyString;
|
||||
use typeob::{PyTypeInfo, PyObjectAlloc};
|
||||
|
||||
|
||||
pub struct PythonToken<T>(PhantomData<T>);
|
||||
|
||||
impl<T> PythonToken<T> {
|
||||
pub fn token<'p>(&'p self) -> Python<'p> {
|
||||
unsafe { Python::assume_gil_acquired() }
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_token<'p, T, F>(py: Python<'p>, f: F) -> Py<'p, T>
|
||||
where F: FnOnce(PythonToken<T>) -> T,
|
||||
T: PyTypeInfo + PyObjectAlloc<Type=T>
|
||||
{
|
||||
let value = f(PythonToken(PhantomData));
|
||||
if let Ok(ob) = Py::new(py, value) {
|
||||
ob
|
||||
} else {
|
||||
::err::panic_after_error()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub trait PythonObjectWithToken : Sized {
|
||||
fn token<'p>(&'p self) -> Python<'p>;
|
||||
}
|
||||
|
||||
|
||||
pub struct PyObjectMarker;
|
||||
|
||||
//pyobject_newtype!(PyObject, PyObject_Check, PyBaseObject_Type);
|
||||
|
||||
|
||||
impl PyObjectMarker {
|
||||
|
||||
#[inline]
|
||||
pub fn from_owned_ptr(_py: Python, ptr: *mut ffi::PyObject) -> PyPtr<PyObjectMarker> {
|
||||
unsafe { PyPtr::from_owned_ptr(ptr) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_owned_ptr_or_err(py: Python, ptr: *mut ffi::PyObject)
|
||||
-> PyResult<PyPtr<PyObjectMarker>> {
|
||||
unsafe { PyPtr::from_owned_ptr_or_err(py, ptr) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_owned_ptr_or_opt(py: Python, ptr: *mut ffi::PyObject)
|
||||
-> Option<PyPtr<PyObjectMarker>> {
|
||||
unsafe { PyPtr::from_owned_ptr_or_opt(py, ptr) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_borrowed_ptr(_py: Python, ptr: *mut ffi::PyObject) -> PyPtr<PyObjectMarker> {
|
||||
unsafe { PyPtr::from_borrowed_ptr(ptr) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'p> fmt::Debug for PyPtr<PyObjectMarker> {
|
||||
default fn fmt(&self, f : &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let repr_obj = unsafe {
|
||||
PyString::downcast_from_owned_ptr(py, ffi::PyObject_Repr(self.as_ptr()))
|
||||
.map_err(|_| fmt::Error)?
|
||||
};
|
||||
f.write_str(&repr_obj.to_string_lossy())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> fmt::Display for PyPtr<PyObjectMarker> {
|
||||
default fn fmt(&self, f : &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let str_obj = unsafe {
|
||||
PyString::downcast_from_owned_ptr(py, ffi::PyObject_Str(self.as_ptr()))
|
||||
.map_err(|_| fmt::Error)?
|
||||
};
|
||||
f.write_str(&str_obj.to_string_lossy())
|
||||
}
|
||||
}
|
|
@ -35,6 +35,12 @@ pub trait PyTypeInfo {
|
|||
|
||||
}
|
||||
|
||||
pub trait PyObjectCtor : PyTypeInfo {
|
||||
|
||||
unsafe fn from_ptr(ptr: *mut ffi::PyObject) -> Self;
|
||||
|
||||
}
|
||||
|
||||
|
||||
impl<'a, T: ?Sized> PyTypeInfo for &'a T where T: PyTypeInfo {
|
||||
type Type = T::Type;
|
||||
|
|
Loading…
Reference in a new issue