Skip to content

Commit b7788e9

Browse files
Add 'PyObject_GetOptionalAttr' compat
1 parent 463442f commit b7788e9

3 files changed

Lines changed: 39 additions & 35 deletions

File tree

newsfragments/5944.added.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
add `pyo3-ffi::compat::PyObject_HasAttrWithError`
1+
add `pyo3-ffi::compat::PyObject_HasAttrWithError` & `pyo3-ffi::compat::PyObject_GetOptionalAttr`

pyo3-ffi/src/compat/py_3_13.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,29 @@ compat_function!(
135135
originally_defined_for(Py_3_13);
136136

137137
#[inline]
138-
pub unsafe fn PyObject_HasAttrWithError(obj: *mut crate::PyObject, attr: *mut crate::PyObject) -> std::ffi::c_int {
139-
let res: *mut crate::PyObject = std::ptr::null_mut();
140-
let rc = crate::PyObject_GetOptionalAttr(obj, attr, &mut result);
138+
pub unsafe fn PyObject_HasAttrWithError(obj: *mut crate::PyObject, attr_name: *mut crate::PyObject) -> std::ffi::c_int {
139+
let mut res: *mut crate::PyObject = std::ptr::null_mut();
140+
let rc = crate::compat::PyObject_GetOptionalAttr(obj, attr_name, &mut res);
141141
crate::Py_XDECREF(res);
142142
rc
143143
}
144144
);
145+
146+
compat_function!(
147+
originally_defined_for(Py_3_13);
148+
149+
#[inline]
150+
pub unsafe fn PyObject_GetOptionalAttr(obj: *mut crate::PyObject, attr_name: *mut crate::PyObject, result: *mut *mut crate::PyObject,) -> std::ffi::c_int {
151+
*result = crate::PyObject_GetAttr(obj, attr_name);
152+
if !(*result).is_null() {
153+
1
154+
} else if crate::PyErr_Occurred().is_null() {
155+
0
156+
} else if crate::PyErr_ExceptionMatches(crate::PyExc_AttributeError) > 0 {
157+
crate::PyErr_Clear();
158+
0
159+
} else {
160+
-1
161+
}
162+
}
163+
);

src/types/any.rs

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,39 +1026,24 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {
10261026
any: &Bound<'py, PyAny>,
10271027
attr_name: Borrowed<'_, 'py, PyString>,
10281028
) -> PyResult<Option<Bound<'py, PyAny>>> {
1029-
#[cfg(Py_3_13)]
1030-
{
1031-
let mut resp_ptr: *mut ffi::PyObject = std::ptr::null_mut();
1032-
match unsafe {
1033-
ffi::PyObject_GetOptionalAttr(any.as_ptr(), attr_name.as_ptr(), &mut resp_ptr)
1034-
} {
1035-
// Attribute found, result is a new strong reference
1036-
1 => {
1037-
let bound = unsafe { Bound::from_owned_ptr(any.py(), resp_ptr) };
1038-
Ok(Some(bound))
1039-
}
1040-
// Attribute not found, result is NULL
1041-
0 => Ok(None),
1042-
1043-
// An error occurred (other than AttributeError)
1044-
_ => Err(PyErr::fetch(any.py())),
1029+
let mut resp_ptr: *mut ffi::PyObject = std::ptr::null_mut();
1030+
match unsafe {
1031+
ffi::compat::PyObject_GetOptionalAttr(
1032+
any.as_ptr(),
1033+
attr_name.as_ptr(),
1034+
&mut resp_ptr,
1035+
)
1036+
} {
1037+
// Attribute found, result is a new strong reference
1038+
1 => {
1039+
let bound = unsafe { Bound::from_owned_ptr(any.py(), resp_ptr) };
1040+
Ok(Some(bound))
10451041
}
1046-
}
1042+
// Attribute not found, result is NULL
1043+
0 => Ok(None),
10471044

1048-
#[cfg(not(Py_3_13))]
1049-
{
1050-
match any.getattr(attr_name) {
1051-
Ok(bound) => Ok(Some(bound)),
1052-
Err(err) => {
1053-
let err_type = err
1054-
.get_type(any.py())
1055-
.is(PyType::new::<PyAttributeError>(any.py()));
1056-
match err_type {
1057-
true => Ok(None),
1058-
false => Err(err),
1059-
}
1060-
}
1061-
}
1045+
// An error occurred (other than AttributeError)
1046+
_ => Err(PyErr::fetch(any.py())),
10621047
}
10631048
}
10641049

0 commit comments

Comments
 (0)