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