Continued modernizing the debugger interface. jsonrpc

Fri, 02 Sep 2016 19:14:41 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Fri, 02 Sep 2016 19:14:41 +0200
branch
jsonrpc
changeset 5128
b6cbdba69967
parent 5125
eb1b3e0577e4
child 5129
e4ab234cf071

Continued modernizing the debugger interface.

DebugClients/Python3/AsyncFile.py file | annotate | diff | comparison | revisions
DebugClients/Python3/AsyncIO.py file | annotate | diff | comparison | revisions
DebugClients/Python3/DCTestResult.py file | annotate | diff | comparison | revisions
DebugClients/Python3/DebugBase.py file | annotate | diff | comparison | revisions
DebugClients/Python3/DebugClient.py file | annotate | diff | comparison | revisions
DebugClients/Python3/DebugClientBase.py file | annotate | diff | comparison | revisions
DebugClients/Python3/DebugClientThreads.py file | annotate | diff | comparison | revisions
DebugClients/Python3/DebugProtocol.py file | annotate | diff | comparison | revisions
Debugger/DebuggerInterfacePython3.py file | annotate | diff | comparison | revisions
Documentation/Source/eric6.DebugClients.Python3.AsyncIO.html file | annotate | diff | comparison | revisions
Documentation/Source/eric6.DebugClients.Python3.DebugProtocol.html file | annotate | diff | comparison | revisions
eric6.e4p file | annotate | diff | comparison | revisions
--- a/DebugClients/Python3/AsyncFile.py	Thu Sep 01 20:03:50 2016 +0200
+++ b/DebugClients/Python3/AsyncFile.py	Fri Sep 02 19:14:41 2016 +0200
@@ -10,8 +10,6 @@
 
 import socket
 
-from DebugProtocol import EOT
-
 
 def AsyncPendingWrite(file):
     """
@@ -77,7 +75,7 @@
         """
         if n:
             try:
-                buf = "{0!s}{1!s}".format(self.wpending[:n], EOT)
+                buf = self.wpending[:n]
                 try:
                     buf = buf.encode('utf-8', 'backslashreplace')
                 except (UnicodeEncodeError, UnicodeDecodeError):
@@ -295,7 +293,27 @@
         """
         Public method to write a string to the file.
         
-        @param s bytes to be written (string)
+        @param s text to be written (string)
+        """
+        self.__checkMode('w')
+        
+        import json
+        commandDict = {
+            "jsonrpc": "2.0",
+            "method": "ClientOutput",
+            "params": {
+                "text": s,
+            }
+        }
+        cmd = json.dumps(commandDict) + '\n'
+        
+        self.write_p(cmd)
+    
+    def write_p(self, s):
+        """
+        Public method to write a string to the file.
+        
+        @param s text to be written (string)
         @exception socket.error raised to indicate too many send attempts
         """
         self.__checkMode('w')
@@ -317,14 +335,13 @@
             self.wpending += s
         self.__nWrite(self.pendingWrite())
 
-    def writelines(self, list):
+    def writelines(self, lines):
         """
         Public method to write a list of strings to the file.
         
-        @param list the list to be written (list of string)
+        @param lines list of texts to be written (list of string)
         """
-        for l in list:
-            self.write(l)
+        self.write("".join(lines))
 
 #
 # eflag: noqa = M702
--- a/DebugClients/Python3/AsyncIO.py	Thu Sep 01 20:03:50 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2009 - 2016 Detlev Offenbach <detlev@die-offenbachs.de>
-#
-
-"""
-Module implementing a base class of an asynchronous interface for the debugger.
-"""
-
-
-class AsyncIO(object):
-    """
-    Class implementing asynchronous reading and writing.
-    """
-    def __init__(self):
-        """
-        Constructor
-        """
-        # There is no connection yet.
-        self.disconnect()
-
-    def disconnect(self):
-        """
-        Public method to disconnect any current connection.
-        """
-        self.readfd = None
-        self.writefd = None
-
-    def setDescriptors(self, rfd, wfd):
-        """
-        Public method called to set the descriptors for the connection.
-        
-        @param rfd file descriptor of the input file (int)
-        @param wfd file descriptor of the output file (int)
-        """
-        self.rbuf = ''
-        self.readfd = rfd
-
-        self.wbuf = ''
-        self.writefd = wfd
-
-    def readReady(self, fd):
-        """
-        Public method called when there is data ready to be read.
-        
-        @param fd file descriptor of the file that has data to be read (int)
-        """
-        try:
-            got = self.readfd.readline_p()
-        except Exception:
-            return
-
-        if len(got) == 0:
-            self.sessionClose()
-            return
-
-        self.rbuf = self.rbuf + got
-
-        # Call handleLine for the line if it is complete.
-        eol = self.rbuf.find('\n')
-
-        while eol >= 0:
-            s = self.rbuf[:eol + 1]
-            self.rbuf = self.rbuf[eol + 1:]
-            self.handleLine(s)
-            eol = self.rbuf.find('\n')
-
-    def writeReady(self, fd):
-        """
-        Public method called when we are ready to write data.
-        
-        @param fd file descriptor of the file that has data to be written (int)
-        """
-        self.writefd.write(self.wbuf)
-        self.writefd.flush()
-        self.wbuf = ''
-
-    def write(self, s):
-        """
-        Public method to write a string.
-        
-        @param s the data to be written (string)
-        """
-        self.wbuf = self.wbuf + s
-
-#
-# eflag: noqa = M702
--- a/DebugClients/Python3/DCTestResult.py	Thu Sep 01 20:03:50 2016 +0200
+++ b/DebugClients/Python3/DCTestResult.py	Fri Sep 02 19:14:41 2016 +0200
@@ -11,9 +11,9 @@
 from unittest import TestResult
 
 
-from DebugProtocol import ResponseUTTestFailed, ResponseUTTestErrored, \
-    ResponseUTStartTest, ResponseUTStopTest, ResponseUTTestSkipped, \
-    ResponseUTTestFailedExpected, ResponseUTTestSucceededUnexpected
+##from DebugProtocol import ResponseUTTestFailed, ResponseUTTestErrored, \
+##    ResponseUTStartTest, ResponseUTStopTest, ResponseUTTestSkipped, \
+##    ResponseUTTestFailedExpected, ResponseUTTestSucceededUnexpected
 
 
 class DCTestResult(TestResult):
@@ -22,14 +22,15 @@
     
     For more details see unittest.py of the standard python distribution.
     """
-    def __init__(self, parent):
+    def __init__(self, dbgClient):
         """
         Constructor
         
-        @param parent The parent widget.
+        @param dbgClient reference to the debug client
+        @type DebugClientBase
         """
         TestResult.__init__(self)
-        self.parent = parent
+        self.__dbgClient = dbgClient
         
     def addFailure(self, test, err):
         """
@@ -40,9 +41,14 @@
         """
         TestResult.addFailure(self, test, err)
         tracebackLines = self._exc_info_to_string(err, test)
-        self.parent.write('{0}{1}\n'.format(
-            ResponseUTTestFailed,
-            str((str(test), tracebackLines, test.id()))))
+##        self.parent.write('{0}{1}\n'.format(
+##            ResponseUTTestFailed,
+##            str((str(test), tracebackLines, test.id()))))
+        self.__dbgClient.sendJsonCommand("ResponseUTTestFailed", {
+            "testname": str(test),
+            "traceback": tracebackLines,
+            "id": test.id(),
+        })
         
     def addError(self, test, err):
         """
@@ -53,9 +59,14 @@
         """
         TestResult.addError(self, test, err)
         tracebackLines = self._exc_info_to_string(err, test)
-        self.parent.write('{0}{1}\n'.format(
-            ResponseUTTestErrored,
-            str((str(test), tracebackLines, test.id()))))
+##        self.parent.write('{0}{1}\n'.format(
+##            ResponseUTTestErrored,
+##            str((str(test), tracebackLines, test.id()))))
+        self.__dbgClient.sendJsonCommand("ResponseUTTestErrored", {
+            "testname": str(test),
+            "traceback": tracebackLines,
+            "id": test.id(),
+        })
         
     def addSkip(self, test, reason):
         """
@@ -65,9 +76,14 @@
         @param reason reason for skipping the test (string)
         """
         TestResult.addSkip(self, test, reason)
-        self.parent.write('{0}{1}\n'.format(
-            ResponseUTTestSkipped,
-            str((str(test), reason, test.id()))))
+##        self.parent.write('{0}{1}\n'.format(
+##            ResponseUTTestSkipped,
+##            str((str(test), reason, test.id()))))
+        self.__dbgClient.sendJsonCommand("ResponseUTTestSkipped", {
+            "testname": str(test),
+            "reason": reason,
+            "id": test.id(),
+        })
         
     def addExpectedFailure(self, test, err):
         """
