--- a/DebugClients/Python/DebugClientBase.py Mon Sep 19 22:47:52 2016 +0200 +++ b/DebugClients/Python/DebugClientBase.py Sat Sep 24 22:52:13 2016 +0200 @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2009 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# Copyright (c) 2002 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> # """ @@ -11,6 +11,7 @@ import socket import select import codeop +import codecs import traceback import os import json @@ -26,15 +27,36 @@ from AsyncFile import AsyncFile, AsyncPendingWrite from DebugConfig import ConfigVarTypeStrings from FlexCompleter import Completer -from DebugUtilities import getargvalues, formatargvalues, prepareJsonCommand +from DebugUtilities import prepareJsonCommand from BreakpointWatch import Breakpoint, Watch +if sys.version_info[0] == 2: + from inspect import getargvalues, formatargvalues +else: + unichr = chr + from DebugUtilities import getargvalues, formatargvalues DebugClientInstance = None ############################################################################### +def DebugClientRawInput(prompt="", echo=True): + """ + Replacement for the standard raw_input builtin. + + This function works with the split debugger. + + @param prompt prompt to be shown. (string) + @param echo flag indicating echoing of the input (boolean) + @return result of the raw_input() call + """ + if DebugClientInstance is None or not DebugClientInstance.redirect: + return DebugClientOrigRawInput(prompt) + + return DebugClientInstance.raw_input(prompt, echo) + + def DebugClientInput(prompt="", echo=True): """ Replacement for the standard input builtin. @@ -50,14 +72,31 @@ return DebugClientInstance.input(prompt, echo) -# Use our own input(). -try: - DebugClientOrigInput = __builtins__.__dict__['input'] - __builtins__.__dict__['input'] = DebugClientInput -except (AttributeError, KeyError): - import __main__ - DebugClientOrigInput = __main__.__builtins__.__dict__['input'] - __main__.__builtins__.__dict__['input'] = DebugClientInput +# Use our own input() and on Python 2 raw_input(). +if sys.version_info[0] == 2: + try: + DebugClientOrigRawInput = __builtins__.__dict__['raw_input'] + __builtins__.__dict__['raw_input'] = DebugClientRawInput + except (AttributeError, KeyError): + import __main__ + DebugClientOrigRawInput = __main__.__builtins__.__dict__['raw_input'] + __main__.__builtins__.__dict__['raw_input'] = DebugClientRawInput + + try: + DebugClientOrigInput = __builtins__.__dict__['input'] + __builtins__.__dict__['input'] = DebugClientInput + except (AttributeError, KeyError): + import __main__ + DebugClientOrigInput = __main__.__builtins__.__dict__['input'] + __main__.__builtins__.__dict__['input'] = DebugClientInput +else: + try: + DebugClientOrigInput = __builtins__.__dict__['input'] + __builtins__.__dict__['input'] = DebugClientRawInput + except (AttributeError, KeyError): + import __main__ + DebugClientOrigInput = __main__.__builtins__.__dict__['input'] + __main__.__builtins__.__dict__['input'] = DebugClientRawInput ############################################################################### @@ -236,8 +275,8 @@ self.__coding = default return - for l in text.splitlines(): - m = self.coding_re.search(l) + for line in text.splitlines(): + m = self.coding_re.search(line) if m: self.__coding = m.group(1) return @@ -290,9 +329,9 @@ "threadList": threadList, }) - def input(self, prompt, echo=True): + def raw_input(self, prompt, echo): """ - Public method to implement input() using the event loop. + Public method to implement raw_input() / input() using the event loop. @param prompt the prompt to be shown (string) @param echo Flag indicating echoing of the input (boolean) @@ -305,6 +344,15 @@ self.eventLoop(True) return self.rawLine + def input(self, prompt): + """ + Public method to implement input() (Python 2) using the event loop. + + @param prompt the prompt to be shown (string) + @return the entered string evaluated as a Python expresion + """ + return eval(self.raw_input(prompt, True)) + def sessionClose(self, exit=True): """ Public method to close the session with the debugger and optionally @@ -338,9 +386,16 @@ @param mode kind of code to be generated (string, exec or eval) @return compiled code object (None in case of errors) """ - with open(filename, encoding=self.__coding) as fp: + with codecs.open(filename, encoding=self.__coding) as fp: statement = fp.read() + if sys.version_info[0] == 2: + lines = statement.splitlines(True) + for lineno, line in enumerate(lines[:2]): + lines[lineno] = self.coding_re.sub('', line) + + statement = unicode('').join(lines) # __IGNORE_WARNING__ + try: code = compile(statement + '\n', filename, mode) except SyntaxError: @@ -392,6 +447,9 @@ method = commandDict["method"] params = commandDict["params"] + if "filename" in params and sys.version_info[0] == 2: + params["filename"] = params["filename"].encode( + sys.getfilesystemencoding()) if method == "RequestVariables": self.__dumpVariables( @@ -415,9 +473,10 @@ }) elif method == "RequestCapabilities": + clientType = "Python2" if sys.version_info[0] == 2 else "Python3" self.sendJsonCommand("ResponseCapabilities", { "capabilities": self.__clientCapabilities(), - "clientType": "Python3" + "clientType": clientType }) elif method == "RequestBanner": @@ -564,15 +623,8 @@ self.cover.erase() sys.modules['__main__'] = self.debugMod self.debugMod.__dict__['__file__'] = sys.argv[0] - fp = open(sys.argv[0], encoding=self.__coding) - try: - script = fp.read() - finally: - fp.close() - if script: - if not script.endswith('\n'): - script += '\n' - code = compile(script, sys.argv[0], 'exec') + code = self.__compileFileSource(sys.argv[0]) + if code: self.running = sys.argv[0] res = 0 self.cover.start() @@ -611,21 +663,24 @@ self.prof.erase() self.debugMod.__dict__['__file__'] = sys.argv[0] sys.modules['__main__'] = self.debugMod - fp = open(sys.argv[0], encoding=self.__coding) - try: - script = fp.read() - finally: - fp.close() + script = '' + if sys.version_info[0] == 2: + script = 'execfile({0!r})'.format(sys.argv[0]) + else: + with codecs.open(sys.argv[0], encoding=self.__coding) as fp: + script = fp.read() + if script and not script.endswith('\n'): + script += '\n' + if script: - if not script.endswith('\n'): - script += '\n' self.running = sys.argv[0] res = 0 try: self.prof.run(script) except SystemExit as exc: res = exc.code - atexit._run_exitfuncs() + + atexit._run_exitfuncs() self.prof.save() self.writestream.flush() self.progTerminated(res) @@ -796,8 +851,7 @@ flag = '' try: - compiledCond = compile( - compiledCond, '<string>', 'eval') + compiledCond = compile(compiledCond, '<string>', 'eval') except SyntaxError: self.sendJsonCommand("ResponseWatchConditionError", { "condition": params["condition"], @@ -1469,7 +1523,8 @@ """ varlist = [] if qttype == 'QChar': - varlist.append(("", "QChar", "{0}".format(chr(value.unicode())))) + varlist.append( + ("", "QChar", "{0}".format(unichr(value.unicode())))) varlist.append(("", "int", "{0:d}".format(value.unicode()))) elif qttype == 'QByteArray': varlist.append( @@ -1480,6 +1535,12 @@ ("base64", "QByteArray", "{0}".format(value.toBase64())[2:-1])) varlist.append(("percent encoding", "QByteArray", "{0}".format(value.toPercentEncoding())[2:-1])) + elif qttype == 'QString': + varlist.append(("", "QString", "{0}".format(value))) + elif qttype == 'QStringList': + for i in range(value.count()): + varlist.append( + ("{0:d}".format(i), "QString", "{0}".format(value[i]))) elif qttype == 'QPoint': varlist.append(("x", "int", "{0:d}".format(value.x()))) varlist.append(("y", "int", "{0:d}".format(value.y()))) @@ -1595,7 +1656,7 @@ return varlist - def __formatVariablesList(self, keylist, dict, scope, filter=[], + def __formatVariablesList(self, keylist, dict_, scope, filter=[], formatSequences=False): """ Private method to produce a formated variables list. @@ -1607,7 +1668,7 @@ values) is returned. @param keylist keys of the dictionary - @param dict the dictionary to be scanned + @param dict_ the dictionary to be scanned @param scope 1 to filter using the globals filter, 0 using the locals filter (int). Variables are only added to the list, if their name do not match @@ -1649,10 +1710,11 @@ rvalue = '<module __builtin__ (built-in)>' valtype = 'module' else: - value = dict[key] + value = dict_[key] valtypestr = str(type(value))[1:-1] - valtype = valtypestr[7:-1] + _, valtype = valtypestr.split(' ', 1) + valtype = valtype[1:-1] if valtype not in ConfigVarTypeStrings: if ConfigVarTypeStrings.index('instance') in filter: continue @@ -1928,8 +1990,8 @@ family = socket.AF_INET else: family = socket.AF_INET6 - return socket.getaddrinfo(host, None, - family, socket.SOCK_STREAM)[0][4][0] + return socket.getaddrinfo(host, None, family, + socket.SOCK_STREAM)[0][4][0] def main(self): """