src/eric7/VirtualEnv/VirtualenvManager.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
diff -r e9e7eca7efee -r bf71ee032bb4 src/eric7/VirtualEnv/VirtualenvManager.py
--- a/src/eric7/VirtualEnv/VirtualenvManager.py	Wed Jul 13 11:16:20 2022 +0200
+++ b/src/eric7/VirtualEnv/VirtualenvManager.py	Wed Jul 13 14:55:47 2022 +0200
@@ -26,7 +26,7 @@
 class VirtualenvManager(QObject):
     """
     Class implementing an object to manage Python virtual environments.
-    
+
     @signal virtualEnvironmentAdded() emitted to indicate the addition of
         a virtual environment
     @signal virtualEnvironmentRemoved() emitted to indicate the removal and
@@ -36,38 +36,41 @@
     @signal virtualEnvironmentsListChanged() emitted to indicate a change of
         the list of virtual environments (may be used to refresh the list)
     """
+
     DefaultKey = "<default>"
-    
+
     virtualEnvironmentAdded = pyqtSignal()
     virtualEnvironmentRemoved = pyqtSignal()
     virtualEnvironmentChanged = pyqtSignal(str)
-    
+
     virtualEnvironmentsListChanged = pyqtSignal()
-    
+
     def __init__(self, parent=None):
         """
         Constructor
-        
+
         @param parent reference to the parent object
         @type QWidget
         """
         super().__init__(parent)
-        
+
         self.__ui = parent
-        
+
         self.__loadSettings()
-    
+
     def __loadSettings(self):
         """
         Private slot to load the virtual environments.
         """
         self.__virtualEnvironmentsBaseDir = Preferences.getSettings().value(
-            "PyVenv/VirtualEnvironmentsBaseDir", "")
-        
+            "PyVenv/VirtualEnvironmentsBaseDir", ""
+        )
+
         venvString = Preferences.getSettings().value(
-            "PyVenv/VirtualEnvironments", "{}")     # __IGNORE_WARNING_M613__
+            "PyVenv/VirtualEnvironments", "{}"  # __IGNORE_WARNING_M613__
+        )
         environments = json.loads(venvString)
-        
+
         self.__virtualEnvironments = {}
         # each environment entry is a dictionary:
         #   path:           the directory of the virtual environment
@@ -83,9 +86,8 @@
         envsToDelete = []
         for venvName in environments:
             environment = environments[venvName]
-            if (
-                ("is_remote" in environment and environment["is_remote"]) or
-                os.access(environment["interpreter"], os.X_OK)
+            if ("is_remote" in environment and environment["is_remote"]) or os.access(
+                environment["interpreter"], os.X_OK
             ):
                 if "is_global" not in environment:
                     environment["is_global"] = environment["path"] == ""
@@ -96,17 +98,16 @@
                 if "exec_path" not in environment:
                     environment["exec_path"] = ""
                 self.__virtualEnvironments[venvName] = environment
-        
+
         # now remove unsupported environments
         for venvName in envsToDelete:
             del environments[venvName]
-        
+
         # check, if the interpreter used to run eric is in the environments
         defaultPy = Globals.getPythonExecutable()
         found = False
         for venvName in self.__virtualEnvironments:
-            if (defaultPy ==
-                    self.__virtualEnvironments[venvName]["interpreter"]):
+            if defaultPy == self.__virtualEnvironments[venvName]["interpreter"]:
                 found = True
                 break
         if not found:
@@ -120,23 +121,22 @@
                 "is_remote": False,
                 "exec_path": "",
             }
-        
+
         self.__saveSettings()
-    
+
     def __saveSettings(self):
         """
         Private slot to save the virtual environments.
         """
         Preferences.getSettings().setValue(
-            "PyVenv/VirtualEnvironmentsBaseDir",
-            self.__virtualEnvironmentsBaseDir)
-        
+            "PyVenv/VirtualEnvironmentsBaseDir", self.__virtualEnvironmentsBaseDir
+        )
+
         Preferences.getSettings().setValue(
-            "PyVenv/VirtualEnvironments",
-            json.dumps(self.__virtualEnvironments)
+            "PyVenv/VirtualEnvironments", json.dumps(self.__virtualEnvironments)
         )
         Preferences.syncPreferences()
-    
+
     @pyqtSlot()
     def reloadSettings(self):
         """
@@ -144,15 +144,15 @@
         """
         Preferences.syncPreferences()
         self.__loadSettings()
-    
+
     def getDefaultEnvironment(self):
         """
         Public method to get the default virtual environment.
-        
+
         Default is an environment with the key '<default>' or the first one
         having an interpreter matching sys.executable (i.e. the one used to
         execute eric with)
-        
+
         @return tuple containing the environment name and a dictionary
             containing a copy of the default virtual environment
         @rtype tuple of (str, dict)
@@ -160,17 +160,16 @@
         if VirtualenvManager.DefaultKey in self.__virtualEnvironments:
             return (
                 VirtualenvManager.DefaultKey,
-                copy.copy(
-                    self.__virtualEnvironments[VirtualenvManager.DefaultKey])
+                copy.copy(self.__virtualEnvironments[VirtualenvManager.DefaultKey]),
             )
-        
+
         else:
             return self.environmentForInterpreter(sys.executable)
-    
+
     def environmentForInterpreter(self, interpreter):
         """
         Public method to get the environment a given interpreter belongs to.
-        
+
         @param interpreter path of the interpreter
         @type str
         @return tuple containing the environment name and a dictionary
@@ -179,87 +178,91 @@
         """
         py = interpreter.replace("w.exe", ".exe")
         for venvName in self.__virtualEnvironments:
-            if (py == self.__virtualEnvironments[venvName]["interpreter"]):
-                return (
-                    venvName,
-                    copy.copy(self.__virtualEnvironments[venvName])
-                )
-        
+            if py == self.__virtualEnvironments[venvName]["interpreter"]:
+                return (venvName, copy.copy(self.__virtualEnvironments[venvName]))
+
         return ("", {})
-    
+
     @pyqtSlot()
     def createVirtualEnv(self, baseDir=""):
         """
         Public slot to create a new virtual environment.
-        
+
         @param baseDir base directory for the virtual environments
         @type str
         """
-        from .VirtualenvConfigurationDialog import (
-            VirtualenvConfigurationDialog
-        )
-        
+        from .VirtualenvConfigurationDialog import VirtualenvConfigurationDialog
+
         if not baseDir:
             baseDir = self.__virtualEnvironmentsBaseDir
-        
+
         dlg = VirtualenvConfigurationDialog(baseDir=baseDir)
         if dlg.exec() == QDialog.DialogCode.Accepted:
             resultDict = dlg.getData()
-            
+
             if resultDict["envType"] == "conda":
                 # create the conda environment
                 conda = ericApp().getObject("Conda")
                 ok, prefix, interpreter = conda.createCondaEnvironment(
-                    resultDict["arguments"])
+                    resultDict["arguments"]
+                )
                 if ok and "--dry-run" not in resultDict["arguments"]:
-                    self.addVirtualEnv(resultDict["logicalName"],
-                                       prefix,
-                                       venvInterpreter=interpreter,
-                                       isConda=True)
+                    self.addVirtualEnv(
+                        resultDict["logicalName"],
+                        prefix,
+                        venvInterpreter=interpreter,
+                        isConda=True,
+                    )
             else:
                 # now do the call
                 from .VirtualenvExecDialog import VirtualenvExecDialog
+
                 dia = VirtualenvExecDialog(resultDict, self)
                 dia.show()
                 dia.start(resultDict["arguments"])
                 dia.exec()
-    
+
     @pyqtSlot()
     def upgradeVirtualEnv(self, venvName):
         """
         Public slot to upgrade a virtual environment.
