28 Constructor |
29 Constructor |
29 |
30 |
30 @param server reference to the eric-ide server object |
31 @param server reference to the eric-ide server object |
31 @type EricServer |
32 @type EricServer |
32 """ |
33 """ |
33 self.__server = server |
34 super().__init__(server) |
34 |
35 |
35 self.__requestMethodMapping = { |
36 self._category = EricRequestCategory.Debugger |
|
37 |
|
38 self._requestMethodMapping = { |
36 "StartClient": self.__startClient, |
39 "StartClient": self.__startClient, |
37 "StopClient": self.__stopClient, |
40 "StopClient": self.__stopClient, |
38 "DebugClientCommand": self.__relayDebugClientCommand, |
41 "DebugClientCommand": self.__relayDebugClientCommand, |
39 } |
42 } |
40 |
43 |
63 f" {address[0]}, port {address[1]}" |
66 f" {address[0]}, port {address[1]}" |
64 ) |
67 ) |
65 data = types.SimpleNamespace( |
68 data = types.SimpleNamespace( |
66 name="server", acceptHandler=self.__acceptDbgClientConnection |
69 name="server", acceptHandler=self.__acceptDbgClientConnection |
67 ) |
70 ) |
68 self.__server.getSelector().register( |
71 self._server.getSelector().register( |
69 self.__socket, selectors.EVENT_READ, data=data |
72 self.__socket, selectors.EVENT_READ, data=data |
70 ) |
73 ) |
71 |
|
72 def handleRequest(self, request, params, reqestUuid): |
|
73 """ |
|
74 Public method handling the received debugger requests. |
|
75 |
|
76 @param request request name |
|
77 @type str |
|
78 @param params dictionary containing the request parameters |
|
79 @type dict |
|
80 @param reqestUuid UUID of the associated request as sent by the eric IDE |
|
81 @type str |
|
82 """ |
|
83 try: |
|
84 result = self.__requestMethodMapping[request](params) |
|
85 if result: |
|
86 self.__server.sendJson( |
|
87 category=EricRequestCategory.Debugger, |
|
88 reply=request, |
|
89 params=result, |
|
90 reqestUuid=reqestUuid, |
|
91 ) |
|
92 |
|
93 except KeyError: |
|
94 self.__server.sendJson( |
|
95 category=EricRequestCategory.Debugger, |
|
96 reply="DebuggerRequestError", |
|
97 params={"Error": f"Request type '{request}' is not supported."}, |
|
98 ) |
|
99 |
74 |
100 ####################################################################### |
75 ####################################################################### |
101 ## DebugServer like methods. |
76 ## DebugServer like methods. |
102 ####################################################################### |
77 ####################################################################### |
103 |
78 |
117 data = types.SimpleNamespace( |
92 data = types.SimpleNamespace( |
118 name="debug_client", |
93 name="debug_client", |
119 address=address, |
94 address=address, |
120 handler=self.__serviceDbgClientConnection, |
95 handler=self.__serviceDbgClientConnection, |
121 ) |
96 ) |
122 self.__server.getSelector().register( |
97 self._server.getSelector().register(connection, selectors.EVENT_READ, data=data) |
123 connection, selectors.EVENT_READ, data=data |
|
124 ) |
|
125 |
98 |
126 def __serviceDbgClientConnection(self, key): |
99 def __serviceDbgClientConnection(self, key): |
127 """ |
100 """ |
128 Private method to service the debug client connection. |
101 Private method to service the debug client connection. |
129 |
102 |
130 @param key reference to the SelectorKey object associated with the connection |
103 @param key reference to the SelectorKey object associated with the connection |
131 to be serviced |
104 to be serviced |
132 @type selectors.SelectorKey |
105 @type selectors.SelectorKey |
133 """ |
106 """ |
134 sock = key.fileobj |
107 sock = key.fileobj |
135 data = self.__server.receiveJsonCommand(sock) |
108 data = self._server.receiveJsonCommand(sock) |
136 |
109 |
137 if data is None: |
110 if data is None: |
138 # socket was closed by debug client |
111 # socket was closed by debug client |
139 self.__clientSocketDisconnected(sock) |
112 self.__clientSocketDisconnected(sock) |
140 elif data: |
113 elif data: |
153 data["params"]["platform"] += " (eric-ide Server)" |
126 data["params"]["platform"] += " (eric-ide Server)" |
154 |
127 |
155 # 2. pass on the data to the eric-ide |
128 # 2. pass on the data to the eric-ide |
156 jsonStr = json.dumps(data) |
129 jsonStr = json.dumps(data) |
157 # - print("Client Response:", jsonStr) |
130 # - print("Client Response:", jsonStr) |
158 self.__server.sendJson( |
131 self._server.sendJson( |
159 category=EricRequestCategory.Debugger, |
132 category=EricRequestCategory.Debugger, |
160 reply="DebugClientResponse", |
133 reply="DebugClientResponse", |
161 params={"response": jsonStr}, |
134 params={"response": jsonStr}, |
162 ) |
135 ) |
163 |
136 |
164 # 3. process debug client messages after relaying |
137 # 3. process debug client messages after relaying |
165 if method == "ResponseExit": |
138 if method == "ResponseExit": |
166 for sock in list(self.__connections.values()): |
139 for sock in list(self.__connections.values()): |
167 if not self.__server.isSocketClosed(sock): |
140 if not self._server.isSocketClosed(sock): |
168 self.__clientSocketDisconnected(sock) |
141 self.__clientSocketDisconnected(sock) |
169 |
142 |
170 def __clientSocketDisconnected(self, sock): |
143 def __clientSocketDisconnected(self, sock): |
171 """ |
144 """ |
172 Private method handling a socket disconnecting. |
145 Private method handling a socket disconnecting. |
173 |
146 |
174 @param sock reference to the disconnected socket |
147 @param sock reference to the disconnected socket |
175 @type socket.socket |
148 @type socket.socket |
176 """ |
149 """ |
177 self.__server.getSelector().unregister(sock) |
150 self._server.getSelector().unregister(sock) |
178 |
151 |
179 address = sock.getpeername() |
152 address = sock.getpeername() |
180 print( # noqa: M801 |
153 print( # noqa: M801 |
181 f"'Debug Client' connection from {address[0]}, port {address[1]} closed." |
154 f"'Debug Client' connection from {address[0]}, port {address[1]} closed." |
182 ) |
155 ) |
183 |
156 |
184 for debuggerId in list(self.__connections): |
157 for debuggerId in list(self.__connections): |
185 if self.__connections[debuggerId] is sock: |
158 if self.__connections[debuggerId] is sock: |
186 del self.__connections[debuggerId] |
159 del self.__connections[debuggerId] |
187 self.__server.sendJson( |
160 self._server.sendJson( |
188 category=EricRequestCategory.Debugger, |
161 category=EricRequestCategory.Debugger, |
189 reply="DebugClientDisconnected", |
162 reply="DebugClientDisconnected", |
190 params={"debugger_id": debuggerId}, |
163 params={"debugger_id": debuggerId}, |
191 ) |
164 ) |
192 |
165 |
202 |
175 |
203 def __mainClientExited(self): |
176 def __mainClientExited(self): |
204 """ |
177 """ |
205 Private method to handle exiting of the main debug client. |
178 Private method to handle exiting of the main debug client. |
206 """ |
179 """ |
207 self.__server.sendJson( |
180 self._server.sendJson( |
208 category=EricRequestCategory.Debugger, |
181 category=EricRequestCategory.Debugger, |
209 reply="MainClientExited", |
182 reply="MainClientExited", |
210 params={"debugger_id": self.__mainClientId if self.__mainClientId else ""}, |
183 params={"debugger_id": self.__mainClientId if self.__mainClientId else ""}, |
211 ) |
184 ) |
212 |
185 |
219 return |
192 return |
220 |
193 |
221 while self.__pendingConnections: |
194 while self.__pendingConnections: |
222 sock = self.__pendingConnections.pop() |
195 sock = self.__pendingConnections.pop() |
223 commandDict = self.__prepareClientCommand("RequestShutdown", {}) |
196 commandDict = self.__prepareClientCommand("RequestShutdown", {}) |
224 self.__server.sendJsonCommand(commandDict, sock) |
197 self._server.sendJsonCommand(commandDict, sock) |
225 self.__shutdownSocket("", sock) |
198 self.__shutdownSocket("", sock) |
226 |
199 |
227 while self.__connections: |
200 while self.__connections: |
228 debuggerId, sock = self.__connections.popitem() |
201 debuggerId, sock = self.__connections.popitem() |
229 commandDict = self.__prepareClientCommand("RequestShutdown", {}) |
202 commandDict = self.__prepareClientCommand("RequestShutdown", {}) |
230 self.__server.sendJsonCommand(commandDict, sock) |
203 self._server.sendJsonCommand(commandDict, sock) |
231 self.__shutdownSocket(debuggerId, sock) |
204 self.__shutdownSocket(debuggerId, sock) |
232 |
205 |
233 # reinitialize |
206 # reinitialize |
234 self.__mainClientId = None |
207 self.__mainClientId = None |
235 self.__client = None |
208 self.__client = None |
241 @param debuggerId ID of the debugger the socket belongs to |
214 @param debuggerId ID of the debugger the socket belongs to |
242 @type str |
215 @type str |
243 @param sock reference to the socket |
216 @param sock reference to the socket |
244 @type socket.socket |
217 @type socket.socket |
245 """ |
218 """ |
246 self.__server.getSelector().unregister(sock) |
219 self._server.getSelector().unregister(sock) |
247 sock.shutdown(socket.SHUT_RDWR) |
220 sock.shutdown(socket.SHUT_RDWR) |
248 sock.close() |
221 sock.close() |
249 |
222 |
250 if debuggerId: |
223 if debuggerId: |
251 self.__server.sendJson( |
224 self._server.sendJson( |
252 category=EricRequestCategory.Debugger, |
225 category=EricRequestCategory.Debugger, |
253 reply="DebugClientDisconnected", |
226 reply="DebugClientDisconnected", |
254 params={"debugger_id": debuggerId}, |
227 params={"debugger_id": debuggerId}, |
255 ) |
228 ) |
256 |
229 |
295 ) |
268 ) |
296 ) |
269 ) |
297 ipaddr, port = self.__socket.getsockname() |
270 ipaddr, port = self.__socket.getsockname() |
298 args = [ |
271 args = [ |
299 params["interpreter"] if params["interpreter"] else sys.executable, |
272 params["interpreter"] if params["interpreter"] else sys.executable, |
300 debugClient |
273 debugClient, |
301 ] |
274 ] |
302 args.extend(params["arguments"]) |
275 args.extend(params["arguments"]) |
303 args.extend([str(port), "True", ipaddr]) |
276 args.extend([str(port), "True", ipaddr]) |
304 |
277 |
305 workingDir = params["working_dir"] if params["working_dir"] else None |
278 workingDir = params["working_dir"] if params["working_dir"] else None |
344 debuggerId = self.__mainClientId |
317 debuggerId = self.__mainClientId |
345 |
318 |
346 if debuggerId == "<<all>>": |
319 if debuggerId == "<<all>>": |
347 # broadcast to all connected debug clients |
320 # broadcast to all connected debug clients |
348 for sock in self.__connections.values(): |
321 for sock in self.__connections.values(): |
349 self.__server.sendJsonCommand(jsonStr, sock) |
322 self._server.sendJsonCommand(jsonStr, sock) |
350 else: |
323 else: |
351 try: # noqa: Y105 |
324 try: # noqa: Y105 |
352 sock = self.__connections[debuggerId] |
325 sock = self.__connections[debuggerId] |
353 self.__server.sendJsonCommand(jsonStr, sock) |
326 self._server.sendJsonCommand(jsonStr, sock) |
354 except KeyError: |
327 except KeyError: |
355 pass |
328 pass |
356 # - print(f"Command for unknown debugger ID '{debuggerId}' received.") |
329 # - print(f"Command for unknown debugger ID '{debuggerId}' received.") |