Skip to content

Commit dedfb8c

Browse files
committed
fix optimized FT builds without test modules
1 parent c04b3de commit dedfb8c

File tree

3 files changed

+39
-7
lines changed

3 files changed

+39
-7
lines changed

Lib/test/libregrtest/main.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from typing import NoReturn
1010

1111
from test.support import (os_helper, MS_WINDOWS, flush_std_streams,
12+
can_use_suppress_immortalization,
1213
suppress_immortalization)
1314

1415
from .cmdline import _parse_args, Namespace
@@ -536,8 +537,15 @@ def _run_tests(self, selected: TestTuple, tests: TestList | None) -> int:
536537
if self.num_workers:
537538
self._run_tests_mp(runtests, self.num_workers)
538539
else:
540+
# gh-135734: suppress_immortalization() raises SkipTest
541+
# if _testinternalcapi is missing and the -R option is set.
542+
if not can_use_suppress_immortalization(runtests.hunt_refleak):
543+
print("Module '_testinternalcapi' is missing. "
544+
"Did you disable it with --disable-test-modules?")
545+
raise SystemExit(1)
546+
539547
# gh-117783: don't immortalize deferred objects when tracking
540-
# refleaks. Only releveant for the free-threaded build.
548+
# refleaks. Only relevant for the free-threaded build.
541549
with suppress_immortalization(runtests.hunt_refleak):
542550
self.run_tests_sequentially(runtests)
543551

Lib/test/support/__init__.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -519,25 +519,45 @@ def requires_debug_ranges(reason='requires co_positions / debug_ranges'):
519519
reason = e.args[0] if e.args else reason
520520
return unittest.skipIf(skip, reason)
521521

522-
@contextlib.contextmanager
523-
def suppress_immortalization(suppress=True):
524-
"""Suppress immortalization of deferred objects."""
522+
523+
def can_use_suppress_immortalization(suppress=True):
524+
"""Check if suppress_immortalization(suppress) can be used.
525+
526+
Use this helper in code where SkipTest must be eagerly handled.
527+
"""
528+
if not suppress:
529+
return True
525530
try:
526531
import _testinternalcapi
527532
except ImportError:
528-
yield
529-
return
533+
return False
534+
return True
535+
530536

537+
@contextlib.contextmanager
538+
def suppress_immortalization(suppress=True):
539+
"""Suppress immortalization of deferred objects.
540+
541+
If _testinternalcapi is not available, the decorated test or class
542+
is skipped. Use can_use_suppress_immortalization() outside test cases
543+
to check if this decorator can be used.
544+
"""
531545
if not suppress:
532-
yield
546+
yield # no-op
533547
return
534548

549+
try:
550+
import _testinternalcapi
551+
except ImportError:
552+
raise unittest.SkipTest("requires _testinternalcapi") from None
553+
535554
_testinternalcapi.suppress_immortalization(True)
536555
try:
537556
yield
538557
finally:
539558
_testinternalcapi.suppress_immortalization(False)
540559

560+
541561
def skip_if_suppress_immortalization():
542562
try:
543563
import _testinternalcapi
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Python can correctly be configured and built with
2+
``./configure --enable-optimizations --disable-test-modules --disable-gil``.
3+
Previously, the profile data generation step failed due to PGO tests where
4+
immortalization couldn't be properly suppressed. Patch by Bénédikt Tran.

0 commit comments

Comments
 (0)