-        
+
         @param venvName name of the virtual environment
         @type str
         """
         from .VirtualenvUpgradeConfigurationDialog import (
-            VirtualenvUpgradeConfigurationDialog
+            VirtualenvUpgradeConfigurationDialog,
         )
-        
+
         venvDirectory = self.getVirtualenvDirectory(venvName)
         if not os.path.exists(os.path.join(venvDirectory, "pyvenv.cfg")):
             # The environment was not created by the 'venv' module.
             return
-        
+
         dlg = VirtualenvUpgradeConfigurationDialog(venvName, venvDirectory)
         if dlg.exec() == QDialog.DialogCode.Accepted:
             pythonExe, args, createLog = dlg.getData()
-            
-            from .VirtualenvUpgradeExecDialog import (
-                VirtualenvUpgradeExecDialog
-            )
-            dia = VirtualenvUpgradeExecDialog(
-                venvName, pythonExe, createLog, self)
+
+            from .VirtualenvUpgradeExecDialog import VirtualenvUpgradeExecDialog
+
+            dia = VirtualenvUpgradeExecDialog(venvName, pythonExe, createLog, self)
             dia.show()
             dia.start(args)
             dia.exec()
-    
-    def addVirtualEnv(self, venvName, venvDirectory, venvInterpreter="",
-                      isGlobal=False, isConda=False, isRemote=False,
-                      execPath=""):
+
+    def addVirtualEnv(
+        self,
+        venvName,
+        venvDirectory,
+        venvInterpreter="",
+        isGlobal=False,
+        isConda=False,
+        isRemote=False,
+        execPath="",
+    ):
         """
         Public method to add a virtual environment.
-        
+
         @param venvName logical name for the virtual environment
         @type str
         @param venvDirectory directory of the virtual environment
@@ -280,49 +283,61 @@
             ok = EricMessageBox.yesNo(
                 None,
                 self.tr("Add Virtual Environment"),
-                self.tr("""A virtual environment named <b>{0}</b> exists"""
-                        """ already. Shall it be replaced?""")
-                .format(venvName),
-                icon=EricMessageBox.Warning)
+                self.tr(
+                    """A virtual environment named <b>{0}</b> exists"""
+                    """ already. Shall it be replaced?"""
+                ).format(venvName),
+                icon=EricMessageBox.Warning,
+            )
             if not ok:
                 from .VirtualenvNameDialog import VirtualenvNameDialog
+
                 dlg = VirtualenvNameDialog(
-                    list(self.__virtualEnvironments.keys()),
-                    venvName)
+                    list(self.__virtualEnvironments.keys()), venvName
+                )
                 if dlg.exec() != QDialog.DialogCode.Accepted:
                     return
-                
+
                 venvName = dlg.getName()
-        
+
         if not venvInterpreter:
             from .VirtualenvInterpreterSelectionDialog import (
-                VirtualenvInterpreterSelectionDialog
+                VirtualenvInterpreterSelectionDialog,
             )
+
             dlg = VirtualenvInterpreterSelectionDialog(venvName, venvDirectory)
             if dlg.exec() == QDialog.DialogCode.Accepted:
                 venvInterpreter = dlg.getData()
-        
+
         if venvInterpreter:
             self.__virtualEnvironments[venvName] = {
                 "path": venvDirectory,
                 "interpreter": venvInterpreter,
-                "variant": 3,                   # always 3
+                "variant": 3,  # always 3
                 "is_global": isGlobal,
                 "is_conda": isConda,
                 "is_remote": isRemote,
                 "exec_path": execPath,
             }
-            
+
             self.__saveSettings()
-            
+
             self.virtualEnvironmentAdded.emit()
             self.virtualEnvironmentsListChanged.emit()
