11use crate :: call:: PyCallArgs ;
22use crate :: class:: basic:: CompareOp ;
33use crate :: conversion:: { FromPyObject , IntoPyObject } ;
4- use crate :: err:: { PyErr , PyResult } ;
5- use crate :: exceptions:: { PyAttributeError , PyTypeError } ;
4+ use crate :: err:: { error_on_minusone , PyErr , PyResult } ;
5+ use crate :: exceptions:: PyTypeError ;
66use crate :: ffi_ptr_ext:: FfiPtrExt ;
77use crate :: impl_:: pycell:: PyStaticClassObject ;
88use crate :: instance:: Bound ;
@@ -11,7 +11,7 @@ use crate::py_result_ext::PyResultExt;
1111use crate :: type_object:: { PyTypeCheck , PyTypeInfo } ;
1212use crate :: types:: PySuper ;
1313use crate :: types:: { PyDict , PyIterator , PyList , PyString , PyType } ;
14- use crate :: { err, ffi, Borrowed , BoundObject , IntoPyObjectExt , Py , Python } ;
14+ use crate :: { err, ffi, Borrowed , BoundObject , IntoPyObjectExt , Py } ;
1515#[ allow( deprecated) ]
1616use crate :: { DowncastError , DowncastIntoError } ;
1717use std:: cell:: UnsafeCell ;
@@ -980,17 +980,23 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {
980980 where
981981 N : IntoPyObject < ' py , Target = PyString > ,
982982 {
983- // PyObject_HasAttr suppresses all exceptions, which was the behaviour of `hasattr` in Python 2.
984- // Use an implementation which suppresses only AttributeError, which is consistent with `hasattr` in Python 3.
985- fn inner ( py : Python < ' _ > , getattr_result : PyResult < Bound < ' _ , PyAny > > ) -> PyResult < bool > {
986- match getattr_result {
987- Ok ( _ ) => Ok ( true ) ,
988- Err ( err ) if err . is_instance_of :: < PyAttributeError > ( py ) => Ok ( false ) ,
989- Err ( e ) => Err ( e ) ,
990- }
983+ fn inner < ' py > (
984+ any : & Bound < ' py , PyAny > ,
985+ attr_name : Borrowed < ' _ , ' _ , PyString > ,
986+ ) -> PyResult < bool > {
987+ let result =
988+ unsafe { ffi :: compat :: PyObject_HasAttrWithError ( any . as_ptr ( ) , attr_name . as_ptr ( ) ) } ;
989+ error_on_minusone ( any . py ( ) , result ) ? ;
990+ Ok ( result > 0 )
991991 }
992992
993- inner ( self . py ( ) , self . getattr ( attr_name) )
993+ inner (
994+ self ,
995+ attr_name
996+ . into_pyobject ( self . py ( ) )
997+ . map_err ( Into :: into) ?
998+ . as_borrowed ( ) ,
999+ )
9941000 }
9951001
9961002 fn getattr < N > ( & self , attr_name : N ) -> PyResult < Bound < ' py , PyAny > >
0 commit comments