diff -r 4a79a6153485 -r 80bd41498eef DebugClients/Python3/DebugClientBase.py --- a/DebugClients/Python3/DebugClientBase.py Wed Aug 31 18:30:40 2016 +0200 +++ b/DebugClients/Python3/DebugClientBase.py Wed Aug 31 18:31:57 2016 +0200 @@ -399,6 +399,9 @@ line = line[:-1] ## printerr(line) ##debug + + if "jsonrpc" in line: + return self.__handleJsonCommand(line) eoc = line.find('<') @@ -477,66 +480,61 @@ # remember for later return - if cmd == DebugProtocol.RequestEnv: - env = eval(arg.replace("u'", "'")) - for key, value in env.items(): - if key.endswith("+"): - if key[:-1] in os.environ: - os.environ[key[:-1]] += value - else: - os.environ[key[:-1]] = value - else: - os.environ[key] = value - return - - if cmd == DebugProtocol.RequestLoad: - self._fncache = {} - self.dircache = [] - sys.argv = [] - wd, fn, args, tracePython = arg.split('|') - self.__setCoding(fn) - sys.argv.append(fn) - sys.argv.extend(eval(args)) - sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) - if wd == '': - os.chdir(sys.path[1]) - else: - os.chdir(wd) - tracePython = int(tracePython) - self.running = sys.argv[0] - self.mainFrame = None - self.inRawMode = False - self.debugging = True - - self.threads.clear() - self.attachThread(mainThread=True) - - # set the system exception handling function to ensure, that - # we report on all unhandled exceptions - sys.excepthook = self.__unhandled_exception - self.__interceptSignals() - - # clear all old breakpoints, they'll get set after we have - # started - self.mainThread.clear_all_breaks() - - self.mainThread.tracePython = tracePython - - # This will eventually enter a local event loop. - # Note the use of backquotes to cause a repr of self.running. - # The need for this is on Windows os where backslash is the - # path separator. They will get inadvertantly stripped away - # during the eval causing IOErrors, if self.running is passed - # as a normal str. - self.debugMod.__dict__['__file__'] = self.running - sys.modules['__main__'] = self.debugMod - code = self.__compileFileSource(self.running) - if code: - self.callTraceEnabled = self.__newCallTraceEnabled - res = self.mainThread.run(code, self.debugMod.__dict__) - self.progTerminated(res) - return - +## if cmd == DebugProtocol.RequestEnv: +## env = eval(arg.replace("u'", "'")) +## for key, value in env.items(): +## if key.endswith("+"): +## if key[:-1] in os.environ: +## os.environ[key[:-1]] += value +## else: +## os.environ[key[:-1]] = value +## else: +## os.environ[key] = value +## return +## +## if cmd == DebugProtocol.RequestLoad: +## self._fncache = {} +## self.dircache = [] +## sys.argv = [] +## wd, fn, args, tracePython = arg.split('|') +## self.__setCoding(fn) +## sys.argv.append(fn) +## sys.argv.extend(eval(args)) +## sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) +## if wd == '': +## os.chdir(sys.path[1]) +## else: +## os.chdir(wd) +## tracePython = int(tracePython) +## self.running = sys.argv[0] +## self.mainFrame = None +## self.inRawMode = False +## self.debugging = True +## +## self.threads.clear() +## self.attachThread(mainThread=True) +## +## # set the system exception handling function to ensure, that +## # we report on all unhandled exceptions +## sys.excepthook = self.__unhandled_exception +## self.__interceptSignals() +## +## # clear all old breakpoints, they'll get set after we have +## # started +## self.mainThread.clear_all_breaks() +## +## self.mainThread.tracePython = tracePython +## +## # This will eventually enter a local event loop. +## self.debugMod.__dict__['__file__'] = self.running +## sys.modules['__main__'] = self.debugMod +## code = self.__compileFileSource(self.running) +## if code: +## self.callTraceEnabled = self.__newCallTraceEnabled +## res = self.mainThread.run(code, self.debugMod.__dict__) +## self.progTerminated(res) +## return +## if cmd == DebugProtocol.RequestRun: sys.argv = [] wd, fn, args = arg.split('|') @@ -836,18 +834,18 @@ return - if cmd == DebugProtocol.RequestBanner: - self.write('{0}{1}\n'.format(DebugProtocol.ResponseBanner, - str(("Python {0}".format(sys.version), - socket.gethostname(), self.variant)))) - return - - if cmd == DebugProtocol.RequestCapabilities: - self.write('{0}{1:d}, "Python3"\n'.format( - DebugProtocol.ResponseCapabilities, - self.__clientCapabilities())) - return - +## if cmd == DebugProtocol.RequestBanner: +## self.write('{0}{1}\n'.format(DebugProtocol.ResponseBanner, +## str(("Python {0}".format(sys.version), +## socket.gethostname(), self.variant)))) +## return +## +## if cmd == DebugProtocol.RequestCapabilities: +## self.write('{0}{1:d}, "Python3"\n'.format( +## DebugProtocol.ResponseCapabilities, +## self.__clientCapabilities())) +## return +## if cmd == DebugProtocol.RequestCompletion: self.__completionList(arg.replace("u'", "'")) return @@ -1021,7 +1019,113 @@ for l in list: self.write(l) + + def __handleJsonCommand(self, jsonStr): + """ + Private method to handle a command serialized as a JSON string. + """ + import json + + try: + commandDict = json.loads(jsonStr.strip()) + except json.JSONDecodeError as err: + printerr(str(err)) + return + + method = commandDict["method"] + params = commandDict["params"] + + if method == "RequestCapabilities": + self.__sendJsonCommand("ResponseCapabilities", { + "capabilities": self.__clientCapabilities(), + "clientType": "Python3" + }) + return + + if method == "RequestBanner": + self.__sendJsonCommand("ResponseBanner", { + "version": "Python {0}".format(sys.version), + "platform": socket.gethostname(), + "dbgclient": self.variant, + }) + return + + if method == "RequestEnvironment": + for key, value in params["environment"].items(): + if key.endswith("+"): + if key[:-1] in os.environ: + os.environ[key[:-1]] += value + else: + os.environ[key[:-1]] = value + else: + os.environ[key] = value + return + + if method == "RequestLoad": + printerr(method) + self._fncache = {} + self.dircache = [] + sys.argv = [] + self.__setCoding(params["filename"]) + sys.argv.append(params["filename"]) + sys.argv.extend(params["argv"]) + sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) + if params["workdir"] == '': + os.chdir(sys.path[1]) + else: + os.chdir(params["workdir"]) + self.running = sys.argv[0] + self.mainFrame = None + self.inRawMode = False + self.debugging = True + + self.fork_auto = params["autofork"] + self.fork_child = params["forkChild"] + + self.threads.clear() + self.attachThread(mainThread=True) + + # set the system exception handling function to ensure, that + # we report on all unhandled exceptions + sys.excepthook = self.__unhandled_exception + self.__interceptSignals() + + # clear all old breakpoints, they'll get set after we have + # started + self.mainThread.clear_all_breaks() + + self.mainThread.tracePython = params["traceInterpreter"] + + # This will eventually enter a local event loop. + self.debugMod.__dict__['__file__'] = self.running + sys.modules['__main__'] = self.debugMod + code = self.__compileFileSource(self.running) + if code: + self.callTraceEnabled = self.__newCallTraceEnabled + res = self.mainThread.run(code, self.debugMod.__dict__) + self.progTerminated(res) + return + + def __sendJsonCommand(self, command, params): + """ + Private method to send a single command to the client. + + @param command command name to be sent + @type str + @param params dictionary of named parameters for the command + @type dict + """ + import json + + commandDict = { + "jsonrpc": "2.0", + "method": command, + "params": params, + } + cmd = json.dumps(commandDict) + '\n' + self.write(cmd) + def __clientCapabilities(self): """ Private method to determine the clients capabilities.