refactor PyTypeObject trait
This commit is contained in:
parent
86c20bb139
commit
ea8f11fa6d
|
@ -107,6 +107,27 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident, token: Option<syn::Ident>) ->
|
|||
}
|
||||
}
|
||||
|
||||
impl _pyo3::typeob::PyTypeObject for #cls {
|
||||
#[inline(always)]
|
||||
fn init_type(py: Python) {
|
||||
static START: std::sync::Once = std::sync::ONCE_INIT;
|
||||
START.call_once(|| {
|
||||
let mut ty = <#cls as _pyo3::typeob::PyTypeInfo>::type_object();
|
||||
|
||||
if (ty.tp_flags & _pyo3::ffi::Py_TPFLAGS_READY) == 0 {
|
||||
// automatically initialize the class on-demand
|
||||
let to = _pyo3::typeob::initialize_type::<#cls>(
|
||||
py, None, <#cls as _pyo3::typeob::PyTypeInfo>::type_name(), ty)
|
||||
.expect(
|
||||
format!("An error occurred while initializing class {}",
|
||||
<#cls as _pyo3::typeob::PyTypeInfo>::type_name())
|
||||
.as_ref());
|
||||
py.release(to);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl _pyo3::python::PyDowncastFrom for #cls
|
||||
{
|
||||
fn downcast_from<'a, 'p>(py: Python<'p>, ob: &'a _pyo3::PyObject)
|
||||
|
|
34
src/err.rs
34
src/err.rs
|
@ -52,24 +52,32 @@ macro_rules! py_exception {
|
|||
pub fn new<T: $crate::IntoPyObject>(py: $crate::Python, args: T) -> $crate::PyErr {
|
||||
$crate::PyErr::new::<$name, T>(py, args)
|
||||
}
|
||||
#[inline(always)]
|
||||
fn type_object(py: $crate::Python) -> *mut $crate::ffi::PyTypeObject {
|
||||
#[allow(non_upper_case_globals)]
|
||||
static mut type_object: *mut $crate::ffi::PyTypeObject =
|
||||
0 as *mut $crate::ffi::PyTypeObject;
|
||||
|
||||
unsafe {
|
||||
if type_object.is_null() {
|
||||
type_object = $crate::PyErr::new_type(
|
||||
py, concat!(stringify!($module), ".", stringify!($name)),
|
||||
Some(py.get_type::<$base>()), None).as_type_ptr();
|
||||
}
|
||||
type_object
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::PyTypeObject for $name {
|
||||
#[inline(always)]
|
||||
fn init_type(py: $crate::Python) {
|
||||
let _ = $name::type_object(py);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn type_object(py: $crate::Python) -> $crate::PyType {
|
||||
unsafe {
|
||||
#[allow(non_upper_case_globals)]
|
||||
static mut type_object: *mut $crate::ffi::PyTypeObject = 0 as *mut $crate::ffi::PyTypeObject;
|
||||
|
||||
if type_object.is_null() {
|
||||
type_object = $crate::PyErr::new_type(
|
||||
py,
|
||||
concat!(stringify!($module), ".", stringify!($name)),
|
||||
Some(py.get_type::<$base>()), None).as_type_ptr();
|
||||
}
|
||||
|
||||
$crate::PyType::from_type_ptr(py, type_object)
|
||||
}
|
||||
unsafe { $crate::PyType::from_type_ptr(py, $name::type_object(py)) }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -20,6 +20,9 @@ macro_rules! exc_type(
|
|||
// pyobject_newtype!($name);
|
||||
|
||||
impl $crate::PyTypeObject for $name {
|
||||
#[inline(always)]
|
||||
fn init_type(_py: Python) {}
|
||||
|
||||
#[inline]
|
||||
fn type_object(py: $crate::python::Python) -> $crate::PyType {
|
||||
unsafe { PyType::from_type_ptr(py, ffi::$exc_name as *mut ffi::PyTypeObject) }
|
||||
|
|
|
@ -39,12 +39,10 @@ macro_rules! pyobject_nativetype(
|
|||
fn size() -> usize {
|
||||
$crate::std::mem::size_of::<ffi::PyObject>()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn offset() -> isize {
|
||||
0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn type_name() -> &'static str {
|
||||
stringify!($name)
|
||||
|
@ -55,6 +53,16 @@ macro_rules! pyobject_nativetype(
|
|||
}
|
||||
}
|
||||
|
||||
impl $crate::typeob::PyTypeObject for $name {
|
||||
#[inline(always)]
|
||||
fn init_type(_py: Python) {}
|
||||
|
||||
#[inline]
|
||||
fn type_object(py: $crate::Python) -> $crate::PyType {
|
||||
unsafe { $crate::PyType::from_type_ptr(py, &mut $crate::ffi::$typeobject) }
|
||||
}
|
||||
}
|
||||
|
||||
pyobject_nativetype!($name, $checkfunction);
|
||||
};
|
||||
|
||||
|
|
|
@ -84,8 +84,7 @@ impl<T> PyObjectAlloc for T where T : PyTypeInfo {
|
|||
/// must be of type `ty`.
|
||||
unsafe fn alloc(py: Python, value: T::Type) -> PyResult<*mut ffi::PyObject> {
|
||||
// TODO: remove this
|
||||
let t = <T as PyTypeObject>::type_object(py);
|
||||
py.release(t);
|
||||
<T as PyTypeObject>::init_type(py);
|
||||
|
||||
let obj = ffi::PyType_GenericAlloc(
|
||||
<Self as PyTypeInfo>::type_object(), 0);
|
||||
|
@ -121,6 +120,9 @@ impl<T> PyObjectAlloc for T where T : PyTypeInfo {
|
|||
/// Trait implemented by Python object types that have a corresponding type object.
|
||||
pub trait PyTypeObject {
|
||||
|
||||
/// Initialize type object
|
||||
fn init_type(py: Python);
|
||||
|
||||
/// Retrieves the type object for this Python object type.
|
||||
fn type_object(py: Python) -> PyType;
|
||||
|
||||
|
@ -129,23 +131,27 @@ pub trait PyTypeObject {
|
|||
impl<T> PyTypeObject for T where T: PyObjectAlloc + PyTypeInfo {
|
||||
|
||||
#[inline]
|
||||
fn type_object(py: Python) -> PyType {
|
||||
default fn init_type(py: Python) {
|
||||
let mut ty = <T as PyTypeInfo>::type_object();
|
||||
//return unsafe { PyType::from_type_ptr(py, ty) };
|
||||
|
||||
if (ty.tp_flags & ffi::Py_TPFLAGS_READY) != 0 {
|
||||
unsafe { PyType::from_type_ptr(py, ty) }
|
||||
} else {
|
||||
if (ty.tp_flags & ffi::Py_TPFLAGS_READY) == 0 {
|
||||
// automatically initialize the class on-demand
|
||||
let to = initialize_type::<T>(
|
||||
py, None, <T as PyTypeInfo>::type_name(), ty).expect(
|
||||
format!("An error occurred while initializing class {}",
|
||||
<T as PyTypeInfo>::type_name()).as_ref());
|
||||
py.release(to);
|
||||
unsafe { PyType::from_type_ptr(py, ty) }
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn type_object(py: Python) -> PyType {
|
||||
<T as PyTypeObject>::init_type(py);
|
||||
|
||||
unsafe { PyType::from_type_ptr(py, <T as PyTypeInfo>::type_object()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn initialize_type<T>(py: Python, module_name: Option<&str>, type_name: &str,
|
||||
type_object: &mut ffi::PyTypeObject) -> PyResult<PyType>
|
||||
|
@ -294,27 +300,21 @@ fn py_class_method_defs<T>(py: Python, type_object: *mut ffi::PyTypeObject)
|
|||
|
||||
for def in <T as class::basic::PyObjectProtocolImpl>::methods() {
|
||||
defs.set_item(py, def.ml_name, def.as_method_descr(py, type_object)?)?;
|
||||
//defs.push(def.as_method_def())
|
||||
}
|
||||
for def in <T as class::async::PyAsyncProtocolImpl>::methods() {
|
||||
defs.set_item(py, def.ml_name, def.as_method_descr(py, type_object)?)?;
|
||||
//defs.push(def.as_method_def())
|
||||
}
|
||||
for def in <T as class::context::PyContextProtocolImpl>::methods() {
|
||||
defs.set_item(py, def.ml_name, def.as_method_descr(py, type_object)?)?;
|
||||
//defs.push(def.as_method_def())
|
||||
}
|
||||
for def in <T as class::mapping::PyMappingProtocolImpl>::methods() {
|
||||
defs.set_item(py, def.ml_name, def.as_method_descr(py, type_object)?)?;
|
||||
//defs.push(def.as_method_def())
|
||||
}
|
||||
for def in <T as class::number::PyNumberProtocolImpl>::methods() {
|
||||
defs.set_item(py, def.ml_name, def.as_method_descr(py, type_object)?)?;
|
||||
//defs.push(def.as_method_def())
|
||||
}
|
||||
for def in <T as class::descr::PyDescrProtocolImpl>::methods() {
|
||||
defs.set_item(py, def.ml_name, def.as_method_descr(py, type_object)?)?;
|
||||
//defs.push(def.as_method_def())
|
||||
}
|
||||
|
||||
Ok((new, call, defs))
|
||||
|
|
|
@ -16,7 +16,6 @@ macro_rules! py_run {
|
|||
($py:expr, $val:ident, $code:expr) => {{
|
||||
let d = PyDict::new($py);
|
||||
d.set_item($py, stringify!($val), &$val).unwrap();
|
||||
//$py.run($code, None, Some(&d)).map_err(|e| e.print($py)).expect($code);
|
||||
$py.run($code, None, Some(&d)).expect($code);
|
||||
}}
|
||||
}
|
||||
|
@ -1136,5 +1135,4 @@ fn class_with_properties() {
|
|||
py_run!(py, inst, "inst.DATA = 20");
|
||||
py_run!(py, inst, "assert inst.get_num() == 20");
|
||||
py_run!(py, inst, "assert inst.get_num() == inst.DATA");
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue