Skip to content

Commit 6383b53

Browse files
committed
Allow passing a custom Pdb subclass via --pdbcls.
This obviates the need for plugins such as `pytest-ipdb`; instead one can simply call `py.test --pdb=IPython.core.debugger:Pdb`
1 parent 7a2058e commit 6383b53

File tree

3 files changed

+21
-7
lines changed

3 files changed

+21
-7
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Anatoly Bubenkoff
1010
Andreas Zeidler
1111
Andy Freeland
1212
Anthon van der Neut
13+
Antony Lee
1314
Armin Rigo
1415
Aron Curzon
1516
Aviv Palivoda

CHANGELOG.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,8 @@
185185
Before, you only got exceptions later from ``argparse`` library,
186186
giving no clue about the actual reason for double-added options.
187187

188-
*
188+
* Allow passing a custom debugger class (e.g. ``IPython.core.debugger:Pdb``
189+
via ``--pdbcls``.
189190

190191
*
191192

_pytest/debugging.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,32 @@
88

99
def pytest_addoption(parser):
1010
group = parser.getgroup("general")
11-
group._addoption('--pdb',
12-
action="store_true", dest="usepdb", default=False,
13-
help="start the interactive Python debugger on errors.")
11+
group._addoption(
12+
'--pdb', dest="usepdb", action="store_true",
13+
help="start the interactive Python debugger on errors.")
14+
group._addoption(
15+
'--pdbcls', dest="usepdb_cls", metavar="modulename:classname",
16+
help="start a custom interactive Python debugger on errors.")
1417

1518
def pytest_namespace():
1619
return {'set_trace': pytestPDB().set_trace}
1720

1821
def pytest_configure(config):
19-
if config.getvalue("usepdb"):
22+
if config.getvalue("usepdb") or config.getvalue("usepdb_cls"):
2023
config.pluginmanager.register(PdbInvoke(), 'pdbinvoke')
24+
if config.getvalue("usepdb_cls"):
25+
modname, classname = config.getvalue("usepdb_cls").split(":")
26+
__import__(modname)
27+
pdb_cls = getattr(sys.modules[modname], classname)
28+
else:
29+
pdb_cls = pdb.Pdb
30+
pytestPDB._pdb_cls = pdb_cls
2131

2232
old = (pdb.set_trace, pytestPDB._pluginmanager)
2333
def fin():
2434
pdb.set_trace, pytestPDB._pluginmanager = old
2535
pytestPDB._config = None
36+
pytestPDB._pdb_cls = pdb.Pdb
2637
pdb.set_trace = pytest.set_trace
2738
pytestPDB._pluginmanager = config.pluginmanager
2839
pytestPDB._config = config
@@ -32,6 +43,7 @@ class pytestPDB:
3243
""" Pseudo PDB that defers to the real pdb. """
3344
_pluginmanager = None
3445
_config = None
46+
_pdb_cls = pdb.Pdb
3547

3648
def set_trace(self):
3749
""" invoke PDB set_trace debugging, dropping any IO capturing. """
@@ -45,7 +57,7 @@ def set_trace(self):
4557
tw.line()
4658
tw.sep(">", "PDB set_trace (IO-capturing turned off)")
4759
self._pluginmanager.hook.pytest_enter_pdb(config=self._config)
48-
pdb.Pdb().set_trace(frame)
60+
self._pdb_cls().set_trace(frame)
4961

5062

5163
class PdbInvoke:
@@ -98,7 +110,7 @@ def _find_last_non_hidden_frame(stack):
98110

99111

100112
def post_mortem(t):
101-
class Pdb(pdb.Pdb):
113+
class Pdb(pytestPDB._pdb_cls):
102114
def get_stack(self, f, t):
103115
stack, i = pdb.Pdb.get_stack(self, f, t)
104116
if f is None:

0 commit comments

Comments
 (0)