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