• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* Testing module for single-phase initialization of extension modules
3 
4 This file contains several distinct modules, meaning each as its own name
5 and its own init function (PyInit_...).  The default import system will
6 only find the one matching the filename: _testsinglephase.  To load the
7 others you must do so manually.  For example:
8 
9 ```python
10 name = '_testsinglephase_base_wrapper'
11 filename = _testsinglephase.__file__
12 loader = importlib.machinery.ExtensionFileLoader(name, filename)
13 spec = importlib.util.spec_from_file_location(name, filename, loader=loader)
14 mod = importlib._bootstrap._load(spec)
15 loader.exec_module(module)
16 sys.modules[modname] = module
17 ```
18 
19 (The last two lines are just for completeness.)
20 
21 Here are the modules:
22 
23 * _testsinglephase
24    * def: _testsinglephase_basic,
25       * m_name: "_testsinglephase"
26       * m_size: -1
27    * state
28       * process-global
29          * <int> initialized_count  (default to -1; will never be 0)
30          * <module_state> module  (see module state below)
31       * module state: no
32       * initial __dict__: see common initial __dict__ below
33    * init function
34       1. create module
35       2. clear <global>.module
36       3. initialize <global>.module: see module state below
37       4. initialize module: set initial __dict__
38       5. increment <global>.initialized_count
39    * functions
40       * (3 common, see below)
41       * initialized_count() - return <global>.module.initialized_count
42    * import system
43       * caches
44          * global extensions cache: yes
45          * def.m_base.m_copy: yes
46          * def.m_base.m_init: no
47          * per-interpreter cache: yes  (all single-phase init modules)
48       * load in main interpreter
49          * initial  (not already in global cache)
50             1. get init function from shared object file
51             2. run init function
52             3. copy __dict__ into def.m_base.m_copy
53             4. set entry in global cache
54             5. set entry in per-interpreter cache
55             6. set entry in sys.modules
56          * reload  (already in sys.modules)
57             1. get def from global cache
58             2. get module from sys.modules
59             3. update module with contents of def.m_base.m_copy
60          * already loaded in other interpreter  (already in global cache)
61             * same as reload, but create new module and update *it*
62          * not in any sys.modules, still in global cache
63             * same as already loaded
64       * load in legacy (non-isolated) interpreter
65          * same as main interpreter
66       * unload: never  (all single-phase init modules)
67 * _testsinglephase_basic_wrapper
68    * identical to _testsinglephase except module name
69 * _testsinglephase_basic_copy
70    * def: static local variable in init function
71       * m_name: "_testsinglephase_basic_copy"
72       * m_size: -1
73    * state: same as _testsinglephase
74    * init function: same as _testsinglephase
75    * functions: same as _testsinglephase
76    * import system: same as _testsinglephase
77 * _testsinglephase_with_reinit
78    * def: _testsinglephase_with_reinit,
79       * m_name: "_testsinglephase_with_reinit"
80       * m_size: 0
81    * state
82       * process-global state: no
83       * module state: no
84       * initial __dict__: see common initial __dict__ below
85    * init function
86       1. create module
87       2. initialize temporary module state (local var): see module state below
88       3. initialize module: set initial __dict__
89    * functions: see common functions below
90    * import system
91       * caches
92          * global extensions cache: only if loaded in main interpreter
93          * def.m_base.m_copy: no
94          * def.m_base.m_init: only if loaded in the main interpreter
95          * per-interpreter cache: yes  (all single-phase init modules)
96       * load in main interpreter
97          * initial  (not already in global cache)
98             * (same as _testsinglephase except step 3)
99             1. get init function from shared object file
100             2. run init function
101             3. set def.m_base.m_init to the init function
102             4. set entry in global cache
103             5. set entry in per-interpreter cache
104             6. set entry in sys.modules
105          * reload  (already in sys.modules)
106             1. get def from global cache
107             2. call def->m_base.m_init to get a new module object
108             3. replace the existing module in sys.modules
109          * already loaded in other interpreter  (already in global cache)
110             * same as reload (since will only be in cache for main interp)
111          * not in any sys.modules, still in global cache
112             * same as already loaded
113       * load in legacy (non-isolated) interpreter
114          * initial  (not already in global cache)
115             * (same as main interpreter except skip steps 3 & 4 there)
116             1. get init function from shared object file
117             2. run init function
118             ...
119             5. set entry in per-interpreter cache
120             6. set entry in sys.modules
121          * reload  (already in sys.modules)
122             * same as initial  (load from scratch)
123          * already loaded in other interpreter  (already in global cache)
124             * same as initial  (load from scratch)
125          * not in any sys.modules, still in global cache
126             * same as initial  (load from scratch)
127       * unload: never  (all single-phase init modules)
128 * _testsinglephase_with_state
129    * def: _testsinglephase_with_state,
130       * m_name: "_testsinglephase_with_state"
131       * m_size: sizeof(module_state)
132    * state
133       * process-global: no
134       * module state: see module state below
135       * initial __dict__: see common initial __dict__ below
136    * init function
137       1. create module
138       3. initialize module state: see module state below
139       4. initialize module: set initial __dict__
140       5. increment <global>.initialized_count
141    * functions: see common functions below
142    * import system: same as _testsinglephase_basic_copy
143 * _testsinglephase_check_cache_first
144    * def: _testsinglepahse_check_cache_first
145       * m_name: "_testsinglephase_check_cache_first"
146       * m_size: -1
147    * state: none
148    * init function:
149       * tries PyState_FindModule() first
150       * otherwise creates empty module
151    * functions: none
152    * import system: same as _testsinglephase
153 * _testsinglephase_with_reinit_check_cache_first
154    * def: _testsinglepahse_with_reinit_check_cache_first
155       * m_name: "_testsinglephase_with_reinit_check_cache_first"
156       * m_size: 0
157    * state: none
158    * init function: same as _testsinglephase_check_cache_first
159    * functions: none
160    * import system: same as _testsinglephase_with_reinit
161 * _testsinglephase_with_state_check_cache_first
162    * def: _testsinglepahse_with_state_check_cache_first
163       * m_name: "_testsinglephase_with_state_check_cache_first"
164       * m_size: 42
165    * state: none
166    * init function: same as _testsinglephase_check_cache_first
167    * functions: none
168    * import system: same as _testsinglephase_with_state
169 
170 * _testsinglephase_circular
171    Regression test for gh-123880.
172    Does not have the common attributes & methods.
173    See test_singlephase_circular test.test_import.SinglephaseInitTests.
174 
175 Module state:
176 
177 * fields
178    * <PyTime_t> initialized - when the module was first initialized
179    * <PyObject> *error
180    * <PyObject> *int_const
181    * <PyObject> *str_const
182 * initialization
183    1. set state.initialized to the current time
184    2. set state.error to a new exception class
185    3. set state->int_const to int(1969)
186    4. set state->str_const to "something different"
187 
188 Common initial __dict__:
189 
190 * error: state.error
191 * int_const: state.int_const
192 * str_const: state.str_const
193 * _module_initialized: state.initialized
194 
195 Common functions:
196 
197 * look_up_self() - return the module from the per-interpreter "by-index" cache
198 * sum() - return a + b
199 * state_initialized() - return state->initialized (or None if m_size == 0)
200 
201 See Python/import.c, especially the long comments, for more about
202 single-phase init modules.
203 */
204 
205 #ifndef Py_BUILD_CORE_BUILTIN
206 #  define Py_BUILD_CORE_MODULE 1
207 #endif
208 
209 //#include <time.h>
210 #include "Python.h"
211 #include "pycore_namespace.h"     // _PyNamespace_New()
212 
213 
214 typedef struct {
215     PyTime_t initialized;
216     PyObject *error;
217     PyObject *int_const;
218     PyObject *str_const;
219 } module_state;
220 
221 
222 /* Process-global state is only used by _testsinglephase
223    since it's the only one that does not support re-init. */
224 static struct {
225     int initialized_count;
226     module_state module;
227 } global_state = {
228 
229 #define NOT_INITIALIZED -1
230     .initialized_count = NOT_INITIALIZED,
231 };
232 
233 static void clear_state(module_state *state);
234 
235 static void
clear_global_state(void)236 clear_global_state(void)
237 {
238     clear_state(&global_state.module);
239     global_state.initialized_count = NOT_INITIALIZED;
240 }
241 
242 
243 static inline module_state *
get_module_state(PyObject * module)244 get_module_state(PyObject *module)
245 {
246     PyModuleDef *def = PyModule_GetDef(module);
247     if (def->m_size == -1) {
248         return &global_state.module;
249     }
250     else if (def->m_size == 0) {
251         return NULL;
252     }
253     else {
254         module_state *state = (module_state*)PyModule_GetState(module);
255         assert(state != NULL);
256         return state;
257     }
258 }
259 
260 static void
clear_state(module_state * state)261 clear_state(module_state *state)
262 {
263     state->initialized = 0;
264     Py_CLEAR(state->error);
265     Py_CLEAR(state->int_const);
266     Py_CLEAR(state->str_const);
267 }
268 
269 static int
_set_initialized(PyTime_t * initialized)270 _set_initialized(PyTime_t *initialized)
271 {
272     /* We go strictly monotonic to ensure each time is unique. */
273     PyTime_t prev;
274     if (PyTime_Monotonic(&prev) != 0) {
275         return -1;
276     }
277     /* We do a busy sleep since the interval should be super short. */
278     PyTime_t t;
279     do {
280         if (PyTime_Monotonic(&t) != 0) {
281             return -1;
282         }
283     } while (t == prev);
284 
285     *initialized = t;
286     return 0;
287 }
288 
289 static int
init_state(module_state * state)290 init_state(module_state *state)
291 {
292     assert(state->initialized == 0 &&
293            state->error == NULL &&
294            state->int_const == NULL &&
295            state->str_const == NULL);
296 
297     if (_set_initialized(&state->initialized) != 0) {
298         goto error;
299     }
300     assert(state->initialized > 0);
301 
302     /* Add an exception type */
303     state->error = PyErr_NewException("_testsinglephase.error", NULL, NULL);
304     if (state->error == NULL) {
305         goto error;
306     }
307 
308     state->int_const = PyLong_FromLong(1969);
309     if (state->int_const == NULL) {
310         goto error;
311     }
312 
313     state->str_const = PyUnicode_FromString("something different");
314     if (state->str_const == NULL) {
315         goto error;
316     }
317 
318     return 0;
319 
320 error:
321     clear_state(state);
322     return -1;
323 }
324 
325 
326 static int
init_module(PyObject * module,module_state * state)327 init_module(PyObject *module, module_state *state)
328 {
329     if (PyModule_AddObjectRef(module, "error", state->error) != 0) {
330         return -1;
331     }
332     if (PyModule_AddObjectRef(module, "int_const", state->int_const) != 0) {
333         return -1;
334     }
335     if (PyModule_AddObjectRef(module, "str_const", state->str_const) != 0) {
336         return -1;
337     }
338 
339     double d = PyTime_AsSecondsDouble(state->initialized);
340     if (PyModule_Add(module, "_module_initialized", PyFloat_FromDouble(d)) < 0) {
341         return -1;
342     }
343 
344     return 0;
345 }
346 
347 
348 PyDoc_STRVAR(common_state_initialized_doc,
349 "state_initialized()\n\
350 \n\
351 Return the seconds-since-epoch when the module state was initialized.");
352 
353 static PyObject *
common_state_initialized(PyObject * self,PyObject * Py_UNUSED (ignored))354 common_state_initialized(PyObject *self, PyObject *Py_UNUSED(ignored))
355 {
356     module_state *state = get_module_state(self);
357     if (state == NULL) {
358         Py_RETURN_NONE;
359     }
360     double d = PyTime_AsSecondsDouble(state->initialized);
361     return PyFloat_FromDouble(d);
362 }
363 
364 #define STATE_INITIALIZED_METHODDEF \
365     {"state_initialized", common_state_initialized, METH_NOARGS, \
366      common_state_initialized_doc}
367 
368 
369 PyDoc_STRVAR(common_look_up_self_doc,
370 "look_up_self()\n\
371 \n\
372 Return the module associated with this module's def.m_base.m_index.");
373 
374 static PyObject *
common_look_up_self(PyObject * self,PyObject * Py_UNUSED (ignored))375 common_look_up_self(PyObject *self, PyObject *Py_UNUSED(ignored))
376 {
377     PyModuleDef *def = PyModule_GetDef(self);
378     if (def == NULL) {
379         return NULL;
380     }
381     return Py_NewRef(
382             PyState_FindModule(def));
383 }
384 
385 #define LOOK_UP_SELF_METHODDEF \
386     {"look_up_self", common_look_up_self, METH_NOARGS, common_look_up_self_doc}
387 
388 
389 /* Function of two integers returning integer */
390 
391 PyDoc_STRVAR(common_sum_doc,
392 "sum(i,j)\n\
393 \n\
394 Return the sum of i and j.");
395 
396 static PyObject *
common_sum(PyObject * self,PyObject * args)397 common_sum(PyObject *self, PyObject *args)
398 {
399     long i, j;
400     long res;
401     if (!PyArg_ParseTuple(args, "ll:sum", &i, &j))
402         return NULL;
403     res = i + j;
404     return PyLong_FromLong(res);
405 }
406 
407 #define SUM_METHODDEF \
408     {"sum", common_sum, METH_VARARGS, common_sum_doc}
409 
410 
411 PyDoc_STRVAR(basic_initialized_count_doc,
412 "initialized_count()\n\
413 \n\
414 Return how many times the module has been initialized.");
415 
416 static PyObject *
basic_initialized_count(PyObject * self,PyObject * Py_UNUSED (ignored))417 basic_initialized_count(PyObject *self, PyObject *Py_UNUSED(ignored))
418 {
419     assert(PyModule_GetDef(self)->m_size == -1);
420     return PyLong_FromLong(global_state.initialized_count);
421 }
422 
423 #define INITIALIZED_COUNT_METHODDEF \
424     {"initialized_count", basic_initialized_count, METH_NOARGS, \
425      basic_initialized_count_doc}
426 
427 
428 PyDoc_STRVAR(basic__clear_globals_doc,
429 "_clear_globals()\n\
430 \n\
431 Free all global state and set it to uninitialized.");
432 
433 static PyObject *
basic__clear_globals(PyObject * self,PyObject * Py_UNUSED (ignored))434 basic__clear_globals(PyObject *self, PyObject *Py_UNUSED(ignored))
435 {
436     assert(PyModule_GetDef(self)->m_size == -1);
437     clear_global_state();
438     Py_RETURN_NONE;
439 }
440 
441 #define _CLEAR_GLOBALS_METHODDEF \
442     {"_clear_globals", basic__clear_globals, METH_NOARGS, \
443      basic__clear_globals_doc}
444 
445 
446 PyDoc_STRVAR(basic__clear_module_state_doc, "_clear_module_state()\n\
447 \n\
448 Free the module state and set it to uninitialized.");
449 
450 static PyObject *
basic__clear_module_state(PyObject * self,PyObject * Py_UNUSED (ignored))451 basic__clear_module_state(PyObject *self, PyObject *Py_UNUSED(ignored))
452 {
453     module_state *state = get_module_state(self);
454     if (state != NULL) {
455         clear_state(state);
456     }
457     Py_RETURN_NONE;
458 }
459 
460 #define _CLEAR_MODULE_STATE_METHODDEF \
461     {"_clear_module_state", basic__clear_module_state, METH_NOARGS, \
462      basic__clear_module_state_doc}
463 
464 
465 /*********************************************/
466 /* the _testsinglephase module (and aliases) */
467 /*********************************************/
468 
469 /* This ia more typical of legacy extensions in the wild:
470    - single-phase init
471    - no module state
472    - does not support repeated initialization
473     (so m_copy is used)
474    - the module def is cached in _PyRuntime.extensions
475      (by name/filename)
476 
477    Also note that, because the module has single-phase init,
478    it is cached in interp->module_by_index (using mod->md_def->m_base.m_index).
479  */
480 
481 static PyMethodDef TestMethods_Basic[] = {
482     LOOK_UP_SELF_METHODDEF,
483     SUM_METHODDEF,
484     STATE_INITIALIZED_METHODDEF,
485     INITIALIZED_COUNT_METHODDEF,
486     _CLEAR_GLOBALS_METHODDEF,
487     {NULL, NULL}           /* sentinel */
488 };
489 
490 static struct PyModuleDef _testsinglephase_basic = {
491     PyModuleDef_HEAD_INIT,
492     .m_name = "_testsinglephase",
493     .m_doc = PyDoc_STR("Test module _testsinglephase"),
494     .m_size = -1,  // no module state
495     .m_methods = TestMethods_Basic,
496 };
497 
498 static PyObject *
init__testsinglephase_basic(PyModuleDef * def)499 init__testsinglephase_basic(PyModuleDef *def)
500 {
501     if (global_state.initialized_count == -1) {
502         global_state.initialized_count = 0;
503     }
504 
505     PyObject *module = PyModule_Create(def);
506     if (module == NULL) {
507         return NULL;
508     }
509 #ifdef Py_GIL_DISABLED
510     PyUnstable_Module_SetGIL(module, Py_MOD_GIL_NOT_USED);
511 #endif
512 
513     module_state *state = &global_state.module;
514     // It may have been set by a previous run or under a different name.
515     clear_state(state);
516     if (init_state(state) < 0) {
517         Py_CLEAR(module);
518         return NULL;
519     }
520 
521     if (init_module(module, state) < 0) {
522         Py_CLEAR(module);
523         goto finally;
524     }
525 
526     global_state.initialized_count++;
527 
528 finally:
529     return module;
530 }
531 
532 PyMODINIT_FUNC
PyInit__testsinglephase(void)533 PyInit__testsinglephase(void)
534 {
535     return init__testsinglephase_basic(&_testsinglephase_basic);
536 }
537 
538 
539 PyMODINIT_FUNC
PyInit__testsinglephase_basic_wrapper(void)540 PyInit__testsinglephase_basic_wrapper(void)
541 {
542     return PyInit__testsinglephase();
543 }
544 
545 
546 PyMODINIT_FUNC
PyInit__testsinglephase_basic_copy(void)547 PyInit__testsinglephase_basic_copy(void)
548 {
549     static struct PyModuleDef def = {
550         PyModuleDef_HEAD_INIT,
551         .m_name = "_testsinglephase_basic_copy",
552         .m_doc = PyDoc_STR("Test module _testsinglephase_basic_copy"),
553         .m_size = -1,  // no module state
554         .m_methods = TestMethods_Basic,
555     };
556     return init__testsinglephase_basic(&def);
557 }
558 
559 
560 /*******************************************/
561 /* the _testsinglephase_with_reinit module */
562 /*******************************************/
563 
564 /* This ia less typical of legacy extensions in the wild:
565    - single-phase init  (same as _testsinglephase above)
566    - no module state
567    - supports repeated initialization
568      (so m_copy is not used)
569    - the module def is not cached in _PyRuntime.extensions
570 
571    At this point most modules would reach for multi-phase init (PEP 489).
572    However, module state has been around a while (PEP 3121),
573    and most extensions predate multi-phase init.
574 
575    (This module is basically the same as _testsinglephase,
576     but supports repeated initialization.)
577  */
578 
579 static PyMethodDef TestMethods_Reinit[] = {
580     LOOK_UP_SELF_METHODDEF,
581     SUM_METHODDEF,
582     STATE_INITIALIZED_METHODDEF,
583     {NULL, NULL}           /* sentinel */
584 };
585 
586 static struct PyModuleDef _testsinglephase_with_reinit = {
587     PyModuleDef_HEAD_INIT,
588     .m_name = "_testsinglephase_with_reinit",
589     .m_doc = PyDoc_STR("Test module _testsinglephase_with_reinit"),
590     .m_size = 0,
591     .m_methods = TestMethods_Reinit,
592 };
593 
594 PyMODINIT_FUNC
PyInit__testsinglephase_with_reinit(void)595 PyInit__testsinglephase_with_reinit(void)
596 {
597     /* We purposefully do not try PyState_FindModule() first here
598        since we want to check the behavior of re-loading the module. */
599     PyObject *module = PyModule_Create(&_testsinglephase_with_reinit);
600     if (module == NULL) {
601         return NULL;
602     }
603 #ifdef Py_GIL_DISABLED
604     PyUnstable_Module_SetGIL(module, Py_MOD_GIL_NOT_USED);
605 #endif
606 
607     assert(get_module_state(module) == NULL);
608 
609     module_state state = {0};
610     if (init_state(&state) < 0) {
611         Py_CLEAR(module);
612         return NULL;
613     }
614 
615     if (init_module(module, &state) < 0) {
616         Py_CLEAR(module);
617         goto finally;
618     }
619 
620 finally:
621     /* We only needed the module state for setting the module attrs. */
622     clear_state(&state);
623     return module;
624 }
625 
626 
627 /******************************************/
628 /* the _testsinglephase_with_state module */
629 /******************************************/
630 
631 /* This is less typical of legacy extensions in the wild:
632    - single-phase init  (same as _testsinglephase above)
633    - has some module state
634    - supports repeated initialization
635      (so m_copy is not used)
636    - the module def is not cached in _PyRuntime.extensions
637 
638    At this point most modules would reach for multi-phase init (PEP 489).
639    However, module state has been around a while (PEP 3121),
640    and most extensions predate multi-phase init.
641  */
642 
643 static PyMethodDef TestMethods_WithState[] = {
644     LOOK_UP_SELF_METHODDEF,
645     SUM_METHODDEF,
646     STATE_INITIALIZED_METHODDEF,
647     _CLEAR_MODULE_STATE_METHODDEF,
648     {NULL, NULL}           /* sentinel */
649 };
650 
651 static struct PyModuleDef _testsinglephase_with_state = {
652     PyModuleDef_HEAD_INIT,
653     .m_name = "_testsinglephase_with_state",
654     .m_doc = PyDoc_STR("Test module _testsinglephase_with_state"),
655     .m_size = sizeof(module_state),
656     .m_methods = TestMethods_WithState,
657 };
658 
659 PyMODINIT_FUNC
PyInit__testsinglephase_with_state(void)660 PyInit__testsinglephase_with_state(void)
661 {
662     /* We purposefully do not try PyState_FindModule() first here
663        since we want to check the behavior of re-loading the module. */
664     PyObject *module = PyModule_Create(&_testsinglephase_with_state);
665     if (module == NULL) {
666         return NULL;
667     }
668 #ifdef Py_GIL_DISABLED
669     PyUnstable_Module_SetGIL(module, Py_MOD_GIL_NOT_USED);
670 #endif
671 
672     module_state *state = get_module_state(module);
673     assert(state != NULL);
674     if (init_state(state) < 0) {
675         Py_CLEAR(module);
676         return NULL;
677     }
678 
679     if (init_module(module, state) < 0) {
680         clear_state(state);
681         Py_CLEAR(module);
682         goto finally;
683     }
684 
685 finally:
686     return module;
687 }
688 
689 
690 /****************************************************/
691 /* the _testsinglephase_*_check_cache_first modules */
692 /****************************************************/
693 
694 /* Each of these modules should only be freshly loaded.  That means
695    clearing the caches and each module def's m_base after each load. */
696 
697 static struct PyModuleDef _testsinglephase_check_cache_first = {
698     PyModuleDef_HEAD_INIT,
699     .m_name = "_testsinglephase_check_cache_first",
700     .m_doc = PyDoc_STR("Test module _testsinglephase_check_cache_first"),
701     .m_size = -1,  // no module state
702 };
703 
704 PyMODINIT_FUNC
PyInit__testsinglephase_check_cache_first(void)705 PyInit__testsinglephase_check_cache_first(void)
706 {
707     assert(_testsinglephase_check_cache_first.m_base.m_index == 0);
708     PyObject *mod = PyState_FindModule(&_testsinglephase_check_cache_first);
709     if (mod != NULL) {
710         return Py_NewRef(mod);
711     }
712     return PyModule_Create(&_testsinglephase_check_cache_first);
713 }
714 
715 
716 static struct PyModuleDef _testsinglephase_with_reinit_check_cache_first = {
717     PyModuleDef_HEAD_INIT,
718     .m_name = "_testsinglephase_with_reinit_check_cache_first",
719     .m_doc = PyDoc_STR("Test module _testsinglephase_with_reinit_check_cache_first"),
720     .m_size = 0,  // no module state
721 };
722 
723 PyMODINIT_FUNC
PyInit__testsinglephase_with_reinit_check_cache_first(void)724 PyInit__testsinglephase_with_reinit_check_cache_first(void)
725 {
726     assert(_testsinglephase_with_reinit_check_cache_first.m_base.m_index == 0);
727     PyObject *mod = PyState_FindModule(&_testsinglephase_with_reinit_check_cache_first);
728     if (mod != NULL) {
729         return Py_NewRef(mod);
730     }
731     return PyModule_Create(&_testsinglephase_with_reinit_check_cache_first);
732 }
733 
734 
735 static struct PyModuleDef _testsinglephase_with_state_check_cache_first = {
736     PyModuleDef_HEAD_INIT,
737     .m_name = "_testsinglephase_with_state_check_cache_first",
738     .m_doc = PyDoc_STR("Test module _testsinglephase_with_state_check_cache_first"),
739     .m_size = 42,  // not used
740 };
741 
742 PyMODINIT_FUNC
PyInit__testsinglephase_with_state_check_cache_first(void)743 PyInit__testsinglephase_with_state_check_cache_first(void)
744 {
745     assert(_testsinglephase_with_state_check_cache_first.m_base.m_index == 0);
746     PyObject *mod = PyState_FindModule(&_testsinglephase_with_state_check_cache_first);
747     if (mod != NULL) {
748         return Py_NewRef(mod);
749     }
750     return PyModule_Create(&_testsinglephase_with_state_check_cache_first);
751 }
752 
753 
754 /****************************************/
755 /* the _testsinglephase_circular module */
756 /****************************************/
757 
758 static PyObject *static_module_circular;
759 
760 static PyObject *
circularmod_clear_static_var(PyObject * self,PyObject * arg)761 circularmod_clear_static_var(PyObject *self, PyObject *arg)
762 {
763     PyObject *result = static_module_circular;
764     static_module_circular = NULL;
765     return result;
766 }
767 
768 static struct PyModuleDef _testsinglephase_circular = {
769     PyModuleDef_HEAD_INIT,
770     .m_name = "_testsinglephase_circular",
771     .m_doc = PyDoc_STR("Test module _testsinglephase_circular"),
772     .m_methods = (PyMethodDef[]) {
773         {"clear_static_var", circularmod_clear_static_var, METH_NOARGS,
774          "Clear the static variable and return its previous value."},
775         {NULL, NULL}           /* sentinel */
776     }
777 };
778 
779 PyMODINIT_FUNC
PyInit__testsinglephase_circular(void)780 PyInit__testsinglephase_circular(void)
781 {
782     if (!static_module_circular) {
783         static_module_circular = PyModule_Create(&_testsinglephase_circular);
784         if (!static_module_circular) {
785             return NULL;
786         }
787     }
788     static const char helper_mod_name[] = (
789         "test.test_import.data.circular_imports.singlephase");
790     PyObject *helper_mod = PyImport_ImportModule(helper_mod_name);
791     Py_XDECREF(helper_mod);
792     if (!helper_mod) {
793         return NULL;
794     }
795     if(PyModule_AddStringConstant(static_module_circular,
796                                   "helper_mod_name",
797                                   helper_mod_name) < 0) {
798         return NULL;
799     }
800     return Py_NewRef(static_module_circular);
801 }
802