RefactoringRope/JsonServer.py

branch
server_client_variant
changeset 192
20950ed6b384
parent 189
2711fdd91925
child 194
5c297b473425
--- a/RefactoringRope/JsonServer.py	Sun Sep 24 17:10:48 2017 +0200
+++ b/RefactoringRope/JsonServer.py	Sun Sep 24 19:27:30 2017 +0200
@@ -24,17 +24,24 @@
     """
     Class implementing the JSON based server base class.
     """
-    def __init__(self, parent=None):
+    def __init__(self, multiplex=False, parent=None):
         """
         Constructor
         
+        @param multiplex flag indicating a multiplexing server
+        @type bool
         @param parent parent object
         @type QObject
         """
         super(JsonServer, self).__init__(parent)
         
-        self.__clientProcess = None
-        self.__connection = None
+        self.__multiplex = multiplex
+        if self.__multiplex:
+            self.__clientProcesses = {}
+            self.__connections = {}
+        else:
+            self.__clientProcess = None
+            self.__connection = None
         
         # setup the network interface
         networkInterface = Preferences.getDebugger("NetworkInterface")
@@ -56,39 +63,67 @@
     @pyqtSlot()
     def __handleNewConnection(self):
         """
-        Private slot for new incomming connections from the refactoring client.
+        Private slot for new incoming connections from a client.
         """
-        if self.__connection is not None:
-            self.__connection.close()
-            self.__connection = None
-        
         connection = self.nextPendingConnection()
         if not connection.isValid():
             return
         
-        self.__connection = connection
-        connection.readyRead.connect(self.__receiveJson)
-        connection.disconnected.connect(self.__handleDisconnect)
+        if self.__multiplex:
+            if not connection.waitForReadyRead(3000):
+                return
+            idString = bytes(connection.readLine()).decode(
+                "utf-8", 'backslashreplace')
+            if idString in self.__connections:
+                self.__connections[id].close()
+                self.__connections[id] = connection
+        else:
+            idString = ""
+            if self.__connection is not None:
+                self.__connection.close()
+            
+            self.__connection = connection
+        
+        connection.readyRead.connect(
+            lambda: self.__receiveJson(idString))
+        connection.disconnected.connect(
+            lambda: self.__handleDisconnect(idString))
         
         self.sendJson("GetConfig", {})
     
     @pyqtSlot()
-    def __handleDisconnect(self):
+    def __handleDisconnect(self, idString):
         """
-        Private slot handling a disconnect of the refactoring client.
+        Private slot handling a disconnect of the client.
+        
+        @param idString id of the connection been disconnected
+        @type str
         """
-        if self.__connection is not None:
-            self.__connection.close()
-        
-        self.__connection = None
+        if idString:
+            if idString in self.__connections:
+                self.__connections[idString].close()
+                del self.__connections[id]
+        else:
+            if self.__connection is not None:
+                self.__connection.close()
+            
+            self.__connection = None
     
     @pyqtSlot()
-    def __receiveJson(self):
+    def __receiveJson(self, idString):
         """
         Private slot handling received data from the client.
+        
+        @param idString id of the connection been disconnected
+        @type str
         """
-        while self.__connection and self.__connection.canReadLine():
-            data = self.__connection.readLine()
+        if idString:
+            connection = self.__connections[idString]
+        else:
+            connection = self.__connection
+        
+        while connection and connection.canReadLine():
+            data = connection.readLine()
             jsonLine = bytes(data).decode("utf-8", 'backslashreplace')
             
 ##            print("JSON Server: ", jsonLine)          ##debug
@@ -129,9 +164,9 @@
         """
         pass
     
-    def sendJson(self, command, params, flush=False):
+    def sendJson(self, command, params, flush=False, idString=""):
         """
-        Public method to send a single refactoring command to the client.
+        Public method to send a single command to a client.
         
         @param command command name to be sent
         @type str
@@ -139,6 +174,8 @@
         @type dict
         @param flush flag indicating to flush the data to the socket
         @type bool
+        @param idString id of the connection to send data to
+        @type str
         """
         commandDict = {
             "jsonrpc": "2.0",
@@ -147,20 +184,27 @@
         }
         cmd = json.dumps(commandDict) + '\n'
         
-        if self.__connection is not None:
-            self.__connection.write(cmd.encode('utf8', 'backslashreplace'))
+        if idString:
+            connection = self.__connections[idString]
+        else:
+            connection = self.__connection
+        
+        if connection is not None:
+            connection.write(cmd.encode('utf8', 'backslashreplace'))
             if flush:
-                self.__connection.flush()
+                connection.flush()
     
-    def startClient(self, interpreter, clientScript, clientArgs):
+    def startClient(self, interpreter, clientScript, clientArgs, idString=""):
         """
-        Public method to start the client process.
+        Public method to start a client process.
         
         @param interpreter interpreter to be used for the client
         @type str
         @param clientScript path to the client script
         @type str
         @param clientArgs list of arguments for the client
+        @param idString id of the client to be started
+        @type str
         @return flag indicating a successful client start
         @rtype bool
         """
@@ -175,19 +219,33 @@
         if not proc.waitForStarted(10000):
             proc = None
         
-        self.__clientProcess = proc
+        if idString:
+            self.__clientProcesses[idString] = proc
+        else:
+            self.__clientProcess = proc
         
         return proc is not None
     
-    def stopClient(self):
+    def stopClient(self, idString=""):
         """
-        Public method to stop the client process.
+        Public method to stop a client process.
+        
+        @param idString id of the client to be stopped
+        @type str
         """
-        self.sendJson("Exit", {}, flush=True)
+        self.sendJson("Exit", {}, flush=True, idString=idString)
         
-        if self.__connection is not None:
-            self.__connection.waitForDisconnected()
+        if idString:
+            connection = self.__connections[idString]
+        else:
+            connection = self.__connection
+        if connection is not None:
+            connection.waitForDisconnected()
         
-        if self.__clientProcess is not None:
-            self.__clientProcess.close()
-            self.__clientProcess = None
+        if idString:
+            self .__clientProcesses[idString].close()
+            del self.__clientProcesses[idString]
+        else:
+            if self.__clientProcess is not None:
+                self.__clientProcess.close()
+                self.__clientProcess = None

eric ide

mercurial