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