5 |
5 |
6 """ |
6 """ |
7 Module implementing the debug server. |
7 Module implementing the debug server. |
8 """ |
8 """ |
9 |
9 |
10 from __future__ import unicode_literals |
|
11 try: |
|
12 str = unicode |
|
13 except NameError: |
|
14 pass |
|
15 |
10 |
16 import os |
11 import os |
17 import sys |
12 import sys |
18 |
13 |
19 from PyQt5.QtCore import pyqtSignal, QModelIndex |
14 from PyQt5.QtCore import pyqtSignal, QModelIndex |
20 from PyQt5.QtNetwork import QTcpServer, QHostAddress, QHostInfo, \ |
15 from PyQt5.QtNetwork import ( |
21 QNetworkInterface |
16 QTcpServer, QHostAddress, QHostInfo, QNetworkInterface |
|
17 ) |
22 |
18 |
23 from E5Gui.E5Application import e5App |
19 from E5Gui.E5Application import e5App |
24 from E5Gui import E5MessageBox |
20 from E5Gui import E5MessageBox |
25 |
21 |
26 from .BreakPointModel import BreakPointModel |
22 from .BreakPointModel import BreakPointModel |
183 # the value |
179 # the value |
184 |
180 |
185 # create our models |
181 # create our models |
186 self.breakpointModel = BreakPointModel(self) |
182 self.breakpointModel = BreakPointModel(self) |
187 self.watchpointModel = WatchPointModel(self) |
183 self.watchpointModel = WatchPointModel(self) |
188 self.watchSpecialCreated = \ |
184 self.watchSpecialCreated = self.tr( |
189 self.tr("created", "must be same as in EditWatchpointDialog") |
185 "created", "must be same as in EditWatchpointDialog") |
190 self.watchSpecialChanged = \ |
186 self.watchSpecialChanged = self.tr( |
191 self.tr("changed", "must be same as in EditWatchpointDialog") |
187 "changed", "must be same as in EditWatchpointDialog") |
192 |
188 |
193 self.networkInterface = Preferences.getDebugger("NetworkInterface") |
189 self.networkInterface = Preferences.getDebugger("NetworkInterface") |
194 if self.networkInterface == "all": |
190 if self.networkInterface == "all": |
195 hostAddress = QHostAddress("0.0.0.0") # QHostAddress.Any) |
191 hostAddress = QHostAddress("0.0.0.0") # QHostAddress.Any) |
196 elif self.networkInterface == "allv6": |
192 elif self.networkInterface == "allv6": |
197 hostAddress = QHostAddress("::") # QHostAddress.AnyIPv6) |
193 hostAddress = QHostAddress("::") # QHostAddress.AnyIPv6) |
198 else: |
194 else: |
199 hostAddress = QHostAddress(self.networkInterface) |
195 hostAddress = QHostAddress(self.networkInterface) |
200 self.networkInterfaceName, self.networkInterfaceIndex = \ |
196 self.networkInterfaceName, self.networkInterfaceIndex = ( |
201 self.__getNetworkInterfaceAndIndex(self.networkInterface) |
197 self.__getNetworkInterfaceAndIndex(self.networkInterface)) |
202 |
198 |
203 if not preventPassiveDebugging and \ |
199 if (not preventPassiveDebugging and |
204 Preferences.getDebugger("PassiveDbgEnabled"): |
200 Preferences.getDebugger("PassiveDbgEnabled")): |
205 sock = Preferences.getDebugger("PassiveDbgPort") # default: 42424 |
201 sock = Preferences.getDebugger("PassiveDbgPort") # default: 42424 |
206 self.listen(hostAddress, sock) |
202 self.listen(hostAddress, sock) |
207 self.passive = True |
203 self.passive = True |
208 self.passiveClientExited = False |
204 self.passiveClientExited = False |
209 else: |
205 else: |
215 self.debuggerInterface = None |
211 self.debuggerInterface = None |
216 self.debugging = False |
212 self.debugging = False |
217 self.running = False |
213 self.running = False |
218 self.clientProcess = None |
214 self.clientProcess = None |
219 self.clientInterpreter = "" |
215 self.clientInterpreter = "" |
220 self.clientType = \ |
216 self.clientType = Preferences.Prefs.settings.value('DebugClient/Type') |
221 Preferences.Prefs.settings.value('DebugClient/Type') |
|
222 if self.clientType is None: |
217 if self.clientType is None: |
223 if sys.version_info[0] == 2: |
218 self.clientType = 'Python3' |
224 self.clientType = 'Python2' |
|
225 else: |
|
226 self.clientType = 'Python3' |
|
227 # Change clientType if dependent interpreter does not exist anymore |
219 # Change clientType if dependent interpreter does not exist anymore |
228 # (maybe deinstalled,...) |
220 # (maybe deinstalled,...) |
229 elif self.clientType == 'Python2' and Preferences.getDebugger( |
221 elif self.clientType == 'Python2' and Preferences.getDebugger( |
230 "Python2VirtualEnv") == '' and sys.version_info[0] == 3: |
222 "Python2VirtualEnv") == '' and sys.version_info[0] >= 3: |
231 self.clientType = 'Python3' |
223 self.clientType = 'Python3' |
232 elif self.clientType == 'Python3' and Preferences.getDebugger( |
224 elif self.clientType == 'Python3' and Preferences.getDebugger( |
233 "Python3VirtualEnv") == '' and sys.version_info[0] == 2: |
225 "Python3VirtualEnv") == '' and sys.version_info[0] == 2: |
234 self.clientType = 'Python2' |
226 self.clientType = 'Python2' |
235 |
227 |
293 if address not in ["all", "allv6"]: |
285 if address not in ["all", "allv6"]: |
294 for networkInterface in QNetworkInterface.allInterfaces(): |
286 for networkInterface in QNetworkInterface.allInterfaces(): |
295 addressEntries = networkInterface.addressEntries() |
287 addressEntries = networkInterface.addressEntries() |
296 if len(addressEntries) > 0: |
288 if len(addressEntries) > 0: |
297 for addressEntry in addressEntries: |
289 for addressEntry in addressEntries: |
298 if addressEntry.ip().toString().lower() == \ |
290 if (addressEntry.ip().toString().lower() == |
299 address.lower(): |
291 address.lower()): |
300 return networkInterface.humanReadableName(), \ |
292 return (networkInterface.humanReadableName(), |
301 networkInterface.index() |
293 networkInterface.index()) |
302 |
294 |
303 return "", 0 |
295 return "", 0 |
304 |
296 |
305 def preferencesChanged(self): |
297 def preferencesChanged(self): |
306 """ |
298 """ |
307 Public slot to handle the preferencesChanged signal. |
299 Public slot to handle the preferencesChanged signal. |
308 """ |
300 """ |
309 registeredInterfaces = {} |
301 registeredInterfaces = {} |
310 for interfaceName in self.__debuggerInterfaces: |
302 for interfaceName in self.__debuggerInterfaces: |
311 registeredInterfaces[interfaceName] = \ |
303 registeredInterfaces[interfaceName] = ( |
312 self.__debuggerInterfaces[interfaceName] |
304 self.__debuggerInterfaces[interfaceName]) |
313 |
305 |
314 self.__debuggerInterfaceRegistry = {} |
306 self.__debuggerInterfaceRegistry = {} |
315 for interfaceName, getRegistryData in registeredInterfaces.items(): |
307 for interfaceName, getRegistryData in registeredInterfaces.items(): |
316 self.registerDebuggerInterface(interfaceName, getRegistryData, |
308 self.registerDebuggerInterface(interfaceName, getRegistryData, |
317 reregister=True) |
309 reregister=True) |
344 |
336 |
345 if not reregister: |
337 if not reregister: |
346 self.__debuggerInterfaces[interfaceName] = getRegistryData |
338 self.__debuggerInterfaces[interfaceName] = getRegistryData |
347 registryDataList = getRegistryData() |
339 registryDataList = getRegistryData() |
348 if registryDataList: |
340 if registryDataList: |
349 for clientLanguage, clientCapabilities, clientExtensions, \ |
341 for (clientLanguage, clientCapabilities, clientExtensions, |
350 interfaceCreator in registryDataList: |
342 interfaceCreator) in registryDataList: |
351 self.__debuggerInterfaceRegistry[clientLanguage] = [ |
343 self.__debuggerInterfaceRegistry[clientLanguage] = [ |
352 clientCapabilities, clientExtensions, interfaceCreator, |
344 clientCapabilities, clientExtensions, interfaceCreator, |
353 interfaceName] |
345 interfaceName] |
354 |
346 |
355 def unregisterDebuggerInterface(self, interfaceName): |
347 def unregisterDebuggerInterface(self, interfaceName): |
359 @param interfaceName interfaceName of the debugger interface |
351 @param interfaceName interfaceName of the debugger interface |
360 @type str |
352 @type str |
361 """ |
353 """ |
362 if interfaceName in self.__debuggerInterfaces: |
354 if interfaceName in self.__debuggerInterfaces: |
363 clientLanguages = [] |
355 clientLanguages = [] |
364 for clientLanguage, registryData in \ |
356 for clientLanguage, registryData in ( |
365 self.__debuggerInterfaceRegistry.items(): |
357 self.__debuggerInterfaceRegistry.items()): |
366 if interfaceName == registryData[-1]: |
358 if interfaceName == registryData[-1]: |
367 clientLanguages.append(clientLanguage) |
359 clientLanguages.append(clientLanguage) |
368 for clientLanguage in clientLanguages: |
360 for clientLanguage in clientLanguages: |
369 del self.__debuggerInterfaceRegistry[clientLanguage] |
361 del self.__debuggerInterfaceRegistry[clientLanguage] |
370 del self.__debuggerInterfaces[interfaceName] |
362 del self.__debuggerInterfaces[interfaceName] |
410 languages.remove("None") |
402 languages.remove("None") |
411 except ValueError: |
403 except ValueError: |
412 pass # it is not in the list |
404 pass # it is not in the list |
413 |
405 |
414 if shellOnly: |
406 if shellOnly: |
415 languages = \ |
407 languages = [lang for lang in languages |
416 [lang for lang in languages |
408 if self.__debuggerInterfaceRegistry[lang][0] & |
417 if self.__debuggerInterfaceRegistry[lang][0] & |
409 DebugClientCapabilities.HasShell] |
418 DebugClientCapabilities.HasShell] |
|
419 |
410 |
420 return languages[:] |
411 return languages[:] |
421 |
412 |
422 def getExtensions(self, language): |
413 def getExtensions(self, language): |
423 """ |
414 """ |
440 """ |
431 """ |
441 if self.lastClientType != self.clientType or clientType is not None: |
432 if self.lastClientType != self.clientType or clientType is not None: |
442 if clientType is None: |
433 if clientType is None: |
443 clientType = self.clientType |
434 clientType = self.clientType |
444 if clientType in self.__debuggerInterfaceRegistry: |
435 if clientType in self.__debuggerInterfaceRegistry: |
445 self.debuggerInterface = \ |
436 self.debuggerInterface = ( |
446 self.__debuggerInterfaceRegistry[clientType][2]( |
437 self.__debuggerInterfaceRegistry[clientType][2]( |
447 self, self.passive) |
438 self, self.passive)) |
448 else: |
439 else: |
449 self.debuggerInterface = \ |
440 self.debuggerInterface = ( |
450 self.__debuggerInterfaceRegistry["None"][2]( |
441 self.__debuggerInterfaceRegistry["None"][2]( |
451 self, self.passive) |
442 self, self.passive)) |
452 self.clientType = "None" |
443 self.clientType = "None" |
453 |
444 |
454 def __setClientType(self, clType): |
445 def __setClientType(self, clType): |
455 """ |
446 """ |
456 Private method to set the client type. |
447 Private method to set the client type. |
507 self.__forProject = forProject |
498 self.__forProject = forProject |
508 self.__createDebuggerInterface() |
499 self.__createDebuggerInterface() |
509 if forProject: |
500 if forProject: |
510 project = e5App().getObject("Project") |
501 project = e5App().getObject("Project") |
511 if not project.isDebugPropertiesLoaded(): |
502 if not project.isDebugPropertiesLoaded(): |
512 self.clientProcess, isNetworked, clientInterpreter = \ |
503 self.clientProcess, isNetworked, clientInterpreter = ( |
513 self.debuggerInterface.startRemote( |
504 self.debuggerInterface.startRemote( |
514 self.serverPort(), runInConsole, venvName, |
505 self.serverPort(), runInConsole, venvName, |
515 self.__originalPathString, workingDir=workingDir) |
506 self.__originalPathString, workingDir=workingDir)) |
516 else: |
507 else: |
517 self.clientProcess, isNetworked, clientInterpreter = \ |
508 self.clientProcess, isNetworked, clientInterpreter = ( |
518 self.debuggerInterface.startRemoteForProject( |
509 self.debuggerInterface.startRemoteForProject( |
519 self.serverPort(), runInConsole, venvName, |
510 self.serverPort(), runInConsole, venvName, |
520 self.__originalPathString, workingDir=workingDir) |
511 self.__originalPathString, workingDir=workingDir)) |
521 else: |
512 else: |
522 self.clientProcess, isNetworked, clientInterpreter = \ |
513 self.clientProcess, isNetworked, clientInterpreter = ( |
523 self.debuggerInterface.startRemote( |
514 self.debuggerInterface.startRemote( |
524 self.serverPort(), runInConsole, venvName, |
515 self.serverPort(), runInConsole, venvName, |
525 self.__originalPathString, workingDir=workingDir) |
516 self.__originalPathString, workingDir=workingDir)) |
526 |
517 |
527 if self.clientProcess: |
518 if self.clientProcess: |
528 self.clientProcess.readyReadStandardError.connect( |
519 self.clientProcess.readyReadStandardError.connect( |
529 self.__clientProcessError) |
520 self.__clientProcessError) |
530 self.clientProcess.readyReadStandardOutput.connect( |
521 self.clientProcess.readyReadStandardOutput.connect( |
588 @param end end row (integer) |
579 @param end end row (integer) |
589 """ |
580 """ |
590 if self.debugging: |
581 if self.debugging: |
591 for row in range(start, end + 1): |
582 for row in range(start, end + 1): |
592 index = self.breakpointModel.index(row, 0, parentIndex) |
583 index = self.breakpointModel.index(row, 0, parentIndex) |
593 fn, lineno = \ |
584 fn, lineno = ( |
594 self.breakpointModel.getBreakPointByIndex(index)[0:2] |
585 self.breakpointModel.getBreakPointByIndex(index)[0:2]) |
595 self.remoteBreakpoint(fn, lineno, False) |
586 self.remoteBreakpoint(fn, lineno, False) |
596 |
587 |
597 def __changeBreakPoints(self, startIndex, endIndex): |
588 def __changeBreakPoints(self, startIndex, endIndex): |
598 """ |
589 """ |
599 Private slot to set changed breakpoints. |
590 Private slot to set changed breakpoints. |
626 @param end end row (integer) |
617 @param end end row (integer) |
627 """ |
618 """ |
628 if self.debugging: |
619 if self.debugging: |
629 for row in range(start, end + 1): |
620 for row in range(start, end + 1): |
630 index = self.breakpointModel.index(row, 0, parentIndex) |
621 index = self.breakpointModel.index(row, 0, parentIndex) |
631 fn, line, cond, temp, enabled, ignorecount = \ |
622 fn, line, cond, temp, enabled, ignorecount = ( |
632 self.breakpointModel.getBreakPointByIndex(index)[:6] |
623 self.breakpointModel.getBreakPointByIndex(index)[:6]) |
633 self.remoteBreakpoint(fn, line, True, cond, temp) |
624 self.remoteBreakpoint(fn, line, True, cond, temp) |
634 if not enabled: |
625 if not enabled: |
635 self.__remoteBreakpointEnable(fn, line, False) |
626 self.__remoteBreakpointEnable(fn, line, False) |
636 if ignorecount: |
627 if ignorecount: |
637 self.__remoteBreakpointIgnore(fn, line, ignorecount) |
628 self.__remoteBreakpointIgnore(fn, line, ignorecount) |
693 @param end end row (integer) |
684 @param end end row (integer) |
694 """ |
685 """ |
695 if self.debugging: |
686 if self.debugging: |
696 for row in range(start, end + 1): |
687 for row in range(start, end + 1): |
697 index = self.watchpointModel.index(row, 0, parentIndex) |
688 index = self.watchpointModel.index(row, 0, parentIndex) |
698 cond, special = \ |
689 cond, special = ( |
699 self.watchpointModel.getWatchPointByIndex(index)[0:2] |
690 self.watchpointModel.getWatchPointByIndex(index)[0:2]) |
700 cond = self.__makeWatchCondition(cond, special) |
691 cond = self.__makeWatchCondition(cond, special) |
701 self.__remoteWatchpoint(cond, False) |
692 self.__remoteWatchpoint(cond, False) |
702 |
693 |
703 def __watchPointDataAboutToBeChanged(self, startIndex, endIndex): |
694 def __watchPointDataAboutToBeChanged(self, startIndex, endIndex): |
704 """ |
695 """ |
721 @param end end row (integer) |
712 @param end end row (integer) |
722 """ |
713 """ |
723 if self.debugging: |
714 if self.debugging: |
724 for row in range(start, end + 1): |
715 for row in range(start, end + 1): |
725 index = self.watchpointModel.index(row, 0, parentIndex) |
716 index = self.watchpointModel.index(row, 0, parentIndex) |
726 cond, special, temp, enabled, ignorecount = \ |
717 cond, special, temp, enabled, ignorecount = ( |
727 self.watchpointModel.getWatchPointByIndex(index)[:5] |
718 self.watchpointModel.getWatchPointByIndex(index)[:5]) |
728 cond = self.__makeWatchCondition(cond, special) |
719 cond = self.__makeWatchCondition(cond, special) |
729 self.__remoteWatchpoint(cond, True, temp) |
720 self.__remoteWatchpoint(cond, True, temp) |
730 if not enabled: |
721 if not enabled: |
731 self.__remoteWatchpointEnable(cond, False) |
722 self.__remoteWatchpointEnable(cond, False) |
732 if ignorecount: |
723 if ignorecount: |