@@ -2374,6 +2374,58 @@ static int test_repeated_init_and_inittab(void)
23742374 return 0 ;
23752375}
23762376
2377+ // Two different single-phase init functions for the same module name.
2378+ static int cmfi_initfunc_a_calls = 0 ;
2379+ static int cmfi_initfunc_b_calls = 0 ;
2380+
2381+ static PyModuleDef cmfi_same_name_a_def = {
2382+ PyModuleDef_HEAD_INIT ,
2383+ .m_name = "same_name" ,
2384+ .m_size = -1 ,
2385+ };
2386+
2387+ static PyModuleDef cmfi_same_name_b_def = {
2388+ PyModuleDef_HEAD_INIT ,
2389+ .m_name = "same_name" ,
2390+ .m_size = -1 ,
2391+ };
2392+
2393+ static PyObject *
2394+ PyInit_cmfi_same_name_a (void )
2395+ {
2396+ cmfi_initfunc_a_calls ++ ;
2397+ PyObject * mod = PyModule_Create (& cmfi_same_name_a_def );
2398+ if (mod == NULL || PyModule_AddStringConstant (mod , "which" , "A" ) < 0 ) {
2399+ Py_XDECREF (mod );
2400+ return NULL ;
2401+ }
2402+ return mod ;
2403+ }
2404+
2405+ static PyObject *
2406+ PyInit_cmfi_same_name_b (void )
2407+ {
2408+ cmfi_initfunc_b_calls ++ ;
2409+ PyObject * mod = PyModule_Create (& cmfi_same_name_b_def );
2410+ if (mod == NULL || PyModule_AddStringConstant (mod , "which" , "B" ) < 0 ) {
2411+ Py_XDECREF (mod );
2412+ return NULL ;
2413+ }
2414+ return mod ;
2415+ }
2416+
2417+ static PyObject *
2418+ create_same_name_b (PyObject * self , PyObject * spec )
2419+ {
2420+ return PyImport_CreateModuleFromInitfunc (spec , PyInit_cmfi_same_name_b );
2421+ }
2422+
2423+ static PyObject *
2424+ initfunc_calls (PyObject * self , PyObject * Py_UNUSED (args ))
2425+ {
2426+ return Py_BuildValue ("(ii)" , cmfi_initfunc_a_calls , cmfi_initfunc_b_calls );
2427+ }
2428+
23772429// A single-phase init submodule that only knows its short name,
23782430// like pybind11's PYBIND11_MODULE(sp_submod, m) would.
23792431static PyModuleDef cmfi_sp_submod_def = {
@@ -2423,6 +2475,10 @@ create_module(PyObject* self, PyObject* spec)
24232475 Py_DECREF (name );
24242476 return PyImport_CreateModuleFromInitfunc (spec , PyInit_embedded_ext );
24252477 }
2478+ if (PyUnicode_EqualToUTF8 (name , "same_name" )) {
2479+ Py_DECREF (name );
2480+ return PyImport_CreateModuleFromInitfunc (spec , PyInit_cmfi_same_name_a );
2481+ }
24262482 if (PyUnicode_EqualToUTF8 (name , "sp_pkg" )) {
24272483 Py_DECREF (name );
24282484 return PyImport_CreateModuleFromInitfunc (spec , PyInit_cmfi_sp_pkg );
@@ -2447,6 +2503,8 @@ exec_module(PyObject* self, PyObject* mod)
24472503
24482504static PyMethodDef create_static_module_methods [] = {
24492505 {"create_module" , create_module , METH_O , NULL },
2506+ {"create_same_name_b" , create_same_name_b , METH_O , NULL },
2507+ {"initfunc_calls" , initfunc_calls , METH_NOARGS , NULL },
24502508 {"exec_module" , exec_module , METH_O , NULL },
24512509 {NULL }
24522510};
@@ -2478,6 +2536,12 @@ test_create_module_from_initfunc(void)
24782536 L"import embedded_ext;"
24792537 L"print(embedded_ext);"
24802538 L"print(f'{embedded_ext.executed=}');"
2539+ // Same name, different initfuncs: the first one wins
2540+ L"spec = spec_from_loader('same_name', StaticExtensionImporter);"
2541+ L"a = create_static_module.create_module(spec);"
2542+ L"b = create_static_module.create_same_name_b(spec);"
2543+ L"print(f'{a.which=} {b.which=} {a is b=}');"
2544+ L"print(f'{create_static_module.initfunc_calls()=}');"
24812545 // Single-phase submodule whose init only knows its short name
24822546 L"import sp_pkg.sp_submod;"
24832547 L"print(sp_pkg.sp_submod);"
@@ -2510,7 +2574,10 @@ test_create_module_from_initfunc(void)
25102574 " return None\n"
25112575 " @staticmethod\n"
25122576 " def create_module(spec):\n"
2513- " return create_static_module.create_module(spec)\n"
2577+ " mod = create_static_module.create_module(spec)\n"
2578+ " print(f'created {spec.name}: '\n"
2579+ " f'in sys.modules={spec.name in sys.modules}')\n"
2580+ " return mod\n"
25142581 " @staticmethod\n"
25152582 " def exec_module(module):\n"
25162583 " create_static_module.exec_module(module)\n"
0 commit comments