1 | use crate::{ffi, IntoPy, PyAny, PyDowncastError, PyObject, PyTryFrom, Python, ToPyObject}; |
2 | |
3 | /// Represents the Python `None` object. |
4 | #[repr (transparent)] |
5 | pub struct PyNone(PyAny); |
6 | |
7 | pyobject_native_type_named!(PyNone); |
8 | pyobject_native_type_extract!(PyNone); |
9 | |
10 | impl 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 | |
18 | impl<'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`. |
40 | impl ToPyObject for () { |
41 | fn to_object(&self, py: Python<'_>) -> PyObject { |
42 | PyNone::get(py).into() |
43 | } |
44 | } |
45 | |
46 | impl IntoPy<PyObject> for () { |
47 | #[inline ] |
48 | fn into_py(self, py: Python<'_>) -> PyObject { |
49 | PyNone::get(py).into() |
50 | } |
51 | } |
52 | |
53 | #[cfg (test)] |
54 | mod 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 | |