@@ -887,10 +887,41 @@ PyObject_GetAttr(PyObject *v, PyObject *name)
887887 return NULL ;
888888}
889889
890+ PyObject *
891+ _PyObject_GetAttrWithoutError (PyObject * v , PyObject * name )
892+ {
893+ PyTypeObject * tp = Py_TYPE (v );
894+ PyObject * ret = NULL ;
895+
896+ if (!PyUnicode_Check (name )) {
897+ PyErr_Format (PyExc_TypeError ,
898+ "attribute name must be string, not '%.200s'" ,
899+ name -> ob_type -> tp_name );
900+ return NULL ;
901+ }
902+
903+ if (tp -> tp_getattro == PyObject_GenericGetAttr ) {
904+ return _PyObject_GenericGetAttrWithDict (v , name , NULL , 1 );
905+ }
906+ if (tp -> tp_getattro != NULL ) {
907+ ret = (* tp -> tp_getattro )(v , name );
908+ }
909+ else if (tp -> tp_getattr != NULL ) {
910+ const char * name_str = PyUnicode_AsUTF8 (name );
911+ if (name_str == NULL )
912+ return NULL ;
913+ ret = (* tp -> tp_getattr )(v , (char * )name_str );
914+ }
915+ if (ret == NULL && PyErr_ExceptionMatches (PyExc_AttributeError )) {
916+ PyErr_Clear ();
917+ }
918+ return ret ;
919+ }
920+
890921int
891922PyObject_HasAttr (PyObject * v , PyObject * name )
892923{
893- PyObject * res = PyObject_GetAttr (v , name );
924+ PyObject * res = _PyObject_GetAttrWithoutError (v , name );
894925 if (res != NULL ) {
895926 Py_DECREF (res );
896927 return 1 ;
@@ -1098,10 +1129,13 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method)
10981129/* Generic GetAttr functions - put these in your tp_[gs]etattro slot. */
10991130
11001131PyObject *
1101- _PyObject_GenericGetAttrWithDict (PyObject * obj , PyObject * name , PyObject * dict )
1132+ _PyObject_GenericGetAttrWithDict (PyObject * obj , PyObject * name ,
1133+ PyObject * dict , int suppress )
11021134{
11031135 /* Make sure the logic of _PyObject_GetMethod is in sync with
11041136 this method.
1137+
1138+ When suppress=1, this function suppress AttributeError.
11051139 */
11061140
11071141 PyTypeObject * tp = Py_TYPE (obj );
@@ -1132,6 +1166,10 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict)
11321166 f = descr -> ob_type -> tp_descr_get ;
11331167 if (f != NULL && PyDescr_IsData (descr )) {
11341168 res = f (descr , obj , (PyObject * )obj -> ob_type );
1169+ if (res == NULL && suppress &&
1170+ PyErr_ExceptionMatches (PyExc_AttributeError )) {
1171+ PyErr_Clear ();
1172+ }
11351173 goto done ;
11361174 }
11371175 }
@@ -1171,6 +1209,10 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict)
11711209
11721210 if (f != NULL ) {
11731211 res = f (descr , obj , (PyObject * )Py_TYPE (obj ));
1212+ if (res == NULL && suppress &&
1213+ PyErr_ExceptionMatches (PyExc_AttributeError )) {
1214+ PyErr_Clear ();
1215+ }
11741216 goto done ;
11751217 }
11761218
@@ -1180,9 +1222,11 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict)
11801222 goto done ;
11811223 }
11821224
1183- PyErr_Format (PyExc_AttributeError ,
1184- "'%.50s' object has no attribute '%U'" ,
1185- tp -> tp_name , name );
1225+ if (!suppress ) {
1226+ PyErr_Format (PyExc_AttributeError ,
1227+ "'%.50s' object has no attribute '%U'" ,
1228+ tp -> tp_name , name );
1229+ }
11861230 done :
11871231 Py_XDECREF (descr );
11881232 Py_DECREF (name );
@@ -1192,7 +1236,7 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict)
11921236PyObject *
11931237PyObject_GenericGetAttr (PyObject * obj , PyObject * name )
11941238{
1195- return _PyObject_GenericGetAttrWithDict (obj , name , NULL );
1239+ return _PyObject_GenericGetAttrWithDict (obj , name , NULL , 0 );
11961240}
11971241
11981242int
0 commit comments