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