Debugger/DebugServer.py

changeset 4553
a6b2acd1a355
parent 4495
b99a70d5cb4b
child 4554
f3428ddd577c
equal deleted inserted replaced
4552:b1ea4ea0190e 4553:a6b2acd1a355
28 28
29 import Preferences 29 import Preferences
30 import Utilities 30 import Utilities
31 31
32 32
33 DebuggerInterfaces = [ 33 DebuggerInterfaces = {
34 "DebuggerInterfacePython", 34 "Python": "DebuggerInterfacePython",
35 "DebuggerInterfacePython3", 35 "Python3": "DebuggerInterfacePython3",
36 ## "DebuggerInterfaceRuby", 36 "None": "DebuggerInterfaceNone",
37 "DebuggerInterfaceNone", 37 }
38 ]
39 38
40 39
41 class DebugServer(QTcpServer): 40 class DebugServer(QTcpServer):
42 """ 41 """
43 Class implementing the debug server embedded within the IDE. 42 Class implementing the debug server embedded within the IDE.
159 """ 158 """
160 Constructor 159 Constructor
161 """ 160 """
162 super(DebugServer, self).__init__() 161 super(DebugServer, self).__init__()
163 162
163 self.__debuggerInterfaceRegistry = {}
164 # the client language is the key, a list containing the client
165 # capabilities, the list of associated file extensions, a
166 # function reference to create the debugger interface (see
167 # __createDebuggerInterface() below) and a function to be called
168 # to get the registration data as values
169
164 # create our models 170 # create our models
165 self.breakpointModel = BreakPointModel(self) 171 self.breakpointModel = BreakPointModel(self)
166 self.watchpointModel = WatchPointModel(self) 172 self.watchpointModel = WatchPointModel(self)
167 self.watchSpecialCreated = \ 173 self.watchSpecialCreated = \
168 self.tr("created", "must be same as in EditWatchpointDialog") 174 self.tr("created", "must be same as in EditWatchpointDialog")
280 286
281 def preferencesChanged(self): 287 def preferencesChanged(self):
282 """ 288 """
283 Public slot to handle the preferencesChanged signal. 289 Public slot to handle the preferencesChanged signal.
284 """ 290 """
285 # TODO: eric 6.2: change this to call all registered debugger 291 registeredInterfaces = {}
286 # interfaces getRegistryData() method ignoring the client 292 for language in self.__debuggerInterfaceRegistry:
287 # language and update the client capabilities and client 293 registeredInterfaces[language] = \
288 # associations. 294 self.__debuggerInterfaceRegistry[language][-1]
289 self.__registerDebuggerInterfaces() 295 # last entry is the registry data function
296
297 self.__debuggerInterfaceRegistry = {}
298 for language, getRegistryData in registeredInterfaces.items():
299 self.registerDebuggerInterface(language, getRegistryData)
300
301 def registerDebuggerInterface(self, name, getRegistryData):
302 """
303 Public method to register a debugger interface.
304
305 @param name name of the debugger interface
306 @type str
307 @param getRegistryData reference to a function to be called
308 to get the debugger interface details. This method shall
309 return the client language, the client capabilities, the
310 list of associated file extensions and a function reference
311 to create the debugger interface (see __createDebuggerInterface())
312 @type function
313 """
314 if name in self.__debuggerInterfaceRegistry:
315 E5MessageBox.warning(
316 None,
317 self.tr("Register Debugger Interface"),
318 self.tr("""<p>The debugger interface <b>{0}</b> has already"""
319 """ been registered. Ignoring this request.</p>"""))
320 return
321
322 clientLanguage, clientCapabilities, clientExtensions, \
323 interfaceCreator = getRegistryData()
324 if clientLanguage:
325 self.__debuggerInterfaceRegistry[clientLanguage] = \
326 [clientCapabilities, clientExtensions, interfaceCreator,
327 getRegistryData]
328
329 def unregisterDebuggerInterface(self, name):
330 """
331 Private method to unregister a debugger interface.
332
333 @param name name of the debugger interface
334 @type str
335 """
336 if name in self.__debuggerInterfaceRegistry:
337 del self.__debuggerInterfaceRegistry[name]
338
339 def __findLanguageForExtension(self, ext):
340 """
341 Private method to get the language associated with a file extension.
342
343 @param ext file extension
344 @type str
345 @return associated language
346 @rtype str
347 """
348 for language in self.__debuggerInterfaceRegistry:
349 if ext in self.__debuggerInterfaceRegistry[language][1]:
350 return language
351
352 return ""
290 353
291 def __registerDebuggerInterfaces(self): 354 def __registerDebuggerInterfaces(self):
292 """ 355 """
293 Private method to register the available debugger interface modules. 356 Private method to register the available internal debugger interfaces.
294 """ 357 """
295 self.__clientCapabilities = {} 358 for name, interface in DebuggerInterfaces.items():
296 self.__clientAssociations = {}
297 # TODO: eric 6.2: Add a debugger interface registry dictionary with the
298 # debugger name (language) as a key
299 # TODO: eric 6.2: Add a registerDebuggerInterface() method taking a
300 # name and a getRegistryData() method. This method should be
301 # called when a debugger backend plug-in is activated.
302 # getRegistryData() shall return the client language, the client
303 # capabilities, the list of associated file extensions and a
304 # function reference to create the debugger interface (see
305 # __createDebuggerInterface() below
306 # TODO: eric 6.2: Add an unregisterDebuggerInterface() method with a
307 # name as parameter to revert the above.
308
309 for interface in DebuggerInterfaces:
310 modName = "Debugger.{0}".format(interface) 359 modName = "Debugger.{0}".format(interface)
311 mod = __import__(modName) 360 mod = __import__(modName)
312 components = modName.split('.') 361 components = modName.split('.')
313 for comp in components[1:]: 362 for comp in components[1:]:
314 mod = getattr(mod, comp) 363 mod = getattr(mod, comp)
315 364
316 clientLanguage, clientCapabilities, clientExtensions = \ 365 self.registerDebuggerInterface(name, mod.getRegistryData)
317 mod.getRegistryData()
318 if clientLanguage:
319 self.__clientCapabilities[clientLanguage] = clientCapabilities
320 for extension in clientExtensions:
321 if extension not in self.__clientAssociations:
322 self.__clientAssociations[extension] = clientLanguage
323 366
324 def getSupportedLanguages(self, shellOnly=False): 367 def getSupportedLanguages(self, shellOnly=False):
325 """ 368 """
326 Public slot to return the supported programming languages. 369 Public slot to return the supported programming languages.
327 370
328 @param shellOnly flag indicating only languages supporting an 371 @param shellOnly flag indicating only languages supporting an
329 interactive shell should be returned 372 interactive shell should be returned
330 @return list of supported languages (list of strings) 373 @return list of supported languages (list of strings)
331 """ 374 """
332 languages = list(self.__clientCapabilities.keys()) 375 languages = list(self.__debuggerInterfaceRegistry.keys())
333 try: 376 try:
334 languages.remove("None") 377 languages.remove("None")
335 except ValueError: 378 except ValueError:
336 pass # it is not in the list 379 pass # it is not in the list
337 380
338 if shellOnly: 381 if shellOnly:
339 languages = \ 382 languages = \
340 [lang for lang in languages 383 [lang for lang in languages
341 if self.__clientCapabilities[lang] & 384 if self.__debuggerInterfaceRegistry[lang][0] &
342 DebugClientCapabilities.HasShell] 385 DebugClientCapabilities.HasShell]
343 386
344 return languages[:] 387 return languages[:]
345 388
346 def getExtensions(self, language): 389 def getExtensions(self, language):
349 392
350 @param language language to get extensions for (string) 393 @param language language to get extensions for (string)
351 @return tuple of extensions associated with the language 394 @return tuple of extensions associated with the language
352 (tuple of strings) 395 (tuple of strings)
353 """ 396 """
354 extensions = [] 397 if language in self.__debuggerInterfaceRegistry:
355 for ext, lang in list(self.__clientAssociations.items()): 398 return tuple(self.__debuggerInterfaceRegistry[language][1])
356 if lang == language: 399 else:
357 extensions.append(ext) 400 return tuple()
358
359 return tuple(extensions)
360 401
361 def __createDebuggerInterface(self, clientType=None): 402 def __createDebuggerInterface(self, clientType=None):
362 """ 403 """
363 Private slot to create the debugger interface object. 404 Private slot to create the debugger interface object.
364 405
365 @param clientType type of the client interface to be created (string) 406 @param clientType type of the client interface to be created (string)
366 """ 407 """
367 # TODO: eric 6.2: make debugger interfaces be registered in order to
368 # allow to implement a debugger backend as a plug-in.
369 if self.lastClientType != self.clientType or clientType is not None: 408 if self.lastClientType != self.clientType or clientType is not None:
370 if clientType is None: 409 if clientType is None:
371 clientType = self.clientType 410 clientType = self.clientType
372 if clientType == "Python2": 411 if clientType in self.__debuggerInterfaceRegistry:
373 from .DebuggerInterfacePython import DebuggerInterfacePython 412 self.debuggerInterface = \
374 self.debuggerInterface = DebuggerInterfacePython( 413 self.__debuggerInterfaceRegistry[clientType][2](
375 self, self.passive) 414 self, self.passive)
376 elif clientType == "Python3":
377 from .DebuggerInterfacePython3 import DebuggerInterfacePython3
378 self.debuggerInterface = DebuggerInterfacePython3(
379 self, self.passive)
380 elif clientType == "Ruby":
381 from .DebuggerInterfaceRuby import DebuggerInterfaceRuby
382 self.debuggerInterface = DebuggerInterfaceRuby(
383 self, self.passive)
384 elif clientType == "None":
385 from .DebuggerInterfaceNone import DebuggerInterfaceNone
386 self.debuggerInterface = DebuggerInterfaceNone(
387 self, self.passive)
388 else: 415 else:
389 from .DebuggerInterfaceNone import DebuggerInterfaceNone 416 self.debuggerInterface = \
390 self.debuggerInterface = DebuggerInterfaceNone( 417 self.__debuggerInterfaceRegistry["None"][2](
391 self, self.passive) 418 self, self.passive)
392 self.clientType = "None" 419 self.clientType = "None"
393 420
394 def __setClientType(self, clType): 421 def __setClientType(self, clType):
395 """ 422 """
396 Private method to set the client type. 423 Private method to set the client type.
672 699
673 @param type debug client type (string) 700 @param type debug client type (string)
674 @return debug client capabilities (integer) 701 @return debug client capabilities (integer)
675 """ 702 """
676 try: 703 try:
677 return self.__clientCapabilities[type] 704 return self.__debuggerInterfaceRegistry[type][0]
678 except KeyError: 705 except KeyError:
679 return 0 # no capabilities 706 return 0 # no capabilities
680 707
681 def getClientInterpreter(self): 708 def getClientInterpreter(self):
682 """ 709 """
790 try: 817 try:
791 if clientType: 818 if clientType:
792 self.__setClientType(clientType) 819 self.__setClientType(clientType)
793 else: 820 else:
794 self.__setClientType( 821 self.__setClientType(
795 self.__clientAssociations[os.path.splitext(fn)[1]]) 822 self.__findLanguageForExtension(os.path.splitext(fn)[1]))
796 except KeyError: 823 except KeyError:
797 self.__setClientType('Python3') # assume it is a Python3 file 824 self.__setClientType('Python3') # assume it is a Python3 file
798 self.startClient(False, forProject=forProject, 825 self.startClient(False, forProject=forProject,
799 runInConsole=runInConsole) 826 runInConsole=runInConsole)
800 827
835 try: 862 try:
836 if clientType: 863 if clientType:
837 self.__setClientType(clientType) 864 self.__setClientType(clientType)
838 else: 865 else:
839 self.__setClientType( 866 self.__setClientType(
840 self.__clientAssociations[os.path.splitext(fn)[1]]) 867 self.__findLanguageForExtension(os.path.splitext(fn)[1]))
841 except KeyError: 868 except KeyError:
842 self.__setClientType('Python3') # assume it is a Python3 file 869 self.__setClientType('Python3') # assume it is a Python3 file
843 self.startClient(False, forProject=forProject, 870 self.startClient(False, forProject=forProject,
844 runInConsole=runInConsole) 871 runInConsole=runInConsole)
845 872
874 try: 901 try:
875 if clientType: 902 if clientType:
876 self.__setClientType(clientType) 903 self.__setClientType(clientType)
877 else: 904 else:
878 self.__setClientType( 905 self.__setClientType(
879 self.__clientAssociations[os.path.splitext(fn)[1]]) 906 self.__findLanguageForExtension(os.path.splitext(fn)[1]))
880 except KeyError: 907 except KeyError:
881 self.__setClientType('Python3') # assume it is a Python3 file 908 self.__setClientType('Python3') # assume it is a Python3 file
882 self.startClient(False, forProject=forProject, 909 self.startClient(False, forProject=forProject,
883 runInConsole=runInConsole) 910 runInConsole=runInConsole)
884 911
914 try: 941 try:
915 if clientType: 942 if clientType:
916 self.__setClientType(clientType) 943 self.__setClientType(clientType)
917 else: 944 else:
918 self.__setClientType( 945 self.__setClientType(
919 self.__clientAssociations[os.path.splitext(fn)[1]]) 946 self.__findLanguageForExtension(os.path.splitext(fn)[1]))
920 except KeyError: 947 except KeyError:
921 self.__setClientType('Python3') # assume it is a Python3 file 948 self.__setClientType('Python3') # assume it is a Python3 file
922 self.startClient(False, forProject=forProject, 949 self.startClient(False, forProject=forProject,
923 runInConsole=runInConsole) 950 runInConsole=runInConsole)
924 951
1159 try: 1186 try:
1160 if clientType: 1187 if clientType:
1161 self.__setClientType(clientType) 1188 self.__setClientType(clientType)
1162 else: 1189 else:
1163 self.__setClientType( 1190 self.__setClientType(
1164 self.__clientAssociations[os.path.splitext(fn)[1]]) 1191 self.__findLanguageForExtension(os.path.splitext(fn)[1]))
1165 except KeyError: 1192 except KeyError:
1166 self.__setClientType('Python3') # assume it is a Python3 file 1193 self.__setClientType('Python3') # assume it is a Python3 file
1167 self.startClient(False) 1194 self.startClient(False)
1168 1195
1169 self.debuggerInterface.remoteUTPrepare( 1196 self.debuggerInterface.remoteUTPrepare(
1378 Public method to process the client capabilities info. 1405 Public method to process the client capabilities info.
1379 1406
1380 @param capabilities bitmaks with the client capabilities (integer) 1407 @param capabilities bitmaks with the client capabilities (integer)
1381 @param clientType type of the debug client (string) 1408 @param clientType type of the debug client (string)
1382 """ 1409 """
1383 self.__clientCapabilities[clientType] = capabilities 1410 self.__debuggerInterfaceRegistry[clientType][0] = capabilities
1384 self.clientCapabilities.emit(capabilities, clientType) 1411 self.clientCapabilities.emit(capabilities, clientType)
1385 1412
1386 def signalClientCompletionList(self, completionList, text): 1413 def signalClientCompletionList(self, completionList, text):
1387 """ 1414 """
1388 Public method to process the client auto completion info. 1415 Public method to process the client auto completion info.

eric ide

mercurial