Sat, 16 Sep 2017 16:40:50 +0200
Implemented the distributed 'query' methods.
# -*- coding: utf-8 -*- # Copyright (c) 2017 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing the JSON based server base class. """ from __future__ import unicode_literals import json from PyQt5.QtCore import pyqtSlot, QProcess, QThread from PyQt5.QtNetwork import QTcpServer, QHostAddress from E5Gui import E5MessageBox import Preferences import Utilities class JsonServer(QTcpServer): """ Class implementing the JSON based server base class. """ def __init__(self, parent=None): """ Constructor @param parent parent object @type QObject """ super(JsonServer, self).__init__(parent) self.__clientProcess = None self.__connection = None # setup the network interface networkInterface = Preferences.getDebugger("NetworkInterface") if networkInterface == "all" or '.' in networkInterface: # IPv4 self.__hostAddress = '127.0.0.1' else: # IPv6 self.__hostAddress = '::1' self.listen(QHostAddress(self.__hostAddress)) self.newConnection.connect(self.__handleNewConnection) port = self.serverPort() ## Note: Need the port if started external in debugger: print('Refactoring server listening on: {0:d}'.format(port)) # __IGNORE_WARNING__ @pyqtSlot() def __handleNewConnection(self): """ Private slot for new incomming connections from the refactoring 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) self.sendJson("GetConfig", {}) @pyqtSlot() def __handleDisconnect(self): """ Private slot handling a disconnect of the refactoring client. """ if self.__connection is not None: self.__connection.close() self.__connection = None @pyqtSlot() def __receiveJson(self): """ Private slot handling received data from the client. """ while self.__connection and self.__connection.canReadLine(): data = self.__connection.readLine() jsonLine = bytes(data).decode("utf-8", 'backslashreplace') ## print("JSON Server: ", jsonLine) ##debug try: clientDict = json.loads(jsonLine.strip()) except (TypeError, ValueError) as err: E5MessageBox.critical( None, self.tr("JSON Protocol Error"), self.tr("""<p>The response received from the client""" """ could not be decoded. Please report""" """ this issue with the received data to the""" """ eric bugs email address.</p>""" """<p>Error: {0}</p>""" """<p>Data:<br/>{0}</p>""").format( str(err), Utilities.html_encode(jsonLine.strip())), E5MessageBox.StandardButtons( E5MessageBox.Ok)) return method = clientDict["method"] params = clientDict["params"] # TODO: remove these once done print("Method:", method) print("Params:", params) self.handleCall(method, params) def handleCall(self, method, params): """ Public method to handle a method call from the client. Note: This is an empty implementation that must be overridden in derived classes. @param method requested method name @type str @param params dictionary with method specific parameters @type dict """ pass def sendJson(self, command, params): """ Public method to send a single refactoring command to the client. @param command command name to be sent @type str @param params dictionary of named parameters for the command @type dict """ commandDict = { "jsonrpc": "2.0", "method": command, "params": params, } cmd = json.dumps(commandDict) + '\n' if self.__connection is not None: self.__connection.write(cmd.encode('utf8', 'backslashreplace')) def startClient(self, interpreter, clientScript, clientArgs): """ Public method to start the 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 @return flag indicating a successful client start @rtype bool """ if interpreter == "" or not Utilities.isinpath(interpreter): return False proc = QProcess() proc.setProcessChannelMode(QProcess.ForwardedChannels) args = [clientScript, self.__hostAddress, str(self.serverPort())] args.extend(clientArgs) proc.start(interpreter, args) if not proc.waitForStarted(10000): proc = None self.__clientProcess = proc return proc is not None def stopClient(self): """ Public method to stop the client process. """ self.sendJson("Exit", {}) QThread.msleep(200) self.__clientProcess.close() self.__clientProcess = None # # eflag: noqa = M801