VirtualEnv/VirtualenvManager.py

Tue, 12 Jun 2018 18:59:45 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Tue, 12 Jun 2018 18:59:45 +0200
changeset 6341
a00e63f6d766
parent 6338
104ee21d765d
child 6349
17b3c75913de
permissions
-rw-r--r--

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())

eric ide

mercurial