pyo3/types/
notimplemented.rs

1use crate::{
2    ffi, ffi_ptr_ext::FfiPtrExt, types::any::PyAnyMethods, Borrowed, Bound, PyAny, PyTypeInfo,
3    Python,
4};
5
6/// Represents the Python `NotImplemented` object.
7///
8/// Values of this type are accessed via PyO3's smart pointers, e.g. as
9/// [`Py<PyNotImplemented>`][crate::Py] or [`Bound<'py, PyNotImplemented>`][Bound].
10#[repr(transparent)]
11pub struct PyNotImplemented(PyAny);
12
13pyobject_native_type_named!(PyNotImplemented);
14
15impl PyNotImplemented {
16    /// Returns the `NotImplemented` object.
17    #[inline]
18    pub fn get(py: Python<'_>) -> Borrowed<'_, '_, PyNotImplemented> {
19        unsafe {
20            ffi::Py_NotImplemented()
21                .assume_borrowed(py)
22                .downcast_unchecked()
23        }
24    }
25
26    /// Deprecated name for [`PyNotImplemented::get`].
27    #[deprecated(since = "0.23.0", note = "renamed to `PyNotImplemented::get`")]
28    #[inline]
29    pub fn get_bound(py: Python<'_>) -> Borrowed<'_, '_, PyNotImplemented> {
30        Self::get(py)
31    }
32}
33
34unsafe impl PyTypeInfo for PyNotImplemented {
35    const NAME: &'static str = "NotImplementedType";
36    const MODULE: Option<&'static str> = None;
37
38    fn type_object_raw(_py: Python<'_>) -> *mut ffi::PyTypeObject {
39        unsafe { ffi::Py_TYPE(ffi::Py_NotImplemented()) }
40    }
41
42    #[inline]
43    fn is_type_of(object: &Bound<'_, PyAny>) -> bool {
44        // NotImplementedType is not usable as a base type
45        Self::is_exact_type_of(object)
46    }
47
48    #[inline]
49    fn is_exact_type_of(object: &Bound<'_, PyAny>) -> bool {
50        object.is(&**Self::get(object.py()))
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use crate::types::any::PyAnyMethods;
57    use crate::types::{PyDict, PyNotImplemented};
58    use crate::{PyTypeInfo, Python};
59
60    #[test]
61    fn test_notimplemented_is_itself() {
62        Python::with_gil(|py| {
63            assert!(PyNotImplemented::get(py).is_instance_of::<PyNotImplemented>());
64            assert!(PyNotImplemented::get(py).is_exact_instance_of::<PyNotImplemented>());
65        })
66    }
67
68    #[test]
69    fn test_notimplemented_type_object_consistent() {
70        Python::with_gil(|py| {
71            assert!(PyNotImplemented::get(py)
72                .get_type()
73                .is(&PyNotImplemented::type_object(py)));
74        })
75    }
76
77    #[test]
78    fn test_dict_is_not_notimplemented() {
79        Python::with_gil(|py| {
80            assert!(PyDict::new(py).downcast::<PyNotImplemented>().is_err());
81        })
82    }
83}