8000 [3.13] gh-135124: Change stdout errors in regrtest worker process (GH… · python/cpython@5a69d4f · GitHub
[go: up one dir, main page]

Skip to content
  • Commit 5a69d4f

    Browse files
    [3.13] gh-135124: Change stdout errors in regrtest worker process (GH-135138) (#135169)
    gh-135124: Change stdout errors in regrtest worker process (GH-135138) Set sys.stdout encoder error handler to backslashreplace in regrtest workers to avoid UnicodeEncodeError when printing a traceback or any other non-encodable character. Move the code from the Regrtest class to setup_process(). Call setup_process() earlier, before displaying regrtest headers. (cherry picked from commit 3d396ab) Co-authored-by: Victor Stinner <vstinner@python.org>
    1 parent fd39aa3 commit 5a69d4f

    File tree

    3 files changed

    +51
    -12
    lines changed

    3 files changed

    +51
    -12
    lines changed

    Lib/test/libregrtest/main.py

    Lines changed: 1 addition & 6 deletions
    Original file line numberDiff line numberDiff line change
    @@ -519,8 +519,6 @@ def _run_tests(self, selected: TestTuple, tests: TestList | None) -> int:
    519519
    self.first_runtests = runtests
    520520
    self.logger.set_tests(runtests)
    521521

    522-
    setup_process()
    523-
    524522
    if (runtests.hunt_refleak is not None) and (not self.num_workers):
    525523
    # gh-109739: WindowsLoadTracker thread interferes with refleak check
    526524
    use_load_tracker = False
    @@ -700,10 +698,7 @@ def _add_python_opts(self) -> None:
    700698
    self._execute_python(cmd, environ)
    701699

    702700
    def _init(self):
    703-
    # Set sys.stdout encoder error handler to backslashreplace,
    704-
    # similar to sys.stderr error handler, to avoid UnicodeEncodeError
    705-
    # when printing a traceback or any other non-encodable character.
    706-
    sys.stdout.reconfigure(errors="backslashreplace")
    701+
    setup_process()
    707702

    708703
    if self.junit_filename and not os.path.isabs(self.junit_filename):
    709704
    self.junit_filename = os.path.abspath(self.junit_filename)

    Lib/test/libregrtest/setup.py

    Lines changed: 9 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,5 +1,6 @@
    11
    import faulthandler
    22
    import gc
    3+
    import io
    34
    import os
    45
    import random
    56
    import signal
    @@ -54,6 +55,14 @@ def setup_process() -> None:
    5455

    5556
    support.record_original_stdout(sys.stdout)
    5657

    58+
    # Set sys.stdout encoder error handler to backslashreplace,
    59+
    # similar to sys.stderr error handler, to avoid UnicodeEncodeError
    60+
    # when printing a traceback or any other non-encodable character.
    61+
    #
    62+
    # Use an assertion to fix mypy error.
    63+
    assert isinstance(sys.stdout, io.TextIOWrapper)
    64+
    sys.stdout.reconfigure(errors="backslashreplace")
    65+
    5766
    # Some times __path__ and __file__ are not absolute (e.g. while running from
    5867
    # Lib/) and, if we change the CWD to run the tests in a temporary dir, some
    5968
    # imports might fail. This affects only the modules imported before os.chdir().

    Lib/test/test_regrtest.py

    Lines changed: 41 additions & 6 deletions
    Original file line numberDiff line numberDiff line change
    @@ -765,13 +765,16 @@ def run_command(self, args, input=None, exitcode=0, **kw):
    765765
    self.fail(msg)
    766766
    return proc
    767767

    768-
    def run_python(self, args, **kw):
    768+
    def run_python(self, args, isolated=True, **kw):
    769769
    extraargs = []
    770770
    if 'uops' in sys._xoptions:
    771771
    # Pass -X uops along
    772772
    extraargs.extend(['-X', 'uops'])
    773-
    args = [sys.executable, *extraargs, '-X', 'faulthandler', '-I', *args]
    774-
    proc = self.run_command(args, **kw)
    773+
    cmd = [sys.executable, *extraargs, '-X', 'faulthandler']
    774+
    if isolated:
    775+
    cmd.append('-I')
    776+
    cmd.extend(args)
    777+
    proc = self.run_command(cmd, **kw)
    775778
    return proc.stdout
    776779

    777780

    @@ -828,8 +831,8 @@ def check_output(self, output):
    828831
    self.check_executed_tests(output, self.tests,
    829832
    randomize=True, stats=len(self.tests))
    830833

    831-
    def run_tests(self, args, env=None):
    832-
    output = self.run_python(args, env=env)
    834+
    def run_tests(self, args, env=None, isolated=True):
    835+
    output = self.run_python(args, env=env 8000 , isolated=isolated)
    833836
    self.check_output(output)
    834837

    835838
    def test_script_regrtest(self):
    @@ -2276,7 +2279,6 @@ def test_pass(self):
    22762279
    def test_xml(self):
    22772280
    code = textwrap.dedent(r"""
    22782281
    import unittest
    2279-
    from test import support
    22802282
    22812283
    class VerboseTests(unittest.TestCase):
    22822284
    def test_failed(self):
    @@ -2311,6 +2313,39 @@ def test_failed(self):
    23112313
    for out in testcase.iter('system-out'):
    23122314
    self.assertEqual(out.text, r"abc \x1b def")
    23132315

    2316+
    def test_nonascii(self):
    2317+
    code = textwrap.dedent(r"""
    2318+
    import unittest
    2319+
    2320+
    class NonASCIITests(unittest.TestCase):
    2321+
    def test_docstring(self):
    2322+
    '''docstring:\u20ac'''
    2323+
    2324+
    def test_subtest(self):
    2325+
    with self.subTest(param='subtest:\u20ac'):
    2326+
    pass
    2327+
    2328+
    def test_skip(self):
    2329+
    self.skipTest('skipped:\u20ac')
    2330+
    """)
    2331+
    testname = self.create_test(code=code)
    2332+
    2333+
    env = dict(os.environ)
    2334+
    env['PYTHONIOENCODING'] = 'ascii'
    2335+
    2336+
    def check(output):
    2337+
    self.check_executed_tests(output, testname, stats=TestStats(3, 0, 1))
    2338+
    self.assertIn(r'docstring:\u20ac', output)
    2339+
    self.assertIn(r'skipped:\u20ac', output)
    2340+
    2341+
    # Run sequentially
    2342+
    output = self.run_tests('-v', testname, env=env, isolated=False)
    2343+
    check(output)
    2344+
    2345+
    # Run in parallel
    2346+
    output = self.run_tests('-j1', '-v', testname, env=env, isolated=False)
    2347+
    check(output)
    2348+
    23142349

    23152350
    class TestUtils(unittest.TestCase):
    23162351
    def test_format_duration(self):

    0 commit comments

    Comments
     (0)
    0