475 else: |
478 else: |
476 self.__newCallTraceEnabled = callTraceEnabled |
479 self.__newCallTraceEnabled = callTraceEnabled |
477 # remember for later |
480 # remember for later |
478 return |
481 return |
479 |
482 |
480 if cmd == DebugProtocol.RequestEnv: |
483 ## if cmd == DebugProtocol.RequestEnv: |
481 env = eval(arg.replace("u'", "'")) |
484 ## env = eval(arg.replace("u'", "'")) |
482 for key, value in env.items(): |
485 ## for key, value in env.items(): |
483 if key.endswith("+"): |
486 ## if key.endswith("+"): |
484 if key[:-1] in os.environ: |
487 ## if key[:-1] in os.environ: |
485 os.environ[key[:-1]] += value |
488 ## os.environ[key[:-1]] += value |
486 else: |
489 ## else: |
487 os.environ[key[:-1]] = value |
490 ## os.environ[key[:-1]] = value |
488 else: |
491 ## else: |
489 os.environ[key] = value |
492 ## os.environ[key] = value |
490 return |
493 ## return |
491 |
494 ## |
492 if cmd == DebugProtocol.RequestLoad: |
495 ## if cmd == DebugProtocol.RequestLoad: |
493 self._fncache = {} |
496 ## self._fncache = {} |
494 self.dircache = [] |
497 ## self.dircache = [] |
495 sys.argv = [] |
498 ## sys.argv = [] |
496 wd, fn, args, tracePython = arg.split('|') |
499 ## wd, fn, args, tracePython = arg.split('|') |
497 self.__setCoding(fn) |
500 ## self.__setCoding(fn) |
498 sys.argv.append(fn) |
501 ## sys.argv.append(fn) |
499 sys.argv.extend(eval(args)) |
502 ## sys.argv.extend(eval(args)) |
500 sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
503 ## sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
501 if wd == '': |
504 ## if wd == '': |
502 os.chdir(sys.path[1]) |
505 ## os.chdir(sys.path[1]) |
503 else: |
506 ## else: |
504 os.chdir(wd) |
507 ## os.chdir(wd) |
505 tracePython = int(tracePython) |
508 ## tracePython = int(tracePython) |
506 self.running = sys.argv[0] |
509 ## self.running = sys.argv[0] |
507 self.mainFrame = None |
510 ## self.mainFrame = None |
508 self.inRawMode = False |
511 ## self.inRawMode = False |
509 self.debugging = True |
512 ## self.debugging = True |
510 |
513 ## |
511 self.threads.clear() |
514 ## self.threads.clear() |
512 self.attachThread(mainThread=True) |
515 ## self.attachThread(mainThread=True) |
513 |
516 ## |
514 # set the system exception handling function to ensure, that |
517 ## # set the system exception handling function to ensure, that |
515 # we report on all unhandled exceptions |
518 ## # we report on all unhandled exceptions |
516 sys.excepthook = self.__unhandled_exception |
519 ## sys.excepthook = self.__unhandled_exception |
517 self.__interceptSignals() |
520 ## self.__interceptSignals() |
518 |
521 ## |
519 # clear all old breakpoints, they'll get set after we have |
522 ## # clear all old breakpoints, they'll get set after we have |
520 # started |
523 ## # started |
521 self.mainThread.clear_all_breaks() |
524 ## self.mainThread.clear_all_breaks() |
522 |
525 ## |
523 self.mainThread.tracePython = tracePython |
526 ## self.mainThread.tracePython = tracePython |
524 |
527 ## |
525 # This will eventually enter a local event loop. |
528 ## # This will eventually enter a local event loop. |
526 # Note the use of backquotes to cause a repr of self.running. |
529 ## self.debugMod.__dict__['__file__'] = self.running |
527 # The need for this is on Windows os where backslash is the |
530 ## sys.modules['__main__'] = self.debugMod |
528 # path separator. They will get inadvertantly stripped away |
531 ## code = self.__compileFileSource(self.running) |
529 # during the eval causing IOErrors, if self.running is passed |
532 ## if code: |
530 # as a normal str. |
533 ## self.callTraceEnabled = self.__newCallTraceEnabled |
531 self.debugMod.__dict__['__file__'] = self.running |
534 ## res = self.mainThread.run(code, self.debugMod.__dict__) |
532 sys.modules['__main__'] = self.debugMod |
535 ## self.progTerminated(res) |
533 code = self.__compileFileSource(self.running) |
536 ## return |
534 if code: |
537 ## |
535 self.callTraceEnabled = self.__newCallTraceEnabled |
|
536 res = self.mainThread.run(code, self.debugMod.__dict__) |
|
537 self.progTerminated(res) |
|
538 return |
|
539 |
|
540 if cmd == DebugProtocol.RequestRun: |
538 if cmd == DebugProtocol.RequestRun: |
541 sys.argv = [] |
539 sys.argv = [] |
542 wd, fn, args = arg.split('|') |
540 wd, fn, args = arg.split('|') |
543 self.__setCoding(fn) |
541 self.__setCoding(fn) |
544 sys.argv.append(fn) |
542 sys.argv.append(fn) |
834 |
832 |
835 self.write(DebugProtocol.ResponseException + '\n') |
833 self.write(DebugProtocol.ResponseException + '\n') |
836 |
834 |
837 return |
835 return |
838 |
836 |
839 if cmd == DebugProtocol.RequestBanner: |
837 ## if cmd == DebugProtocol.RequestBanner: |
840 self.write('{0}{1}\n'.format(DebugProtocol.ResponseBanner, |
838 ## self.write('{0}{1}\n'.format(DebugProtocol.ResponseBanner, |
841 str(("Python {0}".format(sys.version), |
839 ## str(("Python {0}".format(sys.version), |
842 socket.gethostname(), self.variant)))) |
840 ## socket.gethostname(), self.variant)))) |
843 return |
841 ## return |
844 |
842 ## |
845 if cmd == DebugProtocol.RequestCapabilities: |
843 ## if cmd == DebugProtocol.RequestCapabilities: |
846 self.write('{0}{1:d}, "Python3"\n'.format( |
844 ## self.write('{0}{1:d}, "Python3"\n'.format( |
847 DebugProtocol.ResponseCapabilities, |
845 ## DebugProtocol.ResponseCapabilities, |
848 self.__clientCapabilities())) |
846 ## self.__clientCapabilities())) |
849 return |
847 ## return |
850 |
848 ## |
851 if cmd == DebugProtocol.RequestCompletion: |
849 if cmd == DebugProtocol.RequestCompletion: |
852 self.__completionList(arg.replace("u'", "'")) |
850 self.__completionList(arg.replace("u'", "'")) |
853 return |
851 return |
854 |
852 |
855 if cmd == DebugProtocol.RequestSetFilter: |
853 if cmd == DebugProtocol.RequestSetFilter: |
1019 finally: |
1017 finally: |
1020 tblist = exc_tb = None |
1018 tblist = exc_tb = None |
1021 |
1019 |
1022 for l in list: |
1020 for l in list: |
1023 self.write(l) |
1021 self.write(l) |
1024 |
1022 |
|
1023 def __handleJsonCommand(self, jsonStr): |
|
1024 """ |
|
1025 Private method to handle a command serialized as a JSON string. |
|
1026 """ |
|
1027 import json |
|
1028 |
|
1029 try: |
|
1030 commandDict = json.loads(jsonStr.strip()) |
|
1031 except json.JSONDecodeError as err: |
|
1032 printerr(str(err)) |
|
1033 return |
|
1034 |
|
1035 method = commandDict["method"] |
|
1036 params = commandDict["params"] |
|
1037 |
|
1038 if method == "RequestCapabilities": |
|
1039 self.__sendJsonCommand("ResponseCapabilities", { |
|
1040 "capabilities": self.__clientCapabilities(), |
|
1041 "clientType": "Python3" |
|
1042 }) |
|
1043 return |
|
1044 |
|
1045 if method == "RequestBanner": |
|
1046 self.__sendJsonCommand("ResponseBanner", { |
|
1047 "version": "Python {0}".format(sys.version), |
|
1048 "platform": socket.gethostname(), |
|
1049 "dbgclient": self.variant, |
|
1050 }) |
|
1051 return |
|
1052 |
|
1053 if method == "RequestEnvironment": |
|
1054 for key, value in params["environment"].items(): |
|
1055 if key.endswith("+"): |
|
1056 if key[:-1] in os.environ: |
|
1057 os.environ[key[:-1]] += value |
|
1058 else: |
|
1059 os.environ[key[:-1]] = value |
|
1060 else: |
|
1061 os.environ[key] = value |
|
1062 return |
|
1063 |
|
1064 if method == "RequestLoad": |
|
1065 printerr(method) |
|
1066 self._fncache = {} |
|
1067 self.dircache = [] |
|
1068 sys.argv = [] |
|
1069 self.__setCoding(params["filename"]) |
|
1070 sys.argv.append(params["filename"]) |
|
1071 sys.argv.extend(params["argv"]) |
|
1072 sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
|
1073 if params["workdir"] == '': |
|
1074 os.chdir(sys.path[1]) |
|
1075 else: |
|
1076 os.chdir(params["workdir"]) |
|
1077 self.running = sys.argv[0] |
|
1078 self.mainFrame = None |
|
1079 self.inRawMode = False |
|
1080 self.debugging = True |
|
1081 |
|
1082 self.fork_auto = params["autofork"] |
|
1083 self.fork_child = params["forkChild"] |
|
1084 |
|
1085 self.threads.clear() |
|
1086 self.attachThread(mainThread=True) |
|
1087 |
|
1088 # set the system exception handling function to ensure, that |
|
1089 # we report on all unhandled exceptions |
|
1090 sys.excepthook = self.__unhandled_exception |
|
1091 self.__interceptSignals() |
|
1092 |
|
1093 # clear all old breakpoints, they'll get set after we have |
|
1094 # started |
|
1095 self.mainThread.clear_all_breaks() |
|
1096 |
|
1097 self.mainThread.tracePython = params["traceInterpreter"] |
|
1098 |
|
1099 # This will eventually enter a local event loop. |
|
1100 self.debugMod.__dict__['__file__'] = self.running |
|
1101 sys.modules['__main__'] = self.debugMod |
|
1102 code = self.__compileFileSource(self.running) |
|
1103 if code: |
|
1104 self.callTraceEnabled = self.__newCallTraceEnabled |
|
1105 res = self.mainThread.run(code, self.debugMod.__dict__) |
|
1106 self.progTerminated(res) |
|
1107 return |
|
1108 |
|
1109 |
|
1110 def __sendJsonCommand(self, command, params): |
|
1111 """ |
|
1112 Private method to send a single command to the client. |
|
1113 |
|
1114 @param command command name to be sent |
|
1115 @type str |
|
1116 @param params dictionary of named parameters for the command |
|
1117 @type dict |
|
1118 """ |
|
1119 import json |
|
1120 |
|
1121 commandDict = { |
|
1122 "jsonrpc": "2.0", |
|
1123 "method": command, |
|
1124 "params": params, |
|
1125 } |
|
1126 cmd = json.dumps(commandDict) + '\n' |
|
1127 self.write(cmd) |
|
1128 |
1025 def __clientCapabilities(self): |
1129 def __clientCapabilities(self): |
1026 """ |
1130 """ |
1027 Private method to determine the clients capabilities. |
1131 Private method to determine the clients capabilities. |
1028 |
1132 |
1029 @return client capabilities (integer) |
1133 @return client capabilities (integer) |