|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2007 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the debug server. |
|
8 """ |
|
9 |
|
10 from __future__ import unicode_literals |
|
11 try: |
|
12 str = unicode |
|
13 except NameError: |
|
14 pass |
|
15 |
|
16 import os |
|
17 import sys |
|
18 |
|
19 from PyQt5.QtCore import pyqtSignal, QModelIndex |
|
20 from PyQt5.QtNetwork import QTcpServer, QHostAddress, QHostInfo, \ |
|
21 QNetworkInterface |
|
22 |
|
23 from E5Gui.E5Application import e5App |
|
24 from E5Gui import E5MessageBox |
|
25 |
|
26 from .BreakPointModel import BreakPointModel |
|
27 from .WatchPointModel import WatchPointModel |
|
28 from . import DebugClientCapabilities |
|
29 |
|
30 import Preferences |
|
31 import Utilities |
|
32 |
|
33 |
|
34 DebuggerInterfaces = { |
|
35 "Python": "DebuggerInterfacePython", |
|
36 "None": "DebuggerInterfaceNone", |
|
37 } |
|
38 |
|
39 |
|
40 class DebugServer(QTcpServer): |
|
41 """ |
|
42 Class implementing the debug server embedded within the IDE. |
|
43 |
|
44 @signal clientProcessStdout(str) emitted after the client has sent some |
|
45 output via stdout |
|
46 @signal clientProcessStderr(str) emitted after the client has sent some |
|
47 output via stderr |
|
48 @signal clientOutput(str) emitted after the client has sent some output |
|
49 @signal clientRawInputSent() emitted after the data was sent to the |
|
50 debug client |
|
51 @signal clientLine(filename, lineno, forStack) emitted after the |
|
52 debug client has executed a line of code |
|
53 @signal clientStack(stack) emitted after the debug client has executed a |
|
54 line of code |
|
55 @signal clientThreadList(currentId, threadList) emitted after a thread list |
|
56 has been received |
|
57 @signal clientThreadSet() emitted after the client has acknowledged the |
|
58 change of the current thread |
|
59 @signal clientVariables(scope, variables) emitted after a variables dump |
|
60 has been received |
|
61 @signal clientVariable(scope, variables) emitted after a dump for one class |
|
62 variable has been received |
|
63 @signal clientStatement(bool) emitted after an interactive command has |
|
64 been executed. The parameter is 0 to indicate that the command is |
|
65 complete and 1 if it needs more input. |
|
66 @signal clientException(exception) emitted after an exception occured on |
|
67 the client side |
|
68 @signal clientSyntaxError(exception) emitted after a syntax error has been |
|
69 detected on the client side |
|
70 @signal clientSignal(signal) emitted after a signal has been generated on |
|
71 the client side |
|
72 @signal clientExit(int, str, bool) emitted after the client has exited |
|
73 giving the exit status, an exit message and an indication to be quiet |
|
74 @signal clientClearBreak(filename, lineno) emitted after the debug client |
|
75 has decided to clear a temporary breakpoint |
|
76 @signal clientBreakConditionError(fn, lineno) emitted after the client has |
|
77 signaled a syntax error in a breakpoint condition |
|
78 @signal clientClearWatch(condition) emitted after the debug client |
|
79 has decided to clear a temporary watch expression |
|
80 @signal clientWatchConditionError(condition) emitted after the client has |
|
81 signaled a syntax error in a watch expression |
|
82 @signal clientRawInput(prompt, echo) emitted after a raw input request was |
|
83 received |
|
84 @signal clientBanner(version, platform, dbgclient, venvname) emitted after |
|
85 the client banner data was received |
|
86 @signal clientCapabilities(capabilities, cltype, venvname) emitted after |
|
87 the clients capabilities were received |
|
88 @signal clientCompletionList(completionList, text) emitted after the client |
|
89 the commandline completion list and the reworked searchstring was |
|
90 received from the client |
|
91 @signal passiveDebugStarted(str, bool) emitted after the debug client has |
|
92 connected in passive debug mode |
|
93 @signal clientGone(bool) emitted if the client went away (planned or |
|
94 unplanned) |
|
95 @signal clientInterpreterChanged(str) emitted to signal a change of the |
|
96 client interpreter |
|
97 @signal utDiscovered(testCases, exc_type, exc_value) emitted after the |
|
98 client has performed a test case discovery action |
|
99 @signal utPrepared(nrTests, exc_type, exc_value) emitted after the client |
|
100 has loaded a unittest suite |
|
101 @signal utFinished() emitted after the client signalled the end of the |
|
102 unittest |
|
103 @signal utStartTest(testname, testdocu) emitted after the client has |
|
104 started a test |
|
105 @signal utStopTest() emitted after the client has finished a test |
|
106 @signal utTestFailed(testname, exc_info, id) emitted after the client |
|
107 reported a failed test |
|
108 @signal utTestErrored(testname, exc_info, id) emitted after the client |
|
109 reported an errored test |
|
110 @signal utTestSkipped(testname, reason, id) emitted after the client |
|
111 reported a skipped test |
|
112 @signal utTestFailedExpected(testname, exc_info, id) emitted after the |
|
113 client reported an expected test failure |
|
114 @signal utTestSucceededUnexpected(testname, id) emitted after the client |
|
115 reported an unexpected test success |
|
116 @signal callTraceInfo emitted after the client reported the call trace |
|
117 data (isCall, fromFile, fromLine, fromFunction, toFile, toLine, |
|
118 toFunction) |
|
119 @signal appendStdout(msg) emitted when a passive debug connection is |
|
120 established or lost |
|
121 """ |
|
122 clientClearBreak = pyqtSignal(str, int) |
|
123 clientClearWatch = pyqtSignal(str) |
|
124 clientGone = pyqtSignal(bool) |
|
125 clientProcessStdout = pyqtSignal(str) |
|
126 clientProcessStderr = pyqtSignal(str) |
|
127 clientRawInputSent = pyqtSignal() |
|
128 clientOutput = pyqtSignal(str) |
|
129 clientLine = pyqtSignal(str, int, bool) |
|
130 clientStack = pyqtSignal(list) |
|
131 clientThreadList = pyqtSignal('PyQt_PyObject', list) |
|
132 clientThreadSet = pyqtSignal() |
|
133 clientVariables = pyqtSignal(int, list) |
|
134 clientVariable = pyqtSignal(int, list) |
|
135 clientStatement = pyqtSignal(bool) |
|
136 clientException = pyqtSignal(str, str, list) |
|
137 clientSyntaxError = pyqtSignal(str, str, int, int) |
|
138 clientSignal = pyqtSignal(str, str, int, str, str) |
|
139 clientExit = pyqtSignal(int, str, bool) |
|
140 clientBreakConditionError = pyqtSignal(str, int) |
|
141 clientWatchConditionError = pyqtSignal(str) |
|
142 clientRawInput = pyqtSignal(str, bool) |
|
143 clientBanner = pyqtSignal(str, str, str, str) |
|
144 clientCapabilities = pyqtSignal(int, str, str) |
|
145 clientCompletionList = pyqtSignal(list, str) |
|
146 clientInterpreterChanged = pyqtSignal(str) |
|
147 utDiscovered = pyqtSignal(list, str, str) |
|
148 utPrepared = pyqtSignal(int, str, str) |
|
149 utStartTest = pyqtSignal(str, str) |
|
150 utStopTest = pyqtSignal() |
|
151 utTestFailed = pyqtSignal(str, str, str) |
|
152 utTestErrored = pyqtSignal(str, str, str) |
|
153 utTestSkipped = pyqtSignal(str, str, str) |
|
154 utTestFailedExpected = pyqtSignal(str, str, str) |
|
155 utTestSucceededUnexpected = pyqtSignal(str, str) |
|
156 utFinished = pyqtSignal() |
|
157 passiveDebugStarted = pyqtSignal(str, bool) |
|
158 callTraceInfo = pyqtSignal(bool, str, str, str, str, str, str) |
|
159 appendStdout = pyqtSignal(str) |
|
160 |
|
161 def __init__(self, originalPathString, preventPassiveDebugging=False): |
|
162 """ |
|
163 Constructor |
|
164 |
|
165 @param originalPathString original PATH environment variable |
|
166 @type str |
|
167 @param preventPassiveDebugging flag overriding the PassiveDbgEnabled |
|
168 setting |
|
169 @type bool |
|
170 """ |
|
171 super(DebugServer, self).__init__() |
|
172 |
|
173 self.__originalPathString = originalPathString |
|
174 |
|
175 self.__debuggerInterfaces = {} |
|
176 # the interface name is the key, a function to get the |
|
177 # registration data is the value |
|
178 self.__debuggerInterfaceRegistry = {} |
|
179 # the client language is the key, a list containing the client |
|
180 # capabilities, a list of associated file extensions, a |
|
181 # function reference to create the debugger interface (see |
|
182 # __createDebuggerInterface() below) and the interface name is |
|
183 # the value |
|
184 |
|
185 # create our models |
|
186 self.breakpointModel = BreakPointModel(self) |
|
187 self.watchpointModel = WatchPointModel(self) |
|
188 self.watchSpecialCreated = \ |
|
189 self.tr("created", "must be same as in EditWatchpointDialog") |
|
190 self.watchSpecialChanged = \ |
|
191 self.tr("changed", "must be same as in EditWatchpointDialog") |
|
192 |
|
193 self.networkInterface = Preferences.getDebugger("NetworkInterface") |
|
194 if self.networkInterface == "all": |
|
195 hostAddress = QHostAddress("0.0.0.0") # QHostAddress.Any) |
|
196 elif self.networkInterface == "allv6": |
|
197 hostAddress = QHostAddress("::") # QHostAddress.AnyIPv6) |
|
198 else: |
|
199 hostAddress = QHostAddress(self.networkInterface) |
|
200 self.networkInterfaceName, self.networkInterfaceIndex = \ |
|
201 self.__getNetworkInterfaceAndIndex(self.networkInterface) |
|
202 |
|
203 if not preventPassiveDebugging and \ |
|
204 Preferences.getDebugger("PassiveDbgEnabled"): |
|
205 sock = Preferences.getDebugger("PassiveDbgPort") # default: 42424 |
|
206 self.listen(hostAddress, sock) |
|
207 self.passive = True |
|
208 self.passiveClientExited = False |
|
209 else: |
|
210 if hostAddress.toString().lower().startswith("fe80"): |
|
211 hostAddress.setScopeId(self.networkInterfaceName) |
|
212 self.listen(hostAddress) |
|
213 self.passive = False |
|
214 |
|
215 self.debuggerInterface = None |
|
216 self.debugging = False |
|
217 self.running = False |
|
218 self.clientProcess = None |
|
219 self.clientInterpreter = "" |
|
220 self.clientType = \ |
|
221 Preferences.Prefs.settings.value('DebugClient/Type') |
|
222 if self.clientType is None: |
|
223 if sys.version_info[0] == 2: |
|
224 self.clientType = 'Python2' |
|
225 else: |
|
226 self.clientType = 'Python3' |
|
227 # Change clientType if dependent interpreter does not exist anymore |
|
228 # (maybe deinstalled,...) |
|
229 elif self.clientType == 'Python2' and Preferences.getDebugger( |
|
230 "Python2VirtualEnv") == '' and sys.version_info[0] == 3: |
|
231 self.clientType = 'Python3' |
|
232 elif self.clientType == 'Python3' and Preferences.getDebugger( |
|
233 "Python3VirtualEnv") == '' and sys.version_info[0] == 2: |
|
234 self.clientType = 'Python2' |
|
235 |
|
236 self.lastClientType = '' |
|
237 self.__autoClearShell = False |
|
238 self.__forProject = False |
|
239 |
|
240 self.clientClearBreak.connect(self.__clientClearBreakPoint) |
|
241 self.clientClearWatch.connect(self.__clientClearWatchPoint) |
|
242 self.newConnection.connect(self.__newConnection) |
|
243 |
|
244 self.breakpointModel.rowsAboutToBeRemoved.connect( |
|
245 self.__deleteBreakPoints) |
|
246 self.breakpointModel.dataAboutToBeChanged.connect( |
|
247 self.__breakPointDataAboutToBeChanged) |
|
248 self.breakpointModel.dataChanged.connect(self.__changeBreakPoints) |
|
249 self.breakpointModel.rowsInserted.connect(self.__addBreakPoints) |
|
250 |
|
251 self.watchpointModel.rowsAboutToBeRemoved.connect( |
|
252 self.__deleteWatchPoints) |
|
253 self.watchpointModel.dataAboutToBeChanged.connect( |
|
254 self.__watchPointDataAboutToBeChanged) |
|
255 self.watchpointModel.dataChanged.connect(self.__changeWatchPoints) |
|
256 self.watchpointModel.rowsInserted.connect(self.__addWatchPoints) |
|
257 |
|
258 self.__maxVariableSize = Preferences.getDebugger("MaxVariableSize") |
|
259 |
|
260 self.__registerDebuggerInterfaces() |
|
261 |
|
262 def getHostAddress(self, localhost): |
|
263 """ |
|
264 Public method to get the IP address or hostname the debug server is |
|
265 listening. |
|
266 |
|
267 @param localhost flag indicating to return the address for localhost |
|
268 (boolean) |
|
269 @return IP address or hostname (string) |
|
270 """ |
|
271 if self.networkInterface == "all": |
|
272 if localhost: |
|
273 return "127.0.0.1" |
|
274 else: |
|
275 return "{0}@@v4".format(QHostInfo.localHostName()) |
|
276 elif self.networkInterface == "allv6": |
|
277 if localhost: |
|
278 return "::1" |
|
279 else: |
|
280 return "{0}@@v6".format(QHostInfo.localHostName()) |
|
281 else: |
|
282 return "{0}@@i{1}".format(self.networkInterface, |
|
283 self.networkInterfaceIndex) |
|
284 |
|
285 def __getNetworkInterfaceAndIndex(self, address): |
|
286 """ |
|
287 Private method to determine the network interface and the interface |
|
288 index. |
|
289 |
|
290 @param address address to determine the info for (string) |
|
291 @return tuple of network interface name (string) and index (integer) |
|
292 """ |
|
293 if address not in ["all", "allv6"]: |
|
294 for networkInterface in QNetworkInterface.allInterfaces(): |
|
295 addressEntries = networkInterface.addressEntries() |
|
296 if len(addressEntries) > 0: |
|
297 for addressEntry in addressEntries: |
|
298 if addressEntry.ip().toString().lower() == \ |
|
299 address.lower(): |
|
300 return networkInterface.humanReadableName(), \ |
|
301 networkInterface.index() |
|
302 |
|
303 return "", 0 |
|
304 |
|
305 def preferencesChanged(self): |
|
306 """ |
|
307 Public slot to handle the preferencesChanged signal. |
|
308 """ |
|
309 registeredInterfaces = {} |
|
310 for interfaceName in self.__debuggerInterfaces: |
|
311 registeredInterfaces[interfaceName] = \ |
|
312 self.__debuggerInterfaces[interfaceName] |
|
313 |
|
314 self.__debuggerInterfaceRegistry = {} |
|
315 for interfaceName, getRegistryData in registeredInterfaces.items(): |
|
316 self.registerDebuggerInterface(interfaceName, getRegistryData, |
|
317 reregister=True) |
|
318 |
|
319 self.__maxVariableSize = Preferences.getDebugger("MaxVariableSize") |
|
320 |
|
321 def registerDebuggerInterface(self, interfaceName, getRegistryData, |
|
322 reregister=False): |
|
323 """ |
|
324 Public method to register a debugger interface. |
|
325 |
|
326 @param interfaceName name of the debugger interface |
|
327 @type str |
|
328 @param getRegistryData reference to a function to be called |
|
329 to get the debugger interface details. This method shall |
|
330 return the client language, the client capabilities, the |
|
331 list of associated file extensions and a function reference |
|
332 to create the debugger interface (see __createDebuggerInterface()) |
|
333 @type function |
|
334 @param reregister flag indicating to re-register the interface |
|
335 @type bool |
|
336 """ |
|
337 if interfaceName in self.__debuggerInterfaces and not reregister: |
|
338 E5MessageBox.warning( |
|
339 None, |
|
340 self.tr("Register Debugger Interface"), |
|
341 self.tr("""<p>The debugger interface <b>{0}</b> has already""" |
|
342 """ been registered. Ignoring this request.</p>""")) |
|
343 return |
|
344 |
|
345 if not reregister: |
|
346 self.__debuggerInterfaces[interfaceName] = getRegistryData |
|
347 registryDataList = getRegistryData() |
|
348 if registryDataList: |
|
349 for clientLanguage, clientCapabilities, clientExtensions, \ |
|
350 interfaceCreator in registryDataList: |
|
351 self.__debuggerInterfaceRegistry[clientLanguage] = [ |
|
352 clientCapabilities, clientExtensions, interfaceCreator, |
|
353 interfaceName] |
|
354 |
|
355 def unregisterDebuggerInterface(self, interfaceName): |
|
356 """ |
|
357 Public method to unregister a debugger interface. |
|
358 |
|
359 @param interfaceName interfaceName of the debugger interface |
|
360 @type str |
|
361 """ |
|
362 if interfaceName in self.__debuggerInterfaces: |
|
363 clientLanguages = [] |
|
364 for clientLanguage, registryData in \ |
|
365 self.__debuggerInterfaceRegistry.items(): |
|
366 if interfaceName == registryData[-1]: |
|
367 clientLanguages.append(clientLanguage) |
|
368 for clientLanguage in clientLanguages: |
|
369 del self.__debuggerInterfaceRegistry[clientLanguage] |
|
370 del self.__debuggerInterfaces[interfaceName] |
|
371 |
|
372 def __findLanguageForExtension(self, ext): |
|
373 """ |
|
374 Private method to get the language associated with a file extension. |
|
375 |
|
376 @param ext file extension |
|
377 @type str |
|
378 @return associated language |
|
379 @rtype str |
|
380 """ |
|
381 for language in self.__debuggerInterfaceRegistry: |
|
382 if ext in self.__debuggerInterfaceRegistry[language][1]: |
|
383 return language |
|
384 |
|
385 return "" |
|
386 |
|
387 def __registerDebuggerInterfaces(self): |
|
388 """ |
|
389 Private method to register the available internal debugger interfaces. |
|
390 """ |
|
391 for name, interface in DebuggerInterfaces.items(): |
|
392 modName = "Debugger.{0}".format(interface) |
|
393 mod = __import__(modName) |
|
394 components = modName.split('.') |
|
395 for comp in components[1:]: |
|
396 mod = getattr(mod, comp) |
|
397 |
|
398 self.registerDebuggerInterface(name, mod.getRegistryData) |
|
399 |
|
400 def getSupportedLanguages(self, shellOnly=False): |
|
401 """ |
|
402 Public slot to return the supported programming languages. |
|
403 |
|
404 @param shellOnly flag indicating only languages supporting an |
|
405 interactive shell should be returned |
|
406 @return list of supported languages (list of strings) |
|
407 """ |
|
408 languages = list(self.__debuggerInterfaceRegistry.keys()) |
|
409 try: |
|
410 languages.remove("None") |
|
411 except ValueError: |
|
412 pass # it is not in the list |
|
413 |
|
414 if shellOnly: |
|
415 languages = \ |
|
416 [lang for lang in languages |
|
417 if self.__debuggerInterfaceRegistry[lang][0] & |
|
418 DebugClientCapabilities.HasShell] |
|
419 |
|
420 return languages[:] |
|
421 |
|
422 def getExtensions(self, language): |
|
423 """ |
|
424 Public slot to get the extensions associated with the given language. |
|
425 |
|
426 @param language language to get extensions for (string) |
|
427 @return tuple of extensions associated with the language |
|
428 (tuple of strings) |
|
429 """ |
|
430 if language in self.__debuggerInterfaceRegistry: |
|
431 return tuple(self.__debuggerInterfaceRegistry[language][1]) |
|
432 else: |
|
433 return tuple() |
|
434 |
|
435 def __createDebuggerInterface(self, clientType=None): |
|
436 """ |
|
437 Private slot to create the debugger interface object. |
|
438 |
|
439 @param clientType type of the client interface to be created (string) |
|
440 """ |
|
441 if self.lastClientType != self.clientType or clientType is not None: |
|
442 if clientType is None: |
|
443 clientType = self.clientType |
|
444 if clientType in self.__debuggerInterfaceRegistry: |
|
445 self.debuggerInterface = \ |
|
446 self.__debuggerInterfaceRegistry[clientType][2]( |
|
447 self, self.passive) |
|
448 else: |
|
449 self.debuggerInterface = \ |
|
450 self.__debuggerInterfaceRegistry["None"][2]( |
|
451 self, self.passive) |
|
452 self.clientType = "None" |
|
453 |
|
454 def __setClientType(self, clType): |
|
455 """ |
|
456 Private method to set the client type. |
|
457 |
|
458 @param clType type of client to be started (string) |
|
459 """ |
|
460 if clType is not None and clType in self.getSupportedLanguages(): |
|
461 self.clientType = clType |
|
462 Preferences.Prefs.settings.setValue( |
|
463 'DebugClient/Type', self.clientType) |
|
464 |
|
465 def startClient(self, unplanned=True, clType=None, forProject=False, |
|
466 runInConsole=False, venvName="", workingDir=None): |
|
467 """ |
|
468 Public method to start a debug client. |
|
469 |
|
470 @keyparam unplanned flag indicating that the client has died |
|
471 @type bool |
|
472 @keyparam clType type of client to be started |
|
473 @type str |
|
474 @keyparam forProject flag indicating a project related action |
|
475 @type bool |
|
476 @keyparam runInConsole flag indicating to start the debugger in a |
|
477 console window |
|
478 @type bool |
|
479 @keyparam venvName name of the virtual environment to be used |
|
480 @type str |
|
481 @keyparam workingDir directory to start the debugger client in |
|
482 @type str |
|
483 """ |
|
484 self.running = False |
|
485 |
|
486 if not self.passive or not self.passiveClientExited: |
|
487 if self.debuggerInterface and self.debuggerInterface.isConnected(): |
|
488 self.shutdownServer() |
|
489 self.debugging = False |
|
490 self.clientGone.emit(unplanned and self.debugging) |
|
491 |
|
492 if clType: |
|
493 if clType not in self.getSupportedLanguages(): |
|
494 # a not supported client language was requested |
|
495 return |
|
496 |
|
497 self.__setClientType(clType) |
|
498 |
|
499 # only start the client, if we are not in passive mode |
|
500 if not self.passive: |
|
501 if self.clientProcess: |
|
502 self.clientProcess.kill() |
|
503 self.clientProcess.waitForFinished(1000) |
|
504 self.clientProcess.deleteLater() |
|
505 self.clientProcess = None |
|
506 |
|
507 self.__forProject = forProject |
|
508 self.__createDebuggerInterface() |
|
509 if forProject: |
|
510 project = e5App().getObject("Project") |
|
511 if not project.isDebugPropertiesLoaded(): |
|
512 self.clientProcess, isNetworked, clientInterpreter = \ |
|
513 self.debuggerInterface.startRemote( |
|
514 self.serverPort(), runInConsole, venvName, |
|
515 self.__originalPathString, workingDir=workingDir) |
|
516 else: |
|
517 self.clientProcess, isNetworked, clientInterpreter = \ |
|
518 self.debuggerInterface.startRemoteForProject( |
|
519 self.serverPort(), runInConsole, venvName, |
|
520 self.__originalPathString, workingDir=workingDir) |
|
521 else: |
|
522 self.clientProcess, isNetworked, clientInterpreter = \ |
|
523 self.debuggerInterface.startRemote( |
|
524 self.serverPort(), runInConsole, venvName, |
|
525 self.__originalPathString, workingDir=workingDir) |
|
526 |
|
527 if self.clientProcess: |
|
528 self.clientProcess.readyReadStandardError.connect( |
|
529 self.__clientProcessError) |
|
530 self.clientProcess.readyReadStandardOutput.connect( |
|
531 self.__clientProcessOutput) |
|
532 |
|
533 # Perform actions necessary, if client type has changed |
|
534 if self.lastClientType != self.clientType: |
|
535 self.lastClientType = self.clientType |
|
536 self.remoteBanner() |
|
537 elif self.__autoClearShell: |
|
538 self.__autoClearShell = False |
|
539 self.remoteBanner() |
|
540 ## self.remoteClientVariables(0, [], 0) |
|
541 ## self.remoteClientVariables(1, [], 0) |
|
542 else: |
|
543 if clType and self.lastClientType: |
|
544 self.__setClientType(self.lastClientType) |
|
545 else: |
|
546 self.__createDebuggerInterface("None") |
|
547 clientInterpreter = "" |
|
548 |
|
549 if clientInterpreter != self.clientInterpreter: |
|
550 self.clientInterpreter = clientInterpreter |
|
551 self.clientInterpreterChanged.emit(clientInterpreter) |
|
552 |
|
553 def __clientProcessOutput(self): |
|
554 """ |
|
555 Private slot to process client output received via stdout. |
|
556 """ |
|
557 output = str(self.clientProcess.readAllStandardOutput(), |
|
558 Preferences.getSystem("IOEncoding"), |
|
559 'replace') |
|
560 self.clientProcessStdout.emit(output) |
|
561 |
|
562 def __clientProcessError(self): |
|
563 """ |
|
564 Private slot to process client output received via stderr. |
|
565 """ |
|
566 error = str(self.clientProcess.readAllStandardError(), |
|
567 Preferences.getSystem("IOEncoding"), |
|
568 'replace') |
|
569 self.clientProcessStderr.emit(error) |
|
570 |
|
571 def __clientClearBreakPoint(self, fn, lineno): |
|
572 """ |
|
573 Private slot to handle the clientClearBreak signal. |
|
574 |
|
575 @param fn filename of breakpoint to clear (string) |
|
576 @param lineno line number of breakpoint to clear (integer) |
|
577 """ |
|
578 if self.debugging: |
|
579 index = self.breakpointModel.getBreakPointIndex(fn, lineno) |
|
580 self.breakpointModel.deleteBreakPointByIndex(index) |
|
581 |
|
582 def __deleteBreakPoints(self, parentIndex, start, end): |
|
583 """ |
|
584 Private slot to delete breakpoints. |
|
585 |
|
586 @param parentIndex index of parent item (QModelIndex) |
|
587 @param start start row (integer) |
|
588 @param end end row (integer) |
|
589 """ |
|
590 if self.debugging: |
|
591 for row in range(start, end + 1): |
|
592 index = self.breakpointModel.index(row, 0, parentIndex) |
|
593 fn, lineno = \ |
|
594 self.breakpointModel.getBreakPointByIndex(index)[0:2] |
|
595 self.remoteBreakpoint(fn, lineno, False) |
|
596 |
|
597 def __changeBreakPoints(self, startIndex, endIndex): |
|
598 """ |
|
599 Private slot to set changed breakpoints. |
|
600 |
|
601 @param startIndex starting index of the change breakpoins (QModelIndex) |
|
602 @param endIndex ending index of the change breakpoins (QModelIndex) |
|
603 """ |
|
604 if self.debugging: |
|
605 self.__addBreakPoints( |
|
606 QModelIndex(), startIndex.row(), endIndex.row()) |
|
607 |
|
608 def __breakPointDataAboutToBeChanged(self, startIndex, endIndex): |
|
609 """ |
|
610 Private slot to handle the dataAboutToBeChanged signal of the |
|
611 breakpoint model. |
|
612 |
|
613 @param startIndex start index of the rows to be changed (QModelIndex) |
|
614 @param endIndex end index of the rows to be changed (QModelIndex) |
|
615 """ |
|
616 if self.debugging: |
|
617 self.__deleteBreakPoints( |
|
618 QModelIndex(), startIndex.row(), endIndex.row()) |
|
619 |
|
620 def __addBreakPoints(self, parentIndex, start, end): |
|
621 """ |
|
622 Private slot to add breakpoints. |
|
623 |
|
624 @param parentIndex index of parent item (QModelIndex) |
|
625 @param start start row (integer) |
|
626 @param end end row (integer) |
|
627 """ |
|
628 if self.debugging: |
|
629 for row in range(start, end + 1): |
|
630 index = self.breakpointModel.index(row, 0, parentIndex) |
|
631 fn, line, cond, temp, enabled, ignorecount = \ |
|
632 self.breakpointModel.getBreakPointByIndex(index)[:6] |
|
633 self.remoteBreakpoint(fn, line, True, cond, temp) |
|
634 if not enabled: |
|
635 self.__remoteBreakpointEnable(fn, line, False) |
|
636 if ignorecount: |
|
637 self.__remoteBreakpointIgnore(fn, line, ignorecount) |
|
638 |
|
639 def __makeWatchCondition(self, cond, special): |
|
640 """ |
|
641 Private method to construct the condition string. |
|
642 |
|
643 @param cond condition (string) |
|
644 @param special special condition (string) |
|
645 @return condition string (string) |
|
646 """ |
|
647 if special == "": |
|
648 _cond = cond |
|
649 else: |
|
650 if special == self.watchSpecialCreated: |
|
651 _cond = "{0} ??created??".format(cond) |
|
652 elif special == self.watchSpecialChanged: |
|
653 _cond = "{0} ??changed??".format(cond) |
|
654 return _cond |
|
655 |
|
656 def __splitWatchCondition(self, cond): |
|
657 """ |
|
658 Private method to split a remote watch expression. |
|
659 |
|
660 @param cond remote expression (string) |
|
661 @return tuple of local expression (string) and special condition |
|
662 (string) |
|
663 """ |
|
664 if cond.endswith(" ??created??"): |
|
665 cond, special = cond.split() |
|
666 special = self.watchSpecialCreated |
|
667 elif cond.endswith(" ??changed??"): |
|
668 cond, special = cond.split() |
|
669 special = self.watchSpecialChanged |
|
670 else: |
|
671 cond = cond |
|
672 special = "" |
|
673 |
|
674 return cond, special |
|
675 |
|
676 def __clientClearWatchPoint(self, condition): |
|
677 """ |
|
678 Private slot to handle the clientClearWatch signal. |
|
679 |
|
680 @param condition expression of watch expression to clear (string) |
|
681 """ |
|
682 if self.debugging: |
|
683 cond, special = self.__splitWatchCondition(condition) |
|
684 index = self.watchpointModel.getWatchPointIndex(cond, special) |
|
685 self.watchpointModel.deleteWatchPointByIndex(index) |
|
686 |
|
687 def __deleteWatchPoints(self, parentIndex, start, end): |
|
688 """ |
|
689 Private slot to delete watch expressions. |
|
690 |
|
691 @param parentIndex index of parent item (QModelIndex) |
|
692 @param start start row (integer) |
|
693 @param end end row (integer) |
|
694 """ |
|
695 if self.debugging: |
|
696 for row in range(start, end + 1): |
|
697 index = self.watchpointModel.index(row, 0, parentIndex) |
|
698 cond, special = \ |
|
699 self.watchpointModel.getWatchPointByIndex(index)[0:2] |
|
700 cond = self.__makeWatchCondition(cond, special) |
|
701 self.__remoteWatchpoint(cond, False) |
|
702 |
|
703 def __watchPointDataAboutToBeChanged(self, startIndex, endIndex): |
|
704 """ |
|
705 Private slot to handle the dataAboutToBeChanged signal of the |
|
706 watch expression model. |
|
707 |
|
708 @param startIndex start index of the rows to be changed (QModelIndex) |
|
709 @param endIndex end index of the rows to be changed (QModelIndex) |
|
710 """ |
|
711 if self.debugging: |
|
712 self.__deleteWatchPoints( |
|
713 QModelIndex(), startIndex.row(), endIndex.row()) |
|
714 |
|
715 def __addWatchPoints(self, parentIndex, start, end): |
|
716 """ |
|
717 Private slot to set a watch expression. |
|
718 |
|
719 @param parentIndex index of parent item (QModelIndex) |
|
720 @param start start row (integer) |
|
721 @param end end row (integer) |
|
722 """ |
|
723 if self.debugging: |
|
724 for row in range(start, end + 1): |
|
725 index = self.watchpointModel.index(row, 0, parentIndex) |
|
726 cond, special, temp, enabled, ignorecount = \ |
|
727 self.watchpointModel.getWatchPointByIndex(index)[:5] |
|
728 cond = self.__makeWatchCondition(cond, special) |
|
729 self.__remoteWatchpoint(cond, True, temp) |
|
730 if not enabled: |
|
731 self.__remoteWatchpointEnable(cond, False) |
|
732 if ignorecount: |
|
733 self.__remoteWatchpointIgnore(cond, ignorecount) |
|
734 |
|
735 def __changeWatchPoints(self, startIndex, endIndex): |
|
736 """ |
|
737 Private slot to set changed watch expressions. |
|
738 |
|
739 @param startIndex start index of the rows to be changed (QModelIndex) |
|
740 @param endIndex end index of the rows to be changed (QModelIndex) |
|
741 """ |
|
742 if self.debugging: |
|
743 self.__addWatchPoints( |
|
744 QModelIndex(), startIndex.row(), endIndex.row()) |
|
745 |
|
746 def getClientCapabilities(self, clientType): |
|
747 """ |
|
748 Public method to retrieve the debug clients capabilities. |
|
749 |
|
750 @param clientType debug client type (string) |
|
751 @return debug client capabilities (integer) |
|
752 """ |
|
753 try: |
|
754 return self.__debuggerInterfaceRegistry[clientType][0] |
|
755 except KeyError: |
|
756 return 0 # no capabilities |
|
757 |
|
758 def getClientInterpreter(self): |
|
759 """ |
|
760 Public method to get the interpreter of the debug client. |
|
761 |
|
762 @return interpreter of the debug client (string) |
|
763 """ |
|
764 return self.clientInterpreter |
|
765 |
|
766 def getClientType(self): |
|
767 """ |
|
768 Public method to get the currently running debug client type. |
|
769 |
|
770 @return debug client type |
|
771 @rtype str |
|
772 """ |
|
773 return self.clientType |
|
774 |
|
775 def isClientProcessUp(self): |
|
776 """ |
|
777 Public method to check, if the debug client process is up. |
|
778 |
|
779 @return flag indicating a running debug client process |
|
780 @rtype bool |
|
781 """ |
|
782 return self.clientProcess is not None |
|
783 |
|
784 def __newConnection(self): |
|
785 """ |
|
786 Private slot to handle a new connection. |
|
787 """ |
|
788 sock = self.nextPendingConnection() |
|
789 peerAddress = sock.peerAddress().toString() |
|
790 if peerAddress not in Preferences.getDebugger("AllowedHosts"): |
|
791 # the peer is not allowed to connect |
|
792 res = E5MessageBox.yesNo( |
|
793 None, |
|
794 self.tr("Connection from illegal host"), |
|
795 self.tr( |
|
796 """<p>A connection was attempted by the illegal host""" |
|
797 """ <b>{0}</b>. Accept this connection?</p>""") |
|
798 .format(peerAddress), |
|
799 icon=E5MessageBox.Warning) |
|
800 if not res: |
|
801 sock.abort() |
|
802 return |
|
803 else: |
|
804 allowedHosts = Preferences.getDebugger("AllowedHosts") |
|
805 allowedHosts.append(peerAddress) |
|
806 Preferences.setDebugger("AllowedHosts", allowedHosts) |
|
807 |
|
808 if self.passive: |
|
809 self.__createDebuggerInterface( |
|
810 Preferences.getDebugger("PassiveDbgType")) |
|
811 |
|
812 accepted = self.debuggerInterface.newConnection(sock) |
|
813 if accepted: |
|
814 # Perform actions necessary, if client type has changed |
|
815 if self.lastClientType != self.clientType: |
|
816 self.lastClientType = self.clientType |
|
817 self.remoteBanner() |
|
818 elif self.__autoClearShell: |
|
819 self.__autoClearShell = False |
|
820 self.remoteBanner() |
|
821 elif self.passive: |
|
822 self.remoteBanner() |
|
823 |
|
824 self.debuggerInterface.flush() |
|
825 |
|
826 def shutdownServer(self): |
|
827 """ |
|
828 Public method to cleanly shut down. |
|
829 |
|
830 It closes our socket and shuts down |
|
831 the debug client. (Needed on Win OS) |
|
832 """ |
|
833 if self.debuggerInterface is not None: |
|
834 self.debuggerInterface.shutdown() |
|
835 |
|
836 def remoteEnvironment(self, env): |
|
837 """ |
|
838 Public method to set the environment for a program to debug, run, ... |
|
839 |
|
840 @param env environment settings (string) |
|
841 """ |
|
842 envlist = Utilities.parseEnvironmentString(env) |
|
843 envdict = {} |
|
844 for el in envlist: |
|
845 try: |
|
846 key, value = el.split('=', 1) |
|
847 if value.startswith('"') or value.startswith("'"): |
|
848 value = value[1:-1] |
|
849 envdict[key] = value |
|
850 except ValueError: |
|
851 pass |
|
852 self.debuggerInterface.remoteEnvironment(envdict) |
|
853 |
|
854 def remoteLoad(self, venvName, fn, argv, wd, env, autoClearShell=True, |
|
855 tracePython=False, autoContinue=True, forProject=False, |
|
856 runInConsole=False, autoFork=False, forkChild=False, |
|
857 clientType="", enableCallTrace=False): |
|
858 """ |
|
859 Public method to load a new program to debug. |
|
860 |
|
861 @param venvName name of the virtual environment to be used |
|
862 @type str |
|
863 @param fn the filename to debug |
|
864 @type str |
|
865 @param argv the command line arguments to pass to the program |
|
866 @type str |
|
867 @param wd the working directory for the program |
|
868 @type str |
|
869 @param env environment parameter settings |
|
870 @type str |
|
871 @keyparam autoClearShell flag indicating, that the interpreter window |
|
872 should be cleared |
|
873 @type bool |
|
874 @keyparam tracePython flag indicating if the Python library should be |
|
875 traced as well |
|
876 @type bool |
|
877 @keyparam autoContinue flag indicating, that the debugger should not |
|
878 stop at the first executable line |
|
879 @type bool |
|
880 @keyparam forProject flag indicating a project related action |
|
881 @type bool |
|
882 @keyparam runInConsole flag indicating to start the debugger in a |
|
883 console window |
|
884 @type bool |
|
885 @keyparam autoFork flag indicating the automatic fork mode |
|
886 @type bool |
|
887 @keyparam forkChild flag indicating to debug the child after forking |
|
888 @type bool |
|
889 @keyparam clientType client type to be used |
|
890 @type str |
|
891 @keyparam enableCallTrace flag indicating to enable the call trace |
|
892 function |
|
893 @type bool |
|
894 """ |
|
895 self.__autoClearShell = autoClearShell |
|
896 self.__autoContinue = autoContinue |
|
897 |
|
898 if clientType not in self.getSupportedLanguages(): |
|
899 # a not supported client language was requested |
|
900 E5MessageBox.critical( |
|
901 None, |
|
902 self.tr("Start Debugger"), |
|
903 self.tr( |
|
904 """<p>The debugger type <b>{0}</b> is not supported""" |
|
905 """ or not configured.</p>""").format(clientType) |
|
906 ) |
|
907 return |
|
908 |
|
909 # Restart the client |
|
910 try: |
|
911 if clientType: |
|
912 self.__setClientType(clientType) |
|
913 else: |
|
914 self.__setClientType( |
|
915 self.__findLanguageForExtension(os.path.splitext(fn)[1])) |
|
916 except KeyError: |
|
917 self.__setClientType('Python3') # assume it is a Python3 file |
|
918 self.startClient(False, forProject=forProject, |
|
919 runInConsole=runInConsole, venvName=venvName) |
|
920 |
|
921 self.setCallTraceEnabled(enableCallTrace) |
|
922 self.remoteEnvironment(env) |
|
923 |
|
924 self.debuggerInterface.remoteLoad(fn, argv, wd, tracePython, |
|
925 autoContinue, autoFork, forkChild) |
|
926 self.debugging = True |
|
927 self.running = True |
|
928 self.__restoreBreakpoints() |
|
929 self.__restoreWatchpoints() |
|
930 |
|
931 def remoteRun(self, venvName, fn, argv, wd, env, autoClearShell=True, |
|
932 forProject=False, runInConsole=False, autoFork=False, |
|
933 forkChild=False, clientType=""): |
|
934 """ |
|
935 Public method to load a new program to run. |
|
936 |
|
937 @param venvName name of the virtual environment to be used |
|
938 @type str |
|
939 @param fn the filename to debug |
|
940 @type str |
|
941 @param argv the command line arguments to pass to the program |
|
942 @type str |
|
943 @param wd the working directory for the program |
|
944 @type str |
|
945 @param env environment parameter settings |
|
946 @type str |
|
947 @keyparam autoClearShell flag indicating, that the interpreter window |
|
948 should be cleared |
|
949 @type bool |
|
950 @keyparam forProject flag indicating a project related action |
|
951 @type bool |
|
952 @keyparam runInConsole flag indicating to start the debugger in a |
|
953 console window |
|
954 @type bool |
|
955 @keyparam autoFork flag indicating the automatic fork mode |
|
956 @type bool |
|
957 @keyparam forkChild flag indicating to debug the child after forking |
|
958 @type bool |
|
959 @keyparam clientType client type to be used |
|
960 @type str |
|
961 """ |
|
962 self.__autoClearShell = autoClearShell |
|
963 |
|
964 if clientType not in self.getSupportedLanguages(): |
|
965 E5MessageBox.critical( |
|
966 None, |
|
967 self.tr("Start Debugger"), |
|
968 self.tr( |
|
969 """<p>The debugger type <b>{0}</b> is not supported""" |
|
970 """ or not configured.</p>""").format(clientType) |
|
971 ) |
|
972 # a not supported client language was requested |
|
973 return |
|
974 |
|
975 # Restart the client |
|
976 try: |
|
977 if clientType: |
|
978 self.__setClientType(clientType) |
|
979 else: |
|
980 self.__setClientType( |
|
981 self.__findLanguageForExtension(os.path.splitext(fn)[1])) |
|
982 except KeyError: |
|
983 self.__setClientType('Python3') # assume it is a Python3 file |
|
984 self.startClient(False, forProject=forProject, |
|
985 runInConsole=runInConsole, venvName=venvName) |
|
986 |
|
987 self.remoteEnvironment(env) |
|
988 |
|
989 self.debuggerInterface.remoteRun(fn, argv, wd, autoFork, forkChild) |
|
990 self.debugging = False |
|
991 self.running = True |
|
992 |
|
993 def remoteCoverage(self, venvName, fn, argv, wd, env, |
|
994 autoClearShell=True, erase=False, forProject=False, |
|
995 runInConsole=False, clientType=""): |
|
996 """ |
|
997 Public method to load a new program to collect coverage data. |
|
998 |
|
999 @param venvName name of the virtual environment to be used |
|
1000 @type str |
|
1001 @param fn the filename to debug |
|
1002 @type str |
|
1003 @param argv the command line arguments to pass to the program |
|
1004 @type str |
|
1005 @param wd the working directory for the program |
|
1006 @type str |
|
1007 @param env environment parameter settings |
|
1008 @type str |
|
1009 @keyparam autoClearShell flag indicating, that the interpreter window |
|
1010 should be cleared |
|
1011 @type bool |
|
1012 @keyparam erase flag indicating that coverage info should be |
|
1013 cleared first |
|
1014 @type bool |
|
1015 @keyparam forProject flag indicating a project related action |
|
1016 @type bool |
|
1017 @keyparam runInConsole flag indicating to start the debugger in a |
|
1018 console window |
|
1019 @type bool |
|
1020 @keyparam clientType client type to be used |
|
1021 @type str |
|
1022 """ |
|
1023 self.__autoClearShell = autoClearShell |
|
1024 |
|
1025 if clientType not in self.getSupportedLanguages(): |
|
1026 # a not supported client language was requested |
|
1027 E5MessageBox.critical( |
|
1028 None, |
|
1029 self.tr("Start Debugger"), |
|
1030 self.tr( |
|
1031 """<p>The debugger type <b>{0}</b> is not supported""" |
|
1032 """ or not configured.</p>""").format(clientType) |
|
1033 ) |
|
1034 return |
|
1035 |
|
1036 # Restart the client |
|
1037 try: |
|
1038 if clientType: |
|
1039 self.__setClientType(clientType) |
|
1040 else: |
|
1041 self.__setClientType( |
|
1042 self.__findLanguageForExtension(os.path.splitext(fn)[1])) |
|
1043 except KeyError: |
|
1044 self.__setClientType('Python3') # assume it is a Python3 file |
|
1045 self.startClient(False, forProject=forProject, |
|
1046 runInConsole=runInConsole, venvName=venvName) |
|
1047 |
|
1048 self.remoteEnvironment(env) |
|
1049 |
|
1050 self.debuggerInterface.remoteCoverage(fn, argv, wd, erase) |
|
1051 self.debugging = False |
|
1052 self.running = True |
|
1053 |
|
1054 def remoteProfile(self, venvName, fn, argv, wd, env, |
|
1055 autoClearShell=True, erase=False, forProject=False, |
|
1056 runInConsole=False, clientType=""): |
|
1057 """ |
|
1058 Public method to load a new program to collect profiling data. |
|
1059 |
|
1060 @param venvName name of the virtual environment to be used |
|
1061 @type str |
|
1062 @param fn the filename to debug |
|
1063 @type str |
|
1064 @param argv the command line arguments to pass to the program |
|
1065 @type str |
|
1066 @param wd the working directory for the program |
|
1067 @type str |
|
1068 @param env environment parameter settings |
|
1069 @type str |
|
1070 @keyparam autoClearShell flag indicating, that the interpreter window |
|
1071 should be cleared |
|
1072 @type bool |
|
1073 @keyparam erase flag indicating that coverage info should be |
|
1074 cleared first |
|
1075 @type bool |
|
1076 @keyparam forProject flag indicating a project related action |
|
1077 @type bool |
|
1078 @keyparam runInConsole flag indicating to start the debugger in a |
|
1079 console window |
|
1080 @type bool |
|
1081 @keyparam clientType client type to be used |
|
1082 @type str |
|
1083 """ |
|
1084 self.__autoClearShell = autoClearShell |
|
1085 |
|
1086 if clientType not in self.getSupportedLanguages(): |
|
1087 # a not supported client language was requested |
|
1088 E5MessageBox.critical( |
|
1089 None, |
|
1090 self.tr("Start Debugger"), |
|
1091 self.tr( |
|
1092 """<p>The debugger type <b>{0}</b> is not supported""" |
|
1093 """ or not configured.</p>""").format(clientType) |
|
1094 ) |
|
1095 return |
|
1096 |
|
1097 # Restart the client |
|
1098 try: |
|
1099 if clientType: |
|
1100 self.__setClientType(clientType) |
|
1101 else: |
|
1102 self.__setClientType( |
|
1103 self.__findLanguageForExtension(os.path.splitext(fn)[1])) |
|
1104 except KeyError: |
|
1105 self.__setClientType('Python3') # assume it is a Python3 file |
|
1106 self.startClient(False, forProject=forProject, |
|
1107 runInConsole=runInConsole, venvName=venvName) |
|
1108 |
|
1109 self.remoteEnvironment(env) |
|
1110 |
|
1111 self.debuggerInterface.remoteProfile(fn, argv, wd, erase) |
|
1112 self.debugging = False |
|
1113 self.running = True |
|
1114 |
|
1115 def remoteStatement(self, stmt): |
|
1116 """ |
|
1117 Public method to execute a Python statement. |
|
1118 |
|
1119 @param stmt the Python statement to execute (string). It |
|
1120 should not have a trailing newline. |
|
1121 """ |
|
1122 self.debuggerInterface.remoteStatement(stmt) |
|
1123 |
|
1124 def remoteStep(self): |
|
1125 """ |
|
1126 Public method to single step the debugged program. |
|
1127 """ |
|
1128 self.debuggerInterface.remoteStep() |
|
1129 |
|
1130 def remoteStepOver(self): |
|
1131 """ |
|
1132 Public method to step over the debugged program. |
|
1133 """ |
|
1134 self.debuggerInterface.remoteStepOver() |
|
1135 |
|
1136 def remoteStepOut(self): |
|
1137 """ |
|
1138 Public method to step out the debugged program. |
|
1139 """ |
|
1140 self.debuggerInterface.remoteStepOut() |
|
1141 |
|
1142 def remoteStepQuit(self): |
|
1143 """ |
|
1144 Public method to stop the debugged program. |
|
1145 """ |
|
1146 self.debuggerInterface.remoteStepQuit() |
|
1147 |
|
1148 def remoteContinue(self, special=False): |
|
1149 """ |
|
1150 Public method to continue the debugged program. |
|
1151 |
|
1152 @param special flag indicating a special continue operation |
|
1153 """ |
|
1154 self.debuggerInterface.remoteContinue(special) |
|
1155 |
|
1156 def remoteMoveIP(self, line): |
|
1157 """ |
|
1158 Public method to move the instruction pointer to a different line. |
|
1159 |
|
1160 @param line the new line, where execution should be continued |
|
1161 """ |
|
1162 self.debuggerInterface.remoteMoveIP(line) |
|
1163 |
|
1164 def remoteBreakpoint(self, fn, line, setBreakpoint, cond=None, temp=False): |
|
1165 """ |
|
1166 Public method to set or clear a breakpoint. |
|
1167 |
|
1168 @param fn filename the breakpoint belongs to (string) |
|
1169 @param line linenumber of the breakpoint (int) |
|
1170 @param setBreakpoint flag indicating setting or resetting a breakpoint |
|
1171 (boolean) |
|
1172 @param cond condition of the breakpoint (string) |
|
1173 @param temp flag indicating a temporary breakpoint (boolean) |
|
1174 """ |
|
1175 self.debuggerInterface.remoteBreakpoint(fn, line, setBreakpoint, cond, |
|
1176 temp) |
|
1177 |
|
1178 def __remoteBreakpointEnable(self, fn, line, enable): |
|
1179 """ |
|
1180 Private method to enable or disable a breakpoint. |
|
1181 |
|
1182 @param fn filename the breakpoint belongs to (string) |
|
1183 @param line linenumber of the breakpoint (int) |
|
1184 @param enable flag indicating enabling or disabling a breakpoint |
|
1185 (boolean) |
|
1186 """ |
|
1187 self.debuggerInterface.remoteBreakpointEnable(fn, line, enable) |
|
1188 |
|
1189 def __remoteBreakpointIgnore(self, fn, line, count): |
|
1190 """ |
|
1191 Private method to ignore a breakpoint the next couple of occurrences. |
|
1192 |
|
1193 @param fn filename the breakpoint belongs to (string) |
|
1194 @param line linenumber of the breakpoint (int) |
|
1195 @param count number of occurrences to ignore (int) |
|
1196 """ |
|
1197 self.debuggerInterface.remoteBreakpointIgnore(fn, line, count) |
|
1198 |
|
1199 def __remoteWatchpoint(self, cond, setWatch, temp=False): |
|
1200 """ |
|
1201 Private method to set or clear a watch expression. |
|
1202 |
|
1203 @param cond expression of the watch expression (string) |
|
1204 @param setWatch flag indicating setting or resetting a watch expression |
|
1205 (boolean) |
|
1206 @param temp flag indicating a temporary watch expression (boolean) |
|
1207 """ |
|
1208 # cond is combination of cond and special (s. watch expression viewer) |
|
1209 self.debuggerInterface.remoteWatchpoint(cond, setWatch, temp) |
|
1210 |
|
1211 def __remoteWatchpointEnable(self, cond, enable): |
|
1212 """ |
|
1213 Private method to enable or disable a watch expression. |
|
1214 |
|
1215 @param cond expression of the watch expression (string) |
|
1216 @param enable flag indicating enabling or disabling a watch expression |
|
1217 (boolean) |
|
1218 """ |
|
1219 # cond is combination of cond and special (s. watch expression viewer) |
|
1220 self.debuggerInterface.remoteWatchpointEnable(cond, enable) |
|
1221 |
|
1222 def __remoteWatchpointIgnore(self, cond, count): |
|
1223 """ |
|
1224 Private method to ignore a watch expression the next couple of |
|
1225 occurrences. |
|
1226 |
|
1227 @param cond expression of the watch expression (string) |
|
1228 @param count number of occurrences to ignore (int) |
|
1229 """ |
|
1230 # cond is combination of cond and special (s. watch expression viewer) |
|
1231 self.debuggerInterface.remoteWatchpointIgnore(cond, count) |
|
1232 |
|
1233 def remoteRawInput(self, s): |
|
1234 """ |
|
1235 Public method to send the raw input to the debugged program. |
|
1236 |
|
1237 @param s the raw input (string) |
|
1238 """ |
|
1239 self.debuggerInterface.remoteRawInput(s) |
|
1240 self.clientRawInputSent.emit() |
|
1241 |
|
1242 def remoteThreadList(self): |
|
1243 """ |
|
1244 Public method to request the list of threads from the client. |
|
1245 """ |
|
1246 self.debuggerInterface.remoteThreadList() |
|
1247 |
|
1248 def remoteSetThread(self, tid): |
|
1249 """ |
|
1250 Public method to request to set the given thread as current thread. |
|
1251 |
|
1252 @param tid id of the thread (integer) |
|
1253 """ |
|
1254 self.debuggerInterface.remoteSetThread(tid) |
|
1255 |
|
1256 def remoteClientVariables(self, scope, filterList, framenr=0): |
|
1257 """ |
|
1258 Public method to request the variables of the debugged program. |
|
1259 |
|
1260 @param scope the scope of the variables (0 = local, 1 = global) |
|
1261 @param filterList list of variable types to filter out (list of int) |
|
1262 @param framenr framenumber of the variables to retrieve (int) |
|
1263 """ |
|
1264 self.debuggerInterface.remoteClientVariables( |
|
1265 scope, filterList, framenr, self.__maxVariableSize) |
|
1266 |
|
1267 def remoteClientVariable(self, scope, filterList, var, framenr=0): |
|
1268 """ |
|
1269 Public method to request the variables of the debugged program. |
|
1270 |
|
1271 @param scope the scope of the variables (0 = local, 1 = global) |
|
1272 @param filterList list of variable types to filter out (list of int) |
|
1273 @param var list encoded name of variable to retrieve (string) |
|
1274 @param framenr framenumber of the variables to retrieve (int) |
|
1275 """ |
|
1276 self.debuggerInterface.remoteClientVariable( |
|
1277 scope, filterList, var, framenr, self.__maxVariableSize) |
|
1278 |
|
1279 def remoteClientSetFilter(self, scope, filterStr): |
|
1280 """ |
|
1281 Public method to set a variables filter list. |
|
1282 |
|
1283 @param scope the scope of the variables (0 = local, 1 = global) |
|
1284 @param filterStr regexp string for variable names to filter out |
|
1285 (string) |
|
1286 """ |
|
1287 self.debuggerInterface.remoteClientSetFilter(scope, filterStr) |
|
1288 |
|
1289 def setCallTraceEnabled(self, on): |
|
1290 """ |
|
1291 Public method to set the call trace state. |
|
1292 |
|
1293 @param on flag indicating to enable the call trace function (boolean) |
|
1294 """ |
|
1295 self.debuggerInterface.setCallTraceEnabled(on) |
|
1296 |
|
1297 def remoteBanner(self): |
|
1298 """ |
|
1299 Public slot to get the banner info of the remote client. |
|
1300 """ |
|
1301 self.debuggerInterface.remoteBanner() |
|
1302 |
|
1303 def remoteCapabilities(self): |
|
1304 """ |
|
1305 Public slot to get the debug clients capabilities. |
|
1306 """ |
|
1307 self.debuggerInterface.remoteCapabilities() |
|
1308 |
|
1309 def remoteCompletion(self, text): |
|
1310 """ |
|
1311 Public slot to get the a list of possible commandline completions |
|
1312 from the remote client. |
|
1313 |
|
1314 @param text the text to be completed (string) |
|
1315 """ |
|
1316 self.debuggerInterface.remoteCompletion(text) |
|
1317 |
|
1318 def remoteUTDiscover(self, clientType, forProject, venvName, syspath, |
|
1319 workdir, discoveryStart): |
|
1320 """ |
|
1321 Public method to perform a test case discovery. |
|
1322 |
|
1323 @param clientType client type to be used |
|
1324 @type str |
|
1325 @param forProject flag indicating a project related action |
|
1326 @type bool |
|
1327 @param venvName name of a virtual environment |
|
1328 @type str |
|
1329 @param syspath list of directories to be added to sys.path on the |
|
1330 remote side |
|
1331 @type list of str |
|
1332 @param workdir path name of the working directory |
|
1333 @type str |
|
1334 @param discoveryStart directory to start auto-discovery at |
|
1335 @type str |
|
1336 """ |
|
1337 if clientType and clientType not in self.getSupportedLanguages(): |
|
1338 # a not supported client language was requested |
|
1339 E5MessageBox.critical( |
|
1340 None, |
|
1341 self.tr("Start Debugger"), |
|
1342 self.tr( |
|
1343 """<p>The debugger type <b>{0}</b> is not supported""" |
|
1344 """ or not configured.</p>""").format(clientType) |
|
1345 ) |
|
1346 return |
|
1347 |
|
1348 # Restart the client if there is already a program loaded. |
|
1349 try: |
|
1350 if clientType: |
|
1351 self.__setClientType(clientType) |
|
1352 except KeyError: |
|
1353 self.__setClientType('Python3') # assume it is a Python3 file |
|
1354 self.startClient(False, forProject=forProject, venvName=venvName) |
|
1355 |
|
1356 self.debuggerInterface.remoteUTDiscover( |
|
1357 syspath, workdir, discoveryStart) |
|
1358 |
|
1359 def remoteUTPrepare(self, fn, tn, tfn, failed, cov, covname, coverase, |
|
1360 clientType="", forProject=False, venvName="", |
|
1361 syspath=None, workdir="", discover=False, |
|
1362 discoveryStart="", testCases=None, debug=False): |
|
1363 """ |
|
1364 Public method to prepare a new unittest run. |
|
1365 |
|
1366 @param fn the filename to load |
|
1367 @type str |
|
1368 @param tn the testname to load |
|
1369 @type str |
|
1370 @param tfn the test function name to load tests from |
|
1371 @type str |
|
1372 @param failed list of failed test, if only failed test should be run |
|
1373 @type list of str |
|
1374 @param cov flag indicating collection of coverage data is requested |
|
1375 @type bool |
|
1376 @param covname filename to be used to assemble the coverage caches |
|
1377 filename |
|
1378 @type str |
|
1379 @param coverase flag indicating erasure of coverage data is requested |
|
1380 @type bool |
|
1381 @param clientType client type to be used |
|
1382 @type str |
|
1383 @param forProject flag indicating a project related action |
|
1384 @type bool |
|
1385 @param venvName name of a virtual environment |
|
1386 @type str |
|
1387 @param syspath list of directories to be added to sys.path on the |
|
1388 remote side |
|
1389 @type list of str |
|
1390 @param workdir path name of the working directory |
|
1391 @type str |
|
1392 @param discover flag indicating to discover the tests automatically |
|
1393 @type bool |
|
1394 @param discoveryStart directory to start auto-discovery at |
|
1395 @type str |
|
1396 @param testCases list of test cases to be loaded |
|
1397 @type list of str |
|
1398 @param debug flag indicating to run unittest with debugging |
|
1399 @type bool |
|
1400 """ |
|
1401 if clientType and clientType not in self.getSupportedLanguages(): |
|
1402 # a not supported client language was requested |
|
1403 E5MessageBox.critical( |
|
1404 None, |
|
1405 self.tr("Start Debugger"), |
|
1406 self.tr( |
|
1407 """<p>The debugger type <b>{0}</b> is not supported""" |
|
1408 """ or not configured.</p>""").format(clientType) |
|
1409 ) |
|
1410 return |
|
1411 |
|
1412 # Restart the client if there is already a program loaded. |
|
1413 try: |
|
1414 if clientType: |
|
1415 self.__setClientType(clientType) |
|
1416 else: |
|
1417 self.__setClientType( |
|
1418 self.__findLanguageForExtension(os.path.splitext(fn)[1])) |
|
1419 except KeyError: |
|
1420 self.__setClientType('Python3') # assume it is a Python3 file |
|
1421 self.startClient(False, forProject=forProject, venvName=venvName) |
|
1422 |
|
1423 self.debuggerInterface.remoteUTPrepare( |
|
1424 fn, tn, tfn, failed, cov, covname, coverase, syspath, workdir, |
|
1425 discover, discoveryStart, testCases, debug) |
|
1426 self.running = True |
|
1427 self.debugging = debug |
|
1428 if debug: |
|
1429 self.__restoreBreakpoints() |
|
1430 self.__restoreWatchpoints() |
|
1431 |
|
1432 def remoteUTRun(self, debug=False, failfast=False): |
|
1433 """ |
|
1434 Public method to start a unittest run. |
|
1435 |
|
1436 @param debug flag indicating to run unittest with debugging |
|
1437 @type bool |
|
1438 @param failfast flag indicating to stop at the first error |
|
1439 @type bool |
|
1440 """ |
|
1441 self.debuggerInterface.remoteUTRun(debug, failfast) |
|
1442 |
|
1443 def remoteUTStop(self): |
|
1444 """ |
|
1445 public method to stop a unittest run. |
|
1446 """ |
|
1447 self.debuggerInterface.remoteUTStop() |
|
1448 |
|
1449 def signalClientOutput(self, line): |
|
1450 """ |
|
1451 Public method to process a line of client output. |
|
1452 |
|
1453 @param line client output (string) |
|
1454 """ |
|
1455 self.clientOutput.emit(line) |
|
1456 |
|
1457 def signalClientLine(self, filename, lineno, forStack=False): |
|
1458 """ |
|
1459 Public method to process client position feedback. |
|
1460 |
|
1461 @param filename name of the file currently being executed (string) |
|
1462 @param lineno line of code currently being executed (integer) |
|
1463 @param forStack flag indicating this is for a stack dump (boolean) |
|
1464 """ |
|
1465 self.clientLine.emit(filename, lineno, forStack) |
|
1466 |
|
1467 def signalClientStack(self, stack): |
|
1468 """ |
|
1469 Public method to process a client's stack information. |
|
1470 |
|
1471 @param stack list of stack entries. Each entry is a tuple of three |
|
1472 values giving the filename, linenumber and method |
|
1473 (list of lists of (string, integer, string)) |
|
1474 """ |
|
1475 self.clientStack.emit(stack) |
|
1476 |
|
1477 def signalClientThreadList(self, currentId, threadList): |
|
1478 """ |
|
1479 Public method to process the client thread list info. |
|
1480 |
|
1481 @param currentId id of the current thread (integer) |
|
1482 @param threadList list of dictionaries containing the thread data |
|
1483 """ |
|
1484 self.clientThreadList.emit(currentId, threadList) |
|
1485 |
|
1486 def signalClientThreadSet(self): |
|
1487 """ |
|
1488 Public method to handle the change of the client thread. |
|
1489 """ |
|
1490 self.clientThreadSet.emit() |
|
1491 |
|
1492 def signalClientVariables(self, scope, variables): |
|
1493 """ |
|
1494 Public method to process the client variables info. |
|
1495 |
|
1496 @param scope scope of the variables (-1 = empty global, 1 = global, |
|
1497 0 = local) |
|
1498 @param variables the list of variables from the client |
|
1499 """ |
|
1500 self.clientVariables.emit(scope, variables) |
|
1501 |
|
1502 def signalClientVariable(self, scope, variables): |
|
1503 """ |
|
1504 Public method to process the client variable info. |
|
1505 |
|
1506 @param scope scope of the variables (-1 = empty global, 1 = global, |
|
1507 0 = local) |
|
1508 @param variables the list of members of a classvariable from the client |
|
1509 """ |
|
1510 self.clientVariable.emit(scope, variables) |
|
1511 |
|
1512 def signalClientStatement(self, more): |
|
1513 """ |
|
1514 Public method to process the input response from the client. |
|
1515 |
|
1516 @param more flag indicating that more user input is required |
|
1517 """ |
|
1518 self.clientStatement.emit(more) |
|
1519 |
|
1520 def signalClientException(self, exceptionType, exceptionMessage, |
|
1521 stackTrace): |
|
1522 """ |
|
1523 Public method to process the exception info from the client. |
|
1524 |
|
1525 @param exceptionType type of exception raised (string) |
|
1526 @param exceptionMessage message given by the exception (string) |
|
1527 @param stackTrace list of stack entries with the exception position |
|
1528 first. Each stack entry is a list giving the filename and the |
|
1529 linenumber. |
|
1530 """ |
|
1531 if self.running: |
|
1532 self.clientException.emit(exceptionType, exceptionMessage, |
|
1533 stackTrace) |
|
1534 |
|
1535 def signalClientSyntaxError(self, message, filename, lineNo, characterNo): |
|
1536 """ |
|
1537 Public method to process the syntax error info from the client. |
|
1538 |
|
1539 @param message message of the syntax error (string) |
|
1540 @param filename translated filename of the syntax error position |
|
1541 (string) |
|
1542 @param lineNo line number of the syntax error position (integer) |
|
1543 @param characterNo character number of the syntax error position |
|
1544 (integer) |
|
1545 """ |
|
1546 if self.running: |
|
1547 self.clientSyntaxError.emit(message, filename, lineNo, characterNo) |
|
1548 |
|
1549 def signalClientSignal(self, message, filename, lineNo, |
|
1550 funcName, funcArgs): |
|
1551 """ |
|
1552 Public method to process a signal generated on the client side. |
|
1553 |
|
1554 @param message message of the syntax error |
|
1555 @type str |
|
1556 @param filename translated filename of the syntax error position |
|
1557 @type str |
|
1558 @param lineNo line number of the syntax error position |
|
1559 @type int |
|
1560 @param funcName name of the function causing the signal |
|
1561 @type str |
|
1562 @param funcArgs function arguments |
|
1563 @type str |
|
1564 """ |
|
1565 if self.running: |
|
1566 self.clientSignal.emit(message, filename, lineNo, |
|
1567 funcName, funcArgs) |
|
1568 |
|
1569 def signalClientExit(self, status, message=""): |
|
1570 """ |
|
1571 Public method to process the client exit status. |
|
1572 |
|
1573 @param status exit code |
|
1574 @type int |
|
1575 @param message message sent with the exit |
|
1576 @type str |
|
1577 """ |
|
1578 if self.passive: |
|
1579 self.__passiveShutDown() |
|
1580 self.clientExit.emit(int(status), message, False) |
|
1581 if Preferences.getDebugger("AutomaticReset") or (self.running and |
|
1582 not self.debugging): |
|
1583 self.debugging = False |
|
1584 self.startClient(False, forProject=self.__forProject) |
|
1585 if self.passive: |
|
1586 self.__createDebuggerInterface("None") |
|
1587 self.signalClientOutput(self.tr('\nNot connected\n')) |
|
1588 self.signalClientStatement(False) |
|
1589 self.running = False |
|
1590 |
|
1591 def signalClientClearBreak(self, filename, lineno): |
|
1592 """ |
|
1593 Public method to process the client clear breakpoint command. |
|
1594 |
|
1595 @param filename filename of the breakpoint (string) |
|
1596 @param lineno line umber of the breakpoint (integer) |
|
1597 """ |
|
1598 self.clientClearBreak.emit(filename, lineno) |
|
1599 |
|
1600 def signalClientBreakConditionError(self, filename, lineno): |
|
1601 """ |
|
1602 Public method to process the client breakpoint condition error info. |
|
1603 |
|
1604 @param filename filename of the breakpoint (string) |
|
1605 @param lineno line umber of the breakpoint (integer) |
|
1606 """ |
|
1607 self.clientBreakConditionError.emit(filename, lineno) |
|
1608 |
|
1609 def signalClientClearWatch(self, condition): |
|
1610 """ |
|
1611 Public slot to handle the clientClearWatch signal. |
|
1612 |
|
1613 @param condition expression of watch expression to clear (string) |
|
1614 """ |
|
1615 self.clientClearWatch.emit(condition) |
|
1616 |
|
1617 def signalClientWatchConditionError(self, condition): |
|
1618 """ |
|
1619 Public method to process the client watch expression error info. |
|
1620 |
|
1621 @param condition expression of watch expression to clear (string) |
|
1622 """ |
|
1623 self.clientWatchConditionError.emit(condition) |
|
1624 |
|
1625 def signalClientRawInput(self, prompt, echo): |
|
1626 """ |
|
1627 Public method to process the client raw input command. |
|
1628 |
|
1629 @param prompt the input prompt (string) |
|
1630 @param echo flag indicating an echoing of the input (boolean) |
|
1631 """ |
|
1632 self.clientRawInput.emit(prompt, echo) |
|
1633 |
|
1634 def signalClientBanner(self, version, platform, debugClient, venvName): |
|
1635 """ |
|
1636 Public method to process the client banner info. |
|
1637 |
|
1638 @param version interpreter version info |
|
1639 @type str |
|
1640 @param platform hostname of the client |
|
1641 @type str |
|
1642 @param debugClient additional debugger type info |
|
1643 @type str |
|
1644 @param venvName name of the virtual environment |
|
1645 @type str |
|
1646 """ |
|
1647 self.clientBanner.emit(version, platform, debugClient, venvName) |
|
1648 |
|
1649 def signalClientCapabilities(self, capabilities, clientType, venvName): |
|
1650 """ |
|
1651 Public method to process the client capabilities info. |
|
1652 |
|
1653 @param capabilities bitmaks with the client capabilities |
|
1654 @type int |
|
1655 @param clientType type of the debug client |
|
1656 @type str |
|
1657 @param venvName name of the virtual environment |
|
1658 @type str |
|
1659 """ |
|
1660 try: |
|
1661 self.__debuggerInterfaceRegistry[clientType][0] = capabilities |
|
1662 self.clientCapabilities.emit(capabilities, clientType, venvName) |
|
1663 except KeyError: |
|
1664 # ignore silently |
|
1665 pass |
|
1666 |
|
1667 def signalClientCompletionList(self, completionList, text): |
|
1668 """ |
|
1669 Public method to process the client auto completion info. |
|
1670 |
|
1671 @param completionList list of possible completions (list of strings) |
|
1672 @param text the text to be completed (string) |
|
1673 """ |
|
1674 self.clientCompletionList.emit(completionList, text) |
|
1675 |
|
1676 def signalClientCallTrace(self, isCall, fromFile, fromLine, fromFunction, |
|
1677 toFile, toLine, toFunction): |
|
1678 """ |
|
1679 Public method to process the client call trace data. |
|
1680 |
|
1681 @param isCall flag indicating a 'call' (boolean) |
|
1682 @param fromFile name of the originating file (string) |
|
1683 @param fromLine line number in the originating file (string) |
|
1684 @param fromFunction name of the originating function (string) |
|
1685 @param toFile name of the target file (string) |
|
1686 @param toLine line number in the target file (string) |
|
1687 @param toFunction name of the target function (string) |
|
1688 """ |
|
1689 self.callTraceInfo.emit( |
|
1690 isCall, fromFile, fromLine, fromFunction, |
|
1691 toFile, toLine, toFunction) |
|
1692 |
|
1693 def clientUtDiscovered(self, testCases, exceptionType, exceptionValue): |
|
1694 """ |
|
1695 Public method to process the client unittest discover info. |
|
1696 |
|
1697 @param testCases list of detected test cases |
|
1698 @type str |
|
1699 @param exceptionType exception type |
|
1700 @type str |
|
1701 @param exceptionValue exception message |
|
1702 @type str |
|
1703 """ |
|
1704 self.utDiscovered.emit(testCases, exceptionType, exceptionValue) |
|
1705 |
|
1706 def clientUtPrepared(self, result, exceptionType, exceptionValue): |
|
1707 """ |
|
1708 Public method to process the client unittest prepared info. |
|
1709 |
|
1710 @param result number of test cases (0 = error) (integer) |
|
1711 @param exceptionType exception type (string) |
|
1712 @param exceptionValue exception message (string) |
|
1713 """ |
|
1714 self.utPrepared.emit(result, exceptionType, exceptionValue) |
|
1715 |
|
1716 def clientUtStartTest(self, testname, doc): |
|
1717 """ |
|
1718 Public method to process the client start test info. |
|
1719 |
|
1720 @param testname name of the test (string) |
|
1721 @param doc short description of the test (string) |
|
1722 """ |
|
1723 self.utStartTest.emit(testname, doc) |
|
1724 |
|
1725 def clientUtStopTest(self): |
|
1726 """ |
|
1727 Public method to process the client stop test info. |
|
1728 """ |
|
1729 self.utStopTest.emit() |
|
1730 |
|
1731 def clientUtTestFailed(self, testname, traceback, testId): |
|
1732 """ |
|
1733 Public method to process the client test failed info. |
|
1734 |
|
1735 @param testname name of the test (string) |
|
1736 @param traceback lines of traceback info (list of strings) |
|
1737 @param testId id of the test (string) |
|
1738 """ |
|
1739 self.utTestFailed.emit(testname, traceback, testId) |
|
1740 |
|
1741 def clientUtTestErrored(self, testname, traceback, testId): |
|
1742 """ |
|
1743 Public method to process the client test errored info. |
|
1744 |
|
1745 @param testname name of the test (string) |
|
1746 @param traceback lines of traceback info (list of strings) |
|
1747 @param testId id of the test (string) |
|
1748 """ |
|
1749 self.utTestErrored.emit(testname, traceback, testId) |
|
1750 |
|
1751 def clientUtTestSkipped(self, testname, reason, testId): |
|
1752 """ |
|
1753 Public method to process the client test skipped info. |
|
1754 |
|
1755 @param testname name of the test (string) |
|
1756 @param reason reason for skipping the test (string) |
|
1757 @param testId id of the test (string) |
|
1758 """ |
|
1759 self.utTestSkipped.emit(testname, reason, testId) |
|
1760 |
|
1761 def clientUtTestFailedExpected(self, testname, traceback, testId): |
|
1762 """ |
|
1763 Public method to process the client test failed expected info. |
|
1764 |
|
1765 @param testname name of the test (string) |
|
1766 @param traceback lines of traceback info (list of strings) |
|
1767 @param testId id of the test (string) |
|
1768 """ |
|
1769 self.utTestFailedExpected.emit(testname, traceback, testId) |
|
1770 |
|
1771 def clientUtTestSucceededUnexpected(self, testname, testId): |
|
1772 """ |
|
1773 Public method to process the client test succeeded unexpected info. |
|
1774 |
|
1775 @param testname name of the test (string) |
|
1776 @param testId id of the test (string) |
|
1777 """ |
|
1778 self.utTestSucceededUnexpected.emit(testname, testId) |
|
1779 |
|
1780 def clientUtFinished(self, status): |
|
1781 """ |
|
1782 Public method to process the client unit test finished info. |
|
1783 |
|
1784 @param status exit status of the unit test |
|
1785 @type int |
|
1786 """ |
|
1787 self.utFinished.emit() |
|
1788 |
|
1789 self.clientExit.emit(int(status), "", True) |
|
1790 self.debugging = False |
|
1791 self.running = False |
|
1792 |
|
1793 def passiveStartUp(self, fn, exc): |
|
1794 """ |
|
1795 Public method to handle a passive debug connection. |
|
1796 |
|
1797 @param fn filename of the debugged script (string) |
|
1798 @param exc flag to enable exception reporting of the IDE (boolean) |
|
1799 """ |
|
1800 self.appendStdout.emit(self.tr("Passive debug connection received\n")) |
|
1801 self.passiveClientExited = False |
|
1802 self.debugging = True |
|
1803 self.running = True |
|
1804 self.__restoreBreakpoints() |
|
1805 self.__restoreWatchpoints() |
|
1806 self.passiveDebugStarted.emit(fn, exc) |
|
1807 |
|
1808 def __passiveShutDown(self): |
|
1809 """ |
|
1810 Private method to shut down a passive debug connection. |
|
1811 """ |
|
1812 self.passiveClientExited = True |
|
1813 self.shutdownServer() |
|
1814 self.appendStdout.emit(self.tr("Passive debug connection closed\n")) |
|
1815 |
|
1816 def __restoreBreakpoints(self): |
|
1817 """ |
|
1818 Private method to restore the breakpoints after a restart. |
|
1819 """ |
|
1820 if self.debugging: |
|
1821 self.__addBreakPoints( |
|
1822 QModelIndex(), 0, self.breakpointModel.rowCount() - 1) |
|
1823 |
|
1824 def __restoreWatchpoints(self): |
|
1825 """ |
|
1826 Private method to restore the watch expressions after a restart. |
|
1827 """ |
|
1828 if self.debugging: |
|
1829 self.__addWatchPoints( |
|
1830 QModelIndex(), 0, self.watchpointModel.rowCount() - 1) |
|
1831 |
|
1832 def getBreakPointModel(self): |
|
1833 """ |
|
1834 Public slot to get a reference to the breakpoint model object. |
|
1835 |
|
1836 @return reference to the breakpoint model object (BreakPointModel) |
|
1837 """ |
|
1838 return self.breakpointModel |
|
1839 |
|
1840 def getWatchPointModel(self): |
|
1841 """ |
|
1842 Public slot to get a reference to the watch expression model object. |
|
1843 |
|
1844 @return reference to the watch expression model object |
|
1845 (WatchPointModel) |
|
1846 """ |
|
1847 return self.watchpointModel |
|
1848 |
|
1849 def isConnected(self): |
|
1850 """ |
|
1851 Public method to test, if the debug server is connected to a backend. |
|
1852 |
|
1853 @return flag indicating a connection (boolean) |
|
1854 """ |
|
1855 return self.debuggerInterface and self.debuggerInterface.isConnected() |
|
1856 |
|
1857 def isDebugging(self): |
|
1858 """ |
|
1859 Public method to test, if the debug server is debugging. |
|
1860 |
|
1861 @return flag indicating the debugging state |
|
1862 @rtype bool |
|
1863 """ |
|
1864 return self.debugging |
|
1865 |
|
1866 def setDebugging(self, on): |
|
1867 """ |
|
1868 Public method to set the debugging state. |
|
1869 |
|
1870 @param on flag indicating the new debugging state |
|
1871 @type bool |
|
1872 """ |
|
1873 self.debugging = on |