@@ -4219,9 +4219,19 @@ _PyType_LookupId(PyTypeObject *type, _Py_Identifier *name)
42194219}
42204220
42214221/* This is similar to PyObject_GenericGetAttr(),
4222- but uses _PyType_Lookup() instead of just looking in type->tp_dict. */
4223- static PyObject *
4224- type_getattro (PyTypeObject * type , PyObject * name )
4222+ but uses _PyType_Lookup() instead of just looking in type->tp_dict.
4223+
4224+ The argument suppress_missing_attribute is used to provide a
4225+ fast path for hasattr. The possible values are:
4226+
4227+ * NULL: do not suppress the exception
4228+ * Non-zero pointer: suppress the PyExc_AttributeError and
4229+ set *suppress_missing_attribute to 1 to signal we are returning NULL while
4230+ having suppressed the exception (other exceptions are not suppressed)
4231+
4232+ */
4233+ PyObject *
4234+ _Py_type_getattro_impl (PyTypeObject * type , PyObject * name , int * suppress_missing_attribute )
42254235{
42264236 PyTypeObject * metatype = Py_TYPE (type );
42274237 PyObject * meta_attribute , * attribute ;
@@ -4301,12 +4311,25 @@ type_getattro(PyTypeObject *type, PyObject *name)
43014311 }
43024312
43034313 /* Give up */
4304- PyErr_Format (PyExc_AttributeError ,
4305- "type object '%.50s' has no attribute '%U'" ,
4306- type -> tp_name , name );
4314+ if (suppress_missing_attribute == NULL ) {
4315+ PyErr_Format (PyExc_AttributeError ,
4316+ "type object '%.50s' has no attribute '%U'" ,
4317+ type -> tp_name , name );
4318+ } else {
4319+ // signal the caller we have not set an PyExc_AttributeError and gave up
4320+ * suppress_missing_attribute = 1 ;
4321+ }
43074322 return NULL ;
43084323}
43094324
4325+ /* This is similar to PyObject_GenericGetAttr(),
4326+ but uses _PyType_Lookup() instead of just looking in type->tp_dict. */
4327+ PyObject *
4328+ _Py_type_getattro (PyTypeObject * type , PyObject * name )
4329+ {
4330+ return _Py_type_getattro_impl (type , name , NULL );
4331+ }
4332+
43104333static int
43114334type_setattro (PyTypeObject * type , PyObject * name , PyObject * value )
43124335{
@@ -4798,7 +4821,7 @@ PyTypeObject PyType_Type = {
47984821 0 , /* tp_hash */
47994822 (ternaryfunc )type_call , /* tp_call */
48004823 0 , /* tp_str */
4801- (getattrofunc )type_getattro , /* tp_getattro */
4824+ (getattrofunc )_Py_type_getattro , /* tp_getattro */
48024825 (setattrofunc )type_setattro , /* tp_setattro */
48034826 0 , /* tp_as_buffer */
48044827 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
0 commit comments