1 | #[cfg (feature = "experimental-inspect" )] |
2 | use crate::inspect::types::TypeInfo; |
3 | use crate::{ffi, FromPyObject, IntoPy, PyAny, PyObject, PyResult, Python, ToPyObject}; |
4 | |
5 | /// Represents a Python `bool`. |
6 | #[repr (transparent)] |
7 | pub struct PyBool(PyAny); |
8 | |
9 | pyobject_native_type!(PyBool, ffi::PyObject, pyobject_native_static_type_object!(ffi::PyBool_Type), #checkfunction=ffi::PyBool_Check); |
10 | |
11 | impl PyBool { |
12 | /// Depending on `val`, returns `true` or `false`. |
13 | #[inline ] |
14 | pub fn new(py: Python<'_>, val: bool) -> &PyBool { |
15 | unsafe { py.from_borrowed_ptr(if val { ffi::Py_True() } else { ffi::Py_False() }) } |
16 | } |
17 | |
18 | /// Gets whether this boolean is `true`. |
19 | #[inline ] |
20 | pub fn is_true(&self) -> bool { |
21 | self.as_ptr() == unsafe { crate::ffi::Py_True() } |
22 | } |
23 | } |
24 | |
25 | /// Converts a Rust `bool` to a Python `bool`. |
26 | impl ToPyObject for bool { |
27 | #[inline ] |
28 | fn to_object(&self, py: Python<'_>) -> PyObject { |
29 | unsafe { |
30 | PyObject::from_borrowed_ptr( |
31 | py, |
32 | ptr:if *self { |
33 | ffi::Py_True() |
34 | } else { |
35 | ffi::Py_False() |
36 | }, |
37 | ) |
38 | } |
39 | } |
40 | } |
41 | |
42 | impl IntoPy<PyObject> for bool { |
43 | #[inline ] |
44 | fn into_py(self, py: Python<'_>) -> PyObject { |
45 | PyBool::new(py, self).into() |
46 | } |
47 | |
48 | #[cfg (feature = "experimental-inspect" )] |
49 | fn type_output() -> TypeInfo { |
50 | TypeInfo::builtin("bool" ) |
51 | } |
52 | } |
53 | |
54 | /// Converts a Python `bool` to a Rust `bool`. |
55 | /// |
56 | /// Fails with `TypeError` if the input is not a Python `bool`. |
57 | impl<'source> FromPyObject<'source> for bool { |
58 | fn extract(obj: &'source PyAny) -> PyResult<Self> { |
59 | Ok(obj.downcast::<PyBool>()?.is_true()) |
60 | } |
61 | |
62 | #[cfg (feature = "experimental-inspect" )] |
63 | fn type_input() -> TypeInfo { |
64 | Self::type_output() |
65 | } |
66 | } |
67 | |
68 | #[cfg (test)] |
69 | mod tests { |
70 | use crate::types::{PyAny, PyBool}; |
71 | use crate::Python; |
72 | use crate::ToPyObject; |
73 | |
74 | #[test ] |
75 | fn test_true() { |
76 | Python::with_gil(|py| { |
77 | assert!(PyBool::new(py, true).is_true()); |
78 | let t: &PyAny = PyBool::new(py, true).into(); |
79 | assert!(t.extract::<bool>().unwrap()); |
80 | assert!(true.to_object(py).is(PyBool::new(py, true))); |
81 | }); |
82 | } |
83 | |
84 | #[test ] |
85 | fn test_false() { |
86 | Python::with_gil(|py| { |
87 | assert!(!PyBool::new(py, false).is_true()); |
88 | let t: &PyAny = PyBool::new(py, false).into(); |
89 | assert!(!t.extract::<bool>().unwrap()); |
90 | assert!(false.to_object(py).is(PyBool::new(py, false))); |
91 | }); |
92 | } |
93 | } |
94 | |