Skip to content

Commit

Permalink
stop suppressing unrelated exceptions in PyAny::hasattr
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed Jun 25, 2023
1 parent edf47b5 commit cc4ed09
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 4 deletions.
1 change: 1 addition & 0 deletions newsfragments/3271.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Stop suppressing unrelated exceptions in `PyAny::hasattr`.
22 changes: 18 additions & 4 deletions src/types/any.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::class::basic::CompareOp;
use crate::conversion::{AsPyPointer, FromPyObject, IntoPy, IntoPyPointer, PyTryFrom, ToPyObject};
use crate::err::{PyDowncastError, PyErr, PyResult};
use crate::exceptions::PyTypeError;
use crate::exceptions::{PyAttributeError, PyTypeError};
use crate::type_object::PyTypeInfo;
#[cfg(not(PyPy))]
use crate::types::PySuper;
Expand Down Expand Up @@ -83,10 +83,24 @@ impl PyAny {
where
N: IntoPy<Py<PyString>>,
{
let py = self.py();
let attr_name = attr_name.into_py(py);
// PyObject_HasAttr suppresses all exceptions, which was the behaviour of `hasattr` in Python 2.
// Use an implementation which suppresses only AttributeError, which is consistent with `hasattr` in Python 3.
self.hasattr_impl(attr_name.into_py(self.py()))
}

unsafe { Ok(ffi::PyObject_HasAttr(self.as_ptr(), attr_name.as_ptr()) != 0) }
fn hasattr_impl(&self, attr_name: Py<PyString>) -> PyResult<bool> {
let py = self.py();
let result = unsafe {
PyObject::from_owned_ptr_or_err(
py,
ffi::PyObject_GetItem(self.as_ptr(), attr_name.as_ptr()),
)
};
match result {
Ok(_) => Ok(true),
Err(err) if err.is_instance_of::<PyAttributeError>(py) => Ok(false),
Err(e) => Err(e),
}
}

/// Retrieves an attribute value.
Expand Down

0 comments on commit cc4ed09

Please sign in to comment.