update PyType
This commit is contained in:
parent
7cf8e1ab80
commit
af663e0f80
|
@ -97,41 +97,21 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for #cls {
|
||||
impl<'a> std::fmt::Debug for &'a #cls {
|
||||
fn fmt(&self, f : &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||
let py = _pyo3::PyObjectWithToken::token(self);
|
||||
let ptr = <#cls as _pyo3::ToPyPointer>::as_ptr(self);
|
||||
unsafe {
|
||||
let repr = PyObject::from_borrowed_ptr(
|
||||
py, _pyo3::ffi::PyObject_Repr(ptr));
|
||||
use pyo3::ObjectProtocol2;
|
||||
|
||||
let result = {
|
||||
let s = _pyo3::PyString::downcast_from(py, &repr);
|
||||
let s = try!(s.map_err(|_| std::fmt::Error));
|
||||
f.write_str(&s.to_string_lossy())
|
||||
};
|
||||
py.release(repr);
|
||||
result
|
||||
}
|
||||
let s = try!(ObjectProtocol2::repr(self).map_err(|_| std::fmt::Error));
|
||||
f.write_str(&s.to_string_lossy())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for #cls {
|
||||
impl<'a> std::fmt::Display for &'a #cls {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||
let py = _pyo3::PyObjectWithToken::token(self);
|
||||
let ptr = <#cls as _pyo3::ToPyPointer>::as_ptr(self);
|
||||
unsafe {
|
||||
let repr = PyObject::from_borrowed_ptr(
|
||||
py, _pyo3::ffi::PyObject_Str(ptr));
|
||||
use pyo3::ObjectProtocol2;
|
||||
|
||||
let result = {
|
||||
let s = _pyo3::PyString::downcast_from(py, &repr);
|
||||
let s = try!(s.map_err(|_| std::fmt::Error));
|
||||
f.write_str(&s.to_string_lossy())
|
||||
};
|
||||
py.release(repr);
|
||||
result
|
||||
}
|
||||
let s = try!(ObjectProtocol2::str(self).map_err(|_| std::fmt::Error));
|
||||
f.write_str(&s.to_string_lossy())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
42
src/err.rs
42
src/err.rs
|
@ -6,9 +6,10 @@ use std::error::Error;
|
|||
use libc;
|
||||
|
||||
use ffi;
|
||||
use python::{ToPyPointer, IntoPyPointer, Python, PyDowncastInto, PyClone};
|
||||
use python::{ToPyPointer, IntoPyPointer, Python, PyDowncastFrom, PyClone};
|
||||
use objects::{PyObject, PyType, exc};
|
||||
use typeob::{PyTypeObject};
|
||||
use token::Py;
|
||||
use typeob::PyTypeObject;
|
||||
use conversion::{ToPyObject, IntoPyTuple, IntoPyObject};
|
||||
|
||||
/**
|
||||
|
@ -76,7 +77,7 @@ macro_rules! py_exception {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn type_object(py: $crate::Python) -> $crate::PyType {
|
||||
fn type_object<'p>(py: $crate::Python<'p>) -> &'p $crate::PyType {
|
||||
unsafe { $crate::PyType::from_type_ptr(py, $name::type_object(py)) }
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +91,7 @@ macro_rules! py_exception {
|
|||
#[derive(Debug)]
|
||||
pub struct PyErr {
|
||||
/// The type of the exception. This should be either a `PyClass` or a `PyType`.
|
||||
pub ptype: PyType,
|
||||
pub ptype: Py<PyType>,
|
||||
/// The value of the exception.
|
||||
///
|
||||
/// This can be either an instance of `ptype`,
|
||||
|
@ -140,8 +141,8 @@ impl PyErr {
|
|||
///
|
||||
/// `base` can be an existing exception type to subclass, or a tuple of classes
|
||||
/// `dict` specifies an optional dictionary of class variables and methods
|
||||
pub fn new_type(py: Python, name: &str, base: Option<PyType>, dict: Option<PyObject>)
|
||||
-> PyType
|
||||
pub fn new_type<'p>(py: Python<'p>,
|
||||
name: &str, base: Option<&PyType>, dict: Option<PyObject>) -> &'p PyType
|
||||
{
|
||||
let base: *mut ffi::PyObject = match base {
|
||||
None => std::ptr::null_mut(),
|
||||
|
@ -183,19 +184,19 @@ impl PyErr {
|
|||
// and because we mustn't panic in normalize().
|
||||
PyErr {
|
||||
ptype: if ptype.is_null() {
|
||||
py.get_type::<exc::SystemError>()
|
||||
py.get_type::<exc::SystemError>().into()
|
||||
} else {
|
||||
PyObject::from_owned_ptr(py, ptype).unchecked_cast_into::<PyType>()
|
||||
PyType::from_type_ptr(py, ptype as *mut ffi::PyTypeObject).into()
|
||||
},
|
||||
pvalue: PyObject::from_owned_ptr_or_opt(py, pvalue),
|
||||
ptraceback: PyObject::from_owned_ptr_or_opt(py, ptraceback)
|
||||
}
|
||||
}
|
||||
|
||||
fn new_helper(_py: Python, ty: PyType, value: PyObject) -> PyErr {
|
||||
fn new_helper(_py: Python, ty: &PyType, value: PyObject) -> PyErr {
|
||||
assert!(unsafe { ffi::PyExceptionClass_Check(ty.as_ptr()) } != 0);
|
||||
PyErr {
|
||||
ptype: ty,
|
||||
ptype: ty.into(),
|
||||
pvalue: Some(value),
|
||||
ptraceback: None
|
||||
}
|
||||
|
@ -211,23 +212,24 @@ impl PyErr {
|
|||
}
|
||||
|
||||
fn from_instance_helper<'p>(py: Python, obj: PyObject) -> PyErr {
|
||||
if unsafe { ffi::PyExceptionInstance_Check(obj.as_ptr()) } != 0 {
|
||||
let ptr = obj.as_ptr();
|
||||
|
||||
if unsafe { ffi::PyExceptionInstance_Check(ptr) } != 0 {
|
||||
PyErr {
|
||||
ptype: unsafe { PyObject::from_borrowed_ptr(
|
||||
py, ffi::PyExceptionInstance_Class(obj.as_ptr()))
|
||||
.unchecked_cast_into::<PyType>() },
|
||||
ptype: unsafe { PyType::from_type_ptr(py, ptr as *mut ffi::PyTypeObject).into() },
|
||||
pvalue: Some(obj),
|
||||
ptraceback: None
|
||||
}
|
||||
} else if unsafe { ffi::PyExceptionClass_Check(obj.as_ptr()) } != 0 {
|
||||
PyErr {
|
||||
ptype: PyType::downcast_into(py, obj).expect("Failed to downcast into PyType"),
|
||||
ptype: PyType::downcast_from(py, &obj)
|
||||
.expect("Failed to downcast into PyType").into(),
|
||||
pvalue: None,
|
||||
ptraceback: None
|
||||
}
|
||||
} else {
|
||||
PyErr {
|
||||
ptype: py.get_type::<exc::TypeError>(),
|
||||
ptype: py.get_type::<exc::TypeError>().into(),
|
||||
pvalue: Some("exceptions must derive from BaseException".into_object(py)),
|
||||
ptraceback: None
|
||||
}
|
||||
|
@ -238,9 +240,9 @@ 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: PyType, value: Option<PyObject>) -> PyErr {
|
||||
pub fn new_lazy_init(exc: &PyType, value: Option<PyObject>) -> PyErr {
|
||||
PyErr {
|
||||
ptype: exc,
|
||||
ptype: exc.into(),
|
||||
pvalue: value,
|
||||
ptraceback: None
|
||||
}
|
||||
|
@ -254,7 +256,7 @@ impl PyErr {
|
|||
where A: IntoPyTuple
|
||||
{
|
||||
PyErr {
|
||||
ptype: exc.clone_ref(py),
|
||||
ptype: exc.into(),
|
||||
pvalue: Some(args.into_tuple(py).into()),
|
||||
ptraceback: None
|
||||
}
|
||||
|
@ -307,7 +309,7 @@ impl PyErr {
|
|||
}
|
||||
|
||||
/// Retrieves the exception type.
|
||||
pub fn get_type(&self, py: Python) -> PyType {
|
||||
pub fn get_type(&self, py: Python) -> Py<PyType> {
|
||||
self.ptype.clone_ref(py)
|
||||
}
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ pub trait ObjectProtocol {
|
|||
|
||||
/// Gets the Python type object for this object's type.
|
||||
#[inline]
|
||||
fn get_type(&self, py: Python) -> PyType;
|
||||
fn get_type<'p>(&self, py: Python<'p>) -> &'p PyType;
|
||||
|
||||
fn get_refcnt(&self) -> isize;
|
||||
}
|
||||
|
@ -383,7 +383,7 @@ impl<T> ObjectProtocol for T where T: ToPyPointer {
|
|||
|
||||
/// Gets the Python type object for this object's type.
|
||||
#[inline]
|
||||
fn get_type(&self, py: Python) -> PyType {
|
||||
fn get_type<'p>(&self, py: Python<'p>) -> &'p PyType {
|
||||
unsafe {
|
||||
PyType::from_type_ptr(py, (*self.as_ptr()).ob_type)
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ pub trait ObjectProtocol2 {
|
|||
fn iter<'p>(&'p self) -> PyResult<PyIterator<'p>>;
|
||||
|
||||
/// Gets the Python type object for this object's type.
|
||||
fn get_type(&self) -> PyType;
|
||||
fn get_type(&self) -> &PyType;
|
||||
|
||||
fn get_refcnt(&self) -> isize;
|
||||
|
||||
|
@ -388,7 +388,7 @@ impl<'a, T> ObjectProtocol2 for &'a T where T: PyObjectWithToken + ToPyPointer {
|
|||
|
||||
/// Gets the Python type object for this object's type.
|
||||
#[inline]
|
||||
fn get_type(&self) -> PyType {
|
||||
fn get_type(&self) -> &PyType {
|
||||
unsafe {
|
||||
PyType::from_type_ptr(self.token(), (*self.as_ptr()).ob_type)
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ macro_rules! exc_type(
|
|||
fn init_type(_py: Python) {}
|
||||
|
||||
#[inline]
|
||||
fn type_object(py: $crate::python::Python) -> $crate::PyType {
|
||||
fn type_object<'p>(py: $crate::python::Python<'p>) -> &'p $crate::PyType {
|
||||
unsafe { PyType::from_type_ptr(py, ffi::$exc_name as *mut ffi::PyTypeObject) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ macro_rules! pyobject_nativetype(
|
|||
fn init_type(_py: Python) {}
|
||||
|
||||
#[inline]
|
||||
fn type_object(py: $crate::Python) -> $crate::PyType {
|
||||
fn type_object<'p>(py: $crate::Python<'p>) -> &'p $crate::PyType {
|
||||
unsafe { $crate::PyType::from_type_ptr(py, &mut $crate::ffi::$typeobject) }
|
||||
}
|
||||
}
|
||||
|
@ -293,6 +293,11 @@ macro_rules! pyobject_nativetype2(
|
|||
unsafe{$crate::std::mem::transmute(self)}
|
||||
}
|
||||
}
|
||||
impl<'a> $crate::std::convert::From<&'a $name> for &'a $crate::PyObject {
|
||||
fn from(ob: &'a $name) -> Self {
|
||||
unsafe{$crate::std::mem::transmute(ob)}
|
||||
}
|
||||
}
|
||||
impl $crate::PyObjectWithToken for $name {
|
||||
#[inline]
|
||||
fn token<'p>(&'p self) -> $crate::Python<'p> {
|
||||
|
@ -395,7 +400,7 @@ macro_rules! pyobject_nativetype2(
|
|||
fn init_type(_py: Python) {}
|
||||
|
||||
#[inline]
|
||||
fn type_object(py: $crate::Python) -> $crate::PyType {
|
||||
fn type_object<'p>(py: $crate::Python<'p>) -> &'p $crate::PyType {
|
||||
unsafe { $crate::PyType::from_type_ptr(py, &mut $crate::ffi::$typeobject) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,13 @@ use pointers::PyPtr;
|
|||
use python::{Python, ToPyPointer};
|
||||
use objects::PyObject;
|
||||
use err::{PyErr, PyResult};
|
||||
use token::PyObjectWithToken;
|
||||
use typeob::PyTypeObject;
|
||||
|
||||
/// Represents a reference to a Python type object.
|
||||
pub struct PyType(PyPtr);
|
||||
|
||||
pyobject_convert!(PyType);
|
||||
pyobject_nativetype!(PyType, PyType_Type, PyType_Check);
|
||||
pyobject_nativetype2!(PyType, PyType_Type, PyType_Check);
|
||||
|
||||
|
||||
impl PyType {
|
||||
|
@ -30,26 +30,28 @@ impl PyType {
|
|||
/// This increments the reference count on the type object.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_type_ptr(_py: Python, p: *mut ffi::PyTypeObject) -> PyType {
|
||||
PyType(PyPtr::from_borrowed_ptr(p as *mut ffi::PyObject))
|
||||
pub unsafe fn from_type_ptr<'p>(py: Python<'p>, p: *mut ffi::PyTypeObject) -> &'p PyType
|
||||
{
|
||||
|
||||
py.unchecked_cast_from_borrowed_ptr::<PyType>(p as *mut ffi::PyObject)
|
||||
}
|
||||
|
||||
/// Gets the name of the PyType.
|
||||
pub fn name<'a>(&'a self, _py: Python) -> Cow<'a, str> {
|
||||
pub fn name<'a>(&'a self) -> Cow<'a, str> {
|
||||
unsafe {
|
||||
CStr::from_ptr((*self.as_type_ptr()).tp_name).to_string_lossy()
|
||||
}
|
||||
}
|
||||
|
||||
/// Check whether `self` is subclass of type `T` like Python `issubclass` function
|
||||
pub fn is_subclass<T>(&self, py: Python) -> PyResult<bool>
|
||||
pub fn is_subclass<T>(&self) -> PyResult<bool>
|
||||
where T: PyTypeObject
|
||||
{
|
||||
let result = unsafe {
|
||||
ffi::PyObject_IsSubclass(self.as_ptr(), T::type_object(py).as_ptr())
|
||||
ffi::PyObject_IsSubclass(self.as_ptr(), T::type_object(self.token()).as_ptr())
|
||||
};
|
||||
if result == -1 {
|
||||
Err(PyErr::fetch(py))
|
||||
Err(PyErr::fetch(self.token()))
|
||||
} else if result == 1 {
|
||||
Ok(true)
|
||||
} else {
|
||||
|
@ -58,12 +60,12 @@ impl PyType {
|
|||
}
|
||||
|
||||
// Check whether `obj` is an instance of `self`
|
||||
pub fn is_instance<T: ToPyPointer>(&self, py: Python, obj: &T) -> PyResult<bool> {
|
||||
pub fn is_instance<T: ToPyPointer>(&self, obj: &T) -> PyResult<bool> {
|
||||
let result = unsafe {
|
||||
ffi::PyObject_IsInstance(obj.as_ptr(), self.as_ptr())
|
||||
};
|
||||
if result == -1 {
|
||||
Err(PyErr::fetch(py))
|
||||
Err(PyErr::fetch(self.token()))
|
||||
} else if result == 1 {
|
||||
Ok(true)
|
||||
} else {
|
||||
|
|
|
@ -195,7 +195,7 @@ impl<'p> Python<'p> {
|
|||
}
|
||||
|
||||
/// Gets the Python type object for type T.
|
||||
pub fn get_type<T>(self) -> PyType where T: PyTypeObject {
|
||||
pub fn get_type<T>(self) -> &'p PyType where T: PyTypeObject {
|
||||
T::type_object(self)
|
||||
}
|
||||
|
||||
|
@ -261,7 +261,7 @@ impl<'p> Python<'p> {
|
|||
|
||||
/// Check whether `obj` is an instance of type `T` like Python `isinstance` function
|
||||
pub fn is_instance<T: PyTypeObject>(self, obj: &PyObject) -> PyResult<bool> {
|
||||
T::type_object(self).is_instance(self, obj)
|
||||
T::type_object(self).is_instance(obj)
|
||||
}
|
||||
|
||||
/// Check whether type `T` is subclass of type `U` like Python `issubclass` function
|
||||
|
@ -269,7 +269,7 @@ impl<'p> Python<'p> {
|
|||
where T: PyTypeObject,
|
||||
U: PyTypeObject
|
||||
{
|
||||
T::type_object(self).is_subclass::<U>(self)
|
||||
T::type_object(self).is_subclass::<U>()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,6 +297,14 @@ impl<'p> Python<'p> {
|
|||
<D as PyDowncastFrom>::unchecked_downcast_from(self, p)
|
||||
}
|
||||
|
||||
pub unsafe fn unchecked_cast_from_borrowed_ptr<D>(self, ptr: *mut ffi::PyObject) -> &'p D
|
||||
where D: PyDowncastFrom
|
||||
{
|
||||
let obj = PyObject::from_borrowed_ptr(self, ptr);
|
||||
let p = pythonrun::register(self, obj);
|
||||
<D as PyDowncastFrom>::unchecked_downcast_from(self, p)
|
||||
}
|
||||
|
||||
pub fn unchecked_cast_from_ptr_or_err<D>(self, ptr: *mut ffi::PyObject) -> PyResult<&'p D>
|
||||
where D: PyDowncastFrom
|
||||
{
|
||||
|
@ -343,15 +351,15 @@ mod test {
|
|||
assert_eq!(v, 2);
|
||||
}
|
||||
|
||||
/*#[test]
|
||||
#[test]
|
||||
fn test_is_instance() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
assert!(py.is_instance::<PyBool>(py.True().as_ob_ref(py)).unwrap());
|
||||
assert!(py.is_instance::<PyBool>(py.True().into()).unwrap());
|
||||
let list = PyList::new(py, &[1, 2, 3, 4]);
|
||||
assert!(!py.is_instance::<PyBool>(list.as_ref()).unwrap());
|
||||
assert!(py.is_instance::<PyList>(list.as_ref()).unwrap());
|
||||
}*/
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_subclass() {
|
||||
|
|
|
@ -130,7 +130,7 @@ pub trait PyTypeObject {
|
|||
fn init_type(py: Python);
|
||||
|
||||
/// Retrieves the type object for this Python object type.
|
||||
fn type_object(py: Python) -> PyType;
|
||||
fn type_object<'p>(py: Python<'p>) -> &'p PyType;
|
||||
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ impl<T> PyTypeObject for T where T: PyObjectAlloc<T> + PyTypeInfo {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
default fn type_object(py: Python) -> PyType {
|
||||
default fn type_object<'p>(py: Python<'p>) -> &'p PyType {
|
||||
<T as PyTypeObject>::init_type(py);
|
||||
|
||||
unsafe { PyType::from_type_ptr(py, <T as PyTypeInfo>::type_object()) }
|
||||
|
@ -160,9 +160,11 @@ impl<T> PyTypeObject for T where T: PyObjectAlloc<T> + PyTypeInfo {
|
|||
}
|
||||
|
||||
|
||||
pub fn initialize_type<T>(py: Python, module_name: Option<&str>, type_name: &str,
|
||||
type_description: &'static str, type_object: &mut ffi::PyTypeObject)
|
||||
-> PyResult<PyType>
|
||||
pub fn initialize_type<'p, T>(py: Python<'p>,
|
||||
module_name: Option<&str>,
|
||||
type_name: &str,
|
||||
type_description: &'static str,
|
||||
type_object: &mut ffi::PyTypeObject) -> PyResult<&'p PyType>
|
||||
where T: PyObjectAlloc<T> + PyTypeInfo
|
||||
{
|
||||
// type name
|
||||
|
|
|
@ -59,10 +59,16 @@ struct ClassWithDocs { }
|
|||
|
||||
#[test]
|
||||
fn class_with_docstr() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<ClassWithDocs>();
|
||||
py_run!(py, typeobj, "assert typeobj.__doc__ == 'Line1\\nLine2\\n Line3'");
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
println!("TEST1");
|
||||
let typeobj = py.get_type::<ClassWithDocs>();
|
||||
println!("TEST2");
|
||||
py_run!(py, typeobj, "assert typeobj.__doc__ == 'Line1\\nLine2\\n Line3'");
|
||||
println!("TEST3");
|
||||
}
|
||||
println!("TEST4");
|
||||
}
|
||||
|
||||
#[py::class(name=CustomName)]
|
||||
|
@ -283,7 +289,7 @@ impl ClassMethod {
|
|||
|
||||
#[classmethod]
|
||||
fn method(cls: &PyType, py: Python) -> PyResult<String> {
|
||||
Ok(format!("{}.method()!", cls.name(py)))
|
||||
Ok(format!("{}.method()!", cls.name()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -306,7 +312,7 @@ struct ClassMethodWithArgs{token: PyToken}
|
|||
impl ClassMethodWithArgs {
|
||||
#[classmethod]
|
||||
fn method(cls: &PyType, py: Python, input: &PyString) -> PyResult<String> {
|
||||
Ok(format!("{}.method({})", cls.name(py), input))
|
||||
Ok(format!("{}.method({})", cls.name(), input))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1042,7 +1048,7 @@ impl<'p> PyContextProtocol<'p> for ContextManager {
|
|||
}
|
||||
|
||||
fn __exit__(&mut self, py: Python,
|
||||
ty: Option<PyType>,
|
||||
ty: Option<&'p PyType>,
|
||||
value: Option<PyObject>,
|
||||
traceback: Option<PyObject>) -> PyResult<bool> {
|
||||
self.exit_called = true;
|
||||
|
|
Loading…
Reference in New Issue