66#include "pycore_fileutils.h" // _Py_wgetcwd
77#include "pycore_import.h" // _PyImport_GetNextModuleIndex()
88#include "pycore_interp.h" // PyInterpreterState.importlib
9+ #include "pycore_lazyimportobject.h" // _PyLazyImportObject_Check()
910#include "pycore_long.h" // _PyLong_GetOne()
1011#include "pycore_modsupport.h" // _PyModule_CreateInitialized()
1112#include "pycore_moduleobject.h" // _PyModule_GetDef()
2223 (assert(PyModule_Check(op)), _Py_CAST(PyModuleObject*, (op)))
2324
2425
25- static PyMemberDef module_members [] = {
26- {"__dict__" , _Py_T_OBJECT , offsetof(PyModuleObject , md_dict ), Py_READONLY },
27- {0 }
28- };
29-
30-
3126PyTypeObject PyModuleDef_Type = {
3227 PyVarObject_HEAD_INIT (& PyType_Type , 0 )
3328 "moduledef" , /* tp_name */
@@ -1048,6 +1043,18 @@ _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress)
10481043 PyObject * attr , * mod_name , * getattr ;
10491044 attr = _PyObject_GenericGetAttrWithDict ((PyObject * )m , name , NULL , suppress );
10501045 if (attr ) {
1046+ if (PyLazyImport_CheckExact (attr )) {
1047+ PyObject * new_value = _PyImport_LoadLazyImportTstate (PyThreadState_GET (), attr );
1048+ if (new_value == NULL ) {
1049+ return NULL ;
1050+ } else if (PyDict_SetItem (m -> md_dict , name , new_value ) < 0 ) {
1051+ Py_DECREF (new_value );
1052+ Py_DECREF (attr );
1053+ return NULL ;
1054+ }
1055+ Py_DECREF (attr );
1056+ return new_value ;
1057+ }
10511058 return attr ;
10521059 }
10531060 if (suppress == 1 ) {
@@ -1273,7 +1280,7 @@ static PyMethodDef module_methods[] = {
12731280};
12741281
12751282static PyObject *
1276- module_get_dict (PyModuleObject * m )
1283+ module_load_dict (PyModuleObject * m )
12771284{
12781285 PyObject * dict = PyObject_GetAttr ((PyObject * )m , & _Py_ID (__dict__ ));
12791286 if (dict == NULL ) {
@@ -1292,7 +1299,7 @@ module_get_annotate(PyObject *self, void *Py_UNUSED(ignored))
12921299{
12931300 PyModuleObject * m = _PyModule_CAST (self );
12941301
1295- PyObject * dict = module_get_dict (m );
1302+ PyObject * dict = module_load_dict (m );
12961303 if (dict == NULL ) {
12971304 return NULL ;
12981305 }
@@ -1317,7 +1324,7 @@ module_set_annotate(PyObject *self, PyObject *value, void *Py_UNUSED(ignored))
13171324 return -1 ;
13181325 }
13191326
1320- PyObject * dict = module_get_dict (m );
1327+ PyObject * dict = module_load_dict (m );
13211328 if (dict == NULL ) {
13221329 return -1 ;
13231330 }
@@ -1347,7 +1354,7 @@ module_get_annotations(PyObject *self, void *Py_UNUSED(ignored))
13471354{
13481355 PyModuleObject * m = _PyModule_CAST (self );
13491356
1350- PyObject * dict = module_get_dict (m );
1357+ PyObject * dict = module_load_dict (m );
13511358 if (dict == NULL ) {
13521359 return NULL ;
13531360 }
@@ -1419,7 +1426,7 @@ module_set_annotations(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)
14191426{
14201427 PyModuleObject * m = _PyModule_CAST (self );
14211428
1422- PyObject * dict = module_get_dict (m );
1429+ PyObject * dict = module_load_dict (m );
14231430 if (dict == NULL ) {
14241431 return -1 ;
14251432 }
@@ -1448,10 +1455,52 @@ module_set_annotations(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)
14481455 return ret ;
14491456}
14501457
1458+ static PyObject *
1459+ module_get_dict (PyObject * mod , void * Py_UNUSED (ignored ))
1460+ {
1461+ PyModuleObject * self = (PyModuleObject * )mod ;
1462+ PyThreadState * tstate = PyThreadState_GET ();
1463+ Py_BEGIN_CRITICAL_SECTION (self -> md_dict );
1464+ uint32_t version = _PyDict_GetKeysVersionForCurrentState (tstate -> interp ,
1465+ (PyDictObject * )self -> md_dict );
1466+ // Check if the dict has been updated since we last checked to see if
1467+ // it has lazy values.
1468+ if (self -> m_dict_version != version || version == 0 ) {
1469+ // Scan for lazy values...
1470+ bool retry ;
1471+ do {
1472+ retry = false;
1473+ Py_ssize_t pos = 0 ;
1474+ PyObject * key , * value ;
1475+ while (PyDict_Next (self -> md_dict , & pos , & key , & value )) {
1476+ if (PyLazyImport_CheckExact (value )) {
1477+ PyObject * new_value = _PyImport_LoadLazyImportTstate (tstate , value );
1478+ if (new_value == NULL ) {
1479+ return NULL ;
1480+ }
1481+ if (PyDict_SetItem (self -> md_dict , key , new_value ) < 0 ) {
1482+ Py_DECREF (new_value );
1483+ return NULL ;
1484+ }
1485+ if (!PyLazyImport_CheckExact (value )) {
1486+ // Only force a retry if we actually made forward progress
1487+ retry = true;
1488+ }
1489+ Py_DECREF (new_value );
1490+ }
1491+ }
1492+ } while (retry );
1493+ self -> m_dict_version = _PyDict_GetKeysVersionForCurrentState (tstate -> interp ,
1494+ (PyDictObject * )self -> md_dict );
1495+ }
1496+ Py_END_CRITICAL_SECTION ();
1497+ return Py_NewRef (self -> md_dict );
1498+ }
14511499
14521500static PyGetSetDef module_getsets [] = {
14531501 {"__annotations__" , module_get_annotations , module_set_annotations },
14541502 {"__annotate__" , module_get_annotate , module_set_annotate },
1503+ {"__dict__" , (getter )module_get_dict , NULL },
14551504 {NULL }
14561505};
14571506
@@ -1485,7 +1534,7 @@ PyTypeObject PyModule_Type = {
14851534 0 , /* tp_iter */
14861535 0 , /* tp_iternext */
14871536 module_methods , /* tp_methods */
1488- module_members , /* tp_members */
1537+ 0 , /* tp_members */
14891538 module_getsets , /* tp_getset */
14901539 0 , /* tp_base */
14911540 0 , /* tp_dict */
0 commit comments