From 9b3f0f7bb4f845b0af332cc3efdef161f71b27e0 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 4 Mar 2024 14:35:06 +0100 Subject: [PATCH 01/35] gh-116303: Skip some sqlite3 tests if testcapi is unavailable --- Lib/test/test_sqlite3/test_dbapi.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index 588272448bbfda..e46c62cce8c6e2 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -31,11 +31,10 @@ from test.support import ( SHORT_TIMEOUT, check_disallow_instantiation, requires_subprocess, - is_apple, is_emscripten, is_wasi + is_apple, is_emscripten, is_wasi, import_helper ) from test.support import gc_collect from test.support import threading_helper -from _testcapi import INT_MAX, ULLONG_MAX from os import SEEK_SET, SEEK_CUR, SEEK_END from test.support.os_helper import TESTFN, TESTFN_UNDECODABLE, unlink, temp_dir, FakePath @@ -1200,6 +1199,7 @@ def test_blob_seek_and_tell(self): self.assertEqual(self.blob.tell(), 40) def test_blob_seek_error(self): + testcapi = import_helper.import_module("_testcapi") msg_oor = "offset out of blob range" msg_orig = "'origin' should be os.SEEK_SET, os.SEEK_CUR, or os.SEEK_END" msg_of = "seek offset results in overflow" @@ -1217,9 +1217,9 @@ def test_blob_seek_error(self): # Force overflow errors self.blob.seek(1, SEEK_SET) with self.assertRaisesRegex(OverflowError, msg_of): - self.blob.seek(INT_MAX, SEEK_CUR) + self.blob.seek(testcapi.INT_MAX, SEEK_CUR) with self.assertRaisesRegex(OverflowError, msg_of): - self.blob.seek(INT_MAX, SEEK_END) + self.blob.seek(testcapi.INT_MAX, SEEK_END) def test_blob_read(self): buf = self.blob.read() @@ -1374,13 +1374,14 @@ def test_blob_mapping_invalid_index_type(self): self.blob["a"] = b"b" def test_blob_get_item_error(self): + testcapi = import_helper.import_module("_testcapi") dataset = [len(self.blob), 105, -105] for idx in dataset: with self.subTest(idx=idx): with self.assertRaisesRegex(IndexError, "index out of range"): self.blob[idx] with self.assertRaisesRegex(IndexError, "cannot fit 'int'"): - self.blob[ULLONG_MAX] + self.blob[testcapi.ULLONG_MAX] # Provoke read error self.cx.execute("update test set b='aaaa' where rowid=1") From 0f6f74e16def47c4dc144d5e251e3c6e5b5f1e2e Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 4 Mar 2024 14:35:06 +0100 Subject: [PATCH 02/35] Skip more tests - Lib/test/support/__init__.py - Lib/test/test_audit.py - Lib/test/test_gdb/test_misc.py - Lib/test/test_inspect/test_inspect.py - Lib/test/test_pydoc/test_pydoc.py --- Lib/test/support/__init__.py | 1 + Lib/test/test_audit.py | 2 ++ Lib/test/test_gdb/test_misc.py | 6 +++++- Lib/test/test_inspect/test_inspect.py | 12 ++++++++++-- Lib/test/test_pydoc/test_pydoc.py | 6 ++++++ 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 14e3766a34377b..4ca42448271687 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -1698,6 +1698,7 @@ def patch_list(orig): orig[:] = saved +@requires_limited_api def run_in_subinterp(code): """ Run code in a subinterpreter. Raise unittest.SkipTest if the tracemalloc diff --git a/Lib/test/test_audit.py b/Lib/test/test_audit.py index cd0a4e2264865d..30d9ce06fe1b6a 100644 --- a/Lib/test/test_audit.py +++ b/Lib/test/test_audit.py @@ -7,6 +7,7 @@ from test import support from test.support import import_helper from test.support import os_helper +from test.support import requires_limited_api if not hasattr(sys, "addaudithook") or not hasattr(sys, "audit"): @@ -88,6 +89,7 @@ def test_excepthook(self): [("sys.excepthook", " ", "RuntimeError('fatal-error')")], events ) + @requires_limited_api def test_unraisablehook(self): returncode, events, stderr = self.run_python("test_unraisablehook") if returncode: diff --git a/Lib/test/test_gdb/test_misc.py b/Lib/test/test_gdb/test_misc.py index 1047f4867c1d03..92c5447ece0777 100644 --- a/Lib/test/test_gdb/test_misc.py +++ b/Lib/test/test_gdb/test_misc.py @@ -1,6 +1,6 @@ import re import unittest -from test.support import python_is_optimized +from test.support import python_is_optimized, requires_limited_api from .util import run_gdb, setup_module, DebuggerTests, SAMPLE_SCRIPT @@ -85,6 +85,7 @@ def baz(*args): class StackNavigationTests(DebuggerTests): + @requires_limited_api @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") @unittest.skipIf(python_is_optimized(), "Python was compiled with optimizations") @@ -114,6 +115,7 @@ def test_up_at_top(self): self.assertEndsWith(bt, 'Unable to find an older python frame\n') + @requires_limited_api @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") @unittest.skipIf(python_is_optimized(), "Python was compiled with optimizations") @@ -129,6 +131,7 @@ def test_up_then_down(self): $''') class PyPrintTests(DebuggerTests): + @requires_limited_api @unittest.skipIf(python_is_optimized(), "Python was compiled with optimizations") def test_basic_command(self): @@ -138,6 +141,7 @@ def test_basic_command(self): self.assertMultilineMatches(bt, r".*\nlocal 'args' = \(1, 2, 3\)\n.*") + @requires_limited_api @unittest.skipIf(python_is_optimized(), "Python was compiled with optimizations") @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index 52cf68b93b85fa..c36d228112c587 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -32,7 +32,7 @@ except ImportError: ThreadPoolExecutor = None -from test.support import cpython_only +from test.support import cpython_only, requires_limited_api from test.support import MISSING_C_DOCSTRINGS, ALWAYS_EQ from test.support.import_helper import DirsOnSysPath, ready_to_import from test.support.os_helper import TESTFN @@ -668,7 +668,10 @@ def test_cleandoc(self): @cpython_only def test_c_cleandoc(self): - import _testinternalcapi + try: + import _testinternalcapi + except ImportError: + return unittest.skip("requires _testinternalcapi") func = _testinternalcapi.compiler_cleandoc for i, (input, expected) in enumerate(self.cleandoc_testdata): with self.subTest(i=i): @@ -1200,6 +1203,7 @@ def test_getfullargspec_builtin_methods(self): @cpython_only @unittest.skipIf(MISSING_C_DOCSTRINGS, "Signature information for builtins requires docstrings") + @requires_limited_api def test_getfullargspec_builtin_func(self): import _testcapi builtin = _testcapi.docstring_with_signature_with_defaults @@ -1209,6 +1213,7 @@ def test_getfullargspec_builtin_func(self): @cpython_only @unittest.skipIf(MISSING_C_DOCSTRINGS, "Signature information for builtins requires docstrings") + @requires_limited_api def test_getfullargspec_builtin_func_no_signature(self): import _testcapi builtin = _testcapi.docstring_no_signature @@ -2870,6 +2875,7 @@ def test_staticmethod(*args): # NOQA @cpython_only @unittest.skipIf(MISSING_C_DOCSTRINGS, "Signature information for builtins requires docstrings") + @requires_limited_api def test_signature_on_builtins(self): import _testcapi @@ -2951,6 +2957,7 @@ class ThisWorksNow: @cpython_only @unittest.skipIf(MISSING_C_DOCSTRINGS, "Signature information for builtins requires docstrings") + @requires_limited_api def test_signature_on_decorated_builtins(self): import _testcapi func = _testcapi.docstring_with_signature_with_defaults @@ -2972,6 +2979,7 @@ def wrapper_like(*args, **kwargs) -> int: pass inspect.signature(wrapper_like)) @cpython_only + @requires_limited_api def test_signature_on_builtins_no_signature(self): import _testcapi with self.assertRaisesRegex(ValueError, diff --git a/Lib/test/test_pydoc/test_pydoc.py b/Lib/test/test_pydoc/test_pydoc.py index 9d40234ed01697..d2bacd86f02bae 100644 --- a/Lib/test/test_pydoc/test_pydoc.py +++ b/Lib/test/test_pydoc/test_pydoc.py @@ -1371,6 +1371,7 @@ def test_bound_builtin_classmethod_o(self): @support.cpython_only @requires_docstrings + @support.requires_limited_api def test_module_level_callable_unrepresentable_default(self): import _testcapi builtin = _testcapi.func_with_unrepresentable_signature @@ -1379,6 +1380,7 @@ def test_module_level_callable_unrepresentable_default(self): @support.cpython_only @requires_docstrings + @support.requires_limited_api def test_builtin_staticmethod_unrepresentable_default(self): self.assertEqual(self._get_summary_line(str.maketrans), "maketrans(x, y=, z=, /)") @@ -1389,6 +1391,7 @@ def test_builtin_staticmethod_unrepresentable_default(self): @support.cpython_only @requires_docstrings + @support.requires_limited_api def test_unbound_builtin_method_unrepresentable_default(self): self.assertEqual(self._get_summary_line(dict.pop), "pop(self, key, default=, /) " @@ -1401,6 +1404,7 @@ def test_unbound_builtin_method_unrepresentable_default(self): @support.cpython_only @requires_docstrings + @support.requires_limited_api def test_bound_builtin_method_unrepresentable_default(self): self.assertEqual(self._get_summary_line({}.pop), "pop(key, default=, /) " @@ -1413,6 +1417,7 @@ def test_bound_builtin_method_unrepresentable_default(self): @support.cpython_only @requires_docstrings + @support.requires_limited_api def test_unbound_builtin_classmethod_unrepresentable_default(self): import _testcapi cls = _testcapi.DocStringUnrepresentableSignatureTest @@ -1423,6 +1428,7 @@ def test_unbound_builtin_classmethod_unrepresentable_default(self): @support.cpython_only @requires_docstrings + @support.requires_limited_api def test_bound_builtin_classmethod_unrepresentable_default(self): import _testcapi cls = _testcapi.DocStringUnrepresentableSignatureTest From 2f750c3d22deb97a0bbc727c882d7a51afb853f6 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 4 Mar 2024 15:07:08 +0100 Subject: [PATCH 03/35] Split up sqlite3 tests --- Lib/test/test_sqlite3/test_dbapi.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index e46c62cce8c6e2..a34962bd96c6a5 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -31,7 +31,7 @@ from test.support import ( SHORT_TIMEOUT, check_disallow_instantiation, requires_subprocess, - is_apple, is_emscripten, is_wasi, import_helper + is_apple, is_emscripten, is_wasi, requires_limited_api ) from test.support import gc_collect from test.support import threading_helper @@ -1199,7 +1199,6 @@ def test_blob_seek_and_tell(self): self.assertEqual(self.blob.tell(), 40) def test_blob_seek_error(self): - testcapi = import_helper.import_module("_testcapi") msg_oor = "offset out of blob range" msg_orig = "'origin' should be os.SEEK_SET, os.SEEK_CUR, or os.SEEK_END" msg_of = "seek offset results in overflow" @@ -1214,12 +1213,15 @@ def test_blob_seek_error(self): with self.subTest(exc=exc, msg=msg, fn=fn): self.assertRaisesRegex(exc, msg, fn) + @requires_limited_api + def test_blob_seek_error_overflow(self): # Force overflow errors + from _testcapi import INT_MAX self.blob.seek(1, SEEK_SET) with self.assertRaisesRegex(OverflowError, msg_of): - self.blob.seek(testcapi.INT_MAX, SEEK_CUR) + self.blob.seek(INT_MAX, SEEK_CUR) with self.assertRaisesRegex(OverflowError, msg_of): - self.blob.seek(testcapi.INT_MAX, SEEK_END) + self.blob.seek(INT_MAX, SEEK_END) def test_blob_read(self): buf = self.blob.read() @@ -1374,14 +1376,17 @@ def test_blob_mapping_invalid_index_type(self): self.blob["a"] = b"b" def test_blob_get_item_error(self): - testcapi = import_helper.import_module("_testcapi") dataset = [len(self.blob), 105, -105] for idx in dataset: with self.subTest(idx=idx): with self.assertRaisesRegex(IndexError, "index out of range"): self.blob[idx] + + @requires_limited_api + def test_blog_get_item_ullong_max(self): + from _testcapi import ULLONG_MAX with self.assertRaisesRegex(IndexError, "cannot fit 'int'"): - self.blob[testcapi.ULLONG_MAX] + self.blob[ULLONG_MAX] # Provoke read error self.cx.execute("update test set b='aaaa' where rowid=1") From 7c4477de5d40720b94792a4a652575e13b78eeac Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 4 Mar 2024 15:09:23 +0100 Subject: [PATCH 04/35] Amend previous commit --- Lib/test/test_sqlite3/test_dbapi.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index a34962bd96c6a5..10f59cd0b859f5 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -1201,7 +1201,6 @@ def test_blob_seek_and_tell(self): def test_blob_seek_error(self): msg_oor = "offset out of blob range" msg_orig = "'origin' should be os.SEEK_SET, os.SEEK_CUR, or os.SEEK_END" - msg_of = "seek offset results in overflow" dataset = ( (ValueError, msg_oor, lambda: self.blob.seek(1000)), @@ -1217,6 +1216,7 @@ def test_blob_seek_error(self): def test_blob_seek_error_overflow(self): # Force overflow errors from _testcapi import INT_MAX + msg_of = "seek offset results in overflow" self.blob.seek(1, SEEK_SET) with self.assertRaisesRegex(OverflowError, msg_of): self.blob.seek(INT_MAX, SEEK_CUR) @@ -1383,11 +1383,12 @@ def test_blob_get_item_error(self): self.blob[idx] @requires_limited_api - def test_blog_get_item_ullong_max(self): + def test_blob_get_item_ullong_max(self): from _testcapi import ULLONG_MAX with self.assertRaisesRegex(IndexError, "cannot fit 'int'"): self.blob[ULLONG_MAX] + def test_blob_get_item_read_error(self): # Provoke read error self.cx.execute("update test set b='aaaa' where rowid=1") with self.assertRaises(sqlite.OperationalError): From cdc6df41e186fff53ec6288103dc4debf2f25910 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 09:00:45 +0100 Subject: [PATCH 05/35] Use import_helper iso. requires_limited_api --- Lib/test/support/bytecode_helper.py | 11 +-- Lib/test/test__xxsubinterpreters.py | 2 +- Lib/test/test_builtin.py | 3 + Lib/test/test_call.py | 80 +++++++++++---------- Lib/test/test_capi/__init__.py | 4 +- Lib/test/test_code.py | 7 +- Lib/test/test_ctypes/test_as_parameter.py | 3 +- Lib/test/test_ctypes/test_bitfields.py | 3 +- Lib/test/test_ctypes/test_callbacks.py | 3 +- Lib/test/test_ctypes/test_cfuncs.py | 3 +- Lib/test/test_ctypes/test_checkretval.py | 3 +- Lib/test/test_ctypes/test_funcptr.py | 3 +- Lib/test/test_ctypes/test_functions.py | 3 +- Lib/test/test_ctypes/test_libc.py | 3 +- Lib/test/test_ctypes/test_loading.py | 2 +- Lib/test/test_ctypes/test_parameters.py | 3 +- Lib/test/test_ctypes/test_pickling.py | 3 +- Lib/test/test_ctypes/test_pointers.py | 3 +- Lib/test/test_ctypes/test_prototypes.py | 3 +- Lib/test/test_ctypes/test_refcounts.py | 3 +- Lib/test/test_ctypes/test_returnfuncptrs.py | 3 +- Lib/test/test_ctypes/test_slicing.py | 3 +- Lib/test/test_ctypes/test_stringptr.py | 3 +- Lib/test/test_ctypes/test_structures.py | 3 +- Lib/test/test_ctypes/test_unicode.py | 3 +- Lib/test/test_ctypes/test_values.py | 10 +-- Lib/test/test_ctypes/test_win32.py | 4 +- Lib/test/test_embed.py | 6 ++ Lib/test/test_exceptions.py | 22 +++--- Lib/test/test_external_inspection.py | 2 +- Lib/test/test_faulthandler.py | 1 + Lib/test/test_fcntl.py | 6 +- Lib/test/test_fileio.py | 3 +- Lib/test/test_finalization.py | 4 +- Lib/test/test_gdb/test_misc.py | 6 +- Lib/test/test_inspect/test_inspect.py | 17 ++--- Lib/test/test_pydoc/test_pydoc.py | 18 ++--- Lib/test/test_sqlite3/test_dbapi.py | 25 +++---- 38 files changed, 159 insertions(+), 128 deletions(-) diff --git a/Lib/test/support/bytecode_helper.py b/Lib/test/support/bytecode_helper.py index a4845065a5322e..32d4ec06609177 100644 --- a/Lib/test/support/bytecode_helper.py +++ b/Lib/test/support/bytecode_helper.py @@ -3,7 +3,7 @@ import unittest import dis import io -from _testinternalcapi import compiler_codegen, optimize_cfg, assemble_code_object +from test.support import import_helper _UNSPECIFIED = object() @@ -136,20 +136,23 @@ def complete_insts_info(self, insts): class CodegenTestCase(CompilationStepTestCase): def generate_code(self, ast): - insts, _ = compiler_codegen(ast, "my_file.py", 0) + _testinternalcapi = import_helper.import_module("_testinternalcapi") + insts, _ = _testinternalcapi.compiler_codegen(ast, "my_file.py", 0) return insts class CfgOptimizationTestCase(CompilationStepTestCase): def get_optimized(self, insts, consts, nlocals=0): + _testinternalcapi = import_helper.import_module("_testinternalcapi") insts = self.normalize_insts(insts) insts = self.complete_insts_info(insts) - insts = optimize_cfg(insts, consts, nlocals) + insts = _testinternalcapi.optimize_cfg(insts, consts, nlocals) return insts, consts class AssemblerTestCase(CompilationStepTestCase): def get_code_object(self, filename, insts, metadata): - co = assemble_code_object(filename, insts, metadata) + _testinternalcapi = import_helper.import_module("_testinternalcapi") + co = _testinternalcapi.assemble_code_object(filename, insts, metadata) return co diff --git a/Lib/test/test__xxsubinterpreters.py b/Lib/test/test__xxsubinterpreters.py index a76e4d0ade5b8a..e779bb9cffc3ea 100644 --- a/Lib/test/test__xxsubinterpreters.py +++ b/Lib/test/test__xxsubinterpreters.py @@ -7,13 +7,13 @@ import threading import unittest -import _testinternalcapi from test import support from test.support import import_helper from test.support import os_helper from test.support import script_helper +_testinternalcapi = import_helper.import_module('_testinternalcapi') interpreters = import_helper.import_module('_xxsubinterpreters') from _xxsubinterpreters import InterpreterNotFoundError diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 9a0bf524e3943f..5e8b06d0c127b8 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -47,6 +47,9 @@ HAVE_DOUBLE_ROUNDING = (x + y == 1e16 + 4) +raise unittest.SkipTest("FAIL") + + class Squares: def __init__(self, max): diff --git a/Lib/test/test_call.py b/Lib/test/test_call.py index 2a6a5d287b04ee..341afcadd8df38 100644 --- a/Lib/test/test_call.py +++ b/Lib/test/test_call.py @@ -1,6 +1,6 @@ import unittest from test.support import (cpython_only, is_wasi, requires_limited_api, Py_DEBUG, - set_recursion_limit, skip_on_s390x) + set_recursion_limit, skip_on_s390x, import_helper) try: import _testcapi except ImportError: @@ -240,6 +240,7 @@ def test_module_not_callable_suggestion(self): self.assertRaisesRegex(TypeError, msg, mod) +@unittest.skipIf(_testcapi is None, "requires _testcapi") class TestCallingConventions(unittest.TestCase): """Test calling using various C calling conventions (METH_*) from Python @@ -437,6 +438,7 @@ def static_method(): NULL_OR_EMPTY = object() + class FastCallTests(unittest.TestCase): """Test calling using various callables from C """ @@ -480,42 +482,44 @@ class FastCallTests(unittest.TestCase): ] # Add all the calling conventions and variants of C callables - _instance = _testcapi.MethInstance() - for obj, expected_self in ( - (_testcapi, _testcapi), # module-level function - (_instance, _instance), # bound method - (_testcapi.MethClass, _testcapi.MethClass), # class method on class - (_testcapi.MethClass(), _testcapi.MethClass), # class method on inst. - (_testcapi.MethStatic, None), # static method - ): - CALLS_POSARGS.extend([ - (obj.meth_varargs, (1, 2), (expected_self, (1, 2))), - (obj.meth_varargs_keywords, - (1, 2), (expected_self, (1, 2), NULL_OR_EMPTY)), - (obj.meth_fastcall, (1, 2), (expected_self, (1, 2))), - (obj.meth_fastcall, (), (expected_self, ())), - (obj.meth_fastcall_keywords, - (1, 2), (expected_self, (1, 2), NULL_OR_EMPTY)), - (obj.meth_fastcall_keywords, - (), (expected_self, (), NULL_OR_EMPTY)), - (obj.meth_noargs, (), expected_self), - (obj.meth_o, (123, ), (expected_self, 123)), - ]) - - CALLS_KWARGS.extend([ - (obj.meth_varargs_keywords, - (1, 2), {'x': 'y'}, (expected_self, (1, 2), {'x': 'y'})), - (obj.meth_varargs_keywords, - (), {'x': 'y'}, (expected_self, (), {'x': 'y'})), - (obj.meth_varargs_keywords, - (1, 2), {}, (expected_self, (1, 2), NULL_OR_EMPTY)), - (obj.meth_fastcall_keywords, - (1, 2), {'x': 'y'}, (expected_self, (1, 2), {'x': 'y'})), - (obj.meth_fastcall_keywords, - (), {'x': 'y'}, (expected_self, (), {'x': 'y'})), - (obj.meth_fastcall_keywords, - (1, 2), {}, (expected_self, (1, 2), NULL_OR_EMPTY)), - ]) + def setUp(self): + _testcapi = import_helper.import_module("_testcapi") + _instance = _testcapi.MethInstance() + for obj, expected_self in ( + (_testcapi, _testcapi), # module-level function + (_instance, _instance), # bound method + (_testcapi.MethClass, _testcapi.MethClass), # class method on class + (_testcapi.MethClass(), _testcapi.MethClass), # class method on inst. + (_testcapi.MethStatic, None), # static method + ): + self.CALLS_POSARGS.extend([ + (obj.meth_varargs, (1, 2), (expected_self, (1, 2))), + (obj.meth_varargs_keywords, + (1, 2), (expected_self, (1, 2), NULL_OR_EMPTY)), + (obj.meth_fastcall, (1, 2), (expected_self, (1, 2))), + (obj.meth_fastcall, (), (expected_self, ())), + (obj.meth_fastcall_keywords, + (1, 2), (expected_self, (1, 2), NULL_OR_EMPTY)), + (obj.meth_fastcall_keywords, + (), (expected_self, (), NULL_OR_EMPTY)), + (obj.meth_noargs, (), expected_self), + (obj.meth_o, (123, ), (expected_self, 123)), + ]) + + self.CALLS_KWARGS.extend([ + (obj.meth_varargs_keywords, + (1, 2), {'x': 'y'}, (expected_self, (1, 2), {'x': 'y'})), + (obj.meth_varargs_keywords, + (), {'x': 'y'}, (expected_self, (), {'x': 'y'})), + (obj.meth_varargs_keywords, + (1, 2), {}, (expected_self, (1, 2), NULL_OR_EMPTY)), + (obj.meth_fastcall_keywords, + (1, 2), {'x': 'y'}, (expected_self, (1, 2), {'x': 'y'})), + (obj.meth_fastcall_keywords, + (), {'x': 'y'}, (expected_self, (), {'x': 'y'})), + (obj.meth_fastcall_keywords, + (1, 2), {}, (expected_self, (1, 2), NULL_OR_EMPTY)), + ]) def check_result(self, result, expected): if isinstance(expected, tuple) and expected[-1] is NULL_OR_EMPTY: @@ -606,6 +610,7 @@ def testfunction_kw(self, *, kw): ADAPTIVE_WARMUP_DELAY = 2 +@unittest.skipIf(_testcapi is None, "requires _testcapi") class TestPEP590(unittest.TestCase): def test_method_descriptor_flag(self): @@ -1019,6 +1024,7 @@ class TestRecursion(unittest.TestCase): @skip_on_s390x @unittest.skipIf(is_wasi and Py_DEBUG, "requires deep stack") def test_super_deep(self): + _testcapi = import_helper.import_module("_testcapi") def recurse(n): if n: diff --git a/Lib/test/test_capi/__init__.py b/Lib/test/test_capi/__init__.py index 4b16ecc31156a5..889a66ad2dc0d2 100644 --- a/Lib/test/test_capi/__init__.py +++ b/Lib/test/test_capi/__init__.py @@ -1,5 +1,7 @@ import os -from test.support import load_package_tests +from test.support import load_package_tests, import_helper + +import_helper.import_module("_testcapi") def load_tests(*args): return load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py index 46bebfc7af675b..ecd1e82a6dbef9 100644 --- a/Lib/test/test_code.py +++ b/Lib/test/test_code.py @@ -143,9 +143,8 @@ check_impl_detail, requires_debug_ranges, gc_collect) from test.support.script_helper import assert_python_ok -from test.support import threading_helper -from test.support.bytecode_helper import (BytecodeTestCase, - instructions_with_positions) +from test.support import threading_helper, import_helper +from test.support.bytecode_helper import instructions_with_positions from opcode import opmap, opname COPY_FREE_VARS = opmap['COPY_FREE_VARS'] @@ -176,7 +175,7 @@ class CodeTest(unittest.TestCase): @cpython_only def test_newempty(self): - import _testcapi + _testcapi = import_helper.import_module("_testcapi") co = _testcapi.code_newempty("filename", "funcname", 15) self.assertEqual(co.co_filename, "filename") self.assertEqual(co.co_name, "funcname") diff --git a/Lib/test/test_ctypes/test_as_parameter.py b/Lib/test/test_ctypes/test_as_parameter.py index ca75e748256083..cc62b1a22a3b06 100644 --- a/Lib/test/test_ctypes/test_as_parameter.py +++ b/Lib/test/test_ctypes/test_as_parameter.py @@ -1,4 +1,3 @@ -import _ctypes_test import ctypes import unittest from ctypes import (Structure, CDLL, CFUNCTYPE, @@ -6,6 +5,8 @@ c_short, c_int, c_long, c_longlong, c_byte, c_wchar, c_float, c_double, ArgumentError) +from test.support import import_helper +_ctypes_test = import_helper.import_module("_ctypes_test") dll = CDLL(_ctypes_test.__file__) diff --git a/Lib/test/test_ctypes/test_bitfields.py b/Lib/test/test_ctypes/test_bitfields.py index d43c56ad371fbd..0332544b5827e6 100644 --- a/Lib/test/test_ctypes/test_bitfields.py +++ b/Lib/test/test_ctypes/test_bitfields.py @@ -1,4 +1,3 @@ -import _ctypes_test import os import unittest from ctypes import (CDLL, Structure, sizeof, POINTER, byref, alignment, @@ -7,6 +6,8 @@ c_uint32, c_uint64, c_short, c_ushort, c_int, c_uint, c_long, c_ulong, c_longlong, c_ulonglong) from test import support +from test.support import import_helper +_ctypes_test = import_helper.import_module("_ctypes_test") class BITS(Structure): diff --git a/Lib/test/test_ctypes/test_callbacks.py b/Lib/test/test_ctypes/test_callbacks.py index 64f92ffdca6a3f..72b3d019f4d525 100644 --- a/Lib/test/test_ctypes/test_callbacks.py +++ b/Lib/test/test_ctypes/test_callbacks.py @@ -1,4 +1,3 @@ -import _ctypes_test import ctypes import functools import gc @@ -14,6 +13,8 @@ c_float, c_double, c_longdouble, py_object) from ctypes.util import find_library from test import support +from test.support import import_helper +_ctypes_test = import_helper.import_module("_ctypes_test") class Callbacks(unittest.TestCase): diff --git a/Lib/test/test_ctypes/test_cfuncs.py b/Lib/test/test_ctypes/test_cfuncs.py index 6ff0878a35da2f..48330c4b0a763b 100644 --- a/Lib/test/test_ctypes/test_cfuncs.py +++ b/Lib/test/test_ctypes/test_cfuncs.py @@ -1,4 +1,3 @@ -import _ctypes_test import ctypes import unittest from ctypes import (CDLL, @@ -6,6 +5,8 @@ c_short, c_ushort, c_int, c_uint, c_long, c_ulong, c_longlong, c_ulonglong, c_float, c_double, c_longdouble) +from test.support import import_helper +_ctypes_test = import_helper.import_module("_ctypes_test") class CFunctions(unittest.TestCase): diff --git a/Lib/test/test_ctypes/test_checkretval.py b/Lib/test/test_ctypes/test_checkretval.py index 5dc9e25aa38226..9d6bfdb845e6c7 100644 --- a/Lib/test/test_ctypes/test_checkretval.py +++ b/Lib/test/test_ctypes/test_checkretval.py @@ -1,7 +1,8 @@ -import _ctypes_test import ctypes import unittest from ctypes import CDLL, c_int +from test.support import import_helper +_ctypes_test = import_helper.import_module("_ctypes_test") class CHECKED(c_int): diff --git a/Lib/test/test_ctypes/test_funcptr.py b/Lib/test/test_ctypes/test_funcptr.py index 0eed39484fb39e..f0ee3ae38e4f57 100644 --- a/Lib/test/test_ctypes/test_funcptr.py +++ b/Lib/test/test_ctypes/test_funcptr.py @@ -1,8 +1,9 @@ -import _ctypes_test import ctypes import unittest from ctypes import (CDLL, Structure, CFUNCTYPE, sizeof, _CFuncPtr, c_void_p, c_char_p, c_char, c_int, c_uint, c_long) +from test.support import import_helper +_ctypes_test = import_helper.import_module("_ctypes_test") from ._support import (_CData, PyCFuncPtrType, Py_TPFLAGS_DISALLOW_INSTANTIATION, Py_TPFLAGS_IMMUTABLETYPE) diff --git a/Lib/test/test_ctypes/test_functions.py b/Lib/test/test_ctypes/test_functions.py index 04e8582ff1e427..63e393f7b7cb6a 100644 --- a/Lib/test/test_ctypes/test_functions.py +++ b/Lib/test/test_ctypes/test_functions.py @@ -1,4 +1,3 @@ -import _ctypes_test import ctypes import sys import unittest @@ -7,6 +6,8 @@ c_char, c_wchar, c_byte, c_char_p, c_wchar_p, c_short, c_int, c_long, c_longlong, c_void_p, c_float, c_double, c_longdouble) +from test.support import import_helper +_ctypes_test = import_helper.import_module("_ctypes_test") from _ctypes import _Pointer, _SimpleCData diff --git a/Lib/test/test_ctypes/test_libc.py b/Lib/test/test_ctypes/test_libc.py index 09c76db0bd0b17..7716100b08f78e 100644 --- a/Lib/test/test_ctypes/test_libc.py +++ b/Lib/test/test_ctypes/test_libc.py @@ -1,8 +1,9 @@ -import _ctypes_test import math import unittest from ctypes import (CDLL, CFUNCTYPE, POINTER, create_string_buffer, sizeof, c_void_p, c_char, c_int, c_double, c_size_t) +from test.support import import_helper +_ctypes_test = import_helper.import_module("_ctypes_test") lib = CDLL(_ctypes_test.__file__) diff --git a/Lib/test/test_ctypes/test_loading.py b/Lib/test/test_ctypes/test_loading.py index b218e9e7720c79..b25e81b65cf103 100644 --- a/Lib/test/test_ctypes/test_loading.py +++ b/Lib/test/test_ctypes/test_loading.py @@ -1,5 +1,4 @@ import _ctypes -import _ctypes_test import ctypes import os import shutil @@ -10,6 +9,7 @@ from ctypes import CDLL, cdll, addressof, c_void_p, c_char_p from ctypes.util import find_library from test.support import import_helper, os_helper +_ctypes_test = import_helper.import_module("_ctypes_test") libc_name = None diff --git a/Lib/test/test_ctypes/test_parameters.py b/Lib/test/test_ctypes/test_parameters.py index d1eeee6b0306fe..effb8db418f790 100644 --- a/Lib/test/test_ctypes/test_parameters.py +++ b/Lib/test/test_ctypes/test_parameters.py @@ -1,4 +1,3 @@ -import _ctypes_test import unittest import test.support from ctypes import (CDLL, PyDLL, ArgumentError, @@ -14,6 +13,8 @@ c_long, c_ulong, c_longlong, c_ulonglong, c_float, c_double, c_longdouble) +from test.support import import_helper +_ctypes_test = import_helper.import_module("_ctypes_test") class SimpleTypesTestCase(unittest.TestCase): diff --git a/Lib/test/test_ctypes/test_pickling.py b/Lib/test/test_ctypes/test_pickling.py index 0ca42a68f0675f..9d433fc69de391 100644 --- a/Lib/test/test_ctypes/test_pickling.py +++ b/Lib/test/test_ctypes/test_pickling.py @@ -1,9 +1,10 @@ -import _ctypes_test import pickle import unittest from ctypes import (CDLL, Structure, CFUNCTYPE, pointer, c_void_p, c_char_p, c_wchar_p, c_char, c_wchar, c_int, c_double) +from test.support import import_helper +_ctypes_test = import_helper.import_module("_ctypes_test") dll = CDLL(_ctypes_test.__file__) diff --git a/Lib/test/test_ctypes/test_pointers.py b/Lib/test/test_ctypes/test_pointers.py index 8cf2114c282cab..fa232a0641aca6 100644 --- a/Lib/test/test_ctypes/test_pointers.py +++ b/Lib/test/test_ctypes/test_pointers.py @@ -1,4 +1,3 @@ -import _ctypes_test import array import ctypes import sys @@ -10,6 +9,8 @@ c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, c_long, c_ulong, c_longlong, c_ulonglong, c_float, c_double) +from test.support import import_helper +_ctypes_test = import_helper.import_module("_ctypes_test") from ._support import (_CData, PyCPointerType, Py_TPFLAGS_DISALLOW_INSTANTIATION, Py_TPFLAGS_IMMUTABLETYPE) diff --git a/Lib/test/test_ctypes/test_prototypes.py b/Lib/test/test_ctypes/test_prototypes.py index 81eb4562c740fd..63ae799ea86ab2 100644 --- a/Lib/test/test_ctypes/test_prototypes.py +++ b/Lib/test/test_ctypes/test_prototypes.py @@ -18,12 +18,13 @@ # # In this case, there would have to be an additional reference to the argument... -import _ctypes_test import unittest from ctypes import (CDLL, CFUNCTYPE, POINTER, ArgumentError, pointer, byref, sizeof, addressof, create_string_buffer, c_void_p, c_char_p, c_wchar_p, c_char, c_wchar, c_short, c_int, c_long, c_longlong, c_double) +from test.support import import_helper +_ctypes_test = import_helper.import_module("_ctypes_test") testdll = CDLL(_ctypes_test.__file__) diff --git a/Lib/test/test_ctypes/test_refcounts.py b/Lib/test/test_ctypes/test_refcounts.py index a90588ca9bb1b6..e6427d4a295b15 100644 --- a/Lib/test/test_ctypes/test_refcounts.py +++ b/Lib/test/test_ctypes/test_refcounts.py @@ -1,9 +1,10 @@ -import _ctypes_test import ctypes import gc import sys import unittest from test import support +from test.support import import_helper +_ctypes_test = import_helper.import_module("_ctypes_test") MyCallback = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int) diff --git a/Lib/test/test_ctypes/test_returnfuncptrs.py b/Lib/test/test_ctypes/test_returnfuncptrs.py index 4010e511e75ade..337801b226ab06 100644 --- a/Lib/test/test_ctypes/test_returnfuncptrs.py +++ b/Lib/test/test_ctypes/test_returnfuncptrs.py @@ -1,6 +1,7 @@ -import _ctypes_test import unittest from ctypes import CDLL, CFUNCTYPE, ArgumentError, c_char_p, c_void_p, c_char +from test.support import import_helper +_ctypes_test = import_helper.import_module("_ctypes_test") class ReturnFuncPtrTestCase(unittest.TestCase): diff --git a/Lib/test/test_ctypes/test_slicing.py b/Lib/test/test_ctypes/test_slicing.py index a592d911cbe6ca..66f9e530104cac 100644 --- a/Lib/test/test_ctypes/test_slicing.py +++ b/Lib/test/test_ctypes/test_slicing.py @@ -1,7 +1,8 @@ -import _ctypes_test import unittest from ctypes import (CDLL, POINTER, sizeof, c_byte, c_short, c_int, c_long, c_char, c_wchar, c_char_p) +from test.support import import_helper +_ctypes_test = import_helper.import_module("_ctypes_test") class SlicesTestCase(unittest.TestCase): diff --git a/Lib/test/test_ctypes/test_stringptr.py b/Lib/test/test_ctypes/test_stringptr.py index 67c61c6c3e17e6..bb6045b250ffce 100644 --- a/Lib/test/test_ctypes/test_stringptr.py +++ b/Lib/test/test_ctypes/test_stringptr.py @@ -1,9 +1,10 @@ -import _ctypes_test import sys import unittest from test import support from ctypes import (CDLL, Structure, POINTER, create_string_buffer, c_char, c_char_p) +from test.support import import_helper +_ctypes_test = import_helper.import_module("_ctypes_test") lib = CDLL(_ctypes_test.__file__) diff --git a/Lib/test/test_ctypes/test_structures.py b/Lib/test/test_ctypes/test_structures.py index 98bc4bdcac9306..75090c4ff46cae 100644 --- a/Lib/test/test_ctypes/test_structures.py +++ b/Lib/test/test_ctypes/test_structures.py @@ -1,4 +1,3 @@ -import _ctypes_test from platform import architecture as _architecture import struct import sys @@ -12,6 +11,8 @@ from struct import calcsize from collections import namedtuple from test import support +from test.support import import_helper +_ctypes_test = import_helper.import_module("_ctypes_test") from ._support import (_CData, PyCStructType, Py_TPFLAGS_DISALLOW_INSTANTIATION, Py_TPFLAGS_IMMUTABLETYPE) diff --git a/Lib/test/test_ctypes/test_unicode.py b/Lib/test/test_ctypes/test_unicode.py index 2ddc7c56544e35..d9e17371d13572 100644 --- a/Lib/test/test_ctypes/test_unicode.py +++ b/Lib/test/test_ctypes/test_unicode.py @@ -1,6 +1,7 @@ -import _ctypes_test import ctypes import unittest +from test.support import import_helper +_ctypes_test = import_helper.import_module("_ctypes_test") class UnicodeTestCase(unittest.TestCase): diff --git a/Lib/test/test_ctypes/test_values.py b/Lib/test/test_ctypes/test_values.py index d0b4803dff8529..1b757e020d5ce2 100644 --- a/Lib/test/test_ctypes/test_values.py +++ b/Lib/test/test_ctypes/test_values.py @@ -2,7 +2,6 @@ A testcase which accesses *values* in a dll. """ -import _ctypes_test import _imp import importlib.util import sys @@ -15,10 +14,14 @@ class ValuesTestCase(unittest.TestCase): + def setUp(self): + _ctypes_test = import_helper.import_module("_ctypes_test") + self.ctdll = CDLL(_ctypes_test.__file__) + def test_an_integer(self): # This test checks and changes an integer stored inside the # _ctypes_test dll/shared lib. - ctdll = CDLL(_ctypes_test.__file__) + ctdll = self.ctdll an_integer = c_int.in_dll(ctdll, "an_integer") x = an_integer.value self.assertEqual(x, ctdll.get_an_integer()) @@ -30,8 +33,7 @@ def test_an_integer(self): self.assertEqual(x, ctdll.get_an_integer()) def test_undefined(self): - ctdll = CDLL(_ctypes_test.__file__) - self.assertRaises(ValueError, c_int.in_dll, ctdll, "Undefined_Symbol") + self.assertRaises(ValueError, c_int.in_dll, self.ctdll, "Undefined_Symbol") class PythonValuesTestCase(unittest.TestCase): diff --git a/Lib/test/test_ctypes/test_win32.py b/Lib/test/test_ctypes/test_win32.py index 4aaecd8d38f98f..31919118670613 100644 --- a/Lib/test/test_ctypes/test_win32.py +++ b/Lib/test/test_ctypes/test_win32.py @@ -1,6 +1,5 @@ # Windows specific tests -import _ctypes_test import ctypes import errno import sys @@ -9,6 +8,7 @@ _pointer_type_cache, c_void_p, c_char, c_int, c_long) from test import support +from test.support import import_helper from ._support import Py_TPFLAGS_DISALLOW_INSTANTIATION, Py_TPFLAGS_IMMUTABLETYPE @@ -36,6 +36,7 @@ def test_noargs(self): @unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') class ReturnStructSizesTestCase(unittest.TestCase): def test_sizes(self): + _ctypes_test = import_helper.import_module("_ctypes_test") dll = CDLL(_ctypes_test.__file__) for i in range(1, 11): fields = [ (f"f{f}", c_char) for f in range(1, i + 1)] @@ -116,6 +117,7 @@ class RECT(Structure): ("right", c_long), ("bottom", c_long)] + _ctypes_test = import_helper.import_module("_ctypes_test") dll = CDLL(_ctypes_test.__file__) pt = POINT(15, 25) diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 6c60854bbd76cc..88b72a00cc2153 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -19,6 +19,12 @@ if not support.has_subprocess_support: raise unittest.SkipTest("test module requires subprocess") +try: + import _testinternalcapi +except ImportError: + raise unittest.SkipTest("requires _testinternalcapi") + + MACOS = (sys.platform == 'darwin') PYMEM_ALLOCATOR_NOT_SET = 0 PYMEM_ALLOCATOR_DEBUG = 2 diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index c5eff8ad8ccca1..04e24f1af8725a 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -24,7 +24,6 @@ INT_MAX = 2**31 - 1 - class NaiveException(Exception): def __init__(self, x): self.x = x @@ -346,7 +345,7 @@ class InvalidException: pass def test_capi1(): - import _testcapi + _testcapi = import_module("_testcapi") try: _testcapi.raise_exception(BadException, 1) except TypeError as err: @@ -357,7 +356,7 @@ def test_capi1(): self.fail("Expected exception") def test_capi2(): - import _testcapi + _testcapi = import_module("_testcapi") try: _testcapi.raise_exception(BadException, 0) except RuntimeError as err: @@ -371,7 +370,7 @@ def test_capi2(): self.fail("Expected exception") def test_capi3(): - import _testcapi + _testcapi = import_module("_testcapi") self.assertRaises(SystemError, _testcapi.raise_exception, InvalidException, 1) @@ -1381,6 +1380,7 @@ def foo(): @cpython_only def test_recursion_normalizing_exception(self): + import_module("_testinternalcapi") # Issue #22898. # Test that a RecursionError is raised when tstate->recursion_depth is # equal to recursion_limit in PyErr_NormalizeException() and check @@ -1436,6 +1436,7 @@ def gen(): @cpython_only def test_recursion_normalizing_infinite_exception(self): + import_module("_testcapi") # Issue #30697. Test that a RecursionError is raised when # maximum recursion depth has been exceeded when creating # an exception @@ -1504,6 +1505,7 @@ def recurse_in_body_and_except(): # _PyRefchain_Trace() on memory allocation error. @unittest.skipIf(support.Py_TRACE_REFS, 'cannot test Py_TRACE_REFS build') def test_recursion_normalizing_with_no_memory(self): + import_module("_testcapi") # 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 # the size of the list of preallocated MemoryError instances, the @@ -1528,11 +1530,11 @@ def recurse(cnt): def test_MemoryError(self): # PyErr_NoMemory always raises the same exception instance. # Check that the traceback is not doubled. + _testcapi = import_module("_testcapi") import traceback - from _testcapi import raise_memoryerror def raiseMemError(): try: - raise_memoryerror() + _testcapi.raise_memoryerror() except MemoryError as e: tb = e.__traceback__ else: @@ -1545,7 +1547,7 @@ def raiseMemError(): @cpython_only def test_exception_with_doc(self): - import _testcapi + _testcapi = import_module("_testcapi") doc2 = "This is a test docstring." doc4 = "This is another test docstring." @@ -1587,7 +1589,7 @@ class C(object): def test_memory_error_cleanup(self): # Issue #5437: preallocated MemoryError instances should not keep # traceback objects alive. - from _testcapi import raise_memoryerror + _testcapi = import_module("_testcapi") class C: pass wr = None @@ -1595,7 +1597,7 @@ def inner(): nonlocal wr c = C() wr = weakref.ref(c) - raise_memoryerror() + _testcapi.raise_memoryerror() # We cannot use assertRaises since it manually deletes the traceback try: inner() @@ -1675,6 +1677,7 @@ def test_unhandled(self): # _PyRefchain_Trace() on memory allocation error. @unittest.skipIf(support.Py_TRACE_REFS, 'cannot test Py_TRACE_REFS build') def test_memory_error_in_PyErr_PrintEx(self): + import_module("_testcapi") code = """if 1: import _testcapi class C(): pass @@ -1793,6 +1796,7 @@ class TestException(MemoryError): gc_collect() def test_memory_error_in_subinterp(self): + import_module("_testcapi") # gh-109894: subinterpreters shouldn't count on last resort memory error # when MemoryError is raised through PyErr_NoMemory() call, # and should preallocate memory errors as does the main interpreter. diff --git a/Lib/test/test_external_inspection.py b/Lib/test/test_external_inspection.py index 86c07de507e39c..d896fec73d1971 100644 --- a/Lib/test/test_external_inspection.py +++ b/Lib/test/test_external_inspection.py @@ -14,7 +14,7 @@ from _testexternalinspection import PROCESS_VM_READV_SUPPORTED from _testexternalinspection import get_stack_trace except ImportError: - unittest.skip("Test only runs when _testexternalinspection is available") + raise unittest.SkipTest("Test only runs when _testexternalinspection is available") def _make_test_script(script_dir, script_basename, source): to_return = make_script(script_dir, script_basename, source) diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index d0473500a17735..200f34d18ca60a 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -266,6 +266,7 @@ def test_sigill(self): 5, 'Illegal instruction') + @unittest.skipIf(_testcapi is None, 'need _testcapi') def check_fatal_error_func(self, release_gil): # Test that Py_FatalError() dumps a traceback with support.SuppressCrashReport(): diff --git a/Lib/test/test_fcntl.py b/Lib/test/test_fcntl.py index 8b4ed4a9e3a4fe..d07f931be0de9a 100644 --- a/Lib/test/test_fcntl.py +++ b/Lib/test/test_fcntl.py @@ -117,7 +117,9 @@ def test_fcntl_bad_file(self): @cpython_only def test_fcntl_bad_file_overflow(self): - from _testcapi import INT_MAX, INT_MIN + _testcapi = import_module("_testcapi") + INT_MAX = _testcapi.INT_MAX + INT_MIN = _testcapi.INT_MIN # Issue 15989 with self.assertRaises(OverflowError): fcntl.fcntl(INT_MAX + 1, fcntl.F_SETFL, os.O_NONBLOCK) @@ -189,7 +191,7 @@ def test_lockf_share(self): @cpython_only def test_flock_overflow(self): - import _testcapi + _testcapi = import_module("_testcapi") self.assertRaises(OverflowError, fcntl.flock, _testcapi.INT_MAX+1, fcntl.LOCK_SH) diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py index 06d5a8abf32083..0611d1749f41c1 100644 --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -17,6 +17,7 @@ TESTFN, TESTFN_ASCII, TESTFN_UNICODE, make_bad_fd, ) from test.support.warnings_helper import check_warnings +from test.support.import_helper import import_module from collections import UserList import _io # C implementation of io @@ -597,7 +598,7 @@ class COtherFileTests(OtherFileTests, unittest.TestCase): @cpython_only def testInvalidFd_overflow(self): # Issue 15989 - import _testcapi + _testcapi = import_module("_testcapi") self.assertRaises(TypeError, self.FileIO, _testcapi.INT_MAX + 1) self.assertRaises(TypeError, self.FileIO, _testcapi.INT_MIN - 1) diff --git a/Lib/test/test_finalization.py b/Lib/test/test_finalization.py index 1d134430909d84..42871f8a09b16b 100644 --- a/Lib/test/test_finalization.py +++ b/Lib/test/test_finalization.py @@ -13,7 +13,7 @@ def with_tp_del(cls): class C(object): def __new__(cls, *args, **kwargs): - raise TypeError('requires _testcapi.with_tp_del') + raise unittest.SkipTest('requires _testcapi.with_tp_del') return C try: @@ -22,7 +22,7 @@ def __new__(cls, *args, **kwargs): def without_gc(cls): class C: def __new__(cls, *args, **kwargs): - raise TypeError('requires _testcapi.without_gc') + raise unittest.SkipTest('requires _testcapi.without_gc') return C from test import support diff --git a/Lib/test/test_gdb/test_misc.py b/Lib/test/test_gdb/test_misc.py index 92c5447ece0777..1047f4867c1d03 100644 --- a/Lib/test/test_gdb/test_misc.py +++ b/Lib/test/test_gdb/test_misc.py @@ -1,6 +1,6 @@ import re import unittest -from test.support import python_is_optimized, requires_limited_api +from test.support import python_is_optimized from .util import run_gdb, setup_module, DebuggerTests, SAMPLE_SCRIPT @@ -85,7 +85,6 @@ def baz(*args): class StackNavigationTests(DebuggerTests): - @requires_limited_api @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") @unittest.skipIf(python_is_optimized(), "Python was compiled with optimizations") @@ -115,7 +114,6 @@ def test_up_at_top(self): self.assertEndsWith(bt, 'Unable to find an older python frame\n') - @requires_limited_api @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") @unittest.skipIf(python_is_optimized(), "Python was compiled with optimizations") @@ -131,7 +129,6 @@ def test_up_then_down(self): $''') class PyPrintTests(DebuggerTests): - @requires_limited_api @unittest.skipIf(python_is_optimized(), "Python was compiled with optimizations") def test_basic_command(self): @@ -141,7 +138,6 @@ def test_basic_command(self): self.assertMultilineMatches(bt, r".*\nlocal 'args' = \(1, 2, 3\)\n.*") - @requires_limited_api @unittest.skipIf(python_is_optimized(), "Python was compiled with optimizations") @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index c36d228112c587..76af8bb53f221b 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -32,7 +32,7 @@ except ImportError: ThreadPoolExecutor = None -from test.support import cpython_only, requires_limited_api +from test.support import cpython_only, import_helper from test.support import MISSING_C_DOCSTRINGS, ALWAYS_EQ from test.support.import_helper import DirsOnSysPath, ready_to_import from test.support.os_helper import TESTFN @@ -1203,9 +1203,8 @@ def test_getfullargspec_builtin_methods(self): @cpython_only @unittest.skipIf(MISSING_C_DOCSTRINGS, "Signature information for builtins requires docstrings") - @requires_limited_api def test_getfullargspec_builtin_func(self): - import _testcapi + _testcapi = import_helper.import_module("_testcapi") builtin = _testcapi.docstring_with_signature_with_defaults spec = inspect.getfullargspec(builtin) self.assertEqual(spec.defaults[0], 'avocado') @@ -1213,9 +1212,8 @@ def test_getfullargspec_builtin_func(self): @cpython_only @unittest.skipIf(MISSING_C_DOCSTRINGS, "Signature information for builtins requires docstrings") - @requires_limited_api def test_getfullargspec_builtin_func_no_signature(self): - import _testcapi + _testcapi = import_helper.import_module("_testcapi") builtin = _testcapi.docstring_no_signature with self.assertRaises(TypeError): inspect.getfullargspec(builtin) @@ -2875,9 +2873,8 @@ def test_staticmethod(*args): # NOQA @cpython_only @unittest.skipIf(MISSING_C_DOCSTRINGS, "Signature information for builtins requires docstrings") - @requires_limited_api def test_signature_on_builtins(self): - import _testcapi + _testcapi = import_helper.import_module("_testcapi") def test_unbound_method(o): """Use this to test unbound methods (things that should have a self)""" @@ -2957,9 +2954,8 @@ class ThisWorksNow: @cpython_only @unittest.skipIf(MISSING_C_DOCSTRINGS, "Signature information for builtins requires docstrings") - @requires_limited_api def test_signature_on_decorated_builtins(self): - import _testcapi + _testcapi = import_helper.import_module("_testcapi") func = _testcapi.docstring_with_signature_with_defaults def decorator(func): @@ -2979,9 +2975,8 @@ def wrapper_like(*args, **kwargs) -> int: pass inspect.signature(wrapper_like)) @cpython_only - @requires_limited_api def test_signature_on_builtins_no_signature(self): - import _testcapi + _testcapi = import_helper.import_module("_testcapi") with self.assertRaisesRegex(ValueError, 'no signature found for builtin'): inspect.signature(_testcapi.docstring_no_signature) diff --git a/Lib/test/test_pydoc/test_pydoc.py b/Lib/test/test_pydoc/test_pydoc.py index d2bacd86f02bae..436fdb38756ddd 100644 --- a/Lib/test/test_pydoc/test_pydoc.py +++ b/Lib/test/test_pydoc/test_pydoc.py @@ -1371,32 +1371,29 @@ def test_bound_builtin_classmethod_o(self): @support.cpython_only @requires_docstrings - @support.requires_limited_api def test_module_level_callable_unrepresentable_default(self): - import _testcapi + _testcapi = import_helper.import_module("_testcapi") builtin = _testcapi.func_with_unrepresentable_signature self.assertEqual(self._get_summary_line(builtin), "func_with_unrepresentable_signature(a, b=)") @support.cpython_only @requires_docstrings - @support.requires_limited_api def test_builtin_staticmethod_unrepresentable_default(self): self.assertEqual(self._get_summary_line(str.maketrans), "maketrans(x, y=, z=, /)") - import _testcapi + _testcapi = import_helper.import_module("_testcapi") cls = _testcapi.DocStringUnrepresentableSignatureTest self.assertEqual(self._get_summary_line(cls.staticmeth), "staticmeth(a, b=)") @support.cpython_only @requires_docstrings - @support.requires_limited_api def test_unbound_builtin_method_unrepresentable_default(self): self.assertEqual(self._get_summary_line(dict.pop), "pop(self, key, default=, /) " "unbound builtins.dict method") - import _testcapi + _testcapi = import_helper.import_module("_testcapi") cls = _testcapi.DocStringUnrepresentableSignatureTest self.assertEqual(self._get_summary_line(cls.meth), "meth(self, /, a, b=) unbound " @@ -1404,12 +1401,11 @@ def test_unbound_builtin_method_unrepresentable_default(self): @support.cpython_only @requires_docstrings - @support.requires_limited_api def test_bound_builtin_method_unrepresentable_default(self): self.assertEqual(self._get_summary_line({}.pop), "pop(key, default=, /) " "method of builtins.dict instance") - import _testcapi + _testcapi = import_helper.import_module("_testcapi") obj = _testcapi.DocStringUnrepresentableSignatureTest() self.assertEqual(self._get_summary_line(obj.meth), "meth(a, b=) " @@ -1417,9 +1413,8 @@ def test_bound_builtin_method_unrepresentable_default(self): @support.cpython_only @requires_docstrings - @support.requires_limited_api def test_unbound_builtin_classmethod_unrepresentable_default(self): - import _testcapi + _testcapi = import_helper.import_module("_testcapi") cls = _testcapi.DocStringUnrepresentableSignatureTest descr = cls.__dict__['classmeth'] self.assertEqual(self._get_summary_line(descr), @@ -1428,9 +1423,8 @@ def test_unbound_builtin_classmethod_unrepresentable_default(self): @support.cpython_only @requires_docstrings - @support.requires_limited_api def test_bound_builtin_classmethod_unrepresentable_default(self): - import _testcapi + _testcapi = import_helper.import_module("_testcapi") cls = _testcapi.DocStringUnrepresentableSignatureTest self.assertEqual(self._get_summary_line(cls.classmeth), "classmeth(a, b=) class method of " diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index 10f59cd0b859f5..4182de246a071b 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -31,10 +31,10 @@ from test.support import ( SHORT_TIMEOUT, check_disallow_instantiation, requires_subprocess, - is_apple, is_emscripten, is_wasi, requires_limited_api + is_apple, is_emscripten, is_wasi ) from test.support import gc_collect -from test.support import threading_helper +from test.support import threading_helper, import_helper from os import SEEK_SET, SEEK_CUR, SEEK_END from test.support.os_helper import TESTFN, TESTFN_UNDECODABLE, unlink, temp_dir, FakePath @@ -1212,16 +1212,15 @@ def test_blob_seek_error(self): with self.subTest(exc=exc, msg=msg, fn=fn): self.assertRaisesRegex(exc, msg, fn) - @requires_limited_api - def test_blob_seek_error_overflow(self): + def test_blob_seek_overflow_error(self): # Force overflow errors - from _testcapi import INT_MAX msg_of = "seek offset results in overflow" + _testcapi = import_helper.import_module("_testcapi") self.blob.seek(1, SEEK_SET) with self.assertRaisesRegex(OverflowError, msg_of): - self.blob.seek(INT_MAX, SEEK_CUR) + self.blob.seek(_testcapi.INT_MAX, SEEK_CUR) with self.assertRaisesRegex(OverflowError, msg_of): - self.blob.seek(INT_MAX, SEEK_END) + self.blob.seek(_testcapi.INT_MAX, SEEK_END) def test_blob_read(self): buf = self.blob.read() @@ -1382,18 +1381,16 @@ def test_blob_get_item_error(self): with self.assertRaisesRegex(IndexError, "index out of range"): self.blob[idx] - @requires_limited_api - def test_blob_get_item_ullong_max(self): - from _testcapi import ULLONG_MAX - with self.assertRaisesRegex(IndexError, "cannot fit 'int'"): - self.blob[ULLONG_MAX] - - def test_blob_get_item_read_error(self): # Provoke read error self.cx.execute("update test set b='aaaa' where rowid=1") with self.assertRaises(sqlite.OperationalError): self.blob[0] + def test_blob_get_item_error_bigint(self): + _testcapi = import_helper.import_module("_testcapi") + with self.assertRaisesRegex(IndexError, "cannot fit 'int'"): + self.blob[_testcapi.ULLONG_MAX] + def test_blob_set_item_error(self): with self.assertRaisesRegex(TypeError, "cannot be interpreted"): self.blob[0] = b"multiple" From d05dcd7e6c2ab19b62cea93cdc7bea84d658d9db Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 10:42:23 +0100 Subject: [PATCH 06/35] More skips --- Lib/test/support/__init__.py | 15 ++++++++++++--- Lib/test/test_capi/__init__.py | 4 +--- Lib/test/test_capi/test_dict.py | 2 +- Lib/test/test_capi/test_opt.py | 4 ++-- Lib/test/test_format.py | 4 +++- Lib/test/test_gc.py | 4 +++- Lib/test/test_genericclass.py | 5 ++++- Lib/test/test_import/__init__.py | 12 ++++++++---- Lib/test/test_monitoring.py | 5 +++-- Lib/test/test_multibytecodec.py | 3 ++- Lib/test/test_opcache.py | 3 ++- Lib/test/test_os.py | 2 ++ Lib/test/test_perfmaps.py | 6 +++++- Lib/test/test_poll.py | 5 ++++- Lib/test/test_regrtest.py | 8 ++++++++ Lib/test/test_socket.py | 20 ++++++++++---------- Lib/test/test_stable_abi_ctypes.py | 5 ++++- Lib/test/test_sys.py | 2 +- Lib/test/test_threading.py | 3 ++- 19 files changed, 77 insertions(+), 35 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 4ca42448271687..8ce7ca8db43bbc 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -1715,7 +1715,10 @@ def run_in_subinterp_with_config(code, *, own_gil=None, **config): module is enabled. """ _check_tracemalloc() - import _testinternalcapi + try: + import _testinternalcapi + except ImportError: + raise SkipTest("requires _testinternalcapi") if own_gil is not None: assert 'gil' not in config, (own_gil, config) config['gil'] = 2 if own_gil else 1 @@ -1877,12 +1880,18 @@ def restore(self): def with_pymalloc(): - import _testcapi + try: + import _testcapi + except ImportError: + raise unittest.SkipTest("requires _testcapi") return _testcapi.WITH_PYMALLOC and not Py_GIL_DISABLED def with_mimalloc(): - import _testcapi + try: + import _testcapi + except ImportError: + raise unittest.SkipTest("requires _testcapi") return _testcapi.WITH_MIMALLOC diff --git a/Lib/test/test_capi/__init__.py b/Lib/test/test_capi/__init__.py index 889a66ad2dc0d2..4b16ecc31156a5 100644 --- a/Lib/test/test_capi/__init__.py +++ b/Lib/test/test_capi/__init__.py @@ -1,7 +1,5 @@ import os -from test.support import load_package_tests, import_helper - -import_helper.import_module("_testcapi") +from test.support import load_package_tests def load_tests(*args): return load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/test_capi/test_dict.py b/Lib/test/test_capi/test_dict.py index cca6145bc90c04..f9af80dea57377 100644 --- a/Lib/test/test_capi/test_dict.py +++ b/Lib/test/test_capi/test_dict.py @@ -2,7 +2,7 @@ from collections import OrderedDict, UserDict from types import MappingProxyType from test import support -import _testcapi +_testcapi = support.import_helper.import_module("_testcapi") NULL = None diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index a0a19225b79433..f9f9216c1861c0 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -6,9 +6,9 @@ import gc import os -import _testinternalcapi - from test.support import script_helper, requires_specialization +from test.support.import_helper import import_module +_testinternalcapi = import_module("_testinternalcapi") @contextlib.contextmanager diff --git a/Lib/test/test_format.py b/Lib/test/test_format.py index 6fa49dbc0b730c..8cef621bd716ac 100644 --- a/Lib/test/test_format.py +++ b/Lib/test/test_format.py @@ -4,6 +4,7 @@ import re import test.support as support import unittest +from test.support.import_helper import import_module maxsize = support.MAX_Py_ssize_t @@ -478,7 +479,8 @@ def test_precision(self): @support.cpython_only def test_precision_c_limits(self): - from _testcapi import INT_MAX + _testcapi = import_module("_testcapi") + INT_MAX = _testcapi.INT_MAX f = 1.2 with self.assertRaises(ValueError) as cm: diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py index dd09643788d62f..e811cddc8a8188 100644 --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -18,10 +18,11 @@ try: from _testcapi import with_tp_del except ImportError: + _testcapi = None def with_tp_del(cls): class C(object): def __new__(cls, *args, **kwargs): - raise TypeError('requires _testcapi.with_tp_del') + raise unittest.SkipTest('requires _testcapi.with_tp_del') return C try: @@ -689,6 +690,7 @@ def do_work(): @cpython_only @requires_subprocess() + @unittest.skipIf(_testcapi is None, "requires _testcapi") def test_garbage_at_shutdown(self): import subprocess code = """if 1: diff --git a/Lib/test/test_genericclass.py b/Lib/test/test_genericclass.py index aece757fc1933e..e530b463966819 100644 --- a/Lib/test/test_genericclass.py +++ b/Lib/test/test_genericclass.py @@ -1,5 +1,6 @@ import unittest from test import support +from test.support.import_helper import import_module class TestMROEntry(unittest.TestCase): @@ -277,7 +278,9 @@ def __class_getitem__(cls, item): class CAPITest(unittest.TestCase): def test_c_class(self): - from _testcapi import Generic, GenericAlias + _testcapi = import_module("_testcapi") + Generic = _testcapi.Generic + GenericAlias = _testcapi.GenericAlias self.assertIsInstance(Generic.__class_getitem__(int), GenericAlias) IntGeneric = Generic[int] diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index 7b0126226c4aba..e4ba8baf0d1b88 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -29,7 +29,7 @@ is_wasi, run_in_subinterp, run_in_subinterp_with_config, Py_TRACE_REFS) from test.support.import_helper import ( forget, make_legacy_pyc, unlink, unload, ready_to_import, - DirsOnSysPath, CleanImport) + DirsOnSysPath, CleanImport, import_module) from test.support.os_helper import ( TESTFN, rmtree, temp_umask, TESTFN_UNENCODABLE) from test.support import script_helper @@ -352,7 +352,7 @@ def test_from_import_missing_attr_has_name_and_path(self): @cpython_only def test_from_import_missing_attr_has_name_and_so_path(self): - import _testcapi + _testcapi = import_module("_testcapi") with self.assertRaises(ImportError) as cm: from _testcapi import i_dont_exist self.assertEqual(cm.exception.name, '_testcapi') @@ -1836,6 +1836,7 @@ def check_incompatible_fresh(self, name, *, isolated=False): f'ImportError: module {name} does not support loading in subinterpreters', ) + @unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi") def test_builtin_compat(self): # For now we avoid using sys or builtins # since they still don't implement multi-phase init. @@ -1847,6 +1848,7 @@ def test_builtin_compat(self): self.check_compatible_here(module, strict=True) @cpython_only + @unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi") def test_frozen_compat(self): module = '_frozen_importlib' require_frozen(module, skip=True) @@ -1917,6 +1919,7 @@ def test_multi_init_extension_per_interpreter_gil_compat(self): self.check_compatible_here(modname, filename, strict=False, isolated=False) + @unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi") def test_python_compat(self): module = 'threading' require_pure_python(module) @@ -1962,6 +1965,7 @@ def check_incompatible(setting, override): with self.subTest('config: check disabled; override: disabled'): check_compatible(False, -1) + @unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi") def test_isolated_config(self): module = 'threading' require_pure_python(module) @@ -2691,7 +2695,7 @@ class CAPITests(unittest.TestCase): def test_pyimport_addmodule(self): # gh-105922: Test PyImport_AddModuleRef(), PyImport_AddModule() # and PyImport_AddModuleObject() - import _testcapi + _testcapi = import_module("_testcapi") for name in ( 'sys', # frozen module 'test', # package @@ -2701,7 +2705,7 @@ def test_pyimport_addmodule(self): def test_pyimport_addmodule_create(self): # gh-105922: Test PyImport_AddModuleRef(), create a new module - import _testcapi + _testcapi = import_module("_testcapi") name = 'dontexist' self.assertNotIn(name, sys.modules) self.addCleanup(unload, name) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 1e77eb6a2eea4c..3eed5edeea4dec 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -11,6 +11,7 @@ import asyncio from test import support from test.support import requires_specialization, script_helper +from test.support.import_helper import import_module PAIR = (0,1) @@ -1811,14 +1812,14 @@ def test_gh108976(self): class TestOptimizer(MonitoringTestBase, unittest.TestCase): def setUp(self): - import _testinternalcapi + _testinternalcapi = import_module("_testinternalcapi") self.old_opt = _testinternalcapi.get_optimizer() opt = _testinternalcapi.new_counter_optimizer() _testinternalcapi.set_optimizer(opt) super(TestOptimizer, self).setUp() def tearDown(self): - import _testinternalcapi + _testinternalcapi = import_module("_testinternalcapi") super(TestOptimizer, self).tearDown() _testinternalcapi.set_optimizer(self.old_opt) diff --git a/Lib/test/test_multibytecodec.py b/Lib/test/test_multibytecodec.py index 6451df14696933..a1e9bb29083067 100644 --- a/Lib/test/test_multibytecodec.py +++ b/Lib/test/test_multibytecodec.py @@ -12,6 +12,7 @@ from test import support from test.support import os_helper from test.support.os_helper import TESTFN +from test.support.import_helper import import_module ALL_CJKENCODINGS = [ # _codecs_cn @@ -212,7 +213,7 @@ def test_issue5640(self): @support.cpython_only def test_subinterp(self): # bpo-42846: Test a CJK codec in a subinterpreter - import _testcapi + _testcapi = import_module("_testcapi") encoding = 'cp932' text = "Python の開発は、1990 年ごろから開始されています。" code = textwrap.dedent(""" diff --git a/Lib/test/test_opcache.py b/Lib/test/test_opcache.py index 5fb4b815c95d07..3df5dbfa8c508c 100644 --- a/Lib/test/test_opcache.py +++ b/Lib/test/test_opcache.py @@ -5,12 +5,13 @@ import types import unittest from test.support import threading_helper, check_impl_detail, requires_specialization +from test.support.import_helper import import_module # Skip this module on other interpreters, it is cpython specific: if check_impl_detail(cpython=False): raise unittest.SkipTest('implementation detail specific to cpython') -import _testinternalcapi +_testinternalcapi = import_module("_testinternalcapi") def disabling_optimizer(func): diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 3b2d5fccc30f3c..5ce05338b12d82 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -58,6 +58,7 @@ try: from _testcapi import INT_MAX, PY_SSIZE_T_MAX except ImportError: + _testcapi = None INT_MAX = PY_SSIZE_T_MAX = sys.maxsize try: @@ -5258,6 +5259,7 @@ def test_fork(self): @unittest.skipUnless(sys.platform in ("linux", "darwin"), "Only Linux and macOS detect this today.") + @unittest.skipIf(_testcapi is None, "requires _testcapi") def test_fork_warns_when_non_python_thread_exists(self): code = """if 1: import os, threading, warnings diff --git a/Lib/test/test_perfmaps.py b/Lib/test/test_perfmaps.py index a17adb89f55360..d4c6fe0124af18 100644 --- a/Lib/test/test_perfmaps.py +++ b/Lib/test/test_perfmaps.py @@ -2,7 +2,11 @@ import sys import unittest -from _testinternalcapi import perf_map_state_teardown, write_perf_map_entry +try: + from _testinternalcapi import perf_map_state_teardown, write_perf_map_entry +except ImportError: + raise unittest.SkipTest("requires _testinternalcapi") + if sys.platform != 'linux': raise unittest.SkipTest('Linux only') diff --git a/Lib/test/test_poll.py b/Lib/test/test_poll.py index 1847ae95db9292..5675db8d1cab6e 100644 --- a/Lib/test/test_poll.py +++ b/Lib/test/test_poll.py @@ -172,7 +172,10 @@ def test_poll3(self): @cpython_only def test_poll_c_limits(self): - from _testcapi import USHRT_MAX, INT_MAX, UINT_MAX + try: + from _testcapi import USHRT_MAX, INT_MAX, UINT_MAX + except ImportError: + raise unittest.SkipTest("requires _testcapi") pollster = select.poll() pollster.register(1) diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index 7e1eaa7d6a515e..1ef8d0123b8d6e 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -1724,6 +1724,10 @@ def test_other_bug(self): @support.cpython_only def test_uncollectable(self): + try: + import _testcapi + except ImportError: + raise unittest.SkipTest("requires _testcapi") code = textwrap.dedent(r""" import _testcapi import gc @@ -2106,6 +2110,10 @@ def test_unload_tests(self): def check_add_python_opts(self, option): # --fast-ci and --slow-ci add "-u -W default -bb -E" options to Python + try: + import _testinternalcapi + except ImportError: + raise unittest.SkipTest("requires _testinternalcapi") code = textwrap.dedent(r""" import sys import unittest diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index b936e9ae91daca..c7faeb219004db 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -3,7 +3,7 @@ from test.support import ( is_apple, os_helper, refleak_helper, socket_helper, threading_helper ) - +from test.support.import_helper import import_module import _thread as thread import array import contextlib @@ -1171,7 +1171,7 @@ def testNtoH(self): @support.cpython_only def testNtoHErrors(self): - import _testcapi + _testcapi = import_module("_testcapi") s_good_values = [0, 1, 2, 0xffff] l_good_values = s_good_values + [0xffffffff] l_bad_values = [-1, -2, 1<<32, 1<<1000] @@ -1649,9 +1649,9 @@ def test_getaddrinfo_int_port_overflow(self): # prior to 3.12 did for ints outside of a [LONG_MIN, LONG_MAX] range. # Leave the error up to the underlying string based platform C API. - from _testcapi import ULONG_MAX, LONG_MAX, LONG_MIN + _testcapi = import_module("_testcapi") try: - socket.getaddrinfo(None, ULONG_MAX + 1, type=socket.SOCK_STREAM) + socket.getaddrinfo(None, _testcapi.ULONG_MAX + 1, type=socket.SOCK_STREAM) except OverflowError: # Platforms differ as to what values consitute a getaddrinfo() error # return. Some fail for LONG_MAX+1, others ULONG_MAX+1, and Windows @@ -1661,21 +1661,21 @@ def test_getaddrinfo_int_port_overflow(self): pass try: - socket.getaddrinfo(None, LONG_MAX + 1, type=socket.SOCK_STREAM) + socket.getaddrinfo(None, _testcapi.LONG_MAX + 1, type=socket.SOCK_STREAM) except OverflowError: self.fail("Either no error or socket.gaierror expected.") except socket.gaierror: pass try: - socket.getaddrinfo(None, LONG_MAX - 0xffff + 1, type=socket.SOCK_STREAM) + socket.getaddrinfo(None, _testcapi.LONG_MAX - 0xffff + 1, type=socket.SOCK_STREAM) except OverflowError: self.fail("Either no error or socket.gaierror expected.") except socket.gaierror: pass try: - socket.getaddrinfo(None, LONG_MIN - 1, type=socket.SOCK_STREAM) + socket.getaddrinfo(None, _testcapi.LONG_MIN - 1, type=socket.SOCK_STREAM) except OverflowError: self.fail("Either no error or socket.gaierror expected.") except socket.gaierror: @@ -1831,7 +1831,7 @@ def test_listen_backlog(self): @support.cpython_only def test_listen_backlog_overflow(self): # Issue 15989 - import _testcapi + _testcapi = import_module("_testcapi") with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as srv: srv.bind((HOST, 0)) self.assertRaises(OverflowError, srv.listen, _testcapi.INT_MAX + 1) @@ -2727,7 +2727,7 @@ def _testShutdown(self): @support.cpython_only def _testShutdown_overflow(self): - import _testcapi + _testcapi = import_module("_testcapi") self.serv_conn.send(MSG) # Issue 15989 self.assertRaises(OverflowError, self.serv_conn.shutdown, @@ -4884,7 +4884,7 @@ def _testSetBlocking(self): @support.cpython_only def testSetBlocking_overflow(self): # Issue 15989 - import _testcapi + _testcapi = import_module("_testcapi") if _testcapi.UINT_MAX >= _testcapi.ULONG_MAX: self.skipTest('needs UINT_MAX < ULONG_MAX') diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py index 8bd373976426ef..27c4fbcde09889 100644 --- a/Lib/test/test_stable_abi_ctypes.py +++ b/Lib/test/test_stable_abi_ctypes.py @@ -6,7 +6,10 @@ import sys import unittest from test.support.import_helper import import_module -from _testcapi import get_feature_macros +try: + from _testcapi import get_feature_macros +except ImportError: + raise unittest.SkipTest("requires _testcapi") feature_macros = get_feature_macros() diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 38dcabd84d8170..fdca45990f99f9 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1390,7 +1390,7 @@ class SizeofTest(unittest.TestCase): def setUp(self): self.P = struct.calcsize('P') self.longdigit = sys.int_info.sizeof_digit - import _testinternalcapi + _testinternalcapi = import_helper.import_module("_testinternalcapi") self.gc_headsize = _testinternalcapi.SIZEOF_PYGC_HEAD self.managed_pre_header_size = _testinternalcapi.SIZEOF_MANAGED_PRE_HEADER diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 3b5c37c948c8c3..7186b09226c91f 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -1010,7 +1010,7 @@ def callback(): threading.settrace(noop_trace) # Create a generator in a C thread which exits after the call - import _testcapi + _testcapi = import_module("_testcapi") _testcapi.call_in_temporary_c_thread(callback) # Call the generator in a different Python thread, check that the @@ -1509,6 +1509,7 @@ def task(): @cpython_only def test_daemon_threads_fatal_error(self): + import_module("_testcapi") subinterp_code = f"""if 1: import os import threading From cb7cff48ed5a824c6f5fb218b39575589ad40359 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 10:50:15 +0100 Subject: [PATCH 07/35] Fix gc and weakref tests --- Lib/test/test_gc.py | 6 ++---- Lib/test/test_weakref.py | 3 ++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py index e811cddc8a8188..1fe3901c8122f9 100644 --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -16,7 +16,9 @@ import weakref try: + import _testcapi from _testcapi import with_tp_del + from _testcapi import ContainerNoGC except ImportError: _testcapi = None def with_tp_del(cls): @@ -24,10 +26,6 @@ class C(object): def __new__(cls, *args, **kwargs): raise unittest.SkipTest('requires _testcapi.with_tp_del') return C - -try: - from _testcapi import ContainerNoGC -except ImportError: ContainerNoGC = None ### Support code diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py index 4cdd66d3769e0c..f690a0de91383f 100644 --- a/Lib/test/test_weakref.py +++ b/Lib/test/test_weakref.py @@ -14,6 +14,7 @@ from test import support from test.support import script_helper, ALWAYS_EQ from test.support import gc_collect +from test.support import import_helper from test.support import threading_helper # Used in ReferencesTestCase.test_ref_created_during_del() . @@ -134,7 +135,7 @@ def test_basic_callback(self): @support.cpython_only def test_cfunction(self): - import _testcapi + _testcapi = import_helper.import_module("_testcapi") create_cfunction = _testcapi.create_cfunction f = create_cfunction() wr = weakref.ref(f) From ad5e3b6521602651798e63806b38dc8858109431 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 10:50:43 +0100 Subject: [PATCH 08/35] Remove local debug stuff --- Lib/test/test_builtin.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 5e8b06d0c127b8..9a0bf524e3943f 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -47,9 +47,6 @@ HAVE_DOUBLE_ROUNDING = (x + y == 1e16 + 4) -raise unittest.SkipTest("FAIL") - - class Squares: def __init__(self, max): From cdb8bf4bbf3069fbb7f4c624b323a5f355c1c56c Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 10:59:31 +0100 Subject: [PATCH 09/35] Fix test_os --- Lib/test/test_os.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 5ce05338b12d82..ad78943eb1a389 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -56,6 +56,7 @@ except (ImportError, AttributeError): all_users = [] try: + import _testcapi from _testcapi import INT_MAX, PY_SSIZE_T_MAX except ImportError: _testcapi = None From e4a30b0db7694ebbb0e4423235588fd2a46f5afe Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 11:34:34 +0100 Subject: [PATCH 10/35] Fixup stable_abi.py --- Tools/build/stable_abi.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Tools/build/stable_abi.py b/Tools/build/stable_abi.py index 83146622c74f94..6a631c6033d5bd 100644 --- a/Tools/build/stable_abi.py +++ b/Tools/build/stable_abi.py @@ -275,7 +275,10 @@ def gen_ctypes_test(manifest, args, outfile): import sys import unittest from test.support.import_helper import import_module - from _testcapi import get_feature_macros + try: + from _testcapi import get_feature_macros + except ImportError: + raise unittest.SkipTest("requires _testcapi") feature_macros = get_feature_macros() From fabb0071a1dc1649f9188242f891387f0d3f6fc4 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 11:53:44 +0100 Subject: [PATCH 11/35] Fixup run_in_subinterp --- Lib/test/support/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 8ce7ca8db43bbc..b0a610b5daa23e 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -1698,14 +1698,16 @@ def patch_list(orig): orig[:] = saved -@requires_limited_api def run_in_subinterp(code): """ Run code in a subinterpreter. Raise unittest.SkipTest if the tracemalloc module is enabled. """ _check_tracemalloc() - import _testcapi + try: + import _testcapi + except ImportError: + raise SkipTest("requires _testcapi") return _testcapi.run_in_subinterp(code) From c51dafa50d35952102a1c27641062332845b697f Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 12:08:25 +0100 Subject: [PATCH 12/35] Fixup test_call --- Lib/test/test_call.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_call.py b/Lib/test/test_call.py index 341afcadd8df38..f246fe6c3bd85b 100644 --- a/Lib/test/test_call.py +++ b/Lib/test/test_call.py @@ -1023,8 +1023,8 @@ class TestRecursion(unittest.TestCase): @skip_on_s390x @unittest.skipIf(is_wasi and Py_DEBUG, "requires deep stack") + @unittest.skipIf(_testcapi is None, "requires _testcapi") def test_super_deep(self): - _testcapi = import_helper.import_module("_testcapi") def recurse(n): if n: From c3f9c9967343f75ece213a86ca9b7bd4259f9bb5 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 12:10:31 +0100 Subject: [PATCH 13/35] Fixup test_audit --- Lib/test/test_audit.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_audit.py b/Lib/test/test_audit.py index 30d9ce06fe1b6a..b48788d363db22 100644 --- a/Lib/test/test_audit.py +++ b/Lib/test/test_audit.py @@ -7,7 +7,6 @@ from test import support from test.support import import_helper from test.support import os_helper -from test.support import requires_limited_api if not hasattr(sys, "addaudithook") or not hasattr(sys, "audit"): @@ -89,8 +88,11 @@ def test_excepthook(self): [("sys.excepthook", " ", "RuntimeError('fatal-error')")], events ) - @requires_limited_api def test_unraisablehook(self): + try: + import _testcapi + except ImportError: + raise unittest.SkipTest("requires _testcapi") returncode, events, stderr = self.run_python("test_unraisablehook") if returncode: self.fail(stderr) From fde9548ad093b8015d668c9eb5268d313aeca2bc Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 12:46:48 +0100 Subject: [PATCH 14/35] Fix some _testsinglephase issues --- .../test_importlib/extension/test_loader.py | 4 +- Lib/test/test_importlib/util.py | 5 +++ Modules/Setup.stdlib.in | 2 +- configure | 44 +++++++++++++++++++ configure.ac | 1 + 5 files changed, 53 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py index 84a0680e4ec653..650e53e20e3e61 100644 --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -108,7 +108,7 @@ def setUp(self): ) finder = self.machinery.FileFinder(None) self.spec = importlib.util.find_spec(self.name) - assert self.spec + self.assertIsNotNone(self.spec) self.loader = self.machinery.ExtensionFileLoader( self.name, self.spec.origin) @@ -189,7 +189,7 @@ def setUp(self): ) finder = self.machinery.FileFinder(None) self.spec = importlib.util.find_spec(self.name) - assert self.spec + self.assertIsNotNone(self.spec) self.loader = self.machinery.ExtensionFileLoader( self.name, self.spec.origin) diff --git a/Lib/test/test_importlib/util.py b/Lib/test/test_importlib/util.py index c25be096e52874..977aa5a3f259f9 100644 --- a/Lib/test/test_importlib/util.py +++ b/Lib/test/test_importlib/util.py @@ -13,6 +13,11 @@ import tempfile import types +try: + import _testsinglephase +except ImportError: + raise unittest.SkipTest("requires _testsinglephase") + BUILTINS = types.SimpleNamespace() BUILTINS.good_name = None diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 73b082691a3fd4..297823439ab0f1 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -170,7 +170,7 @@ *shared* @MODULE__TESTIMPORTMULTIPLE_TRUE@_testimportmultiple _testimportmultiple.c @MODULE__TESTMULTIPHASE_TRUE@_testmultiphase _testmultiphase.c -@MODULE__TESTMULTIPHASE_TRUE@_testsinglephase _testsinglephase.c +@MODULE__TESTSINGLEPHASE_TRUE@_testsinglephase _testsinglephase.c @MODULE__TESTEXTERNALINSPECTION_TRUE@_testexternalinspection _testexternalinspection.c @MODULE__CTYPES_TEST_TRUE@_ctypes_test _ctypes/_ctypes_test.c diff --git a/configure b/configure index 4a980fea453697..8b8189b4fffcef 100755 --- a/configure +++ b/configure @@ -663,6 +663,8 @@ MODULE_XXSUBTYPE_FALSE MODULE_XXSUBTYPE_TRUE MODULE__TESTEXTERNALINSPECTION_FALSE MODULE__TESTEXTERNALINSPECTION_TRUE +MODULE__TESTSINGLEPHASE_FALSE +MODULE__TESTSINGLEPHASE_TRUE MODULE__TESTMULTIPHASE_FALSE MODULE__TESTMULTIPHASE_TRUE MODULE__TESTIMPORTMULTIPLE_FALSE @@ -30877,6 +30879,44 @@ fi printf "%s\n" "$py_cv_module__testmultiphase" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _testsinglephase" >&5 +printf %s "checking for stdlib extension module _testsinglephase... " >&6; } + if test "$py_cv_module__testsinglephase" != "n/a" +then : + + if test "$TEST_MODULES" = yes +then : + if test "$ac_cv_func_dlopen" = yes +then : + py_cv_module__testsinglephase=yes +else $as_nop + py_cv_module__testsinglephase=missing +fi +else $as_nop + py_cv_module__testsinglephase=disabled +fi + +fi + as_fn_append MODULE_BLOCK "MODULE__TESTSINGLEPHASE_STATE=$py_cv_module__testsinglephase$as_nl" + if test "x$py_cv_module__testsinglephase" = xyes +then : + + + + +fi + if test "$py_cv_module__testsinglephase" = yes; then + MODULE__TESTSINGLEPHASE_TRUE= + MODULE__TESTSINGLEPHASE_FALSE='#' +else + MODULE__TESTSINGLEPHASE_TRUE='#' + MODULE__TESTSINGLEPHASE_FALSE= +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__testsinglephase" >&5 +printf "%s\n" "$py_cv_module__testsinglephase" >&6; } + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _testexternalinspection" >&5 printf %s "checking for stdlib extension module _testexternalinspection... " >&6; } if test "$py_cv_module__testexternalinspection" != "n/a" @@ -31527,6 +31567,10 @@ if test -z "${MODULE__TESTMULTIPHASE_TRUE}" && test -z "${MODULE__TESTMULTIPHASE as_fn_error $? "conditional \"MODULE__TESTMULTIPHASE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__TESTSINGLEPHASE_TRUE}" && test -z "${MODULE__TESTSINGLEPHASE_FALSE}"; then + as_fn_error $? "conditional \"MODULE__TESTSINGLEPHASE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__TESTEXTERNALINSPECTION_TRUE}" && test -z "${MODULE__TESTEXTERNALINSPECTION_FALSE}"; then as_fn_error $? "conditional \"MODULE__TESTEXTERNALINSPECTION\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 103c24962b7b42..5877a1dc837009 100644 --- a/configure.ac +++ b/configure.ac @@ -7580,6 +7580,7 @@ PY_STDLIB_MOD([_testinternalcapi], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testbuffer], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testimportmultiple], [test "$TEST_MODULES" = yes], [test "$ac_cv_func_dlopen" = yes]) PY_STDLIB_MOD([_testmultiphase], [test "$TEST_MODULES" = yes], [test "$ac_cv_func_dlopen" = yes]) +PY_STDLIB_MOD([_testsinglephase], [test "$TEST_MODULES" = yes], [test "$ac_cv_func_dlopen" = yes]) PY_STDLIB_MOD([_testexternalinspection], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([xxsubtype], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_xxtestfuzz], [test "$TEST_MODULES" = yes]) From ea72ced21d9fc7f2aa7bc2a38d3844c80df2049e Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 13:07:41 +0100 Subject: [PATCH 15/35] Address review: use setUpClass in test_call; don't skip everything --- Lib/test/test_call.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_call.py b/Lib/test/test_call.py index f246fe6c3bd85b..8f156f3d29e682 100644 --- a/Lib/test/test_call.py +++ b/Lib/test/test_call.py @@ -482,8 +482,10 @@ class FastCallTests(unittest.TestCase): ] # Add all the calling conventions and variants of C callables - def setUp(self): - _testcapi = import_helper.import_module("_testcapi") + @classmethod + def setUpClass(cls): + if _testcapi is None: + return _instance = _testcapi.MethInstance() for obj, expected_self in ( (_testcapi, _testcapi), # module-level function @@ -492,7 +494,7 @@ def setUp(self): (_testcapi.MethClass(), _testcapi.MethClass), # class method on inst. (_testcapi.MethStatic, None), # static method ): - self.CALLS_POSARGS.extend([ + cls.CALLS_POSARGS.extend([ (obj.meth_varargs, (1, 2), (expected_self, (1, 2))), (obj.meth_varargs_keywords, (1, 2), (expected_self, (1, 2), NULL_OR_EMPTY)), @@ -506,7 +508,7 @@ def setUp(self): (obj.meth_o, (123, ), (expected_self, 123)), ]) - self.CALLS_KWARGS.extend([ + cls.CALLS_KWARGS.extend([ (obj.meth_varargs_keywords, (1, 2), {'x': 'y'}, (expected_self, (1, 2), {'x': 'y'})), (obj.meth_varargs_keywords, @@ -527,6 +529,7 @@ def check_result(self, result, expected): expected = (*expected[:-1], result[-1]) self.assertEqual(result, expected) + @unittest.skipIf(_testcapi is None, "requires _testcapi") def test_vectorcall_dict(self): # Test PyObject_VectorcallDict() @@ -546,6 +549,7 @@ def test_vectorcall_dict(self): result = _testcapi.pyobject_fastcalldict(func, args, kwargs) self.check_result(result, expected) + @unittest.skipIf(_testcapi is None, "requires _testcapi") def test_vectorcall(self): # Test PyObject_Vectorcall() From 628896ca12108b2e7723ce5592c13e5ab11082e4 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 13:13:19 +0100 Subject: [PATCH 16/35] Address review: no need to skip in tearDown --- Lib/test/test_monitoring.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 3eed5edeea4dec..4bf112cc2ffc9c 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1819,7 +1819,6 @@ def setUp(self): super(TestOptimizer, self).setUp() def tearDown(self): - _testinternalcapi = import_module("_testinternalcapi") super(TestOptimizer, self).tearDown() _testinternalcapi.set_optimizer(self.old_opt) From 88c6739d3a19992cf8ca8fc36190b66635a5f99a Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 13:15:24 +0100 Subject: [PATCH 17/35] Address review: check import at the top of test_threading.test_frame_tstate_tracing --- Lib/test/test_threading.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 7186b09226c91f..4d2df11088c269 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -983,6 +983,7 @@ def test_BoundedSemaphore_limit(self): @cpython_only def test_frame_tstate_tracing(self): + _testcapi = import_module("_testcapi") # Issue #14432: Crash when a generator is created in a C thread that is # destroyed while the generator is still used. The issue was that a # generator contains a frame, and the frame kept a reference to the @@ -1010,7 +1011,6 @@ def callback(): threading.settrace(noop_trace) # Create a generator in a C thread which exits after the call - _testcapi = import_module("_testcapi") _testcapi.call_in_temporary_c_thread(callback) # Call the generator in a different Python thread, check that the From c02cd6f10366d8b6da63dd6adbd68e22f47b500a Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 13:17:07 +0100 Subject: [PATCH 18/35] Fixup some test.support helpers --- Lib/test/support/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index b0a610b5daa23e..b1c0b591444f2a 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -1707,7 +1707,7 @@ def run_in_subinterp(code): try: import _testcapi except ImportError: - raise SkipTest("requires _testcapi") + raise unittest.SkipTest("requires _testcapi") return _testcapi.run_in_subinterp(code) @@ -1720,7 +1720,7 @@ def run_in_subinterp_with_config(code, *, own_gil=None, **config): try: import _testinternalcapi except ImportError: - raise SkipTest("requires _testinternalcapi") + raise unittest.SkipTest("requires _testinternalcapi") if own_gil is not None: assert 'gil' not in config, (own_gil, config) config['gil'] = 2 if own_gil else 1 From d49532b430e26f44fc035303d056468efe397ac4 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 13:19:05 +0100 Subject: [PATCH 19/35] Fixup test_coroutines --- Lib/test/test_coroutines.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py index d848bfbd46c83b..f705f4f5bfbd88 100644 --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -11,6 +11,10 @@ from test.support import import_helper from test.support import warnings_helper from test.support.script_helper import assert_python_ok +try: + import _testcapi +except ImportError: + _testcapi = None class AsyncYieldFrom: @@ -2445,6 +2449,7 @@ def test_unawaited_warning_during_shutdown(self): @support.cpython_only +@unittest.skipIf(_testcapi is None, "requires _testcapi") class CAPITest(unittest.TestCase): def test_tp_await_1(self): From 2427111b052cfdd50027a0023c596ad5cfa839db Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 13:22:03 +0100 Subject: [PATCH 20/35] Fixup test_threading --- Lib/test/test_threading.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 4d2df11088c269..96da9efaea2f07 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -1536,6 +1536,7 @@ def _check_allowed(self, before_start='', *, daemon_allowed=True, daemon=False, ): + import_module("_testinternalcapi") subinterp_code = textwrap.dedent(f""" import test.support import threading From 25d0999401768d9e9cf74b2f727631e7582f4b3b Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 13:26:24 +0100 Subject: [PATCH 21/35] Fixup test_repl --- Lib/test/test_repl.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/test/test_repl.py b/Lib/test/test_repl.py index a28d1595f44533..457279a4db687d 100644 --- a/Lib/test/test_repl.py +++ b/Lib/test/test_repl.py @@ -8,6 +8,7 @@ from test import support from test.support import cpython_only, has_subprocess_support, SuppressCrashReport from test.support.script_helper import kill_python +from test.support.import_helper import import_module if not has_subprocess_support: @@ -64,6 +65,7 @@ class TestInteractiveInterpreter(unittest.TestCase): # _PyRefchain_Trace() on memory allocation error. @unittest.skipIf(support.Py_TRACE_REFS, 'cannot test Py_TRACE_REFS build') 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. From bdd8cff169999a49cd3feae20b73b5dd06e28687 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 13:32:07 +0100 Subject: [PATCH 22/35] Fixup test_monitoring --- Lib/test/test_monitoring.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 4bf112cc2ffc9c..c1d3f2be69f19f 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1820,6 +1820,7 @@ def setUp(self): def tearDown(self): super(TestOptimizer, self).tearDown() + import _testinternalcapi _testinternalcapi.set_optimizer(self.old_opt) def test_for_loop(self): From ee9fa515251901005915c868efe9b763f95c5e47 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 14:11:04 +0100 Subject: [PATCH 23/35] Amend test_embed --- Lib/test/test_embed.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 88b72a00cc2153..010dd0ce43c615 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -19,10 +19,8 @@ if not support.has_subprocess_support: raise unittest.SkipTest("test module requires subprocess") -try: - import _testinternalcapi -except ImportError: - raise unittest.SkipTest("requires _testinternalcapi") + +_testinternalcapi = import_helper.import_module("_testinternalcapi") MACOS = (sys.platform == 'darwin') From a47c5ff1d7e90c5cb4bd5e74b4030251d86ee6b0 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 14:13:34 +0100 Subject: [PATCH 24/35] Amend test_audit --- Lib/test/test_audit.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Lib/test/test_audit.py b/Lib/test/test_audit.py index b48788d363db22..5dc9cf25047f86 100644 --- a/Lib/test/test_audit.py +++ b/Lib/test/test_audit.py @@ -89,10 +89,7 @@ def test_excepthook(self): ) def test_unraisablehook(self): - try: - import _testcapi - except ImportError: - raise unittest.SkipTest("requires _testcapi") + import_helper.import_module("_testcapi") returncode, events, stderr = self.run_python("test_unraisablehook") if returncode: self.fail(stderr) From d84a5c497e8bf4b804a1de6a270eb418466d2b82 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 15:02:15 +0100 Subject: [PATCH 25/35] Fix test_socket --- Lib/test/test_socket.py | 42 +++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index c7faeb219004db..451800c18662db 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -3,7 +3,6 @@ from test.support import ( is_apple, os_helper, refleak_helper, socket_helper, threading_helper ) -from test.support.import_helper import import_module import _thread as thread import array import contextlib @@ -37,6 +36,10 @@ import fcntl except ImportError: fcntl = None +try: + import _testcapi +except ImportError: + _testcapi = None support.requires_working_socket(module=True) @@ -1170,8 +1173,9 @@ def testNtoH(self): self.assertRaises(OverflowError, func, 1<<34) @support.cpython_only + @unittest.skipIf(_testcapi is None, "requires _testcapi") def testNtoHErrors(self): - _testcapi = import_module("_testcapi") + import _testcapi s_good_values = [0, 1, 2, 0xffff] l_good_values = s_good_values + [0xffffffff] l_bad_values = [-1, -2, 1<<32, 1<<1000] @@ -1636,6 +1640,7 @@ def testGetaddrinfo(self): except socket.gaierror: pass + @unittest.skipIf(_testcapi is None, "requires _testcapi") def test_getaddrinfo_int_port_overflow(self): # gh-74895: Test that getaddrinfo does not raise OverflowError on port. # @@ -1649,9 +1654,9 @@ def test_getaddrinfo_int_port_overflow(self): # prior to 3.12 did for ints outside of a [LONG_MIN, LONG_MAX] range. # Leave the error up to the underlying string based platform C API. - _testcapi = import_module("_testcapi") + from _testcapi import ULONG_MAX, LONG_MAX, LONG_MIN try: - socket.getaddrinfo(None, _testcapi.ULONG_MAX + 1, type=socket.SOCK_STREAM) + socket.getaddrinfo(None, ULONG_MAX + 1, type=socket.SOCK_STREAM) except OverflowError: # Platforms differ as to what values consitute a getaddrinfo() error # return. Some fail for LONG_MAX+1, others ULONG_MAX+1, and Windows @@ -1661,21 +1666,21 @@ def test_getaddrinfo_int_port_overflow(self): pass try: - socket.getaddrinfo(None, _testcapi.LONG_MAX + 1, type=socket.SOCK_STREAM) + socket.getaddrinfo(None, LONG_MAX + 1, type=socket.SOCK_STREAM) except OverflowError: self.fail("Either no error or socket.gaierror expected.") except socket.gaierror: pass try: - socket.getaddrinfo(None, _testcapi.LONG_MAX - 0xffff + 1, type=socket.SOCK_STREAM) + socket.getaddrinfo(None, LONG_MAX - 0xffff + 1, type=socket.SOCK_STREAM) except OverflowError: self.fail("Either no error or socket.gaierror expected.") except socket.gaierror: pass try: - socket.getaddrinfo(None, _testcapi.LONG_MIN - 1, type=socket.SOCK_STREAM) + socket.getaddrinfo(None, LONG_MIN - 1, type=socket.SOCK_STREAM) except OverflowError: self.fail("Either no error or socket.gaierror expected.") except socket.gaierror: @@ -1829,9 +1834,10 @@ def test_listen_backlog(self): srv.listen() @support.cpython_only + @unittest.skipIf(_testcapi is None, "requires _testcapi") def test_listen_backlog_overflow(self): # Issue 15989 - _testcapi = import_module("_testcapi") + import _testcapi with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as srv: srv.bind((HOST, 0)) self.assertRaises(OverflowError, srv.listen, _testcapi.INT_MAX + 1) @@ -2710,24 +2716,31 @@ def testDup(self): def _testDup(self): self.serv_conn.send(MSG) - def testShutdown(self): - # Testing shutdown() + def check_shutdown(self): + # Test shutdown() helper msg = self.cli_conn.recv(1024) self.assertEqual(msg, MSG) - # wait for _testShutdown to finish: on OS X, when the server + # wait for _testShutdown[_overflow] to finish: on OS X, when the server # closes the connection the client also becomes disconnected, # and the client's shutdown call will fail. (Issue #4397.) self.done.wait() + def testShutdown(self): + self.check_shutdown() + def _testShutdown(self): self.serv_conn.send(MSG) self.serv_conn.shutdown(2) - testShutdown_overflow = support.cpython_only(testShutdown) + @support.cpython_only + @unittest.skipIf(_testcapi is None, "requires _testcapi") + def testShutdown_overflow(self): + self.check_shutdown() @support.cpython_only + @unittest.skipIf(_testcapi is None, "requires _testcapi") def _testShutdown_overflow(self): - _testcapi = import_module("_testcapi") + import _testcapi self.serv_conn.send(MSG) # Issue 15989 self.assertRaises(OverflowError, self.serv_conn.shutdown, @@ -4882,9 +4895,10 @@ def _testSetBlocking(self): pass @support.cpython_only + @unittest.skipIf(_testcapi is None, "requires _testcapi") def testSetBlocking_overflow(self): # Issue 15989 - _testcapi = import_module("_testcapi") + import _testcapi if _testcapi.UINT_MAX >= _testcapi.ULONG_MAX: self.skipTest('needs UINT_MAX < ULONG_MAX') From e877ffb04d45e6ddd77f75dcdaa2f17bda46ddbf Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 15:51:07 +0100 Subject: [PATCH 26/35] Resolve test_exceptions nicer --- Lib/test/test_exceptions.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 04e24f1af8725a..6ad6acc61563e5 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -19,8 +19,10 @@ from test import support try: + import _testcapi from _testcapi import INT_MAX except ImportError: + _testcapi = None INT_MAX = 2**31 - 1 @@ -344,8 +346,8 @@ def __init__(self_): class InvalidException: pass + @unittest.skipIf(_testcapi is None, "requires _testcapi") def test_capi1(): - _testcapi = import_module("_testcapi") try: _testcapi.raise_exception(BadException, 1) except TypeError as err: @@ -355,8 +357,8 @@ def test_capi1(): else: self.fail("Expected exception") + @unittest.skipIf(_testcapi is None, "requires _testcapi") def test_capi2(): - _testcapi = import_module("_testcapi") try: _testcapi.raise_exception(BadException, 0) except RuntimeError as err: @@ -369,8 +371,8 @@ def test_capi2(): else: self.fail("Expected exception") + @unittest.skipIf(_testcapi is None, "requires _testcapi") def test_capi3(): - _testcapi = import_module("_testcapi") self.assertRaises(SystemError, _testcapi.raise_exception, InvalidException, 1) @@ -1435,8 +1437,8 @@ def gen(): self.assertIn(b'Done.', out) @cpython_only + @unittest.skipIf(_testcapi is None, "requires _testcapi") def test_recursion_normalizing_infinite_exception(self): - import_module("_testcapi") # Issue #30697. Test that a RecursionError is raised when # maximum recursion depth has been exceeded when creating # an exception @@ -1504,8 +1506,8 @@ def recurse_in_body_and_except(): # 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") def test_recursion_normalizing_with_no_memory(self): - import_module("_testcapi") # 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 # the size of the list of preallocated MemoryError instances, the @@ -1527,14 +1529,15 @@ def recurse(cnt): self.assertIn(b'MemoryError', err) @cpython_only + @unittest.skipIf(_testcapi is None, "requires _testcapi") def test_MemoryError(self): # PyErr_NoMemory always raises the same exception instance. # Check that the traceback is not doubled. - _testcapi = import_module("_testcapi") import traceback + from _testcapi import raise_memoryerror def raiseMemError(): try: - _testcapi.raise_memoryerror() + raise_memoryerror() except MemoryError as e: tb = e.__traceback__ else: @@ -1546,8 +1549,8 @@ def raiseMemError(): self.assertEqual(tb1, tb2) @cpython_only + @unittest.skipIf(_testcapi is None, "requires _testcapi") def test_exception_with_doc(self): - _testcapi = import_module("_testcapi") doc2 = "This is a test docstring." doc4 = "This is another test docstring." @@ -1586,10 +1589,11 @@ class C(object): self.assertEqual(error5.__doc__, "") @cpython_only + @unittest.skipIf(_testcapi is None, "requires _testcapi") def test_memory_error_cleanup(self): # Issue #5437: preallocated MemoryError instances should not keep # traceback objects alive. - _testcapi = import_module("_testcapi") + from _testcapi import raise_memoryerror class C: pass wr = None @@ -1597,7 +1601,7 @@ def inner(): nonlocal wr c = C() wr = weakref.ref(c) - _testcapi.raise_memoryerror() + raise_memoryerror() # We cannot use assertRaises since it manually deletes the traceback try: inner() @@ -1676,8 +1680,8 @@ def test_unhandled(self): # 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") def test_memory_error_in_PyErr_PrintEx(self): - import_module("_testcapi") code = """if 1: import _testcapi class C(): pass @@ -1795,8 +1799,8 @@ class TestException(MemoryError): gc_collect() + @unittest.skipIf(_testcapi is None, "requires _testcapi") def test_memory_error_in_subinterp(self): - import_module("_testcapi") # gh-109894: subinterpreters shouldn't count on last resort memory error # when MemoryError is raised through PyErr_NoMemory() call, # and should preallocate memory errors as does the main interpreter. From afa58a937dbe297431d42334197d02e269ab1a69 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 18:39:39 +0100 Subject: [PATCH 27/35] Use import_helper in test_importlib --- Lib/test/test_importlib/util.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Lib/test/test_importlib/util.py b/Lib/test/test_importlib/util.py index 977aa5a3f259f9..ee6a994a064f85 100644 --- a/Lib/test/test_importlib/util.py +++ b/Lib/test/test_importlib/util.py @@ -13,10 +13,7 @@ import tempfile import types -try: - import _testsinglephase -except ImportError: - raise unittest.SkipTest("requires _testsinglephase") +_testsinglephase = import_helper.import_module("_testsinglephase") BUILTINS = types.SimpleNamespace() From 760c6cb58c2c41a115bcafd4d159d6a485001ede Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 22:26:24 +0100 Subject: [PATCH 28/35] Fixup test_embed --- Doc/library/functions.rst | 4 ++-- Lib/test/test_embed.py | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index e598ef423de497..a1f106f4ed9ef8 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -528,11 +528,11 @@ are always available. They are listed here in alphabetical order. :param expression: A Python expression. - :type expression: :class:`str` | :ref:`code object ` + :type expression: str | :ref:`code object ` :param globals: The global namespace (default: ``None``). - :type globals: :class:`dict` | ``None`` + :type globals: dict :param locals: The local namespace (default: ``None``). diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 010dd0ce43c615..39504042e10a25 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -20,7 +20,10 @@ raise unittest.SkipTest("test module requires subprocess") -_testinternalcapi = import_helper.import_module("_testinternalcapi") +try: + import _testinternalcapi +except ImportError: + _testinternalcapi = None MACOS = (sys.platform == 'darwin') @@ -356,6 +359,7 @@ def test_simple_initialization_api(self): self.assertEqual(out, 'Finalized\n' * INIT_LOOPS) @support.requires_specialization + @unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi") def test_specialized_static_code_gets_unspecialized_at_Py_FINALIZE(self): # https://github.com/python/cpython/issues/92031 @@ -400,6 +404,8 @@ def test_ucnhash_capi_reset(self): out, err = self.run_embedded_interpreter("test_repeated_init_exec", code) self.assertEqual(out, '9\n' * INIT_LOOPS) + +@unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi") class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): maxDiff = 4096 UTF8_MODE_ERRORS = ('surrogatepass' if MS_WINDOWS else 'surrogateescape') @@ -1590,7 +1596,7 @@ def test_global_pathconfig(self): # The global path configuration (_Py_path_config) must be a copy # of the path configuration of PyInterpreter.config (PyConfig). ctypes = import_helper.import_module('ctypes') - _testinternalcapi = import_helper.import_module('_testinternalcapi') + import _testinternalcapi def get_func(name): func = getattr(ctypes.pythonapi, name) @@ -1786,6 +1792,7 @@ def test_unicode_id_init(self): # See bpo-44133 @unittest.skipIf(os.name == 'nt', 'Py_FrozenMain is not exported on Windows') + @unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi") def test_frozenmain(self): env = dict(os.environ) env['PYTHONUNBUFFERED'] = '1' From a1106b7eff4a30e1337aba2040d793ff74a63417 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 5 Mar 2024 23:17:46 +0100 Subject: [PATCH 29/35] Revert spurious docs change --- Doc/library/functions.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index a1f106f4ed9ef8..e598ef423de497 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -528,11 +528,11 @@ are always available. They are listed here in alphabetical order. :param expression: A Python expression. - :type expression: str | :ref:`code object ` + :type expression: :class:`str` | :ref:`code object ` :param globals: The global namespace (default: ``None``). - :type globals: dict + :type globals: :class:`dict` | ``None`` :param locals: The local namespace (default: ``None``). From db458522b503a78a0faa5b5c9d26b5cd9c27b627 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 6 Mar 2024 00:07:41 +0100 Subject: [PATCH 30/35] Workaround: use a different test module name in test_module_resources --- Lib/test/test_importlib/resources/test_files.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_importlib/resources/test_files.py b/Lib/test/test_importlib/resources/test_files.py index 1450cfb310926a..5a0d7f4542ee8c 100644 --- a/Lib/test/test_importlib/resources/test_files.py +++ b/Lib/test/test_importlib/resources/test_files.py @@ -79,14 +79,14 @@ def test_module_resources(self): A module can have resources found adjacent to the module. """ spec = { - 'mod.py': '', + 'mod_res.py': '', 'res.txt': 'resources are the best', } _path.build(spec, self.site_dir) - import mod + import mod_res - actual = resources.files(mod).joinpath('res.txt').read_text(encoding='utf-8') - assert actual == spec['res.txt'] + actual = resources.files(mod_res).joinpath('res.txt').read_text(encoding='utf-8') + self.assertEqual(actual, spec['res.txt']) class ImplicitContextFilesTests(SiteDir, unittest.TestCase): From ccd8bea9bb9fd4278d88769e4c1568ac6a905603 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 6 Mar 2024 18:30:27 -0500 Subject: [PATCH 31/35] gh-116307: Create a new import helper 'isolated modules' and use that instead of 'Clean Import' to ensure that tests from importlib_resources don't leave modules in sys.modules. (#61) --- Lib/test/support/import_helper.py | 12 ++++++++++++ Lib/test/test_importlib/resources/test_files.py | 2 +- .../2024-03-06-11-00-36.gh-issue-116307.Uij0t_.rst | 3 +++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Tests/2024-03-06-11-00-36.gh-issue-116307.Uij0t_.rst diff --git a/Lib/test/support/import_helper.py b/Lib/test/support/import_helper.py index 3d804f2b590108..29c6f535b40342 100644 --- a/Lib/test/support/import_helper.py +++ b/Lib/test/support/import_helper.py @@ -268,6 +268,18 @@ def modules_cleanup(oldmodules): sys.modules.update(oldmodules) +@contextlib.contextmanager +def isolated_modules(): + """ + Save modules on entry and cleanup on exit. + """ + (saved,) = modules_setup() + try: + yield + finally: + modules_cleanup(saved) + + def mock_register_at_fork(func): # bpo-30599: Mock os.register_at_fork() when importing the random module, # since this function doesn't allow to unregister callbacks and would leak diff --git a/Lib/test/test_importlib/resources/test_files.py b/Lib/test/test_importlib/resources/test_files.py index 5a0d7f4542ee8c..f28abf09a622e4 100644 --- a/Lib/test/test_importlib/resources/test_files.py +++ b/Lib/test/test_importlib/resources/test_files.py @@ -70,7 +70,7 @@ def setUp(self): self.addCleanup(self.fixtures.close) self.site_dir = self.fixtures.enter_context(os_helper.temp_dir()) self.fixtures.enter_context(import_helper.DirsOnSysPath(self.site_dir)) - self.fixtures.enter_context(import_helper.CleanImport()) + self.fixtures.enter_context(import_helper.isolated_modules()) class ModulesFilesTests(SiteDir, unittest.TestCase): diff --git a/Misc/NEWS.d/next/Tests/2024-03-06-11-00-36.gh-issue-116307.Uij0t_.rst b/Misc/NEWS.d/next/Tests/2024-03-06-11-00-36.gh-issue-116307.Uij0t_.rst new file mode 100644 index 00000000000000..0bc4be94789f21 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2024-03-06-11-00-36.gh-issue-116307.Uij0t_.rst @@ -0,0 +1,3 @@ +Added import helper ``isolated_modules`` as ``CleanImport`` does not remove +modules imported during the context. Use it in importlib.resources tests to +avoid leaving ``mod`` around to impede importlib.metadata tests. From 39d135d15a14c47e34d254c325eaecb7c6214445 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 7 Mar 2024 00:36:58 +0100 Subject: [PATCH 32/35] Revert "Workaround: use a different test module name in test_module_resources" This reverts commit db458522b503a78a0faa5b5c9d26b5cd9c27b627. --- Lib/test/test_importlib/resources/test_files.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_importlib/resources/test_files.py b/Lib/test/test_importlib/resources/test_files.py index f28abf09a622e4..26c8b04e44c3b9 100644 --- a/Lib/test/test_importlib/resources/test_files.py +++ b/Lib/test/test_importlib/resources/test_files.py @@ -79,14 +79,14 @@ def test_module_resources(self): A module can have resources found adjacent to the module. """ spec = { - 'mod_res.py': '', + 'mod.py': '', 'res.txt': 'resources are the best', } _path.build(spec, self.site_dir) - import mod_res + import mod - actual = resources.files(mod_res).joinpath('res.txt').read_text(encoding='utf-8') - self.assertEqual(actual, spec['res.txt']) + actual = resources.files(mod).joinpath('res.txt').read_text(encoding='utf-8') + assert actual == spec['res.txt'] class ImplicitContextFilesTests(SiteDir, unittest.TestCase): From 13c4829b8f2a1f0b0f488f3140d5dba2cb2f1907 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 7 Mar 2024 00:41:13 +0100 Subject: [PATCH 33/35] Revert another spurious test_importlib change --- Lib/test/test_importlib/extension/test_loader.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py index 650e53e20e3e61..84a0680e4ec653 100644 --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -108,7 +108,7 @@ def setUp(self): ) finder = self.machinery.FileFinder(None) self.spec = importlib.util.find_spec(self.name) - self.assertIsNotNone(self.spec) + assert self.spec self.loader = self.machinery.ExtensionFileLoader( self.name, self.spec.origin) @@ -189,7 +189,7 @@ def setUp(self): ) finder = self.machinery.FileFinder(None) self.spec = importlib.util.find_spec(self.name) - self.assertIsNotNone(self.spec) + assert self.spec self.loader = self.machinery.ExtensionFileLoader( self.name, self.spec.origin) From 31e19a7f21830da46925c20bb4be6a5a557fffbf Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 7 Mar 2024 01:13:25 +0100 Subject: [PATCH 34/35] Fix test_embed --- Lib/test/support/__init__.py | 2 +- Lib/test/test_embed.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index b1c0b591444f2a..162930f9941cca 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -508,7 +508,7 @@ def has_no_debug_ranges(): try: import _testinternalcapi except ImportError: - raise unittest.SkipTest("_testinternalcapi required") + return unittest.skip("_testinternalcapi required") config = _testinternalcapi.get_config() return not bool(config['code_debug_ranges']) diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index c72673839366bb..940639c2e895f6 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -359,7 +359,6 @@ def test_simple_initialization_api(self): self.assertEqual(out, 'Finalized\n' * INIT_LOOPS) @support.requires_specialization - @unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi") def test_specialized_static_code_gets_unspecialized_at_Py_FINALIZE(self): # https://github.com/python/cpython/issues/92031 From a148fb567c0a8888d9f117880bdb2a9e43606bc9 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 7 Mar 2024 10:12:34 +0100 Subject: [PATCH 35/35] Remove useless import from test_embed --- Lib/test/test_embed.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 940639c2e895f6..9d11a0fc078d08 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -1595,7 +1595,6 @@ def test_global_pathconfig(self): # The global path configuration (_Py_path_config) must be a copy # of the path configuration of PyInterpreter.config (PyConfig). ctypes = import_helper.import_module('ctypes') - import _testinternalcapi def get_func(name): func = getattr(ctypes.pythonapi, name)