diff --git a/changelog/4908.bugfix.rst b/changelog/4908.bugfix.rst new file mode 100644 index 000000000..2513618a1 --- /dev/null +++ b/changelog/4908.bugfix.rst @@ -0,0 +1 @@ +The ``pytest_enter_pdb`` hook gets called with post-mortem (``--pdb``). diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index 52c6536f4..3c433b274 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -212,6 +212,17 @@ class pytestPDB(object): self._pytest_capman.suspend_global_capture(in_=True) return ret + def get_stack(self, f, t): + stack, i = super(PytestPdbWrapper, self).get_stack(f, t) + if f is None: + # Find last non-hidden frame. + i = max(0, len(stack) - 1) + while i and stack[i][0].f_locals.get( + "__tracebackhide__", False + ): + i -= 1 + return stack, i + _pdb = PytestPdbWrapper(**kwargs) cls._pluginmanager.hook.pytest_enter_pdb(config=cls._config, pdb=_pdb) else: @@ -298,22 +309,8 @@ def _postmortem_traceback(excinfo): return excinfo._excinfo[2] -def _find_last_non_hidden_frame(stack): - i = max(0, len(stack) - 1) - while i and stack[i][0].f_locals.get("__tracebackhide__", False): - i -= 1 - return i - - def post_mortem(t): - class Pdb(pytestPDB._pdb_cls, object): - def get_stack(self, f, t): - stack, i = super(Pdb, self).get_stack(f, t) - if f is None: - i = _find_last_non_hidden_frame(stack) - return stack, i - - p = Pdb() + p = pytestPDB._init_pdb() p.reset() p.interaction(None, t) if p.quitting: diff --git a/testing/test_pdb.py b/testing/test_pdb.py index 3b21bacd9..9bac78557 100644 --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -744,7 +744,8 @@ class TestPDB(object): ["E NameError: *xxx*", "*! *Exit: Quitting debugger !*"] # due to EOF ) - def test_enter_leave_pdb_hooks_are_called(self, testdir): + @pytest.mark.parametrize("post_mortem", (False, True)) + def test_enter_leave_pdb_hooks_are_called(self, post_mortem, testdir): testdir.makeconftest( """ mypdb = None @@ -773,16 +774,25 @@ class TestPDB(object): """ import pytest - def test_foo(): + def test_set_trace(): pytest.set_trace() assert 0 + + def test_post_mortem(): + assert 0 """ ) - child = testdir.spawn_pytest(str(p1)) + if post_mortem: + child = testdir.spawn_pytest(str(p1) + " --pdb -s -k test_post_mortem") + else: + child = testdir.spawn_pytest(str(p1) + " -k test_set_trace") child.expect("enter_pdb_hook") child.sendline("c") - child.expect(r"PDB continue \(IO-capturing resumed\)") - child.expect("Captured stdout call") + if post_mortem: + child.expect(r"PDB continue") + else: + child.expect(r"PDB continue \(IO-capturing resumed\)") + child.expect("Captured stdout call") rest = child.read().decode("utf8") assert "leave_pdb_hook" in rest assert "1 failed" in rest