pyo3/types/
none.rs

1use crate::ffi_ptr_ext::FfiPtrExt;
2use crate::{
3    ffi, types::any::PyAnyMethods, Borrowed, Bound, IntoPy, PyAny, PyObject, PyTypeInfo, Python,
4    ToPyObject,
5};
6
7/// Represents the Python `None` object.
8///
9/// Values of this type are accessed via PyO3's smart pointers, e.g. as
10/// [`Py<PyNone>`][crate::Py] or [`Bound<'py, PyNone>`][Bound].
11#[repr(transparent)]
12pub struct PyNone(PyAny);
13
14pyobject_native_type_named!(PyNone);
15pyobject_native_type_extract!(PyNone);
16
17impl PyNone {
18    /// Returns the `None` object.
19    /// Deprecated form of [`PyNone::get_bound`]
20    #[cfg(feature = "gil-refs")]
21    #[deprecated(
22        since = "0.21.0",
23        note = "`PyNone::get` will be replaced by `PyNone::get_bound` in a future PyO3 version"
24    )]
25    #[inline]
26    pub fn get(py: Python<'_>) -> &PyNone {
27        Self::get_bound(py).into_gil_ref()
28    }
29
30    /// Returns the `None` object.
31    #[inline]
32    pub fn get_bound(py: Python<'_>) -> Borrowed<'_, '_, PyNone> {
33        unsafe { ffi::Py_None().assume_borrowed(py).downcast_unchecked() }
34    }
35}
36
37unsafe impl PyTypeInfo for PyNone {
38    const NAME: &'static str = "NoneType";
39
40    const MODULE: Option<&'static str> = None;
41
42    fn type_object_raw(_py: Python<'_>) -> *mut ffi::PyTypeObject {
43        unsafe { ffi::Py_TYPE(ffi::Py_None()) }
44    }
45
46    #[inline]
47    fn is_type_of_bound(object: &Bound<'_, PyAny>) -> bool {
48        // NoneType is not usable as a base type
49        Self::is_exact_type_of_bound(object)
50    }
51
52    #[inline]
53    fn is_exact_type_of_bound(object: &Bound<'_, PyAny>) -> bool {
54        object.is(&**Self::get_bound(object.py()))
55    }
56}
57
58/// `()` is converted to Python `None`.
59impl ToPyObject for () {
60    fn to_object(&self, py: Python<'_>) -> PyObject {
61        PyNone::get_bound(py).into_py(py)
62    }
63}
64
65impl IntoPy<PyObject> for () {
66    #[inline]
67    fn into_py(self, py: Python<'_>) -> PyObject {
68        PyNone::get_bound(py).into_py(py)
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use crate::types::any::PyAnyMethods;
75    use crate::types::{PyDict, PyNone};
76    use crate::{IntoPy, PyObject, PyTypeInfo, Python, ToPyObject};
77    #[test]
78    fn test_none_is_itself() {
79        Python::with_gil(|py| {
80            assert!(PyNone::get_bound(py).is_instance_of::<PyNone>());
81            assert!(PyNone::get_bound(py).is_exact_instance_of::<PyNone>());
82        })
83    }
84
85    #[test]
86    fn test_none_type_object_consistent() {
87        Python::with_gil(|py| {
88            assert!(PyNone::get_bound(py)
89                .get_type()
90                .is(&PyNone::type_object_bound(py)));
91        })
92    }
93
94    #[test]
95    fn test_none_is_none() {
96        Python::with_gil(|py| {
97            assert!(PyNone::get_bound(py)
98                .downcast::<PyNone>()
99                .unwrap()
100                .is_none());
101        })
102    }
103
104    #[test]
105    fn test_unit_to_object_is_none() {
106        Python::with_gil(|py| {
107            assert!(().to_object(py).downcast_bound::<PyNone>(py).is_ok());
108        })
109    }
110
111    #[test]
112    fn test_unit_into_py_is_none() {
113        Python::with_gil(|py| {
114            let obj: PyObject = ().into_py(py);
115            assert!(obj.downcast_bound::<PyNone>(py).is_ok());
116        })
117    }
118
119    #[test]
120    fn test_dict_is_not_none() {
121        Python::with_gil(|py| {
122            assert!(PyDict::new_bound(py).downcast::<PyNone>().is_err());
123        })
124    }
125}