1 # -*- coding: utf-8 -*- |
1 # -*- coding: utf-8 -*- |
2 |
2 |
3 # Copyright (c) 2009 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> |
3 # Copyright (c) 2002 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> |
4 # |
4 # |
5 |
5 |
6 """ |
6 """ |
7 Module implementing the debug base class which based originally on bdb. |
7 Module implementing the debug base class which based originally on bdb. |
8 """ |
8 """ |
9 |
9 |
10 import sys |
10 import sys |
11 import os |
11 import os |
|
12 import types |
12 import atexit |
13 import atexit |
13 import inspect |
14 import inspect |
14 import ctypes |
15 import ctypes |
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 DebugUtilities import getargvalues, formatargvalues |
|
20 from BreakpointWatch import Breakpoint, Watch |
19 from BreakpointWatch import Breakpoint, Watch |
|
20 |
|
21 if sys.version_info[0] == 2: |
|
22 import thread as _thread |
|
23 from inspect import getargvalues, formatargvalues |
|
24 else: |
|
25 import _thread |
|
26 from DebugUtilities import getargvalues, formatargvalues |
|
27 unicode = str |
|
28 basestring = str |
21 |
29 |
22 gRecursionLimit = 64 |
30 gRecursionLimit = 64 |
23 |
31 |
24 |
32 |
25 def printerr(s): |
33 def printerr(s): |
63 Constructor |
71 Constructor |
64 |
72 |
65 @param dbgClient the owning client |
73 @param dbgClient the owning client |
66 """ |
74 """ |
67 self._dbgClient = dbgClient |
75 self._dbgClient = dbgClient |
|
76 if sys.version_info[0] == 2: |
|
77 self.stopOnHandleLine = self._dbgClient.handleLine.func_code |
|
78 else: |
|
79 self.stopOnHandleLine = self._dbgClient.handleLine.__code__ |
|
80 |
68 self._mainThread = True |
81 self._mainThread = True |
69 self.quitting = 0 |
82 self.quitting = 0 |
70 |
83 |
71 self.tracePythonLibs(0) |
84 self.tracePythonLibs(0) |
72 |
85 |
378 frame = sys._getframe().f_back # Skip set_trace method |
391 frame = sys._getframe().f_back # Skip set_trace method |
379 |
392 |
380 frame.f_trace = self.trace_dispatch |
393 frame.f_trace = self.trace_dispatch |
381 while frame is not None: |
394 while frame is not None: |
382 # stop at erics debugger frame |
395 # stop at erics debugger frame |
383 if frame.f_back.f_code == self._dbgClient.handleLine.__code__: |
396 if frame.f_back.f_code == self.stopOnHandleLine: |
384 frame.f_trace = self.trace_dispatch |
397 frame.f_trace = self.trace_dispatch |
385 self.botframe = frame |
398 self.botframe = frame |
386 self._dbgClient.mainFrame = frame |
399 self._dbgClient.mainFrame = frame |
387 break |
400 break |
388 |
401 |
409 |
422 |
410 if locals is None: |
423 if locals is None: |
411 locals = globals |
424 locals = globals |
412 |
425 |
413 sys.settrace(self.trace_dispatch) |
426 sys.settrace(self.trace_dispatch) |
414 if isinstance(cmd, str): |
427 if not isinstance(cmd, types.CodeType): |
415 cmd = compile(cmd, "<string>", "exec") |
428 cmd = compile(cmd, "<string>", "exec") |
416 |
429 |
417 try: |
430 try: |
418 exec(cmd, globals, locals) |
431 exec(cmd, globals, locals) |
419 except SystemExit: |
432 except SystemExit: |
557 # (e.g. closure), because the additional lines won't cause a bp |
570 # (e.g. closure), because the additional lines won't cause a bp |
558 for co_lno in frame.f_code.co_lnotab[1::2]: |
571 for co_lno in frame.f_code.co_lnotab[1::2]: |
559 lineNo += co_lno |
572 lineNo += co_lno |
560 lineNumbers.append(lineNo) |
573 lineNumbers.append(lineNo) |
561 |
574 |
|
575 if sys.version_info[0] == 2: |
|
576 lineNo = map(ord, lineNo) |
|
577 |
562 for bp in Breakpoint.breakInFile[filename]: |
578 for bp in Breakpoint.breakInFile[filename]: |
563 if bp in lineNumbers: |
579 if bp in lineNumbers: |
564 Breakpoint.breakInFrameCache[ |
580 Breakpoint.breakInFrameCache[ |
565 frame.f_globals.get('__file__'), |
581 frame.f_globals.get('__file__'), |
566 frame.f_code.co_firstlineno] = True |
582 frame.f_code.co_firstlineno] = True |
737 if exctype == SystemExit: |
753 if exctype == SystemExit: |
738 atexit._run_exitfuncs() |
754 atexit._run_exitfuncs() |
739 if excval is None: |
755 if excval is None: |
740 exitcode = 0 |
756 exitcode = 0 |
741 message = "" |
757 message = "" |
742 elif isinstance(excval, str): |
758 elif isinstance(excval, basestring): |
743 exitcode = 1 |
759 exitcode = 1 |
744 message = excval |
760 message = excval |
745 elif isinstance(excval, bytes): |
761 elif isinstance(excval, bytes): |
746 exitcode = 1 |
762 exitcode = 1 |
747 message = excval.decode() |
763 message = excval.decode() |
748 elif isinstance(excval, int): |
764 elif isinstance(excval, int): |
749 exitcode = excval |
765 exitcode = excval |
750 message = "" |
766 message = "" |
751 elif isinstance(excval, SystemExit): |
767 elif isinstance(excval, SystemExit): |
752 code = excval.code |
768 code = excval.code |
753 if isinstance(code, str): |
769 if isinstance(code, basestring): |
754 exitcode = 1 |
770 exitcode = 1 |
755 message = code |
771 message = code |
756 elif isinstance(code, bytes): |
772 elif isinstance(code, bytes): |
757 exitcode = 1 |
773 exitcode = 1 |
758 message = code.decode() |
774 message = code.decode() |
768 self._dbgClient.progTerminated(exitcode, message) |
784 self._dbgClient.progTerminated(exitcode, message) |
769 return |
785 return |
770 |
786 |
771 if exctype in [SyntaxError, IndentationError]: |
787 if exctype in [SyntaxError, IndentationError]: |
772 try: |
788 try: |
773 message = str(excval) |
789 if sys.version_info[0] == 2: |
|
790 message = unicode(excval) |
|
791 try: |
|
792 message = unicode(excval).encode( |
|
793 self._dbgClient.getCoding()) |
|
794 except UnicodeError: |
|
795 message = str(excval) |
|
796 else: |
|
797 message = str(excval) |
774 filename = excval.filename |
798 filename = excval.filename |
775 lineno = excval.lineno |
799 lineno = excval.lineno |
776 charno = excval.offset |
800 charno = excval.offset |
777 realSyntaxError = os.path.exists(filename) |
801 realSyntaxError = os.path.exists(filename) |
778 except (AttributeError, ValueError): |
802 except (AttributeError, ValueError): |
814 if unhandled: |
838 if unhandled: |
815 exctypetxt = "unhandled {0!s}".format(str(exctype)) |
839 exctypetxt = "unhandled {0!s}".format(str(exctype)) |
816 else: |
840 else: |
817 exctypetxt = str(exctype) |
841 exctypetxt = str(exctype) |
818 |
842 |
|
843 if sys.version_info[0] == 2: |
|
844 try: |
|
845 excvaltxt = unicode(excval).encode(self._dbgClient.getCoding()) |
|
846 except UnicodeError: |
|
847 excvaltxt = str(excval) |
|
848 else: |
|
849 excvaltxt = str(excval) |
|
850 |
819 stack = [] |
851 stack = [] |
820 if exctb: |
852 if exctb: |
821 frlist = self.__extract_stack(exctb) |
853 frlist = self.__extract_stack(exctb) |
822 frlist.reverse() |
854 frlist.reverse() |
823 |
855 |
846 else: |
878 else: |
847 fargs = "" |
879 fargs = "" |
848 |
880 |
849 stack.append([filename, linenr, ffunc, fargs]) |
881 stack.append([filename, linenr, ffunc, fargs]) |
850 |
882 |
851 self._dbgClient.sendException(exctypetxt, str(excval), stack) |
883 self._dbgClient.sendException(exctypetxt, excvaltxt, stack) |
852 |
884 |
853 if exctb is None: |
885 if exctb is None: |
854 return |
886 return |
855 |
887 |
856 self._dbgClient.eventLoop() |
888 self._dbgClient.eventLoop() |
862 type object. |
894 type object. |
863 |
895 |
864 @param exctype type of the exception |
896 @param exctype type of the exception |
865 @return exception name (string) |
897 @return exception name (string) |
866 """ |
898 """ |
867 return str(exctype).replace("<class '", "").replace("'>", "") |
899 if sys.version_info[0] == 2: |
|
900 if type(exctype) in [types.ClassType, # Python up to 2.4 |
|
901 types.TypeType]: # Python 2.5+ |
|
902 return exctype.__name__ |
|
903 else: |
|
904 return exctype |
|
905 else: |
|
906 return str(exctype).replace("<class '", "").replace("'>", "") |
868 |
907 |
869 def __extract_stack(self, exctb): |
908 def __extract_stack(self, exctb): |
870 """ |
909 """ |
871 Private member to return a list of stack frames. |
910 Private member to return a list of stack frames. |
872 |
911 |