VirtualEnv/VirtualenvManager.py

branch
maintenance
changeset 6826
c6dda2cbe081
parent 6792
9dd854f05c83
child 6896
3716c4af48bb
--- a/VirtualEnv/VirtualenvManager.py	Sat Feb 16 10:27:50 2019 +0100
+++ b/VirtualEnv/VirtualenvManager.py	Sat Mar 02 11:15:24 2019 +0100
@@ -15,21 +15,32 @@
 import json
 import copy
 
-from PyQt5.QtCore import pyqtSlot, QObject
+from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject
 from PyQt5.QtWidgets import QDialog
 
 from E5Gui import E5MessageBox
+from E5Gui.E5Application import e5App
 
 import Preferences
-import Utilities
 
 
 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
+        deletion of a virtual environment
+    @signal virtualEnvironmentChanged(name) emitted to indicate a change of
+        a virtual environment
     """
     DefaultKey = "<default>"
     
+    virtualEnvironmentAdded = pyqtSignal()
+    virtualEnvironmentRemoved = pyqtSignal()
+    virtualEnvironmentChanged = pyqtSignal(str)
+    
     def __init__(self, parent=None):
         """
         Constructor
@@ -61,17 +72,20 @@
         #   variant:        Python variant (2 or 3)
         #   is_global:      a flag indicating a global environment
         #   is_conda:       a flag indicating an Anaconda environment
+        #   is_remote:      a flag indicating a remotely accessed environment
         #   exec_path:      a string to be prefixed to the PATH environment
         #                   setting
         #
         for venvName in environments:
-            interpreter = environments[venvName]["interpreter"]
-            if os.access(interpreter, os.X_OK):
-                environment = environments[venvName]
+            environment = environments[venvName]
+            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"] == ""
                 if "is_conda" not in environment:
                     environment["is_conda"] = False
+                if "is_remote" not in environment:
+                    environment["is_remote"] = False
                 if "exec_path" not in environment:
                     environment["exec_path"] = ""
                 self.__virtualEnvironments[venvName] = environment
@@ -92,6 +106,7 @@
                 "variant": sys.version_info[0],
                 "is_global": True,
                 "is_conda": False,
+                "is_remote": False,
                 "exec_path": "",
             }
         
@@ -105,6 +120,7 @@
             "PyVenv/VirtualEnvironments",
             json.dumps(self.__virtualEnvironments)
         )
+        Preferences.syncPreferences()
     
     def getDefaultEnvironment(self):
         """
@@ -147,21 +163,29 @@
         
         dlg = VirtualenvConfigurationDialog()
         if dlg.exec_() == QDialog.Accepted:
-            (pyvenv, args, name, openTarget, createLog, createScript,
-             targetDir, interpreter) = dlg.getData()
+            resultDict = dlg.getData()
             
-            # now do the call
-            from .VirtualenvExecDialog import VirtualenvExecDialog
-            dia = VirtualenvExecDialog(pyvenv, targetDir, name, openTarget,
-                                       createLog, createScript, interpreter,
-                                       self)
-            dia.show()
-            dia.start(args)
-            dia.exec_()
+            if resultDict["envType"] == "conda":
+                # create the conda environment
+                conda = e5App().getObject("Conda")
+                ok, prefix, interpreter = conda.createCondaEnvironment(
+                    resultDict["arguments"])
+                if ok and "--dry-run" not in resultDict["arguments"]:
+                    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_()
     
     def addVirtualEnv(self, venvName, venvDirectory, venvInterpreter="",
                       venvVariant=3, isGlobal=False, isConda=False,
-                      execPath=""):
+                      isRemote=False, execPath=""):
         """
         Public method to add a virtual environment.
         
@@ -177,6 +201,8 @@
         @type bool
         @param isConda flag indicating an Anaconda virtual environment
         @type bool
+        @param isRemote flag indicating a remotely accessed environment
+        @type bool
         @param execPath search path string to be prepended to the PATH
             environment variable
         @type str
@@ -190,7 +216,14 @@
                 .format(venvName),
                 icon=E5MessageBox.Warning)
             if not ok:
-                return
+                from .VirtualenvNameDialog import VirtualenvNameDialog
+                dlg = VirtualenvNameDialog(
+                    list(self.__virtualEnvironments.keys()),
+                    venvName)
+                if dlg.exec_() != QDialog.Accepted:
+                    return
+                
+                venvName = dlg.getName()
         
         if not venvInterpreter:
             from .VirtualenvInterpreterSelectionDialog import \
