@@ -4219,9 +4219,19 @@ _PyType_LookupId(PyTypeObject *type, _Py_Identifier *name)
4219
4219
}
4220
4220
4221
4221
/* 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 )
4225
4235
{
4226
4236
PyTypeObject * metatype = Py_TYPE (type );
4227
4237
PyObject * meta_attribute , * attribute ;
@@ -4301,12 +4311,25 @@ type_getattro(PyTypeObject *type, PyObject *name)
4301
4311
}
4302
4312
4303
4313
/* 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
+ }
4307
4322
return NULL ;
4308
4323
}
4309
4324
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
+
4310
4333
static int
4311
4334
type_setattro (PyTypeObject * type , PyObject * name , PyObject * value )
4312
4335
{
@@ -4798,7 +4821,7 @@ PyTypeObject PyType_Type = {
4798
4821
0 , /* tp_hash */
4799
4822
(ternaryfunc )type_call , /* tp_call */
4800
4823
0 , /* tp_str */
4801
- (getattrofunc )type_getattro , /* tp_getattro */
4824
+ (getattrofunc )_Py_type_getattro , /* tp_getattro */
4802
4825
(setattrofunc )type_setattro , /* tp_setattro */
4803
4826
0 , /* tp_as_buffer */
4804
4827
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
0 commit comments