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