DebugClients/Python3/DebugBase.py

branch
debugger speed
changeset 5174
8c48f5e0cd92
parent 5088
5b992bcb3c86
parent 5169
74e000797a93
equal deleted inserted replaced
5170:fb9168c2e069 5174:8c48f5e0cd92
14 import ctypes 14 import ctypes
15 import _thread 15 import _thread
16 import time 16 import time
17 from inspect import CO_GENERATOR 17 from inspect import CO_GENERATOR
18 18
19 from DebugProtocol import ResponseClearWatch, ResponseClearBreak, \
20 ResponseLine, ResponseSyntax, ResponseException, CallTrace
21 from DebugUtilities import getargvalues, formatargvalues 19 from DebugUtilities import getargvalues, formatargvalues
22 from BreakpointWatch import Breakpoint, Watch 20 from BreakpointWatch import Breakpoint, Watch
23 21
24 gRecursionLimit = 64 22 gRecursionLimit = 64
25 23
142 """ 140 """
143 cf = self.currentFrame 141 cf = self.currentFrame
144 while cf is not None and frmnr > 0: 142 while cf is not None and frmnr > 0:
145 cf = cf.f_back 143 cf = cf.f_back
146 frmnr -= 1 144 frmnr -= 1
145
146 try:
147 if "__pypy__" in sys.builtin_module_names:
148 import __pypy__
149 __pypy__.locals_to_fast(cf)
150 return
151 except Exception:
152 pass
153
147 ctypes.pythonapi.PyFrame_LocalsToFast( 154 ctypes.pythonapi.PyFrame_LocalsToFast(
148 ctypes.py_object(cf), 155 ctypes.py_object(cf),
149 ctypes.c_int(0)) 156 ctypes.c_int(0))
150 157
151 def step(self, traceMode): 158 def step(self, traceMode):
247 @type frame object 254 @type frame object
248 @param toFrame destination frame 255 @param toFrame destination frame
249 @type frame object 256 @type frame object
250 """ 257 """
251 if not self.__skipFrame(fromFrame) and not self.__skipFrame(toFrame): 258 if not self.__skipFrame(fromFrame) and not self.__skipFrame(toFrame):
252 fromStr = "{0}:{1}:{2}".format( 259 fromInfo = {
253 self._dbgClient.absPath(self.fix_frame_filename(fromFrame)), 260 "filename": self._dbgClient.absPath(
254 fromFrame.f_lineno, 261 self.fix_frame_filename(fromFrame)),
255 fromFrame.f_code.co_name) 262 "linenumber": fromFrame.f_lineno,
256 toStr = "{0}:{1}:{2}".format( 263 "codename": fromFrame.f_code.co_name,
257 self._dbgClient.absPath(self.fix_frame_filename(toFrame)), 264 }
258 toFrame.f_lineno, 265 toInfo = {
259 toFrame.f_code.co_name) 266 "filename": self._dbgClient.absPath(
260 self._dbgClient.write("{0}{1}@@{2}@@{3}\n".format( 267 self.fix_frame_filename(toFrame)),
261 CallTrace, event[0], fromStr, toStr)) 268 "linenumber": toFrame.f_lineno,
269 "codename": toFrame.f_code.co_name,
270 }
271 self._dbgClient.sendCallTrace(event, fromInfo, toInfo)
262 272
263 def trace_dispatch(self, frame, event, arg): 273 def trace_dispatch(self, frame, event, arg):
264 """ 274 """
265 Public method reimplemented from bdb.py to do some special things. 275 Public method reimplemented from bdb.py to do some special things.
266 276
311 if self.stop_here(frame): 321 if self.stop_here(frame):
312 # Ignore return events in generator except when stepping. 322 # Ignore return events in generator except when stepping.
313 if self.stopframe and frame.f_code.co_flags & CO_GENERATOR: 323 if self.stopframe and frame.f_code.co_flags & CO_GENERATOR:
314 return 324 return
315 # The program has finished if we have just left the first frame 325 # The program has finished if we have just left the first frame
316 if frame == self._dbgClient.mainFrame and \ 326 if (frame == self._dbgClient.mainFrame and
317 self._mainThread: 327 self._mainThread):
318 atexit._run_exitfuncs() 328 atexit._run_exitfuncs()
319 self._dbgClient.progTerminated(arg) 329 self._dbgClient.progTerminated(arg)
320 330
321 if self.quitting and not self._dbgClient.passive: 331 if self.quitting and not self._dbgClient.passive:
322 raise SystemExit 332 raise SystemExit
345 return 355 return
346 if event == 'c_exception': 356 if event == 'c_exception':
347 return 357 return
348 if event == 'c_return': 358 if event == 'c_return':
349 return 359 return
350 print('bdb.Bdb.dispatch: unknown debugging event: ', repr(event)) # __IGNORE_WARNING__ 360
361 print('DebugBase.trace_dispatch:' # __IGNORE_WARNING__
362 ' unknown debugging event: ',
363 repr(event))
351 return self.trace_dispatch 364 return self.trace_dispatch
352 365
353 def set_trace(self, frame=None): 366 def set_trace(self, frame=None):
354 """ 367 """
355 Public method to start debugging from 'frame'. 368 Public method to start debugging from 'frame'.
597 @type str 610 @type str
598 @param lineno linenumber of the bp 611 @param lineno linenumber of the bp
599 @type int 612 @type int
600 """ 613 """
601 Breakpoint.clear_break(filename, lineno) 614 Breakpoint.clear_break(filename, lineno)
602 self._dbgClient.write('{0}{1},{2:d}\n'.format( 615 self._dbgClient.sendClearTemporaryBreakpoint(filename, lineno)
603 ResponseClearBreak, filename, lineno))
604 616
605 def __do_clearWatch(self, cond): 617 def __do_clearWatch(self, cond):
606 """ 618 """
607 Private method called to clear a temporary watch expression. 619 Private method called to clear a temporary watch expression.
608 620
609 @param cond expression of the watch expression to be cleared 621 @param cond expression of the watch expression to be cleared
610 @type str 622 @type str
611 """ 623 """
612 Watch.clear_watch(cond) 624 Watch.clear_watch(cond)
613 self._dbgClient.write('{0}{1}\n'.format(ResponseClearWatch, cond)) 625 self._dbgClient.sendClearTemporaryWatch(cond)
614 626
615 def getStack(self): 627 def getStack(self):
616 """ 628 """
617 Public method to get the stack. 629 Public method to get the stack.
618 630
698 else: 710 else:
699 fr = fr.f_back 711 fr = fr.f_back
700 712
701 self.__isBroken = True 713 self.__isBroken = True
702 714
703 self._dbgClient.write('{0}{1}\n'.format(ResponseLine, str(stack))) 715 self._dbgClient.sendResponseLine(stack)
704 self._dbgClient.eventLoop() 716 self._dbgClient.eventLoop()
705 717
706 self.__isBroken = False 718 self.__isBroken = False
707 719
708 def user_exception(self, frame, excinfo, unhandled=False): 720 def user_exception(self, frame, excinfo, unhandled=False):
723 return 735 return
724 736
725 if exctype == SystemExit: 737 if exctype == SystemExit:
726 atexit._run_exitfuncs() 738 atexit._run_exitfuncs()
727 if excval is None: 739 if excval is None:
728 excval = 0 740 exitcode = 0
741 message = ""
729 elif isinstance(excval, str): 742 elif isinstance(excval, str):
730 self._dbgClient.write(excval) 743 exitcode = 1
731 excval = 1 744 message = excval
732 elif isinstance(excval, bytes): 745 elif isinstance(excval, bytes):
733 self._dbgClient.write(excval.decode()) 746 exitcode = 1
734 excval = 1 747 message = excval.decode()
735 if isinstance(excval, int): 748 elif isinstance(excval, int):
736 self._dbgClient.progTerminated(excval) 749 exitcode = excval
750 message = ""
751 elif isinstance(excval, SystemExit):
752 code = excval.code
753 if isinstance(code, str):
754 exitcode = 1
755 message = code
756 elif isinstance(code, bytes):
757 exitcode = 1
758 message = code.decode()
759 elif isinstance(code, int):
760 exitcode = code
761 message = ""
762 else:
763 exitcode = 1
764 message = str(code)
737 else: 765 else:
738 self._dbgClient.progTerminated(excval.code) 766 exitcode = 1
767 message = str(excval)
768 self._dbgClient.progTerminated(exitcode, message)
739 return 769 return
740 770
741 if exctype in [SyntaxError, IndentationError]: 771 if exctype in [SyntaxError, IndentationError]:
742 try: 772 try:
743 message = str(excval) 773 message = str(excval)
744 filename = excval.filename 774 filename = excval.filename
745 linenr = excval.lineno 775 lineno = excval.lineno
746 charnr = excval.offset 776 charno = excval.offset
777 realSyntaxError = os.path.exists(filename)
747 except (AttributeError, ValueError): 778 except (AttributeError, ValueError):
748 exclist = [] 779 message = ""
780 filename = ""
781 lineno = 0
782 charno = 0
749 realSyntaxError = True 783 realSyntaxError = True
750 else:
751 exclist = [message, [filename, linenr, charnr]]
752 realSyntaxError = os.path.exists(filename)
753 784
754 if realSyntaxError: 785 if realSyntaxError:
755 self._dbgClient.write("{0}{1}\n".format( 786 self._dbgClient.sendSyntaxError(
756 ResponseSyntax, str(exclist))) 787 message, filename, lineno, charno)
757 self._dbgClient.eventLoop() 788 self._dbgClient.eventLoop()
758 return 789 return
759 790
760 self.skipFrames = 0 791 self.skipFrames = 0
761 if (exctype == RuntimeError and 792 if (exctype == RuntimeError and
782 813
783 if unhandled: 814 if unhandled:
784 exctypetxt = "unhandled {0!s}".format(str(exctype)) 815 exctypetxt = "unhandled {0!s}".format(str(exctype))
785 else: 816 else:
786 exctypetxt = str(exctype) 817 exctypetxt = str(exctype)
787 try: 818
788 exclist = [exctypetxt, str(excval)] 819 stack = []
789 except TypeError:
790 exclist = [exctypetxt, str(excval)]
791
792 if exctb: 820 if exctb:
793 frlist = self.__extract_stack(exctb) 821 frlist = self.__extract_stack(exctb)
794 frlist.reverse() 822 frlist.reverse()
795 823
796 self.currentFrame = frlist[0] 824 self.currentFrame = frlist[0]
816 except Exception: 844 except Exception:
817 fargs = "" 845 fargs = ""
818 else: 846 else:
819 fargs = "" 847 fargs = ""
820 848
821 exclist.append([filename, linenr, ffunc, fargs]) 849 stack.append([filename, linenr, ffunc, fargs])
822 850
823 self._dbgClient.write("{0}{1}\n".format( 851 self._dbgClient.sendException(exctypetxt, str(excval), stack)
824 ResponseException, str(exclist)))
825 852
826 if exctb is None: 853 if exctb is None:
827 return 854 return
828 855
829 self._dbgClient.eventLoop() 856 self._dbgClient.eventLoop()
877 def tracePythonLibs(self, enable): 904 def tracePythonLibs(self, enable):
878 """ 905 """
879 Public method to update the settings to trace into Python libraries. 906 Public method to update the settings to trace into Python libraries.
880 907
881 @param enable flag to debug into Python libraries 908 @param enable flag to debug into Python libraries
882 @type int 909 @type bool
883 """ 910 """
884 pathsToSkip = list(self.pathsToSkip) 911 pathsToSkip = list(self.pathsToSkip)
885 # don't trace into Python library? 912 # don't trace into Python library?
886 if enable: 913 if enable:
887 pathsToSkip = [x for x in pathsToSkip if not x.endswith( 914 pathsToSkip = [x for x in pathsToSkip if not x.endswith(

eric ide

mercurial