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