##// 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 self.shell.call_pdb = new_pdb
293 self.shell.call_pdb = new_pdb
294 print 'Automatic pdb calling has been turned',on_off(new_pdb)
294 print 'Automatic pdb calling has been turned',on_off(new_pdb)
295
295
296 @line_magic
296 @skip_doctest
297 def debug(self, parameter_s=''):
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 """Activate the interactive debugger in post-mortem mode.
311 """Activate the interactive debugger in post-mortem mode.
299
312
300 If an exception has just occurred, this lets you inspect its stack
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 If you want IPython to automatically do this on every exception, see
319 If you want IPython to automatically do this on every exception, see
307 the %pdb magic for more details.
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 self.shell.debugger(force=True)
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 @line_magic
343 @line_magic
312 def tb(self, s):
344 def tb(self, s):
313 """Print the last traceback with the currently active exception mode.
345 """Print the last traceback with the currently active exception mode.
@@ -560,8 +592,10 b' python-profiler package from non-free.""")'
560 stats = self._run_with_profiler(code, opts, code_ns)
592 stats = self._run_with_profiler(code, opts, code_ns)
561 else:
593 else:
562 if 'd' in opts:
594 if 'd' in opts:
595 bp_file, bp_line = parse_breakpoint(
596 opts.get('b', ['1'])[0], filename)
563 self._run_with_debugger(
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 else:
599 else:
566 if 'm' in opts:
600 if 'm' in opts:
567 def run():
601 def run():
@@ -629,7 +663,8 b' python-profiler package from non-free.""")'
629
663
630 return stats
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 Run `code` in debugger with a break point.
669 Run `code` in debugger with a break point.
635
670
@@ -639,19 +674,18 b' python-profiler package from non-free.""")'
639 Code to execute.
674 Code to execute.
640 code_ns : dict
675 code_ns : dict
641 A namespace in which `code` is executed.
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 filename : str
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 Path to the file in which break point is specified.
682 Path to the file in which break point is specified.
683 `filename` is used if not given.
649
684
650 Raises
685 Raises
651 ------
686 ------
652 UsageError
687 UsageError
653 If no meaningful break point is given by `break_point` and
688 If the break point given by `bp_line` is not valid.
654 `filename`.
655
689
656 """
690 """
657 deb = debugger.Pdb(self.shell.colors)
691 deb = debugger.Pdb(self.shell.colors)
@@ -660,34 +694,37 b' python-profiler package from non-free.""")'
660 bdb.Breakpoint.next = 1
694 bdb.Breakpoint.next = 1
661 bdb.Breakpoint.bplist = {}
695 bdb.Breakpoint.bplist = {}
662 bdb.Breakpoint.bpbynumber = [None]
696 bdb.Breakpoint.bpbynumber = [None]
663 # Set an initial breakpoint to stop execution
697 if bp_line is not None:
664 maxtries = 10
698 # Set an initial breakpoint to stop execution
665 bp_file, bp_line = parse_breakpoint(break_point, filename)
699 maxtries = 10
666 checkline = deb.checkline(bp_file, bp_line)
700 bp_file = bp_file or filename
667 if not checkline:
701 checkline = deb.checkline(bp_file, bp_line)
668 for bp in range(bp_line + 1, bp_line + maxtries + 1):
702 if not checkline:
669 if deb.checkline(bp_file, bp):
703 for bp in range(bp_line + 1, bp_line + maxtries + 1):
670 break
704 if deb.checkline(bp_file, bp):
671 else:
705 break
672 msg = ("\nI failed to find a valid line to set "
706 else:
673 "a breakpoint\n"
707 msg = ("\nI failed to find a valid line to set "
674 "after trying up to line: %s.\n"
708 "a breakpoint\n"
675 "Please set a valid breakpoint manually "
709 "after trying up to line: %s.\n"
676 "with the -b option." % bp)
710 "Please set a valid breakpoint manually "
677 raise UsageError(msg)
711 "with the -b option." % bp)
678 # if we find a good linenumber, set the breakpoint
712 raise UsageError(msg)
679 deb.do_break('%s:%s' % (bp_file, bp_line))
713 # if we find a good linenumber, set the breakpoint
680
714 deb.do_break('%s:%s' % (bp_file, bp_line))
681 # Mimic Pdb._runscript(...)
715
682 deb._wait_for_mainpyfile = True
716 if filename:
683 deb.mainpyfile = deb.canonic(filename)
717 # Mimic Pdb._runscript(...)
718 deb._wait_for_mainpyfile = True
719 deb.mainpyfile = deb.canonic(filename)
684
720
685 # Start file run
721 # Start file run
686 print "NOTE: Enter 'c' at the",
722 print "NOTE: Enter 'c' at the",
687 print "%s prompt to start your script." % deb.prompt
723 print "%s prompt to start your script." % deb.prompt
688 try:
724 try:
689 #save filename so it can be used by methods on the deb object
725 if filename:
690 deb._exec_filename = filename
726 # save filename so it can be used by methods on the deb object
727 deb._exec_filename = filename
691 deb.run(code, code_ns)
728 deb.run(code, code_ns)
692
729
693 except:
730 except:
General Comments 0
You need to be logged in to leave comments. Login now