[Python-checkins] gh-102251: Explicitly free state for test modules with state in test_import (#105085)

erlend-aasland webhook-mailer at python.org
Wed May 31 17:12:24 EDT 2023


https://github.com/python/cpython/commit/a99b9d911e0f8cb11b3436bdd8eb649b15d01a50
commit: a99b9d911e0f8cb11b3436bdd8eb649b15d01a50
branch: main
author: sunmy2019 <59365878+sunmy2019 at users.noreply.github.com>
committer: erlend-aasland <erlend.aasland at protonmail.com>
date: 2023-05-31T23:12:10+02:00
summary:

gh-102251: Explicitly free state for test modules with state in test_import (#105085)

Co-authored-by: Erlend E. Aasland <erlend.aasland at protonmail.com>

files:
M Lib/test/test_import/__init__.py
M Modules/_testsinglephase.c

diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py
index e2384a08ecaa9..227c912bc8c32 100644
--- a/Lib/test/test_import/__init__.py
+++ b/Lib/test/test_import/__init__.py
@@ -2320,6 +2320,7 @@ def test_variants(self):
         self.add_module_cleanup(name)
         with self.subTest(name):
             loaded = self.load(name)
+            self.addCleanup(loaded.module._clear_module_state)
 
             self.check_common(loaded)
             self.assertIsNot(loaded.snapshot.state_initialized, None)
@@ -2379,14 +2380,19 @@ def test_with_reinit_reloaded(self):
         # Keep a reference around.
         basic = self.load(self.NAME)
 
-        for name in [
-            f'{self.NAME}_with_reinit',  # m_size == 0
-            f'{self.NAME}_with_state',  # m_size > 0
+        for name, has_state in [
+            (f'{self.NAME}_with_reinit', False),  # m_size == 0
+            (f'{self.NAME}_with_state', True),    # m_size > 0
         ]:
             self.add_module_cleanup(name)
-            with self.subTest(name):
+            with self.subTest(name=name, has_state=has_state):
                 loaded = self.load(name)
+                if has_state:
+                    self.addCleanup(loaded.module._clear_module_state)
+
                 reloaded = self.re_load(name, loaded.module)
+                if has_state:
+                    self.addCleanup(reloaded.module._clear_module_state)
 
                 self.check_common(loaded)
                 self.check_common(reloaded)
diff --git a/Modules/_testsinglephase.c b/Modules/_testsinglephase.c
index 8e6973f0b052c..dca7abff89146 100644
--- a/Modules/_testsinglephase.c
+++ b/Modules/_testsinglephase.c
@@ -248,6 +248,25 @@ basic__clear_globals(PyObject *self, PyObject *Py_UNUSED(ignored))
      basic__clear_globals_doc}
 
 
+PyDoc_STRVAR(basic__clear_module_state_doc, "_clear_module_state()\n\
+\n\
+Free the module state and set it to uninitialized.");
+
+static PyObject *
+basic__clear_module_state(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    module_state *state = get_module_state(self);
+    if (state != NULL) {
+        clear_state(state);
+    }
+    Py_RETURN_NONE;
+}
+
+#define _CLEAR_MODULE_STATE_METHODDEF \
+    {"_clear_module_state", basic__clear_module_state, METH_NOARGS, \
+     basic__clear_module_state_doc}
+
+
 /*********************************************/
 /* the _testsinglephase module (and aliases) */
 /*********************************************/
@@ -408,7 +427,7 @@ PyInit__testsinglephase_with_reinit(void)
 /* the _testsinglephase_with_state module */
 /******************************************/
 
-/* This ia less typical of legacy extensions in the wild:
+/* This is less typical of legacy extensions in the wild:
    - single-phase init  (same as _testsinglephase above)
    - has some module state
    - supports repeated initialization
@@ -424,6 +443,7 @@ static PyMethodDef TestMethods_WithState[] = {
     LOOK_UP_SELF_METHODDEF,
     SUM_METHODDEF,
     STATE_INITIALIZED_METHODDEF,
+    _CLEAR_MODULE_STATE_METHODDEF,
     {NULL, NULL}           /* sentinel */
 };
 



More information about the Python-checkins mailing list