@@ -3,7 +3,7 @@ use std::convert::Infallible;
33use std:: fmt;
44
55use pyo3:: IntoPyObjectExt ;
6- use pyo3:: exceptions:: { PyTypeError , PyValueError } ;
6+ use pyo3:: exceptions:: { PyAttributeError , PyTypeError , PyValueError } ;
77use pyo3:: prelude:: * ;
88use pyo3:: pybacked:: PyBackedStr ;
99use pyo3:: types:: { PyDict , PyList , PyMapping , PyString } ;
@@ -111,7 +111,7 @@ impl LookupPath {
111111 }
112112
113113 pub fn simple_py_get_attr < ' py > ( & self , obj : & Bound < ' py , PyAny > ) -> PyResult < Option < Bound < ' py , PyAny > > > {
114- self . get_impl ( obj, PyAnyMethods :: getattr_opt , |d, loc| loc. py_get_attrs ( & d) )
114+ self . get_impl ( obj, py_get_attrs , |d, loc| loc. py_get_attrs ( & d) )
115115 }
116116
117117 pub fn py_get_attr < ' py > (
@@ -366,7 +366,7 @@ impl PathItemString {
366366 // FIXME: should this instance check be for Mapping instead of Dict, and use `mapping_get`?
367367 Ok ( obj. get_item ( self ) . ok ( ) )
368368 } else {
369- obj . getattr_opt ( self )
369+ py_get_attrs ( obj , self )
370370 }
371371 }
372372}
@@ -454,3 +454,20 @@ impl LookupType {
454454 ( self as u8 & other as u8 ) != 0
455455 }
456456}
457+
458+ // TODO replace with `PyAnyMethods::getattr_opt` once https://github.com/PyO3/pyo3/pull/5985 is merged:
459+ fn py_get_attrs < ' py , N > ( obj : & Bound < ' py , PyAny > , attr_name : N ) -> PyResult < Option < Bound < ' py , PyAny > > >
460+ where
461+ N : IntoPyObject < ' py , Target = PyString > ,
462+ {
463+ match obj. getattr ( attr_name) {
464+ Ok ( attr) => Ok ( Some ( attr) ) ,
465+ Err ( err) => {
466+ if err. get_type ( obj. py ( ) ) . is_subclass_of :: < PyAttributeError > ( ) ? {
467+ Ok ( None )
468+ } else {
469+ Err ( err)
470+ }
471+ }
472+ }
473+ }
0 commit comments