1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use crate::types::{PyAny, PyType};
use crate::{ffi, AsPyPointer, PyNativeType, Python};
pub unsafe trait PyLayout<T> {}
pub trait PySizedLayout<T>: PyLayout<T> + Sized {}
pub unsafe trait PyTypeInfo: Sized {
const NAME: &'static str;
const MODULE: Option<&'static str>;
type AsRefTarget: PyNativeType;
fn type_object_raw(py: Python<'_>) -> *mut ffi::PyTypeObject;
fn type_object(py: Python<'_>) -> &PyType {
unsafe { py.from_borrowed_ptr(Self::type_object_raw(py) as _) }
}
fn is_type_of(object: &PyAny) -> bool {
unsafe { ffi::PyObject_TypeCheck(object.as_ptr(), Self::type_object_raw(object.py())) != 0 }
}
fn is_exact_type_of(object: &PyAny) -> bool {
unsafe { ffi::Py_TYPE(object.as_ptr()) == Self::type_object_raw(object.py()) }
}
}
#[deprecated(
since = "0.17.0",
note = "PyTypeObject::type_object was moved to PyTypeInfo::type_object"
)]
pub unsafe trait PyTypeObject: PyTypeInfo {}
#[allow(deprecated)]
unsafe impl<T: PyTypeInfo> PyTypeObject for T {}
#[inline]
pub(crate) unsafe fn get_tp_alloc(tp: *mut ffi::PyTypeObject) -> Option<ffi::allocfunc> {
#[cfg(not(Py_LIMITED_API))]
{
(*tp).tp_alloc
}
#[cfg(Py_LIMITED_API)]
{
let ptr = ffi::PyType_GetSlot(tp, ffi::Py_tp_alloc);
std::mem::transmute(ptr)
}
}
#[inline]
pub(crate) unsafe fn get_tp_free(tp: *mut ffi::PyTypeObject) -> ffi::freefunc {
#[cfg(not(Py_LIMITED_API))]
{
(*tp).tp_free.unwrap()
}
#[cfg(Py_LIMITED_API)]
{
let ptr = ffi::PyType_GetSlot(tp, ffi::Py_tp_free);
debug_assert_ne!(ptr, std::ptr::null_mut());
std::mem::transmute(ptr)
}
}
#[cfg(test)]
mod tests {
#[test]
#[allow(deprecated)]
fn test_deprecated_type_object() {
use super::PyTypeObject;
use crate::types::{PyList, PyType};
use crate::Python;
fn get_type_object<T: PyTypeObject>(py: Python<'_>) -> &PyType {
T::type_object(py)
}
Python::with_gil(|py| {
assert!(get_type_object::<PyList>(py).is(<PyList as crate::PyTypeInfo>::type_object(py)))
});
}
}