Skip to content

test.test_pdb.PdbTestColorize.test_gen_colors fails when pyrepl is unavailable at runtime #150544

Description

@sendaoYan

Bug report

Bug description:

Description

test.test_pdb.PdbTestColorize.test_gen_colors can fail in the standard test suite (for example via make test) with:

Re-running test_pdb in verbose mode (matching: test_gen_colors)
test_gen_colors (test.test_pdb.PdbTestColorize.test_gen_colors) ... ERROR

======================================================================
ERROR: test_gen_colors (test.test_pdb.PdbTestColorize.test_gen_colors)
----------------------------------------------------------------------
Traceback (most recent call last):
  File �[35m"/home/yansendao/git/cpython-ysd/Lib/test/test_pdb.py"�[0m, line �[35m5008�[0m, in �[35mtest_gen_colors�[0m
    gen_colors = �[1;31mp.pyrepl_input.gen_colors�[0m
                 �[1;31m^^^^^^^^^^^^^^^^^^^^^^^^^�[0m
�[1;35mAttributeError�[0m: �[35m'NoneType' object has no attribute 'gen_colors'�[0m

test_pdb.log

Root cause

PdbTestColorize.test_gen_colors creates pdb.Pdb() with the default streams,
so it uses sys.stdin/sys.stdout at the moment the test runs. With
--junit-xml, regrtest creates its test runner with capture_output=True
(_run_suite() in Lib/test/libregrtest/single.py), i.e.
TextTestRunner(buffer=True). For every test, unittest.result.TestResult. _setupStdout() replaces sys.stdout and sys.stderr with io.StringIO().
PdbPyReplInput.__init__() then calls stdout.fileno() (Lib/pdb.py), which
raises io.UnsupportedOperation on a StringIO; Pdb.__init__ swallows the
exception (except Exception: pass) and leaves self.pyrepl_input = None,
which the test then dereferences.

The test was skipped at import time instead:

@unittest.skipIf(not pdb._pyrepl_available()) is evaluated when the test
class is defined, not when the test runs. _pyrepl_available() only consults
_pyrepl.main.CAN_USE_PYREPL, which is computed at import time from
sys.stdin alone. In this scenario sys.stdin is still a real TTY, so the
condition stays True and the test is not skipped, even though the pdb.Pdb()
instance created inside the test cannot use pyrepl.

Additionally, _pyrepl_available() always inspected sys.stdin, while Pdb
uses self.stdin and self.stdout, so it could disagree with whether
PdbPyReplInput can actually be created.

Steps to reproduce

Run from a terminal, so that sys.stdin is a TTY and pyrepl is considered
available. The --junit-xml flag is what enables unittest output buffering
and triggers the error:

./python -m test test_pdb -m test_gen_colors                         # passes
./python -m test test_pdb -m test_gen_colors --junit-xml /tmp/x.xml  # errors

Or without regrtest:

./python -c 'import io, sys, pdb; sys.stdout = io.StringIO(); print(pdb.Pdb().pyrepl_input, file=sys.__stdout__)'
# None

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

Activity

  1. added a commit that references this issue on May 28, 2026
  2. sendaoYan commented on Jul 25, 2026

    @sendaoYan
    ContributorAuthor

    /touch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    testsTests in the Lib/test dirtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions