src/eric7/PluginManager/PluginManager.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9299
e40589582f82
--- a/src/eric7/PluginManager/PluginManager.py	Wed Jul 13 11:16:20 2022 +0200
+++ b/src/eric7/PluginManager/PluginManager.py	Wed Jul 13 14:55:47 2022 +0200
@@ -18,25 +18,27 @@
 
 from PyQt6.QtCore import pyqtSignal, QObject, QFile, QUrl, QIODevice
 from PyQt6.QtGui import QPixmap
-from PyQt6.QtNetwork import (
-    QNetworkAccessManager, QNetworkRequest, QNetworkReply
-)
+from PyQt6.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
 
 from EricWidgets import EricMessageBox
 from EricWidgets.EricApplication import ericApp
 
 from EricNetwork.EricNetworkProxyFactory import proxyAuthenticationRequired
+
 try:
-    from EricNetwork.EricSslErrorHandler import (
-        EricSslErrorHandler, EricSslErrorState
-    )
+    from EricNetwork.EricSslErrorHandler import EricSslErrorHandler, EricSslErrorState
+
     SSL_AVAILABLE = True
 except ImportError:
     SSL_AVAILABLE = False
 
 from .PluginExceptions import (
-    PluginPathError, PluginModulesError, PluginLoadError,
-    PluginActivationError, PluginModuleFormatError, PluginClassFormatError
+    PluginPathError,
+    PluginModulesError,
+    PluginLoadError,
+    PluginActivationError,
+    PluginModuleFormatError,
+    PluginClassFormatError,
 )
 
 import UI.PixmapCache
@@ -51,7 +53,7 @@
 class PluginManager(QObject):
     """
     Class implementing the Plugin Manager.
-    
+
     @signal shutdown() emitted at shutdown of the IDE
     @signal pluginAboutToBeActivated(modulName, pluginObject) emitted just
         before a plugin is activated
@@ -66,6 +68,7 @@
     @signal pluginRepositoryFileDownloaded() emitted to indicate a completed
         download of the plugin repository file
     """
+
     shutdown = pyqtSignal()
     pluginAboutToBeActivated = pyqtSignal(str, object)
     pluginActivated = pyqtSignal(str, object)
@@ -73,19 +76,20 @@
     pluginAboutToBeDeactivated = pyqtSignal(str, object)
     pluginDeactivated = pyqtSignal(str, object)
     pluginRepositoryFileDownloaded = pyqtSignal()
-    
-    def __init__(self, parent=None, disabledPlugins=None, doLoadPlugins=True,
-                 develPlugin=None):
+
+    def __init__(
+        self, parent=None, disabledPlugins=None, doLoadPlugins=True, develPlugin=None
+    ):
         """
         Constructor
-        
+
         The Plugin Manager deals with three different plugin directories.
         The first is the one, that is part of eric7 (eric7/Plugins). The
         second one is the global plugin directory called 'eric7plugins',
         which is located inside the site-packages directory. The last one
         is the user plugin directory located inside the .eric7 directory
         of the users home directory.
-        
+
         @param parent reference to the parent object
         @type QObject
         @param disabledPlugins list of plug-ins that have been disabled via
@@ -102,7 +106,7 @@
             plug-in modules
         """
         super().__init__(parent)
-        
+
         self.__ui = parent
         self.__develPluginFile = develPlugin
         self.__develPluginName = None
@@ -110,20 +114,20 @@
             self.__disabledPlugins = disabledPlugins[:]
         else:
             self.__disabledPlugins = []
-        
+
         self.__inactivePluginsKey = "PluginManager/InactivePlugins"
-        
+
         self.pluginDirs = {
-            "eric7": os.path.join(getConfig('ericDir'), "Plugins"),
-            "global": os.path.join(Utilities.getPythonLibraryDirectory(),
-                                   "eric7plugins"),
+            "eric7": os.path.join(getConfig("ericDir"), "Plugins"),
+            "global": os.path.join(
+                Utilities.getPythonLibraryDirectory(), "eric7plugins"
+            ),
             "user": os.path.join(Utilities.getConfigDir(), "eric7plugins"),
         }
         self.__priorityOrder = ["eric7", "global", "user"]
-        
-        self.__defaultDownloadDir = os.path.join(
-            Utilities.getConfigDir(), "Downloads")
-        
+
+        self.__defaultDownloadDir = os.path.join(Utilities.getConfigDir(), "Downloads")
+
         self.__activePlugins = {}
         self.__inactivePlugins = {}
         self.__onDemandActivePlugins = {}
@@ -133,54 +137,55 @@
         self.__onDemandActiveModules = {}
         self.__onDemandInactiveModules = {}
         self.__failedModules = {}
-        
+
         self.__foundCoreModules = []
         self.__foundGlobalModules = []
         self.__foundUserModules = []
-        
+
         self.__modulesCount = 0
-        
+
         pdirsExist, msg = self.__pluginDirectoriesExist()
         if not pdirsExist:
             raise PluginPathError(msg)
-        
+
         if doLoadPlugins:
             if not self.__pluginModulesExist():
                 raise PluginModulesError
-            
+
             self.__insertPluginsPaths()
-            
+
             self.__loadPlugins()
-        
+
         self.__checkPluginsDownloadDirectory()
-        
-        self.pluginRepositoryFile = os.path.join(Utilities.getConfigDir(),
-                                                 "PluginRepository")
-        
+
+        self.pluginRepositoryFile = os.path.join(
+            Utilities.getConfigDir(), "PluginRepository"
+        )
+
         # attributes for the network objects
         self.__networkManager = QNetworkAccessManager(self)
         self.__networkManager.proxyAuthenticationRequired.connect(
-            proxyAuthenticationRequired)
+            proxyAuthenticationRequired
+        )
         if SSL_AVAILABLE:
             self.__sslErrorHandler = EricSslErrorHandler(self)
             self.__networkManager.sslErrors.connect(self.__sslErrors)
         self.__replies = []
-        
+
     def finalizeSetup(self):
         """
         Public method to finalize the setup of the plugin manager.
         """
-        for module in (
-            list(self.__onDemandInactiveModules.values()) +
-            list(self.__onDemandActiveModules.values())
+        for module in list(self.__onDemandInactiveModules.values()) + list(
+            self.__onDemandActiveModules.values()
         ):
             if hasattr(module, "moduleSetup"):
                 module.moduleSetup()
-        
+
     def getPluginDir(self, key):
         """
         Public method to get the path of a plugin directory.
-        
+
         @param key key of the plug-in directory (string)
         @return path of the requested plugin directory (string)
         """
@@ -191,13 +196,13 @@
                 return self.pluginDirs[key]
             except KeyError:
                 return None
-    
+
     def __pluginDirectoriesExist(self):
         """
         Private method to check, if the plugin folders exist.
-        
+
         If the plugin folders don't exist, they are created (if possible).
-        
+
         @return tuple of a flag indicating existence of any of the plugin
             directories (boolean) and a message (string)
         """
@@ -211,9 +216,11 @@
                 except OSError:
                     return (
                         False,
-                        self.tr("Could not create a package for {0}.")
-                            .format(self.__develPluginFile))
-        
+                        self.tr("Could not create a package for {0}.").format(
+                            self.__develPluginFile
+                        ),
+                    )
+
         fname = os.path.join(self.pluginDirs["user"], "__init__.py")
         if not os.path.exists(fname):
             if not os.path.exists(self.pluginDirs["user"]):
@@ -223,77 +230,81 @@
                     pass
             except OSError:
                 del self.pluginDirs["user"]
-        
+
         if not os.path.exists(self.pluginDirs["global"]):
             try:
                 # create the global plugins directory
                 os.mkdir(self.pluginDirs["global"], 0o755)
                 fname = os.path.join(self.pluginDirs["global"], "__init__.py")
                 with open(fname, "w", encoding="utf-8") as f:
-                    f.write('# -*- coding: utf-8 -*-' + "\n")
+                    f.write("# -*- coding: utf-8 -*-" + "\n")
                     f.write("\n")
                     f.write('"""' + "\n")
-                    f.write('Package containing the global plugins.' + "\n")
+                    f.write("Package containing the global plugins." + "\n")
                     f.write('"""' + "\n")
             except OSError:
                 del self.pluginDirs["global"]
-        
+
         if not os.path.exists(self.pluginDirs["eric7"]):
             return (
                 False,
                 self.tr(
-                    "The internal plugin directory <b>{0}</b>"
-                    " does not exits.").format(self.pluginDirs["eric7"]))
-        
+                    "The internal plugin directory <b>{0}</b>" " does not exits."
+                ).format(self.pluginDirs["eric7"]),
+            )
+
         return (True, "")
-    
+
     def __pluginModulesExist(self):
         """
         Private method to check, if there are plugins available.
-        
+
         @return flag indicating the availability of plugins (boolean)
         """
-        if (
-            self.__develPluginFile and
-            not os.path.exists(self.__develPluginFile)
-        ):
+        if self.__develPluginFile and not os.path.exists(self.__develPluginFile):
             return False
-        
-        self.__foundCoreModules = self.getPluginModules(
-            self.pluginDirs["eric7"])
+
+        self.__foundCoreModules = self.getPluginModules(self.pluginDirs["eric7"])
         if Preferences.getPluginManager("ActivateExternal"):
             if "global" in self.pluginDirs:
                 self.__foundGlobalModules = self.getPluginModules(
-                    self.pluginDirs["global"])
+                    self.pluginDirs["global"]
+                )
             if "user" in self.pluginDirs:
-                self.__foundUserModules = self.getPluginModules(
-                    self.pluginDirs["user"])
-        
-        return len(self.__foundCoreModules + self.__foundGlobalModules +
-                   self.__foundUserModules) > 0
-    
+                self.__foundUserModules = self.getPluginModules(self.pluginDirs["user"])
+
+        return (
+            len(
+                self.__foundCoreModules
+                + self.__foundGlobalModules
+                + self.__foundUserModules
+            )
+            > 0
+        )
+
     def getPluginModules(self, pluginPath):
         """
         Public method to get a list of plugin modules.
-        
+
         @param pluginPath name of the path to search (string)
         @return list of plugin module names (list of string)
         """
-        pluginFiles = [f[:-3] for f in os.listdir(pluginPath)
-                       if self.isValidPluginName(f)]
+        pluginFiles = [
+            f[:-3] for f in os.listdir(pluginPath) if self.isValidPluginName(f)
+        ]
         return pluginFiles[:]
-    
+
     def isValidPluginName(self, pluginName):
         """
         Public method to check, if a file name is a valid plugin name.
-        
+
         Plugin modules must start with "Plugin" and have the extension ".py".
-        
+
         @param pluginName name of the file to be checked (string)
         @return flag indicating a valid plugin name (boolean)
         """
         return pluginName.startswith("Plugin") and pluginName.endswith(".py")
-    
+
     def __insertPluginsPaths(self):
         """
         Private method to insert the valid plugin paths intos the search path.
@@ -303,13 +314,13 @@
                 if self.pluginDirs[key] not in sys.path:
                     sys.path.insert(2, self.pluginDirs[key])
                 UI.PixmapCache.addSearchPath(self.pluginDirs[key])
-        
+
         if self.__develPluginFile:
             path = Utilities.splitPath(self.__develPluginFile)[0]
             if path not in sys.path:
                 sys.path.insert(2, path)
             UI.PixmapCache.addSearchPath(path)
-    
+
     def __loadPlugins(self):
         """
         Private method to load the plugins found.
@@ -317,79 +328,79 @@
         develPluginName = ""
         if self.__develPluginFile:
             develPluginPath, develPluginName = Utilities.splitPath(
-                self.__develPluginFile)
+                self.__develPluginFile
+            )
             if self.isValidPluginName(develPluginName):
                 develPluginName = develPluginName[:-3]
-        
+
         for pluginName in self.__foundGlobalModules:
             # user and core plug-ins have priority
             if (
-                pluginName not in self.__foundUserModules and
-                pluginName not in self.__foundCoreModules and
-                pluginName != develPluginName
+                pluginName not in self.__foundUserModules
+                and pluginName not in self.__foundCoreModules
+                and pluginName != develPluginName
             ):
                 self.loadPlugin(pluginName, self.pluginDirs["global"])
-        
+
         for pluginName in self.__foundUserModules:
             # core plug-ins have priority
             if (
-                pluginName not in self.__foundCoreModules and
-                pluginName != develPluginName
+                pluginName not in self.__foundCoreModules
+                and pluginName != develPluginName
             ):
                 self.loadPlugin(pluginName, self.pluginDirs["user"])
-        
+
         for pluginName in self.__foundCoreModules:
             # plug-in under development has priority
             if pluginName != develPluginName:
                 self.loadPlugin(pluginName, self.pluginDirs["eric7"])
-        
+
         if develPluginName:
             self.loadPlugin(develPluginName, develPluginPath)
             self.__develPluginName = develPluginName
-    
+
     def loadDocumentationSetPlugins(self):
         """
         Public method to load just the documentation sets plugins.
-        
+
         @exception PluginModulesError raised to indicate the absence of
             plug-in modules
         """
         if not self.__pluginModulesExist():
             raise PluginModulesError
-        
+
         self.__insertPluginsPaths()
-        
+
         for pluginName in self.__foundGlobalModules:
             # user and core plug-ins have priority
             if (
-                pluginName not in self.__foundUserModules and
-                pluginName not in self.__foundCoreModules and
-                pluginName.startswith("PluginDocumentationSets")
+                pluginName not in self.__foundUserModules
+                and pluginName not in self.__foundCoreModules
+                and pluginName.startswith("PluginDocumentationSets")
             ):
                 self.loadPlugin(pluginName, self.pluginDirs["global"])
-        
+
         for pluginName in self.__foundUserModules:
             # core plug-ins have priority
-            if (
-                pluginName not in self.__foundCoreModules and
-                pluginName.startswith("PluginDocumentationSets")
+            if pluginName not in self.__foundCoreModules and pluginName.startswith(
+                "PluginDocumentationSets"
             ):
                 self.loadPlugin(pluginName, self.pluginDirs["user"])
-        
+
         for pluginName in self.__foundCoreModules:
             # plug-in under development has priority
             if pluginName.startswith("PluginDocumentationSets"):
                 self.loadPlugin(pluginName, self.pluginDirs["eric7"])
-    
+
     def loadPlugin(self, name, directory, reload_=False, install=False):
         """
         Public method to load a plugin module.
-        
+
         Initially all modules are inactive. Modules that are requested on
         demand are sorted out and are added to the on demand list. Some
         basic validity checks are performed as well. Modules failing these
         checks are added to the failed modules list.
-        
+
         @param name name of the module to be loaded
         @type str
         @param directory name of the plugin directory
@@ -410,15 +421,15 @@
             spec.loader.exec_module(module)
             if not hasattr(module, "autoactivate"):
                 module.error = self.tr(
-                    "Module is missing the 'autoactivate' attribute.")
+                    "Module is missing the 'autoactivate' attribute."
+                )
                 self.__failedModules[name] = module
                 raise PluginLoadError(name)
             if getattr(module, "autoactivate", False):
                 self.__inactiveModules[name] = module
             else:
-                if (
-                    not hasattr(module, "pluginType") or
-                    not hasattr(module, "pluginTypename")
+                if not hasattr(module, "pluginType") or not hasattr(
+                    module, "pluginTypename"
                 ):
                     module.error = self.tr(
                         "Module is missing the 'pluginType' "
@@ -431,10 +442,8 @@
             module.eric7PluginModuleName = name
             module.eric7PluginModuleFilename = fname
             if (
-                (install or
-                 Preferences.getPluginManager("AutoInstallDependencies")) and
-                hasattr(module, "installDependencies")
-            ):
+                install or Preferences.getPluginManager("AutoInstallDependencies")
+            ) and hasattr(module, "installDependencies"):
                 # ask the module to install its dependencies
                 module.installDependencies(self.pipInstall)
             self.__modulesCount += 1
@@ -444,31 +453,31 @@
                 with contextlib.suppress(KeyError, AttributeError):
                     pluginObject = self.__onDemandInactivePlugins[name]
                     pluginObject.initToolbar(
-                        self.__ui, ericApp().getObject("ToolbarManager"))
+                        self.__ui, ericApp().getObject("ToolbarManager")
+                    )
         except PluginLoadError:
             print("Error loading plug-in module:", name)
         except Exception as err:
             module = types.ModuleType(name)
-            module.error = self.tr(
-                "Module failed to load. Error: {0}").format(str(err))
+            module.error = self.tr("Module failed to load. Error: {0}").format(str(err))
             self.__failedModules[name] = module
             print("Error loading plug-in module:", name)
             print(str(err))
-    
+
     def unloadPlugin(self, name):
         """
         Public method to unload a plugin module.
-        
+
         @param name name of the module to be unloaded (string)
         @return flag indicating success (boolean)
         """
         if name in self.__onDemandActiveModules:
             # cannot unload an ondemand plugin, that is in use
             return False
-        
+
         if name in self.__activeModules:
             self.deactivatePlugin(name)
-        
+
         if name in self.__inactiveModules:
             with contextlib.suppress(KeyError):
                 pluginObject = self.__inactivePlugins[name]
@@ -485,16 +494,15 @@
             del self.__onDemandInactiveModules[name]
         elif name in self.__failedModules:
             del self.__failedModules[name]
-        
+
         self.__modulesCount -= 1
         return True
-    
-    def removePluginFromSysModules(self, pluginName, package,
-                                   internalPackages):
+
+    def removePluginFromSysModules(self, pluginName, package, internalPackages):
         """
         Public method to remove a plugin and all related modules from
         sys.modules.
-        
+
         @param pluginName name of the plugin module (string)
         @param package name of the plugin package (string)
         @param internalPackages list of intenal packages (list of string)
@@ -506,30 +514,27 @@
         if not package:
             package = "__None__"
         for moduleName in list(sys.modules.keys())[:]:
-            if (
-                moduleName == pluginName or
-                moduleName.split(".")[0] in packages
-            ):
+            if moduleName == pluginName or moduleName.split(".")[0] in packages:
                 found = True
                 del sys.modules[moduleName]
         return found
-    
+
     def initOnDemandPlugins(self):
         """
         Public method to create plugin objects for all on demand plugins.
-        
+
         Note: The plugins are not activated.
         """
         names = sorted(self.__onDemandInactiveModules.keys())
         for name in names:
             self.initOnDemandPlugin(name)
-    
+
     def initOnDemandPlugin(self, name):
         """
         Public method to create a plugin object for the named on demand plugin.
-        
+
         Note: The plug-in is not activated.
-        
+
         @param name name of the plug-in (string)
         @exception PluginActivationError raised to indicate an issue during the
             plug-in activation
@@ -539,7 +544,7 @@
                 module = self.__onDemandInactiveModules[name]
             except KeyError:
                 return
-            
+
             if not self.__canActivatePlugin(module):
                 raise PluginActivationError(module.eric7PluginModuleName)
             version = getattr(module, "version", "0.0.0")
@@ -554,11 +559,11 @@
                 self.__onDemandInactivePlugins[name] = pluginObject
         except PluginActivationError:
             return
-    
+
     def initPluginToolbars(self, toolbarManager):
         """
         Public method to initialize plug-in toolbars.
-        
+
         @param toolbarManager reference to the toolbar manager object
             (EricToolBarManager)
         """
@@ -566,21 +571,21 @@
         for pluginObject in self.__onDemandInactivePlugins.values():
             with contextlib.suppress(AttributeError):
                 pluginObject.initToolbar(self.__ui, toolbarManager)
-    
+
     def activatePlugins(self):
         """
         Public method to activate all plugins having the "autoactivate"
         attribute set to True.
         """
-        savedInactiveList = Preferences.getSettings().value(
-            self.__inactivePluginsKey)
+        savedInactiveList = Preferences.getSettings().value(self.__inactivePluginsKey)
         inactiveList = self.__disabledPlugins[:]
         if savedInactiveList is not None:
-            inactiveList += [p for p in savedInactiveList
-                             if p not in self.__disabledPlugins]
+            inactiveList += [
+                p for p in savedInactiveList if p not in self.__disabledPlugins
+            ]
         if (
-            self.__develPluginName is not None and
-            self.__develPluginName in inactiveList
+            self.__develPluginName is not None
+            and self.__develPluginName in inactiveList
         ):
             inactiveList.remove(self.__develPluginName)
         names = sorted(self.__inactiveModules.keys())
@@ -588,11 +593,11 @@
             if name not in inactiveList:
                 self.activatePlugin(name)
         self.allPlugginsActivated.emit()
-    
+
     def activatePlugin(self, name, onDemand=False):
         """
         Public method to activate a plugin.
-        
+
         @param name name of the module to be activated
         @param onDemand flag indicating activation of an
             on demand plugin (boolean)
@@ -604,12 +609,12 @@
             try:
                 module = (
                     self.__onDemandInactiveModules[name]
-                    if onDemand else
-                    self.__inactiveModules[name]
+                    if onDemand
+                    else self.__inactiveModules[name]
                 )
             except KeyError:
                 return None
-            
+
             if not self.__canActivatePlugin(module):
                 raise PluginActivationError(module.eric7PluginModuleName)
             version = getattr(module, "version", "0.0.0")
@@ -626,8 +631,7 @@
             try:
                 obj, ok = pluginObject.activate()
             except TypeError:
-                module.error = self.tr(
-                    "Incompatible plugin activation method.")
+                module.error = self.tr("Incompatible plugin activation method.")
                 obj = None
                 ok = True
             except Exception as err:
@@ -636,12 +640,12 @@
                 ok = False
             if not ok:
                 return None
-            
+
             self.pluginActivated.emit(name, pluginObject)
             pluginObject.eric7PluginModule = module
             pluginObject.eric7PluginName = className
             pluginObject.eric7PluginVersion = version
-            
+
             if onDemand:
                 self.__onDemandInactiveModules.pop(name)
                 with contextlib.suppress(KeyError):
@@ -657,11 +661,11 @@
             return obj
         except PluginActivationError:
             return None
-    
+
     def __canActivatePlugin(self, module):
         """
         Private method to check, if a plugin can be activated.
-        
+
         @param module reference to the module to be activated
         @return flag indicating, if the module satisfies all requirements
             for being activated (boolean)
@@ -672,28 +676,25 @@
         """
         try:
             if not hasattr(module, "version"):
-                raise PluginModuleFormatError(
-                    module.eric7PluginModuleName, "version")
+                raise PluginModuleFormatError(module.eric7PluginModuleName, "version")
             if not hasattr(module, "className"):
-                raise PluginModuleFormatError(
-                    module.eric7PluginModuleName, "className")
+                raise PluginModuleFormatError(module.eric7PluginModuleName, "className")
             className = getattr(module, "className", "")
             if not className or not hasattr(module, className):
-                raise PluginModuleFormatError(
-                    module.eric7PluginModuleName, className)
+                raise PluginModuleFormatError(module.eric7PluginModuleName, className)
             pluginClass = getattr(module, className)
             if not hasattr(pluginClass, "__init__"):
                 raise PluginClassFormatError(
-                    module.eric7PluginModuleName,
-                    className, "__init__")
+                    module.eric7PluginModuleName, className, "__init__"
+                )
             if not hasattr(pluginClass, "activate"):
                 raise PluginClassFormatError(
-                    module.eric7PluginModuleName,
-                    className, "activate")
+                    module.eric7PluginModuleName, className, "activate"
+                )
             if not hasattr(pluginClass, "deactivate"):
                 raise PluginClassFormatError(
-                    module.eric7PluginModuleName,
-                    className, "deactivate")
+                    module.eric7PluginModuleName, className, "deactivate"
+                )
             return True
         except PluginModuleFormatError as e:
             print(repr(e))
@@ -701,11 +702,11 @@
         except PluginClassFormatError as e:
             print(repr(e))
             return False
-    
+
     def deactivatePlugin(self, name, onDemand=False):
         """
         Public method to deactivate a plugin.
-        
+
         @param name name of the module to be deactivated
         @param onDemand flag indicating deactivation of an
             on demand plugin (boolean)
@@ -713,12 +714,12 @@
         try:
             module = (
                 self.__onDemandActiveModules[name]
-                if onDemand else
-                self.__activeModules[name]
+                if onDemand
+                else self.__activeModules[name]
             )
         except KeyError:
             return
-        
+
         if self.__canDeactivatePlugin(module):
             pluginObject = None
             if onDemand and name in self.__onDemandActivePlugins:
@@ -729,7 +730,7 @@
                 self.pluginAboutToBeDeactivated.emit(name, pluginObject)
                 pluginObject.deactivate()
                 self.pluginDeactivated.emit(name, pluginObject)
-                
+
                 if onDemand:
                     self.__onDemandActiveModules.pop(name)
                     self.__onDemandActivePlugins.pop(name)
@@ -741,22 +742,22 @@
                         self.__activePlugins.pop(name)
                     self.__inactivePlugins[name] = pluginObject
                     self.__inactiveModules[name] = module
-    
+
     def __canDeactivatePlugin(self, module):
         """
         Private method to check, if a plugin can be deactivated.
-        
+
         @param module reference to the module to be deactivated
         @return flag indicating, if the module satisfies all requirements
             for being deactivated (boolean)
         """
         return getattr(module, "deactivateable", True)
-    
+
     def getPluginObject(self, type_, typename, maybeActive=False):
         """
         Public method to activate an ondemand plugin given by type and
         typename.
-        
+
         @param type_ type of the plugin to be activated (string)
         @param typename name of the plugin within the type category (string)
         @param maybeActive flag indicating, that the plugin may be active
@@ -765,26 +766,26 @@
         """
         for name, module in list(self.__onDemandInactiveModules.items()):
             if (
-                getattr(module, "pluginType", "") == type_ and
-                getattr(module, "pluginTypename", "") == typename
+                getattr(module, "pluginType", "") == type_
+                and getattr(module, "pluginTypename", "") == typename
             ):
                 return self.activatePlugin(name, onDemand=True)
-        
+
         if maybeActive:
             for name, module in list(self.__onDemandActiveModules.items()):
                 if (
-                    getattr(module, "pluginType", "") == type_ and
-                    getattr(module, "pluginTypename", "") == typename
+                    getattr(module, "pluginType", "") == type_
+                    and getattr(module, "pluginTypename", "") == typename
                 ):
                     self.deactivatePlugin(name, onDemand=True)
                     return self.activatePlugin(name, onDemand=True)
-        
+
         return None
-    
+
     def getPluginInfos(self):
         """
         Public method to get infos about all loaded plug-ins.
-        
+
         @return list of dictionaries with keys "module_name", "plugin_name",
             "version", "auto_activate", "active", "short_desc", "error"
         @rtype list of dict ("module_name": str, "plugin_name": str,
@@ -792,63 +793,73 @@
             "short_desc": str, "error": bool)
         """
         infos = []
-        
+
         # 1. active, non-on-demand modules
         for name in list(self.__activeModules.keys()):
             info = self.__getShortInfo(self.__activeModules[name])
-            info.update({
-                "module_name": name,
-                "auto_activate": True,
-                "active": True,
-            })
+            info.update(
+                {
+                    "module_name": name,
+                    "auto_activate": True,
+                    "active": True,
+                }
+            )
             infos.append(info)
-        
+
         # 2. inactive, non-on-demand modules
         for name in list(self.__inactiveModules.keys()):
             info = self.__getShortInfo(self.__inactiveModules[name])
-            info.update({
-                "module_name": name,
-                "auto_activate": True,
-                "active": False,
-            })
+            info.update(
+                {
+                    "module_name": name,
+                    "auto_activate": True,
+                    "active": False,
+                }
+            )
             infos.append(info)
-        
+
         # 3. active, on-demand modules
         for name in list(self.__onDemandActiveModules.keys()):
             info = self.__getShortInfo(self.__onDemandActiveModules[name])
-            info.update({
-                "module_name": name,
-                "auto_activate": False,
-                "active": True,
-            })
+            info.update(
+                {
+                    "module_name": name,
+                    "auto_activate": False,
+                    "active": True,
+                }
+            )
             infos.append(info)
-        
+
         # 4. inactive, non-on-demand modules
         for name in list(self.__onDemandInactiveModules.keys()):
             info = self.__getShortInfo(self.__onDemandInactiveModules[name])
-            info.update({
-                "module_name": name,
-                "auto_activate": False,
-                "active": False,
-            })
+            info.update(
+                {
+                    "module_name": name,
+                    "auto_activate": False,
+                    "active": False,
+                }
+            )
             infos.append(info)
-        
+
         # 5. failed modules
         for name in list(self.__failedModules.keys()):
             info = self.__getShortInfo(self.__failedModules[name])
-            info.update({
-                "module_name": name,
-                "auto_activate": False,
-                "active": False,
-            })
+            info.update(
+                {
+                    "module_name": name,
+                    "auto_activate": False,
+                    "active": False,
+                }
+            )
             infos.append(info)
-        
+
         return infos
-    
+
     def __getShortInfo(self, module):
         """
         Private method to extract the short info from a module.
-        
+
         @param module module to extract short info from
         @return dictionay containing plug-in data
         @rtype dict ("plugin_name": str, "version": str, "short_desc": str,
@@ -860,19 +871,19 @@
             "short_desc": getattr(module, "shortDescription", ""),
             "error": bool(getattr(module, "error", "")),
         }
-    
+
     def getPluginDetails(self, name):
         """
         Public method to get detailed information about a plugin.
-        
+
         @param name name of the module to get detailed infos about (string)
         @return details of the plugin as a dictionary
         """
         details = {}
-        
+
         autoactivate = True
         active = True
-        
+
         if name in self.__activeModules:
             module = self.__activeModules[name]
         elif name in self.__inactiveModules:
@@ -895,10 +906,9 @@
         else:
             # should not happen
             return None
-        
+
         details["moduleName"] = name
-        details["moduleFileName"] = getattr(
-            module, "eric7PluginModuleFilename", "")
+        details["moduleFileName"] = getattr(module, "eric7PluginModuleFilename", "")
         details["pluginName"] = getattr(module, "name", "")
         details["version"] = getattr(module, "version", "")
         details["author"] = getattr(module, "author", "")
@@ -906,9 +916,9 @@
         details["autoactivate"] = autoactivate
         details["active"] = active
         details["error"] = getattr(module, "error", "")
-        
+
         return details
-    
+
     def doShutdown(self):
         """
         Public method called to perform actions upon shutdown of the IDE.
@@ -917,27 +927,26 @@
         for name in list(self.__inactiveModules.keys()):
             names.append(name)
         Preferences.getSettings().setValue(self.__inactivePluginsKey, names)
-        
+
         self.shutdown.emit()
 
     def getPluginDisplayStrings(self, type_):
         """
         Public method to get the display strings of all plugins of a specific
         type.
-        
+
         @param type_ type of the plugins (string)
         @return dictionary with name as key and display string as value
             (dictionary of string)
         """
         pluginDict = {}
-        
-        for module in (
-            list(self.__onDemandActiveModules.values()) +
-            list(self.__onDemandInactiveModules.values())
+
+        for module in list(self.__onDemandActiveModules.values()) + list(
+            self.__onDemandInactiveModules.values()
         ):
             if (
-                getattr(module, "pluginType", "") == type_ and
-                getattr(module, "error", "") == ""
+                getattr(module, "pluginType", "") == type_
+                and getattr(module, "error", "") == ""
             ):
                 plugin_name = getattr(module, "pluginTypename", "")
                 if plugin_name:
@@ -950,74 +959,71 @@
                             pluginDict[plugin_name] = disp
                     else:
                         pluginDict[plugin_name] = plugin_name
-        
+
         return pluginDict
-        
+
     def getPluginPreviewPixmap(self, type_, name):
         """
         Public method to get a preview pixmap of a plugin of a specific type.
-        
+
         @param type_ type of the plugin (string)
         @param name name of the plugin type (string)
         @return preview pixmap (QPixmap)
         """
-        for module in (
-            list(self.__onDemandActiveModules.values()) +
-            list(self.__onDemandInactiveModules.values())
+        for module in list(self.__onDemandActiveModules.values()) + list(
+            self.__onDemandInactiveModules.values()
         ):
             if (
-                getattr(module, "pluginType", "") == type_ and
-                getattr(module, "pluginTypename", "") == name
+                getattr(module, "pluginType", "") == type_
+                and getattr(module, "pluginTypename", "") == name
             ):
                 if hasattr(module, "previewPix"):
                     return module.previewPix()
                 else:
                     return QPixmap()
-        
+
         return QPixmap()
-        
+
     def getPluginApiFiles(self, language):
         """
         Public method to get the list of API files installed by a plugin.
-        
+
         @param language language of the requested API files (string)
         @return list of API filenames (list of string)
         """
         apis = []
-        
-        for module in (
-            list(self.__activeModules.values()) +
-            list(self.__onDemandActiveModules.values())
+
+        for module in list(self.__activeModules.values()) + list(
+            self.__onDemandActiveModules.values()
         ):
             if hasattr(module, "apiFiles"):
                 apis.extend(module.apiFiles(language))
-        
+
         return apis
-        
+
     def getPluginQtHelpFiles(self):
         """
         Public method to get the list of QtHelp documentation files provided
         by a plug-in.
-        
+
         @return dictionary with documentation type as key and list of files
             as value
         @rtype dict (key: str, value: list of str)
         """
         helpFiles = {}
-        for module in (
-            list(self.__activeModules.values()) +
-            list(self.__onDemandActiveModules.values())
+        for module in list(self.__activeModules.values()) + list(
+            self.__onDemandActiveModules.values()
         ):
             if hasattr(module, "helpFiles"):
                 helpFiles.update(module.helpFiles())
-        
+
         return helpFiles
-        
+
     def getPluginExeDisplayData(self):
         """
         Public method to get data to display information about a plugins
         external tool.
-        
+
         @return list of dictionaries containing the data. Each dictionary must
             either contain data for the determination or the data to be
             displayed.<br />
@@ -1048,31 +1054,29 @@
             </ul>
         """
         infos = []
-        
-        for module in (
-            list(self.__activeModules.values()) +
-            list(self.__inactiveModules.values())
+
+        for module in list(self.__activeModules.values()) + list(
+            self.__inactiveModules.values()
         ):
             if hasattr(module, "exeDisplayDataList"):
                 infos.extend(module.exeDisplayDataList())
             elif hasattr(module, "exeDisplayData"):
                 infos.append(module.exeDisplayData())
-        for module in (
-            list(self.__onDemandActiveModules.values()) +
-            list(self.__onDemandInactiveModules.values())
+        for module in list(self.__onDemandActiveModules.values()) + list(
+            self.__onDemandInactiveModules.values()
         ):
             if hasattr(module, "exeDisplayDataList"):
                 infos.extend(module.exeDisplayDataList())
             elif hasattr(module, "exeDisplayData"):
                 infos.append(module.exeDisplayData())
-        
+
         return infos
-        
+
     def getPluginConfigData(self):
         """
         Public method to get the config data of all active, non on-demand
         plugins used by the configuration dialog.
-        
+
         Plugins supporting this functionality must provide the plugin module
         function 'getConfigData' returning a dictionary with unique keys
         of lists with the following list contents:
@@ -1097,74 +1101,72 @@
           <dd>This will be used by the configuration dialog and must always
               be None</dd>
         </dl>
-        
+
         @return plug-in configuration data
         """
         configData = {}
         for module in (
-            list(self.__activeModules.values()) +
-            list(self.__onDemandActiveModules.values()) +
-                list(self.__onDemandInactiveModules.values())
+            list(self.__activeModules.values())
+            + list(self.__onDemandActiveModules.values())
+            + list(self.__onDemandInactiveModules.values())
         ):
-            if hasattr(module, 'getConfigData'):
+            if hasattr(module, "getConfigData"):
                 configData.update(module.getConfigData())
         return configData
-        
+
     def isPluginLoaded(self, pluginName):
         """
         Public method to check, if a certain plugin is loaded.
-        
+
         @param pluginName name of the plugin to check for (string)
         @return flag indicating, if the plugin is loaded (boolean)
         """
         return (
-            pluginName in self.__activeModules or
-            pluginName in self.__inactiveModules or
-            pluginName in self.__onDemandActiveModules or
-            pluginName in self.__onDemandInactiveModules
+            pluginName in self.__activeModules
+            or pluginName in self.__inactiveModules
+            or pluginName in self.__onDemandActiveModules
+            or pluginName in self.__onDemandInactiveModules
         )
-        
+
     def isPluginActive(self, pluginName):
         """
         Public method to check, if a certain plugin is active.
-        
+
         @param pluginName name of the plugin to check for (string)
         @return flag indicating, if the plugin is active (boolean)
         """
         return (
-            pluginName in self.__activeModules or
-            pluginName in self.__onDemandActiveModules
+            pluginName in self.__activeModules
+            or pluginName in self.__onDemandActiveModules
         )
-    
+
     ###########################################################################
     ## Specialized plug-in module handling methods below
     ###########################################################################
-    
+
     ###########################################################################
     ## VCS related methods below
     ###########################################################################
-    
+
     def getVcsSystemIndicators(self):
         """
         Public method to get the Vcs System indicators.
-        
+
         Plugins supporting this functionality must support the module function
         getVcsSystemIndicator returning a dictionary with indicator as key and
         a tuple with the vcs name (string) and vcs display string (string).
-        
+
         @return dictionary with indicator as key and a list of tuples as
             values. Each tuple contains the vcs name (string) and vcs display
             string (string).
         """
         vcsDict = {}
-        
-        for module in (
-            list(self.__onDemandActiveModules.values()) +
-            list(self.__onDemandInactiveModules.values())
+
+        for module in list(self.__onDemandActiveModules.values()) + list(
+            self.__onDemandInactiveModules.values()
         ):
-            if (
-                getattr(module, "pluginType", "") == "version_control" and
-                hasattr(module, "getVcsSystemIndicator")
+            if getattr(module, "pluginType", "") == "version_control" and hasattr(
+                module, "getVcsSystemIndicator"
             ):
                 res = module.getVcsSystemIndicator()
                 for indicator, vcsData in list(res.items()):
@@ -1172,9 +1174,9 @@
                         vcsDict[indicator].append(vcsData)
                     else:
                         vcsDict[indicator] = [vcsData]
-        
+
         return vcsDict
-    
+
     def deactivateVcsPlugins(self):
         """
         Public method to deactivated all activated VCS plugins.
@@ -1182,11 +1184,11 @@
         for name, module in list(self.__onDemandActiveModules.items()):
             if getattr(module, "pluginType", "") == "version_control":
                 self.deactivatePlugin(name, True)
-    
+
     ########################################################################
     ## Methods for the creation of the plug-ins download directory
     ########################################################################
-    
+
     def __checkPluginsDownloadDirectory(self):
         """
         Private slot to check for the existence of the plugins download
@@ -1195,7 +1197,7 @@
         downloadDir = Preferences.getPluginManager("DownloadPath")
         if not downloadDir:
             downloadDir = self.__defaultDownloadDir
-        
+
         if not os.path.exists(downloadDir):
             try:
                 os.mkdir(downloadDir, 0o755)
@@ -1213,22 +1215,23 @@
                                 """<p>The plugin download directory"""
                                 """ <b>{0}</b> could not be created. Please"""
                                 """ configure it via the configuration"""
-                                """ dialog.</p><p>Reason: {1}</p>""")
-                            .format(downloadDir, str(err)))
+                                """ dialog.</p><p>Reason: {1}</p>"""
+                            ).format(downloadDir, str(err)),
+                        )
                         downloadDir = ""
-        
+
         Preferences.setPluginManager("DownloadPath", downloadDir)
-    
+
     def preferencesChanged(self):
         """
         Public slot to react to changes in configuration.
         """
         self.__checkPluginsDownloadDirectory()
-    
+
     ########################################################################
     ## Methods for automatic plug-in update check below
     ########################################################################
-    
+
     def checkPluginUpdatesAvailable(self):
         """
         Public method to check the availability of updates of plug-ins.
@@ -1239,13 +1242,10 @@
         # 2 = weekly
         # 3 = monthly
         # 4 = always
-        
-        if (
-            period == 0 or
-            (self.__ui is not None and not self.__ui.isOnline())
-        ):
+
+        if period == 0 or (self.__ui is not None and not self.__ui.isOnline()):
             return
-        
+
         elif period in [1, 2, 3] and pathlib.Path(self.pluginRepositoryFile).exists():
             lastModified = datetime.datetime.fromtimestamp(
                 pathlib.Path(self.pluginRepositoryFile).stat().st_mtime
@@ -1253,46 +1253,46 @@
             now = datetime.datetime.now()
             delta = now - lastModified
             if (
-                (period == 1 and lastModified.date().day == now.date().day) or
-                (period == 2 and delta.days < 7) or
-                (period == 3 and delta.days < 30)
+                (period == 1 and lastModified.date().day == now.date().day)
+                or (period == 2 and delta.days < 7)
+                or (period == 3 and delta.days < 30)
             ):
                 # daily, weekly, monthly
                 return
-        
+
         self.downLoadRepositoryFile()
-    
+
     def downLoadRepositoryFile(self, url=None):
         """
         Public method to download the plugin repository file.
-        
+
         @param url URL to get the plugin repository file from
             (defaults to None)
         @type QUrl or str (optional)
         """
         self.__updateAvailable = False
-        
+
         if url is None:
             url = Preferences.getUI("PluginRepositoryUrl7")
         request = QNetworkRequest(QUrl(url))
         request.setAttribute(
             QNetworkRequest.Attribute.CacheLoadControlAttribute,
-            QNetworkRequest.CacheLoadControl.AlwaysNetwork)
+            QNetworkRequest.CacheLoadControl.AlwaysNetwork,
+        )
         reply = self.__networkManager.get(request)
-        reply.finished.connect(
-            lambda: self.__downloadRepositoryFileDone(reply))
+        reply.finished.connect(lambda: self.__downloadRepositoryFileDone(reply))
         self.__replies.append(reply)
-    
+
     def __downloadRepositoryFileDone(self, reply):
         """
         Private method called after the repository file was downloaded.
-        
+
         @param reply reference to the reply object of the download
         @type QNetworkReply
         """
         if reply in self.__replies:
             self.__replies.remove(reply)
-        
+
         if reply.error() != QNetworkReply.NetworkError.NoError:
             EricMessageBox.warning(
                 None,
@@ -1300,12 +1300,13 @@
                 self.tr(
                     """<p>Could not download the requested file"""
                     """ from {0}.</p><p>Error: {1}</p>"""
-                ).format(Preferences.getUI("PluginRepositoryUrl7"),
-                         reply.errorString())
+                ).format(
+                    Preferences.getUI("PluginRepositoryUrl7"), reply.errorString()
+                ),
             )
             reply.deleteLater()
             return
-        
+
         ioDevice = QFile(self.pluginRepositoryFile + ".tmp")
         ioDevice.open(QIODevice.OpenModeFlag.WriteOnly)
         ioDevice.write(reply.readAll())
@@ -1314,34 +1315,34 @@
             QFile.remove(self.pluginRepositoryFile)
         ioDevice.rename(self.pluginRepositoryFile)
         reply.deleteLater()
-        
+
         if os.path.exists(self.pluginRepositoryFile):
             f = QFile(self.pluginRepositoryFile)
             if f.open(QIODevice.OpenModeFlag.ReadOnly):
                 # save current URL
                 url = Preferences.getUI("PluginRepositoryUrl7")
-                
+
                 # read the repository file
-                from EricXML.PluginRepositoryReader import (
-                    PluginRepositoryReader
-                )
+                from EricXML.PluginRepositoryReader import PluginRepositoryReader
+
                 reader = PluginRepositoryReader(f, self.checkPluginEntry)
                 reader.readXML()
                 if url != Preferences.getUI("PluginRepositoryUrl7"):
                     # redo if it is a redirect
                     self.checkPluginUpdatesAvailable()
                     return
-                
+
                 if self.__updateAvailable:
                     self.__ui and self.__ui.activatePluginRepositoryViewer()
                 else:
                     self.pluginRepositoryFileDownloaded.emit()
-    
-    def checkPluginEntry(self, name, short, description, url, author, version,
-                         filename, status):
+
+    def checkPluginEntry(
+        self, name, short, description, url, author, version, filename, status
+    ):
         """
         Public method to check a plug-in's data for an update.
-        
+
         @param name data for the name field (string)
         @param short data for the short field (string)
         @param description data for the description field (list of strings)
@@ -1355,25 +1356,23 @@
         pluginName = os.path.splitext(url.rsplit("/", 1)[1])[0]
         if pluginName in Preferences.getPluginManager("HiddenPlugins"):
             return
-        
-        archive = os.path.join(Preferences.getPluginManager("DownloadPath"),
-                               filename)
-        
+
+        archive = os.path.join(Preferences.getPluginManager("DownloadPath"), filename)
+
         # Check against installed/loaded plug-ins
         pluginDetails = self.getPluginDetails(pluginName)
         if pluginDetails is None:
             if not Preferences.getPluginManager("CheckInstalledOnly"):
                 self.__updateAvailable = True
             return
-        
+
         versionTuple = Globals.versionToTuple(version)[:3]
-        pluginVersionTuple = Globals.versionToTuple(
-            pluginDetails["version"])[:3]
-        
+        pluginVersionTuple = Globals.versionToTuple(pluginDetails["version"])[:3]
+
         if pluginVersionTuple < versionTuple:
             self.__updateAvailable = True
             return
-        
+
         if not Preferences.getPluginManager("CheckInstalledOnly"):
             # Check against downloaded plugin archives
             # 1. Check, if the archive file exists
@@ -1381,12 +1380,12 @@
                 if pluginDetails["moduleName"] != pluginName:
                     self.__updateAvailable = True
                 return
-            
+
             # 2. Check, if the archive is a valid zip file
             if not zipfile.is_zipfile(archive):
                 self.__updateAvailable = True
                 return
-            
+
             # 3. Check the version of the archive file
             zipFile = zipfile.ZipFile(archive, "r")
             try:
@@ -1394,56 +1393,55 @@
             except KeyError:
                 aversion = "0.0.0"
             zipFile.close()
-            
+
             aversionTuple = Globals.versionToTuple(aversion)[:3]
             if aversionTuple != versionTuple:
                 self.__updateAvailable = True
-    
+
     def __sslErrors(self, reply, errors):
         """
         Private slot to handle SSL errors.
-        
+
         @param reply reference to the reply object (QNetworkReply)
         @param errors list of SSL errors (list of QSslError)
         """
         ignored = self.__sslErrorHandler.sslErrorsReply(reply, errors)[0]
         if ignored == EricSslErrorState.NOT_IGNORED:
             self.__downloadCancelled = True
-    
+
     ########################################################################
     ## Methods to clear private data of plug-ins below
     ########################################################################
-    
+
     def clearPluginsPrivateData(self, type_):
         """
         Public method to clear the private data of plug-ins of a specified
         type.
-        
+
         Plugins supporting this functionality must support the module function
         clearPrivateData() and have the module level attribute pluginType.
-        
+
         @param type_ type of the plugin to clear private data for (string)
         """
         for module in (
-            list(self.__onDemandActiveModules.values()) +
-            list(self.__onDemandInactiveModules.values()) +
-            list(self.__activeModules.values()) +
-            list(self.__inactiveModules.values())
+            list(self.__onDemandActiveModules.values())
+            + list(self.__onDemandInactiveModules.values())
+            + list(self.__activeModules.values())
+            + list(self.__inactiveModules.values())
         ):
-            if (
-                getattr(module, "pluginType", "") == type_ and
-                hasattr(module, "clearPrivateData")
+            if getattr(module, "pluginType", "") == type_ and hasattr(
+                module, "clearPrivateData"
             ):
                 module.clearPrivateData()
-    
+
     ########################################################################
     ## Methods to install a plug-in module dependency via pip
     ########################################################################
-    
+
     def pipInstall(self, packages):
         """
         Public method to install the given package via pip.
-        
+
         @param packages list of packages to install
         @type list of str
         """
@@ -1452,9 +1450,10 @@
         except KeyError:
             # Installation is performed via the plug-in installation script.
             from PipInterface.Pip import Pip
+
             pip = Pip(self)
-        pip.installPackages(packages,
-                            interpreter=Globals.getPythonExecutable())
+        pip.installPackages(packages, interpreter=Globals.getPythonExecutable())
+
 
 #
 # eflag: noqa = M801

eric ide

mercurial