-    
-    def setVirtualEnv(self, venvName, venvDirectory, venvInterpreter,
-                      isGlobal, isConda, isRemote, execPath):
+
+    def setVirtualEnv(
+        self,
+        venvName,
+        venvDirectory,
+        venvInterpreter,
+        isGlobal,
+        isConda,
+        isRemote,
+        execPath,
+    ):
         """
         Public method to change a virtual environment.
-        
+
         @param venvName logical name of the virtual environment
         @type str
         @param venvDirectory directory of the virtual environment
@@ -343,34 +358,44 @@
             EricMessageBox.yesNo(
                 None,
                 self.tr("Change Virtual Environment"),
-                self.tr("""A virtual environment named <b>{0}</b> does not"""
-                        """ exist. Aborting!""")
-                .format(venvName),
-                icon=EricMessageBox.Warning)
+                self.tr(
+                    """A virtual environment named <b>{0}</b> does not"""
+                    """ exist. Aborting!"""
+                ).format(venvName),
+                icon=EricMessageBox.Warning,
+            )
             return
-        
+
         self.__virtualEnvironments[venvName] = {
             "path": venvDirectory,
             "interpreter": venvInterpreter,
-            "variant": 3,                   # always 3
+            "variant": 3,  # always 3
             "is_global": isGlobal,
             "is_conda": isConda,
             "is_remote": isRemote,
             "exec_path": execPath,
         }
-        
+
         self.__saveSettings()
-        
+
         self.virtualEnvironmentChanged.emit(venvName)
         self.virtualEnvironmentsListChanged.emit()
-    
-    def renameVirtualEnv(self, oldVenvName, venvName, venvDirectory,
-                         venvInterpreter, isGlobal, isConda,
-                         isRemote, execPath):
+
+    def renameVirtualEnv(
+        self,
+        oldVenvName,
+        venvName,
+        venvDirectory,
+        venvInterpreter,
+        isGlobal,
+        isConda,
+        isRemote,
+        execPath,
+    ):
         """
         Public method to substitute a virtual environment entry with a new
         name.
-        
+
         @param oldVenvName old name of the virtual environment
         @type str
         @param venvName logical name for the virtual environment
@@ -393,41 +418,53 @@
             EricMessageBox.yesNo(
                 None,
                 self.tr("Rename Virtual Environment"),
-                self.tr("""A virtual environment named <b>{0}</b> does not"""
-                        """ exist. Aborting!""")
-                .format(oldVenvName),
-                icon=EricMessageBox.Warning)
+                self.tr(
+                    """A virtual environment named <b>{0}</b> does not"""
+                    """ exist. Aborting!"""
+                ).format(oldVenvName),
+                icon=EricMessageBox.Warning,
+            )
             return
-        
+
         del self.__virtualEnvironments[oldVenvName]
-        self.addVirtualEnv(venvName, venvDirectory, venvInterpreter,
-                           isGlobal, isConda, isRemote, execPath)
-    
+        self.addVirtualEnv(
+            venvName,
+            venvDirectory,
+            venvInterpreter,
+            isGlobal,
+            isConda,
+            isRemote,
+            execPath,
+        )
+
     def deleteVirtualEnvs(self, venvNames):
         """
         Public method to delete virtual environments from the list and disk.
-        
+
         @param venvNames list of logical names for the virtual environments
         @type list of str
         """
         venvMessages = []
         for venvName in venvNames:
-            if (
-                venvName in self.__virtualEnvironments and
-                bool(self.__virtualEnvironments[venvName]["path"])
+            if venvName in self.__virtualEnvironments and bool(
+                self.__virtualEnvironments[venvName]["path"]
             ):
-                venvMessages.append(self.tr("{0} - {1}").format(
-                    venvName, self.__virtualEnvironments[venvName]["path"]))
+                venvMessages.append(
+                    self.tr("{0} - {1}").format(
+                        venvName, self.__virtualEnvironments[venvName]["path"]
+                    )
+                )
         if venvMessages:
-            from UI.DeleteFilesConfirmationDialog import (
-                DeleteFilesConfirmationDialog
-            )
+            from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog
+
             dlg = DeleteFilesConfirmationDialog(
                 None,
                 self.tr("Delete Virtual Environments"),
-                self.tr("""Do you really want to delete these virtual"""
-                        """ environments?"""),
-                venvMessages
+                self.tr(
+                    """Do you really want to delete these virtual"""
+                    """ environments?"""
+                ),
+                venvMessages,
             )
             if dlg.exec() == QDialog.DialogCode.Accepted:
                 for venvName in venvNames:
@@ -440,20 +477,20 @@
                                 del self.__virtualEnvironments[venvName]
                         else:
                             shutil.rmtree(
-                                self.__virtualEnvironments[venvName]["path"],
-                                True)
+                                self.__virtualEnvironments[venvName]["path"], True
+                            )
                             del self.__virtualEnvironments[venvName]
