forked from luqmaan/nose-ipdb
/
ipdbplugin.py
92 lines (84 loc) · 3.48 KB
/
ipdbplugin.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
"""
This plugin provides ``--ipdb`` and ``--ipdb-failures`` options. The ``--ipdb``
option will drop the test runner into pdb when it encounters an error. To
drop into pdb on failure, use ``--ipdb-failures``.
"""
import sys
import inspect
import traceback
from nose.plugins.base import Plugin
class iPdb(Plugin):
"""
Provides --ipdb and --ipdb-failures options that cause the test runner to
drop into ipdb if it encounters an error or failure, respectively.
"""
enabled_for_errors = False
enabled_for_failures = False
score = 5 # run last, among builtins
def options(self, parser, env):
"""Register commandline options.
"""
parser.add_option(
"--ipdb", action="store_true", dest="ipdbBoth",
default=env.get('NOSE_IPDB', False),
help="Drop into ipdb on errors and failures")
parser.add_option(
"--ipdb-errors", action="store_true", dest="ipdbErrors",
default=env.get('NOSE_IPDB_ERRORS', False),
help="Drop into ipdb on errors")
parser.add_option(
"--ipdb-failures", action="store_true",
dest="ipdbFailures",
default=env.get('NOSE_IPDB_FAILURES', False),
help="Drop into ipdb on failures")
def configure(self, options, conf):
"""Configure which kinds of exceptions trigger plugin.
"""
self.conf = conf
self.enabled_for_errors = options.ipdbErrors or options.ipdbBoth
self.enabled_for_failures = options.ipdbFailures or options.ipdbBoth
self.enabled = self.enabled_for_errors or self.enabled_for_failures
def addError(self, test, err):
"""Enter ipdb if configured to debug errors.
"""
if not self.enabled_for_errors:
return
self.debug(err)
def addFailure(self, test, err):
"""Enter ipdb if configured to debug failures.
"""
if not self.enabled_for_failures:
return
self.debug(err)
def debug(self, err):
import IPython
ec, ev, tb = err
stdout = sys.stdout
sys.stdout = sys.__stdout__
sys.stderr.write('\n- TRACEBACK --------------------------------------------------------------------\n')
traceback.print_exception(*err)
sys.stderr.write('--------------------------------------------------------------------------------\n')
try:
# The IPython API changed a bit so we should
# support the new version
if hasattr(IPython, 'InteractiveShell'):
if hasattr(IPython.InteractiveShell, 'instance'):
shell = IPython.InteractiveShell.instance()
p = IPython.core.debugger.Pdb(shell.colors)
else:
shell = IPython.InteractiveShell()
ip = IPython.core.ipapi.get()
p = IPython.core.debugger.Pdb(ip.colors)
# and keep support for older versions
else:
shell = IPython.Shell.IPShell(argv=[''])
ip = IPython.ipapi.get()
p = IPython.Debugger.Pdb(ip.options.colors)
p.reset()
# inspect.getinnerframes() returns a list of frames information
# from this frame to the one that raised the exception being
# treated
frame, filename, line, func_name, ctx, idx = inspect.getinnerframes(tb)[-1]
p.interaction(frame, tb)
finally:
sys.stdout = stdout