@@ -198,9 +231,6 @@
             dlg = VirtualenvInterpreterSelectionDialog(venvName, venvDirectory)
             if dlg.exec_() == QDialog.Accepted:
                 venvInterpreter, venvVariant = dlg.getData()
-                if not Utilities.startswithPath(venvInterpreter,
-                                                venvDirectory):
-                    isGlobal = True
         
         if venvInterpreter:
             self.__virtualEnvironments[venvName] = {
@@ -209,16 +239,19 @@
                 "variant": venvVariant,
                 "is_global": isGlobal,
                 "is_conda": isConda,
+                "is_remote": isRemote,
                 "exec_path": execPath,
             }
             
             self.__saveSettings()
             
+            self.virtualEnvironmentAdded.emit()
             if self.__virtualenvManagerDialog:
                 self.__virtualenvManagerDialog.refresh()
     
     def setVirtualEnv(self, venvName, venvDirectory, venvInterpreter,
-                      venvVariant, isGlobal, isConda, execPath):
+                      venvVariant, isGlobal, isConda, isRemote,
+                      execPath):
         """
         Public method to change a virtual environment.
         
@@ -234,6 +267,8 @@
         @type bool
         @param isConda flag indicating an Anaconda virtual environment
         @type bool
+        @param isRemote flag indicating a remotely accessed environment
+        @type bool
         @param execPath search path string to be prepended to the PATH
             environment variable
         @type str
@@ -254,17 +289,19 @@
             "variant": venvVariant,
             "is_global": isGlobal,
             "is_conda": isConda,
+            "is_remote": isRemote,
             "exec_path": execPath,
         }
         
         self.__saveSettings()
         
+        self.virtualEnvironmentChanged.emit(venvName)
         if self.__virtualenvManagerDialog:
             self.__virtualenvManagerDialog.refresh()
     
     def renameVirtualEnv(self, oldVenvName, venvName, venvDirectory,
                          venvInterpreter, venvVariant, isGlobal, isConda,
-                         execPath):
+                         isRemote, execPath):
         """
         Public method to substitute a virtual environment entry with a new
         name.
@@ -283,6 +320,8 @@
         @type bool
         @param isConda flag indicating an Anaconda virtual environment
         @type bool
+        @param isRemote flag indicating a remotely accessed environment
+        @type bool
         @param execPath search path string to be prepended to the PATH
             environment variable
         @type str
@@ -299,7 +338,8 @@
         
         del self.__virtualEnvironments[oldVenvName]
         self.addVirtualEnv(venvName, venvDirectory, venvInterpreter,
-                           venvVariant, isGlobal, isConda, execPath)
+                           venvVariant, isGlobal, isConda, isRemote,
+                           execPath)
     
     def deleteVirtualEnvs(self, venvNames):
         """
@@ -327,12 +367,21 @@
             if dlg.exec_() == QDialog.Accepted:
                 for venvName in venvNames:
                     if self.__isEnvironmentDeleteable(venvName):
-                        shutil.rmtree(
-                            self.__virtualEnvironments[venvName]["path"], True)
-                        del self.__virtualEnvironments[venvName]
+                        if self.isCondaEnvironment(venvName):
+                            conda = e5App().getObject("Conda")
+                            path = self.__virtualEnvironments[venvName]["path"]
+                            res = conda.removeCondaEnvironment(prefix=path)
+                            if res:
+                                del self.__virtualEnvironments[venvName]
+                        else:
+                            shutil.rmtree(
+                                self.__virtualEnvironments[venvName]["path"],
+                                True)
+                            del self.__virtualEnvironments[venvName]
                 
                 self.__saveSettings()
                 
+                self.virtualEnvironmentRemoved.emit()
                 if self.__virtualenvManagerDialog:
                     self.__virtualenvManagerDialog.refresh()
     
@@ -351,6 +400,7 @@
             ok = True
             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)
         
@@ -385,6 +435,7 @@
                 
                 self.__saveSettings()
                 
+                self.virtualEnvironmentRemoved.emit()
                 if self.__virtualenvManagerDialog:
                     self.__virtualenvManagerDialog.refresh()
     
@@ -521,6 +572,21 @@
         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
+        @rtype bool
+        """
+        if venvName in self.__virtualEnvironments:
+            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.

eric ide

mercurial