| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Testing module for single-phase initialization of extension modules
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #ifndef Py_BUILD_CORE_BUILTIN
 | 
					
						
							|  |  |  | #  define Py_BUILD_CORE_MODULE 1
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | //#include <time.h>
 | 
					
						
							| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  | #include "Python.h"
 | 
					
						
							|  |  |  | #include "pycore_namespace.h"     // _PyNamespace_New()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | typedef struct { | 
					
						
							|  |  |  |     _PyTime_t initialized; | 
					
						
							|  |  |  |     PyObject *error; | 
					
						
							|  |  |  |     PyObject *int_const; | 
					
						
							|  |  |  |     PyObject *str_const; | 
					
						
							|  |  |  | } module_state; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-15 16:05:07 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | /* Process-global state is only used by _testsinglephase
 | 
					
						
							|  |  |  |    since it's the only one that does not support re-init. */ | 
					
						
							|  |  |  | static struct { | 
					
						
							|  |  |  |     int initialized_count; | 
					
						
							|  |  |  |     module_state module; | 
					
						
							| 
									
										
										
										
											2023-02-15 16:05:07 -07:00
										 |  |  | } global_state = { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define NOT_INITIALIZED -1
 | 
					
						
							|  |  |  |     .initialized_count = NOT_INITIALIZED, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void clear_state(module_state *state); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | clear_global_state(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     clear_state(&global_state.module); | 
					
						
							|  |  |  |     global_state.initialized_count = NOT_INITIALIZED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | static inline module_state * | 
					
						
							|  |  |  | get_module_state(PyObject *module) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyModuleDef *def = PyModule_GetDef(module); | 
					
						
							|  |  |  |     if (def->m_size == -1) { | 
					
						
							|  |  |  |         return &global_state.module; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (def->m_size == 0) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         module_state *state = (module_state*)PyModule_GetState(module); | 
					
						
							|  |  |  |         assert(state != NULL); | 
					
						
							|  |  |  |         return state; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | clear_state(module_state *state) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     state->initialized = 0; | 
					
						
							|  |  |  |     Py_CLEAR(state->error); | 
					
						
							|  |  |  |     Py_CLEAR(state->int_const); | 
					
						
							|  |  |  |     Py_CLEAR(state->str_const); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | _set_initialized(_PyTime_t *initialized) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /* We go strictly monotonic to ensure each time is unique. */ | 
					
						
							|  |  |  |     _PyTime_t prev; | 
					
						
							|  |  |  |     if (_PyTime_GetMonotonicClockWithInfo(&prev, NULL) != 0) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* We do a busy sleep since the interval should be super short. */ | 
					
						
							|  |  |  |     _PyTime_t t; | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |         if (_PyTime_GetMonotonicClockWithInfo(&t, NULL) != 0) { | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } while (t == prev); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *initialized = t; | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | init_state(module_state *state) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(state->initialized == 0 && | 
					
						
							|  |  |  |            state->error == NULL && | 
					
						
							|  |  |  |            state->int_const == NULL && | 
					
						
							|  |  |  |            state->str_const == NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (_set_initialized(&state->initialized) != 0) { | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     assert(state->initialized > 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Add an exception type */ | 
					
						
							|  |  |  |     state->error = PyErr_NewException("_testsinglephase.error", NULL, NULL); | 
					
						
							|  |  |  |     if (state->error == NULL) { | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     state->int_const = PyLong_FromLong(1969); | 
					
						
							|  |  |  |     if (state->int_const == NULL) { | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     state->str_const = PyUnicode_FromString("something different"); | 
					
						
							|  |  |  |     if (state->str_const == NULL) { | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | error: | 
					
						
							|  |  |  |     clear_state(state); | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-15 16:05:07 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | static int | 
					
						
							|  |  |  | init_module(PyObject *module, module_state *state) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (PyModule_AddObjectRef(module, "error", state->error) != 0) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (PyModule_AddObjectRef(module, "int_const", state->int_const) != 0) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (PyModule_AddObjectRef(module, "str_const", state->str_const) != 0) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-02-15 16:05:07 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     double d = _PyTime_AsSecondsDouble(state->initialized); | 
					
						
							|  |  |  |     PyObject *initialized = PyFloat_FromDouble(d); | 
					
						
							|  |  |  |     if (initialized == NULL) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-02-27 09:21:18 -07:00
										 |  |  |     if (PyModule_AddObjectRef(module, "_module_initialized", initialized) != 0) { | 
					
						
							| 
									
										
										
										
											2023-02-15 16:05:07 -07:00
										 |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-27 09:21:18 -07:00
										 |  |  | PyDoc_STRVAR(common_state_initialized_doc, | 
					
						
							|  |  |  | "state_initialized()\n\
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | \n\ | 
					
						
							| 
									
										
										
										
											2023-02-27 09:21:18 -07:00
										 |  |  | Return the seconds-since-epoch when the module state was initialized."); | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2023-02-27 09:21:18 -07:00
										 |  |  | common_state_initialized(PyObject *self, PyObject *Py_UNUSED(ignored)) | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | { | 
					
						
							|  |  |  |     module_state *state = get_module_state(self); | 
					
						
							|  |  |  |     if (state == NULL) { | 
					
						
							|  |  |  |         Py_RETURN_NONE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     double d = _PyTime_AsSecondsDouble(state->initialized); | 
					
						
							|  |  |  |     return PyFloat_FromDouble(d); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-27 09:21:18 -07:00
										 |  |  | #define STATE_INITIALIZED_METHODDEF \
 | 
					
						
							|  |  |  |     {"state_initialized", common_state_initialized, METH_NOARGS, \ | 
					
						
							|  |  |  |      common_state_initialized_doc} | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(common_look_up_self_doc, | 
					
						
							|  |  |  | "look_up_self()\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return the module associated with this module's def.m_base.m_index."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | common_look_up_self(PyObject *self, PyObject *Py_UNUSED(ignored)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyModuleDef *def = PyModule_GetDef(self); | 
					
						
							|  |  |  |     if (def == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return Py_NewRef( | 
					
						
							|  |  |  |             PyState_FindModule(def)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define LOOK_UP_SELF_METHODDEF \
 | 
					
						
							|  |  |  |     {"look_up_self", common_look_up_self, METH_NOARGS, common_look_up_self_doc} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  | /* Function of two integers returning integer */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | PyDoc_STRVAR(common_sum_doc, | 
					
						
							|  |  |  | "sum(i,j)\n\
 | 
					
						
							| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  | \n\ | 
					
						
							|  |  |  | Return the sum of i and j."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | common_sum(PyObject *self, PyObject *args) | 
					
						
							| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  | { | 
					
						
							|  |  |  |     long i, j; | 
					
						
							|  |  |  |     long res; | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  |     if (!PyArg_ParseTuple(args, "ll:sum", &i, &j)) | 
					
						
							| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     res = i + j; | 
					
						
							|  |  |  |     return PyLong_FromLong(res); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | #define SUM_METHODDEF \
 | 
					
						
							|  |  |  |     {"sum", common_sum, METH_VARARGS, common_sum_doc} | 
					
						
							| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | PyDoc_STRVAR(basic_initialized_count_doc, | 
					
						
							|  |  |  | "initialized_count()\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Return how many times the module has been initialized."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | basic_initialized_count(PyObject *self, PyObject *Py_UNUSED(ignored)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(PyModule_GetDef(self)->m_size == -1); | 
					
						
							|  |  |  |     return PyLong_FromLong(global_state.initialized_count); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define INITIALIZED_COUNT_METHODDEF \
 | 
					
						
							| 
									
										
										
										
											2023-02-15 16:05:07 -07:00
										 |  |  |     {"initialized_count", basic_initialized_count, METH_NOARGS, \ | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  |      basic_initialized_count_doc} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-15 16:05:07 -07:00
										 |  |  | PyDoc_STRVAR(basic__clear_globals_doc, | 
					
						
							|  |  |  | "_clear_globals()\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Free all global state and set it to uninitialized."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | basic__clear_globals(PyObject *self, PyObject *Py_UNUSED(ignored)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(PyModule_GetDef(self)->m_size == -1); | 
					
						
							|  |  |  |     clear_global_state(); | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define _CLEAR_GLOBALS_METHODDEF \
 | 
					
						
							|  |  |  |     {"_clear_globals", basic__clear_globals, METH_NOARGS, \ | 
					
						
							|  |  |  |      basic__clear_globals_doc} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | /*********************************************/ | 
					
						
							|  |  |  | /* the _testsinglephase module (and aliases) */ | 
					
						
							|  |  |  | /*********************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* This ia more typical of legacy extensions in the wild:
 | 
					
						
							|  |  |  |    - single-phase init | 
					
						
							|  |  |  |    - no module state | 
					
						
							|  |  |  |    - does not support repeated initialization | 
					
						
							|  |  |  |     (so m_copy is used) | 
					
						
							|  |  |  |    - the module def is cached in _PyRuntime.extensions | 
					
						
							|  |  |  |      (by name/filename) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    Also note that, because the module has single-phase init, | 
					
						
							|  |  |  |    it is cached in interp->module_by_index (using mod->md_def->m_base.m_index). | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | static PyMethodDef TestMethods_Basic[] = { | 
					
						
							|  |  |  |     LOOK_UP_SELF_METHODDEF, | 
					
						
							|  |  |  |     SUM_METHODDEF, | 
					
						
							| 
									
										
										
										
											2023-02-27 09:21:18 -07:00
										 |  |  |     STATE_INITIALIZED_METHODDEF, | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  |     INITIALIZED_COUNT_METHODDEF, | 
					
						
							| 
									
										
										
										
											2023-02-15 16:05:07 -07:00
										 |  |  |     _CLEAR_GLOBALS_METHODDEF, | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  |     {NULL, NULL}           /* sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct PyModuleDef _testsinglephase_basic = { | 
					
						
							| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  |     PyModuleDef_HEAD_INIT, | 
					
						
							|  |  |  |     .m_name = "_testsinglephase", | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  |     .m_doc = PyDoc_STR("Test module _testsinglephase"), | 
					
						
							| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  |     .m_size = -1,  // no module state
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  |     .m_methods = TestMethods_Basic, | 
					
						
							| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | init__testsinglephase_basic(PyModuleDef *def) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (global_state.initialized_count == -1) { | 
					
						
							|  |  |  |         global_state.initialized_count = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *module = PyModule_Create(def); | 
					
						
							|  |  |  |     if (module == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     module_state *state = &global_state.module; | 
					
						
							|  |  |  |     // It may have been set by a previous run or under a different name.
 | 
					
						
							|  |  |  |     clear_state(state); | 
					
						
							|  |  |  |     if (init_state(state) < 0) { | 
					
						
							|  |  |  |         Py_CLEAR(module); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (init_module(module, state) < 0) { | 
					
						
							|  |  |  |         Py_CLEAR(module); | 
					
						
							|  |  |  |         goto finally; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     global_state.initialized_count++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | finally: | 
					
						
							|  |  |  |     return module; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | PyMODINIT_FUNC | 
					
						
							|  |  |  | PyInit__testsinglephase(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  |     return init__testsinglephase_basic(&_testsinglephase_basic); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyMODINIT_FUNC | 
					
						
							|  |  |  | PyInit__testsinglephase_basic_wrapper(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return PyInit__testsinglephase(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyMODINIT_FUNC | 
					
						
							|  |  |  | PyInit__testsinglephase_basic_copy(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     static struct PyModuleDef def = { | 
					
						
							|  |  |  |         PyModuleDef_HEAD_INIT, | 
					
						
							|  |  |  |         .m_name = "_testsinglephase_basic_copy", | 
					
						
							|  |  |  |         .m_doc = PyDoc_STR("Test module _testsinglephase_basic_copy"), | 
					
						
							|  |  |  |         .m_size = -1,  // no module state
 | 
					
						
							|  |  |  |         .m_methods = TestMethods_Basic, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     return init__testsinglephase_basic(&def); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*******************************************/ | 
					
						
							|  |  |  | /* the _testsinglephase_with_reinit module */ | 
					
						
							|  |  |  | /*******************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* This ia less typical of legacy extensions in the wild:
 | 
					
						
							|  |  |  |    - single-phase init  (same as _testsinglephase above) | 
					
						
							|  |  |  |    - no module state | 
					
						
							|  |  |  |    - supports repeated initialization | 
					
						
							|  |  |  |      (so m_copy is not used) | 
					
						
							|  |  |  |    - the module def is not cached in _PyRuntime.extensions | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    At this point most modules would reach for multi-phase init (PEP 489). | 
					
						
							|  |  |  |    However, module state has been around a while (PEP 3121), | 
					
						
							|  |  |  |    and most extensions predate multi-phase init. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    (This module is basically the same as _testsinglephase, | 
					
						
							|  |  |  |     but supports repeated initialization.) | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef TestMethods_Reinit[] = { | 
					
						
							|  |  |  |     LOOK_UP_SELF_METHODDEF, | 
					
						
							|  |  |  |     SUM_METHODDEF, | 
					
						
							| 
									
										
										
										
											2023-02-27 09:21:18 -07:00
										 |  |  |     STATE_INITIALIZED_METHODDEF, | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  |     {NULL, NULL}           /* sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct PyModuleDef _testsinglephase_with_reinit = { | 
					
						
							|  |  |  |     PyModuleDef_HEAD_INIT, | 
					
						
							|  |  |  |     .m_name = "_testsinglephase_with_reinit", | 
					
						
							|  |  |  |     .m_doc = PyDoc_STR("Test module _testsinglephase_with_reinit"), | 
					
						
							|  |  |  |     .m_size = 0, | 
					
						
							|  |  |  |     .m_methods = TestMethods_Reinit, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyMODINIT_FUNC | 
					
						
							|  |  |  | PyInit__testsinglephase_with_reinit(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /* We purposefully do not try PyState_FindModule() first here
 | 
					
						
							|  |  |  |        since we want to check the behavior of re-loading the module. */ | 
					
						
							|  |  |  |     PyObject *module = PyModule_Create(&_testsinglephase_with_reinit); | 
					
						
							| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  |     if (module == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  |     assert(get_module_state(module) == NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     module_state state = {0}; | 
					
						
							|  |  |  |     if (init_state(&state) < 0) { | 
					
						
							|  |  |  |         Py_CLEAR(module); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (init_module(module, &state) < 0) { | 
					
						
							|  |  |  |         Py_CLEAR(module); | 
					
						
							|  |  |  |         goto finally; | 
					
						
							| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | finally: | 
					
						
							|  |  |  |     /* We only needed the module state for setting the module attrs. */ | 
					
						
							|  |  |  |     clear_state(&state); | 
					
						
							|  |  |  |     return module; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /******************************************/ | 
					
						
							|  |  |  | /* the _testsinglephase_with_state module */ | 
					
						
							|  |  |  | /******************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* This ia less typical of legacy extensions in the wild:
 | 
					
						
							|  |  |  |    - single-phase init  (same as _testsinglephase above) | 
					
						
							|  |  |  |    - has some module state | 
					
						
							|  |  |  |    - supports repeated initialization | 
					
						
							|  |  |  |      (so m_copy is not used) | 
					
						
							|  |  |  |    - the module def is not cached in _PyRuntime.extensions | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    At this point most modules would reach for multi-phase init (PEP 489). | 
					
						
							|  |  |  |    However, module state has been around a while (PEP 3121), | 
					
						
							|  |  |  |    and most extensions predate multi-phase init. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef TestMethods_WithState[] = { | 
					
						
							|  |  |  |     LOOK_UP_SELF_METHODDEF, | 
					
						
							|  |  |  |     SUM_METHODDEF, | 
					
						
							| 
									
										
										
										
											2023-02-27 09:21:18 -07:00
										 |  |  |     STATE_INITIALIZED_METHODDEF, | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  |     {NULL, NULL}           /* sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct PyModuleDef _testsinglephase_with_state = { | 
					
						
							|  |  |  |     PyModuleDef_HEAD_INIT, | 
					
						
							|  |  |  |     .m_name = "_testsinglephase_with_state", | 
					
						
							|  |  |  |     .m_doc = PyDoc_STR("Test module _testsinglephase_with_state"), | 
					
						
							|  |  |  |     .m_size = sizeof(module_state), | 
					
						
							|  |  |  |     .m_methods = TestMethods_WithState, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyMODINIT_FUNC | 
					
						
							|  |  |  | PyInit__testsinglephase_with_state(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /* We purposefully do not try PyState_FindModule() first here
 | 
					
						
							|  |  |  |        since we want to check the behavior of re-loading the module. */ | 
					
						
							|  |  |  |     PyObject *module = PyModule_Create(&_testsinglephase_with_state); | 
					
						
							|  |  |  |     if (module == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  |     module_state *state = get_module_state(module); | 
					
						
							|  |  |  |     assert(state != NULL); | 
					
						
							|  |  |  |     if (init_state(state) < 0) { | 
					
						
							|  |  |  |         Py_CLEAR(module); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  |     if (init_module(module, state) < 0) { | 
					
						
							|  |  |  |         clear_state(state); | 
					
						
							|  |  |  |         Py_CLEAR(module); | 
					
						
							|  |  |  |         goto finally; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 14:26:03 -07:00
										 |  |  | finally: | 
					
						
							|  |  |  |     return module; | 
					
						
							| 
									
										
										
										
											2022-11-08 09:58:11 -07:00
										 |  |  | } |