Sat, 24 Sep 2016 22:52:13 +0200
Combined version of the Python debugger.
--- a/DebugClients/Python/AsyncFile.py Mon Sep 19 22:47:52 2016 +0200 +++ b/DebugClients/Python/AsyncFile.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> # """ @@ -12,6 +12,12 @@ from DebugUtilities import prepareJsonCommand +try: + unicode +except NameError: + unicode = str + raw_input = input + def AsyncPendingWrite(file): """ @@ -51,7 +57,7 @@ self.nWriteErrors = 0 self.encoding = "utf-8" - self.wpending = '' + self.wpending = unicode('') def __checkMode(self, mode): """ @@ -85,7 +91,7 @@ except socket.error: self.nWriteErrors += 1 if self.nWriteErrors > self.maxtries: - self.wpending = '' # delete all output + self.wpending = unicode('') # delete all output def pendingWrite(self): """ @@ -163,7 +169,7 @@ """ self.__checkMode('r') - buf = input() + buf = raw_input() if size >= 0: buf = buf[:size] return buf @@ -237,7 +243,7 @@ """ self.__checkMode('r') - line = input() + '\n' + line = raw_input() + '\n' if sizehint >= 0: line = line[:sizehint] return line
--- a/DebugClients/Python/DCTestResult.py Mon Sep 19 22:47:52 2016 +0200 +++ b/DebugClients/Python/DCTestResult.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) 2003 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> # """
--- a/DebugClients/Python/DebugBase.py Mon Sep 19 22:47:52 2016 +0200 +++ b/DebugClients/Python/DebugBase.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> # """ @@ -9,16 +9,24 @@ import sys import os +import types import atexit import inspect import ctypes -import _thread import time from inspect import CO_GENERATOR -from DebugUtilities import getargvalues, formatargvalues from BreakpointWatch import Breakpoint, Watch +if sys.version_info[0] == 2: + import thread as _thread + from inspect import getargvalues, formatargvalues +else: + import _thread + from DebugUtilities import getargvalues, formatargvalues + unicode = str + basestring = str + gRecursionLimit = 64 @@ -65,6 +73,11 @@ @param dbgClient the owning client """ self._dbgClient = dbgClient + if sys.version_info[0] == 2: + self.stopOnHandleLine = self._dbgClient.handleLine.func_code + else: + self.stopOnHandleLine = self._dbgClient.handleLine.__code__ + self._mainThread = True self.quitting = 0 @@ -380,7 +393,7 @@ frame.f_trace = self.trace_dispatch while frame is not None: # stop at erics debugger frame - if frame.f_back.f_code == self._dbgClient.handleLine.__code__: + if frame.f_back.f_code == self.stopOnHandleLine: frame.f_trace = self.trace_dispatch self.botframe = frame self._dbgClient.mainFrame = frame @@ -411,7 +424,7 @@ locals = globals sys.settrace(self.trace_dispatch) - if isinstance(cmd, str): + if not isinstance(cmd, types.CodeType): cmd = compile(cmd, "<string>", "exec") try: @@ -559,6 +572,9 @@ lineNo += co_lno lineNumbers.append(lineNo) + if sys.version_info[0] == 2: + lineNo = map(ord, lineNo) + for bp in Breakpoint.breakInFile[filename]: if bp in lineNumbers: Breakpoint.breakInFrameCache[ @@ -739,7 +755,7 @@ if excval is None: exitcode = 0 message = "" - elif isinstance(excval, str): + elif isinstance(excval, basestring): exitcode = 1 message = excval elif isinstance(excval, bytes): @@ -750,7 +766,7 @@ message = "" elif isinstance(excval, SystemExit): code = excval.code - if isinstance(code, str): + if isinstance(code, basestring): exitcode = 1 message = code elif isinstance(code, bytes): @@ -770,7 +786,15 @@ if exctype in [SyntaxError, IndentationError]: try: - message = str(excval) + if sys.version_info[0] == 2: + message = unicode(excval) + try: + message = unicode(excval).encode( + self._dbgClient.getCoding()) + except UnicodeError: + message = str(excval) + else: + message = str(excval) filename = excval.filename lineno = excval.lineno charno = excval.offset @@ -816,6 +840,14 @@ else: exctypetxt = str(exctype) + if sys.version_info[0] == 2: + try: + excvaltxt = unicode(excval).encode(self._dbgClient.getCoding()) + except UnicodeError: + excvaltxt = str(excval) + else: + excvaltxt = str(excval) + stack = [] if exctb: frlist = self.__extract_stack(exctb) @@ -848,7 +880,7 @@ stack.append([filename, linenr, ffunc, fargs]) - self._dbgClient.sendException(exctypetxt, str(excval), stack) + self._dbgClient.sendException(exctypetxt, excvaltxt, stack) if exctb is None: return @@ -864,7 +896,14 @@ @param exctype type of the exception @return exception name (string) """ - return str(exctype).replace("<class '", "").replace("'>", "") + if sys.version_info[0] == 2: + if type(exctype) in [types.ClassType, # Python up to 2.4 + types.TypeType]: # Python 2.5+ + return exctype.__name__ + else: + return exctype + else: + return str(exctype).replace("<class '", "").replace("'>", "") def __extract_stack(self, exctb): """
--- a/DebugClients/Python/DebugClient.py Mon Sep 19 22:47:52 2016 +0200 +++ b/DebugClients/Python/DebugClient.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) 2003 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> # """
--- 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): """
--- a/DebugClients/Python/DebugClientCapabilities.py Mon Sep 19 22:47:52 2016 +0200 +++ b/DebugClients/Python/DebugClientCapabilities.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) 2005 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> # """
--- a/DebugClients/Python/DebugConfig.py Mon Sep 19 22:47:52 2016 +0200 +++ b/DebugClients/Python/DebugConfig.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) 2005 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> # """
--- a/DebugClients/Python/FlexCompleter.py Mon Sep 19 22:47:52 2016 +0200 +++ b/DebugClients/Python/FlexCompleter.py Sat Sep 24 22:52:13 2016 +0200 @@ -48,7 +48,11 @@ </ul> """ -import builtins +try: + import __builtin__ as builtins +except ImportError: + import builtins + import __main__ __all__ = ["Completer"]
--- a/DebugClients/Python/PyProfile.py Mon Sep 19 22:47:52 2016 +0200 +++ b/DebugClients/Python/PyProfile.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> """ Module defining additions to the standard Python profile.py. @@ -11,6 +11,7 @@ import profile import atexit import pickle +import sys class PyProfile(profile.Profile): @@ -30,7 +31,10 @@ @param timer function defining the timing calculation @param bias calibration value (float) """ - profile.Profile.__init__(self, timer, bias) + try: + profile.Profile.__init__(self, timer, bias) + except TypeError: + profile.Profile.__init__(self, timer) self.dispatch = self.__class__.dispatch @@ -115,16 +119,21 @@ @param frame the frame object @return fixed up file name (string) """ + if sys.version_info[0] == 2: + versionExt = '.py2' + else: + versionExt = '.py3' + # get module name from __file__ if not isinstance(frame, profile.Profile.fake_frame) and \ '__file__' in frame.f_globals: root, ext = os.path.splitext(frame.f_globals['__file__']) - if ext in ['.pyc', '.py', '.py3', '.pyo']: + if ext in ['.pyc', '.py', versionExt, '.pyo']: fixedName = root + '.py' if os.path.exists(fixedName): return fixedName - fixedName = root + '.py3' + fixedName = root + versionExt if os.path.exists(fixedName): return fixedName
--- a/DebugClients/Python/__init__.py Mon Sep 19 22:47:52 2016 +0200 +++ b/DebugClients/Python/__init__.py Sat Sep 24 22:52:13 2016 +0200 @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2009 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# Copyright (c) 2005 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> # """ -Package implementing the Python3 debugger. +Package implementing the standard Python debugger. It consists of different kinds of debug clients. """
--- a/DebugClients/Python/eric6dbgstub.py Mon Sep 19 22:47:52 2016 +0200 +++ b/DebugClients/Python/eric6dbgstub.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> # """
--- a/DebugClients/Python/getpass.py Mon Sep 19 22:47:52 2016 +0200 +++ b/DebugClients/Python/getpass.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) 2004 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> # """
--- a/Debugger/DebuggerInterfacePython2.py Mon Sep 19 22:47:52 2016 +0200 +++ b/Debugger/DebuggerInterfacePython2.py Sat Sep 24 22:52:13 2016 +0200 @@ -149,17 +149,17 @@ debugClientType = Preferences.getDebugger("DebugClientType") if debugClientType == "standard": debugClient = os.path.join(getConfig('ericDir'), - "DebugClients", "Python2", + "DebugClients", "Python", "DebugClient.py") elif debugClientType == "threaded": debugClient = os.path.join(getConfig('ericDir'), - "DebugClients", "Python2", + "DebugClients", "Python", "DebugClientThreads.py") else: debugClient = Preferences.getDebugger("DebugClient") if debugClient == "": debugClient = os.path.join(sys.path[0], - "DebugClients", "Python2", + "DebugClients", "Python", "DebugClient.py") redirect = str(Preferences.getDebugger("PythonRedirect"))
--- a/Debugger/DebuggerInterfacePython3.py Mon Sep 19 22:47:52 2016 +0200 +++ b/Debugger/DebuggerInterfacePython3.py Sat Sep 24 22:52:13 2016 +0200 @@ -149,17 +149,17 @@ debugClientType = Preferences.getDebugger("DebugClientType3") if debugClientType == "standard": debugClient = os.path.join(getConfig('ericDir'), - "DebugClients", "Python3", + "DebugClients", "Python", "DebugClient.py") elif debugClientType == "threaded": debugClient = os.path.join(getConfig('ericDir'), - "DebugClients", "Python3", + "DebugClients", "Python", "DebugClientThreads.py") else: debugClient = Preferences.getDebugger("DebugClient3") if debugClient == "": debugClient = os.path.join(sys.path[0], - "DebugClients", "Python3", + "DebugClients", "Python", "DebugClient.py") redirect = str(Preferences.getDebugger("Python3Redirect"))
--- a/Preferences/__init__.py Mon Sep 19 22:47:52 2016 +0200 +++ b/Preferences/__init__.py Sat Sep 24 22:52:13 2016 +0200 @@ -113,15 +113,15 @@ } debuggerDefaults["AllowedHosts"] = ["127.0.0.1", "::1%0"] if sys.version_info[0] == 2: + # space separated list of Python2 extensions debuggerDefaults["PythonExtensions"] = ".py .pyw .py2 .pyw2 .ptl" - # space separated list of Python extensions - debuggerDefaults["Python3Extensions"] = ".py .pyw .py3 .pyw3" # space separated list of Python3 extensions + debuggerDefaults["Python3Extensions"] = ".py3 .pyw3" else: + # space separated list of Python2 extensions debuggerDefaults["PythonExtensions"] = ".py2 .pyw2 .ptl" - # space separated list of Python extensions + # space separated list of Python3 extensions debuggerDefaults["Python3Extensions"] = ".py .pyw .py3 .pyw3" - # space separated list of Python3 extensions # defaults for the UI settings uiDefaults = {
--- a/install-debugclients.py Mon Sep 19 22:47:52 2016 +0200 +++ b/install-debugclients.py Sat Sep 24 22:52:13 2016 +0200 @@ -307,10 +307,7 @@ if doCompile: print("\nCompiling source files ...") - if sys.version_info[0] == 3: - skipRe = re.compile(r"DebugClients[\\/]Python2[\\/]") - else: - skipRe = re.compile(r"DebugClients[\\/]Python3[\\/]") + skipRe = re.compile(r"DebugClients[\\/]Python[\\/]") # Hide compile errors (mainly because of Py2/Py3 differences) sys.stdout = io.StringIO() if distDir: