Sun, 09 Dec 2018 13:13:27 +0100
pip Interface: added an entry to select the virtual environment of the current project if it has one defined.
# -*- coding: utf-8 -*- # Copyright (c) 2015 - 2018 Detlev Offenbach <detlev@die-offenbachs.de> # """ Package implementing the pip GUI logic. """ from __future__ import unicode_literals try: str = unicode # __IGNORE_EXCEPTION__ except NameError: pass import os import sys from PyQt5.QtCore import pyqtSlot, QObject, QProcess from PyQt5.QtWidgets import QMenu, QInputDialog, QDialog from E5Gui import E5MessageBox from E5Gui.E5Action import E5Action from E5Gui.E5Application import e5App from .PipDialog import PipDialog from . import DefaultIndexUrlXml import Preferences import Globals class Pip(QObject): """ Class implementing the pip GUI logic. """ def __init__(self, plugin, parent=None): """ Constructor @param plugin reference to the plugin object @type PipInterfacePlugin @param parent parent @type QObject """ super(Pip, self).__init__(parent) self.__plugin = plugin self.__ui = parent self.__virtualenvManager = e5App().getObject("VirtualEnvManager") self.__project = e5App().getObject("Project") self.__menus = {} # dictionary with references to menus self.__plugin.currentEnvironmentChanged.connect( self.__handleTearOffMenu) def initActions(self): """ Public method to define the actions. """ self.actions = [] self.selectEnvironmentAct = E5Action( self.tr('Virtual Environment for pip'), self.tr('&Virtual Environment for pip'), 0, 0, self, 'pip_select_environment') self.selectEnvironmentAct.setStatusTip(self.tr( 'Selects the virtual environment to be used for pip')) self.selectEnvironmentAct.setWhatsThis(self.tr( """<b>Virtual Environment for pip</b>""" """<p>This selects the virtual environment to be used for pip.""" """</p>""" )) self.selectEnvironmentAct.triggered.connect(self.__selectPipVirtualenv) self.actions.append(self.selectEnvironmentAct) ############################################## ## Actions for listing packages ############################################## self.listPackagesAct = E5Action( self.tr('List Installed Packages'), self.tr('&List Installed Packages...'), 0, 0, self, 'pip_list_packages') self.listPackagesAct.setStatusTip(self.tr( 'List all installed packages with versions')) self.listPackagesAct.setWhatsThis(self.tr( """<b>List Installed Packages</b>""" """<p>This lists all the installed packages together""" """ with their versions.</p>""" )) self.listPackagesAct.triggered.connect(self.__listPackages) self.actions.append(self.listPackagesAct) self.listUptodatePackagesAct = E5Action( self.tr('List Up-to-date Packages'), self.tr('List Up-to-&date Packages...'), 0, 0, self, 'pip_list_uptodate_packages') self.listUptodatePackagesAct.setStatusTip(self.tr( 'List all installed, up-to-date packages with versions')) self.listUptodatePackagesAct.setWhatsThis(self.tr( """<b>List Up-to-date Packages</b>""" """<p>This lists all the installed, up-to-date packages together""" """ with their versions.</p>""" )) self.listUptodatePackagesAct.triggered.connect( self.__listUptodatePackages) self.actions.append(self.listUptodatePackagesAct) self.listOutdatedPackagesAct = E5Action( self.tr('List Outdated Packages'), self.tr('List &Outdated Packages...'), 0, 0, self, 'pip_list_outdated_packages') self.listOutdatedPackagesAct.setStatusTip(self.tr( 'List all installed, outdated packages with versions')) self.listOutdatedPackagesAct.setWhatsThis(self.tr( """<b>List Up-to-date Packages</b>""" """<p>This lists all the installed, outdated packages together""" """ with their current and latest versions.</p>""" )) self.listOutdatedPackagesAct.triggered.connect( self.__listOutdatedPackages) self.actions.append(self.listOutdatedPackagesAct) ############################################## ## Actions for installing packages ############################################## self.installPackagesAct = E5Action( self.tr('Install Packages'), self.tr('&Install Packages'), 0, 0, self, 'pip_install_packages') self.installPackagesAct.setStatusTip(self.tr( 'Install packages according to user input')) self.installPackagesAct.setWhatsThis(self.tr( """<b>Install Packages</b>""" """<p>This installs packages according to user input.</p>""" )) self.installPackagesAct.triggered.connect(self.__installPackages) self.actions.append(self.installPackagesAct) self.installLocalPackageAct = E5Action( self.tr('Install Local Package'), self.tr('Install Local Package'), 0, 0, self, 'pip_install_local_package') self.installLocalPackageAct.setStatusTip(self.tr( 'Install a package from local storage')) self.installLocalPackageAct.setWhatsThis(self.tr( """<b>Install Local Package</b>""" """<p>This installs a package available on local storage.</p>""" )) self.installLocalPackageAct.triggered.connect( self.__installLocalPackage) self.actions.append(self.installLocalPackageAct) self.installRequirementsAct = E5Action( self.tr('Install Requirements'), self.tr('Install Requirements'), 0, 0, self, 'pip_install_requirements') self.installRequirementsAct.setStatusTip(self.tr( 'Install packages according to a requirements file')) self.installRequirementsAct.setWhatsThis(self.tr( """<b>Install Requirements</b>""" """<p>This installs packages according to a requirements""" """ file.</p>""" )) self.installRequirementsAct.triggered.connect( self.__installRequirements) self.actions.append(self.installRequirementsAct) self.installPipAct = E5Action( self.tr('Install Pip'), self.tr('Install Pip'), 0, 0, self, 'pip_install_pip') self.installPipAct.setStatusTip(self.tr( 'Install the pip package itself')) self.installPipAct.setWhatsThis(self.tr( """<b>Install Pip</b>""" """<p>This installs the pip package itself.</p>""" )) self.installPipAct.triggered.connect(self.__installPip) self.actions.append(self.installPipAct) self.repairPipAct = E5Action( self.tr('Repair Pip'), self.tr('Repair Pip'), 0, 0, self, 'pip_repair_pip') self.repairPipAct.setStatusTip(self.tr( 'Repair the pip package')) self.repairPipAct.setWhatsThis(self.tr( """<b>Repair Pip</b>""" """<p>This repairs the pip package by re-installing it.</p>""" )) self.repairPipAct.triggered.connect(self.__repairPip) self.actions.append(self.repairPipAct) self.upgradePipAct = E5Action( self.tr('Upgrade Pip'), self.tr('Upgrade &Pip'), 0, 0, self, 'pip_upgrade_pip') self.upgradePipAct.setStatusTip(self.tr( 'Upgrade the pip package itself')) self.upgradePipAct.setWhatsThis(self.tr( """<b>Upgrade Pip</b>""" """<p>This upgrades the pip package itself.</p>""" )) self.upgradePipAct.triggered.connect(self.upgradePip) self.actions.append(self.upgradePipAct) self.upgradePackagesAct = E5Action( self.tr('Upgrade Packages'), self.tr('&Upgrade Packages'), 0, 0, self, 'pip_upgrade_packages') self.upgradePackagesAct.setStatusTip(self.tr( 'Upgrade packages according to user input')) self.upgradePackagesAct.setWhatsThis(self.tr( """<b>Upgrade Packages</b>""" """<p>This upgrades packages according to user input.</p>""" )) self.upgradePackagesAct.triggered.connect(self.__upgradePackages) self.actions.append(self.upgradePackagesAct) ############################################## ## Actions for uninstalling packages ############################################## self.uninstallPackagesAct = E5Action( self.tr('Uninstall Packages'), self.tr('Uninstall Packages'), 0, 0, self, 'pip_uninstall_packages') self.uninstallPackagesAct.setStatusTip(self.tr( 'Uninstall packages according to user input')) self.uninstallPackagesAct.setWhatsThis(self.tr( """<b>Uninstall Packages</b>""" """<p>This uninstalls packages according to user input.</p>""" )) self.uninstallPackagesAct.triggered.connect(self.__uninstallPackages) self.actions.append(self.uninstallPackagesAct) self.uninstallRequirementsAct = E5Action( self.tr('Uninstall Requirements'), self.tr('Uninstall Requirements'), 0, 0, self, 'pip_uninstall_requirements') self.uninstallRequirementsAct.setStatusTip(self.tr( 'Uninstall packages according to a requirements file')) self.uninstallRequirementsAct.setWhatsThis(self.tr( """<b>Uninstall Requirements</b>""" """<p>This uninstalls packages according to a requirements""" """ file.</p>""" )) self.uninstallRequirementsAct.triggered.connect( self.__uninstallRequirements) self.actions.append(self.uninstallRequirementsAct) ############################################## ## Actions for generating requirements files ############################################## self.generateRequirementsAct = E5Action( self.tr('Generate Requirements'), self.tr('&Generate Requirements...'), 0, 0, self, 'pip_generate_requirements') self.generateRequirementsAct.setStatusTip(self.tr( 'Generate the contents of a requirements file')) self.generateRequirementsAct.setWhatsThis(self.tr( """<b>Generate Requirements</b>""" """<p>This generates the contents of a requirements file.</p>""" )) self.generateRequirementsAct.triggered.connect( self.__generateRequirements) self.actions.append(self.generateRequirementsAct) ############################################## ## Actions for generating requirements files ############################################## self.searchPyPIAct = E5Action( self.tr('Search PyPI'), self.tr('&Search PyPI...'), 0, 0, self, 'pip_search_pypi') self.searchPyPIAct.setStatusTip(self.tr( 'Open a dialog to search the Python Package Index')) self.searchPyPIAct.setWhatsThis(self.tr( """<b>Search PyPI</b>""" """<p>This opens a dialog to search the Python Package""" """ Index.</p>""" )) self.searchPyPIAct.triggered.connect(self.__searchPyPI) self.actions.append(self.searchPyPIAct) ############################################## ## Actions for editing configuration files ############################################## self.editUserConfigAct = E5Action( self.tr('Edit User Configuration'), self.tr('Edit User Configuration...'), 0, 0, self, 'pip_edit_user_config') self.editUserConfigAct.setStatusTip(self.tr( 'Open the per user configuration file in an editor')) self.editUserConfigAct.setWhatsThis(self.tr( """<b>Edit User Configuration</b>""" """<p>This opens the per user configuration file in an editor.""" """</p>""" )) self.editUserConfigAct.triggered.connect(self.__editUserConfiguration) self.actions.append(self.editUserConfigAct) self.editVirtualenvConfigAct = E5Action( self.tr('Edit Current Virtualenv Configuration'), self.tr('Edit Current Virtualenv Configuration...'), 0, 0, self, 'pip_edit_virtualenv_config') self.editVirtualenvConfigAct.setStatusTip(self.tr( 'Open the current virtualenv configuration file in an editor')) self.editVirtualenvConfigAct.setWhatsThis(self.tr( """<b>Edit Current Virtualenv Configuration</b>""" """<p>This opens the current virtualenv configuration file in""" """ an editor. </p>""" )) self.editVirtualenvConfigAct.triggered.connect( self.__editVirtualenvConfiguration) self.actions.append(self.editVirtualenvConfigAct) self.pipConfigAct = E5Action( self.tr('Configure'), self.tr('Configure...'), 0, 0, self, 'pip_configure') self.pipConfigAct.setStatusTip(self.tr( 'Show the configuration dialog with the Python Package Management' ' page selected' )) self.pipConfigAct.setWhatsThis(self.tr( """<b>Configure</b>""" """<p>Show the configuration dialog with the Python Package""" """ Management page selected.</p>""" )) self.pipConfigAct.triggered.connect(self.__pipConfigure) self.actions.append(self.pipConfigAct) def initMenu(self): """ Public slot to initialize the menu. @return the menu generated @rtype QMenu """ self.__menus = {} # clear menus references menu = QMenu(self.tr('P&ython Package Management'), self.__ui) menu.setTearOffEnabled(True) menu.addAction(self.selectEnvironmentAct) menu.addSeparator() menu.addAction(self.listPackagesAct) menu.addAction(self.listUptodatePackagesAct) menu.addAction(self.listOutdatedPackagesAct) menu.addSeparator() menu.addAction(self.installPipAct) menu.addSeparator() menu.addAction(self.installPackagesAct) menu.addAction(self.installLocalPackageAct) menu.addAction(self.installRequirementsAct) menu.addSeparator() menu.addAction(self.upgradePipAct) menu.addAction(self.upgradePackagesAct) menu.addSeparator() menu.addAction(self.uninstallPackagesAct) menu.addAction(self.uninstallRequirementsAct) menu.addSeparator() menu.addAction(self.generateRequirementsAct) menu.addSeparator() menu.addAction(self.searchPyPIAct) menu.addSeparator() menu.addAction(self.repairPipAct) menu.addSeparator() menu.addAction(self.editUserConfigAct) menu.addAction(self.editVirtualenvConfigAct) menu.addSeparator() menu.addAction(self.pipConfigAct) self.__menus["main"] = menu menu.aboutToShow.connect(self.__aboutToShowMenu) return menu def __aboutToShowMenu(self): """ Private slot to set the action enabled status. """ enable = bool(self.__plugin.getPreferences("CurrentEnvironment")) for act in self.actions: if act not in [self.selectEnvironmentAct, self.installPipAct, self.editUserConfigAct, self.editVirtualenvConfigAct, self.pipConfigAct]: act.setEnabled(enable) def getMenu(self, name): """ Public method to get a reference to the requested menu. @param name name of the menu @type str @return reference to the menu or None, if no menu with the given name exists @rtype QMenu or None """ if name in self.__menus: return self.__menus[name] else: return None def getMenuNames(self): """ Public method to get the names of all menus. @return menu names @rtype list of str """ return list(self.__menus.keys()) def __handleTearOffMenu(self, venvName): """ Private slot to handle a change of the selected virtual environment. @param venvName logical name of the virtual environment @type str """ if self.__menus["main"].isTearOffMenuVisible(): # determine, if torn off menu needs to be refreshed enabled = self.listPackagesAct.isEnabled() if ((bool(venvName) and not enabled) or (not bool(venvName) and enabled)): self.__menus["main"].hideTearOffMenu() ########################################################################## ## Methods below implement some utility functions ########################################################################## def runProcess(self, args, interpreter): """ Public method to execute the current pip with the given arguments. The selected pip executable is called with the given arguments and waited for its end. @param args list of command line arguments @type list of str @param interpreter path of the Python interpreter to be used @type str @return tuple containing a flag indicating success and the output of the process @rtype tuple of (bool, str) """ ioEncoding = Preferences.getSystem("IOEncoding") process = QProcess() process.start(interpreter, args) procStarted = process.waitForStarted() if procStarted: finished = process.waitForFinished(30000) if finished: if process.exitCode() == 0: output = str(process.readAllStandardOutput(), ioEncoding, 'replace') return True, output else: return (False, self.tr("python exited with an error ({0}).") .format(process.exitCode())) else: process.terminate() process.waitForFinished(2000) process.kill() process.waitForFinished(3000) return False, self.tr("python did not finish within" " 30 seconds.") return False, self.tr("python could not be started.") def __getUserConfig(self): """ Private method to get the name of the user configuration file. @return path of the user configuration file @rtype str """ # Unix: ~/.config/pip/pip.conf # OS X: ~/Library/Application Support/pip/pip.conf # Windows: %APPDATA%\pip\pip.ini # Environment: $PIP_CONFIG_FILE try: return os.environ["PIP_CONFIG_FILE"] except KeyError: pass if Globals.isWindowsPlatform(): config = os.path.join(os.environ["APPDATA"], "pip", "pip.ini") elif Globals.isMacPlatform(): config = os.path.expanduser( "~/Library/Application Support/pip/pip.conf") else: config = os.path.expanduser("~/.config/pip/pip.conf") return config def __getVirtualenvConfig(self): """ Private method to get the name of the virtualenv configuration file. @return path of the virtualenv configuration file @rtype str """ # Unix, OS X: $VIRTUAL_ENV/pip.conf # Windows: %VIRTUAL_ENV%\pip.ini if Globals.isWindowsPlatform(): pip = "pip.ini" else: pip = "pip.conf" try: venvDirectory = os.environ["VIRTUAL_ENV"] except KeyError: venvName = self.__plugin.getPreferences("CurrentEnvironment") if not venvName: self.__selectPipVirtualenv() venvName = self.__plugin.getPreferences("CurrentEnvironment") if self.__virtualenvManager.isGlobalEnvironment(venvName): venvDirectory = self.__getUserConfig() else: venvDirectory = \ self.__virtualenvManager.getVirtualenvDirectory(venvName) return os.path.join(venvDirectory, pip) def getDefaultEnvironmentString(self): """ Public method to get the string for the default environment. @return string for the default environment @rtype str """ return self.tr("<standard>") def getProjectEnvironmentString(self): """ Public method to get the string for the project environment. @return string for the project environment @rtype str """ if self.__project.isOpen(): return self.tr("<project>") else: return "" 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 == self.getDefaultEnvironmentString(): venvName = self.__plugin.getPreferences("CurrentEnvironment") elif venvName == self.getProjectEnvironmentString(): venvName = self.__project.getDebugProperty("VIRTUALENV") if not venvName: # fall back to standard if not defined venvName = self.__plugin.getPreferences("CurrentEnvironment") interpreter = self.__virtualenvManager.getVirtualenvInterpreter( venvName) if not interpreter: E5MessageBox.critical( None, self.tr("Interpreter for Virtual Environment"), self.tr("""No interpreter configured for the selected""" """ virtual environment.""")) return interpreter def getVirtualenvNames(self): """ Public method to get a sorted list of virtual environment names. @return sorted list of virtual environment names @rtype list of str """ return sorted(self.__virtualenvManager.getVirtualenvNames()) ########################################################################## ## Methods below implement the individual menu entries ########################################################################## def __selectPipVirtualenv(self): """ Private method to select the virtual environment to be used. """ environments = self.getVirtualenvNames() if environments: currentEnvironment = self.__plugin.getPreferences( "CurrentEnvironment") try: index = environments.index(currentEnvironment) except ValueError: index = 0 environment, ok = QInputDialog.getItem( None, self.tr("Virtual Environment for pip"), self.tr("Select the virtual environment to be used:"), environments, index, False) if ok and environment: self.__plugin.setPreferences("CurrentEnvironment", environment) else: E5MessageBox.warning( None, self.tr("Virtual Environment for pip"), self.tr("""No virtual environments have been configured yet.""" """ Please use the Virtualenv Manager to do that.""")) def __listPackages(self): """ Private slot to list all installed packages. """ from .PipListDialog import PipListDialog self.__listDialog = PipListDialog( self, "list", self.__plugin.getPreferences("PipSearchIndex"), self.tr("Installed Packages")) self.__listDialog.show() self.__listDialog.start() def __listUptodatePackages(self): """ Private slot to list all installed, up-to-date packages. """ from .PipListDialog import PipListDialog self.__listUptodateDialog = PipListDialog( self, "uptodate", self.__plugin.getPreferences("PipSearchIndex"), self.tr("Up-to-date Packages")) self.__listUptodateDialog.show() self.__listUptodateDialog.start() def __listOutdatedPackages(self): """ Private slot to list all installed, up-to-date packages. """ from .PipListDialog import PipListDialog self.__listOutdatedDialog = PipListDialog( self, "outdated", self.__plugin.getPreferences("PipSearchIndex"), self.tr("Outdated Packages")) self.__listOutdatedDialog.show() self.__listOutdatedDialog.start() def __editUserConfiguration(self): """ Private slot to edit the user configuration. """ self.__editConfiguration() def __editVirtualenvConfiguration(self): """ Private slot to edit the current virtualenv configuration. """ self.__editConfiguration(virtualenv=True) def __editConfiguration(self, virtualenv=False): """ Private method to edit a configuration. @param virtualenv flag indicating to edit the current virtualenv configuration file @type bool """ from QScintilla.MiniEditor import MiniEditor if virtualenv: cfgFile = self.__getVirtualenvConfig() else: cfgFile = self.__getUserConfig() cfgDir = os.path.dirname(cfgFile) if not cfgDir: E5MessageBox.critical( None, self.tr("Edit Configuration"), self.tr("""No valid configuration path determined.""" """ Is a virtual environment selected? Aborting""")) return try: if not os.path.isdir(cfgDir): os.makedirs(cfgDir) except OSError: E5MessageBox.critical( None, self.tr("Edit Configuration"), self.tr("""No valid configuration path determined.""" """ Is a virtual environment selected? Aborting""")) return if not os.path.exists(cfgFile): try: f = open(cfgFile, "w") f.write("[global]\n") f.close() except (IOError, OSError): # ignore these pass # check, if the destination is writeable if not os.access(cfgFile, os.W_OK): E5MessageBox.critical( None, self.tr("Edit Configuration"), self.tr("""No valid configuartion path determined.""" """ Is a virtual environment selected? Aborting""")) return self.__editor = MiniEditor(cfgFile, "Properties") self.__editor.show() def __installPip(self, userSite=False): """ Private slot to install pip. @param userSite flag indicating an install to the user install directory @type bool """ from .PipSelectionDialog import PipSelectionDialog dlg = PipSelectionDialog(self) if dlg.exec_() != QDialog.Accepted: return venvName, userSite = dlg.getData() interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: return dia = PipDialog(self.tr('Install PIP')) if userSite: commands = [(interpreter, ["-m", "ensurepip", "--user"])] else: commands = [(interpreter, ["-m", "ensurepip"])] if self.__plugin.getPreferences("PipSearchIndex"): indexUrl = \ self.__plugin.getPreferences("PipSearchIndex") + "/simple" args = ["-m", "pip", "install", "--index-url", indexUrl, "--upgrade"] else: args = ["-m", "pip", "install", "--upgrade"] if userSite: args.append("--user") args.append("pip") commands.append((interpreter, args[:])) res = dia.startProcesses(commands) if res: dia.exec_() @pyqtSlot() def upgradePip(self, venvName="", userSite=False): """ Public method to upgrade pip itself. @param venvName name of the virtual environment to be used @type str @param userSite flag indicating an install to the user install directory @type bool @return flag indicating a successful execution @rtype bool """ # Upgrading pip needs to be treated specially because # it must be done using the python executable if not venvName: from .PipSelectionDialog import PipSelectionDialog dlg = PipSelectionDialog(self) if dlg.exec_() != QDialog.Accepted: return venvName, userSite = dlg.getData() interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: return if self.__plugin.getPreferences("PipSearchIndex"): indexUrl = \ self.__plugin.getPreferences("PipSearchIndex") + "/simple" args = ["-m", "pip", "install", "--index-url", indexUrl, "--upgrade"] else: args = ["-m", "pip", "install", "--upgrade"] if userSite: args.append("--user") args.append("pip") dia = PipDialog(self.tr('Upgrade PIP')) res = dia.startProcess(interpreter, args) if res: dia.exec_() return res @pyqtSlot() def __repairPip(self): """ Private method to repair the pip installation. @return flag indicating a successful execution @rtype bool """ from .PipSelectionDialog import PipSelectionDialog dlg = PipSelectionDialog(self) if dlg.exec_() != QDialog.Accepted: return False venvName, userSite = dlg.getData() interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: return # python -m pip install --ignore-installed pip if self.__plugin.getPreferences("PipSearchIndex"): indexUrl = \ self.__plugin.getPreferences("PipSearchIndex") + "/simple" args = ["-m", "pip", "install", "--index-url", indexUrl, "--ignore-installed"] else: args = ["-m", "pip", "install", "--ignore-installed"] if userSite: args.append("--user") args.append("pip") dia = PipDialog(self.tr('Repair PIP')) res = dia.startProcess(interpreter, args) if res: dia.exec_() def __checkUpgradePyQt(self, packages): """ Private method to check, if an upgrade of PyQt packages is attempted. @param packages list of packages to upgrade @type list of str @return flag indicating to abort the upgrade attempt @rtype bool """ pyqtPackages = [p for p in packages if p.lower() in ["pyqt5", "qscintilla", "sip"]] if bool(pyqtPackages): abort = not E5MessageBox.yesNo( None, self.tr("Upgrade Packages"), self.tr( """You are trying to upgrade PyQt packages. This will""" """ not work for the current instance of Python ({0}).""" """ Do you want to continue?""").format(sys.executable), icon=E5MessageBox.Critical) else: abort = False return abort def upgradePackages(self, packages, venvName="", userSite=False): """ Public method to upgrade the given list of packages. @param packages list of packages to upgrade @type list of str @param venvName name of the virtual environment to be used @type str @param userSite flag indicating an install to the user install directory @type bool @return flag indicating a successful execution @rtype bool """ if self.__checkUpgradePyQt(packages): return False if not venvName: venvName = self.__plugin.getPreferences("CurrentEnvironment") interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: return if self.__plugin.getPreferences("PipSearchIndex"): indexUrl = \ self.__plugin.getPreferences("PipSearchIndex") + "/simple" args = ["-m", "pip", "install", "--index-url", indexUrl, "--upgrade"] else: args = ["-m", "pip", "install", "--upgrade"] if userSite: args.append("--user") args += packages dia = PipDialog(self.tr('Upgrade Packages')) res = dia.startProcess(interpreter, args) if res: dia.exec_() return res def __upgradePackages(self): """ Private slot to upgrade packages to be given by the user. """ from .PipPackagesInputDialog import PipPackagesInputDialog dlg = PipPackagesInputDialog(self, self.tr("Upgrade Packages")) if dlg.exec_() == QDialog.Accepted: venvName, packages, user = dlg.getData() if packages: self.upgradePackages(packages, venvName=venvName, userSite=user) def installPackages(self, packages, venvName="", userSite=False): """ Public method to install the given list of packages. @param packages list of packages to install @type list of str @param venvName name of the virtual environment to be used @type str @param userSite flag indicating an install to the user install directory @type bool """ if not venvName: venvName = self.__plugin.getPreferences("CurrentEnvironment") interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: return if self.__plugin.getPreferences("PipSearchIndex"): indexUrl = \ self.__plugin.getPreferences("PipSearchIndex") + "/simple" args = ["-m", "pip", "install", "--index-url", indexUrl] else: args = ["-m", "pip", "install"] if userSite: args.append("--user") args += packages dia = PipDialog(self.tr('Install Packages')) res = dia.startProcess(interpreter, args) if res: dia.exec_() def __installPackages(self): """ Private slot to install packages to be given by the user. """ from .PipPackagesInputDialog import PipPackagesInputDialog dlg = PipPackagesInputDialog( self, self.tr("Install Packages")) if dlg.exec_() == QDialog.Accepted: venvName, packages, user = dlg.getData() if packages: self.installPackages(packages, venvName=venvName, userSite=user) def __installLocalPackage(self): """ Private slot to install a package available on local storage. """ from .PipFileSelectionDialog import PipFileSelectionDialog dlg = PipFileSelectionDialog(self, "package") if dlg.exec_() == QDialog.Accepted: venvName, package, user = dlg.getData() if package and os.path.exists(package): self.installPackages([package], venvName=venvName, userSite=user) def __installRequirements(self): """ Private slot to install packages as given in a requirements file. """ from .PipFileSelectionDialog import PipFileSelectionDialog dlg = PipFileSelectionDialog(self, "requirements") if dlg.exec_() == QDialog.Accepted: venvName, requirements, user = dlg.getData() if requirements and os.path.exists(requirements): interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: return if self.__plugin.getPreferences("PipSearchIndex"): indexUrl = \ self.__plugin.getPreferences("PipSearchIndex") + \ "/simple" args = ["-m", "pip", "install", "--index-url", indexUrl] else: args = ["-m", "pip", "install"] if user: args.append("--user") args += ["--requirement", requirements] dia = PipDialog(self.tr('Install Packages from Requirements')) res = dia.startProcess(interpreter, args) if res: dia.exec_() def uninstallPackages(self, packages, venvName=""): """ Public method to uninstall the given list of packages. @param packages list of packages to uninstall @type list of str @param venvName name of the virtual environment to be used @type str @return flag indicating a successful execution @rtype bool """ res = False if packages: from UI.DeleteFilesConfirmationDialog import \ DeleteFilesConfirmationDialog dlg = DeleteFilesConfirmationDialog( self.parent(), self.tr("Uninstall Packages"), self.tr( "Do you really want to uninstall these packages?"), packages) if dlg.exec_() == QDialog.Accepted: if not venvName: venvName = self.__plugin.getPreferences( "CurrentEnvironment") interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: return args = ["-m", "pip", "uninstall", "--yes"] + packages dia = PipDialog(self.tr('Uninstall Packages')) res = dia.startProcess(interpreter, args) if res: dia.exec_() return res def __uninstallPackages(self): """ Private slot to uninstall packages to be given by the user. """ from .PipPackagesInputDialog import PipPackagesInputDialog dlg = PipPackagesInputDialog( self, self.tr("Uninstall Packages"), install=False) if dlg.exec_() == QDialog.Accepted: venvName, packages, _user = dlg.getData() if packages: self.uninstallPackages(packages, venvName=venvName) def __uninstallRequirements(self): """ Private slot to uninstall packages as given in a requirements file. """ from .PipFileSelectionDialog import PipFileSelectionDialog dlg = PipFileSelectionDialog(self, "requirements", install=False) if dlg.exec_() == QDialog.Accepted: venvName, requirements, _user = dlg.getData() if requirements and os.path.exists(requirements): try: f = open(requirements, "r") reqs = f.read().splitlines() f.close() except (OSError, IOError): return from UI.DeleteFilesConfirmationDialog import \ DeleteFilesConfirmationDialog dlg = DeleteFilesConfirmationDialog( self.parent(), self.tr("Uninstall Packages"), self.tr( "Do you really want to uninstall these packages?"), reqs) if dlg.exec_() == QDialog.Accepted: if not venvName: venvName = self.__plugin.getPreferences( "CurrentEnvironment") interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: return args = ["-m", "pip", "uninstall", "--requirement", requirements] dia = PipDialog( self.tr('Uninstall Packages from Requirements')) res = dia.startProcess(interpreter, args) if res: dia.exec_() def __generateRequirements(self): """ Private slot to generate the contents for a requirements file. """ from .PipFreezeDialog import PipFreezeDialog self.__freezeDialog = PipFreezeDialog(self) self.__freezeDialog.show() self.__freezeDialog.start() def __searchPyPI(self): """ Private slot to search the Python Package Index. """ from .PipSearchDialog import PipSearchDialog if self.__plugin.getPreferences("PipSearchIndex"): indexUrl = self.__plugin.getPreferences("PipSearchIndex") + "/pypi" else: indexUrl = DefaultIndexUrlXml self.__searchDialog = PipSearchDialog(self, indexUrl) self.__searchDialog.show() def __pipConfigure(self): """ Private slot to open the configuration page. """ e5App().getObject("UserInterface").showPreferences("pipPage")