diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index 2e3d49c37..a56ad4b83 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -1,8 +1,6 @@ """ interactive debugging with PDB, the Python Debugger. """ import argparse -import pdb import sys -from doctest import UnexpectedException from _pytest import outcomes from _pytest.config import hookimpl @@ -45,6 +43,8 @@ def pytest_addoption(parser): def pytest_configure(config): + import pdb + if config.getvalue("trace"): config.pluginmanager.register(PdbTrace(), "pdbtrace") if config.getvalue("usepdb"): @@ -87,6 +87,8 @@ class pytestPDB: @classmethod def _import_pdb_cls(cls, capman): if not cls._config: + import pdb + # Happens when using pytest.set_trace outside of a test. return pdb.Pdb @@ -113,6 +115,8 @@ class pytestPDB: "--pdbcls: could not import {!r}: {}".format(value, exc) ) else: + import pdb + pdb_cls = pdb.Pdb wrapped_cls = cls._get_pdb_wrapper_class(pdb_cls, capman) @@ -313,6 +317,8 @@ def _enter_pdb(node, excinfo, rep): def _postmortem_traceback(excinfo): + from doctest import UnexpectedException + if isinstance(excinfo.value, UnexpectedException): # A doctest.UnexpectedException is not useful for post_mortem. # Use the underlying exception instead: diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index ad9c37737..1b11a8af0 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1238,3 +1238,40 @@ def test_warn_on_async_gen_function(testdir): assert ( result.stdout.str().count("async def functions are not natively supported") == 1 ) + + +def test_pdb_can_be_rewritten(testdir): + testdir.makepyfile( + **{ + "conftest.py": """ + import pytest + pytest.register_assert_rewrite("pdb") + """, + "__init__.py": "", + "pdb.py": """ + def check(): + assert 1 == 2 + """, + "test_pdb.py": """ + def test(): + import pdb + assert pdb.check() + """, + } + ) + # Disable debugging plugin itself to avoid: + # > INTERNALERROR> AttributeError: module 'pdb' has no attribute 'set_trace' + result = testdir.runpytest_subprocess("-p", "no:debugging", "-vv") + result.stdout.fnmatch_lines( + [ + " def check():", + "> assert 1 == 2", + "E assert 1 == 2", + "E -1", + "E +2", + "", + "pdb.py:2: AssertionError", + "*= 1 failed in *", + ] + ) + assert result.ret == 1