eric7/Debugger/DebugServer.py

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

eric ide

mercurial