VirtualEnv/VirtualenvManager.py

changeset 6349
17b3c75913de
parent 6341
a00e63f6d766
child 6362
ec32d1d7f525
--- a/VirtualEnv/VirtualenvManager.py	Fri Jun 15 18:49:48 2018 +0200
+++ b/VirtualEnv/VirtualenvManager.py	Sat Jun 16 13:34:22 2018 +0200
@@ -12,6 +12,8 @@
 import os
 import sys
 import shutil
+import json
+import copy
 
 from PyQt5.QtCore import pyqtSlot, QObject
 from PyQt5.QtWidgets import QDialog
@@ -36,35 +38,56 @@
         
         self.__ui = parent
         
-        self.__virtualEnvironments = {}
-        self.__virtualEnvironmentInterpreters = {}
-        environments = Preferences.toDict(Preferences.Prefs.settings.value(
-            "PyVenv/Environments", {}))
-        interpreters = Preferences.toDict(Preferences.Prefs.settings.value(
-            "PyVenv/Interpreters", {}))
-        for venvName, venvExe in interpreters.items():
-            # remove all environments, that don't exist anymore
-            if os.access(venvExe, os.X_OK):
-                self.__virtualEnvironmentInterpreters[venvName] = venvExe
-                self.__virtualEnvironments[venvName] = environments[venvName]
-        
-        defaultPy = sys.executable.replace("w.exe", ".exe")
-        if defaultPy not in self.__virtualEnvironmentInterpreters.values():
-            self.__virtualEnvironmentInterpreters["<default>"] = defaultPy
-            self.__virtualEnvironments["<default>"] = ""
-        
-        self.__updateSettings()
+        self.__loadSettings()
         
         self.__virtualenvManagerDialog = None
     
-    def __updateSettings(self):
+    def __loadSettings(self):
+        """
+        Private slot to load the virtual environments.
+        """
+        venvString = Preferences.Prefs.settings.value(
+            "PyVenv/VirtualEnvironments", "{}")     # __IGNORE_WARNING_M613__
+        environments = json.loads(venvString)
+        
+        self.__virtualEnvironments = {}
+        # each environment entry is a dictionary:
+        #   path:           the directory of the virtual environment
+        #                   (empty for a global environment)
+        #   interpreter:    the path of the Python interpreter
+        #   variant:        Python variant (2 or 3)
+        #
+        for venvName in environments:
+            interpreter = environments[venvName]["interpreter"]
+            if os.access(interpreter, os.X_OK):
+                self.__virtualEnvironments[venvName] = environments[venvName]
+        
+        # check, if the interpreter used to run eric is in the environments
+        defaultPy = sys.executable.replace("w.exe", ".exe")
+        found = False
+        for venvName in self.__virtualEnvironments:
+            if (defaultPy ==
+                    self.__virtualEnvironments[venvName]["interpreter"]):
+                found = True
+                break
+        if not found:
+            # add an environment entry for the default interpreter
+            self.__virtualEnvironments["<default>"] = {
+                "path": "",
+                "interpreter": defaultPy,
+                "variant": sys.version_info[0],
+            }
+        
+        self.__saveSettings()
+    
+    def __saveSettings(self):
         """
         Private slot to save the virtual environments.
         """
         Preferences.Prefs.settings.setValue(
-            "PyVenv/Environments", self.__virtualEnvironments)
-        Preferences.Prefs.settings.setValue(
-            "PyVenv/Interpreters", self.__virtualEnvironmentInterpreters)
+            "PyVenv/VirtualEnvironments",
+            json.dumps(self.__virtualEnvironments)
+        )
     
     @pyqtSlot()
     def createVirtualEnv(self):
@@ -88,7 +111,8 @@
             dia.start(args)
             dia.exec_()
     
