Splitted PyTypeCreate of PyTypeObject to remove specialization
This commit is contained in:
parent
71c584a110
commit
5100676497
|
@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
* `IntoPyDictPointer` was replace by `IntoPyDict` which doesn't convert `PyDict` itself anymore and returns a `PyDict` instead of `*mut PyObject`.
|
||||
* `PyTuple::new` now takes an `IntoIterator` instead of a slice
|
||||
* Updated to syn 0.15
|
||||
* Splitted `PyTypeObject` into `PyTypeObject` without the create method and `PyTypeCreate` with requires `PyObjectAlloc<Self> + PyTypeInfo + Sized`.
|
||||
|
||||
### Fixed
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ To define python custom class, rust struct needs to be annotated with `#[pyclass
|
|||
# extern crate pyo3;
|
||||
# use pyo3::prelude::*;
|
||||
|
||||
|
||||
#[pyclass]
|
||||
struct MyClass {
|
||||
num: i32,
|
||||
|
|
|
@ -127,7 +127,7 @@ fn impl_class(
|
|||
FREELIST = Box::into_raw(Box::new(
|
||||
::pyo3::freelist::FreeList::with_capacity(#freelist)));
|
||||
|
||||
<#cls as ::pyo3::typeob::PyTypeObject>::init_type();
|
||||
<#cls as ::pyo3::typeob::PyTypeCreate>::init_type();
|
||||
}
|
||||
&mut *FREELIST
|
||||
}
|
||||
|
@ -204,27 +204,6 @@ fn impl_class(
|
|||
}
|
||||
}
|
||||
|
||||
impl ::pyo3::typeob::PyTypeObject for #cls {
|
||||
#[inline]
|
||||
fn init_type() {
|
||||
static START: ::std::sync::Once = ::std::sync::ONCE_INIT;
|
||||
START.call_once(|| {
|
||||
let ty = unsafe{<#cls as ::pyo3::typeob::PyTypeInfo>::type_object()};
|
||||
|
||||
if (ty.tp_flags & ::pyo3::ffi::Py_TPFLAGS_READY) == 0 {
|
||||
let gil = ::pyo3::Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
// automatically initialize the class on-demand
|
||||
::pyo3::typeob::initialize_type::<#cls>(py, None)
|
||||
.map_err(|e| e.print(py))
|
||||
.expect(format!("An error occurred while initializing class {}",
|
||||
<#cls as ::pyo3::typeob::PyTypeInfo>::NAME).as_ref());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// TBH I'm not sure what exactely this does and I'm sure there's a better way,
|
||||
// but for now it works and it only safe code and it is required to return custom
|
||||
// objects, so for now I'm keeping it
|
||||
|
|
|
@ -363,7 +363,7 @@ pub type allocfunc =
|
|||
unsafe extern "C" fn(arg1: *mut PyTypeObject, arg2: Py_ssize_t) -> *mut PyObject;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct PyTypeObject {
|
||||
pub ob_refcnt: Py_ssize_t,
|
||||
pub ob_type: *mut PyTypeObject,
|
||||
|
@ -416,13 +416,6 @@ pub struct PyTypeObject {
|
|||
pub tp_version_tag: c_uint,
|
||||
}
|
||||
|
||||
impl Clone for PyTypeObject {
|
||||
#[inline]
|
||||
fn clone(&self) -> PyTypeObject {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(py_sys_config = "Py_TRACE_REFS")]
|
||||
pub const PyTypeObject_INIT: PyTypeObject = PyTypeObject {
|
||||
_ob_next: ::std::ptr::null_mut(),
|
||||
|
|
|
@ -14,6 +14,7 @@ use python::{IntoPyPointer, Python, ToPyPointer};
|
|||
use pythonrun;
|
||||
use typeob::{PyTypeInfo, PyTypeObject};
|
||||
use types::PyObjectRef;
|
||||
use typeob::PyTypeCreate;
|
||||
|
||||
pub struct PyToken(PhantomData<Rc<()>>);
|
||||
|
||||
|
@ -175,7 +176,7 @@ where
|
|||
F: FnOnce(::PyToken) -> T,
|
||||
T: PyTypeObject + PyTypeInfo,
|
||||
{
|
||||
let ob = <T as PyTypeObject>::create(py)?;
|
||||
let ob = <T as PyTypeCreate>::create(py)?;
|
||||
ob.init(f)?;
|
||||
|
||||
let ob = unsafe { Py::from_owned_ptr(ob.into_ptr()) };
|
||||
|
@ -189,7 +190,7 @@ where
|
|||
F: FnOnce(::PyToken) -> T,
|
||||
T: PyTypeObject + PyTypeInfo,
|
||||
{
|
||||
let ob = <T as PyTypeObject>::create(py)?;
|
||||
let ob = <T as PyTypeCreate>::create(py)?;
|
||||
ob.init(f)?;
|
||||
|
||||
unsafe { Ok(py.from_owned_ptr(ob.into_ptr())) }
|
||||
|
@ -202,7 +203,7 @@ where
|
|||
F: FnOnce(::PyToken) -> T,
|
||||
T: PyTypeObject + PyTypeInfo,
|
||||
{
|
||||
let ob = <T as PyTypeObject>::create(py)?;
|
||||
let ob = <T as PyTypeCreate>::create(py)?;
|
||||
ob.init(f)?;
|
||||
|
||||
unsafe { Ok(py.mut_from_owned_ptr(ob.into_ptr())) }
|
||||
|
|
|
@ -12,7 +12,8 @@ use std;
|
|||
use std::ffi::CString;
|
||||
use std::marker::PhantomData;
|
||||
use std::os::raw::c_int;
|
||||
use typeob::{PyObjectAlloc, PyTypeInfo, PyTypeObject};
|
||||
use typeob::PyTypeCreate;
|
||||
use typeob::{PyTypeInfo, PyTypeObject};
|
||||
use types::{PyDict, PyModule, PyObjectRef, PyType};
|
||||
|
||||
/// Marker type that indicates that the GIL is currently held.
|
||||
|
@ -253,7 +254,7 @@ impl<'p> Python<'p> {
|
|||
pub fn init<T, F>(self, f: F) -> PyResult<Py<T>>
|
||||
where
|
||||
F: FnOnce(PyToken) -> T,
|
||||
T: PyTypeInfo + PyObjectAlloc<T>,
|
||||
T: PyTypeCreate,
|
||||
{
|
||||
Py::new(self, f)
|
||||
}
|
||||
|
@ -264,7 +265,7 @@ impl<'p> Python<'p> {
|
|||
pub fn init_ref<T, F>(self, f: F) -> PyResult<&'p T>
|
||||
where
|
||||
F: FnOnce(PyToken) -> T,
|
||||
T: PyTypeInfo + PyObjectAlloc<T>,
|
||||
T: PyTypeCreate,
|
||||
{
|
||||
Py::new_ref(self, f)
|
||||
}
|
||||
|
@ -275,7 +276,7 @@ impl<'p> Python<'p> {
|
|||
pub fn init_mut<T, F>(self, f: F) -> PyResult<&'p mut T>
|
||||
where
|
||||
F: FnOnce(PyToken) -> T,
|
||||
T: PyTypeInfo + PyObjectAlloc<T>,
|
||||
T: PyTypeCreate,
|
||||
{
|
||||
Py::new_mut(self, f)
|
||||
}
|
||||
|
|
|
@ -217,7 +217,7 @@ where
|
|||
|
||||
default unsafe fn alloc(_py: Python) -> PyResult<*mut ffi::PyObject> {
|
||||
// TODO: remove this
|
||||
T::init_type();
|
||||
<T as PyTypeCreate>::init_type();
|
||||
|
||||
let tp_ptr = T::type_object();
|
||||
let alloc = (*tp_ptr).tp_alloc.unwrap_or(ffi::PyType_GenericAlloc);
|
||||
|
@ -256,20 +256,42 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Trait implemented by Python object types that have a corresponding type object.
|
||||
/// Python object types that have a corresponding type object.
|
||||
pub trait PyTypeObject {
|
||||
/// Initialize type object
|
||||
fn init_type();
|
||||
|
||||
/// Retrieves the type object for this Python object type.
|
||||
fn type_object() -> Py<PyType>;
|
||||
}
|
||||
|
||||
/// Python object types that have a corresponding type object and be
|
||||
/// instanciated with [Self::create()]
|
||||
pub trait PyTypeCreate: PyObjectAlloc<Self> + PyTypeInfo + Sized {
|
||||
#[inline]
|
||||
fn init_type() {
|
||||
let type_object = unsafe { *<Self as PyTypeInfo>::type_object() };
|
||||
|
||||
if (type_object.tp_flags & ffi::Py_TPFLAGS_READY) == 0 {
|
||||
// automatically initialize the class on-demand
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
initialize_type::<Self>(py, None).unwrap_or_else(|_| {
|
||||
panic!("An error occurred while initializing class {}", Self::NAME)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn type_object() -> Py<PyType> {
|
||||
<Self as PyTypeObject>::init_type();
|
||||
PyType::new::<Self>()
|
||||
}
|
||||
|
||||
/// Create PyRawObject which can be initialized with rust value
|
||||
#[must_use]
|
||||
fn create(py: Python) -> PyResult<PyRawObject>
|
||||
where
|
||||
Self: Sized + PyObjectAlloc<Self> + PyTypeInfo,
|
||||
{
|
||||
fn create(py: Python) -> PyResult<PyRawObject> {
|
||||
<Self as PyTypeObject>::init_type();
|
||||
|
||||
unsafe {
|
||||
|
@ -284,29 +306,18 @@ pub trait PyTypeObject {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> PyTypeCreate for T where T: PyObjectAlloc<Self> + PyTypeInfo + Sized {}
|
||||
|
||||
impl<T> PyTypeObject for T
|
||||
where
|
||||
T: PyObjectAlloc<T> + PyTypeInfo,
|
||||
T: PyTypeCreate,
|
||||
{
|
||||
#[inline]
|
||||
default fn init_type() {
|
||||
unsafe {
|
||||
if ((*<T>::type_object()).tp_flags & ffi::Py_TPFLAGS_READY) == 0 {
|
||||
// automatically initialize the class on-demand
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
initialize_type::<T>(py, None).unwrap_or_else(|_| {
|
||||
panic!("An error occurred while initializing class {}", T::NAME)
|
||||
});
|
||||
}
|
||||
}
|
||||
fn init_type() {
|
||||
<T as PyTypeCreate>::init_type()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn type_object() -> Py<PyType> {
|
||||
<T as PyTypeObject>::init_type();
|
||||
PyType::new::<T>()
|
||||
fn type_object() -> Py<PyType> {
|
||||
<T as PyTypeCreate>::type_object()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ macro_rules! pyobject_native_type_convert(
|
|||
}
|
||||
}
|
||||
|
||||
impl<$($type_param,)*> $crate::typeob::PyTypeObject for $name {
|
||||
impl<$($type_param,)*> $crate::typeob::PyTypeCreate for $name {
|
||||
#[inline]
|
||||
fn init_type() {}
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ use ffi;
|
|||
use instance::{Py, PyObjectWithToken};
|
||||
use object::PyObject;
|
||||
use python::{Python, ToPyPointer};
|
||||
use types::PyObjectRef;
|
||||
use types::exceptions;
|
||||
use types::PyObjectRef;
|
||||
|
||||
/// Represents a Python `string`.
|
||||
#[repr(transparent)]
|
||||
|
@ -72,7 +72,7 @@ impl PyString {
|
|||
Ok(s) => Ok(Cow::Borrowed(s)),
|
||||
Err(e) => Err(PyErr::from_instance(
|
||||
exceptions::UnicodeDecodeError::new_utf8(self.py(), self.as_bytes(), e)?,
|
||||
))
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,12 +120,12 @@ impl PyBytes {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::borrow::Cow;
|
||||
use conversion::{FromPyObject, ToPyObject, PyTryFrom};
|
||||
use instance::AsPyRef;
|
||||
use python::Python;
|
||||
use object::PyObject;
|
||||
use super::PyString;
|
||||
use conversion::{FromPyObject, PyTryFrom, ToPyObject};
|
||||
use instance::AsPyRef;
|
||||
use object::PyObject;
|
||||
use python::Python;
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[test]
|
||||
fn test_non_bmp() {
|
||||
|
|
|
@ -88,7 +88,7 @@ impl PyString {
|
|||
Ok(s) => Ok(Cow::Borrowed(s)),
|
||||
Err(e) => Err(PyErr::from_instance(
|
||||
exceptions::UnicodeDecodeError::new_utf8(self.py(), self.as_bytes(), e)?,
|
||||
))
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,9 +156,8 @@ impl PyUnicode {
|
|||
unsafe {
|
||||
// PyUnicode_AsUTF8String would return null if the pointer did not reference a valid
|
||||
// unicode object, but because we have a valid PyUnicode, assume success
|
||||
let data: Py<PyBytes> = Py::from_owned_ptr(
|
||||
ffi::PyUnicode_AsUTF8String(self.0.as_ptr()),
|
||||
);
|
||||
let data: Py<PyBytes> =
|
||||
Py::from_owned_ptr(ffi::PyUnicode_AsUTF8String(self.0.as_ptr()));
|
||||
let buffer = ffi::PyBytes_AsString(data.as_ptr()) as *const u8;
|
||||
let length = ffi::PyBytes_Size(data.as_ptr()) as usize;
|
||||
debug_assert!(!buffer.is_null());
|
||||
|
@ -175,7 +174,7 @@ impl PyUnicode {
|
|||
Ok(s) => Ok(Cow::Borrowed(s)),
|
||||
Err(e) => Err(PyErr::from_instance(
|
||||
exceptions::UnicodeDecodeError::new_utf8(self.py(), self.as_bytes(), e)?,
|
||||
))
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,12 +204,12 @@ impl std::convert::From<Py<PyUnicode>> for Py<PyString> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::borrow::Cow;
|
||||
use conversion::{FromPyObject, ToPyObject, PyTryFrom};
|
||||
use instance::AsPyRef;
|
||||
use python::Python;
|
||||
use object::PyObject;
|
||||
use super::PyString;
|
||||
use conversion::{FromPyObject, PyTryFrom, ToPyObject};
|
||||
use instance::AsPyRef;
|
||||
use object::PyObject;
|
||||
use python::Python;
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[test]
|
||||
fn test_non_bmp() {
|
||||
|
|
Loading…
Reference in New Issue