@@ -81,6 +81,29 @@ lazy_import_dealloc(PyObject *op)
8181 Py_TYPE (op )-> tp_free (op );
8282}
8383
84+ /* Specialize the error message for failed attribute lookups. */
85+ static PyObject *
86+ lazy_import_getattro (PyObject * op , PyObject * name )
87+ {
88+ PyObject * value = _PyObject_GenericGetAttrWithDict (op , name , NULL , /* suppress */ 1 );
89+ if (value == NULL ) {
90+ if (PyErr_Occurred ()) {
91+ // pass up non-AttributeError exception
92+ return NULL ;
93+ }
94+ PyObject * lz_name = _PyLazyImport_GetName (op );
95+ if (lz_name == NULL ) {
96+ return NULL ;
97+ }
98+ PyErr_Format (PyExc_AttributeError ,
99+ "cannot access attribute %R on unresolved lazy import %R" ,
100+ name , lz_name );
101+ Py_DECREF (lz_name );
102+ return NULL ;
103+ }
104+ return value ;
105+ }
106+
84107static PyObject *
85108lazy_import_name (PyLazyImportObject * m )
86109{
@@ -149,6 +172,7 @@ PyTypeObject PyLazyImport_Type = {
149172 .tp_repr = lazy_import_repr ,
150173 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC ,
151174 .tp_doc = lazy_import_doc ,
175+ .tp_getattro = lazy_import_getattro ,
152176 .tp_traverse = lazy_import_traverse ,
153177 .tp_clear = lazy_import_clear ,
154178 .tp_methods = lazy_import_methods ,
0 commit comments