-                
+
                 self.__saveSettings()
-                
+
                 self.virtualEnvironmentRemoved.emit()
                 self.virtualEnvironmentsListChanged.emit()
-    
+
     def __isEnvironmentDeleteable(self, venvName):
         """
         Private method to check, if a virtual environment can be deleted from
         disk.
-        
+
         @param venvName name of the virtual environment
         @type str
         @return flag indicating it can be deleted
@@ -465,122 +502,122 @@
             ok &= bool(self.__virtualEnvironments[venvName]["path"])
             ok &= not self.__virtualEnvironments[venvName]["is_global"]
             ok &= not self.__virtualEnvironments[venvName]["is_remote"]
-            ok &= os.access(self.__virtualEnvironments[venvName]["path"],
-                            os.W_OK)
-        
+            ok &= os.access(self.__virtualEnvironments[venvName]["path"], os.W_OK)
+
         return ok
-    
+
     def removeVirtualEnvs(self, venvNames):
         """
         Public method to delete virtual environment from the list.
-        
+
         @param venvNames list of logical names for the virtual environments
         @type list of str
         """
         venvMessages = []
         for venvName in venvNames:
             if venvName in self.__virtualEnvironments:
-                venvMessages.append(self.tr("{0} - {1}").format(
-                    venvName, self.__virtualEnvironments[venvName]["path"]))
+                venvMessages.append(
+                    self.tr("{0} - {1}").format(
+                        venvName, self.__virtualEnvironments[venvName]["path"]
+                    )
+                )
         if venvMessages:
-            from UI.DeleteFilesConfirmationDialog import (
-                DeleteFilesConfirmationDialog
-            )
+            from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog
+
             dlg = DeleteFilesConfirmationDialog(
                 None,
                 self.tr("Remove Virtual Environments"),
-                self.tr("""Do you really want to remove these virtual"""
-                        """ environments?"""),
-                venvMessages
+                self.tr(
+                    """Do you really want to remove these virtual"""
+                    """ environments?"""
+                ),
+                venvMessages,
             )
             if dlg.exec() == QDialog.DialogCode.Accepted:
                 for venvName in venvNames:
                     if venvName in self.__virtualEnvironments:
                         del self.__virtualEnvironments[venvName]
-                
+
                 self.__saveSettings()
-                
+
                 self.virtualEnvironmentRemoved.emit()
                 self.virtualEnvironmentsListChanged.emit()
-    
+
     def getEnvironmentEntries(self):
         """
         Public method to get a dictionary containing the defined virtual
         environment entries.
-        
+
         @return dictionary containing a copy of the defined virtual
             environments
         @rtype dict
         """
         return copy.deepcopy(self.__virtualEnvironments)
-    
+
     @pyqtSlot()
     def showVirtualenvManagerDialog(self, modal=False):
         """
         Public slot to show the virtual environment manager dialog.
-        
+
         @param modal flag indicating that the dialog should be shown in
             a blocking mode
         """
         if modal:
             from .VirtualenvManagerWidgets import VirtualenvManagerDialog
-            virtualenvManagerDialog = VirtualenvManagerDialog(
-                self, self.__ui)
+
+            virtualenvManagerDialog = VirtualenvManagerDialog(self, self.__ui)
             virtualenvManagerDialog.exec()
             self.virtualEnvironmentsListChanged.emit()
         else:
             self.__ui.activateVirtualenvManager()
-    
+
     def isUnique(self, venvName):
         """
         Public method to check, if the give logical name is unique.
-        
+
         @param venvName logical name for the virtual environment
         @type str
         @return flag indicating uniqueness
         @rtype bool
         """
         return venvName not in self.__virtualEnvironments
-    
+
     def getVirtualenvInterpreter(self, venvName):
         """
         Public method to get the interpreter for a virtual environment.
