From dedfb8c9a53076dff33038cd054cac26076efb48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Wed, 20 Aug 2025 16:51:24 +0200 Subject: [PATCH 1/4] fix optimized FT builds without test modules --- Lib/test/libregrtest/main.py | 10 +++++- Lib/test/support/__init__.py | 32 +++++++++++++++---- ...-08-20-16-45-34.gh-issue-135734.2hvJCe.rst | 4 +++ 3 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2025-08-20-16-45-34.gh-issue-135734.2hvJCe.rst diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index 2894da7509110c..6c2491faad12e4 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -9,6 +9,7 @@ from typing import NoReturn from test.support import (os_helper, MS_WINDOWS, flush_std_streams, + can_use_suppress_immortalization, suppress_immortalization) from .cmdline import _parse_args, Namespace @@ -536,8 +537,15 @@ def _run_tests(self, selected: TestTuple, tests: TestList | None) -> int: if self.num_workers: self._run_tests_mp(runtests, self.num_workers) else: + # gh-135734: suppress_immortalization() raises SkipTest + # if _testinternalcapi is missing and the -R option is set. + if not can_use_suppress_immortalization(runtests.hunt_refleak): + print("Module '_testinternalcapi' is missing. " + "Did you disable it with --disable-test-modules?") + raise SystemExit(1) + # gh-117783: don't immortalize deferred objects when tracking - # refleaks. Only releveant for the free-threaded build. + # refleaks. Only relevant for the free-threaded build. with suppress_immortalization(runtests.hunt_refleak): self.run_tests_sequentially(runtests) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index c60fc03064f3c2..efa04b9ea6acf4 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -519,25 +519,45 @@ def requires_debug_ranges(reason='requires co_positions / debug_ranges'): reason = e.args[0] if e.args else reason return unittest.skipIf(skip, reason) -@contextlib.contextmanager -def suppress_immortalization(suppress=True): - """Suppress immortalization of deferred objects.""" + +def can_use_suppress_immortalization(suppress=True): + """Check if suppress_immortalization(suppress) can be used. + + Use this helper in code where SkipTest must be eagerly handled. + """ + if not suppress: + return True try: import _testinternalcapi except ImportError: - yield - return + return False + return True + +@contextlib.contextmanager +def suppress_immortalization(suppress=True): + """Suppress immortalization of deferred objects. + + If _testinternalcapi is not available, the decorated test or class + is skipped. Use can_use_suppress_immortalization() outside test cases + to check if this decorator can be used. + """ if not suppress: - yield + yield # no-op return + try: + import _testinternalcapi + except ImportError: + raise unittest.SkipTest("requires _testinternalcapi") from None + _testinternalcapi.suppress_immortalization(True) try: yield finally: _testinternalcapi.suppress_immortalization(False) + def skip_if_suppress_immortalization(): try: import _testinternalcapi diff --git a/Misc/NEWS.d/next/Build/2025-08-20-16-45-34.gh-issue-135734.2hvJCe.rst b/Misc/NEWS.d/next/Build/2025-08-20-16-45-34.gh-issue-135734.2hvJCe.rst new file mode 100644 index 00000000000000..596bbacf60993b --- /dev/null +++ b/Misc/NEWS.d/next/Build/2025-08-20-16-45-34.gh-issue-135734.2hvJCe.rst @@ -0,0 +1,4 @@ +Python can correctly be configured and built with +``./configure --enable-optimizations --disable-test-modules --disable-gil``. +Previously, the profile data generation step failed due to PGO tests where +immortalization couldn't be properly suppressed. Patch by Bénédikt Tran. From 3fcafb5d072947f958ad598021d53757f9937ee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Wed, 20 Aug 2025 17:46:51 +0200 Subject: [PATCH 2/4] use import_helper.import_module --- Lib/test/support/__init__.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index efa04b9ea6acf4..279a9ca23ef4df 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -546,11 +546,9 @@ def suppress_immortalization(suppress=True): yield # no-op return - try: - import _testinternalcapi - except ImportError: - raise unittest.SkipTest("requires _testinternalcapi") from None + from .import_helper import import_module + _testinternalcapi = import_module("_testinternalcapi") _testinternalcapi.suppress_immortalization(True) try: yield From 2fc71871cd68f273ff1f33c621dee9dea61732e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Wed, 20 Aug 2025 17:47:25 +0200 Subject: [PATCH 3/4] print to stderr --- Lib/test/libregrtest/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index 6c2491faad12e4..9e04138890c257 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -541,7 +541,8 @@ def _run_tests(self, selected: TestTuple, tests: TestList | None) -> int: # if _testinternalcapi is missing and the -R option is set. if not can_use_suppress_immortalization(runtests.hunt_refleak): print("Module '_testinternalcapi' is missing. " - "Did you disable it with --disable-test-modules?") + "Did you disable it with --disable-test-modules?", + file=sys.stderr) raise SystemExit(1) # gh-117783: don't immortalize deferred objects when tracking From 4b55b573ba9070a534ba625b3d8c2bc7878b49d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Wed, 20 Aug 2025 18:29:40 +0200 Subject: [PATCH 4/4] Update Misc/NEWS.d/next/Build/2025-08-20-16-45-34.gh-issue-135734.2hvJCe.rst --- .../next/Build/2025-08-20-16-45-34.gh-issue-135734.2hvJCe.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Build/2025-08-20-16-45-34.gh-issue-135734.2hvJCe.rst b/Misc/NEWS.d/next/Build/2025-08-20-16-45-34.gh-issue-135734.2hvJCe.rst index 596bbacf60993b..9a835804d8114b 100644 --- a/Misc/NEWS.d/next/Build/2025-08-20-16-45-34.gh-issue-135734.2hvJCe.rst +++ b/Misc/NEWS.d/next/Build/2025-08-20-16-45-34.gh-issue-135734.2hvJCe.rst @@ -1,4 +1,4 @@ Python can correctly be configured and built with -``./configure --enable-optimizations --disable-test-modules --disable-gil``. +``./configure --enable-optimizations --disable-test-modules``. Previously, the profile data generation step failed due to PGO tests where immortalization couldn't be properly suppressed. Patch by Bénédikt Tran.