add `Bound` constructor for `PyBool`
This commit is contained in:
parent
57735540e8
commit
af21a9dc74
|
@ -79,7 +79,7 @@ use pyo3::prelude::*;
|
||||||
use pyo3::types::{PyBool, PyList};
|
use pyo3::types::{PyBool, PyList};
|
||||||
|
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
assert!(PyBool::new(py, true).is_instance_of::<PyBool>());
|
assert!(PyBool::new_bound(py, true).is_instance_of::<PyBool>());
|
||||||
let list = PyList::new_bound(py, &[1, 2, 3, 4]);
|
let list = PyList::new_bound(py, &[1, 2, 3, 4]);
|
||||||
assert!(!list.is_instance_of::<PyBool>());
|
assert!(!list.is_instance_of::<PyBool>());
|
||||||
assert!(list.is_instance_of::<PyList>());
|
assert!(list.is_instance_of::<PyList>());
|
||||||
|
|
|
@ -813,7 +813,7 @@ slot_fragment_trait! {
|
||||||
// By default `__ne__` will try `__eq__` and invert the result
|
// By default `__ne__` will try `__eq__` and invert the result
|
||||||
let slf: &PyAny = py.from_borrowed_ptr(slf);
|
let slf: &PyAny = py.from_borrowed_ptr(slf);
|
||||||
let other: &PyAny = py.from_borrowed_ptr(other);
|
let other: &PyAny = py.from_borrowed_ptr(other);
|
||||||
slf.eq(other).map(|is_eq| PyBool::new(py, !is_eq).into_ptr())
|
slf.eq(other).map(|is_eq| PyBool::new_bound(py, !is_eq).to_owned().into_ptr())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -321,6 +321,14 @@ impl<'a, 'py> Borrowed<'a, 'py, PyAny> {
|
||||||
pub(crate) unsafe fn from_ptr_unchecked(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self {
|
pub(crate) unsafe fn from_ptr_unchecked(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self {
|
||||||
Self(NonNull::new_unchecked(ptr), PhantomData, py)
|
Self(NonNull::new_unchecked(ptr), PhantomData, py)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts this `PyAny` to a concrete Python type without checking validity.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// Callers must ensure that the type is valid or risk type confusion.
|
||||||
|
pub(crate) unsafe fn downcast_unchecked<T>(self) -> Borrowed<'a, 'py, T> {
|
||||||
|
Borrowed(self.0, PhantomData, self.2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'py, T> From<&'a Bound<'py, T>> for Borrowed<'a, 'py, T> {
|
impl<'a, 'py, T> From<&'a Bound<'py, T>> for Borrowed<'a, 'py, T> {
|
||||||
|
|
|
@ -759,9 +759,9 @@ impl PyAny {
|
||||||
/// use pyo3::types::{PyBool, PyLong};
|
/// use pyo3::types::{PyBool, PyLong};
|
||||||
///
|
///
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let b = PyBool::new(py, true);
|
/// let b = PyBool::new_bound(py, true);
|
||||||
/// assert!(b.is_instance_of::<PyBool>());
|
/// assert!(b.is_instance_of::<PyBool>());
|
||||||
/// let any: &PyAny = b.as_ref();
|
/// let any: &Bound<'_, PyAny> = b.as_any();
|
||||||
///
|
///
|
||||||
/// // `bool` is a subtype of `int`, so `downcast` will accept a `bool` as an `int`
|
/// // `bool` is a subtype of `int`, so `downcast` will accept a `bool` as an `int`
|
||||||
/// // but `downcast_exact` will not.
|
/// // but `downcast_exact` will not.
|
||||||
|
@ -1583,9 +1583,9 @@ pub trait PyAnyMethods<'py> {
|
||||||
/// use pyo3::types::{PyBool, PyLong};
|
/// use pyo3::types::{PyBool, PyLong};
|
||||||
///
|
///
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let b = PyBool::new(py, true);
|
/// let b = PyBool::new_bound(py, true);
|
||||||
/// assert!(b.is_instance_of::<PyBool>());
|
/// assert!(b.is_instance_of::<PyBool>());
|
||||||
/// let any: &PyAny = b.as_ref();
|
/// let any: &Bound<'_, PyAny> = b.as_any();
|
||||||
///
|
///
|
||||||
/// // `bool` is a subtype of `int`, so `downcast` will accept a `bool` as an `int`
|
/// // `bool` is a subtype of `int`, so `downcast` will accept a `bool` as an `int`
|
||||||
/// // but `downcast_exact` will not.
|
/// // but `downcast_exact` will not.
|
||||||
|
@ -2530,7 +2530,7 @@ class SimpleClass:
|
||||||
let x = 5.to_object(py).into_ref(py);
|
let x = 5.to_object(py).into_ref(py);
|
||||||
assert!(x.is_exact_instance_of::<PyLong>());
|
assert!(x.is_exact_instance_of::<PyLong>());
|
||||||
|
|
||||||
let t = PyBool::new(py, true);
|
let t = PyBool::new_bound(py, true);
|
||||||
assert!(t.is_instance_of::<PyLong>());
|
assert!(t.is_instance_of::<PyLong>());
|
||||||
assert!(!t.is_exact_instance_of::<PyLong>());
|
assert!(!t.is_exact_instance_of::<PyLong>());
|
||||||
assert!(t.is_exact_instance_of::<PyBool>());
|
assert!(t.is_exact_instance_of::<PyBool>());
|
||||||
|
@ -2543,10 +2543,12 @@ class SimpleClass:
|
||||||
#[test]
|
#[test]
|
||||||
fn test_any_is_exact_instance() {
|
fn test_any_is_exact_instance() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let t = PyBool::new(py, true);
|
let t = PyBool::new_bound(py, true);
|
||||||
assert!(t.is_instance(py.get_type::<PyLong>()).unwrap());
|
assert!(t
|
||||||
assert!(!t.is_exact_instance(py.get_type::<PyLong>()));
|
.is_instance(&py.get_type::<PyLong>().as_borrowed())
|
||||||
assert!(t.is_exact_instance(py.get_type::<PyBool>()));
|
.unwrap());
|
||||||
|
assert!(!t.is_exact_instance(&py.get_type::<PyLong>().as_borrowed()));
|
||||||
|
assert!(t.is_exact_instance(&py.get_type::<PyBool>().as_borrowed()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#[cfg(feature = "experimental-inspect")]
|
#[cfg(feature = "experimental-inspect")]
|
||||||
use crate::inspect::types::TypeInfo;
|
use crate::inspect::types::TypeInfo;
|
||||||
use crate::{
|
use crate::{
|
||||||
exceptions::PyTypeError, ffi, instance::Bound, FromPyObject, IntoPy, PyAny, PyNativeType,
|
exceptions::PyTypeError, ffi, ffi_ptr_ext::FfiPtrExt, instance::Bound, Borrowed, FromPyObject,
|
||||||
PyObject, PyResult, Python, ToPyObject,
|
IntoPy, PyAny, PyNativeType, PyObject, PyResult, Python, ToPyObject,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::any::PyAnyMethods;
|
use super::any::PyAnyMethods;
|
||||||
|
@ -14,12 +14,33 @@ pub struct PyBool(PyAny);
|
||||||
pyobject_native_type!(PyBool, ffi::PyObject, pyobject_native_static_type_object!(ffi::PyBool_Type), #checkfunction=ffi::PyBool_Check);
|
pyobject_native_type!(PyBool, ffi::PyObject, pyobject_native_static_type_object!(ffi::PyBool_Type), #checkfunction=ffi::PyBool_Check);
|
||||||
|
|
||||||
impl PyBool {
|
impl PyBool {
|
||||||
/// Depending on `val`, returns `true` or `false`.
|
/// Deprecated form of [`PyBool::new_bound`]
|
||||||
|
#[cfg_attr(
|
||||||
|
not(feature = "gil-refs"),
|
||||||
|
deprecated(
|
||||||
|
since = "0.21.0",
|
||||||
|
note = "`PyBool::new` will be replaced by `PyBool::new_bound` in a future PyO3 version"
|
||||||
|
)
|
||||||
|
)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(py: Python<'_>, val: bool) -> &PyBool {
|
pub fn new(py: Python<'_>, val: bool) -> &PyBool {
|
||||||
unsafe { py.from_borrowed_ptr(if val { ffi::Py_True() } else { ffi::Py_False() }) }
|
unsafe { py.from_borrowed_ptr(if val { ffi::Py_True() } else { ffi::Py_False() }) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Depending on `val`, returns `true` or `false`.
|
||||||
|
///
|
||||||
|
/// # Note
|
||||||
|
/// This returns a [`Borrowed`] reference to one of Pythons `True` or
|
||||||
|
/// `False` singletons
|
||||||
|
#[inline]
|
||||||
|
pub fn new_bound(py: Python<'_>, val: bool) -> Borrowed<'_, '_, Self> {
|
||||||
|
unsafe {
|
||||||
|
if val { ffi::Py_True() } else { ffi::Py_False() }
|
||||||
|
.assume_borrowed(py)
|
||||||
|
.downcast_unchecked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets whether this boolean is `true`.
|
/// Gets whether this boolean is `true`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_true(&self) -> bool {
|
pub fn is_true(&self) -> bool {
|
||||||
|
@ -65,7 +86,7 @@ impl ToPyObject for bool {
|
||||||
impl IntoPy<PyObject> for bool {
|
impl IntoPy<PyObject> for bool {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_py(self, py: Python<'_>) -> PyObject {
|
fn into_py(self, py: Python<'_>) -> PyObject {
|
||||||
PyBool::new(py, self).into()
|
PyBool::new_bound(py, self).into_py(py)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "experimental-inspect")]
|
#[cfg(feature = "experimental-inspect")]
|
||||||
|
@ -135,27 +156,29 @@ impl FromPyObject<'_> for bool {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::types::{PyAny, PyBool};
|
use crate::types::any::PyAnyMethods;
|
||||||
|
use crate::types::boolobject::PyBoolMethods;
|
||||||
|
use crate::types::PyBool;
|
||||||
use crate::Python;
|
use crate::Python;
|
||||||
use crate::ToPyObject;
|
use crate::ToPyObject;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_true() {
|
fn test_true() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
assert!(PyBool::new(py, true).is_true());
|
assert!(PyBool::new_bound(py, true).is_true());
|
||||||
let t: &PyAny = PyBool::new(py, true).into();
|
let t = PyBool::new_bound(py, true);
|
||||||
assert!(t.extract::<bool>().unwrap());
|
assert!(t.as_any().extract::<bool>().unwrap());
|
||||||
assert!(true.to_object(py).is(PyBool::new(py, true)));
|
assert!(true.to_object(py).is(&*PyBool::new_bound(py, true)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_false() {
|
fn test_false() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
assert!(!PyBool::new(py, false).is_true());
|
assert!(!PyBool::new_bound(py, false).is_true());
|
||||||
let t: &PyAny = PyBool::new(py, false).into();
|
let t = PyBool::new_bound(py, false);
|
||||||
assert!(!t.extract::<bool>().unwrap());
|
assert!(!t.as_any().extract::<bool>().unwrap());
|
||||||
assert!(false.to_object(py).is(PyBool::new(py, false)));
|
assert!(false.to_object(py).is(&*PyBool::new_bound(py, false)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,12 +190,12 @@ fn test_renaming_all_struct_fields() {
|
||||||
let struct_class = py.get_type::<StructWithRenamedFields>();
|
let struct_class = py.get_type::<StructWithRenamedFields>();
|
||||||
let struct_obj = struct_class.call0().unwrap();
|
let struct_obj = struct_class.call0().unwrap();
|
||||||
assert!(struct_obj
|
assert!(struct_obj
|
||||||
.setattr("firstField", PyBool::new(py, false))
|
.setattr("firstField", PyBool::new_bound(py, false))
|
||||||
.is_ok());
|
.is_ok());
|
||||||
py_assert!(py, struct_obj, "struct_obj.firstField == False");
|
py_assert!(py, struct_obj, "struct_obj.firstField == False");
|
||||||
py_assert!(py, struct_obj, "struct_obj.secondField == 5");
|
py_assert!(py, struct_obj, "struct_obj.secondField == 5");
|
||||||
assert!(struct_obj
|
assert!(struct_obj
|
||||||
.setattr("third_field", PyBool::new(py, true))
|
.setattr("third_field", PyBool::new_bound(py, true))
|
||||||
.is_ok());
|
.is_ok());
|
||||||
py_assert!(py, struct_obj, "struct_obj.third_field == True");
|
py_assert!(py, struct_obj, "struct_obj.third_field == True");
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue