Tidy some usage of py.from_borrowed_ptr and py.from_borrowed_ptr_or_opt (#3877)

* Tidy some usage of py.from_borrowed_ptr

* Add BoundRef::ref_from_ptr_or_opt
This commit is contained in:
Lily Foote 2024-02-22 23:06:55 +00:00 committed by GitHub
parent 8bd82da939
commit 22a23ffb31
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 33 additions and 14 deletions

View file

@ -572,12 +572,12 @@ pub fn impl_py_setter_def(
_slf: *mut _pyo3::ffi::PyObject,
_value: *mut _pyo3::ffi::PyObject,
) -> _pyo3::PyResult<::std::os::raw::c_int> {
let _value = py
.from_borrowed_ptr_or_opt(_value)
use ::std::convert::Into;
let _value = _pyo3::impl_::pymethods::BoundRef::ref_from_ptr_or_opt(py, &_value)
.ok_or_else(|| {
_pyo3::exceptions::PyAttributeError::new_err("can't delete attribute")
})?;
let _val = _pyo3::FromPyObject::extract(_value)?;
let _val = _pyo3::FromPyObject::extract_bound(_value.into())?;
#( #holders )*
_pyo3::callback::convert(py, #setter_impl)
}

View file

@ -57,9 +57,9 @@ fn test_date_fromtimestamp() {
#[test]
fn test_utc_timezone() {
Python::with_gil(|py| {
let utc_timezone: &PyAny = unsafe {
let utc_timezone: Bound<'_, PyAny> = unsafe {
PyDateTime_IMPORT();
py.from_borrowed_ptr(PyDateTime_TimeZone_UTC())
Bound::from_borrowed_ptr(py, PyDateTime_TimeZone_UTC())
};
let locals = PyDict::new_bound(py);
locals.set_item("utc_timezone", utc_timezone).unwrap();
@ -254,35 +254,33 @@ fn test_get_tzinfo() {
crate::Python::with_gil(|py| {
use crate::types::{PyDateTime, PyTime};
use crate::PyAny;
let utc = &timezone_utc_bound(py);
let dt = PyDateTime::new_bound(py, 2018, 1, 1, 0, 0, 0, 0, Some(utc)).unwrap();
assert!(
unsafe { py.from_borrowed_ptr::<PyAny>(PyDateTime_DATE_GET_TZINFO(dt.as_ptr())) }
unsafe { Bound::from_borrowed_ptr(py, PyDateTime_DATE_GET_TZINFO(dt.as_ptr())) }
.is(utc)
);
let dt = PyDateTime::new_bound(py, 2018, 1, 1, 0, 0, 0, 0, None).unwrap();
assert!(
unsafe { py.from_borrowed_ptr::<PyAny>(PyDateTime_DATE_GET_TZINFO(dt.as_ptr())) }
unsafe { Bound::from_borrowed_ptr(py, PyDateTime_DATE_GET_TZINFO(dt.as_ptr())) }
.is_none()
);
let t = PyTime::new_bound(py, 0, 0, 0, 0, Some(utc)).unwrap();
assert!(
unsafe { py.from_borrowed_ptr::<PyAny>(PyDateTime_TIME_GET_TZINFO(t.as_ptr())) }
.is(utc)
unsafe { Bound::from_borrowed_ptr(py, PyDateTime_TIME_GET_TZINFO(t.as_ptr())) }.is(utc)
);
let t = PyTime::new_bound(py, 0, 0, 0, 0, None).unwrap();
assert!(
unsafe { py.from_borrowed_ptr::<PyAny>(PyDateTime_TIME_GET_TZINFO(t.as_ptr())) }
unsafe { Bound::from_borrowed_ptr(py, PyDateTime_TIME_GET_TZINFO(t.as_ptr())) }
.is_none()
);
})

View file

@ -6,8 +6,10 @@ use crate::{
internal_tricks::extract_c_string,
pycell::PyCellLayout,
pyclass_init::PyObjectInit,
types::any::PyAnyMethods,
types::PyBool,
Py, PyAny, PyCell, PyClass, PyErr, PyMethodDefType, PyNativeType, PyResult, PyTypeInfo, Python,
Borrowed, Py, PyAny, PyCell, PyClass, PyErr, PyMethodDefType, PyNativeType, PyResult,
PyTypeInfo, Python,
};
use std::{
borrow::Cow,
@ -811,8 +813,8 @@ slot_fragment_trait! {
other: *mut ffi::PyObject,
) -> PyResult<*mut ffi::PyObject> {
// By default `__ne__` will try `__eq__` and invert the result
let slf: &PyAny = py.from_borrowed_ptr(slf);
let other: &PyAny = py.from_borrowed_ptr(other);
let slf = Borrowed::from_ptr(py, slf);
let other = Borrowed::from_ptr(py, other);
slf.eq(other).map(|is_eq| PyBool::new_bound(py, !is_eq).to_owned().into_ptr())
}
}

View file

@ -483,6 +483,13 @@ impl<'a, 'py> BoundRef<'a, 'py, PyAny> {
BoundRef(Bound::ref_from_ptr(py, ptr))
}
pub unsafe fn ref_from_ptr_or_opt(
py: Python<'py>,
ptr: &'a *mut ffi::PyObject,
) -> Option<Self> {
Bound::ref_from_ptr_or_opt(py, ptr).as_ref().map(BoundRef)
}
pub unsafe fn downcast_unchecked<T>(self) -> BoundRef<'a, 'py, T> {
BoundRef(self.0.downcast_unchecked::<T>())
}

View file

@ -191,6 +191,18 @@ impl<'py> Bound<'py, PyAny> {
) -> &'a Self {
&*(ptr as *const *mut ffi::PyObject).cast::<Bound<'py, PyAny>>()
}
/// Variant of the above which returns `None` for null pointers.
///
/// # Safety
/// - `ptr` must be a valid pointer to a Python object for the lifetime `'a, or null.
#[inline]
pub(crate) unsafe fn ref_from_ptr_or_opt<'a>(
_py: Python<'py>,
ptr: &'a *mut ffi::PyObject,
) -> &'a Option<Self> {
&*(ptr as *const *mut ffi::PyObject).cast::<Option<Bound<'py, PyAny>>>()
}
}
impl<'py, T> Bound<'py, T>