https://github.com/python/cpython/commit/a89de4b230f3003280e44546de8713e604d4c4eb
commit: a89de4b230f3003280e44546de8713e604d4c4eb
branch: 3.15
author: Miss Islington (bot) <[email protected]>
committer: sobolevn <[email protected]>
date: 2026-06-26T14:03:29Z
summary:

[3.15] gh-152236: Fix skips on `_testcapi.set_nomemory` tests (GH-152253) 
(#152281)

gh-152236: Fix skips on `_testcapi.set_nomemory` tests (GH-152253)
(cherry picked from commit 1cbe460eb6c5f40980463f381b3096c92320ff84)

Co-authored-by: sobolevn <[email protected]>

files:
M Lib/test/support/__init__.py
M Lib/test/test_atexit.py
M Lib/test/test_capi/test_mem.py
M Lib/test/test_class.py
M Lib/test/test_exceptions.py
M Lib/test/test_interpreters/test_stress.py
M Lib/test/test_list.py
M Lib/test/test_repl.py
M Lib/test/test_weakref.py

diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index ebbce63852c4b85..65bf3e7feb837f4 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -35,7 +35,7 @@
     "requires_gil_enabled", "requires_linux_version", "requires_mac_ver",
     "check_syntax_error",
     "requires_gzip", "requires_bz2", "requires_lzma", "requires_zstd",
-    "bigmemtest", "bigaddrspacetest", "cpython_only", "get_attribute",
+    "bigmemtest", "nomemtest", "bigaddrspacetest", "cpython_only", 
"get_attribute",
     "requires_IEEE_754", "requires_zlib",
     "has_fork_support", "requires_fork",
     "has_subprocess_support", "requires_subprocess",
@@ -1314,6 +1314,22 @@ def wrapper(self):
         return wrapper
     return decorator
 
+def nomemtest(f):
+    """Check that we can use this test with `_testcapi.set_nomemory`."""
+    from .import_helper import import_module
+
+    @functools.wraps(f)
+    def internal(*args, **kwargs):
+        import_module('_testcapi')
+        return f(*args, **kwargs)
+
+    return unittest.skipIf(
+        # Python built with Py_TRACE_REFS fail with a fatal error in
+        # _PyRefchain_Trace() on memory allocation error.
+        Py_TRACE_REFS,
+        'cannot test Py_TRACE_REFS build',
+    )(cpython_only(internal))
+
 def bigaddrspacetest(f):
     """Decorator for tests that fill the address space."""
     def wrapper(self):
diff --git a/Lib/test/test_atexit.py b/Lib/test/test_atexit.py
index 8256ff183f28c9c..33c37648da31fc7 100644
--- a/Lib/test/test_atexit.py
+++ b/Lib/test/test_atexit.py
@@ -191,9 +191,7 @@ def callback():
         self.assertEqual(os.read(r, len(expected)), expected)
         os.close(r)
 
-    # Python built with Py_TRACE_REFS fail with a fatal error in
-    # _PyRefchain_Trace() on memory allocation error.
-    @unittest.skipIf(support.Py_TRACE_REFS, 'cannot test Py_TRACE_REFS build')
+    @support.nomemtest
     def test_atexit_with_low_memory(self):
         # gh-140080: Test that setting low memory after registering an atexit
         # callback doesn't cause an infinite loop during finalization.
diff --git a/Lib/test/test_capi/test_mem.py b/Lib/test/test_capi/test_mem.py
index 5035b2b4829bf64..66ab072733e17bd 100644
--- a/Lib/test/test_capi/test_mem.py
+++ b/Lib/test/test_capi/test_mem.py
@@ -117,9 +117,7 @@ def test_pyobject_forbidden_bytes_is_freed(self):
     def test_pyobject_freed_is_freed(self):
         self.check_pyobject_is_freed('check_pyobject_freed_is_freed')
 
-    # Python built with Py_TRACE_REFS fail with a fatal error in
-    # _PyRefchain_Trace() on memory allocation error.
-    @unittest.skipIf(support.Py_TRACE_REFS, 'cannot test Py_TRACE_REFS build')
+    @support.nomemtest
     def test_set_nomemory(self):
         code = """if 1:
             import _testcapi
diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py
index 64222555166a2e3..e401941c6d69700 100644
--- a/Lib/test/test_class.py
+++ b/Lib/test/test_class.py
@@ -449,7 +449,6 @@ def __delattr__(self, *args):
 
     def testHasAttrString(self):
         import sys
-        from test.support import import_helper
         _testlimitedcapi = import_helper.import_module('_testlimitedcapi')
 
         class A:
@@ -1013,11 +1012,8 @@ class C:
         C.a = X()
         C.a = X()
 
-    @cpython_only
+    @support.nomemtest
     def test_detach_materialized_dict_no_memory(self):
-        # Skip test if _testcapi is not available:
-        import_helper.import_module('_testcapi')
-
         code = """if 1:
             import test.support
             import _testcapi
diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py
index df7a04273b9b41c..cc7faef93e1af7c 100644
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -1583,11 +1583,7 @@ def recurse_in_body_and_except():
             sys.setrecursionlimit(recursionlimit)
 
 
-    @cpython_only
-    # Python built with Py_TRACE_REFS fail with a fatal error in
-    # _PyRefchain_Trace() on memory allocation error.
-    @unittest.skipIf(support.Py_TRACE_REFS, 'cannot test Py_TRACE_REFS build')
-    @unittest.skipIf(_testcapi is None, "requires _testcapi")
+    @support.nomemtest
     def test_recursion_normalizing_with_no_memory(self):
         # Issue #30697. Test that in the abort that occurs when there is no
         # memory left and the size of the Python frames stack is greater than
@@ -1774,11 +1770,7 @@ def test_unhandled(self):
                     self.assertIn("test message", report)
                 self.assertEndsWith(report, "\n")
 
-    @cpython_only
-    # Python built with Py_TRACE_REFS fail with a fatal error in
-    # _PyRefchain_Trace() on memory allocation error.
-    @unittest.skipIf(support.Py_TRACE_REFS, 'cannot test Py_TRACE_REFS build')
-    @unittest.skipIf(_testcapi is None, "requires _testcapi")
+    @support.nomemtest
     def test_memory_error_in_PyErr_PrintEx(self):
         code = """if 1:
             import _testcapi
@@ -1936,12 +1928,8 @@ def test_keyerror_context(self):
             exc2 = None
 
 
-    @cpython_only
-    # Python built with Py_TRACE_REFS fail with a fatal error in
-    # _PyRefchain_Trace() on memory allocation error.
-    @unittest.skipIf(support.Py_TRACE_REFS, 'cannot test Py_TRACE_REFS build')
+    @support.nomemtest
     def test_exec_set_nomemory_hang(self):
-        import_module("_testcapi")
         # gh-134163: A MemoryError inside code that was wrapped by a try/except
         # block would lead to an infinite loop.
 
diff --git a/Lib/test/test_interpreters/test_stress.py 
b/Lib/test/test_interpreters/test_stress.py
index 6b40a536bd3c319..50d87a6ccd3cadb 100644
--- a/Lib/test/test_interpreters/test_stress.py
+++ b/Lib/test/test_interpreters/test_stress.py
@@ -5,7 +5,7 @@
 from test.support import import_helper
 from test.support import threading_helper
 # Raise SkipTest if subinterpreters not supported.
-import_helper.import_module('_interpreters')
+_interpreters = import_helper.import_module('_interpreters')
 from concurrent import interpreters
 from concurrent.interpreters import InterpreterError
 from .utils import TestBase
@@ -75,12 +75,13 @@ def run():
             start.set()
         support.gc_collect()
 
+    @support.nomemtest
     def test_create_interpreter_no_memory(self):
-        import _interpreters
-        _testcapi = import_helper.import_module("_testcapi")
+        import _testcapi
 
-        with self.assertRaises(InterpreterError):
-            _testcapi.set_nomemory(0, 1)
+        assertion = self.assertRaises(InterpreterError)
+        _testcapi.set_nomemory(0, 1)
+        with assertion:
             _interpreters.create()
 
 
diff --git a/Lib/test/test_list.py b/Lib/test/test_list.py
index 642b54d34849dab..44ecd62d6735def 100644
--- a/Lib/test/test_list.py
+++ b/Lib/test/test_list.py
@@ -3,7 +3,6 @@
 import textwrap
 from test import list_tests, support
 from test.support import cpython_only
-from test.support.import_helper import import_module
 from test.support.script_helper import assert_python_failure, assert_python_ok
 import pickle
 import unittest
@@ -326,10 +325,9 @@ def test_tier2_invalidates_iterator(self):
             a.append(4)
             self.assertEqual(list(it), [])
 
-    @support.cpython_only
+    @support.nomemtest
     def test_no_memory(self):
         # gh-118331: Make sure we don't crash if list allocation fails
-        import_module("_testcapi")
         code = textwrap.dedent("""
         import _testcapi, sys
         # Prime the freelist
diff --git a/Lib/test/test_repl.py b/Lib/test/test_repl.py
index 850cb66a89ba84a..0f5009c32124902 100644
--- a/Lib/test/test_repl.py
+++ b/Lib/test/test_repl.py
@@ -17,7 +17,6 @@
     SHORT_TIMEOUT,
 )
 from test.support.script_helper import kill_python
-from test.support.import_helper import import_module
 
 try:
     import pty
@@ -99,12 +98,8 @@ def run_on_interactive_mode(source):
 @support.force_not_colorized_test_class
 class TestInteractiveInterpreter(unittest.TestCase):
 
-    @cpython_only
-    # Python built with Py_TRACE_REFS fail with a fatal error in
-    # _PyRefchain_Trace() on memory allocation error.
-    @unittest.skipIf(support.Py_TRACE_REFS, 'cannot test Py_TRACE_REFS build')
+    @support.nomemtest
     def test_no_memory(self):
-        import_module("_testcapi")
         # Issue #30696: Fix the interactive interpreter looping endlessly when
         # no memory. Check also that the fix does not break the interactive
         # loop when an exception is raised.
diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py
index b187643e84521cc..f02691bf3002000 100644
--- a/Lib/test/test_weakref.py
+++ b/Lib/test/test_weakref.py
@@ -1019,7 +1019,7 @@ def __del__(self): pass
         del x
         support.gc_collect()
 
-    @support.cpython_only
+    @support.nomemtest
     def test_no_memory_when_clearing(self):
         # gh-118331: Make sure we do not raise an exception from the destructor
         # when clearing weakrefs if allocating the intermediate tuple fails.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to