Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
type_object.rs - source
[go: Go Back, main page]

pyo3/
type_object.rs

1//! Python type object information
2
3use crate::ffi_ptr_ext::FfiPtrExt;
4use crate::types::any::PyAnyMethods;
5use crate::types::{PyAny, PyType};
6use crate::{ffi, Bound, Python};
7use std::ptr;
8
9/// `T: PyLayout<U>` represents that `T` is a concrete representation of `U` in the Python heap.
10/// E.g., `PyClassObject` is a concrete representation of all `pyclass`es, and `ffi::PyObject`
11/// is of `PyAny`.
12///
13/// This trait is intended to be used internally.
14///
15/// # Safety
16///
17/// This trait must only be implemented for types which represent valid layouts of Python objects.
18pub unsafe trait PyLayout<T> {}
19
20/// `T: PySizedLayout<U>` represents that `T` is not a instance of
21/// [`PyVarObject`](https://docs.python.org/3/c-api/structures.html#c.PyVarObject).
22///
23/// In addition, that `T` is a concrete representation of `U`.
24pub trait PySizedLayout<T>: PyLayout<T> + Sized {}
25
26/// Python type information.
27/// All Python native types (e.g., `PyDict`) and `#[pyclass]` structs implement this trait.
28///
29/// This trait is marked unsafe because:
30///  - specifying the incorrect layout can lead to memory errors
31///  - the return value of type_object must always point to the same PyTypeObject instance
32///
33/// It is safely implemented by the `pyclass` macro.
34///
35/// # Safety
36///
37/// Implementations must provide an implementation for `type_object_raw` which infallibly produces a
38/// non-null pointer to the corresponding Python type object.
39pub unsafe trait PyTypeInfo: Sized {
40    /// Class name.
41    const NAME: &'static str;
42
43    /// Module name, if any.
44    const MODULE: Option<&'static str>;
45
46    /// Returns the PyTypeObject instance for this type.
47    fn type_object_raw(py: Python<'_>) -> *mut ffi::PyTypeObject;
48
49    /// Returns the safe abstraction over the type object.
50    #[inline]
51    fn type_object(py: Python<'_>) -> Bound<'_, PyType> {
52        // Making the borrowed object `Bound` is necessary for soundness reasons. It's an extreme
53        // edge case, but arbitrary Python code _could_ change the __class__ of an object and cause
54        // the type object to be freed.
55        //
56        // By making `Bound` we assume ownership which is then safe against races.
57        unsafe {
58            Self::type_object_raw(py)
59                .cast::<ffi::PyObject>()
60                .assume_borrowed_unchecked(py)
61                .to_owned()
62                .downcast_into_unchecked()
63        }
64    }
65
66    /// Deprecated name for [`PyTypeInfo::type_object`].
67    #[deprecated(since = "0.23.0", note = "renamed to `PyTypeInfo::type_object`")]
68    #[inline]
69    fn type_object_bound(py: Python<'_>) -> Bound<'_, PyType> {
70        Self::type_object(py)
71    }
72
73    /// Checks if `object` is an instance of this type or a subclass of this type.
74    #[inline]
75    fn is_type_of(object: &Bound<'_, PyAny>) -> bool {
76        unsafe { ffi::PyObject_TypeCheck(object.as_ptr(), Self::type_object_raw(object.py())) != 0 }
77    }
78
79    /// Deprecated name for [`PyTypeInfo::is_type_of`].
80    #[deprecated(since = "0.23.0", note = "renamed to `PyTypeInfo::is_type_of`")]
81    #[inline]
82    fn is_type_of_bound(object: &Bound<'_, PyAny>) -> bool {
83        Self::is_type_of(object)
84    }
85
86    /// Checks if `object` is an instance of this type.
87    #[inline]
88    fn is_exact_type_of(object: &Bound<'_, PyAny>) -> bool {
89        unsafe {
90            ptr::eq(
91                ffi::Py_TYPE(object.as_ptr()),
92                Self::type_object_raw(object.py()),
93            )
94        }
95    }
96
97    /// Deprecated name for [`PyTypeInfo::is_exact_type_of`].
98    #[deprecated(since = "0.23.0", note = "renamed to `PyTypeInfo::is_exact_type_of`")]
99    #[inline]
100    fn is_exact_type_of_bound(object: &Bound<'_, PyAny>) -> bool {
101        Self::is_exact_type_of(object)
102    }
103}
104
105/// Implemented by types which can be used as a concrete Python type inside `Py<T>` smart pointers.
106pub trait PyTypeCheck {
107    /// Name of self. This is used in error messages, for example.
108    const NAME: &'static str;
109
110    /// Checks if `object` is an instance of `Self`, which may include a subtype.
111    ///
112    /// This should be equivalent to the Python expression `isinstance(object, Self)`.
113    fn type_check(object: &Bound<'_, PyAny>) -> bool;
114}
115
116impl<T> PyTypeCheck for T
117where
118    T: PyTypeInfo,
119{
120    const NAME: &'static str = <T as PyTypeInfo>::NAME;
121
122    #[inline]
123    fn type_check(object: &Bound<'_, PyAny>) -> bool {
124        T::is_type_of(object)
125    }
126}