##// END OF EJS Templates
Add a mode to exec code in %debug magic
Takafumi Arakaki -
Show More
@@ -293,8 +293,21 b' python-profiler package from non-free.""")'
293 293 self.shell.call_pdb = new_pdb
294 294 print 'Automatic pdb calling has been turned',on_off(new_pdb)
295 295
296 @line_magic
297 def debug(self, parameter_s=''):
296 @skip_doctest
297 @magic_arguments.magic_arguments()
298 @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE',
299 help="""
300 Set break point at LINE in FILE.
301 """
302 )
303 @magic_arguments.argument('statement', nargs='*',
304 help="""
305 Code to run in debugger.
306 You can omit this in cell magic mode.
307 """
308 )
309 @line_cell_magic
310 def debug(self, line='', cell=None):
298 311 """Activate the interactive debugger in post-mortem mode.
299 312
300 313 If an exception has just occurred, this lets you inspect its stack
@@ -306,8 +319,27 b' python-profiler package from non-free.""")'
306 319 If you want IPython to automatically do this on every exception, see
307 320 the %pdb magic for more details.
308 321 """
322 args = magic_arguments.parse_argstring(self.debug, line)
323
324 if not (args.breakpoint or args.statement or cell):
325 self._debug_post_mortem()
326 else:
327 code = "\n".join(args.statement)
328 if cell:
329 code += "\n" + cell
330 self._debug_exec(code, args.breakpoint)
331
332 def _debug_post_mortem(self):
309 333 self.shell.debugger(force=True)
310 334
335 def _debug_exec(self, code, breakpoint):
336 if breakpoint:
337 (filename, bp_line) = breakpoint.split(':', 1)
338 bp_line = int(bp_line)
339 else:
340 (filename, bp_line) = (None, None)
341 self._run_with_debugger(code, self.shell.user_ns, filename, bp_line)
342
311 343 @line_magic
312 344 def tb(self, s):
313 345 """Print the last traceback with the currently active exception mode.
@@ -560,8 +592,10 b' python-profiler package from non-free.""")'
560 592 stats = self._run_with_profiler(code, opts, code_ns)
561 593 else:
562 594 if 'd' in opts:
595 bp_file, bp_line = parse_breakpoint(
596 opts.get('b', ['1'])[0], filename)
563 597 self._run_with_debugger(
564 code, code_ns, opts.get('b', ['1'])[0], filename)
598 code, code_ns, filename, bp_line, bp_file)
565 599 else:
566 600 if 'm' in opts:
567 601 def run():
@@ -629,7 +663,8 b' python-profiler package from non-free.""")'
629 663
630 664 return stats
631 665
632 def _run_with_debugger(self, code, code_ns, break_point, filename):
666 def _run_with_debugger(self, code, code_ns, filename=None,
667 bp_line=None, bp_file=None):
633 668 """
634 669 Run `code` in debugger with a break point.
635 670
@@ -639,19 +674,18 b' python-profiler package from non-free.""")'
639 674 Code to execute.
640 675 code_ns : dict
641 676 A namespace in which `code` is executed.
642 break_point : str
643 Line number in the file specified by `filename` argument
644 or a string in the format ``file:line``. In the latter
645 case, `filename` is ignored.
646 See also :func:`.parse_breakpoint`.
647 677 filename : str
678 `code` is ran as if it is in `filename`.
679 bp_line : int, optional
680 Line number of the break point.
681 bp_file : str, optional
648 682 Path to the file in which break point is specified.
683 `filename` is used if not given.
649 684
650 685 Raises
651 686 ------
652 687 UsageError
653 If no meaningful break point is given by `break_point` and
654 `filename`.
688 If the break point given by `bp_line` is not valid.
655 689
656 690 """
657 691 deb = debugger.Pdb(self.shell.colors)
@@ -660,34 +694,37 b' python-profiler package from non-free.""")'
660 694 bdb.Breakpoint.next = 1
661 695 bdb.Breakpoint.bplist = {}
662 696 bdb.Breakpoint.bpbynumber = [None]
663 # Set an initial breakpoint to stop execution
664 maxtries = 10
665 bp_file, bp_line = parse_breakpoint(break_point, filename)
666 checkline = deb.checkline(bp_file, bp_line)
667 if not checkline:
668 for bp in range(bp_line + 1, bp_line + maxtries + 1):
669 if deb.checkline(bp_file, bp):
670 break
671 else:
672 msg = ("\nI failed to find a valid line to set "
673 "a breakpoint\n"
674 "after trying up to line: %s.\n"
675 "Please set a valid breakpoint manually "
676 "with the -b option." % bp)
677 raise UsageError(msg)
678 # if we find a good linenumber, set the breakpoint
679 deb.do_break('%s:%s' % (bp_file, bp_line))
680
681 # Mimic Pdb._runscript(...)
682 deb._wait_for_mainpyfile = True
683 deb.mainpyfile = deb.canonic(filename)
697 if bp_line is not None:
698 # Set an initial breakpoint to stop execution
699 maxtries = 10
700 bp_file = bp_file or filename
701 checkline = deb.checkline(bp_file, bp_line)
702 if not checkline:
703 for bp in range(bp_line + 1, bp_line + maxtries + 1):
704 if deb.checkline(bp_file, bp):
705 break
706 else:
707 msg = ("\nI failed to find a valid line to set "
708 "a breakpoint\n"
709 "after trying up to line: %s.\n"
710 "Please set a valid breakpoint manually "
711 "with the -b option." % bp)
712 raise UsageError(msg)
713 # if we find a good linenumber, set the breakpoint
714 deb.do_break('%s:%s' % (bp_file, bp_line))
715
716 if filename:
717 # Mimic Pdb._runscript(...)
718 deb._wait_for_mainpyfile = True
719 deb.mainpyfile = deb.canonic(filename)
684 720
685 721 # Start file run
686 722 print "NOTE: Enter 'c' at the",
687 723 print "%s prompt to start your script." % deb.prompt
688 724 try:
689 #save filename so it can be used by methods on the deb object
690 deb._exec_filename = filename
725 if filename:
726 # save filename so it can be used by methods on the deb object
727 deb._exec_filename = filename
691 728 deb.run(code, code_ns)
692 729
693 730 except:
General Comments 0
You need to be logged in to leave comments. Login now