##// END OF EJS Templates
add whitespace
Terry Davis -
Show More
@@ -1,641 +1,642 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 try:
156 try:
157 from reprlib import aRepr # Py 3
157 from reprlib import aRepr # Py 3
158 except ImportError:
158 except ImportError:
159 from repr import aRepr # Py 2
159 from repr import aRepr # Py 2
160 aRepr.maxstring = 80
160 aRepr.maxstring = 80
161 except:
161 except:
162 # This is only a user-facing convenience, so any error we encounter
162 # This is only a user-facing convenience, so any error we encounter
163 # here can be warned about but can be otherwise ignored. These
163 # here can be warned about but can be otherwise ignored. These
164 # printouts will tell us about problems if this API changes
164 # printouts will tell us about problems if this API changes
165 import traceback
165 import traceback
166 traceback.print_exc()
166 traceback.print_exc()
167
167
168 self.debugger = Pdb(colors)
168 self.debugger = Pdb(colors)
169
169
170 def __call__(self):
170 def __call__(self):
171 """Starts an interactive debugger at the point where called.
171 """Starts an interactive debugger at the point where called.
172
172
173 This is similar to the pdb.set_trace() function from the std lib, but
173 This is similar to the pdb.set_trace() function from the std lib, but
174 using IPython's enhanced debugger."""
174 using IPython's enhanced debugger."""
175
175
176 self.debugger.set_trace(sys._getframe().f_back)
176 self.debugger.set_trace(sys._getframe().f_back)
177
177
178
178
179 RGX_EXTRA_INDENT = re.compile(r'(?<=\n)\s+')
179 RGX_EXTRA_INDENT = re.compile(r'(?<=\n)\s+')
180
180
181
181
182 def strip_indentation(multiline_string):
182 def strip_indentation(multiline_string):
183 return RGX_EXTRA_INDENT.sub('', multiline_string)
183 return RGX_EXTRA_INDENT.sub('', multiline_string)
184
184
185
185
186 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
186 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
187 """Make new_fn have old_fn's doc string. This is particularly useful
187 """Make new_fn have old_fn's doc string. This is particularly useful
188 for the ``do_...`` commands that hook into the help system.
188 for the ``do_...`` commands that hook into the help system.
189 Adapted from from a comp.lang.python posting
189 Adapted from from a comp.lang.python posting
190 by Duncan Booth."""
190 by Duncan Booth."""
191 def wrapper(*args, **kw):
191 def wrapper(*args, **kw):
192 return new_fn(*args, **kw)
192 return new_fn(*args, **kw)
193 if old_fn.__doc__:
193 if old_fn.__doc__:
194 wrapper.__doc__ = strip_indentation(old_fn.__doc__) + additional_text
194 wrapper.__doc__ = strip_indentation(old_fn.__doc__) + additional_text
195 return wrapper
195 return wrapper
196
196
197
197
198 class Pdb(OldPdb):
198 class Pdb(OldPdb):
199 """Modified Pdb class, does not load readline.
199 """Modified Pdb class, does not load readline.
200
200
201 for a standalone version that uses prompt_toolkit, see
201 for a standalone version that uses prompt_toolkit, see
202 `IPython.terminal.debugger.TerminalPdb` and
202 `IPython.terminal.debugger.TerminalPdb` and
203 `IPython.terminal.debugger.set_trace()`
203 `IPython.terminal.debugger.set_trace()`
204 """
204 """
205
205
206 def __init__(self, color_scheme=None, completekey=None,
206 def __init__(self, color_scheme=None, completekey=None,
207 stdin=None, stdout=None, context=5, **kwargs):
207 stdin=None, stdout=None, context=5, **kwargs):
208 """Create a new IPython debugger.
208 """Create a new IPython debugger.
209
209
210 :param color_scheme: Deprecated, do not use.
210 :param color_scheme: Deprecated, do not use.
211 :param completekey: Passed to pdb.Pdb.
211 :param completekey: Passed to pdb.Pdb.
212 :param stdin: Passed to pdb.Pdb.
212 :param stdin: Passed to pdb.Pdb.
213 :param stdout: Passed to pdb.Pdb.
213 :param stdout: Passed to pdb.Pdb.
214 :param context: Number of lines of source code context to show when
214 :param context: Number of lines of source code context to show when
215 displaying stacktrace information.
215 displaying stacktrace information.
216 :param kwargs: Passed to pdb.Pdb.
216 :param kwargs: Passed to pdb.Pdb.
217 The possibilities are python version dependent, see the python
217 The possibilities are python version dependent, see the python
218 docs for more info.
218 docs for more info.
219 """
219 """
220
220
221 # Parent constructor:
221 # Parent constructor:
222 try:
222 try:
223 self.context = int(context)
223 self.context = int(context)
224 if self.context <= 0:
224 if self.context <= 0:
225 raise ValueError("Context must be a positive integer")
225 raise ValueError("Context must be a positive integer")
226 except (TypeError, ValueError):
226 except (TypeError, ValueError):
227 raise ValueError("Context must be a positive integer")
227 raise ValueError("Context must be a positive integer")
228
228 # `kwargs` ensures full compatibility with stdlib's `pdb.Pdb`.
229 # `kwargs` ensures full compatibility with stdlib's `pdb.Pdb`.
229 OldPdb.__init__(self, completekey, stdin, stdout, **kwargs)
230 OldPdb.__init__(self, completekey, stdin, stdout, **kwargs)
230
231
231 # IPython changes...
232 # IPython changes...
232 self.shell = get_ipython()
233 self.shell = get_ipython()
233
234
234 if self.shell is None:
235 if self.shell is None:
235 save_main = sys.modules['__main__']
236 save_main = sys.modules['__main__']
236 # No IPython instance running, we must create one
237 # No IPython instance running, we must create one
237 from IPython.terminal.interactiveshell import \
238 from IPython.terminal.interactiveshell import \
238 TerminalInteractiveShell
239 TerminalInteractiveShell
239 self.shell = TerminalInteractiveShell.instance()
240 self.shell = TerminalInteractiveShell.instance()
240 # needed by any code which calls __import__("__main__") after
241 # needed by any code which calls __import__("__main__") after
241 # the debugger was entered. See also #9941.
242 # the debugger was entered. See also #9941.
242 sys.modules['__main__'] = save_main
243 sys.modules['__main__'] = save_main
243
244
244 if color_scheme is not None:
245 if color_scheme is not None:
245 warnings.warn(
246 warnings.warn(
246 "The `color_scheme` argument is deprecated since version 5.1",
247 "The `color_scheme` argument is deprecated since version 5.1",
247 DeprecationWarning, stacklevel=2)
248 DeprecationWarning, stacklevel=2)
248 else:
249 else:
249 color_scheme = self.shell.colors
250 color_scheme = self.shell.colors
250
251
251 self.aliases = {}
252 self.aliases = {}
252
253
253 # Create color table: we copy the default one from the traceback
254 # Create color table: we copy the default one from the traceback
254 # module and add a few attributes needed for debugging
255 # module and add a few attributes needed for debugging
255 self.color_scheme_table = exception_colors()
256 self.color_scheme_table = exception_colors()
256
257
257 # shorthands
258 # shorthands
258 C = coloransi.TermColors
259 C = coloransi.TermColors
259 cst = self.color_scheme_table
260 cst = self.color_scheme_table
260
261
261 cst['NoColor'].colors.prompt = C.NoColor
262 cst['NoColor'].colors.prompt = C.NoColor
262 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
263 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
263 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
264 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
264
265
265 cst['Linux'].colors.prompt = C.Green
266 cst['Linux'].colors.prompt = C.Green
266 cst['Linux'].colors.breakpoint_enabled = C.LightRed
267 cst['Linux'].colors.breakpoint_enabled = C.LightRed
267 cst['Linux'].colors.breakpoint_disabled = C.Red
268 cst['Linux'].colors.breakpoint_disabled = C.Red
268
269
269 cst['LightBG'].colors.prompt = C.Blue
270 cst['LightBG'].colors.prompt = C.Blue
270 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
271 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
271 cst['LightBG'].colors.breakpoint_disabled = C.Red
272 cst['LightBG'].colors.breakpoint_disabled = C.Red
272
273
273 cst['Neutral'].colors.prompt = C.Blue
274 cst['Neutral'].colors.prompt = C.Blue
274 cst['Neutral'].colors.breakpoint_enabled = C.LightRed
275 cst['Neutral'].colors.breakpoint_enabled = C.LightRed
275 cst['Neutral'].colors.breakpoint_disabled = C.Red
276 cst['Neutral'].colors.breakpoint_disabled = C.Red
276
277
277
278
278 # Add a python parser so we can syntax highlight source while
279 # Add a python parser so we can syntax highlight source while
279 # debugging.
280 # debugging.
280 self.parser = PyColorize.Parser(style=color_scheme)
281 self.parser = PyColorize.Parser(style=color_scheme)
281 self.set_colors(color_scheme)
282 self.set_colors(color_scheme)
282
283
283 # Set the prompt - the default prompt is '(Pdb)'
284 # Set the prompt - the default prompt is '(Pdb)'
284 self.prompt = prompt
285 self.prompt = prompt
285
286
286 def set_colors(self, scheme):
287 def set_colors(self, scheme):
287 """Shorthand access to the color table scheme selector method."""
288 """Shorthand access to the color table scheme selector method."""
288 self.color_scheme_table.set_active_scheme(scheme)
289 self.color_scheme_table.set_active_scheme(scheme)
289 self.parser.style = scheme
290 self.parser.style = scheme
290
291
291 def interaction(self, frame, traceback):
292 def interaction(self, frame, traceback):
292 try:
293 try:
293 OldPdb.interaction(self, frame, traceback)
294 OldPdb.interaction(self, frame, traceback)
294 except KeyboardInterrupt:
295 except KeyboardInterrupt:
295 self.stdout.write('\n' + self.shell.get_exception_only())
296 self.stdout.write('\n' + self.shell.get_exception_only())
296
297
297 def new_do_up(self, arg):
298 def new_do_up(self, arg):
298 OldPdb.do_up(self, arg)
299 OldPdb.do_up(self, arg)
299 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
300 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
300
301
301 def new_do_down(self, arg):
302 def new_do_down(self, arg):
302 OldPdb.do_down(self, arg)
303 OldPdb.do_down(self, arg)
303
304
304 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
305 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
305
306
306 def new_do_frame(self, arg):
307 def new_do_frame(self, arg):
307 OldPdb.do_frame(self, arg)
308 OldPdb.do_frame(self, arg)
308
309
309 def new_do_quit(self, arg):
310 def new_do_quit(self, arg):
310
311
311 if hasattr(self, 'old_all_completions'):
312 if hasattr(self, 'old_all_completions'):
312 self.shell.Completer.all_completions=self.old_all_completions
313 self.shell.Completer.all_completions=self.old_all_completions
313
314
314 return OldPdb.do_quit(self, arg)
315 return OldPdb.do_quit(self, arg)
315
316
316 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
317 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
317
318
318 def new_do_restart(self, arg):
319 def new_do_restart(self, arg):
319 """Restart command. In the context of ipython this is exactly the same
320 """Restart command. In the context of ipython this is exactly the same
320 thing as 'quit'."""
321 thing as 'quit'."""
321 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
322 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
322 return self.do_quit(arg)
323 return self.do_quit(arg)
323
324
324 def print_stack_trace(self, context=None):
325 def print_stack_trace(self, context=None):
325 if context is None:
326 if context is None:
326 context = self.context
327 context = self.context
327 try:
328 try:
328 context=int(context)
329 context=int(context)
329 if context <= 0:
330 if context <= 0:
330 raise ValueError("Context must be a positive integer")
331 raise ValueError("Context must be a positive integer")
331 except (TypeError, ValueError):
332 except (TypeError, ValueError):
332 raise ValueError("Context must be a positive integer")
333 raise ValueError("Context must be a positive integer")
333 try:
334 try:
334 for frame_lineno in self.stack:
335 for frame_lineno in self.stack:
335 self.print_stack_entry(frame_lineno, context=context)
336 self.print_stack_entry(frame_lineno, context=context)
336 except KeyboardInterrupt:
337 except KeyboardInterrupt:
337 pass
338 pass
338
339
339 def print_stack_entry(self, frame_lineno, prompt_prefix='\n-> ',
340 def print_stack_entry(self, frame_lineno, prompt_prefix='\n-> ',
340 context=None):
341 context=None):
341 if context is None:
342 if context is None:
342 context = self.context
343 context = self.context
343 try:
344 try:
344 context=int(context)
345 context=int(context)
345 if context <= 0:
346 if context <= 0:
346 raise ValueError("Context must be a positive integer")
347 raise ValueError("Context must be a positive integer")
347 except (TypeError, ValueError):
348 except (TypeError, ValueError):
348 raise ValueError("Context must be a positive integer")
349 raise ValueError("Context must be a positive integer")
349 print(self.format_stack_entry(frame_lineno, '', context), file=self.stdout)
350 print(self.format_stack_entry(frame_lineno, '', context), file=self.stdout)
350
351
351 # vds: >>
352 # vds: >>
352 frame, lineno = frame_lineno
353 frame, lineno = frame_lineno
353 filename = frame.f_code.co_filename
354 filename = frame.f_code.co_filename
354 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
355 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
355 # vds: <<
356 # vds: <<
356
357
357 def format_stack_entry(self, frame_lineno, lprefix=': ', context=None):
358 def format_stack_entry(self, frame_lineno, lprefix=': ', context=None):
358 if context is None:
359 if context is None:
359 context = self.context
360 context = self.context
360 try:
361 try:
361 context=int(context)
362 context=int(context)
362 if context <= 0:
363 if context <= 0:
363 print("Context must be a positive integer", file=self.stdout)
364 print("Context must be a positive integer", file=self.stdout)
364 except (TypeError, ValueError):
365 except (TypeError, ValueError):
365 print("Context must be a positive integer", file=self.stdout)
366 print("Context must be a positive integer", file=self.stdout)
366 try:
367 try:
367 import reprlib # Py 3
368 import reprlib # Py 3
368 except ImportError:
369 except ImportError:
369 import repr as reprlib # Py 2
370 import repr as reprlib # Py 2
370
371
371 ret = []
372 ret = []
372
373
373 Colors = self.color_scheme_table.active_colors
374 Colors = self.color_scheme_table.active_colors
374 ColorsNormal = Colors.Normal
375 ColorsNormal = Colors.Normal
375 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
376 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
376 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
377 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
377 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
378 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
378 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
379 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
379 ColorsNormal)
380 ColorsNormal)
380
381
381 frame, lineno = frame_lineno
382 frame, lineno = frame_lineno
382
383
383 return_value = ''
384 return_value = ''
384 if '__return__' in frame.f_locals:
385 if '__return__' in frame.f_locals:
385 rv = frame.f_locals['__return__']
386 rv = frame.f_locals['__return__']
386 #return_value += '->'
387 #return_value += '->'
387 return_value += reprlib.repr(rv) + '\n'
388 return_value += reprlib.repr(rv) + '\n'
388 ret.append(return_value)
389 ret.append(return_value)
389
390
390 #s = filename + '(' + `lineno` + ')'
391 #s = filename + '(' + `lineno` + ')'
391 filename = self.canonic(frame.f_code.co_filename)
392 filename = self.canonic(frame.f_code.co_filename)
392 link = tpl_link % py3compat.cast_unicode(filename)
393 link = tpl_link % py3compat.cast_unicode(filename)
393
394
394 if frame.f_code.co_name:
395 if frame.f_code.co_name:
395 func = frame.f_code.co_name
396 func = frame.f_code.co_name
396 else:
397 else:
397 func = "<lambda>"
398 func = "<lambda>"
398
399
399 call = ''
400 call = ''
400 if func != '?':
401 if func != '?':
401 if '__args__' in frame.f_locals:
402 if '__args__' in frame.f_locals:
402 args = reprlib.repr(frame.f_locals['__args__'])
403 args = reprlib.repr(frame.f_locals['__args__'])
403 else:
404 else:
404 args = '()'
405 args = '()'
405 call = tpl_call % (func, args)
406 call = tpl_call % (func, args)
406
407
407 # The level info should be generated in the same format pdb uses, to
408 # The level info should be generated in the same format pdb uses, to
408 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
409 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
409 if frame is self.curframe:
410 if frame is self.curframe:
410 ret.append('> ')
411 ret.append('> ')
411 else:
412 else:
412 ret.append(' ')
413 ret.append(' ')
413 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
414 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
414
415
415 start = lineno - 1 - context//2
416 start = lineno - 1 - context//2
416 lines = linecache.getlines(filename)
417 lines = linecache.getlines(filename)
417 start = min(start, len(lines) - context)
418 start = min(start, len(lines) - context)
418 start = max(start, 0)
419 start = max(start, 0)
419 lines = lines[start : start + context]
420 lines = lines[start : start + context]
420
421
421 for i,line in enumerate(lines):
422 for i,line in enumerate(lines):
422 show_arrow = (start + 1 + i == lineno)
423 show_arrow = (start + 1 + i == lineno)
423 linetpl = (frame is self.curframe or show_arrow) \
424 linetpl = (frame is self.curframe or show_arrow) \
424 and tpl_line_em \
425 and tpl_line_em \
425 or tpl_line
426 or tpl_line
426 ret.append(self.__format_line(linetpl, filename,
427 ret.append(self.__format_line(linetpl, filename,
427 start + 1 + i, line,
428 start + 1 + i, line,
428 arrow = show_arrow) )
429 arrow = show_arrow) )
429 return ''.join(ret)
430 return ''.join(ret)
430
431
431 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
432 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
432 bp_mark = ""
433 bp_mark = ""
433 bp_mark_color = ""
434 bp_mark_color = ""
434
435
435 new_line, err = self.parser.format2(line, 'str')
436 new_line, err = self.parser.format2(line, 'str')
436 if not err:
437 if not err:
437 line = new_line
438 line = new_line
438
439
439 bp = None
440 bp = None
440 if lineno in self.get_file_breaks(filename):
441 if lineno in self.get_file_breaks(filename):
441 bps = self.get_breaks(filename, lineno)
442 bps = self.get_breaks(filename, lineno)
442 bp = bps[-1]
443 bp = bps[-1]
443
444
444 if bp:
445 if bp:
445 Colors = self.color_scheme_table.active_colors
446 Colors = self.color_scheme_table.active_colors
446 bp_mark = str(bp.number)
447 bp_mark = str(bp.number)
447 bp_mark_color = Colors.breakpoint_enabled
448 bp_mark_color = Colors.breakpoint_enabled
448 if not bp.enabled:
449 if not bp.enabled:
449 bp_mark_color = Colors.breakpoint_disabled
450 bp_mark_color = Colors.breakpoint_disabled
450
451
451 numbers_width = 7
452 numbers_width = 7
452 if arrow:
453 if arrow:
453 # This is the line with the error
454 # This is the line with the error
454 pad = numbers_width - len(str(lineno)) - len(bp_mark)
455 pad = numbers_width - len(str(lineno)) - len(bp_mark)
455 num = '%s%s' % (make_arrow(pad), str(lineno))
456 num = '%s%s' % (make_arrow(pad), str(lineno))
456 else:
457 else:
457 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
458 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
458
459
459 return tpl_line % (bp_mark_color + bp_mark, num, line)
460 return tpl_line % (bp_mark_color + bp_mark, num, line)
460
461
461
462
462 def print_list_lines(self, filename, first, last):
463 def print_list_lines(self, filename, first, last):
463 """The printing (as opposed to the parsing part of a 'list'
464 """The printing (as opposed to the parsing part of a 'list'
464 command."""
465 command."""
465 try:
466 try:
466 Colors = self.color_scheme_table.active_colors
467 Colors = self.color_scheme_table.active_colors
467 ColorsNormal = Colors.Normal
468 ColorsNormal = Colors.Normal
468 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
469 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
469 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
470 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
470 src = []
471 src = []
471 if filename == "<string>" and hasattr(self, "_exec_filename"):
472 if filename == "<string>" and hasattr(self, "_exec_filename"):
472 filename = self._exec_filename
473 filename = self._exec_filename
473
474
474 for lineno in range(first, last+1):
475 for lineno in range(first, last+1):
475 line = linecache.getline(filename, lineno)
476 line = linecache.getline(filename, lineno)
476 if not line:
477 if not line:
477 break
478 break
478
479
479 if lineno == self.curframe.f_lineno:
480 if lineno == self.curframe.f_lineno:
480 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
481 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
481 else:
482 else:
482 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
483 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
483
484
484 src.append(line)
485 src.append(line)
485 self.lineno = lineno
486 self.lineno = lineno
486
487
487 print(''.join(src), file=self.stdout)
488 print(''.join(src), file=self.stdout)
488
489
489 except KeyboardInterrupt:
490 except KeyboardInterrupt:
490 pass
491 pass
491
492
492 def do_list(self, arg):
493 def do_list(self, arg):
493 """Print lines of code from the current stack frame
494 """Print lines of code from the current stack frame
494 """
495 """
495 self.lastcmd = 'list'
496 self.lastcmd = 'list'
496 last = None
497 last = None
497 if arg:
498 if arg:
498 try:
499 try:
499 x = eval(arg, {}, {})
500 x = eval(arg, {}, {})
500 if type(x) == type(()):
501 if type(x) == type(()):
501 first, last = x
502 first, last = x
502 first = int(first)
503 first = int(first)
503 last = int(last)
504 last = int(last)
504 if last < first:
505 if last < first:
505 # Assume it's a count
506 # Assume it's a count
506 last = first + last
507 last = first + last
507 else:
508 else:
508 first = max(1, int(x) - 5)
509 first = max(1, int(x) - 5)
509 except:
510 except:
510 print('*** Error in argument:', repr(arg), file=self.stdout)
511 print('*** Error in argument:', repr(arg), file=self.stdout)
511 return
512 return
512 elif self.lineno is None:
513 elif self.lineno is None:
513 first = max(1, self.curframe.f_lineno - 5)
514 first = max(1, self.curframe.f_lineno - 5)
514 else:
515 else:
515 first = self.lineno + 1
516 first = self.lineno + 1
516 if last is None:
517 if last is None:
517 last = first + 10
518 last = first + 10
518 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
519 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
519
520
520 # vds: >>
521 # vds: >>
521 lineno = first
522 lineno = first
522 filename = self.curframe.f_code.co_filename
523 filename = self.curframe.f_code.co_filename
523 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
524 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
524 # vds: <<
525 # vds: <<
525
526
526 do_l = do_list
527 do_l = do_list
527
528
528 def getsourcelines(self, obj):
529 def getsourcelines(self, obj):
529 lines, lineno = inspect.findsource(obj)
530 lines, lineno = inspect.findsource(obj)
530 if inspect.isframe(obj) and obj.f_globals is obj.f_locals:
531 if inspect.isframe(obj) and obj.f_globals is obj.f_locals:
531 # must be a module frame: do not try to cut a block out of it
532 # must be a module frame: do not try to cut a block out of it
532 return lines, 1
533 return lines, 1
533 elif inspect.ismodule(obj):
534 elif inspect.ismodule(obj):
534 return lines, 1
535 return lines, 1
535 return inspect.getblock(lines[lineno:]), lineno+1
536 return inspect.getblock(lines[lineno:]), lineno+1
536
537
537 def do_longlist(self, arg):
538 def do_longlist(self, arg):
538 """Print lines of code from the current stack frame.
539 """Print lines of code from the current stack frame.
539
540
540 Shows more lines than 'list' does.
541 Shows more lines than 'list' does.
541 """
542 """
542 self.lastcmd = 'longlist'
543 self.lastcmd = 'longlist'
543 try:
544 try:
544 lines, lineno = self.getsourcelines(self.curframe)
545 lines, lineno = self.getsourcelines(self.curframe)
545 except OSError as err:
546 except OSError as err:
546 self.error(err)
547 self.error(err)
547 return
548 return
548 last = lineno + len(lines)
549 last = lineno + len(lines)
549 self.print_list_lines(self.curframe.f_code.co_filename, lineno, last)
550 self.print_list_lines(self.curframe.f_code.co_filename, lineno, last)
550 do_ll = do_longlist
551 do_ll = do_longlist
551
552
552 def do_debug(self, arg):
553 def do_debug(self, arg):
553 """debug code
554 """debug code
554 Enter a recursive debugger that steps through the code
555 Enter a recursive debugger that steps through the code
555 argument (which is an arbitrary expression or statement to be
556 argument (which is an arbitrary expression or statement to be
556 executed in the current environment).
557 executed in the current environment).
557 """
558 """
558 sys.settrace(None)
559 sys.settrace(None)
559 globals = self.curframe.f_globals
560 globals = self.curframe.f_globals
560 locals = self.curframe_locals
561 locals = self.curframe_locals
561 p = self.__class__(completekey=self.completekey,
562 p = self.__class__(completekey=self.completekey,
562 stdin=self.stdin, stdout=self.stdout)
563 stdin=self.stdin, stdout=self.stdout)
563 p.use_rawinput = self.use_rawinput
564 p.use_rawinput = self.use_rawinput
564 p.prompt = "(%s) " % self.prompt.strip()
565 p.prompt = "(%s) " % self.prompt.strip()
565 self.message("ENTERING RECURSIVE DEBUGGER")
566 self.message("ENTERING RECURSIVE DEBUGGER")
566 sys.call_tracing(p.run, (arg, globals, locals))
567 sys.call_tracing(p.run, (arg, globals, locals))
567 self.message("LEAVING RECURSIVE DEBUGGER")
568 self.message("LEAVING RECURSIVE DEBUGGER")
568 sys.settrace(self.trace_dispatch)
569 sys.settrace(self.trace_dispatch)
569 self.lastcmd = p.lastcmd
570 self.lastcmd = p.lastcmd
570
571
571 def do_pdef(self, arg):
572 def do_pdef(self, arg):
572 """Print the call signature for any callable object.
573 """Print the call signature for any callable object.
573
574
574 The debugger interface to %pdef"""
575 The debugger interface to %pdef"""
575 namespaces = [('Locals', self.curframe.f_locals),
576 namespaces = [('Locals', self.curframe.f_locals),
576 ('Globals', self.curframe.f_globals)]
577 ('Globals', self.curframe.f_globals)]
577 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
578 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
578
579
579 def do_pdoc(self, arg):
580 def do_pdoc(self, arg):
580 """Print the docstring for an object.
581 """Print the docstring for an object.
581
582
582 The debugger interface to %pdoc."""
583 The debugger interface to %pdoc."""
583 namespaces = [('Locals', self.curframe.f_locals),
584 namespaces = [('Locals', self.curframe.f_locals),
584 ('Globals', self.curframe.f_globals)]
585 ('Globals', self.curframe.f_globals)]
585 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
586 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
586
587
587 def do_pfile(self, arg):
588 def do_pfile(self, arg):
588 """Print (or run through pager) the file where an object is defined.
589 """Print (or run through pager) the file where an object is defined.
589
590
590 The debugger interface to %pfile.
591 The debugger interface to %pfile.
591 """
592 """
592 namespaces = [('Locals', self.curframe.f_locals),
593 namespaces = [('Locals', self.curframe.f_locals),
593 ('Globals', self.curframe.f_globals)]
594 ('Globals', self.curframe.f_globals)]
594 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
595 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
595
596
596 def do_pinfo(self, arg):
597 def do_pinfo(self, arg):
597 """Provide detailed information about an object.
598 """Provide detailed information about an object.
598
599
599 The debugger interface to %pinfo, i.e., obj?."""
600 The debugger interface to %pinfo, i.e., obj?."""
600 namespaces = [('Locals', self.curframe.f_locals),
601 namespaces = [('Locals', self.curframe.f_locals),
601 ('Globals', self.curframe.f_globals)]
602 ('Globals', self.curframe.f_globals)]
602 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
603 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
603
604
604 def do_pinfo2(self, arg):
605 def do_pinfo2(self, arg):
605 """Provide extra detailed information about an object.
606 """Provide extra detailed information about an object.
606
607
607 The debugger interface to %pinfo2, i.e., obj??."""
608 The debugger interface to %pinfo2, i.e., obj??."""
608 namespaces = [('Locals', self.curframe.f_locals),
609 namespaces = [('Locals', self.curframe.f_locals),
609 ('Globals', self.curframe.f_globals)]
610 ('Globals', self.curframe.f_globals)]
610 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
611 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
611
612
612 def do_psource(self, arg):
613 def do_psource(self, arg):
613 """Print (or run through pager) the source code for an object."""
614 """Print (or run through pager) the source code for an object."""
614 namespaces = [('Locals', self.curframe.f_locals),
615 namespaces = [('Locals', self.curframe.f_locals),
615 ('Globals', self.curframe.f_globals)]
616 ('Globals', self.curframe.f_globals)]
616 self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
617 self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
617
618
618 def do_where(self, arg):
619 def do_where(self, arg):
619 """w(here)
620 """w(here)
620 Print a stack trace, with the most recent frame at the bottom.
621 Print a stack trace, with the most recent frame at the bottom.
621 An arrow indicates the "current frame", which determines the
622 An arrow indicates the "current frame", which determines the
622 context of most commands. 'bt' is an alias for this command.
623 context of most commands. 'bt' is an alias for this command.
623
624
624 Take a number as argument as an (optional) number of context line to
625 Take a number as argument as an (optional) number of context line to
625 print"""
626 print"""
626 if arg:
627 if arg:
627 context = int(arg)
628 context = int(arg)
628 self.print_stack_trace(context)
629 self.print_stack_trace(context)
629 else:
630 else:
630 self.print_stack_trace()
631 self.print_stack_trace()
631
632
632 do_w = do_where
633 do_w = do_where
633
634
634
635
635 def set_trace(frame=None):
636 def set_trace(frame=None):
636 """
637 """
637 Start debugging from `frame`.
638 Start debugging from `frame`.
638
639
639 If frame is not specified, debugging starts from caller's frame.
640 If frame is not specified, debugging starts from caller's frame.
640 """
641 """
641 Pdb().set_trace(frame or sys._getframe().f_back)
642 Pdb().set_trace(frame or sys._getframe().f_back)
General Comments 0
You need to be logged in to leave comments. Login now