simplify class generation

This commit is contained in:
Nikolay Kim 2017-05-18 21:35:08 -07:00
parent 5119fa4f1d
commit 0c7293125c
16 changed files with 166 additions and 215 deletions

View File

@ -15,8 +15,8 @@ Supported Python versions:
* Python 3.5 and up
Supported Rust version:
* Rust 1.15.1 or later
* On Windows, we require rustc 1.15.0-nightly
* Rust 1.17.0-nightly or later
* On Windows, we require rustc 1.17.0-nightly
# Usage
@ -64,7 +64,7 @@ On Windows, you will need to rename the output from \*.dll to \*.pyd.
name = "rust2py"
crate-type = ["cdylib"]
[dependencies.cpython]
[dependencies.pyo3]
version = "0.1"
features = ["extension-module"]
```
@ -101,4 +101,4 @@ fn sum_as_string_py(_: Python, a:i64, b:i64) -> PyResult<String> {
For `setup.py` integration, see https://github.com/PyO3/setuptools-rust
** This is fork of rust-cpython project https://github.com/dgrunwald/rust-cpython **
**This is fork of rust-cpython project https://github.com/dgrunwald/rust-cpython**

View File

@ -34,7 +34,6 @@ pub fn build_py_class(ast: &mut syn::DeriveInput) -> Tokens {
impl_to_py_object(&ast.ident).to_tokens(&mut tokens);
impl_from_py_object(&ast.ident).to_tokens(&mut tokens);
impl_python_object(&ast.ident).to_tokens(&mut tokens);
impl_checked_downcast(&ast.ident).to_tokens(&mut tokens);
let dummy_const = syn::Ident::new(format!("_IMPL_PYO3_CLS_{}", ast.ident));
quote! {
@ -106,42 +105,14 @@ fn impl_storage(cls: &syn::Ident, base: &syn::Ident, fields: &Vec<syn::Field>) -
#accessors
impl _pyo3::PythonObjectWithTypeObject for #cls {
impl _pyo3::class::typeob::PyTypeObjectInfo for #cls {
#[inline]
fn type_name() -> &'static str { #cls_name }
#[inline]
fn type_object(py: _pyo3::Python) -> _pyo3::PyType {
unsafe { <#cls as _pyo3::class::PyTypeObject>::initialized(py, None) }
}
}
impl _pyo3::class::PyTypeObject for #cls {
fn add_to_module(py: _pyo3::Python, module: &_pyo3::PyModule) -> _pyo3::PyResult<()> {
let ty = unsafe { #cls::initialized(py, module.name(py).ok()) };
module.add(py, stringify!(#cls), ty)
}
#[inline]
unsafe fn type_obj() -> &'static mut _pyo3::ffi::PyTypeObject {
fn type_object() -> &'static mut _pyo3::ffi::PyTypeObject {
static mut TYPE_OBJECT: _pyo3::ffi::PyTypeObject = _pyo3::ffi::PyTypeObject_INIT;
&mut TYPE_OBJECT
}
unsafe fn initialized(py: _pyo3::Python, module_name: Option<&str>) -> _pyo3::PyType {
let mut ty = #cls::type_obj();
if (ty.tp_flags & _pyo3::ffi::Py_TPFLAGS_READY) != 0 {
_pyo3::PyType::from_type_ptr(py, ty)
} else {
// automatically initialize the class on-demand
_pyo3::class::typeob::initialize_type::<#cls>(
py, module_name, #cls_name, ty).expect(
concat!("An error occurred while initializing class ",
stringify!(#cls)));
_pyo3::PyType::from_type_ptr(py, ty)
}
unsafe { &mut TYPE_OBJECT }
}
}
@ -258,29 +229,3 @@ fn impl_python_object(cls: &syn::Ident) -> Tokens {
}
}
}
fn impl_checked_downcast(cls: &syn::Ident) -> Tokens {
quote! {
impl _pyo3::PythonObjectWithCheckedDowncast for #cls {
#[inline]
fn downcast_from<'p>(py: _pyo3::Python<'p>, obj: _pyo3::PyObject)
-> Result<#cls, _pyo3::PythonObjectDowncastError<'p>> {
if py.get_type::<#cls>().is_instance(py, &obj) {
Ok(#cls { _unsafe_inner: obj })
} else {
Err(_pyo3::PythonObjectDowncastError(py))
}
}
#[inline]
fn downcast_borrow_from<'a, 'p>(py: _pyo3::Python<'p>, obj: &'a _pyo3::PyObject)
-> Result<&'a #cls, _pyo3::PythonObjectDowncastError<'p>> {
if py.get_type::<#cls>().is_instance(py, obj) {
unsafe { Ok(std::mem::transmute(obj)) }
} else {
Err(_pyo3::PythonObjectDowncastError(py))
}
}
}
}
}

View File

@ -473,9 +473,13 @@ fn impl_arg_param(arg: &Arg, spec: &Vec<FnSpec>, body: &Tokens) -> Tokens {
quote! {
match match _iter.next().unwrap().as_ref() {
Some(obj) => {
match <#opt_ty as _pyo3::FromPyObject>::extract(py, obj) {
Ok(obj) => Ok(Some(obj)),
Err(e) => Err(e),
if obj == &py.None() {
Ok(#default)
} else {
match <#opt_ty as _pyo3::FromPyObject>::extract(py, obj) {
Ok(obj) => Ok(Some(obj)),
Err(e) => Err(e)
}
}
},
None => Ok(#default)
@ -488,9 +492,13 @@ fn impl_arg_param(arg: &Arg, spec: &Vec<FnSpec>, body: &Tokens) -> Tokens {
quote! {
match match _iter.next().unwrap().as_ref() {
Some(obj) => {
match <#ty as _pyo3::FromPyObject>::extract(py, obj) {
Ok(obj) => Ok(obj),
Err(e) => Err(e),
if obj == &py.None() {
Ok(#default)
} else {
match <#ty as _pyo3::FromPyObject>::extract(py, obj) {
Ok(obj) => Ok(obj),
Err(e) => Err(e),
}
}
},
None => Ok(#default)

View File

@ -5,19 +5,45 @@ use std::ffi::CString;
use std::collections::HashMap;
use ::{ffi, class, PyErr, Python, PyResult, PythonObject};
use objects::{PyType, PyModule};
use objects::PyType;
use callback::AbortOnDrop;
use class::{BaseObject, PyMethodDefType};
pub trait PyTypeObject : BaseObject + PythonObject {
/// Trait implemented by Python object types that have a corresponding type object.
pub trait PyTypeObject {
fn add_to_module(py: Python, module: &PyModule) -> PyResult<()>;
/// Retrieves the type object for this Python object type.
fn type_object(py: Python) -> PyType;
unsafe fn type_obj() -> &'static mut ffi::PyTypeObject;
}
unsafe fn initialized(py: Python, module_name: Option<&str>) -> PyType;
/// Trait implemented by object that generated by py::class macro
pub trait PyTypeObjectInfo {
fn type_name() -> &'static str;
fn type_object() -> &'static mut ffi::PyTypeObject;
}
impl<T> PyTypeObject for T where T: BaseObject + PythonObject + PyTypeObjectInfo {
#[inline]
fn type_object(py: Python) -> PyType {
let mut ty = <T as PyTypeObjectInfo>::type_object();
if (ty.tp_flags & ffi::Py_TPFLAGS_READY) != 0 {
unsafe { PyType::from_type_ptr(py, ty) }
} else {
// automatically initialize the class on-demand
initialize_type::<T>(py, None, <T as PyTypeObjectInfo>::type_name(), ty).expect(
format!("An error occurred while initializing class {}",
<T as PyTypeObjectInfo>::type_name()).as_ref());
unsafe { PyType::from_type_ptr(py, ty) }
}
}
}
pub fn initialize_type<T>(py: Python, module_name: Option<&str>, type_name: &str,

View File

@ -85,6 +85,7 @@ pub trait ToPyTuple {
}
py_impl_to_py_object_for_python_object!(PyObject);
py_impl_from_py_object_for_python_object!(PyObject);
/// FromPyObject is implemented by various types that can be extracted from a Python object.
///
@ -111,10 +112,6 @@ pub trait FromPyObject<'source> : Sized {
fn extract(py: Python, obj: &'source PyObject) -> PyResult<Self>;
}
py_impl_from_py_object_for_python_object!(PyObject);
pub trait RefFromPyObject {
fn with_extracted<F, R>(py: Python, obj: &PyObject, f: F) -> PyResult<R>
where F: FnOnce(&Self) -> R;
@ -134,29 +131,32 @@ impl <T: ?Sized> RefFromPyObject for T
}
}
/*
impl <'prepared, T> ExtractPyObject<'prepared> for T
where T: PythonObjectWithCheckedDowncast
{
type Prepared = PyObject;
/// Identity conversion: allows using existing `PyObject` instances where
/// `T: ToPyObject` is expected.
/*impl<T> ToPyObject for T where T: PythonObject {
#[inline]
fn prepare_extract(py: Python, obj: &PyObject) -> PyResult<Self::Prepared> {
Ok(obj.clone_ref(py))
fn to_py_object(&self, py: Python) -> PyObject {
PyClone::clone_ref(self, py).into_object()
}
#[inline]
fn extract(py: Python, obj: &'prepared Self::Prepared) -> PyResult<T> {
Ok(try!(obj.clone_ref(py).cast_into(py)))
default fn into_py_object(self, _py: Python) -> PyObject {
self.into_object()
}
}
*/
#[inline]
default fn with_borrowed_ptr<F, R>(&self, _py: Python, f: F) -> R
where F: FnOnce(*mut ffi::PyObject) -> R
{
f(PythonObject::as_object(self).as_ptr())
}
}*/
// ToPyObject for references
impl <'a, T: ?Sized> ToPyObject for &'a T where T: ToPyObject {
#[inline]
fn to_py_object(&self, py: Python) -> PyObject {
default fn to_py_object(&self, py: Python) -> PyObject {
<T as ToPyObject>::to_py_object(*self, py)
}
@ -194,14 +194,9 @@ impl <T> ToPyObject for Option<T> where T: ToPyObject {
/// `()` is converted to Python `None`.
impl ToPyObject for () {
fn to_py_object(&self, py: Python) -> PyObject {
py.None()
}
fn into_py_object(self, py: Python) -> PyObject {
py.None()
}
}
@ -217,32 +212,3 @@ impl <'source, T> FromPyObject<'source> for Option<T> where T: FromPyObject<'sou
}
}
}
/*
impl <'prepared, T> ExtractPyObject<'prepared> for Option<T>
where T: ExtractPyObject<'prepared>
{
type Prepared = Option<T::Prepared>;
fn prepare_extract(py: Python, obj: &PyObject) -> PyResult<Self::Prepared> {
if obj.as_ptr() == unsafe { ffi::Py_None() } {
Ok(None)
} else {
Ok(Some(try!(T::prepare_extract(py, obj))))
}
}
fn extract(py: Python, obj: &'prepared Self::Prepared) -> PyResult<Option<T>> {
match *obj {
Some(ref inner) => {
match T::extract(py, inner) {
Ok(v) => Ok(Some(v)),
Err(e) => Err(e)
}
},
None => Ok(None)
}
}
}
*/

View File

@ -17,13 +17,13 @@
// DEALINGS IN THE SOFTWARE.
use std;
use python::{PythonObject, ToPythonPointer, Python, PythonObjectDowncastError,
PythonObjectWithTypeObject, PyClone, PyDrop};
use python::{PythonObject, ToPythonPointer, Python, PythonObjectDowncastError, PyClone, PyDrop};
use objects::{PyObject, PyType, exc};
use ffi;
use libc;
use std::ptr;
use libc::c_char;
use class::PyTypeObject;
use conversion::{ToPyObject, ToPyTuple};
use std::ffi::CString;
@ -46,7 +46,7 @@ use pyo3::{Python, PyDict};
py_exception!(mymodule, CustomError);
fn main() {
let gil = Python::acquire_gil();
let gil = Python::acquire_gil();
let py = gil.python();
let ctx = PyDict::new(py);
@ -72,31 +72,11 @@ macro_rules! py_exception {
}
}
impl $crate::PythonObjectWithCheckedDowncast for $name {
impl $crate::PyTypeObject for $name {
#[inline]
fn downcast_from<'p>(py: $crate::Python<'p>, obj: $crate::PyObject)
-> Result<$name, $crate::PythonObjectDowncastError<'p>>
{
if <$name as $crate::PythonObjectWithTypeObject>::type_object(py).is_instance(py, &obj) {
Ok(unsafe { $crate::PythonObject::unchecked_downcast_from(obj) })
} else {
Err($crate::PythonObjectDowncastError(py))
}
fn type_name() -> &'static str {
"$name"
}
#[inline]
fn downcast_borrow_from<'a, 'p>(py: $crate::Python<'p>, obj: &'a $crate::PyObject)
-> Result<&'a $name, $crate::PythonObjectDowncastError<'p>>
{
if <$name as $crate::PythonObjectWithTypeObject>::type_object(py).is_instance(py, obj) {
Ok(unsafe { $crate::PythonObject::unchecked_downcast_borrow_from(obj) })
} else {
Err($crate::PythonObjectDowncastError(py))
}
}
}
impl $crate::PythonObjectWithTypeObject for $name {
#[inline]
fn type_object(py: $crate::Python) -> $crate::PyType {
unsafe {
@ -153,7 +133,7 @@ impl PyErr {
/// Example:
/// `return Err(PyErr::new::<exc::TypeError, _>(py, "Error message"));`
pub fn new<T, V>(py: Python, value: V) -> PyErr
where T: PythonObjectWithTypeObject, V: ToPyObject
where T: PyTypeObject, V: ToPyObject
{
PyErr::new_helper(py, py.get_type::<T>(), value.to_py_object(py).into_object())
}

View File

@ -93,7 +93,8 @@ pub mod ffi;
pub use ffi::{Py_ssize_t, Py_hash_t};
pub use err::{PyErr, PyResult};
pub use objects::*;
pub use python::{Python, PythonObject, PythonObjectWithCheckedDowncast, PythonObjectDowncastError, PythonObjectWithTypeObject, PyClone, PyDrop};
pub use python::{Python, PythonObject,
PythonObjectWithCheckedDowncast, PythonObjectDowncastError, PyClone, PyDrop};
pub use pythonrun::{GILGuard, GILProtected, prepare_freethreaded_python};
pub use conversion::{FromPyObject, RefFromPyObject, ToPyObject, ToPyTuple};
pub use class::{CompareOp};

View File

@ -25,7 +25,6 @@ impl PyBool {
/// Converts a rust `bool` to a Python `bool`.
impl ToPyObject for bool {
#[inline]
fn to_py_object(&self, py: Python) -> PyObject {
PyBool::get(py, *self).into_object()

View File

@ -22,7 +22,7 @@ use std::os::raw::c_char;
use std::{self, mem, ops};
use std::ffi::CStr;
use ffi;
use python::{Python, PythonObject, PythonObjectWithCheckedDowncast, PythonObjectDowncastError, PythonObjectWithTypeObject};
use python::{Python, PythonObject};
use err::{self, PyResult};
use super::object::PyObject;
use super::tuple::PyTuple;
@ -34,37 +34,9 @@ macro_rules! exc_type(
pyobject_newtype!($name);
impl PythonObjectWithCheckedDowncast for $name {
impl $crate::class::typeob::PyTypeObject for $name {
#[inline]
fn downcast_from<'p>(py: Python<'p>, obj : PyObject)
-> Result<$name, PythonObjectDowncastError<'p>>
{
unsafe {
if ffi::PyObject_TypeCheck(obj.as_ptr(), ffi::$exc_name as *mut ffi::PyTypeObject) != 0 {
Ok(PythonObject::unchecked_downcast_from(obj))
} else {
Err(PythonObjectDowncastError(py))
}
}
}
#[inline]
fn downcast_borrow_from<'a, 'p>(py: Python<'p>, obj: &'a PyObject)
-> Result<&'a $name, PythonObjectDowncastError<'p>>
{
unsafe {
if ffi::PyObject_TypeCheck(obj.as_ptr(), ffi::$exc_name as *mut ffi::PyTypeObject) != 0 {
Ok(PythonObject::unchecked_downcast_borrow_from(obj))
} else {
Err(PythonObjectDowncastError(py))
}
}
}
}
impl PythonObjectWithTypeObject for $name {
#[inline]
fn type_object(py: Python) -> PyType {
fn type_object(py: Python) -> $crate::PyType {
unsafe { PyType::from_type_ptr(py, ffi::$exc_name as *mut ffi::PyTypeObject) }
}
}

View File

@ -36,7 +36,7 @@ impl <'p> PyIterator<'p> {
if unsafe { ffi::PyIter_Check(obj.as_ptr()) != 0 } {
Ok(PyIterator { py: py, iter: obj })
} else {
Err(PythonObjectDowncastError(py))
Err(PythonObjectDowncastError(py, None))
}
}

View File

@ -72,7 +72,21 @@ macro_rules! pyobject_newtype(
if ::ffi::$checkfunction(obj.as_ptr()) != 0 {
Ok($name(obj))
} else {
Err(::python::PythonObjectDowncastError(py))
Err(::python::PythonObjectDowncastError(py, None))
}
}
}
#[inline]
fn downcast_from_with_msg<'p>(
py: ::python::Python<'p>,
obj: ::objects::object::PyObject, msg: &'p str)
-> Result<$name, ::python::PythonObjectDowncastError<'p>> {
unsafe {
if ::ffi::$checkfunction(obj.as_ptr()) != 0 {
Ok($name(obj))
} else {
Err(::python::PythonObjectDowncastError(py, Some(msg)))
}
}
}
@ -83,7 +97,7 @@ macro_rules! pyobject_newtype(
if ::ffi::$checkfunction(obj.as_ptr()) != 0 {
Ok(::std::mem::transmute(obj))
} else {
Err(::python::PythonObjectDowncastError(py))
Err(::python::PythonObjectDowncastError(py, None))
}
}
}
@ -92,10 +106,14 @@ macro_rules! pyobject_newtype(
($name: ident, $checkfunction: ident, $typeobject: ident) => (
pyobject_newtype!($name, $checkfunction);
impl ::python::PythonObjectWithTypeObject for $name {
impl $crate::class::typeob::PyTypeObjectInfo for $name {
#[inline]
fn type_object(py: ::python::Python) -> ::objects::typeobject::PyType {
unsafe { ::objects::typeobject::PyType::from_type_ptr(py, &mut ::ffi::$typeobject) }
fn type_name() -> &'static str {
stringify!($name)
}
#[inline]
fn type_object() -> &'static mut $crate::ffi::PyTypeObject {
unsafe { &mut $crate::ffi::$typeobject }
}
}
);

View File

@ -22,8 +22,7 @@ use std::os::raw::c_char;
use python::{Python, PythonObject};
use objectprotocol::ObjectProtocol;
use conversion::{ToPyObject, ToPyTuple};
use objects::{PyObject, PyDict, exc};
use class::PyTypeObject;
use objects::{PyObject, PyDict, PyType, exc};
use err::{self, PyResult, PyErr};
use std::ffi::{CStr, CString};
@ -111,10 +110,23 @@ impl PyModule {
/// sets `new_type.__module__` to this module's name,
/// and adds the type to this module.
pub fn add_class<'p, T>(&self, py: Python<'p>) -> PyResult<()>
where T: PyTypeObject
where T: ::class::BaseObject + PythonObject + ::class::typeob::PyTypeObjectInfo
{
T::add_to_module(py, self)
let mut ty = <T as ::class::typeob::PyTypeObjectInfo>::type_object();
let type_name = <T as ::class::typeob::PyTypeObjectInfo>::type_name();
let ty = if (ty.tp_flags & ffi::Py_TPFLAGS_READY) != 0 {
unsafe { PyType::from_type_ptr(py, ty) }
} else {
// automatically initialize the class on-demand
let name = self.name(py)?;
::class::typeob::initialize_type::<T>(
py, Some(name), type_name, ty).expect(
format!("An error occurred while initializing class {}",
<T as ::class::typeob::PyTypeObjectInfo>::type_name()).as_ref());
unsafe { PyType::from_type_ptr(py, ty) }
};
self.add(py, type_name, ty)
}
}

View File

@ -18,7 +18,7 @@
use std::{mem, ptr};
use ffi;
use python::{Python, PythonObject, PythonObjectWithCheckedDowncast, PythonObjectWithTypeObject, PythonObjectDowncastError};
use python::{Python, PythonObject, PythonObjectWithCheckedDowncast, PythonObjectDowncastError};
use objects::PyType;
use err::PyResult;
@ -122,7 +122,7 @@ impl PythonObjectWithCheckedDowncast for PyObject {
}
}
impl PythonObjectWithTypeObject for PyObject {
impl ::class::PyTypeObject for PyObject {
#[inline]
fn type_object(py: Python) -> PyType {
unsafe { PyType::from_type_ptr(py, &mut ffi::PyBaseObject_Type) }

View File

@ -74,7 +74,6 @@ impl PySlice {
}
impl ToPyObject for PySliceIndices {
fn to_py_object(&self, py: Python) -> PyObject {
PySlice::new(py, self.start, self.stop, self.step).into_object()
}

View File

@ -117,11 +117,11 @@ macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+
]).into_object()
}
fn into_py_object(self, py: Python) -> PyObject {
PyTuple::new(py, &[
$(py_coerce_expr!(self.$n.into_py_object(py)).into_object(),)+
]).into_object()
}
//fn into_py_object(self, py: Python) -> PyObject {
// PyTuple::new(py, &[
// $(py_coerce_expr!(self.$n.into_py_object(py)).into_object(),)+
// ]).into_object()
//}
}
impl <$($T: ToPyObject),+> ToPyTuple for ($($T,)+) {
@ -193,7 +193,6 @@ impl ToPyTuple for NoArgs {
}
}
/// Converts `()` to an empty Python tuple.
impl ToPyTuple for () {

View File

@ -21,6 +21,7 @@ use std::ffi::CString;
use std::marker::PhantomData;
use std::os::raw::c_int;
use ffi;
use class::PyTypeObject;
use objects::{PyObject, PyType, PyBool, PyDict, PyModule};
use err::{self, PyErr, PyResult};
use pythonrun::GILGuard;
@ -39,7 +40,7 @@ use pythonrun::GILGuard;
pub struct Python<'p>(PhantomData<&'p GILGuard>);
/// Trait implemented by all Python object types.
pub trait PythonObject : ::conversion::ToPyObject + Send + Sized + 'static {
pub trait PythonObject : Send + Sized + 'static {
/// Casts the Python object to PyObject.
fn as_object(&self) -> &PyObject;
@ -56,26 +57,51 @@ pub trait PythonObject : ::conversion::ToPyObject + Send + Sized + 'static {
}
// Marker type that indicates an error while downcasting
pub struct PythonObjectDowncastError<'p>(pub Python<'p>);
pub struct PythonObjectDowncastError<'p>(pub Python<'p>, pub Option<&'p str>);
/// Trait implemented by Python object types that allow a checked downcast.
pub trait PythonObjectWithCheckedDowncast : PythonObject {
/// Cast from PyObject to a concrete Python object type.
fn downcast_from<'p>(Python<'p>, PyObject) -> Result<Self, PythonObjectDowncastError<'p>>;
/// Cast from PyObject to a concrete Python object type.
fn downcast_from_with_msg<'p>(
Python<'p>, PyObject, msg: &'p str) -> Result<Self, PythonObjectDowncastError<'p>>;
/// Cast from PyObject to a concrete Python object type.
fn downcast_borrow_from<'a, 'p>(Python<'p>, &'a PyObject) -> Result<&'a Self, PythonObjectDowncastError<'p>>;
}
/// Trait implemented by Python object types that have a corresponding type object.
pub trait PythonObjectWithTypeObject : PythonObjectWithCheckedDowncast {
impl<T> PythonObjectWithCheckedDowncast for T where T: PyTypeObject + PythonObject {
#[inline]
default fn downcast_from<'p>(py: Python<'p>, obj: PyObject)
-> Result<T, PythonObjectDowncastError<'p>> {
if T::type_object(py).is_instance(py, &obj) {
Ok( unsafe { T::unchecked_downcast_from(obj) })
} else {
Err(PythonObjectDowncastError(py, None))
}
}
/// Type name
fn type_name() -> &'static str { "Unknown" }
/// Retrieves the type object for this Python object type.
fn type_object(Python) -> PyType;
#[inline]
default fn downcast_from_with_msg<'p>(py: Python<'p>, obj: PyObject, msg: &'p str)
-> Result<T, PythonObjectDowncastError<'p>> {
if T::type_object(py).is_instance(py, &obj) {
Ok( unsafe { T::unchecked_downcast_from(obj) })
} else {
Err(PythonObjectDowncastError(py, Some(msg)))
}
}
#[inline]
default fn downcast_borrow_from<'a, 'p>(py: Python<'p>, obj: &'a PyObject)
-> Result<&'a T, PythonObjectDowncastError<'p>> {
if T::type_object(py).is_instance(py, obj) {
unsafe { Ok( T::unchecked_downcast_borrow_from(obj)) }
} else {
Err(PythonObjectDowncastError(py, None))
}
}
}
pub trait PyClone : Sized {
@ -298,7 +324,7 @@ impl<'p> Python<'p> {
}
/// Gets the Python type object for type T.
pub fn get_type<T>(self) -> PyType where T: PythonObjectWithTypeObject {
pub fn get_type<T>(self) -> PyType where T: PyTypeObject {
T::type_object(self)
}