Tue, 12 Jun 2018 18:59:45 +0200
VirtualenvManager: changed code to allow environments without environment directory denoting a global environment.
# -*- coding: utf-8 -*- # Copyright (c) 2018 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing a class to manage Python virtual environments. """ from __future__ import unicode_literals import os import sys import shutil from PyQt5.QtCore import pyqtSlot, QObject from PyQt5.QtWidgets import QDialog from E5Gui import E5MessageBox import Preferences class VirtualenvManager(QObject): """ Class implementing an object to manage Python virtual environments. """ def __init__(self, parent=None): """ Constructor @param parent reference to the parent object @type QWidget """ super(VirtualenvManager, self).__init__(parent) 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.__virtualenvManagerDialog = None def __updateSettings(self): """ Private slot to save the virtual environments. """ Preferences.Prefs.settings.setValue( "PyVenv/Environments", self.__virtualEnvironments) Preferences.Prefs.settings.setValue( "PyVenv/Interpreters", self.__virtualEnvironmentInterpreters) @pyqtSlot() def createVirtualEnv(self): """ Public slot to create a new virtual environment. """ from .VirtualenvConfigurationDialog import \ VirtualenvConfigurationDialog dlg = VirtualenvConfigurationDialog() if dlg.exec_() == QDialog.Accepted: (pyvenv, args, name, openTarget, createLog, createScript, targetDir, interpreter) = 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_() def addVirtualEnv(self, venvName, venvDirectory, venvInterpreter=""): """ Public method to add a virtual environment. @param venvName logical name for the virtual environment @type str @param venvDirectory directory of the virtual environment @type str @param venvInterpreter interpreter of the virtual environment """ if venvName in self.__virtualEnvironments: ok = E5MessageBox.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=E5MessageBox.Warning) if not ok: return if not venvInterpreter: from .VirtualenvInterpreterSelectionDialog import \ VirtualenvInterpreterSelectionDialog dlg = VirtualenvInterpreterSelectionDialog(venvName, venvDirectory) if dlg.exec_() == QDialog.Accepted: venvInterpreter = dlg.getData() if venvInterpreter: self.__virtualEnvironmentInterpreters[venvName] = venvInterpreter self.__virtualEnvironments[venvName] = venvDirectory self.__updateSettings() if self.__virtualenvManagerDialog: self.__virtualenvManagerDialog.refresh() def setVirtualEnv(self, venvName, venvDirectory, venvInterpreter=""): """ Public method to change a virtual environment. @param venvName logical name of the virtual environment @type str @param venvDirectory directory of the virtual environment @type str @param venvInterpreter interpreter of the virtual environment """ if venvName not in self.__virtualEnvironments: E5MessageBox.yesNo( None, self.tr("Change Virtual Environment"), self.tr("""A virtual environment named <b>{0}</b> does not""" """ exist. Aborting!""") .format(venvName), icon=E5MessageBox.Warning) return self.__virtualEnvironmentInterpreters[venvName] = venvInterpreter self.__virtualEnvironments[venvName] = venvDirectory self.__updateSettings() if self.__virtualenvManagerDialog: self.__virtualenvManagerDialog.refresh() def renameVirtualEnv(self, oldVenvName, venvName, venvDirectory, venvInterpreter): """ 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 @type str @param venvDirectory directory of the virtual environment @type str @param venvInterpreter interpreter of the virtual environment """ if oldVenvName not in self.__virtualEnvironments: E5MessageBox.yesNo( None, self.tr("Rename Virtual Environment"), self.tr("""A virtual environment named <b>{0}</b> does not""" """ exist. Aborting!""") .format(oldVenvName), icon=E5MessageBox.Warning) return del self.__virtualEnvironments[oldVenvName] del self.__virtualEnvironmentInterpreters[oldVenvName] self.addVirtualEnv(venvName, venvDirectory, venvInterpreter) 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]): venvMessages.append(self.tr("{0} - {1}").format( venvName, self.__virtualEnvironments[venvName])) if venvMessages: 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 ) 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) del self.__virtualEnvironments[venvName] del self.__virtualEnvironmentInterpreters[venvName] self.__updateSettings() if self.__virtualenvManagerDialog: self.__virtualenvManagerDialog.refresh() 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])) if venvMessages: 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 ) if dlg.exec_() == QDialog.Accepted: for venvName in venvNames: if venvName in self.__virtualEnvironments: del self.__virtualEnvironments[venvName] del self.__virtualEnvironmentInterpreters[venvName] self.__updateSettings() if self.__virtualenvManagerDialog: self.__virtualenvManagerDialog.refresh() def getEnvironmentEntries(self): """ Public method to 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) """ environments = {} for venvName in self.__virtualEnvironments: environments[venvName] = ( self.__virtualEnvironments[venvName], self.__virtualEnvironmentInterpreters[venvName], ) return environments @pyqtSlot() def showVirtualenvManagerDialog(self): """ Public slot to show the virtual environment manager dialog. """ if self.__virtualenvManagerDialog is None: from .VirtualenvManagerDialog import VirtualenvManagerDialog self.__virtualenvManagerDialog = VirtualenvManagerDialog( self, self.__ui) self.__virtualenvManagerDialog.show() def shutdown(self): """ Public method to shutdown the manager. """ if self.__virtualenvManagerDialog is not None: self.__virtualenvManagerDialog.close() self.__virtualenvManagerDialog = None 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.__virtualEnvironmentInterpreters: return self.__virtualEnvironmentInterpreters[venvName] else: return "" 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 @rtype str """ if venvName in self.__virtualEnvironments: return self.__virtualEnvironments[venvName] else: return "" def getVirtualenvNames(self): """ Public method to get a list of defined virtual environments. @return list of defined virtual environments @rtype list of str """ return list(self.__virtualEnvironmentInterpreters.keys())