-        
+
         @param venvName logical name for the virtual environment
         @type str
         @return interpreter path
         @rtype str
         """
         if venvName in self.__virtualEnvironments:
-            return (
-                self.__virtualEnvironments[venvName]["interpreter"]
-                .replace("w.exe", ".exe")
+            return self.__virtualEnvironments[venvName]["interpreter"].replace(
+                "w.exe", ".exe"
             )
         else:
             return ""
-    
+
     def setVirtualEnvInterpreter(self, venvName, venvInterpreter):
         """
         Public method to change the interpreter for a virtual environment.
-        
+
         @param venvName logical name for the virtual environment
         @type str
         @param venvInterpreter interpreter path to be set
         @type str
         """
         if venvName in self.__virtualEnvironments:
-            self.__virtualEnvironments[venvName]["interpreter"] = (
-                venvInterpreter
-            )
+            self.__virtualEnvironments[venvName]["interpreter"] = venvInterpreter
             self.__saveSettings()
-            
+
             self.virtualEnvironmentChanged.emit(venvName)
             self.virtualEnvironmentsListChanged.emit()
-    
+
     def getVirtualenvDirectory(self, venvName):
         """
         Public method to get the directory of a virtual environment.
-        
+
         @param venvName logical name for the virtual environment
         @type str
         @return directory path
@@ -590,11 +627,11 @@
             return self.__virtualEnvironments[venvName]["path"]
         else:
             return ""
-    
+
     def getVirtualenvNames(self, noRemote=False, noConda=False):
         """
         Public method to get a list of defined virtual environments.
-        
+
         @param noRemote flag indicating to exclude environments for remote
             debugging
         @type bool
@@ -605,18 +642,20 @@
         """
         environments = list(self.__virtualEnvironments.keys())
         if noRemote:
-            environments = [name for name in environments
-                            if not self.isRemoteEnvironment(name)]
+            environments = [
+                name for name in environments if not self.isRemoteEnvironment(name)
+            ]
         if noConda:
-            environments = [name for name in environments
-                            if not self.isCondaEnvironment(name)]
-        
+            environments = [
+                name for name in environments if not self.isCondaEnvironment(name)
+            ]
+
         return environments
-    
+
     def isGlobalEnvironment(self, venvName):
         """
         Public method to test, if a given environment is a global one.
-        
+
         @param venvName logical name of the virtual environment
         @type str
         @return flag indicating a global environment
@@ -626,12 +665,12 @@
             return self.__virtualEnvironments[venvName]["is_global"]
         else:
             return False
-    
+
     def isCondaEnvironment(self, venvName):
         """
         Public method to test, if a given environment is an Anaconda
         environment.
-        
+
         @param venvName logical name of the virtual environment
         @type str
         @return flag indicating an Anaconda environment
@@ -641,12 +680,12 @@
             return self.__virtualEnvironments[venvName]["is_conda"]
         else:
             return False
-    
+
     def isRemoteEnvironment(self, venvName):
         """
         Public method to test, if a given environment is a remotely accessed
         environment.
-        
+
         @param venvName logical name of the virtual environment
         @type str
         @return flag indicating a remotely accessed environment
@@ -656,11 +695,11 @@
             return self.__virtualEnvironments[venvName]["is_remote"]
         else:
             return False
-    
+
     def getVirtualenvExecPath(self, venvName):
         """
         Public method to get the search path prefix of a virtual environment.
-        
+
         @param venvName logical name for the virtual environment
         @type str
         @return search path prefix
@@ -670,21 +709,21 @@
             return self.__virtualEnvironments[venvName]["exec_path"]
         else:
             return ""
-    
+
     def setVirtualEnvironmentsBaseDir(self, baseDir):
         """
         Public method to set the base directory for the virtual environments.
-        
+
         @param baseDir base directory for the virtual environments
         @type str
         """
         self.__virtualEnvironmentsBaseDir = baseDir
         self.__saveSettings()
-    
+
     def getVirtualEnvironmentsBaseDir(self):
         """
         Public method to set the base directory for the virtual environments.
-        
+
         @return base directory for the virtual environments
         @rtype str
         """

eric ide

mercurial