@@ -78,9 +94,14 @@
         """
         TestResult.addExpectedFailure(self, test, err)
         tracebackLines = self._exc_info_to_string(err, test)
-        self.parent.write('{0}{1}\n'.format(
-            ResponseUTTestFailedExpected,
-            str((str(test), tracebackLines, test.id()))))
+##        self.parent.write('{0}{1}\n'.format(
+##            ResponseUTTestFailedExpected,
+##            str((str(test), tracebackLines, test.id()))))
+        self.__dbgClient.sendJsonCommand("ResponseUTTestFailedExpected", {
+            "testname": str(test),
+            "traceback": tracebackLines,
+            "id": test.id(),
+        })
         
     def addUnexpectedSuccess(self, test):
         """
@@ -89,9 +110,13 @@
         @param test reference to the test object
         """
         TestResult.addUnexpectedSuccess(self, test)
-        self.parent.write('{0}{1}\n'.format(
-            ResponseUTTestSucceededUnexpected,
-            str((str(test), test.id()))))
+##        self.parent.write('{0}{1}\n'.format(
+##            ResponseUTTestSucceededUnexpected,
+##            str((str(test), test.id()))))
+        self.__dbgClient.sendJsonCommand("ResponseUTTestSucceededUnexpected", {
+            "testname": str(test),
+            "id": test.id(),
+        })
         
     def startTest(self, test):
         """
@@ -100,9 +125,13 @@
         @param test Reference to the test object
         """
         TestResult.startTest(self, test)
-        self.parent.write('{0}{1}\n'.format(
-            ResponseUTStartTest,
-            str((str(test), test.shortDescription()))))
+##        self.parent.write('{0}{1}\n'.format(
+##            ResponseUTStartTest,
+##            str((str(test), test.shortDescription()))))
+        self.__dbgClient.sendJsonCommand("ResponseUTStartTest", {
+            "testname": str(test),
+            "description": test.shortDescription(),
+        })
 
     def stopTest(self, test):
         """
@@ -111,14 +140,15 @@
         @param test Reference to the test object
         """
         TestResult.stopTest(self, test)
-        self.parent.write('{0}\n'.format(ResponseUTStopTest))
+##        self.parent.write('{0}\n'.format(ResponseUTStopTest))
+        self.__dbgClient.sendJsonCommand("ResponseUTStopTest", {})
         
         # ensure that pending input is processed
         rrdy, wrdy, xrdy = select.select(
-            [self.parent.readstream], [], [], 0.01)
+            [self.__dbgClient.readstream], [], [], 0.01)
 
-        if self.parent.readstream in rrdy:
-            self.parent.readReady(self.parent.readstream.fileno())
+        if self.__dbgClient.readstream in rrdy:
+            self.__dbgClient.readReady(self.__dbgClient.readstream.fileno())
 
 #
 # eflag: noqa = M702
--- a/DebugClients/Python3/DebugBase.py	Thu Sep 01 20:03:50 2016 +0200
+++ b/DebugClients/Python3/DebugBase.py	Fri Sep 02 19:14:41 2016 +0200
@@ -246,7 +246,8 @@
             return self.trace_dispatch
         if event == 'c_return':
             return self.trace_dispatch
-        print('DebugBase.trace_dispatch: unknown debugging event: ',       # __IGNORE_WARNING__
+        print('DebugBase.trace_dispatch:'       # __IGNORE_WARNING__
+              ' unknown debugging event: ',
               repr(event))
         return self.trace_dispatch
 
@@ -707,16 +708,17 @@
             atexit._run_exitfuncs()
             if excval is None:
                 excval = 0
+                message = ""
             elif isinstance(excval, str):
-                self._dbgClient.write(excval)
                 excval = 1
+                message = excval
             elif isinstance(excval, bytes):
-                self._dbgClient.write(excval.decode())
                 excval = 1
+                message = excval.decode()
             if isinstance(excval, int):
-                self._dbgClient.progTerminated(excval)
+                self._dbgClient.progTerminated(excval, message)
             else:
-                self._dbgClient.progTerminated(excval.code)
+                self._dbgClient.progTerminated(excval.code, "")
             return
         
         if exctype in [SyntaxError, IndentationError]:
@@ -869,12 +871,13 @@
         #debugging the debugger - when the debugger code is in the current
         #directory.
         if os.path.basename(fn) in [
-            'AsyncFile.py', 'AsyncIO.py',
-            'DebugConfig.py', 'DCTestResult.py',
-            'DebugBase.py', 'DebugClientBase.py',
-            'DebugClientCapabilities.py', 'DebugClient.py',
-            'DebugClientThreads.py', 'DebugProtocol.py',
-            'DebugThread.py', 'FlexCompleter.py',
+            'AsyncFile.py', 'DCTestResult.py',
+            'DebugBase.py', 'DebugClient.py',
+            'DebugClientBase.py',
+            'DebugClientCapabilities.py',
+            'DebugClientThreads.py',
+            'DebugConfig.py', 'DebugThread.py',
+            'DebugUtilities.py', 'FlexCompleter.py',
             'PyProfile.py'] or \
            os.path.dirname(fn).endswith("coverage"):
             return True
--- a/DebugClients/Python3/DebugClient.py	Thu Sep 01 20:03:50 2016 +0200
+++ b/DebugClients/Python3/DebugClient.py	Fri Sep 02 19:14:41 2016 +0200
@@ -7,12 +7,11 @@
 Module implementing a non-threaded variant of the debug client.
 """
 
-from AsyncIO import AsyncIO
 from DebugBase import DebugBase
 import DebugClientBase
 
 
-class DebugClient(DebugClientBase.DebugClientBase, AsyncIO, DebugBase):
+class DebugClient(DebugClientBase.DebugClientBase, DebugBase):
     """
     Class implementing the client side of the debugger.
     
@@ -23,8 +22,6 @@
         """
         Constructor
         """
-        AsyncIO.__init__(self)
-        
         DebugClientBase.DebugClientBase.__init__(self)
         
         DebugBase.__init__(self, self)
--- a/DebugClients/Python3/DebugClientBase.py	Thu Sep 01 20:03:50 2016 +0200
+++ b/DebugClients/Python3/DebugClientBase.py	Fri Sep 02 19:14:41 2016 +0200
@@ -20,7 +20,7 @@
 import signal
 
 
-import DebugProtocol
+##import DebugProtocol
 import DebugClientCapabilities
 from DebugBase import setRecursionLimit, printerr   # __IGNORE_WARNING__
 from AsyncFile import AsyncFile, AsyncPendingWrite
@@ -160,6 +160,7 @@
         """
         self.breakpoints = {}
         self.redirect = True
+        self.__receiveBuffer = ""
 
         # The next couple of members are needed for the threaded version.
         # For this base class they contain static values for the non threaded
@@ -188,7 +189,7 @@
         self.globalsFilterObjects = []
         self.localsFilterObjects = []
 
-        self.pendingResponse = DebugProtocol.ResponseOK
+##        self.pendingResponse = DebugProtocol.ResponseOK
         self._fncache = {}
         self.dircache = []
 ##        self.inRawMode = False
@@ -304,7 +305,7 @@
         
 ##        self.write("{0}{1!r}\n".format(DebugProtocol.ResponseThreadList,
 ##                                       (currentId, threadList)))
