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