##// END OF EJS Templates
Backport PR #12219: Catch ValueError
Matthias Bussonnier -
Show More
@@ -1,639 +1,643 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Pdb debugger class.
3 Pdb debugger class.
4
4
5 Modified from the standard pdb.Pdb class to avoid including readline, so that
5 Modified from the standard pdb.Pdb class to avoid including readline, so that
6 the command line completion of other programs which include this isn't
6 the command line completion of other programs which include this isn't
7 damaged.
7 damaged.
8
8
9 In the future, this class will be expanded with improvements over the standard
9 In the future, this class will be expanded with improvements over the standard
10 pdb.
10 pdb.
11
11
12 The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
12 The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
13 changes. Licensing should therefore be under the standard Python terms. For
13 changes. Licensing should therefore be under the standard Python terms. For
14 details on the PSF (Python Software Foundation) standard license, see:
14 details on the PSF (Python Software Foundation) standard license, see:
15
15
16 https://docs.python.org/2/license.html
16 https://docs.python.org/2/license.html
17 """
17 """
18
18
19 #*****************************************************************************
19 #*****************************************************************************
20 #
20 #
21 # This file is licensed under the PSF license.
21 # This file is licensed under the PSF license.
22 #
22 #
23 # Copyright (C) 2001 Python Software Foundation, www.python.org
23 # Copyright (C) 2001 Python Software Foundation, www.python.org
24 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
24 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
25 #
25 #
26 #
26 #
27 #*****************************************************************************
27 #*****************************************************************************
28
28
29 import bdb
29 import bdb
30 import functools
30 import functools
31 import inspect
31 import inspect
32 import linecache
32 import linecache
33 import sys
33 import sys
34 import warnings
34 import warnings
35 import re
35 import re
36
36
37 from IPython import get_ipython
37 from IPython import get_ipython
38 from IPython.utils import PyColorize
38 from IPython.utils import PyColorize
39 from IPython.utils import coloransi, py3compat
39 from IPython.utils import coloransi, py3compat
40 from IPython.core.excolors import exception_colors
40 from IPython.core.excolors import exception_colors
41 from IPython.testing.skipdoctest import skip_doctest
41 from IPython.testing.skipdoctest import skip_doctest
42
42
43
43
44 prompt = 'ipdb> '
44 prompt = 'ipdb> '
45
45
46 #We have to check this directly from sys.argv, config struct not yet available
46 #We have to check this directly from sys.argv, config struct not yet available
47 from pdb import Pdb as OldPdb
47 from pdb import Pdb as OldPdb
48
48
49 # Allow the set_trace code to operate outside of an ipython instance, even if
49 # Allow the set_trace code to operate outside of an ipython instance, even if
50 # it does so with some limitations. The rest of this support is implemented in
50 # it does so with some limitations. The rest of this support is implemented in
51 # the Tracer constructor.
51 # the Tracer constructor.
52
52
53 def make_arrow(pad):
53 def make_arrow(pad):
54 """generate the leading arrow in front of traceback or debugger"""
54 """generate the leading arrow in front of traceback or debugger"""
55 if pad >= 2:
55 if pad >= 2:
56 return '-'*(pad-2) + '> '
56 return '-'*(pad-2) + '> '
57 elif pad == 1:
57 elif pad == 1:
58 return '>'
58 return '>'
59 return ''
59 return ''
60
60
61
61
62 def BdbQuit_excepthook(et, ev, tb, excepthook=None):
62 def BdbQuit_excepthook(et, ev, tb, excepthook=None):
63 """Exception hook which handles `BdbQuit` exceptions.
63 """Exception hook which handles `BdbQuit` exceptions.
64
64
65 All other exceptions are processed using the `excepthook`
65 All other exceptions are processed using the `excepthook`
66 parameter.
66 parameter.
67 """
67 """
68 warnings.warn("`BdbQuit_excepthook` is deprecated since version 5.1",
68 warnings.warn("`BdbQuit_excepthook` is deprecated since version 5.1",
69 DeprecationWarning, stacklevel=2)
69 DeprecationWarning, stacklevel=2)
70 if et==bdb.BdbQuit:
70 if et==bdb.BdbQuit:
71 print('Exiting Debugger.')
71 print('Exiting Debugger.')
72 elif excepthook is not None:
72 elif excepthook is not None:
73 excepthook(et, ev, tb)
73 excepthook(et, ev, tb)
74 else:
74 else:
75 # Backwards compatibility. Raise deprecation warning?
75 # Backwards compatibility. Raise deprecation warning?
76 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
76 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
77
77
78
78
79 def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None):
79 def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None):
80 warnings.warn(
80 warnings.warn(
81 "`BdbQuit_IPython_excepthook` is deprecated since version 5.1",
81 "`BdbQuit_IPython_excepthook` is deprecated since version 5.1",
82 DeprecationWarning, stacklevel=2)
82 DeprecationWarning, stacklevel=2)
83 print('Exiting Debugger.')
83 print('Exiting Debugger.')
84
84
85
85
86 class Tracer(object):
86 class Tracer(object):
87 """
87 """
88 DEPRECATED
88 DEPRECATED
89
89
90 Class for local debugging, similar to pdb.set_trace.
90 Class for local debugging, similar to pdb.set_trace.
91
91
92 Instances of this class, when called, behave like pdb.set_trace, but
92 Instances of this class, when called, behave like pdb.set_trace, but
93 providing IPython's enhanced capabilities.
93 providing IPython's enhanced capabilities.
94
94
95 This is implemented as a class which must be initialized in your own code
95 This is implemented as a class which must be initialized in your own code
96 and not as a standalone function because we need to detect at runtime
96 and not as a standalone function because we need to detect at runtime
97 whether IPython is already active or not. That detection is done in the
97 whether IPython is already active or not. That detection is done in the
98 constructor, ensuring that this code plays nicely with a running IPython,
98 constructor, ensuring that this code plays nicely with a running IPython,
99 while functioning acceptably (though with limitations) if outside of it.
99 while functioning acceptably (though with limitations) if outside of it.
100 """
100 """
101
101
102 @skip_doctest
102 @skip_doctest
103 def __init__(self, colors=None):
103 def __init__(self, colors=None):
104 """
104 """
105 DEPRECATED
105 DEPRECATED
106
106
107 Create a local debugger instance.
107 Create a local debugger instance.
108
108
109 Parameters
109 Parameters
110 ----------
110 ----------
111
111
112 colors : str, optional
112 colors : str, optional
113 The name of the color scheme to use, it must be one of IPython's
113 The name of the color scheme to use, it must be one of IPython's
114 valid color schemes. If not given, the function will default to
114 valid color schemes. If not given, the function will default to
115 the current IPython scheme when running inside IPython, and to
115 the current IPython scheme when running inside IPython, and to
116 'NoColor' otherwise.
116 'NoColor' otherwise.
117
117
118 Examples
118 Examples
119 --------
119 --------
120 ::
120 ::
121
121
122 from IPython.core.debugger import Tracer; debug_here = Tracer()
122 from IPython.core.debugger import Tracer; debug_here = Tracer()
123
123
124 Later in your code::
124 Later in your code::
125
125
126 debug_here() # -> will open up the debugger at that point.
126 debug_here() # -> will open up the debugger at that point.
127
127
128 Once the debugger activates, you can use all of its regular commands to
128 Once the debugger activates, you can use all of its regular commands to
129 step through code, set breakpoints, etc. See the pdb documentation
129 step through code, set breakpoints, etc. See the pdb documentation
130 from the Python standard library for usage details.
130 from the Python standard library for usage details.
131 """
131 """
132 warnings.warn("`Tracer` is deprecated since version 5.1, directly use "
132 warnings.warn("`Tracer` is deprecated since version 5.1, directly use "
133 "`IPython.core.debugger.Pdb.set_trace()`",
133 "`IPython.core.debugger.Pdb.set_trace()`",
134 DeprecationWarning, stacklevel=2)
134 DeprecationWarning, stacklevel=2)
135
135
136 ip = get_ipython()
136 ip = get_ipython()
137 if ip is None:
137 if ip is None:
138 # Outside of ipython, we set our own exception hook manually
138 # Outside of ipython, we set our own exception hook manually
139 sys.excepthook = functools.partial(BdbQuit_excepthook,
139 sys.excepthook = functools.partial(BdbQuit_excepthook,
140 excepthook=sys.excepthook)
140 excepthook=sys.excepthook)
141 def_colors = 'NoColor'
141 def_colors = 'NoColor'
142 else:
142 else:
143 # In ipython, we use its custom exception handler mechanism
143 # In ipython, we use its custom exception handler mechanism
144 def_colors = ip.colors
144 def_colors = ip.colors
145 ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook)
145 ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook)
146
146
147 if colors is None:
147 if colors is None:
148 colors = def_colors
148 colors = def_colors
149
149
150 # The stdlib debugger internally uses a modified repr from the `repr`
150 # The stdlib debugger internally uses a modified repr from the `repr`
151 # module, that limits the length of printed strings to a hardcoded
151 # module, that limits the length of printed strings to a hardcoded
152 # limit of 30 characters. That much trimming is too aggressive, let's
152 # limit of 30 characters. That much trimming is too aggressive, let's
153 # at least raise that limit to 80 chars, which should be enough for
153 # at least raise that limit to 80 chars, which should be enough for
154 # most interactive uses.
154 # most interactive uses.
155 try:
155 try:
156 from reprlib import aRepr
156 from reprlib import aRepr
157 aRepr.maxstring = 80
157 aRepr.maxstring = 80
158 except:
158 except:
159 # This is only a user-facing convenience, so any error we encounter
159 # This is only a user-facing convenience, so any error we encounter
160 # here can be warned about but can be otherwise ignored. These
160 # here can be warned about but can be otherwise ignored. These
161 # printouts will tell us about problems if this API changes
161 # printouts will tell us about problems if this API changes
162 import traceback
162 import traceback
163 traceback.print_exc()
163 traceback.print_exc()
164
164
165 self.debugger = Pdb(colors)
165 self.debugger = Pdb(colors)
166
166
167 def __call__(self):
167 def __call__(self):
168 """Starts an interactive debugger at the point where called.
168 """Starts an interactive debugger at the point where called.
169
169
170 This is similar to the pdb.set_trace() function from the std lib, but
170 This is similar to the pdb.set_trace() function from the std lib, but
171 using IPython's enhanced debugger."""
171 using IPython's enhanced debugger."""
172
172
173 self.debugger.set_trace(sys._getframe().f_back)
173 self.debugger.set_trace(sys._getframe().f_back)
174
174
175
175
176 RGX_EXTRA_INDENT = re.compile(r'(?<=\n)\s+')
176 RGX_EXTRA_INDENT = re.compile(r'(?<=\n)\s+')
177
177
178
178
179 def strip_indentation(multiline_string):
179 def strip_indentation(multiline_string):
180 return RGX_EXTRA_INDENT.sub('', multiline_string)
180 return RGX_EXTRA_INDENT.sub('', multiline_string)
181
181
182
182
183 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
183 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
184 """Make new_fn have old_fn's doc string. This is particularly useful
184 """Make new_fn have old_fn's doc string. This is particularly useful
185 for the ``do_...`` commands that hook into the help system.
185 for the ``do_...`` commands that hook into the help system.
186 Adapted from from a comp.lang.python posting
186 Adapted from from a comp.lang.python posting
187 by Duncan Booth."""
187 by Duncan Booth."""
188 def wrapper(*args, **kw):
188 def wrapper(*args, **kw):
189 return new_fn(*args, **kw)
189 return new_fn(*args, **kw)
190 if old_fn.__doc__:
190 if old_fn.__doc__:
191 wrapper.__doc__ = strip_indentation(old_fn.__doc__) + additional_text
191 wrapper.__doc__ = strip_indentation(old_fn.__doc__) + additional_text
192 return wrapper
192 return wrapper
193
193
194
194
195 class Pdb(OldPdb):
195 class Pdb(OldPdb):
196 """Modified Pdb class, does not load readline.
196 """Modified Pdb class, does not load readline.
197
197
198 for a standalone version that uses prompt_toolkit, see
198 for a standalone version that uses prompt_toolkit, see
199 `IPython.terminal.debugger.TerminalPdb` and
199 `IPython.terminal.debugger.TerminalPdb` and
200 `IPython.terminal.debugger.set_trace()`
200 `IPython.terminal.debugger.set_trace()`
201 """
201 """
202
202
203 def __init__(self, color_scheme=None, completekey=None,
203 def __init__(self, color_scheme=None, completekey=None,
204 stdin=None, stdout=None, context=5, **kwargs):
204 stdin=None, stdout=None, context=5, **kwargs):
205 """Create a new IPython debugger.
205 """Create a new IPython debugger.
206
206
207 :param color_scheme: Deprecated, do not use.
207 :param color_scheme: Deprecated, do not use.
208 :param completekey: Passed to pdb.Pdb.
208 :param completekey: Passed to pdb.Pdb.
209 :param stdin: Passed to pdb.Pdb.
209 :param stdin: Passed to pdb.Pdb.
210 :param stdout: Passed to pdb.Pdb.
210 :param stdout: Passed to pdb.Pdb.
211 :param context: Number of lines of source code context to show when
211 :param context: Number of lines of source code context to show when
212 displaying stacktrace information.
212 displaying stacktrace information.
213 :param kwargs: Passed to pdb.Pdb.
213 :param kwargs: Passed to pdb.Pdb.
214 The possibilities are python version dependent, see the python
214 The possibilities are python version dependent, see the python
215 docs for more info.
215 docs for more info.
216 """
216 """
217
217
218 # Parent constructor:
218 # Parent constructor:
219 try:
219 try:
220 self.context = int(context)
220 self.context = int(context)
221 if self.context <= 0:
221 if self.context <= 0:
222 raise ValueError("Context must be a positive integer")
222 raise ValueError("Context must be a positive integer")
223 except (TypeError, ValueError):
223 except (TypeError, ValueError):
224 raise ValueError("Context must be a positive integer")
224 raise ValueError("Context must be a positive integer")
225
225
226 # `kwargs` ensures full compatibility with stdlib's `pdb.Pdb`.
226 # `kwargs` ensures full compatibility with stdlib's `pdb.Pdb`.
227 OldPdb.__init__(self, completekey, stdin, stdout, **kwargs)
227 OldPdb.__init__(self, completekey, stdin, stdout, **kwargs)
228
228
229 # IPython changes...
229 # IPython changes...
230 self.shell = get_ipython()
230 self.shell = get_ipython()
231
231
232 if self.shell is None:
232 if self.shell is None:
233 save_main = sys.modules['__main__']
233 save_main = sys.modules['__main__']
234 # No IPython instance running, we must create one
234 # No IPython instance running, we must create one
235 from IPython.terminal.interactiveshell import \
235 from IPython.terminal.interactiveshell import \
236 TerminalInteractiveShell
236 TerminalInteractiveShell
237 self.shell = TerminalInteractiveShell.instance()
237 self.shell = TerminalInteractiveShell.instance()
238 # needed by any code which calls __import__("__main__") after
238 # needed by any code which calls __import__("__main__") after
239 # the debugger was entered. See also #9941.
239 # the debugger was entered. See also #9941.
240 sys.modules['__main__'] = save_main
240 sys.modules['__main__'] = save_main
241
241
242 if color_scheme is not None:
242 if color_scheme is not None:
243 warnings.warn(
243 warnings.warn(
244 "The `color_scheme` argument is deprecated since version 5.1",
244 "The `color_scheme` argument is deprecated since version 5.1",
245 DeprecationWarning, stacklevel=2)
245 DeprecationWarning, stacklevel=2)
246 else:
246 else:
247 color_scheme = self.shell.colors
247 color_scheme = self.shell.colors
248
248
249 self.aliases = {}
249 self.aliases = {}
250
250
251 # Create color table: we copy the default one from the traceback
251 # Create color table: we copy the default one from the traceback
252 # module and add a few attributes needed for debugging
252 # module and add a few attributes needed for debugging
253 self.color_scheme_table = exception_colors()
253 self.color_scheme_table = exception_colors()
254
254
255 # shorthands
255 # shorthands
256 C = coloransi.TermColors
256 C = coloransi.TermColors
257 cst = self.color_scheme_table
257 cst = self.color_scheme_table
258
258
259 cst['NoColor'].colors.prompt = C.NoColor
259 cst['NoColor'].colors.prompt = C.NoColor
260 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
260 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
261 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
261 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
262
262
263 cst['Linux'].colors.prompt = C.Green
263 cst['Linux'].colors.prompt = C.Green
264 cst['Linux'].colors.breakpoint_enabled = C.LightRed
264 cst['Linux'].colors.breakpoint_enabled = C.LightRed
265 cst['Linux'].colors.breakpoint_disabled = C.Red
265 cst['Linux'].colors.breakpoint_disabled = C.Red
266
266
267 cst['LightBG'].colors.prompt = C.Blue
267 cst['LightBG'].colors.prompt = C.Blue
268 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
268 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
269 cst['LightBG'].colors.breakpoint_disabled = C.Red
269 cst['LightBG'].colors.breakpoint_disabled = C.Red
270
270
271 cst['Neutral'].colors.prompt = C.Blue
271 cst['Neutral'].colors.prompt = C.Blue
272 cst['Neutral'].colors.breakpoint_enabled = C.LightRed
272 cst['Neutral'].colors.breakpoint_enabled = C.LightRed
273 cst['Neutral'].colors.breakpoint_disabled = C.Red
273 cst['Neutral'].colors.breakpoint_disabled = C.Red
274
274
275
275
276 # Add a python parser so we can syntax highlight source while
276 # Add a python parser so we can syntax highlight source while
277 # debugging.
277 # debugging.
278 self.parser = PyColorize.Parser(style=color_scheme)
278 self.parser = PyColorize.Parser(style=color_scheme)
279 self.set_colors(color_scheme)
279 self.set_colors(color_scheme)
280
280
281 # Set the prompt - the default prompt is '(Pdb)'
281 # Set the prompt - the default prompt is '(Pdb)'
282 self.prompt = prompt
282 self.prompt = prompt
283
283
284 def set_colors(self, scheme):
284 def set_colors(self, scheme):
285 """Shorthand access to the color table scheme selector method."""
285 """Shorthand access to the color table scheme selector method."""
286 self.color_scheme_table.set_active_scheme(scheme)
286 self.color_scheme_table.set_active_scheme(scheme)
287 self.parser.style = scheme
287 self.parser.style = scheme
288
288
289 def interaction(self, frame, traceback):
289 def interaction(self, frame, traceback):
290 try:
290 try:
291 OldPdb.interaction(self, frame, traceback)
291 OldPdb.interaction(self, frame, traceback)
292 except KeyboardInterrupt:
292 except KeyboardInterrupt:
293 self.stdout.write('\n' + self.shell.get_exception_only())
293 self.stdout.write('\n' + self.shell.get_exception_only())
294
294
295 def new_do_up(self, arg):
295 def new_do_up(self, arg):
296 OldPdb.do_up(self, arg)
296 OldPdb.do_up(self, arg)
297 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
297 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
298
298
299 def new_do_down(self, arg):
299 def new_do_down(self, arg):
300 OldPdb.do_down(self, arg)
300 OldPdb.do_down(self, arg)
301
301
302 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
302 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
303
303
304 def new_do_frame(self, arg):
304 def new_do_frame(self, arg):
305 OldPdb.do_frame(self, arg)
305 OldPdb.do_frame(self, arg)
306
306
307 def new_do_quit(self, arg):
307 def new_do_quit(self, arg):
308
308
309 if hasattr(self, 'old_all_completions'):
309 if hasattr(self, 'old_all_completions'):
310 self.shell.Completer.all_completions=self.old_all_completions
310 self.shell.Completer.all_completions=self.old_all_completions
311
311
312 return OldPdb.do_quit(self, arg)
312 return OldPdb.do_quit(self, arg)
313
313
314 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
314 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
315
315
316 def new_do_restart(self, arg):
316 def new_do_restart(self, arg):
317 """Restart command. In the context of ipython this is exactly the same
317 """Restart command. In the context of ipython this is exactly the same
318 thing as 'quit'."""
318 thing as 'quit'."""
319 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
319 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
320 return self.do_quit(arg)
320 return self.do_quit(arg)
321
321
322 def print_stack_trace(self, context=None):
322 def print_stack_trace(self, context=None):
323 if context is None:
323 if context is None:
324 context = self.context
324 context = self.context
325 try:
325 try:
326 context=int(context)
326 context=int(context)
327 if context <= 0:
327 if context <= 0:
328 raise ValueError("Context must be a positive integer")
328 raise ValueError("Context must be a positive integer")
329 except (TypeError, ValueError):
329 except (TypeError, ValueError):
330 raise ValueError("Context must be a positive integer")
330 raise ValueError("Context must be a positive integer")
331 try:
331 try:
332 for frame_lineno in self.stack:
332 for frame_lineno in self.stack:
333 self.print_stack_entry(frame_lineno, context=context)
333 self.print_stack_entry(frame_lineno, context=context)
334 except KeyboardInterrupt:
334 except KeyboardInterrupt:
335 pass
335 pass
336
336
337 def print_stack_entry(self, frame_lineno, prompt_prefix='\n-> ',
337 def print_stack_entry(self, frame_lineno, prompt_prefix='\n-> ',
338 context=None):
338 context=None):
339 if context is None:
339 if context is None:
340 context = self.context
340 context = self.context
341 try:
341 try:
342 context=int(context)
342 context=int(context)
343 if context <= 0:
343 if context <= 0:
344 raise ValueError("Context must be a positive integer")
344 raise ValueError("Context must be a positive integer")
345 except (TypeError, ValueError):
345 except (TypeError, ValueError):
346 raise ValueError("Context must be a positive integer")
346 raise ValueError("Context must be a positive integer")
347 print(self.format_stack_entry(frame_lineno, '', context), file=self.stdout)
347 print(self.format_stack_entry(frame_lineno, '', context), file=self.stdout)
348
348
349 # vds: >>
349 # vds: >>
350 frame, lineno = frame_lineno
350 frame, lineno = frame_lineno
351 filename = frame.f_code.co_filename
351 filename = frame.f_code.co_filename
352 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
352 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
353 # vds: <<
353 # vds: <<
354
354
355 def format_stack_entry(self, frame_lineno, lprefix=': ', context=None):
355 def format_stack_entry(self, frame_lineno, lprefix=': ', context=None):
356 if context is None:
356 if context is None:
357 context = self.context
357 context = self.context
358 try:
358 try:
359 context=int(context)
359 context=int(context)
360 if context <= 0:
360 if context <= 0:
361 print("Context must be a positive integer", file=self.stdout)
361 print("Context must be a positive integer", file=self.stdout)
362 except (TypeError, ValueError):
362 except (TypeError, ValueError):
363 print("Context must be a positive integer", file=self.stdout)
363 print("Context must be a positive integer", file=self.stdout)
364 try:
364 try:
365 import reprlib # Py 3
365 import reprlib # Py 3
366 except ImportError:
366 except ImportError:
367 import repr as reprlib # Py 2
367 import repr as reprlib # Py 2
368
368
369 ret = []
369 ret = []
370
370
371 Colors = self.color_scheme_table.active_colors
371 Colors = self.color_scheme_table.active_colors
372 ColorsNormal = Colors.Normal
372 ColorsNormal = Colors.Normal
373 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
373 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
374 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
374 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
375 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
375 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
376 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
376 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
377 ColorsNormal)
377 ColorsNormal)
378
378
379 frame, lineno = frame_lineno
379 frame, lineno = frame_lineno
380
380
381 return_value = ''
381 return_value = ''
382 if '__return__' in frame.f_locals:
382 if '__return__' in frame.f_locals:
383 rv = frame.f_locals['__return__']
383 rv = frame.f_locals['__return__']
384 #return_value += '->'
384 #return_value += '->'
385 return_value += reprlib.repr(rv) + '\n'
385 return_value += reprlib.repr(rv) + '\n'
386 ret.append(return_value)
386 ret.append(return_value)
387
387
388 #s = filename + '(' + `lineno` + ')'
388 #s = filename + '(' + `lineno` + ')'
389 filename = self.canonic(frame.f_code.co_filename)
389 filename = self.canonic(frame.f_code.co_filename)
390 link = tpl_link % py3compat.cast_unicode(filename)
390 link = tpl_link % py3compat.cast_unicode(filename)
391
391
392 if frame.f_code.co_name:
392 if frame.f_code.co_name:
393 func = frame.f_code.co_name
393 func = frame.f_code.co_name
394 else:
394 else:
395 func = "<lambda>"
395 func = "<lambda>"
396
396
397 call = ''
397 call = ''
398 if func != '?':
398 if func != '?':
399 if '__args__' in frame.f_locals:
399 if '__args__' in frame.f_locals:
400 args = reprlib.repr(frame.f_locals['__args__'])
400 args = reprlib.repr(frame.f_locals['__args__'])
401 else:
401 else:
402 args = '()'
402 args = '()'
403 call = tpl_call % (func, args)
403 call = tpl_call % (func, args)
404
404
405 # The level info should be generated in the same format pdb uses, to
405 # The level info should be generated in the same format pdb uses, to
406 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
406 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
407 if frame is self.curframe:
407 if frame is self.curframe:
408 ret.append('> ')
408 ret.append('> ')
409 else:
409 else:
410 ret.append(' ')
410 ret.append(' ')
411 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
411 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
412
412
413 start = lineno - 1 - context//2
413 start = lineno - 1 - context//2
414 lines = linecache.getlines(filename)
414 lines = linecache.getlines(filename)
415 start = min(start, len(lines) - context)
415 start = min(start, len(lines) - context)
416 start = max(start, 0)
416 start = max(start, 0)
417 lines = lines[start : start + context]
417 lines = lines[start : start + context]
418
418
419 for i,line in enumerate(lines):
419 for i,line in enumerate(lines):
420 show_arrow = (start + 1 + i == lineno)
420 show_arrow = (start + 1 + i == lineno)
421 linetpl = (frame is self.curframe or show_arrow) \
421 linetpl = (frame is self.curframe or show_arrow) \
422 and tpl_line_em \
422 and tpl_line_em \
423 or tpl_line
423 or tpl_line
424 ret.append(self.__format_line(linetpl, filename,
424 ret.append(self.__format_line(linetpl, filename,
425 start + 1 + i, line,
425 start + 1 + i, line,
426 arrow = show_arrow) )
426 arrow = show_arrow) )
427 return ''.join(ret)
427 return ''.join(ret)
428
428
429 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
429 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
430 bp_mark = ""
430 bp_mark = ""
431 bp_mark_color = ""
431 bp_mark_color = ""
432
432
433 new_line, err = self.parser.format2(line, 'str')
433 new_line, err = self.parser.format2(line, 'str')
434 if not err:
434 if not err:
435 line = new_line
435 line = new_line
436
436
437 bp = None
437 bp = None
438 if lineno in self.get_file_breaks(filename):
438 if lineno in self.get_file_breaks(filename):
439 bps = self.get_breaks(filename, lineno)
439 bps = self.get_breaks(filename, lineno)
440 bp = bps[-1]
440 bp = bps[-1]
441
441
442 if bp:
442 if bp:
443 Colors = self.color_scheme_table.active_colors
443 Colors = self.color_scheme_table.active_colors
444 bp_mark = str(bp.number)
444 bp_mark = str(bp.number)
445 bp_mark_color = Colors.breakpoint_enabled
445 bp_mark_color = Colors.breakpoint_enabled
446 if not bp.enabled:
446 if not bp.enabled:
447 bp_mark_color = Colors.breakpoint_disabled
447 bp_mark_color = Colors.breakpoint_disabled
448
448
449 numbers_width = 7
449 numbers_width = 7
450 if arrow:
450 if arrow:
451 # This is the line with the error
451 # This is the line with the error
452 pad = numbers_width - len(str(lineno)) - len(bp_mark)
452 pad = numbers_width - len(str(lineno)) - len(bp_mark)
453 num = '%s%s' % (make_arrow(pad), str(lineno))
453 num = '%s%s' % (make_arrow(pad), str(lineno))
454 else:
454 else:
455 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
455 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
456
456
457 return tpl_line % (bp_mark_color + bp_mark, num, line)
457 return tpl_line % (bp_mark_color + bp_mark, num, line)
458
458
459
459
460 def print_list_lines(self, filename, first, last):
460 def print_list_lines(self, filename, first, last):
461 """The printing (as opposed to the parsing part of a 'list'
461 """The printing (as opposed to the parsing part of a 'list'
462 command."""
462 command."""
463 try:
463 try:
464 Colors = self.color_scheme_table.active_colors
464 Colors = self.color_scheme_table.active_colors
465 ColorsNormal = Colors.Normal
465 ColorsNormal = Colors.Normal
466 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
466 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
467 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
467 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
468 src = []
468 src = []
469 if filename == "<string>" and hasattr(self, "_exec_filename"):
469 if filename == "<string>" and hasattr(self, "_exec_filename"):
470 filename = self._exec_filename
470 filename = self._exec_filename
471
471
472 for lineno in range(first, last+1):
472 for lineno in range(first, last+1):
473 line = linecache.getline(filename, lineno)
473 line = linecache.getline(filename, lineno)
474 if not line:
474 if not line:
475 break
475 break
476
476
477 if lineno == self.curframe.f_lineno:
477 if lineno == self.curframe.f_lineno:
478 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
478 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
479 else:
479 else:
480 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
480 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
481
481
482 src.append(line)
482 src.append(line)
483 self.lineno = lineno
483 self.lineno = lineno
484
484
485 print(''.join(src), file=self.stdout)
485 print(''.join(src), file=self.stdout)
486
486
487 except KeyboardInterrupt:
487 except KeyboardInterrupt:
488 pass
488 pass
489
489
490 def do_list(self, arg):
490 def do_list(self, arg):
491 """Print lines of code from the current stack frame
491 """Print lines of code from the current stack frame
492 """
492 """
493 self.lastcmd = 'list'
493 self.lastcmd = 'list'
494 last = None
494 last = None
495 if arg:
495 if arg:
496 try:
496 try:
497 x = eval(arg, {}, {})
497 x = eval(arg, {}, {})
498 if type(x) == type(()):
498 if type(x) == type(()):
499 first, last = x
499 first, last = x
500 first = int(first)
500 first = int(first)
501 last = int(last)
501 last = int(last)
502 if last < first:
502 if last < first:
503 # Assume it's a count
503 # Assume it's a count
504 last = first + last
504 last = first + last
505 else:
505 else:
506 first = max(1, int(x) - 5)
506 first = max(1, int(x) - 5)
507 except:
507 except:
508 print('*** Error in argument:', repr(arg), file=self.stdout)
508 print('*** Error in argument:', repr(arg), file=self.stdout)
509 return
509 return
510 elif self.lineno is None:
510 elif self.lineno is None:
511 first = max(1, self.curframe.f_lineno - 5)
511 first = max(1, self.curframe.f_lineno - 5)
512 else:
512 else:
513 first = self.lineno + 1
513 first = self.lineno + 1
514 if last is None:
514 if last is None:
515 last = first + 10
515 last = first + 10
516 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
516 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
517
517
518 # vds: >>
518 # vds: >>
519 lineno = first
519 lineno = first
520 filename = self.curframe.f_code.co_filename
520 filename = self.curframe.f_code.co_filename
521 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
521 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
522 # vds: <<
522 # vds: <<
523
523
524 do_l = do_list
524 do_l = do_list
525
525
526 def getsourcelines(self, obj):
526 def getsourcelines(self, obj):
527 lines, lineno = inspect.findsource(obj)
527 lines, lineno = inspect.findsource(obj)
528 if inspect.isframe(obj) and obj.f_globals is obj.f_locals:
528 if inspect.isframe(obj) and obj.f_globals is obj.f_locals:
529 # must be a module frame: do not try to cut a block out of it
529 # must be a module frame: do not try to cut a block out of it
530 return lines, 1
530 return lines, 1
531 elif inspect.ismodule(obj):
531 elif inspect.ismodule(obj):
532 return lines, 1
532 return lines, 1
533 return inspect.getblock(lines[lineno:]), lineno+1
533 return inspect.getblock(lines[lineno:]), lineno+1
534
534
535 def do_longlist(self, arg):
535 def do_longlist(self, arg):
536 """Print lines of code from the current stack frame.
536 """Print lines of code from the current stack frame.
537
537
538 Shows more lines than 'list' does.
538 Shows more lines than 'list' does.
539 """
539 """
540 self.lastcmd = 'longlist'
540 self.lastcmd = 'longlist'
541 try:
541 try:
542 lines, lineno = self.getsourcelines(self.curframe)
542 lines, lineno = self.getsourcelines(self.curframe)
543 except OSError as err:
543 except OSError as err:
544 self.error(err)
544 self.error(err)
545 return
545 return
546 last = lineno + len(lines)
546 last = lineno + len(lines)
547 self.print_list_lines(self.curframe.f_code.co_filename, lineno, last)
547 self.print_list_lines(self.curframe.f_code.co_filename, lineno, last)
548 do_ll = do_longlist
548 do_ll = do_longlist
549
549
550 def do_debug(self, arg):
550 def do_debug(self, arg):
551 """debug code
551 """debug code
552 Enter a recursive debugger that steps through the code
552 Enter a recursive debugger that steps through the code
553 argument (which is an arbitrary expression or statement to be
553 argument (which is an arbitrary expression or statement to be
554 executed in the current environment).
554 executed in the current environment).
555 """
555 """
556 sys.settrace(None)
556 sys.settrace(None)
557 globals = self.curframe.f_globals
557 globals = self.curframe.f_globals
558 locals = self.curframe_locals
558 locals = self.curframe_locals
559 p = self.__class__(completekey=self.completekey,
559 p = self.__class__(completekey=self.completekey,
560 stdin=self.stdin, stdout=self.stdout)
560 stdin=self.stdin, stdout=self.stdout)
561 p.use_rawinput = self.use_rawinput
561 p.use_rawinput = self.use_rawinput
562 p.prompt = "(%s) " % self.prompt.strip()
562 p.prompt = "(%s) " % self.prompt.strip()
563 self.message("ENTERING RECURSIVE DEBUGGER")
563 self.message("ENTERING RECURSIVE DEBUGGER")
564 sys.call_tracing(p.run, (arg, globals, locals))
564 sys.call_tracing(p.run, (arg, globals, locals))
565 self.message("LEAVING RECURSIVE DEBUGGER")
565 self.message("LEAVING RECURSIVE DEBUGGER")
566 sys.settrace(self.trace_dispatch)
566 sys.settrace(self.trace_dispatch)
567 self.lastcmd = p.lastcmd
567 self.lastcmd = p.lastcmd
568
568
569 def do_pdef(self, arg):
569 def do_pdef(self, arg):
570 """Print the call signature for any callable object.
570 """Print the call signature for any callable object.
571
571
572 The debugger interface to %pdef"""
572 The debugger interface to %pdef"""
573 namespaces = [('Locals', self.curframe.f_locals),
573 namespaces = [('Locals', self.curframe.f_locals),
574 ('Globals', self.curframe.f_globals)]
574 ('Globals', self.curframe.f_globals)]
575 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
575 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
576
576
577 def do_pdoc(self, arg):
577 def do_pdoc(self, arg):
578 """Print the docstring for an object.
578 """Print the docstring for an object.
579
579
580 The debugger interface to %pdoc."""
580 The debugger interface to %pdoc."""
581 namespaces = [('Locals', self.curframe.f_locals),
581 namespaces = [('Locals', self.curframe.f_locals),
582 ('Globals', self.curframe.f_globals)]
582 ('Globals', self.curframe.f_globals)]
583 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
583 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
584
584
585 def do_pfile(self, arg):
585 def do_pfile(self, arg):
586 """Print (or run through pager) the file where an object is defined.
586 """Print (or run through pager) the file where an object is defined.
587
587
588 The debugger interface to %pfile.
588 The debugger interface to %pfile.
589 """
589 """
590 namespaces = [('Locals', self.curframe.f_locals),
590 namespaces = [('Locals', self.curframe.f_locals),
591 ('Globals', self.curframe.f_globals)]
591 ('Globals', self.curframe.f_globals)]
592 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
592 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
593
593
594 def do_pinfo(self, arg):
594 def do_pinfo(self, arg):
595 """Provide detailed information about an object.
595 """Provide detailed information about an object.
596
596
597 The debugger interface to %pinfo, i.e., obj?."""
597 The debugger interface to %pinfo, i.e., obj?."""
598 namespaces = [('Locals', self.curframe.f_locals),
598 namespaces = [('Locals', self.curframe.f_locals),
599 ('Globals', self.curframe.f_globals)]
599 ('Globals', self.curframe.f_globals)]
600 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
600 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
601
601
602 def do_pinfo2(self, arg):
602 def do_pinfo2(self, arg):
603 """Provide extra detailed information about an object.
603 """Provide extra detailed information about an object.
604
604
605 The debugger interface to %pinfo2, i.e., obj??."""
605 The debugger interface to %pinfo2, i.e., obj??."""
606 namespaces = [('Locals', self.curframe.f_locals),
606 namespaces = [('Locals', self.curframe.f_locals),
607 ('Globals', self.curframe.f_globals)]
607 ('Globals', self.curframe.f_globals)]
608 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
608 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
609
609
610 def do_psource(self, arg):
610 def do_psource(self, arg):
611 """Print (or run through pager) the source code for an object."""
611 """Print (or run through pager) the source code for an object."""
612 namespaces = [('Locals', self.curframe.f_locals),
612 namespaces = [('Locals', self.curframe.f_locals),
613 ('Globals', self.curframe.f_globals)]
613 ('Globals', self.curframe.f_globals)]
614 self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
614 self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
615
615
616 def do_where(self, arg):
616 def do_where(self, arg):
617 """w(here)
617 """w(here)
618 Print a stack trace, with the most recent frame at the bottom.
618 Print a stack trace, with the most recent frame at the bottom.
619 An arrow indicates the "current frame", which determines the
619 An arrow indicates the "current frame", which determines the
620 context of most commands. 'bt' is an alias for this command.
620 context of most commands. 'bt' is an alias for this command.
621
621
622 Take a number as argument as an (optional) number of context line to
622 Take a number as argument as an (optional) number of context line to
623 print"""
623 print"""
624 if arg:
624 if arg:
625 context = int(arg)
625 try:
626 context = int(arg)
627 except ValueError as err:
628 self.error(err)
629 return
626 self.print_stack_trace(context)
630 self.print_stack_trace(context)
627 else:
631 else:
628 self.print_stack_trace()
632 self.print_stack_trace()
629
633
630 do_w = do_where
634 do_w = do_where
631
635
632
636
633 def set_trace(frame=None):
637 def set_trace(frame=None):
634 """
638 """
635 Start debugging from `frame`.
639 Start debugging from `frame`.
636
640
637 If frame is not specified, debugging starts from caller's frame.
641 If frame is not specified, debugging starts from caller's frame.
638 """
642 """
639 Pdb().set_trace(frame or sys._getframe().f_back)
643 Pdb().set_trace(frame or sys._getframe().f_back)
General Comments 0
You need to be logged in to leave comments. Login now