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