pyo3/impl_/
pyclass_init.rs1use crate::ffi_ptr_ext::FfiPtrExt;
3use crate::internal::get_slot::TP_ALLOC;
4use crate::types::PyType;
5use crate::{ffi, Borrowed, PyErr, PyResult, Python};
6use crate::{ffi::PyTypeObject, sealed::Sealed, type_object::PyTypeInfo};
7use std::marker::PhantomData;
8
9pub trait PyObjectInit<T>: Sized + Sealed {
14 unsafe fn into_new_object(
17 self,
18 py: Python<'_>,
19 subtype: *mut PyTypeObject,
20 ) -> PyResult<*mut ffi::PyObject>;
21
22 #[doc(hidden)]
23 fn can_be_subclassed(&self) -> bool;
24}
25
26pub struct PyNativeTypeInitializer<T: PyTypeInfo>(pub PhantomData<T>);
28
29impl<T: PyTypeInfo> PyObjectInit<T> for PyNativeTypeInitializer<T> {
30 unsafe fn into_new_object(
31 self,
32 py: Python<'_>,
33 subtype: *mut PyTypeObject,
34 ) -> PyResult<*mut ffi::PyObject> {
35 unsafe fn inner(
36 py: Python<'_>,
37 type_object: *mut PyTypeObject,
38 subtype: *mut PyTypeObject,
39 ) -> PyResult<*mut ffi::PyObject> {
40 let is_base_object = type_object == std::ptr::addr_of_mut!(ffi::PyBaseObject_Type);
42 let subtype_borrowed: Borrowed<'_, '_, PyType> = subtype
43 .cast::<ffi::PyObject>()
44 .assume_borrowed_unchecked(py)
45 .downcast_unchecked();
46
47 if is_base_object {
48 let alloc = subtype_borrowed
49 .get_slot(TP_ALLOC)
50 .unwrap_or(ffi::PyType_GenericAlloc);
51
52 let obj = alloc(subtype, 0);
53 return if obj.is_null() {
54 Err(PyErr::fetch(py))
55 } else {
56 Ok(obj)
57 };
58 }
59
60 #[cfg(Py_LIMITED_API)]
61 unreachable!("subclassing native types is not possible with the `abi3` feature");
62
63 #[cfg(not(Py_LIMITED_API))]
64 {
65 match (*type_object).tp_new {
66 Some(newfunc) => {
68 let obj = newfunc(subtype, std::ptr::null_mut(), std::ptr::null_mut());
69 if obj.is_null() {
70 Err(PyErr::fetch(py))
71 } else {
72 Ok(obj)
73 }
74 }
75 None => Err(crate::exceptions::PyTypeError::new_err(
76 "base type without tp_new",
77 )),
78 }
79 }
80 }
81 let type_object = T::type_object_raw(py);
82 inner(py, type_object, subtype)
83 }
84
85 #[inline]
86 fn can_be_subclassed(&self) -> bool {
87 true
88 }
89}