-    def addVirtualEnv(self, venvName, venvDirectory, venvInterpreter=""):
+    def addVirtualEnv(self, venvName, venvDirectory, venvInterpreter="",
+                      venvVariant=3):
         """
         Public method to add a virtual environment.
         
@@ -97,6 +121,9 @@
         @param venvDirectory directory of the virtual environment
         @type str
         @param venvInterpreter interpreter of the virtual environment
+        @type str
+        @param venvVariant Python variant of the virtual environment
+        @type int
         """
         if venvName in self.__virtualEnvironments:
             ok = E5MessageBox.yesNo(
@@ -114,18 +141,22 @@
                 VirtualenvInterpreterSelectionDialog
             dlg = VirtualenvInterpreterSelectionDialog(venvName, venvDirectory)
             if dlg.exec_() == QDialog.Accepted:
-                venvInterpreter = dlg.getData()
+                venvInterpreter, venvVariant = dlg.getData()
         
         if venvInterpreter:
-            self.__virtualEnvironmentInterpreters[venvName] = venvInterpreter
-            self.__virtualEnvironments[venvName] = venvDirectory
+            self.__virtualEnvironments[venvName] = {
+                "path": venvDirectory,
+                "interpreter": venvInterpreter,
+                "variant": venvVariant,
+            }
             
-            self.__updateSettings()
+            self.__saveSettings()
             
             if self.__virtualenvManagerDialog:
                 self.__virtualenvManagerDialog.refresh()
     
-    def setVirtualEnv(self, venvName, venvDirectory, venvInterpreter=""):
+    def setVirtualEnv(self, venvName, venvDirectory, venvInterpreter,
+                      venvVariant):
         """
         Public method to change a virtual environment.
         
@@ -134,6 +165,9 @@
         @param venvDirectory directory of the virtual environment
         @type str
         @param venvInterpreter interpreter of the virtual environment
+        @type str
+        @param venvVariant Python variant of the virtual environment
+        @type int
         """
         if venvName not in self.__virtualEnvironments:
             E5MessageBox.yesNo(
@@ -145,16 +179,19 @@
                 icon=E5MessageBox.Warning)
             return
         
-        self.__virtualEnvironmentInterpreters[venvName] = venvInterpreter
-        self.__virtualEnvironments[venvName] = venvDirectory
+        self.__virtualEnvironments[venvName] = {
+            "path": venvDirectory,
+            "interpreter": venvInterpreter,
+            "variant": venvVariant,
+        }
         
-        self.__updateSettings()
+        self.__saveSettings()
         
         if self.__virtualenvManagerDialog:
             self.__virtualenvManagerDialog.refresh()
     
     def renameVirtualEnv(self, oldVenvName, venvName, venvDirectory,
-                         venvInterpreter):
+                         venvInterpreter, venvVariant):
         """
         Public method to substitute a virtual environment entry with a new
         name.
@@ -166,6 +203,9 @@
         @param venvDirectory directory of the virtual environment
         @type str
         @param venvInterpreter interpreter of the virtual environment
+        @type str
+        @param venvVariant Python variant of the virtual environment
+        @type int
         """
         if oldVenvName not in self.__virtualEnvironments:
             E5MessageBox.yesNo(
@@ -178,8 +218,8 @@
             return
         
         del self.__virtualEnvironments[oldVenvName]
-        del self.__virtualEnvironmentInterpreters[oldVenvName]
-        self.addVirtualEnv(venvName, venvDirectory, venvInterpreter)
+        self.addVirtualEnv(venvName, venvDirectory, venvInterpreter,
+                           venvVariant)
     
     def deleteVirtualEnvs(self, venvNames):
         """
@@ -191,9 +231,9 @@
         venvMessages = []
         for venvName in venvNames:
             if venvName in self.__virtualEnvironments and \
-                    bool(self.__virtualEnvironments[venvName]):
+                    bool(self.__virtualEnvironments[venvName]["path"]):
                 venvMessages.append(self.tr("{0} - {1}").format(
-                    venvName, self.__virtualEnvironments[venvName]))
+                    venvName, self.__virtualEnvironments[venvName]["path"]))
         if venvMessages:
             from UI.DeleteFilesConfirmationDialog import \
                 DeleteFilesConfirmationDialog
@@ -207,13 +247,12 @@
             if dlg.exec_() == QDialog.Accepted:
                 for venvName in venvNames:
                     if venvName in self.__virtualEnvironments and \
-                            bool(self.__virtualEnvironments[venvName]):
-                        shutil.rmtree(self.__virtualEnvironments[venvName],
-                                      True)
+                            bool(self.__virtualEnvironments[venvName]["path"]):
+                        shutil.rmtree(
+                            self.__virtualEnvironments[venvName]["path"], True)
                         del self.__virtualEnvironments[venvName]
-                        del self.__virtualEnvironmentInterpreters[venvName]
                 
-                self.__updateSettings()
+                self.__saveSettings()
                 
                 if self.__virtualenvManagerDialog:
                     self.__virtualenvManagerDialog.refresh()
@@ -229,7 +268,7 @@
         for venvName in venvNames:
             if venvName in self.__virtualEnvironments:
                 venvMessages.append(self.tr("{0} - {1}").format(
-                    venvName, self.__virtualEnvironments[venvName]))
+                    venvName, self.__virtualEnvironments[venvName]["path"]))
         if venvMessages:
             from UI.DeleteFilesConfirmationDialog import \
                 DeleteFilesConfirmationDialog
@@ -244,30 +283,22 @@
                 for venvName in venvNames:
                     if venvName in self.__virtualEnvironments:
                         del self.__virtualEnvironments[venvName]
-                        del self.__virtualEnvironmentInterpreters[venvName]
                 
-                self.__updateSettings()
+                self.__saveSettings()
                 
                 if self.__virtualenvManagerDialog:
                     self.__virtualenvManagerDialog.refresh()
     
     def getEnvironmentEntries(self):
         """
-        Public method to a dictionary containing the defined virtual
+        Public method to get a dictionary containing the defined virtual
         environment entries.
         
-        @return dictionary containing tuples of the environment path and
-            the associated interpreter
-        @rtype dict of (str, str)
+        @return dictionary containing a copy of the defined virtual
+            environments
+        @rtype dict
         """
-        environments = {}
-        for venvName in self.__virtualEnvironments:
-            environments[venvName] = (
-                self.__virtualEnvironments[venvName],
-                self.__virtualEnvironmentInterpreters[venvName],
-            )
-        
-        return environments
+        return copy.deepcopy(self.__virtualEnvironments)
     
     @pyqtSlot()
     def showVirtualenvManagerDialog(self):
@@ -309,8 +340,8 @@
         @return interpreter path
         @rtype str
         """
-        if venvName in self.__virtualEnvironmentInterpreters:
-            return self.__virtualEnvironmentInterpreters[venvName]
+        if venvName in self.__virtualEnvironments:
+            return self.__virtualEnvironments[venvName]["interpreter"]
         else:
             return ""
     
@@ -324,7 +355,7 @@
         @rtype str
         """
         if venvName in self.__virtualEnvironments:
-            return self.__virtualEnvironments[venvName]
+            return self.__virtualEnvironments[venvName]["path"]
         else:
             return ""
     
@@ -335,4 +366,23 @@
         @return list of defined virtual environments
         @rtype list of str
         """
-        return list(self.__virtualEnvironmentInterpreters.keys())
+        return list(self.__virtualEnvironments.keys())
+    
+    def getVirtualenvNamesForVariant(self, variant):
+        """
+        Public method to get a list of virtual environments for a given
+        Python variant.
+        
+        @param variant Python variant (2 or 3)
+        @type int
+        @return list of defined virtual environments
+        @rtype list of str
+        """
+        assert variant in (2, 3)
+        
+        environments = []
+        for venvName in self.__virtualEnvironments:
+            if self.__virtualEnvironments[venvName]["variant"] == variant:
+                environments.append(venvName)
+        
+        return environments

eric ide

mercurial