|
1 | 1 | //! Contains initialization utilities for `#[pyclass]`. |
| 2 | +use crate::exceptions::PyTypeError; |
2 | 3 | use crate::ffi_ptr_ext::FfiPtrExt; |
3 | | -use crate::internal::get_slot::TP_ALLOC; |
4 | | -use crate::types::PyType; |
5 | | -use crate::{ffi, Borrowed, PyErr, PyResult, Python}; |
| 4 | +use crate::internal::get_slot::TP_NEW; |
| 5 | +use crate::types::{PyTuple, PyType}; |
| 6 | +use crate::{ffi, PyErr, PyResult, Python}; |
6 | 7 | use crate::{ffi::PyTypeObject, sealed::Sealed, type_object::PyTypeInfo}; |
7 | 8 | use std::marker::PhantomData; |
8 | | -use std::ptr; |
9 | 9 |
|
10 | 10 | /// Initializer for Python types. |
11 | 11 | /// |
@@ -35,55 +35,26 @@ impl<T: PyTypeInfo> PyObjectInit<T> for PyNativeTypeInitializer<T> { |
35 | 35 | ) -> PyResult<*mut ffi::PyObject> { |
36 | 36 | unsafe fn inner( |
37 | 37 | py: Python<'_>, |
38 | | - type_object: *mut PyTypeObject, |
| 38 | + type_ptr: *mut PyTypeObject, |
39 | 39 | subtype: *mut PyTypeObject, |
40 | 40 | ) -> PyResult<*mut ffi::PyObject> { |
41 | | - // HACK (due to FIXME below): PyBaseObject_Type's tp_new isn't happy with NULL arguments |
42 | | - let is_base_object = ptr::eq(type_object, ptr::addr_of!(ffi::PyBaseObject_Type)); |
43 | | - let subtype_borrowed: Borrowed<'_, '_, PyType> = unsafe { |
44 | | - subtype |
| 41 | + let tp_new = unsafe { |
| 42 | + type_ptr |
45 | 43 | .cast::<ffi::PyObject>() |
46 | 44 | .assume_borrowed_unchecked(py) |
47 | | - .cast_unchecked() |
| 45 | + .cast_unchecked::<PyType>() |
| 46 | + .get_slot(TP_NEW) |
| 47 | + .ok_or_else(|| PyTypeError::new_err("base type without tp_new"))? |
48 | 48 | }; |
49 | 49 |
|
50 | | - if is_base_object { |
51 | | - let alloc = subtype_borrowed |
52 | | - .get_slot(TP_ALLOC) |
53 | | - .unwrap_or(ffi::PyType_GenericAlloc); |
54 | | - |
55 | | - let obj = unsafe { alloc(subtype, 0) }; |
56 | | - return if obj.is_null() { |
57 | | - Err(PyErr::fetch(py)) |
58 | | - } else { |
59 | | - Ok(obj) |
60 | | - }; |
61 | | - } |
62 | | - |
63 | | - #[cfg(Py_LIMITED_API)] |
64 | | - unreachable!("subclassing native types is not possible with the `abi3` feature"); |
65 | | - |
66 | | - #[cfg(not(Py_LIMITED_API))] |
67 | | - { |
68 | | - match unsafe { (*type_object).tp_new } { |
69 | | - // FIXME: Call __new__ with actual arguments |
70 | | - Some(newfunc) => { |
71 | | - let obj = |
72 | | - unsafe { newfunc(subtype, std::ptr::null_mut(), std::ptr::null_mut()) }; |
73 | | - if obj.is_null() { |
74 | | - Err(PyErr::fetch(py)) |
75 | | - } else { |
76 | | - Ok(obj) |
77 | | - } |
78 | | - } |
79 | | - None => Err(crate::exceptions::PyTypeError::new_err( |
80 | | - "base type without tp_new", |
81 | | - )), |
82 | | - } |
| 50 | + let obj = unsafe { tp_new(subtype, PyTuple::empty(py).as_ptr(), std::ptr::null_mut()) }; |
| 51 | + if obj.is_null() { |
| 52 | + Err(PyErr::fetch(py)) |
| 53 | + } else { |
| 54 | + Ok(obj) |
83 | 55 | } |
84 | 56 | } |
85 | | - let type_object = T::type_object_raw(py); |
86 | | - unsafe { inner(py, type_object, subtype) } |
| 57 | + unsafe { inner(py, T::type_object_raw(py), subtype) } |
87 | 58 | } |
88 | 59 |
|
89 | 60 | #[inline] |
|
0 commit comments