Implement ToPyObject for all PythonObjects.

This commit is contained in:
Daniel Grunwald 2015-07-18 13:39:53 +02:00
parent a469635eca
commit 1c4d71d712
5 changed files with 60 additions and 35 deletions

View File

@ -75,36 +75,6 @@ pub trait FromPyObject<'p> {
fn from_py_object(s: &PyObject<'p>) -> PyResult<'p, Self>; fn from_py_object(s: &PyObject<'p>) -> PyResult<'p, Self>;
} }
// PyObject, PyModule etc.
// We support FromPyObject and ToPyObject for owned python references.
// This allows using existing Python objects in code that generically expects a value
// convertible to a Python object.
/// Identity conversion: allows using existing `PyObject` instances where
/// `ToPyObject` is expected.
impl <'p, 's> ToPyObject<'p> for PyObject<'s> {
type ObjectType = PyObject<'p>;
#[inline]
fn to_py_object(&self, py: Python<'p>) -> PyObject<'p> {
self.clone().into_py_object(py)
}
#[inline]
fn into_py_object(self, _py: Python<'p>) -> PyObject<'p> {
// Transmute the lifetime.
// This is safe, because both lifetime variables represent the same lifetime:
// that of the python GIL acquisition.
unsafe { std::mem::transmute(self) }
}
#[inline]
fn with_borrowed_ptr<F, R>(&self, _py: Python<'p>, f: F) -> R
where F: FnOnce(*mut ffi::PyObject) -> R {
f(self.as_ptr())
}
}
impl <'p, T> FromPyObject<'p> for T where T: PythonObjectWithCheckedDowncast<'p> { impl <'p, T> FromPyObject<'p> for T where T: PythonObjectWithCheckedDowncast<'p> {
#[inline] #[inline]
fn from_py_object(s : &PyObject<'p>) -> PyResult<'p, T> { fn from_py_object(s : &PyObject<'p>) -> PyResult<'p, T> {
@ -112,10 +82,7 @@ impl <'p, T> FromPyObject<'p> for T where T: PythonObjectWithCheckedDowncast<'p>
} }
} }
// &PyObject, &PyModule etc. // ToPyObject for references
// We support FromPyObject and ToPyObject for borrowed python references.
// This allows using existing Python objects in code that generically expects a value
// convertible to a Python object.
impl <'p, 's, T: ?Sized> ToPyObject<'p> for &'s T where T: ToPyObject<'p> { impl <'p, 's, T: ?Sized> ToPyObject<'p> for &'s T where T: ToPyObject<'p> {
type ObjectType = T::ObjectType; type ObjectType = T::ObjectType;

View File

@ -39,6 +39,35 @@ pub use self::num::PyInt;
pub use self::num::PyLong as PyInt; pub use self::num::PyLong as PyInt;
pub use self::num::{PyLong, PyFloat}; pub use self::num::{PyLong, PyFloat};
/// Identity conversion: allows using existing `PyObject` instances where
/// `T: ToPyObject` is expected.
macro_rules! pyobject_to_pyobject(
($name: ident) => (
impl <'p, 's> ::conversion::ToPyObject<'p> for $name<'s> {
type ObjectType = $name<'p>;
#[inline]
fn to_py_object(&self, py: Python<'p>) -> $name<'p> {
self.clone().into_py_object(py)
}
#[inline]
fn into_py_object(self, _py: Python<'p>) -> $name<'p> {
// Transmute the lifetime.
// This is safe, because both lifetime variables represent the same lifetime:
// that of the python GIL acquisition.
unsafe { ::std::mem::transmute(self) }
}
#[inline]
fn with_borrowed_ptr<F, R>(&self, _py: Python<'p>, f: F) -> R
where F: FnOnce(*mut ffi::PyObject) -> R {
f(self.as_ptr())
}
}
)
);
macro_rules! pyobject_newtype( macro_rules! pyobject_newtype(
($name: ident) => ( ($name: ident) => (
/// Clone returns another reference to the Python object, /// Clone returns another reference to the Python object,
@ -50,6 +79,8 @@ macro_rules! pyobject_newtype(
} }
} }
pyobject_to_pyobject!($name);
impl <'p> ::python::PythonObject<'p> for $name<'p> { impl <'p> ::python::PythonObject<'p> for $name<'p> {
#[inline] #[inline]
fn as_object(&self) -> &::objects::object::PyObject<'p> { fn as_object(&self) -> &::objects::object::PyObject<'p> {
@ -74,6 +105,11 @@ macro_rules! pyobject_newtype(
unsafe fn unchecked_downcast_borrow_from<'a>(obj: &'a ::objects::object::PyObject<'p>) -> &'a Self { unsafe fn unchecked_downcast_borrow_from<'a>(obj: &'a ::objects::object::PyObject<'p>) -> &'a Self {
::std::mem::transmute(obj) ::std::mem::transmute(obj)
} }
#[inline]
fn python(&self) -> Python<'p> {
self.0.python()
}
} }
); );
($name: ident, $checkfunction: ident) => ( ($name: ident, $checkfunction: ident) => (

View File

@ -69,6 +69,8 @@ impl <'p> Clone for PyObject<'p> {
} }
} }
pyobject_to_pyobject!(PyObject);
impl <'p> PythonObject<'p> for PyObject<'p> { impl <'p> PythonObject<'p> for PyObject<'p> {
#[inline] #[inline]
fn as_object<'a>(&'a self) -> &'a PyObject<'p> { fn as_object<'a>(&'a self) -> &'a PyObject<'p> {

View File

@ -46,7 +46,7 @@ pub trait ToPythonPointer {
} }
/// Trait implemented by all Python object types. /// Trait implemented by all Python object types.
pub trait PythonObject<'p> : 'p + Clone { pub trait PythonObject<'p> : 'p + Clone + ::conversion::ToPyObject<'p> {
/// Casts the Python object to PyObject. /// Casts the Python object to PyObject.
fn as_object(&self) -> &PyObject<'p>; fn as_object(&self) -> &PyObject<'p>;

View File

@ -233,6 +233,26 @@ impl <'p, T> Clone for PyRustType<'p, T> where T: 'p + Send {
} }
} }
impl <'p, 's, T> ToPyObject<'p> for PyRustType<'s, T> where T: 's + Send {
type ObjectType = PyType<'p>;
#[inline]
fn to_py_object(&self, py: Python<'p>) -> PyType<'p> {
self.type_obj.to_py_object(py)
}
#[inline]
fn into_py_object(self, py: Python<'p>) -> PyType<'p> {
self.type_obj.into_py_object(py)
}
#[inline]
fn with_borrowed_ptr<F, R>(&self, _py: Python<'p>, f: F) -> R
where F: FnOnce(*mut ffi::PyObject) -> R {
f(self.as_ptr())
}
}
impl <'p, T> PythonObject<'p> for PyRustType<'p, T> where T: 'p + Send { impl <'p, T> PythonObject<'p> for PyRustType<'p, T> where T: 'p + Send {
#[inline] #[inline]
fn as_object(&self) -> &PyObject<'p> { fn as_object(&self) -> &PyObject<'p> {