simplify class generation
This commit is contained in:
parent
5119fa4f1d
commit
0c7293125c
|
@ -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"]
|
||||
```
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) => {
|
||||
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),
|
||||
Err(e) => Err(e)
|
||||
}
|
||||
}
|
||||
},
|
||||
None => Ok(#default)
|
||||
|
@ -488,10 +492,14 @@ fn impl_arg_param(arg: &Arg, spec: &Vec<FnSpec>, body: &Tokens) -> Tokens {
|
|||
quote! {
|
||||
match match _iter.next().unwrap().as_ref() {
|
||||
Some(obj) => {
|
||||
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)
|
||||
} {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
/// Identity conversion: allows using existing `PyObject` instances where
|
||||
/// `T: ToPyObject` is expected.
|
||||
/*impl<T> ToPyObject for T where T: PythonObject {
|
||||
#[inline]
|
||||
fn to_py_object(&self, py: Python) -> PyObject {
|
||||
PyClone::clone_ref(self, py).into_object()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
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
|
||||
{
|
||||
type Prepared = PyObject;
|
||||
|
||||
#[inline]
|
||||
fn prepare_extract(py: Python, obj: &PyObject) -> PyResult<Self::Prepared> {
|
||||
Ok(obj.clone_ref(py))
|
||||
f(PythonObject::as_object(self).as_ptr())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn extract(py: Python, obj: &'prepared Self::Prepared) -> PyResult<T> {
|
||||
Ok(try!(obj.clone_ref(py).cast_into(py)))
|
||||
}
|
||||
}
|
||||
*/
|
||||
}*/
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
|
32
src/err.rs
32
src/err.rs
|
@ -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;
|
||||
|
||||
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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 () {
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue