@@ -166,6 +166,8 @@ static PyModuleDef embedded_ext = {
166166static PyObject *
167167PyInit_embedded_ext (void )
168168{
169+ // keep this a single-phase initialization module;
170+ // see test_create_module_from_initfunc
169171 return PyModule_Create (& embedded_ext );
170172}
171173
@@ -1894,8 +1896,16 @@ static int test_initconfig_exit(void)
18941896}
18951897
18961898
1899+ int
1900+ extension_module_exec (PyObject * mod )
1901+ {
1902+ return PyModule_AddStringConstant (mod , "exec_slot_ran" , "yes" );
1903+ }
1904+
1905+
18971906static PyModuleDef_Slot extension_slots [] = {
18981907 {Py_mod_gil , Py_MOD_GIL_NOT_USED },
1908+ {Py_mod_exec , extension_module_exec },
18991909 {0 , NULL }
19001910};
19011911
@@ -2214,11 +2224,33 @@ static int test_repeated_init_and_inittab(void)
22142224}
22152225
22162226static PyObject * create_module (PyObject * self , PyObject * spec ) {
2217- return PyImport_CreateModuleFromInitfunc (spec , init_my_test_extension );
2227+ PyObject * name = PyObject_GetAttrString (spec , "name" );
2228+ if (!name ) {
2229+ return NULL ;
2230+ }
2231+ if (PyUnicode_EqualToUTF8 (name , "my_test_extension" )) {
2232+ Py_DECREF (name );
2233+ return PyImport_CreateModuleFromInitfunc (spec , init_my_test_extension );
2234+ }
2235+ if (PyUnicode_EqualToUTF8 (name , "embedded_ext" )) {
2236+ Py_DECREF (name );
2237+ return PyImport_CreateModuleFromInitfunc (spec , PyInit_embedded_ext );
2238+ }
2239+ PyErr_Format (PyExc_LookupError , "static module %R not found" , name );
2240+ Py_DECREF (name );
2241+ return NULL ;
2242+ }
2243+
2244+ static PyObject * exec_module (PyObject * self , PyObject * mod ) {
2245+ if (PyModule_Exec (mod ) < 0 ) {
2246+ return NULL ;
2247+ }
2248+ Py_RETURN_NONE ;
22182249}
22192250
22202251static PyMethodDef create_static_module_methods [] = {
22212252 {"create_module" , create_module , METH_O , NULL },
2253+ {"exec_module" , exec_module , METH_O , NULL },
22222254 {}
22232255};
22242256
@@ -2236,7 +2268,19 @@ PyMODINIT_FUNC PyInit_create_static_module(void) {
22362268
22372269static int test_create_module_from_initfunc (void )
22382270{
2239- wchar_t * argv [] = {PROGRAM_NAME , L"-c" , L"import my_test_extension; print(my_test_extension)" };
2271+ wchar_t * argv [] = {
2272+ PROGRAM_NAME ,
2273+ L"-c" ,
2274+ // Multi-phase initialization
2275+ L"import my_test_extension;"
2276+ L"print(my_test_extension);"
2277+ L"print(f'{my_test_extension.executed=}');"
2278+ L"print(f'{my_test_extension.exec_slot_ran=}');"
2279+ // Single-phase initialization
2280+ L"import embedded_ext;"
2281+ L"print(embedded_ext);"
2282+ L"print(f'{embedded_ext.executed=}');"
2283+ };
22402284 PyConfig config ;
22412285 if (PyImport_AppendInittab ("create_static_module" ,
22422286 & PyInit_create_static_module ) != 0 ) {
@@ -2249,22 +2293,22 @@ static int test_create_module_from_initfunc(void)
22492293 init_from_config_clear (& config );
22502294 int result = PyRun_SimpleString (
22512295 "import sys\n"
2252- "from importlib._bootstrap import spec_from_loader, _call_with_frames_removed\n"
2253- "import _imp\n"
2296+ "from importlib.util import spec_from_loader\n"
22542297 "import create_static_module\n"
22552298 "class StaticExtensionImporter:\n"
22562299 " _ORIGIN = \"static-extension\"\n"
22572300 " @classmethod\n"
22582301 " def find_spec(cls, fullname, path, target=None):\n"
2259- " if fullname == \" my_test_extension\" :\n"
2302+ " if fullname in {' my_test_extension', 'embedded_ext'} :\n"
22602303 " return spec_from_loader(fullname, cls, origin=cls._ORIGIN)\n"
22612304 " return None\n"
22622305 " @staticmethod\n"
22632306 " def create_module(spec):\n"
2264- " return _call_with_frames_removed( create_static_module.create_module, spec)\n"
2307+ " return create_static_module.create_module( spec)\n"
22652308 " @staticmethod\n"
22662309 " def exec_module(module):\n"
2267- " _call_with_frames_removed(_imp.exec_builtin, module)\n"
2310+ " create_static_module.exec_module(module)\n"
2311+ " module.executed = 'yes'\n"
22682312 "sys.meta_path.append(StaticExtensionImporter)\n"
22692313 );
22702314 if (result < 0 ) {
0 commit comments