https://github.com/python/cpython/commit/4a11a2eb1639692e02159a0db07fe04250a0bb63
commit: 4a11a2eb1639692e02159a0db07fe04250a0bb63
branch: 3.14
author: Miss Islington (bot) <[email protected]>
committer: freakboy3742 <[email protected]>
date: 2026-10-05T09:54:18+08:00
summary:

[3.14] gh-146410: Add --pythoninfo option to regrtest (GH-146413) (#158606)

* Android now runs tests with --pythoninfo to dump build information.
* Add display_title() function.
(cherry picked from commit b5a27bdcf035c2a1c1ffc746bf3720c284991873)

Co-authored-by: Victor Stinner <[email protected]>

files:
M Android/android.py
M Lib/test/libregrtest/cmdline.py
M Lib/test/libregrtest/main.py
M Lib/test/libregrtest/utils.py
M Lib/test/pythoninfo.py
M Lib/test/test_regrtest.py

diff --git a/Android/android.py b/Android/android.py
index 7e9c52452a22b40..246e45de72c4077 100755
--- a/Android/android.py
+++ b/Android/android.py
@@ -659,7 +659,8 @@ async def gradle_task(context):
             # Randomization is disabled because order-dependent failures are
             # much less likely to pass on a rerun in single-process mode.
             "-m", "test",
-            f"--{context.ci_mode}-ci", "--single-process", "--no-randomize"
+            f"--{context.ci_mode}-ci", "--single-process", "--no-randomize",
+            "--pythoninfo",
         ]
 
     if not any(arg in context.args for arg in ["-c", "-m"]):
diff --git a/Lib/test/libregrtest/cmdline.py b/Lib/test/libregrtest/cmdline.py
index 2c404f6d80bcf39..ea26cc849f81828 100644
--- a/Lib/test/libregrtest/cmdline.py
+++ b/Lib/test/libregrtest/cmdline.py
@@ -393,6 +393,8 @@ def _create_parser():
                        help='remove old test_python_* directories')
     group.add_argument('--bisect', action='store_true',
                        help='if some tests fail, run test.bisect_cmd on them')
+    group.add_argument('--pythoninfo', action='store_true',
+                       help="run python -m test.pythoninfo before tests")
     group.add_argument('--dont-add-python-opts', dest='_add_python_opts',
                        action='store_false',
                        help="internal option, don't use it")
diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py
index d26e0e113ced2dc..62f66adadebbb18 100644
--- a/Lib/test/libregrtest/main.py
+++ b/Lib/test/libregrtest/main.py
@@ -26,7 +26,7 @@
     strip_py_suffix, count, format_duration,
     printlist, get_temp_dir, get_work_dir, exit_timeout,
     display_header, cleanup_temp_dir, print_warning,
-    is_cross_compiled, get_host_runner,
+    is_cross_compiled, get_host_runner, display_title,
     EXIT_TIMEOUT)
 
 
@@ -126,6 +126,7 @@ def __init__(self, ns: Namespace, _add_python_opts: bool = 
False):
         self.coverage: bool = ns.trace
         self.coverage_dir: StrPath | None = ns.coverdir
         self._tmp_dir: StrPath | None = ns.tempdir
+        self.pythoninfo: bool = ns.pythoninfo
 
         # Randomize
         self.randomize: bool = ns.randomize
@@ -322,9 +323,7 @@ def _run_bisect(self, runtests: RunTests, test: str, 
progress: str) -> bool:
         title = f"Bisect {test}"
         if progress:
             title = f"{title} ({progress})"
-        print(title)
-        print("#" * len(title))
-        print()
+        display_title(title)
 
         cmd = runtests.create_python_cmd()
         cmd.extend([
@@ -345,9 +344,7 @@ def _run_bisect(self, runtests: RunTests, test: str, 
progress: str) -> bool:
         exitcode = proc.returncode
 
         title = f"{title}: exit code {exitcode}"
-        print(title)
-        print("#" * len(title))
-        print(flush=True)
+        display_title(title)
 
         if exitcode:
             print(f"Bisect failed with exit code {exitcode}")
@@ -752,6 +749,15 @@ def tmp_dir(self) -> StrPath:
             )
         return self._tmp_dir
 
+    def run_pythoninfo(self):
+        from test import pythoninfo
+        try:
+            pythoninfo.main()
+        except SystemExit:
+            # Ignore non-zero exit code on purpose
+            pass
+        print()
+
     def main(self, tests: TestList | None = None) -> NoReturn:
         if self.want_add_python_opts:
             self._add_python_opts()
@@ -765,6 +771,9 @@ def main(self, tests: TestList | None = None) -> NoReturn:
         if self.want_wait:
             input("Press any key to continue...")
 
+        if self.pythoninfo:
+            self.run_pythoninfo()
+
         setup_test_dir(self.test_dir)
         selected, tests = self.find_tests(tests)
 
diff --git a/Lib/test/libregrtest/utils.py b/Lib/test/libregrtest/utils.py
index 68ea34e21af0140..cde9f6f8344e6f5 100644
--- a/Lib/test/libregrtest/utils.py
+++ b/Lib/test/libregrtest/utils.py
@@ -730,3 +730,9 @@ def _sanitize_xml_replace(regs):
 
 def sanitize_xml(text: str) -> str:
     return ILLEGAL_XML_CHARS_RE.sub(_sanitize_xml_replace, text)
+
+
+def display_title(title):
+    print(title)
+    print("#" * len(title))
+    print(flush=True)
diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py
index 4b000284526e5f0..3e64422fdfbf3af 100644
--- a/Lib/test/pythoninfo.py
+++ b/Lib/test/pythoninfo.py
@@ -1360,9 +1360,9 @@ def collect_info(info):
 
 
 def dump_info(info, file=None):
-    title = "Python debug information"
+    title = "Python build information"
     print(title)
-    print("=" * len(title))
+    print("#" * len(title))
     print()
 
     infos = info.get_infos()
diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py
index b578f81c075c942..4c43629b39a046b 100644
--- a/Lib/test/test_regrtest.py
+++ b/Lib/test/test_regrtest.py
@@ -571,6 +571,13 @@ def test_single_process(self):
         self.assertEqual(regrtest.num_workers, 0)
         self.assertTrue(regrtest.single_process)
 
+    def test_pythoninfo(self):
+        ns = self.parse_args([])
+        self.assertFalse(ns.pythoninfo)
+
+        ns = self.parse_args(['--pythoninfo'])
+        self.assertTrue(ns.pythoninfo)
+
 
 @dataclasses.dataclass(slots=True)
 class Rerun:
@@ -2431,6 +2438,11 @@ def test_pgo_exclude(self):
         self.assertNotIn('test_re', tests)
         self.assertEqual(len(tests), len(pgo_tests) - 1)
 
+    def test_pythoninfo(self):
+        testname = self.create_test()
+        output = self.run_tests('--pythoninfo', testname)
+        self.assertIn("Python build information", output)
+
 
 class TestUtils(unittest.TestCase):
     def test_format_duration(self):

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

Reply via email to