-        self.__sendJsonCommand("ResponseThreadList", {
+        self.sendJsonCommand("ResponseThreadList", {
             "currentID": currentId,
             "threadList": threadList,
         })
@@ -319,7 +320,7 @@
         """
 ##        self.write("{0}{1!r}\n".format(
 ##            DebugProtocol.ResponseRaw, (prompt, echo)))
-        self.__sendJsonCommand("RequestRaw", {
+        self.sendJsonCommand("RequestRaw", {
             "prompt": prompt,
             "echo": echo,
         })
@@ -327,15 +328,15 @@
         self.eventLoop(True)
         return self.rawLine
 
-    def __exceptionRaised(self):
-        """
-        Private method called in the case of an exception.
-        
-        It ensures that the debug server is informed of the raised exception.
-        """
-##        self.pendingResponse = DebugProtocol.ResponseException
-        self.__sendJsonCommand("ResponseException", {})
-    
+##    def __exceptionRaised(self):
+##        """
+##        Private method called in the case of an exception.
+##        
+##        It ensures that the debug server is informed of the raised exception.
+##        """
+####        self.pendingResponse = DebugProtocol.ResponseException
+##        self.sendJsonCommand("ResponseException", {})
+##    
     def sessionClose(self, exit=True):
         """
         Public method to close the session with the debugger and optionally
@@ -348,8 +349,8 @@
         except Exception:
             pass
 
-        # clean up asyncio.
-        self.disconnect()
+##        # clean up asyncio.
+##        self.disconnect()
         self.debugging = False
         
         # make sure we close down our end of the socket
@@ -408,16 +409,16 @@
 
 ##        printerr(line)          ##debug
         
-        if "jsonrpc" in line:
+        if line.startswith("{") and "jsonrpc" in line:
             return self.handleJsonCommand(line)
-
-        eoc = line.find('<')
-
-        if eoc >= 0 and line[0] == '>':
-            # Get the command part and any argument.
-            cmd = line[:eoc + 1]
-            arg = line[eoc + 1:]
-            
+##
+##        eoc = line.find('<')
+##
+##        if eoc >= 0 and line[0] == '>':
+##            # Get the command part and any argument.
+##            cmd = line[:eoc + 1]
+##            arg = line[eoc + 1:]
+##            
 ##            if cmd == DebugProtocol.RequestVariables:
 ##                frmnr, scope, filter = eval(arg.replace("u'", "'"))
 ##                self.__dumpVariables(int(frmnr), int(scope), filter)
@@ -912,32 +913,32 @@
 ##                    str((self.test.countTestCases(), "", ""))))
 ##                return
 ##            
-            if cmd == DebugProtocol.RequestUTRun:
-                from DCTestResult import DCTestResult
-                self.testResult = DCTestResult(self)
-                if self.cover:
-                    self.cover.start()
-                self.test.run(self.testResult)
-                if self.cover:
-                    self.cover.stop()
-                    self.cover.save()
-                self.write('{0}\n'.format(DebugProtocol.ResponseUTFinished))
-                return
-            
-            if cmd == DebugProtocol.RequestUTStop:
-                self.testResult.stop()
-                return
-        
-            if cmd == DebugProtocol.ResponseForkTo:
-                # this results from a separate event loop
-                self.fork_child = (arg == 'child')
-                self.eventExit = True
-                return
-            
-            if cmd == DebugProtocol.RequestForkMode:
-                self.fork_auto, self.fork_child = eval(arg)
-                return
-        
+##            if cmd == DebugProtocol.RequestUTRun:
+##                from DCTestResult import DCTestResult
+##                self.testResult = DCTestResult(self)
+##                if self.cover:
+##                    self.cover.start()
+##                self.test.run(self.testResult)
+##                if self.cover:
+##                    self.cover.stop()
+##                    self.cover.save()
+##                self.write('{0}\n'.format(DebugProtocol.ResponseUTFinished))
+##                return
+##            
+##            if cmd == DebugProtocol.RequestUTStop:
+##                self.testResult.stop()
+##                return
+##        
+##            if cmd == DebugProtocol.ResponseForkTo:
+##                # this results from a separate event loop
+##                self.fork_child = (arg == 'child')
+##                self.eventExit = True
+##                return
+##            
+##            if cmd == DebugProtocol.RequestForkMode:
+##                self.fork_auto, self.fork_child = eval(arg)
+##                return
+##        
 ##        # If we are handling raw mode input then reset the mode and break out
 ##        # of the current event loop.
 ##        if self.inRawMode:
@@ -1046,56 +1047,48 @@
         if method == "RequestVariables":
             self.__dumpVariables(
                 params["frameNumber"], params["scope"], params["filters"])
-            return
         
-        if method == "RequestVariable":
+        elif method == "RequestVariable":
             self.__dumpVariable(
                 params["variable"], params["frameNumber"],
                 params["scope"], params["filters"])
-            return
         
-        if method == "RequestThreadList":
+        elif method == "RequestThreadList":
             self.__dumpThreadList()
-            return
         
-        if method == "RequestThreadSet":
+        elif method == "RequestThreadSet":
             if params["threadID"] in self.threads:
                 self.setCurrentThread(params["threadID"])
-                self.__sendJsonCommand("ResponseThreadSet", {})
+                self.sendJsonCommand("ResponseThreadSet", {})
                 stack = self.currentThread.getStack()
-                self.__sendJsonCommand("ResponseStack", {
+                self.sendJsonCommand("ResponseStack", {
                     "stack": stack,
                 })
-            return
         
-        if method == "RequestCapabilities":
-            self.__sendJsonCommand("ResponseCapabilities", {
+        elif method == "RequestCapabilities":
+            self.sendJsonCommand("ResponseCapabilities", {
                 "capabilities": self.__clientCapabilities(),
                 "clientType": "Python3"
             })
-            return
         
-        if method == "RequestBanner":
-            self.__sendJsonCommand("ResponseBanner", {
+        elif method == "RequestBanner":
+            self.sendJsonCommand("ResponseBanner", {
                 "version": "Python {0}".format(sys.version),
                 "platform": socket.gethostname(),
                 "dbgclient": self.variant,
             })
-            return
         
-        if method == "RequestSetFilter":
+        elif method == "RequestSetFilter":
             self.__generateFilterObjects(params["scope"], params["filter"])
-            return
         
-        if method == "RequestCallTrace":
+        elif method == "RequestCallTrace":
             if self.debugging:
                 self.callTraceEnabled = params["enable"]
             else:
                 self.__newCallTraceEnabled = params["enable"]
                 # remember for later
-            return
         
-        if method == "RequestEnvironment":
+        elif method == "RequestEnvironment":
             for key, value in params["environment"].items():
                 if key.endswith("+"):
                     if key[:-1] in os.environ:
@@ -1104,9 +1097,8 @@
                         os.environ[key[:-1]] = value
                 else:
                     os.environ[key] = value
-            return
         
-        if method == "RequestLoad":
+        elif method == "RequestLoad":
             self._fncache = {}
             self.dircache = []
             sys.argv = []
@@ -1149,9 +1141,8 @@
                 self.callTraceEnabled = self.__newCallTraceEnabled
                 res = self.mainThread.run(code, self.debugMod.__dict__)
                 self.progTerminated(res)
-            return
 
-        if method == "RequestRun":
+        elif method == "RequestRun":
             sys.argv = []
             self.__setCoding(params["filename"])
             sys.argv.append(params["filename"])
@@ -1192,9 +1183,8 @@
                     atexit._run_exitfuncs()
                 self.writestream.flush()
                 self.progTerminated(res)
-            return
 
-        if method == "RequestCoverage":
+        elif method == "RequestCoverage":
             from coverage import coverage
             sys.argv = []
             self.__setCoding(params["filename"])
@@ -1242,9 +1232,8 @@
                 self.cover.save()
                 self.writestream.flush()
                 self.progTerminated(res)
-            return
         
-        if method == "RequestProfile":
+        elif method == "RequestProfile":
             sys.setprofile(None)
             import PyProfile
             sys.argv = []
@@ -1287,9 +1276,8 @@
                 self.prof.save()
                 self.writestream.flush()
                 self.progTerminated(res)
-            return
         
-        if method == "ExecuteStatement":
+        elif method == "ExecuteStatement":
             if self.buffer:
                 self.buffer = self.buffer + '\n' + params["statement"]
             else:
@@ -1301,13 +1289,17 @@
                 # Report the exception
                 sys.last_type, sys.last_value, sys.last_traceback = \
                     sys.exc_info()
-                for l in traceback.format_exception_only(
-                        sys.last_type, sys.last_value):
-                    self.write(l)
+##                for l in traceback.format_exception_only(
+##                        sys.last_type, sys.last_value):
+##                    self.write(l)
+                self.sendJsonCommand("ClientOutput", {
+                    "text": "".join(traceback.format_exception_only(
+                        sys.last_type, sys.last_value))
+                })
                 self.buffer = ''
             else:
                 if code is None:
-                    self.__sendJsonCommand("ResponseContinue", {})
+                    self.sendJsonCommand("ResponseContinue", {})
                     return
                 else:
                     self.buffer = ''
@@ -1357,6 +1349,7 @@
                         self.progTerminated(exc.code)
                     except Exception:
                         # Report the exception and the traceback
+                        tlist = []
                         try:
                             exc_type, exc_value, exc_tb = sys.exc_info()
                             sys.last_type = exc_type
@@ -1364,57 +1357,54 @@
                             sys.last_traceback = exc_tb
                             tblist = traceback.extract_tb(exc_tb)
                             del tblist[:1]
-                            list = traceback.format_list(tblist)
-                            if list:
-                                list.insert(0, "Traceback (innermost last):\n")
-                                list[len(list):] = \
+                            tlist = traceback.format_list(tblist)
+                            if tlist:
+                                tlist.insert(
+                                    0, "Traceback (innermost last):\n")
+                                tlist[len(tlist):] = \
                                     traceback.format_exception_only(
                                         exc_type, exc_value)
                         finally:
                             tblist = exc_tb = None
 
-                        for l in list:
-                            self.write(l)
+##                        for l in list:
+##                            self.write(l)
+                        self.sendJsonCommand("ClientOutput", {
+                            "text": "".join(tlist)
+                        })
             
-            self.__sendJsonCommand("ResponseOK", {})
-            return
+            self.sendJsonCommand("ResponseOK", {})
         
-        if method == "RequestStep":
+        elif method == "RequestStep":
             self.currentThread.step(True)
             self.eventExit = True
-            return
 
-        if method == "RequestStepOver":
+        elif method == "RequestStepOver":
             self.currentThread.step(False)
             self.eventExit = True
-            return
         
-        if method == "RequestStepOut":
+        elif method == "RequestStepOut":
             self.currentThread.stepOut()
             self.eventExit = True
-            return
         
-        if method == "RequestStepQuit":
+        elif method == "RequestStepQuit":
             if self.passive:
                 self.progTerminated(42)
             else:
                 self.set_quit()
                 self.eventExit = True
-            return
         
-        if method == "RequestContinue":
+        elif method == "RequestContinue":
             self.currentThread.go(params["special"])
             self.eventExit = True
-            return
         
-        if method == "RawInput":
+        elif method == "RawInput":
             # If we are handling raw mode input then break out of the current
             # event loop.
             self.rawLine = params["input"]
             self.eventExit = True
-            return
         
-        if method == "RequestBreakpoint":
+        elif method == "RequestBreakpoint":
             if params["setBreakpoint"]:
                 if params["condition"] in ['None', '']:
                     params["condition"] = None
@@ -1422,7 +1412,7 @@
                     try:
                         compile(params["condition"], '<string>', 'eval')
                     except SyntaxError:
-                        self.__sendJsonCommand("ResponseBPConditionError", {
+                        self.sendJsonCommand("ResponseBPConditionError", {
                             "filename": params["filename"],
                             "line": params["line"],
                         })
@@ -1432,32 +1422,28 @@
                     params["condition"])
             else:
                 self.mainThread.clear_break(params["filename"], params["line"])
-
-            return
         
-        if method == "RequestBreakpointEnable":
+        elif method == "RequestBreakpointEnable":
             bp = self.mainThread.get_break(params["filename"], params["line"])
             if bp is not None:
                 if params["enable"]:
                     bp.enable()
                 else:
                     bp.disable()
-            return
         
-        if method == "RequestBreakpointIgnore":
+        elif method == "RequestBreakpointIgnore":
             bp = self.mainThread.get_break(params["filename"], params["line"])
             if bp is not None:
                 bp.ignore = params["count"]
-            return
         
-        if method == "RequestWatch":
+        elif method == "RequestWatch":
             if params["setWatch"]:
                 if not params["condition"].endswith(
                         ('??created??', '??changed??')):
                     try:
                         compile(params["condition"], '<string>', 'eval')
                     except SyntaxError:
-                        self.__sendJsonCommand("ResponseWatchConditionError", {
+                        self.sendJsonCommand("ResponseWatchConditionError", {
                             "condition": params["condition"],
                         })
                         return
@@ -1465,37 +1451,28 @@
                     params["condition"], params["temporary"])
             else:
                 self.mainThread.clear_watch(params["condition"])
-            return
         
-        if method == "RequestWatchEnable":
+        elif method == "RequestWatchEnable":
             wp = self.mainThread.get_watch(params["condition"])
             if wp is not None:
                 if params["enable"]:
                     wp.enable()
                 else:
                     wp.disable()
-            return
         
-        if method == "RequestWatchIgnore":
+        elif method == "RequestWatchIgnore":
             wp = self.mainThread.get_watch(params["condition"])
             if wp is not None:
                 wp.ignore = params["count"]
             return
         
-        if method == "RequestShutdown":
+        elif method == "RequestShutdown":
             self.sessionClose()
-            return
         
-        if method == "RequestCompletion":
+        elif method == "RequestCompletion":
             self.__completionList(params["text"])
-            return
         
-        if method == "RequestUTPrepare":
-##            fn, tn, tfn, failed, cov, covname, erase = arg.split('|')
-##            sys.path.insert(0, os.path.dirname(os.path.abspath(fn)))
-##            os.chdir(sys.path[0])
-##            failed = eval(failed)
-##
+        elif method == "RequestUTPrepare":
             # set the system exception handling function to ensure, that
             # we report on all unhandled exceptions
             sys.excepthook = self.__unhandled_exception
@@ -1518,15 +1495,12 @@
                         .loadTestsFromModule(utModule)
             except Exception:
                 exc_type, exc_value, exc_tb = sys.exc_info()
-##                self.write('{0}{1}\n'.format(
-##                    DebugProtocol.ResponseUTPrepared,
-##                    str((0, str(exc_type), str(exc_value)))))
-                self.__sendJsonCommand("ResponseUTPrepared", {
+                self.sendJsonCommand("ResponseUTPrepared", {
                     "count": 0,
                     "exception": exc_type.__name__,
                     "message": str(exc_value),
                 })
-                self.__exceptionRaised()
+##                self.__exceptionRaised()
                 return
             
             # generate a coverage object
@@ -1541,19 +1515,34 @@
             else:
                 self.cover = None
             
-##            self.write('{0}{1}\n'.format(
-##                DebugProtocol.ResponseUTPrepared,
-##                str((self.test.countTestCases(), "", ""))))
-            self.__sendJsonCommand("ResponseUTPrepared", {
+            self.sendJsonCommand("ResponseUTPrepared", {
                 "count": self.test.countTestCases(),
                 "exception": "",
                 "message": "",
             })
-            return
+        
+        elif method == "RequestUTRun":
+            from DCTestResult import DCTestResult
+            self.testResult = DCTestResult(self)
+            if self.cover:
+                self.cover.start()
+            self.test.run(self.testResult)
+            if self.cover:
+                self.cover.stop()
+                self.cover.save()
+            self.sendJsonCommand("ResponseUTFinished", {})
+        
+        elif method == "RequestUTStop":
+            self.testResult.stop()
+        
+        elif method == "ResponseForkTo":
+            # this results from a separate event loop
+            self.fork_child = (params["target"] == 'child')
+            self.eventExit = True
     
-    def __sendJsonCommand(self, command, params):
+    def sendJsonCommand(self, command, params):
         """
-        Private method to send a single command to the client.
+        Public method to send a single command to the client.
         
         @param command command name to be sent
         @type str
@@ -1568,7 +1557,9 @@
             "params": params,
         }
         cmd = json.dumps(commandDict) + '\n'
-        self.write(cmd)
+        
+        self.writestream.write_p(cmd)
+        self.writestream.flush()
     
     def sendClearTemporaryBreakpoint(self, filename, lineno):
         """
@@ -1579,7 +1570,7 @@
         @param lineno linenumber of the bp
         @type int
         """
-        self.__sendJsonCommand("ResponseClearBreakpoint", {
+        self.sendJsonCommand("ResponseClearBreakpoint", {
             "filename": filename,
             "line": lineno
         })
@@ -1591,7 +1582,7 @@
         @param condition condition of the watch expression to be cleared
         @type str
         """
-        self.__sendJsonCommand("ResponseClearWatch", {
+        self.sendJsonCommand("ResponseClearWatch", {
             "condition": condition,
         })
     
@@ -1602,7 +1593,7 @@
         @param stack call stack
         @type list
         """
-        self.__sendJsonCommand("ResponseLine", {
+        self.sendJsonCommand("ResponseLine", {
             "stack": stack,
         })
     
@@ -1617,7 +1608,7 @@
         @param toStr pre-formatted target info
         @type str
         """
-        self.__sendJsonCommand("CallTrace", {
+        self.sendJsonCommand("CallTrace", {
             "event": event[0],
             "from": fromStr,
             "to": toStr,
@@ -1634,7 +1625,7 @@
         @param stack stack trace information
         @param list
         """
-        self.__sendJsonCommand("ResponseException", {
+        self.sendJsonCommand("ResponseException", {
             "type": exceptionType,
             "message": exceptionMessage,
             "stack": stack,
@@ -1653,7 +1644,7 @@
         @param charno character number info
         @tyoe int
         """
-        self.__sendJsonCommand("ResponseSyntax", {
+        self.sendJsonCommand("ResponseSyntax", {
             "message": message,
             "filename": filename,
             "linenumber": lineno,
@@ -1669,7 +1660,7 @@
         @param exceptions flag to enable exception reporting of the IDE
         @type bool
         """
-        self.__sendJsonCommand("PassiveStartup", {
+        self.sendJsonCommand("PassiveStartup", {
             "filename": filename,
             "exceptions": exceptions,
         })
@@ -1691,23 +1682,58 @@
             return (
                 self.clientCapabilities & ~DebugClientCapabilities.HasProfiler)
     
-    def write(self, s):
+##    def write(self, s):
+##        """
+##        Public method to write data to the output stream.
+##        
+##        @param s data to be written (string)
+##        """
+##        self.writestream.write_p(s)
+##        self.writestream.flush()
+##
+    def readReady(self, stream):
         """
-        Public method to write data to the output stream.
+        Public method called when there is data ready to be read.
         
-        @param s data to be written (string)
+        @param fd file descriptor of the file that has data to be read (int)
         """
-        self.writestream.write(s)
-        self.writestream.flush()
+        try:
+            got = stream.readline_p()
+        except Exception:
+            return
+
+        if len(got) == 0:
+            self.sessionClose()
+            return
+
+        self.__receiveBuffer = self.__receiveBuffer + got
 
+        # Call handleLine for the line if it is complete.
+        eol = self.__receiveBuffer.find('\n')
+        while eol >= 0:
+            line = self.__receiveBuffer[:eol + 1]
+            self.__receiveBuffer = self.__receiveBuffer[eol + 1:]
+            self.handleLine(line)
+            eol = self.__receiveBuffer.find('\n')
+
+    def writeReady(self, stream):
+        """
+        Public method called when we are ready to write data.
+        
+        @param fd file descriptor of the file that has data to be written (int)
+        """
+        stream.write_p("")
+        stream.flush()
+    
     def __interact(self):
         """
         Private method to interact with the debugger.
         """
         global DebugClientInstance
 
-        self.setDescriptors(self.readstream, self.writestream)
+##        self.setDescriptors(self.readstream, self.writestream)
         DebugClientInstance = self
+        self.__receiveBuffer = ""
 
         if not self.passive:
             # At this point simulate an event loop.
@@ -1742,13 +1768,13 @@
                 continue
 
             if self.readstream in rrdy:
-                self.readReady(self.readstream.fileno())
+                self.readReady(self.readstream)
 
             if self.writestream in wrdy:
-                self.writeReady(self.writestream.fileno())
+                self.writeReady(self.writestream)
 
             if self.errorstream in wrdy:
-                self.writeReady(self.errorstream.fileno())
+                self.writeReady(self.errorstream)
 
         self.eventExit = None
         self.pollingDisabled = False
@@ -1786,10 +1812,10 @@
             self.readReady(self.readstream.fileno())
 
         if self.writestream in wrdy:
-            self.writeReady(self.writestream.fileno())
+            self.writeReady(self.writestream)
 
         if self.errorstream in wrdy:
-            self.writeReady(self.errorstream.fileno())
+            self.writeReady(self.errorstream)
     
     def connectDebugger(self, port, remoteAddress=None, redirect=True):
         """
@@ -1888,7 +1914,7 @@
 ##        siglist = [message, [filename, linenr, ffunc, fargs]]
 ##        
 ##        self.write("{0}{1}".format(DebugProtocol.ResponseSignal, str(siglist)))
-        self.__sendJsonCommand("ResponseSignal", {
+        self.sendJsonCommand("ResponseSignal", {
             "message": message,
             "filename": filename, 
             "linenumber": linenr, 
@@ -1969,12 +1995,14 @@
         """
         return self.running
 
-    def progTerminated(self, status):
+    def progTerminated(self, status, message=""):
         """
         Public method to tell the debugger that the program has terminated.
         
         @param status return status
         @type int
+        @param message status message
+        @type str
         """
         if status is None:
             status = 0
@@ -1988,8 +2016,9 @@
             self.set_quit()
             self.running = None
 ##            self.write('{0}{1:d}\n'.format(DebugProtocol.ResponseExit, status))
-            self.__sendJsonCommand("ResponseExit", {
+            self.sendJsonCommand("ResponseExit", {
                 "status": status,
+                "message": message,
             })
         
         # reset coding
@@ -2039,7 +2068,7 @@
         
 ##        self.write('{0}{1}\n'.format(
 ##            DebugProtocol.ResponseVariables, str(varlist)))
-        self.__sendJsonCommand("ResponseVariables", {
+        self.sendJsonCommand("ResponseVariables", {
             "scope": scope,
             "variables": varlist,
         })
@@ -2328,7 +2357,7 @@
         
 ##        self.write('{0}{1}\n'.format(
 ##            DebugProtocol.ResponseVariable, str(varlist)))
-        self.__sendJsonCommand("ResponseVariable", {
+        self.sendJsonCommand("ResponseVariable", {
             "scope": scope,
             "variable": var,
             "variables": varlist,
@@ -2630,7 +2659,7 @@
         
 ##        self.write("{0}{1}||{2}\n".format(DebugProtocol.ResponseCompletion,
 ##                                          str(list(completions)), text))
-        self.__sendJsonCommand("ResponseCompletion", {
+        self.sendJsonCommand("ResponseCompletion", {
             "completions": list(completions),
             "text": text, 
         })
@@ -2914,7 +2943,8 @@
         @return process ID (integer)
         """
         if not self.fork_auto:
-            self.write(DebugProtocol.RequestForkTo + '\n')
+##            self.write(DebugProtocol.RequestForkTo + '\n')
+            self.sendJsonCommand("RequestForkTo", {})
             self.eventLoop(True)
         pid = DebugClientOrigFork()
         if pid == 0:
--- a/DebugClients/Python3/DebugClientThreads.py	Thu Sep 01 20:03:50 2016 +0200
+++ b/DebugClients/Python3/DebugClientThreads.py	Fri Sep 02 19:14:41 2016 +0200
@@ -10,7 +10,6 @@
 import _thread
 import sys
 
-from AsyncIO import AsyncIO
 from DebugThread import DebugThread
 import DebugClientBase
 
@@ -49,7 +48,7 @@
 from threading import RLock
 
 
-class DebugClientThreads(DebugClientBase.DebugClientBase, AsyncIO):
+class DebugClientThreads(DebugClientBase.DebugClientBase):
     """
     Class implementing the client side of the debugger.
 
@@ -60,8 +59,6 @@
         """
         Constructor
         """
-        AsyncIO.__init__(self)
-        
         DebugClientBase.DebugClientBase.__init__(self)
         
         # protection lock for synchronization
--- a/DebugClients/Python3/DebugProtocol.py	Thu Sep 01 20:03:50 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2009 - 2016 Detlev Offenbach <detlev@die-offenbachs.de>
-#
-
-"""
-Module defining the debug protocol tokens.
-"""
-
-# The address used for debugger/client communications.
-DebugAddress = '127.0.0.1'
-
-# The protocol "words".
-RequestOK = '>OK?<'
-RequestEnv = '>Environment<'
-RequestCapabilities = '>Capabilities<'
-RequestLoad = '>Load<'
-RequestRun = '>Run<'
-RequestCoverage = '>Coverage<'
-RequestProfile = '>Profile<'
-RequestContinue = '>Continue<'
-RequestStep = '>Step<'
-RequestStepOver = '>StepOver<'
-RequestStepOut = '>StepOut<'
-RequestStepQuit = '>StepQuit<'
-RequestBreak = '>Break<'
-RequestBreakEnable = '>EnableBreak<'
-RequestBreakIgnore = '>IgnoreBreak<'
-RequestWatch = '>Watch<'
-RequestWatchEnable = '>EnableWatch<'
-RequestWatchIgnore = '>IgnoreWatch<'
-RequestVariables = '>Variables<'
-RequestVariable = '>Variable<'
-RequestSetFilter = '>SetFilter<'
-RequestThreadList = '>ThreadList<'
-RequestThreadSet = '>ThreadSet<'
-RequestEval = '>Eval<'
-RequestExec = '>Exec<'
-RequestShutdown = '>Shutdown<'
-RequestBanner = '>Banner<'
-RequestCompletion = '>Completion<'
-RequestUTPrepare = '>UTPrepare<'
-RequestUTRun = '>UTRun<'
-RequestUTStop = '>UTStop<'
-RequestForkTo = '>ForkTo<'
-RequestForkMode = '>ForkMode<'
-
-ResponseOK = '>OK<'
-ResponseCapabilities = RequestCapabilities
-ResponseContinue = '>Continue<'
-ResponseException = '>Exception<'
-ResponseSyntax = '>SyntaxError<'
-ResponseSignal = '>Signal<'
-ResponseExit = '>Exit<'
-ResponseLine = '>Line<'
-ResponseRaw = '>Raw<'
-ResponseClearBreak = '>ClearBreak<'
-ResponseBPConditionError = '>BPConditionError<'
-ResponseClearWatch = '>ClearWatch<'
-ResponseWPConditionError = '>WPConditionError<'
-ResponseVariables = RequestVariables
-ResponseVariable = RequestVariable
-ResponseThreadList = RequestThreadList
-ResponseThreadSet = RequestThreadSet
-ResponseStack = '>CurrentStack<'
-ResponseBanner = RequestBanner
-ResponseCompletion = RequestCompletion
-ResponseUTPrepared = '>UTPrepared<'
-ResponseUTStartTest = '>UTStartTest<'
-ResponseUTStopTest = '>UTStopTest<'
-ResponseUTTestFailed = '>UTTestFailed<'
-ResponseUTTestErrored = '>UTTestErrored<'
-ResponseUTTestSkipped = '>UTTestSkipped<'
-ResponseUTTestFailedExpected = '>UTTestFailedExpected<'
-ResponseUTTestSucceededUnexpected = '>UTTestSucceededUnexpected<'
-ResponseUTFinished = '>UTFinished<'
-ResponseForkTo = RequestForkTo
-
-PassiveStartup = '>PassiveStartup<'
-
-RequestCallTrace = '>CallTrace<'
-CallTrace = '>CallTrace<'
-
-EOT = '>EOT<\n'
-
-#
-# eflag: noqa = M702
--- a/Debugger/DebuggerInterfacePython3.py	Thu Sep 01 20:03:50 2016 +0200
+++ b/Debugger/DebuggerInterfacePython3.py	Fri Sep 02 19:14:41 2016 +0200
@@ -19,7 +19,7 @@
 from E5Gui.E5Application import e5App
 from E5Gui import E5MessageBox
 
-from . import DebugProtocol
+##from . import DebugProtocol
 from . import DebugClientCapabilities
 
 import Preferences
@@ -29,6 +29,7 @@
 
 
 ClientDefaultCapabilities = DebugClientCapabilities.HasAll
+##EOT = '>EOT<\n'
 
 
 class DebuggerInterfacePython3(QObject):
@@ -884,13 +885,15 @@
         """
         Public method to start a unittest run.
         """
-        self.__sendCommand('{0}\n'.format(DebugProtocol.RequestUTRun))
+##        self.__sendCommand('{0}\n'.format(DebugProtocol.RequestUTRun))
+        self.__sendJsonCommand("RequestUTRun", {})
     
     def remoteUTStop(self):
         """
         Public method to stop a unittest run.
         """
-        self.__sendCommand('{0}\n'.format(DebugProtocol.RequestUTStop))
+##        self.__sendCommand('{0}\n'.format(DebugProtocol.RequestUTStop))
+        self.__sendJsonCommand("RequestUTStop", {})
     
     def __askForkTo(self):
         """
@@ -905,9 +908,15 @@
             selections,
             0, False)
         if not ok or res == selections[0]:
-            self.__sendCommand(DebugProtocol.ResponseForkTo + 'parent\n')
+##            self.__sendCommand(DebugProtocol.ResponseForkTo + 'parent\n')
+            self.__sendJsonCommand("ResponseForkTo", {
+                "target": "parent",
+            })
         else:
-            self.__sendCommand(DebugProtocol.ResponseForkTo + 'child\n')
+##            self.__sendCommand(DebugProtocol.ResponseForkTo + 'child\n')
+            self.__sendJsonCommand("ResponseForkTo", {
+                "target": "child",
+            })
     
     def __parseClientLine(self):
         """
@@ -919,33 +928,34 @@
                 line = self.codec.toUnicode(qs)
             else:
                 line = bytes(qs).decode()
-            if line.endswith(DebugProtocol.EOT):
-                line = line[:-len(DebugProtocol.EOT)]
-                if not line:
-                    continue
+##            if line.endswith(EOT):
+##                line = line[:-len(EOT)]
+##                if not line:
+##                    continue
             
 ##            print("Server: ", line)          ##debug
             
-            if line.startswith("{") and "jsonrpc" in line:
-                self.__handleJsonCommand(line)
-                continue
-            
-            eoc = line.find('<') + 1
-            
-            # Deal with case where user has written directly to stdout
-            # or stderr, but not line terminated and we stepped over the
-            # write call, in that case the >line< will not be the first
-            # string read from the socket...
-            boc = line.find('>')
-            if boc > 0 and eoc > boc:
-                self.debugServer.signalClientOutput(line[:boc])
-                line = line[boc:]
-                eoc = line.find('<') + 1
-                boc = line.find('>')
-            
-            if boc >= 0 and eoc > boc:
-                resp = line[boc:eoc]
-                
+##            if line.startswith("{") and "jsonrpc" in line:
+            self.__handleJsonCommand(line)
+            continue
+##            
+##            eoc = line.find('<') + 1
+##            
+##            # Deal with case where user has written directly to stdout
+##            # or stderr, but not line terminated and we stepped over the
+##            # write call, in that case the >line< will not be the first
+##            # string read from the socket...
+##            boc = line.find('>')
+##            if boc > 0 and eoc > boc:
+##                self.debugServer.signalClientOutput(line[:boc])
+##                line = line[boc:]
+##                eoc = line.find('<') + 1
+##                boc = line.find('>')
+##            
+##            self.debugServer.signalClientOutput(line)
+##            if boc >= 0 and eoc > boc:
+##                resp = line[boc:eoc]
+##                
 ##                if resp == DebugProtocol.ResponseLine or \
 ##                   resp == DebugProtocol.ResponseStack:
 ##                    stack = eval(line[eoc:-1])
@@ -1124,53 +1134,53 @@
 ##                    self.debugServer.clientUtPrepared(res, exc_type, exc_value)
 ##                    continue
 ##                
-                if resp == DebugProtocol.ResponseUTStartTest:
-                    testname, doc = eval(line[eoc:-1])
-                    self.debugServer.clientUtStartTest(testname, doc)
-                    continue
-                
-                if resp == DebugProtocol.ResponseUTStopTest:
-                    self.debugServer.clientUtStopTest()
-                    continue
-                
-                if resp == DebugProtocol.ResponseUTTestFailed:
-                    testname, traceback, id = eval(line[eoc:-1])
-                    self.debugServer.clientUtTestFailed(
-                        testname, traceback, id)
-                    continue
-                
-                if resp == DebugProtocol.ResponseUTTestErrored:
-                    testname, traceback, id = eval(line[eoc:-1])
-                    self.debugServer.clientUtTestErrored(
-                        testname, traceback, id)
-                    continue
-                
-                if resp == DebugProtocol.ResponseUTTestSkipped:
-                    testname, reason, id = eval(line[eoc:-1])
-                    self.debugServer.clientUtTestSkipped(testname, reason, id)
-                    continue
-                
-                if resp == DebugProtocol.ResponseUTTestFailedExpected:
-                    testname, traceback, id = eval(line[eoc:-1])
-                    self.debugServer.clientUtTestFailedExpected(
-                        testname, traceback, id)
-                    continue
-                
-                if resp == DebugProtocol.ResponseUTTestSucceededUnexpected:
-                    testname, id = eval(line[eoc:-1])
-                    self.debugServer.clientUtTestSucceededUnexpected(
-                        testname, id)
-                    continue
-                
-                if resp == DebugProtocol.ResponseUTFinished:
-                    self.debugServer.clientUtFinished()
-                    continue
-                
-                if resp == DebugProtocol.RequestForkTo:
-                    self.__askForkTo()
-                    continue
-            
-            self.debugServer.signalClientOutput(line)
+##                if resp == DebugProtocol.ResponseUTStartTest:
+##                    testname, doc = eval(line[eoc:-1])
+##                    self.debugServer.clientUtStartTest(testname, doc)
+##                    continue
+##                
+##                if resp == DebugProtocol.ResponseUTStopTest:
+##                    self.debugServer.clientUtStopTest()
+##                    continue
+##                
+##                if resp == DebugProtocol.ResponseUTTestFailed:
+##                    testname, traceback, id = eval(line[eoc:-1])
+##                    self.debugServer.clientUtTestFailed(
+##                        testname, traceback, id)
+##                    continue
+##                
+##                if resp == DebugProtocol.ResponseUTTestErrored:
+##                    testname, traceback, id = eval(line[eoc:-1])
+##                    self.debugServer.clientUtTestErrored(
+##                        testname, traceback, id)
+##                    continue
+##                
+##                if resp == DebugProtocol.ResponseUTTestSkipped:
+##                    testname, reason, id = eval(line[eoc:-1])
+##                    self.debugServer.clientUtTestSkipped(testname, reason, id)
+##                    continue
+##                
+##                if resp == DebugProtocol.ResponseUTTestFailedExpected:
+##                    testname, traceback, id = eval(line[eoc:-1])
+##                    self.debugServer.clientUtTestFailedExpected(
+##                        testname, traceback, id)
+##                    continue
+##                
+##                if resp == DebugProtocol.ResponseUTTestSucceededUnexpected:
+##                    testname, id = eval(line[eoc:-1])
+##                    self.debugServer.clientUtTestSucceededUnexpected(
+##                        testname, id)
+##                    continue
+##                
+##                if resp == DebugProtocol.ResponseUTFinished:
+##                    self.debugServer.clientUtFinished()
+##                    continue
+##                
+##                if resp == DebugProtocol.RequestForkTo:
+##                    self.__askForkTo()
+##                    continue
+##            
+##            self.debugServer.signalClientOutput(line)
     
     def __handleJsonCommand(self, jsonStr):
         """
@@ -1182,13 +1192,16 @@
             commandDict = json.loads(jsonStr.strip())
         except json.JSONDecodeError as err:
             # TODO: implement real error handling
-            print(str(err))
+##            print(str(err))
             return
         
         method = commandDict["method"]
         params = commandDict["params"]
         
-        if method in ["ResponseLine", "ResponseStack"]:
+        if method == "ClientOutput":
+            self.debugServer.signalClientOutput(params["text"])
+        
+        elif method in ["ResponseLine", "ResponseStack"]:
             for s in params["stack"]:
                 s[0] = self.translate(s[0], True)
             cf = params["stack"][0]
@@ -1200,9 +1213,8 @@
                     cf[0], int(cf[1]),
                     method == "ResponseStack")
                 self.debugServer.signalClientStack(params["stack"])
-            return
         
-        if method == "CallTrace":
+        elif method == "CallTrace":
             isCall = params["event"].lower() == "c"
             fromFile, fromLineno, fromFunc = params["from"].rsplit(":", 2)
             toFile, toLineno, toFunc = params["to"].rsplit(":", 2)
@@ -1210,75 +1222,61 @@
                 isCall,
                 fromFile, fromLineno, fromFunc,
                 toFile, toLineno, toFunc)
-            return
         
-        if method == "ResponseVariables":
+        elif method == "ResponseVariables":
             self.debugServer.signalClientVariables(
                 params["scope"], params["variables"])
-            return
         
-        if method == "ResponseVariable":
+        elif method == "ResponseVariable":
             self.debugServer.signalClientVariable(
                 params["scope"], [params["variable"]] + params["variables"])
-            return
         
-        if method == "ResponseThreadList":
+        elif method == "ResponseThreadList":
             self.debugServer.signalClientThreadList(
                 params["currentID"], params["threadList"])
-            return
         
-        if method == "ResponseThreadSet":
+        elif method == "ResponseThreadSet":
             self.debugServer.signalClientThreadSet()
-            return
         
-        if method == "ResponseCapabilities":
+        elif method == "ResponseCapabilities":
             self.clientCapabilities = params["capabilities"]
             self.debugServer.signalClientCapabilities(
                 params["capabilities"], params["clientType"])
-            return
         
-        if method == "ResponseBanner":
+        elif method == "ResponseBanner":
             self.debugServer.signalClientBanner(
                 params["version"],
                 params["platform"],
                 params["dbgclient"])
-            return
         
-        if method == "ResponseOK":
+        elif method == "ResponseOK":
             self.debugServer.signalClientStatement(False)
-            return
         
-        if method == "ResponseContinue":
+        elif method == "ResponseContinue":
             self.debugServer.signalClientStatement(True)
-            return
         
-        if method == "RequestRaw":
+        elif method == "RequestRaw":
             self.debugServer.signalClientRawInput(
                 params["prompt"], params["echo"])
-            return
         
-        if method == "ResponseBPConditionError":
+        elif method == "ResponseBPConditionError":
             params["filename"] = self.translate(params["filename"], True)
             self.debugServer.signalClientBreakConditionError(
                 params["filename"], params["line"])
-            return
         
-        if method == "ResponseClearBreakpoint":
+        elif method == "ResponseClearBreakpoint":
             params["filename"] = self.translate(params["filename"], True)
             self.debugServer.signalClientClearBreak(
                 params["filename"], params["line"])
-            return
         
-        if method == "ResponseWatchConditionError":
+        elif method == "ResponseWatchConditionError":
             self.debugServer.signalClientWatchConditionError(
                 params["condition"])
-            return
         
-        if method == "ResponseClearWatch":
+        elif method == "ResponseClearWatch":
             self.debugServer.signalClientClearWatch(params["condition"])
-            return
         
-        if method == "ResponseException":
+        elif method == "ResponseException":
             if params:
                 exctype = params["type"]
                 excmessage = params["message"]
@@ -1293,45 +1291,73 @@
                             else:
                                 break
             else:
-                exctype = None
+                exctype = ''
                 excmessage = ''
                 stack = []
             
             self.debugServer.signalClientException(
                 exctype, excmessage, stack)
-            return
         
-        if method == "ResponseSyntax":
+        elif method == "ResponseSyntax":
             self.debugServer.signalClientSyntaxError(
                 params["message"], self.translate(params["filename"], True),
                 params["linenumber"], params["characternumber"])
-            return
         
-        if method == "ResponseSignal":
+        elif method == "ResponseSignal":
             self.debugServer.signalClientSignal(
                 params["message"], self.translate(params["filename"], True),
                 params["linenumber"], params["function"], params["arguments"])
-            return
         
-        if method == "ResponseExit":
+        elif method == "ResponseExit":
             self.__scriptName = ""
             self.debugServer.signalClientExit(params["status"])
-            return
+            if params["message"]:
+                self.debugServer.signalClientOutput(params["message"])
         
-        if method == "PassiveStartup":
+        elif method == "PassiveStartup":
             self.debugServer.passiveStartUp(
                 self.translate(params["filename"], True), params["exceptions"])
-            return
         
-        if method == "ResponseCompletion":
+        elif method == "ResponseCompletion":
             self.debugServer.signalClientCompletionList(
                 params["completions"], params["text"])
-            return
         
-        if method == "ResponseUTPrepared":
+        elif method == "ResponseUTPrepared":
             self.debugServer.clientUtPrepared(
                 params["count"], params["exception"], params["message"])
-            return
+        
+        elif method == "ResponseUTFinished":
+            self.debugServer.clientUtFinished()
+        
+        elif method == "ResponseUTStartTest":
+            self.debugServer.clientUtStartTest(
+                params["testname"], params["description"])
+        
+        elif method == "ResponseUTStopTest":
+            self.debugServer.clientUtStopTest()
+        
+        elif method == "ResponseUTTestFailed":
+            self.debugServer.clientUtTestFailed(
+                params["testname"], params["traceback"], params["id"])
+        
+        elif method == "ResponseUTTestErrored":
+            self.debugServer.clientUtTestErrored(
+                params["testname"], params["traceback"], params["id"])
+        
+        elif method == "ResponseUTTestSkipped":
+            self.debugServer.clientUtTestSkipped(
+                params["testname"], params["reason"], params["id"])
+        
+        elif method == "ResponseUTTestFailedExpected":
+            self.debugServer.clientUtTestFailedExpected(
+                params["testname"], params["traceback"], params["id"])
+        
+        elif method == "ResponseUTTestSucceededUnexpected":
+            self.debugServer.clientUtTestSucceededUnexpected(
+                params["testname"], params["id"])
+        
+        elif method == "RequestForkTo":
+            self.__askForkTo()
     
     def __sendCommand(self, cmd):
         """
--- a/Documentation/Source/eric6.DebugClients.Python3.AsyncIO.html	Thu Sep 01 20:03:50 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-<!DOCTYPE html>
-<html><head>
-<title>eric6.DebugClients.Python3.AsyncIO</title>
-<meta charset="UTF-8">
-<style>
-body {
-    background: #EDECE6;
-    margin: 0em 1em 10em 1em;
-    color: black;
-}
-
-h1 { color: white; background: #85774A; }
-h2 { color: white; background: #85774A; }
-h3 { color: white; background: #9D936E; }
-h4 { color: white; background: #9D936E; }
-    
-a { color: #BA6D36; }
-
-</style>
-</head>
-<body><a NAME="top" ID="top"></a>
-<h1>eric6.DebugClients.Python3.AsyncIO</h1>
-<p>
-Module implementing a base class of an asynchronous interface for the debugger.
-</p>
-<h3>Global Attributes</h3>
-<table>
-<tr><td>None</td></tr>
-</table>
-<h3>Classes</h3>
-<table>
-<tr>
-<td><a href="#AsyncIO">AsyncIO</a></td>
-<td>Class implementing asynchronous reading and writing.</td>
-</tr>
-</table>
-<h3>Functions</h3>
-<table>
-<tr><td>None</td></tr>
-</table>
-<hr /><hr />
-<a NAME="AsyncIO" ID="AsyncIO"></a>
-<h2>AsyncIO</h2>
-<p>
-    Class implementing asynchronous reading and writing.
-</p>
-<h3>Derived from</h3>
-object
-<h3>Class Attributes</h3>
-<table>
-<tr><td>None</td></tr>
-</table>
-<h3>Class Methods</h3>
-<table>
-<tr><td>None</td></tr>
-</table>
-<h3>Methods</h3>
-<table>
-<tr>
-<td><a href="#AsyncIO.__init__">AsyncIO</a></td>
-<td>Constructor</td>
-</tr><tr>
-<td><a href="#AsyncIO.disconnect">disconnect</a></td>
-<td>Public method to disconnect any current connection.</td>
-</tr><tr>
-<td><a href="#AsyncIO.readReady">readReady</a></td>
-<td>Public method called when there is data ready to be read.</td>
-</tr><tr>
-<td><a href="#AsyncIO.setDescriptors">setDescriptors</a></td>
-<td>Public method called to set the descriptors for the connection.</td>
-</tr><tr>
-<td><a href="#AsyncIO.write">write</a></td>
-<td>Public method to write a string.</td>
-</tr><tr>
-<td><a href="#AsyncIO.writeReady">writeReady</a></td>
-<td>Public method called when we are ready to write data.</td>
-</tr>
-</table>
-<h3>Static Methods</h3>
-<table>
-<tr><td>None</td></tr>
-</table>
-<a NAME="AsyncIO.__init__" ID="AsyncIO.__init__"></a>
-<h4>AsyncIO (Constructor)</h4>
-<b>AsyncIO</b>(<i></i>)
-<p>
-        Constructor
-</p><a NAME="AsyncIO.disconnect" ID="AsyncIO.disconnect"></a>
-<h4>AsyncIO.disconnect</h4>
-<b>disconnect</b>(<i></i>)
-<p>
-        Public method to disconnect any current connection.
-</p><a NAME="AsyncIO.readReady" ID="AsyncIO.readReady"></a>
-<h4>AsyncIO.readReady</h4>
-<b>readReady</b>(<i>fd</i>)
-<p>
-        Public method called when there is data ready to be read.
-</p><dl>
-<dt><i>fd</i></dt>
-<dd>
-file descriptor of the file that has data to be read (int)
-</dd>
-</dl><a NAME="AsyncIO.setDescriptors" ID="AsyncIO.setDescriptors"></a>
-<h4>AsyncIO.setDescriptors</h4>
-<b>setDescriptors</b>(<i>rfd, wfd</i>)
-<p>
-        Public method called to set the descriptors for the connection.
-</p><dl>
-<dt><i>rfd</i></dt>
-<dd>
-file descriptor of the input file (int)
-</dd><dt><i>wfd</i></dt>
-<dd>
-file descriptor of the output file (int)
-</dd>
-</dl><a NAME="AsyncIO.write" ID="AsyncIO.write"></a>
-<h4>AsyncIO.write</h4>
-<b>write</b>(<i>s</i>)
-<p>
-        Public method to write a string.
-</p><dl>
-<dt><i>s</i></dt>
-<dd>
-the data to be written (string)
-</dd>
-</dl><a NAME="AsyncIO.writeReady" ID="AsyncIO.writeReady"></a>
-<h4>AsyncIO.writeReady</h4>
-<b>writeReady</b>(<i>fd</i>)
-<p>
-        Public method called when we are ready to write data.
-</p><dl>
-<dt><i>fd</i></dt>
-<dd>
-file descriptor of the file that has data to be written (int)
-</dd>
-</dl>
-<div align="right"><a href="#top">Up</a></div>
-<hr />
-</body></html>
\ No newline at end of file
--- a/Documentation/Source/eric6.DebugClients.Python3.DebugProtocol.html	Thu Sep 01 20:03:50 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-<!DOCTYPE html>
-<html><head>
-<title>eric6.DebugClients.Python3.DebugProtocol</title>
-<meta charset="UTF-8">
-<style>
-body {
-    background: #EDECE6;
-    margin: 0em 1em 10em 1em;
-    color: black;
-}
-
-h1 { color: white; background: #85774A; }
-h2 { color: white; background: #85774A; }
-h3 { color: white; background: #9D936E; }
-h4 { color: white; background: #9D936E; }
-    
-a { color: #BA6D36; }
-
-</style>
-</head>
-<body><a NAME="top" ID="top"></a>
-<h1>eric6.DebugClients.Python3.DebugProtocol</h1>
-<p>
-Module defining the debug protocol tokens.
-</p>
-<h3>Global Attributes</h3>
-<table>
-<tr><td>CallTrace</td></tr><tr><td>DebugAddress</td></tr><tr><td>EOT</td></tr><tr><td>PassiveStartup</td></tr><tr><td>RequestBanner</td></tr><tr><td>RequestBreak</td></tr><tr><td>RequestBreakEnable</td></tr><tr><td>RequestBreakIgnore</td></tr><tr><td>RequestCallTrace</td></tr><tr><td>RequestCapabilities</td></tr><tr><td>RequestCompletion</td></tr><tr><td>RequestContinue</td></tr><tr><td>RequestCoverage</td></tr><tr><td>RequestEnv</td></tr><tr><td>RequestEval</td></tr><tr><td>RequestExec</td></tr><tr><td>RequestForkMode</td></tr><tr><td>RequestForkTo</td></tr><tr><td>RequestLoad</td></tr><tr><td>RequestOK</td></tr><tr><td>RequestProfile</td></tr><tr><td>RequestRun</td></tr><tr><td>RequestSetFilter</td></tr><tr><td>RequestShutdown</td></tr><tr><td>RequestStep</td></tr><tr><td>RequestStepOut</td></tr><tr><td>RequestStepOver</td></tr><tr><td>RequestStepQuit</td></tr><tr><td>RequestThreadList</td></tr><tr><td>RequestThreadSet</td></tr><tr><td>RequestUTPrepare</td></tr><tr><td>RequestUTRun</td></tr><tr><td>RequestUTStop</td></tr><tr><td>RequestVariable</td></tr><tr><td>RequestVariables</td></tr><tr><td>RequestWatch</td></tr><tr><td>RequestWatchEnable</td></tr><tr><td>RequestWatchIgnore</td></tr><tr><td>ResponseBPConditionError</td></tr><tr><td>ResponseBanner</td></tr><tr><td>ResponseCapabilities</td></tr><tr><td>ResponseClearBreak</td></tr><tr><td>ResponseClearWatch</td></tr><tr><td>ResponseCompletion</td></tr><tr><td>ResponseContinue</td></tr><tr><td>ResponseException</td></tr><tr><td>ResponseExit</td></tr><tr><td>ResponseForkTo</td></tr><tr><td>ResponseLine</td></tr><tr><td>ResponseOK</td></tr><tr><td>ResponseRaw</td></tr><tr><td>ResponseSignal</td></tr><tr><td>ResponseStack</td></tr><tr><td>ResponseSyntax</td></tr><tr><td>ResponseThreadList</td></tr><tr><td>ResponseThreadSet</td></tr><tr><td>ResponseUTFinished</td></tr><tr><td>ResponseUTPrepared</td></tr><tr><td>ResponseUTStartTest</td></tr><tr><td>ResponseUTStopTest</td></tr><tr><td>ResponseUTTestErrored</td></tr><tr><td>ResponseUTTestFailed</td></tr><tr><td>ResponseUTTestFailedExpected</td></tr><tr><td>ResponseUTTestSkipped</td></tr><tr><td>ResponseUTTestSucceededUnexpected</td></tr><tr><td>ResponseVariable</td></tr><tr><td>ResponseVariables</td></tr><tr><td>ResponseWPConditionError</td></tr>
-</table>
-<h3>Classes</h3>
-<table>
-<tr><td>None</td></tr>
-</table>
-<h3>Functions</h3>
-<table>
-<tr><td>None</td></tr>
-</table>
-<hr />
-</body></html>
\ No newline at end of file
--- a/eric6.e4p	Thu Sep 01 20:03:50 2016 +0200
+++ b/eric6.e4p	Fri Sep 02 19:14:41 2016 +0200
@@ -75,7 +75,6 @@
     <Source>DebugClients/Python/eric6dbgstub.py</Source>
     <Source>DebugClients/Python/getpass.py</Source>
     <Source>DebugClients/Python3/AsyncFile.py</Source>
-    <Source>DebugClients/Python3/AsyncIO.py</Source>
     <Source>DebugClients/Python3/DCTestResult.py</Source>
     <Source>DebugClients/Python3/DebugBase.py</Source>
     <Source>DebugClients/Python3/DebugClient.py</Source>
@@ -83,7 +82,6 @@
     <Source>DebugClients/Python3/DebugClientCapabilities.py</Source>
     <Source>DebugClients/Python3/DebugClientThreads.py</Source>
     <Source>DebugClients/Python3/DebugConfig.py</Source>
-    <Source>DebugClients/Python3/DebugProtocol.py</Source>
     <Source>DebugClients/Python3/DebugThread.py</Source>
     <Source>DebugClients/Python3/DebugUtilities.py</Source>
     <Source>DebugClients/Python3/FlexCompleter.py</Source>

eric ide

mercurial