diff -r d6c0b8ab1fc6 -r 17b3c75913de VirtualEnv/VirtualenvManager.py --- 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