1use crate::{ffi, IntoPy, PyAny, PyDowncastError, PyObject, PyTryFrom, Python, ToPyObject};
2
3/// Represents the Python `None` object.
4#[repr(transparent)]
5pub struct PyNone(PyAny);
6
7pyobject_native_type_named!(PyNone);
8pyobject_native_type_extract!(PyNone);
9
10impl PyNone {
11 /// Returns the `None` object.
12 #[inline]
13 pub fn get(py: Python<'_>) -> &PyNone {
14 unsafe { py.from_borrowed_ptr(ffi::Py_None()) }
15 }
16}
17
18impl<'v> PyTryFrom<'v> for PyNone {
19 fn try_from<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, crate::PyDowncastError<'v>> {
20 let value: &PyAny = value.into();
21 if value.is_none() {
22 return unsafe { Ok(value.downcast_unchecked()) };
23 }
24 Err(PyDowncastError::new(from:value, to:"NoneType"))
25 }
26
27 fn try_from_exact<V: Into<&'v PyAny>>(
28 value: V,
29 ) -> Result<&'v Self, crate::PyDowncastError<'v>> {
30 value.into().downcast()
31 }
32
33 unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v Self {
34 let ptr: *const PyNone = value.into() as *const _ as *const PyNone;
35 &*ptr
36 }
37}
38
39/// `()` is converted to Python `None`.
40impl ToPyObject for () {
41 fn to_object(&self, py: Python<'_>) -> PyObject {
42 PyNone::get(py).into()
43 }
44}
45
46impl IntoPy<PyObject> for () {
47 #[inline]
48 fn into_py(self, py: Python<'_>) -> PyObject {
49 PyNone::get(py).into()
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use crate::types::{PyDict, PyNone};
56 use crate::{IntoPy, PyObject, Python, ToPyObject};
57
58 #[test]
59 fn test_none_is_none() {
60 Python::with_gil(|py| {
61 assert!(PyNone::get(py).downcast::<PyNone>().unwrap().is_none());
62 })
63 }
64
65 #[test]
66 fn test_unit_to_object_is_none() {
67 Python::with_gil(|py| {
68 assert!(().to_object(py).downcast::<PyNone>(py).is_ok());
69 })
70 }
71
72 #[test]
73 fn test_unit_into_py_is_none() {
74 Python::with_gil(|py| {
75 let obj: PyObject = ().into_py(py);
76 assert!(obj.downcast::<PyNone>(py).is_ok());
77 })
78 }
79
80 #[test]
81 fn test_dict_is_not_none() {
82 Python::with_gil(|py| {
83 assert!(PyDict::new(py).downcast::<PyNone>().is_err());
84 })
85 }
86}
87