Skip to content

Commit 5100676

Browse files
committed
Splitted PyTypeCreate of PyTypeObject to remove specialization
1 parent 71c584a commit 5100676

File tree

10 files changed

+62
-78
lines changed

10 files changed

+62
-78
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
2929
* `IntoPyDictPointer` was replace by `IntoPyDict` which doesn't convert `PyDict` itself anymore and returns a `PyDict` instead of `*mut PyObject`.
3030
* `PyTuple::new` now takes an `IntoIterator` instead of a slice
3131
* Updated to syn 0.15
32+
* Splitted `PyTypeObject` into `PyTypeObject` without the create method and `PyTypeCreate` with requires `PyObjectAlloc<Self> + PyTypeInfo + Sized`.
3233

3334
### Fixed
3435

guide/src/class.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ To define python custom class, rust struct needs to be annotated with `#[pyclass
99
# extern crate pyo3;
1010
# use pyo3::prelude::*;
1111

12-
1312
#[pyclass]
1413
struct MyClass {
1514
num: i32,

pyo3-derive-backend/src/py_class.rs

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ fn impl_class(
127127
FREELIST = Box::into_raw(Box::new(
128128
::pyo3::freelist::FreeList::with_capacity(#freelist)));
129129

130-
<#cls as ::pyo3::typeob::PyTypeObject>::init_type();
130+
<#cls as ::pyo3::typeob::PyTypeCreate>::init_type();
131131
}
132132
&mut *FREELIST
133133
}
@@ -204,27 +204,6 @@ fn impl_class(
204204
}
205205
}
206206

207-
impl ::pyo3::typeob::PyTypeObject for #cls {
208-
#[inline]
209-
fn init_type() {
210-
static START: ::std::sync::Once = ::std::sync::ONCE_INIT;
211-
START.call_once(|| {
212-
let ty = unsafe{<#cls as ::pyo3::typeob::PyTypeInfo>::type_object()};
213-
214-
if (ty.tp_flags & ::pyo3::ffi::Py_TPFLAGS_READY) == 0 {
215-
let gil = ::pyo3::Python::acquire_gil();
216-
let py = gil.python();
217-
218-
// automatically initialize the class on-demand
219-
::pyo3::typeob::initialize_type::<#cls>(py, None)
220-
.map_err(|e| e.print(py))
221-
.expect(format!("An error occurred while initializing class {}",
222-
<#cls as ::pyo3::typeob::PyTypeInfo>::NAME).as_ref());
223-
}
224-
});
225-
}
226-
}
227-
228207
// TBH I'm not sure what exactely this does and I'm sure there's a better way,
229208
// but for now it works and it only safe code and it is required to return custom
230209
// objects, so for now I'm keeping it

src/ffi2/object.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ pub type allocfunc =
363363
unsafe extern "C" fn(arg1: *mut PyTypeObject, arg2: Py_ssize_t) -> *mut PyObject;
364364

365365
#[repr(C)]
366-
#[derive(Copy)]
366+
#[derive(Copy, Clone)]
367367
pub struct PyTypeObject {
368368
pub ob_refcnt: Py_ssize_t,
369369
pub ob_type: *mut PyTypeObject,
@@ -416,13 +416,6 @@ pub struct PyTypeObject {
416416
pub tp_version_tag: c_uint,
417417
}
418418

419-
impl Clone for PyTypeObject {
420-
#[inline]
421-
fn clone(&self) -> PyTypeObject {
422-
*self
423-
}
424-
}
425-
426419
#[cfg(py_sys_config = "Py_TRACE_REFS")]
427420
pub const PyTypeObject_INIT: PyTypeObject = PyTypeObject {
428421
_ob_next: ::std::ptr::null_mut(),

src/instance.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use python::{IntoPyPointer, Python, ToPyPointer};
1414
use pythonrun;
1515
use typeob::{PyTypeInfo, PyTypeObject};
1616
use types::PyObjectRef;
17+
use typeob::PyTypeCreate;
1718

1819
pub struct PyToken(PhantomData<Rc<()>>);
1920

@@ -175,7 +176,7 @@ where
175176
F: FnOnce(::PyToken) -> T,
176177
T: PyTypeObject + PyTypeInfo,
177178
{
178-
let ob = <T as PyTypeObject>::create(py)?;
179+
let ob = <T as PyTypeCreate>::create(py)?;
179180
ob.init(f)?;
180181

181182
let ob = unsafe { Py::from_owned_ptr(ob.into_ptr()) };
@@ -189,7 +190,7 @@ where
189190
F: FnOnce(::PyToken) -> T,
190191
T: PyTypeObject + PyTypeInfo,
191192
{
192-
let ob = <T as PyTypeObject>::create(py)?;
193+
let ob = <T as PyTypeCreate>::create(py)?;
193194
ob.init(f)?;
194195

195196
unsafe { Ok(py.from_owned_ptr(ob.into_ptr())) }
@@ -202,7 +203,7 @@ where
202203
F: FnOnce(::PyToken) -> T,
203204
T: PyTypeObject + PyTypeInfo,
204205
{
205-
let ob = <T as PyTypeObject>::create(py)?;
206+
let ob = <T as PyTypeCreate>::create(py)?;
206207
ob.init(f)?;
207208

208209
unsafe { Ok(py.mut_from_owned_ptr(ob.into_ptr())) }

src/python.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ use std;
1212
use std::ffi::CString;
1313
use std::marker::PhantomData;
1414
use std::os::raw::c_int;
15-
use typeob::{PyObjectAlloc, PyTypeInfo, PyTypeObject};
15+
use typeob::PyTypeCreate;
16+
use typeob::{PyTypeInfo, PyTypeObject};
1617
use types::{PyDict, PyModule, PyObjectRef, PyType};
1718

1819
/// Marker type that indicates that the GIL is currently held.
@@ -253,7 +254,7 @@ impl<'p> Python<'p> {
253254
pub fn init<T, F>(self, f: F) -> PyResult<Py<T>>
254255
where
255256
F: FnOnce(PyToken) -> T,
256-
T: PyTypeInfo + PyObjectAlloc<T>,
257+
T: PyTypeCreate,
257258
{
258259
Py::new(self, f)
259260
}
@@ -264,7 +265,7 @@ impl<'p> Python<'p> {
264265
pub fn init_ref<T, F>(self, f: F) -> PyResult<&'p T>
265266
where
266267
F: FnOnce(PyToken) -> T,
267-
T: PyTypeInfo + PyObjectAlloc<T>,
268+
T: PyTypeCreate,
268269
{
269270
Py::new_ref(self, f)
270271
}
@@ -275,7 +276,7 @@ impl<'p> Python<'p> {
275276
pub fn init_mut<T, F>(self, f: F) -> PyResult<&'p mut T>
276277
where
277278
F: FnOnce(PyToken) -> T,
278-
T: PyTypeInfo + PyObjectAlloc<T>,
279+
T: PyTypeCreate,
279280
{
280281
Py::new_mut(self, f)
281282
}

src/typeob.rs

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ where
217217

218218
default unsafe fn alloc(_py: Python) -> PyResult<*mut ffi::PyObject> {
219219
// TODO: remove this
220-
T::init_type();
220+
<T as PyTypeCreate>::init_type();
221221

222222
let tp_ptr = T::type_object();
223223
let alloc = (*tp_ptr).tp_alloc.unwrap_or(ffi::PyType_GenericAlloc);
@@ -256,20 +256,42 @@ where
256256
}
257257
}
258258

259-
/// Trait implemented by Python object types that have a corresponding type object.
259+
/// Python object types that have a corresponding type object.
260260
pub trait PyTypeObject {
261261
/// Initialize type object
262262
fn init_type();
263263

264264
/// Retrieves the type object for this Python object type.
265265
fn type_object() -> Py<PyType>;
266+
}
267+
268+
/// Python object types that have a corresponding type object and be
269+
/// instanciated with [Self::create()]
270+
pub trait PyTypeCreate: PyObjectAlloc<Self> + PyTypeInfo + Sized {
271+
#[inline]
272+
fn init_type() {
273+
let type_object = unsafe { *<Self as PyTypeInfo>::type_object() };
274+
275+
if (type_object.tp_flags & ffi::Py_TPFLAGS_READY) == 0 {
276+
// automatically initialize the class on-demand
277+
let gil = Python::acquire_gil();
278+
let py = gil.python();
279+
280+
initialize_type::<Self>(py, None).unwrap_or_else(|_| {
281+
panic!("An error occurred while initializing class {}", Self::NAME)
282+
});
283+
}
284+
}
285+
286+
#[inline]
287+
fn type_object() -> Py<PyType> {
288+
<Self as PyTypeObject>::init_type();
289+
PyType::new::<Self>()
290+
}
266291

267292
/// Create PyRawObject which can be initialized with rust value
268293
#[must_use]
269-
fn create(py: Python) -> PyResult<PyRawObject>
270-
where
271-
Self: Sized + PyObjectAlloc<Self> + PyTypeInfo,
272-
{
294+
fn create(py: Python) -> PyResult<PyRawObject> {
273295
<Self as PyTypeObject>::init_type();
274296

275297
unsafe {
@@ -284,29 +306,18 @@ pub trait PyTypeObject {
284306
}
285307
}
286308

309+
impl<T> PyTypeCreate for T where T: PyObjectAlloc<Self> + PyTypeInfo + Sized {}
310+
287311
impl<T> PyTypeObject for T
288312
where
289-
T: PyObjectAlloc<T> + PyTypeInfo,
313+
T: PyTypeCreate,
290314
{
291-
#[inline]
292-
default fn init_type() {
293-
unsafe {
294-
if ((*<T>::type_object()).tp_flags & ffi::Py_TPFLAGS_READY) == 0 {
295-
// automatically initialize the class on-demand
296-
let gil = Python::acquire_gil();
297-
let py = gil.python();
298-
299-
initialize_type::<T>(py, None).unwrap_or_else(|_| {
300-
panic!("An error occurred while initializing class {}", T::NAME)
301-
});
302-
}
303-
}
315+
fn init_type() {
316+
<T as PyTypeCreate>::init_type()
304317
}
305318

306-
#[inline]
307-
default fn type_object() -> Py<PyType> {
308-
<T as PyTypeObject>::init_type();
309-
PyType::new::<T>()
319+
fn type_object() -> Py<PyType> {
320+
<T as PyTypeCreate>::type_object()
310321
}
311322
}
312323

src/types/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ macro_rules! pyobject_native_type_convert(
125125
}
126126
}
127127

128-
impl<$($type_param,)*> $crate::typeob::PyTypeObject for $name {
128+
impl<$($type_param,)*> $crate::typeob::PyTypeCreate for $name {
129129
#[inline]
130130
fn init_type() {}
131131

src/types/string.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use ffi;
1010
use instance::{Py, PyObjectWithToken};
1111
use object::PyObject;
1212
use python::{Python, ToPyPointer};
13-
use types::PyObjectRef;
1413
use types::exceptions;
14+
use types::PyObjectRef;
1515

1616
/// Represents a Python `string`.
1717
#[repr(transparent)]
@@ -72,7 +72,7 @@ impl PyString {
7272
Ok(s) => Ok(Cow::Borrowed(s)),
7373
Err(e) => Err(PyErr::from_instance(
7474
exceptions::UnicodeDecodeError::new_utf8(self.py(), self.as_bytes(), e)?,
75-
))
75+
)),
7676
}
7777
}
7878

@@ -120,12 +120,12 @@ impl PyBytes {
120120

121121
#[cfg(test)]
122122
mod test {
123-
use std::borrow::Cow;
124-
use conversion::{FromPyObject, ToPyObject, PyTryFrom};
123+
use super::PyString;
124+
use conversion::{FromPyObject, PyTryFrom, ToPyObject};
125125
use instance::AsPyRef;
126-
use python::Python;
127126
use object::PyObject;
128-
use super::PyString;
127+
use python::Python;
128+
use std::borrow::Cow;
129129

130130
#[test]
131131
fn test_non_bmp() {

src/types/string2.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ impl PyString {
8888
Ok(s) => Ok(Cow::Borrowed(s)),
8989
Err(e) => Err(PyErr::from_instance(
9090
exceptions::UnicodeDecodeError::new_utf8(self.py(), self.as_bytes(), e)?,
91-
))
91+
)),
9292
}
9393
}
9494

@@ -156,9 +156,8 @@ impl PyUnicode {
156156
unsafe {
157157
// PyUnicode_AsUTF8String would return null if the pointer did not reference a valid
158158
// unicode object, but because we have a valid PyUnicode, assume success
159-
let data: Py<PyBytes> = Py::from_owned_ptr(
160-
ffi::PyUnicode_AsUTF8String(self.0.as_ptr()),
161-
);
159+
let data: Py<PyBytes> =
160+
Py::from_owned_ptr(ffi::PyUnicode_AsUTF8String(self.0.as_ptr()));
162161
let buffer = ffi::PyBytes_AsString(data.as_ptr()) as *const u8;
163162
let length = ffi::PyBytes_Size(data.as_ptr()) as usize;
164163
debug_assert!(!buffer.is_null());
@@ -175,7 +174,7 @@ impl PyUnicode {
175174
Ok(s) => Ok(Cow::Borrowed(s)),
176175
Err(e) => Err(PyErr::from_instance(
177176
exceptions::UnicodeDecodeError::new_utf8(self.py(), self.as_bytes(), e)?,
178-
))
177+
)),
179178
}
180179
}
181180

@@ -205,12 +204,12 @@ impl std::convert::From<Py<PyUnicode>> for Py<PyString> {
205204

206205
#[cfg(test)]
207206
mod test {
208-
use std::borrow::Cow;
209-
use conversion::{FromPyObject, ToPyObject, PyTryFrom};
207+
use super::PyString;
208+
use conversion::{FromPyObject, PyTryFrom, ToPyObject};
210209
use instance::AsPyRef;
211-
use python::Python;
212210
use object::PyObject;
213-
use super::PyString;
211+
use python::Python;
212+
use std::borrow::Cow;
214213

215214
#[test]
216215
fn test_non_bmp() {

0 commit comments

Comments
 (0)