Thu, 25 Jan 2024 14:13:36 +0100
JSON server and client
- Changed the code code to secure the data with an Adler32 checksum.
8300 | 1 | # -*- coding: utf-8 -*- |
2 | ||
10439
21c28b0f9e41
Updated copyright for 2024.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10423
diff
changeset
|
3 | # Copyright (c) 2017 - 2024 Detlev Offenbach <detlev@die-offenbachs.de> |
8300 | 4 | # |
5 | ||
6 | """ | |
7 | Module implementing the JSON based server base class. | |
8 | """ | |
9 | ||
10 | import contextlib | |
11 | import json | |
10524
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
12 | import struct |
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
13 | import zlib |
8300 | 14 | |
8318
962bce857696
Replaced all imports of PyQt5 to PyQt6 and started to replace code using obsoleted methods and adapt to the PyQt6 enum usage.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8312
diff
changeset
|
15 | from PyQt6.QtCore import ( |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
16 | QCoreApplication, |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
17 | QEventLoop, |
9473
3f23dbf37dbe
Resorted the import statements using isort.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9413
diff
changeset
|
18 | QProcess, |
3f23dbf37dbe
Resorted the import statements using isort.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9413
diff
changeset
|
19 | QProcessEnvironment, |
3f23dbf37dbe
Resorted the import statements using isort.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9413
diff
changeset
|
20 | QThread, |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
21 | QTimer, |
9473
3f23dbf37dbe
Resorted the import statements using isort.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9413
diff
changeset
|
22 | pyqtSlot, |
8300 | 23 | ) |
9473
3f23dbf37dbe
Resorted the import statements using isort.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9413
diff
changeset
|
24 | from PyQt6.QtNetwork import QHostAddress, QTcpServer |
8300 | 25 | |
9413
80c06d472826
Changed the eric7 import statements to include the package name (i.e. eric7) in order to not fiddle with sys.path.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9221
diff
changeset
|
26 | from eric7 import Preferences, Utilities |
9473
3f23dbf37dbe
Resorted the import statements using isort.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9413
diff
changeset
|
27 | from eric7.EricWidgets import EricMessageBox |
9624
b47dfa7a137d
Refactored the Utilities and Globals modules in order to enhance the maintainability.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9521
diff
changeset
|
28 | from eric7.SystemUtilities import FileSystemUtilities |
8300 | 29 | |
30 | ||
8354
12ebd3934fef
Renamed 'E5Utilities' to 'EricUtilities' and 'E5Network' to 'EricNetwork'.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8322
diff
changeset
|
31 | class EricJsonServer(QTcpServer): |
8300 | 32 | """ |
33 | Class implementing a JSON based server base class. | |
34 | """ | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
35 | |
8300 | 36 | def __init__(self, name="", multiplex=False, parent=None): |
37 | """ | |
38 | Constructor | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
39 | |
8300 | 40 | @param name name of the server (used for output only) |
41 | @type str | |
42 | @param multiplex flag indicating a multiplexing server | |
43 | @type bool | |
44 | @param parent parent object | |
45 | @type QObject | |
46 | """ | |
47 | super().__init__(parent) | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
48 | |
8300 | 49 | self.__name = name |
50 | self.__multiplex = multiplex | |
51 | if self.__multiplex: | |
52 | self.__clientProcesses = {} | |
53 | self.__connections = {} | |
54 | else: | |
55 | self.__clientProcess = None | |
56 | self.__connection = None | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
57 | |
8300 | 58 | # setup the network interface |
59 | networkInterface = Preferences.getDebugger("NetworkInterface") | |
9521 | 60 | if networkInterface in ("allv4", "localv4") or "." in networkInterface: |
8300 | 61 | # IPv4 |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
62 | self.__hostAddress = "127.0.0.1" |
9521 | 63 | elif networkInterface in ("all", "allv6", "localv6"): |
8300 | 64 | # IPv6 |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
65 | self.__hostAddress = "::1" |
9521 | 66 | else: |
67 | self.__hostAddress = networkInterface | |
8300 | 68 | self.listen(QHostAddress(self.__hostAddress)) |
69 | ||
70 | self.newConnection.connect(self.handleNewConnection) | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
71 | |
9521 | 72 | ## Note: Need the address and port if client is started external in debugger. |
73 | hostAddressStr = ( | |
74 | "[{0}]".format(self.__hostAddress) | |
75 | if ":" in self.__hostAddress | |
76 | else self.__hostAddress | |
77 | ) | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
78 | print( # __IGNORE_WARNING_M801__ |
9521 | 79 | "JSON server ({2}) listening on: {0}:{1:d}".format( |
80 | hostAddressStr, self.serverPort(), self.__name | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
81 | ) |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
82 | ) |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
83 | |
8300 | 84 | @pyqtSlot() |
85 | def handleNewConnection(self): | |
86 | """ | |
87 | Public slot for new incoming connections from a client. | |
88 | """ | |
89 | connection = self.nextPendingConnection() | |
90 | if not connection.isValid(): | |
91 | return | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
92 | |
8300 | 93 | if self.__multiplex: |
94 | if not connection.waitForReadyRead(3000): | |
95 | return | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
96 | idString = ( |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
97 | bytes(connection.readLine()).decode("utf-8", "backslashreplace").strip() |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
98 | ) |
8300 | 99 | if idString in self.__connections: |
100 | self.__connections[idString].close() | |
101 | self.__connections[idString] = connection | |
102 | else: | |
103 | idString = "" | |
104 | if self.__connection is not None: | |
105 | self.__connection.close() | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
106 | |
8300 | 107 | self.__connection = connection |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
108 | |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
109 | connection.readyRead.connect(lambda: self.__receiveJson(idString)) |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
110 | connection.disconnected.connect(lambda: self.__handleDisconnect(idString)) |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
111 | |
8300 | 112 | @pyqtSlot() |
113 | def __handleDisconnect(self, idString): | |
114 | """ | |
115 | Private slot handling a disconnect of the client. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
116 | |
8300 | 117 | @param idString id of the connection been disconnected |
118 | @type str | |
119 | """ | |
120 | if idString: | |
121 | if idString in self.__connections: | |
122 | self.__connections[idString].close() | |
123 | del self.__connections[idString] | |
124 | else: | |
125 | if self.__connection is not None: | |
126 | self.__connection.close() | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
127 | |
8300 | 128 | self.__connection = None |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
129 | |
8300 | 130 | def connectionNames(self): |
131 | """ | |
132 | Public method to get the list of active connection names. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
133 | |
8300 | 134 | If this is not a multiplexing server, an empty list is returned. |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
135 | |
8300 | 136 | @return list of active connection names |
137 | @rtype list of str | |
138 | """ | |
139 | if self.__multiplex: | |
10373
093dcebe5ecb
Corrected some uses of dict.keys(), dict.values() and dict.items().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10205
diff
changeset
|
140 | return list(self.__connections) |
8300 | 141 | else: |
142 | return [] | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
143 | |
8300 | 144 | @pyqtSlot() |
145 | def __receiveJson(self, idString): | |
146 | """ | |
147 | Private slot handling received data from the client. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
148 | |
9057
ddc46e93ccc4
Added classes to realize a JSON based stream between two processes.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8943
diff
changeset
|
149 | @param idString id of the connection |
8300 | 150 | @type str |
151 | """ | |
152 | if idString: | |
153 | try: | |
154 | connection = self.__connections[idString] | |
155 | except KeyError: | |
156 | connection = None | |
157 | else: | |
158 | connection = self.__connection | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
159 | |
10524
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
160 | while connection and connection.bytesAvailable(): |
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
161 | header = connection.read(struct.calcsize(b"!II")) |
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
162 | length, datahash = struct.unpack(b"!II", header) |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
163 | |
10524
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
164 | data = bytearray() |
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
165 | while len(data) < length: |
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
166 | maxSize = length - len(data) |
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
167 | if connection.bytesAvailable() < maxSize: |
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
168 | connection.waitForReadyRead(50) |
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
169 | data += connection.read(maxSize) |
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
170 | |
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
171 | if zlib.adler32(data) & 0xFFFFFFFF != datahash: |
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
172 | # corrupted data -> discard and continue |
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
173 | continue |
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
174 | |
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
175 | jsonString = data.decode("utf-8", "backslashreplace") |
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
176 | |
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
177 | # - print("JSON Server ({0}): {1}".format(self.__name, jsonString)) |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
178 | # - this is for debugging only |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
179 | |
8300 | 180 | try: |
10524
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
181 | clientDict = json.loads(jsonString.strip()) |
8300 | 182 | except (TypeError, ValueError) as err: |
8356
68ec9c3d4de5
Renamed the modules and classes of the E5Gui package to have the prefix 'Eric' instead of 'E5'.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8354
diff
changeset
|
183 | EricMessageBox.critical( |
8300 | 184 | None, |
185 | self.tr("JSON Protocol Error"), | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
186 | self.tr( |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
187 | """<p>The response received from the client""" |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
188 | """ could not be decoded. Please report""" |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
189 | """ this issue with the received data to the""" |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
190 | """ eric bugs email address.</p>""" |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
191 | """<p>Error: {0}</p>""" |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
192 | """<p>Data:<br/>{1}</p>""" |
10524
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
193 | ).format(str(err), Utilities.html_encode(jsonString.strip())), |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
194 | EricMessageBox.Ok, |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
195 | ) |
8300 | 196 | return |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
197 | |
8300 | 198 | self.handleCall(clientDict["method"], clientDict["params"]) |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
199 | |
8300 | 200 | def sendJson(self, command, params, flush=False, idString=""): |
201 | """ | |
202 | Public method to send a single command to a client. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
203 | |
8300 | 204 | @param command command name to be sent |
205 | @type str | |
206 | @param params dictionary of named parameters for the command | |
207 | @type dict | |
208 | @param flush flag indicating to flush the data to the socket | |
209 | @type bool | |
210 | @param idString id of the connection to send data to | |
211 | @type str | |
212 | """ | |
213 | commandDict = { | |
214 | "jsonrpc": "2.0", | |
215 | "method": command, | |
216 | "params": params, | |
217 | } | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
218 | cmd = json.dumps(commandDict) + "\n" |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
219 | |
8300 | 220 | if idString: |
221 | try: | |
222 | connection = self.__connections[idString] | |
223 | except KeyError: | |
224 | connection = None | |
225 | else: | |
226 | connection = self.__connection | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
227 | |
8300 | 228 | if connection is not None: |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
229 | data = cmd.encode("utf8", "backslashreplace") |
10524
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
230 | header = struct.pack(b"!II", len(data), zlib.adler32(data) & 0xFFFFFFFF) |
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
231 | connection.write(header) |
ed4fd87c4d4c
JSON server and client
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
232 | connection.write(data) |
8300 | 233 | if flush: |
234 | connection.flush() | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
235 | |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
236 | def startClient( |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
237 | self, interpreter, clientScript, clientArgs, idString="", environment=None |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
238 | ): |
8300 | 239 | """ |
240 | Public method to start a client process. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
241 | |
8300 | 242 | @param interpreter interpreter to be used for the client |
243 | @type str | |
244 | @param clientScript path to the client script | |
245 | @type str | |
246 | @param clientArgs list of arguments for the client | |
10423
299802979277
Converted some source code documentation to the new style.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10373
diff
changeset
|
247 | @type list of str |
8300 | 248 | @param idString id of the client to be started |
249 | @type str | |
250 | @param environment dictionary of environment settings to pass | |
251 | @type dict | |
8301
952a05857e81
E5JsonServer: changed code to return the exit code in case of a premature exit.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8300
diff
changeset
|
252 | @return flag indicating a successful client start and the exit code |
952a05857e81
E5JsonServer: changed code to return the exit code in case of a premature exit.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8300
diff
changeset
|
253 | in case of an issue |
952a05857e81
E5JsonServer: changed code to return the exit code in case of a premature exit.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8300
diff
changeset
|
254 | @rtype bool, int |
8300 | 255 | """ |
9624
b47dfa7a137d
Refactored the Utilities and Globals modules in order to enhance the maintainability.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9521
diff
changeset
|
256 | if interpreter == "" or not FileSystemUtilities.isinpath(interpreter): |
10205
6889b666ddef
Corrected an issue in the EricJsonServer code.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9653
diff
changeset
|
257 | return False, -1 |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
258 | |
8301
952a05857e81
E5JsonServer: changed code to return the exit code in case of a premature exit.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8300
diff
changeset
|
259 | exitCode = None |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
260 | |
8300 | 261 | proc = QProcess() |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
262 | proc.setProcessChannelMode(QProcess.ProcessChannelMode.ForwardedChannels) |
8300 | 263 | if environment is not None: |
264 | env = QProcessEnvironment() | |
10373
093dcebe5ecb
Corrected some uses of dict.keys(), dict.values() and dict.items().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10205
diff
changeset
|
265 | for key, value in environment.items(): |
8300 | 266 | env.insert(key, value) |
267 | proc.setProcessEnvironment(env) | |
268 | args = [clientScript, self.__hostAddress, str(self.serverPort())] | |
269 | if idString: | |
270 | args.append(idString) | |
271 | args.extend(clientArgs) | |
272 | proc.start(interpreter, args) | |
273 | if not proc.waitForStarted(10000): | |
274 | proc = None | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
275 | |
8300 | 276 | if idString: |
277 | self.__clientProcesses[idString] = proc | |
278 | if proc: | |
279 | timer = QTimer() | |
280 | timer.setSingleShot(True) | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
281 | timer.start(30000) # 30s timeout |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
282 | while idString not in self.connectionNames() and timer.isActive(): |
8300 | 283 | # Give the event loop the chance to process the new |
284 | # connection of the client (= slow start). | |
285 | QCoreApplication.processEvents( | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
286 | QEventLoop.ProcessEventsFlag.ExcludeUserInputEvents |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
287 | ) |
8934
d3798915e0d2
Changed some code to not call QCoreApplication.processEvents() too often.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8881
diff
changeset
|
288 | QThread.msleep(100) |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
289 | |
8301
952a05857e81
E5JsonServer: changed code to return the exit code in case of a premature exit.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8300
diff
changeset
|
290 | # check if client exited prematurely |
8303
0cbba94590d2
E5JsonServer: fixed an issue introduced by the latest change.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8302
diff
changeset
|
291 | if proc.state() == QProcess.ProcessState.NotRunning: |
8301
952a05857e81
E5JsonServer: changed code to return the exit code in case of a premature exit.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8300
diff
changeset
|
292 | exitCode = proc.exitCode() |
952a05857e81
E5JsonServer: changed code to return the exit code in case of a premature exit.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8300
diff
changeset
|
293 | proc = None |
952a05857e81
E5JsonServer: changed code to return the exit code in case of a premature exit.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8300
diff
changeset
|
294 | self.__clientProcesses[idString] = None |
952a05857e81
E5JsonServer: changed code to return the exit code in case of a premature exit.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8300
diff
changeset
|
295 | break |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
296 | |
8936
dca47d2dde1c
Some performance optimizations.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8934
diff
changeset
|
297 | QThread.msleep(500) |
8300 | 298 | else: |
8303
0cbba94590d2
E5JsonServer: fixed an issue introduced by the latest change.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8302
diff
changeset
|
299 | if proc: |
0cbba94590d2
E5JsonServer: fixed an issue introduced by the latest change.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8302
diff
changeset
|
300 | timer = QTimer() |
0cbba94590d2
E5JsonServer: fixed an issue introduced by the latest change.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8302
diff
changeset
|
301 | timer.setSingleShot(True) |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
302 | timer.start(1000) # 1s timeout |
8303
0cbba94590d2
E5JsonServer: fixed an issue introduced by the latest change.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8302
diff
changeset
|
303 | while timer.isActive(): |
0cbba94590d2
E5JsonServer: fixed an issue introduced by the latest change.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8302
diff
changeset
|
304 | # check if client exited prematurely |
0cbba94590d2
E5JsonServer: fixed an issue introduced by the latest change.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8302
diff
changeset
|
305 | QCoreApplication.processEvents( |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
306 | QEventLoop.ProcessEventsFlag.ExcludeUserInputEvents |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
307 | ) |
8943
23f9c7b9e18e
Implemented some performance improvements.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8936
diff
changeset
|
308 | QThread.msleep(100) |
8303
0cbba94590d2
E5JsonServer: fixed an issue introduced by the latest change.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8302
diff
changeset
|
309 | if proc.state() == QProcess.ProcessState.NotRunning: |
0cbba94590d2
E5JsonServer: fixed an issue introduced by the latest change.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8302
diff
changeset
|
310 | exitCode = proc.exitCode() |
0cbba94590d2
E5JsonServer: fixed an issue introduced by the latest change.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8302
diff
changeset
|
311 | proc = None |
0cbba94590d2
E5JsonServer: fixed an issue introduced by the latest change.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8302
diff
changeset
|
312 | break |
8300 | 313 | self.__clientProcess = proc |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
314 | |
8301
952a05857e81
E5JsonServer: changed code to return the exit code in case of a premature exit.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8300
diff
changeset
|
315 | return proc is not None, exitCode |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
316 | |
8300 | 317 | def stopClient(self, idString=""): |
318 | """ | |
319 | Public method to stop a client process. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
320 | |
8300 | 321 | @param idString id of the client to be stopped |
322 | @type str | |
323 | """ | |
324 | self.sendJson("Exit", {}, flush=True, idString=idString) | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
325 | |
8300 | 326 | if idString: |
327 | try: | |
328 | connection = self.__connections[idString] | |
329 | except KeyError: | |
330 | connection = None | |
331 | else: | |
332 | connection = self.__connection | |
333 | if connection is not None: | |
334 | connection.waitForDisconnected() | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
335 | |
8300 | 336 | if idString: |
337 | with contextlib.suppress(KeyError): | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
338 | if self.__clientProcesses[idString] is not None: |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
339 | self.__clientProcesses[idString].close() |
8300 | 340 | del self.__clientProcesses[idString] |
341 | else: | |
342 | if self.__clientProcess is not None: | |
343 | self.__clientProcess.close() | |
344 | self.__clientProcess = None | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
345 | |
8300 | 346 | def stopAllClients(self): |
347 | """ | |
348 | Public method to stop all clients. | |
349 | """ | |
350 | clientNames = self.connectionNames()[:] | |
351 | for clientName in clientNames: | |
352 | self.stopClient(clientName) | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
353 | |
8300 | 354 | ####################################################################### |
355 | ## The following methods should be overridden by derived classes | |
356 | ####################################################################### | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
357 | |
8300 | 358 | def handleCall(self, method, params): |
359 | """ | |
360 | Public method to handle a method call from the client. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
361 | |
8300 | 362 | Note: This is an empty implementation that must be overridden in |
363 | derived classes. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
364 | |
8300 | 365 | @param method requested method name |
366 | @type str | |
367 | @param params dictionary with method specific parameters | |
368 | @type dict | |
369 | """ | |
370 | pass |