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 |
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( |