diff -r a00e63f6d766 -r c79ecba9cde7 Plugins/UiExtensionPlugins/PipInterface/Pip.py --- a/Plugins/UiExtensionPlugins/PipInterface/Pip.py Tue Jun 12 18:59:45 2018 +0200 +++ b/Plugins/UiExtensionPlugins/PipInterface/Pip.py Tue Jun 12 19:01:06 2018 +0200 @@ -14,23 +14,22 @@ pass import os -import re import sys -from PyQt5.QtCore import pyqtSlot, QObject, QProcess, QDir +from PyQt5.QtCore import pyqtSlot, QObject, QProcess from PyQt5.QtWidgets import QMenu, QInputDialog, QDialog -from E5Gui import E5MessageBox, E5FileDialog +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 -# TODO: 1) change all uses of pip to python3 -m pip class Pip(QObject): """ Class implementing the pip GUI logic. @@ -40,38 +39,42 @@ Constructor @param plugin reference to the plugin object - @param parent parent (QObject) + @type PipInterfacePlugin + @param parent parent + @type QObject """ super(Pip, self).__init__(parent) self.__plugin = plugin self.__ui = parent + self.__virtualenvManager = e5App().getObject("VirtualEnvManager") + self.__menus = {} # dictionary with references to menus - self.__plugin.currentPipChanged.connect(self.__handleTearOffMenu) + self.__plugin.currentEnvironmentChanged.connect( + self.__handleTearOffMenu) def initActions(self): """ - Public method to define the Django actions. + Public method to define the actions. """ self.actions = [] - self.selectExecutableAct = E5Action( - self.tr('pip Executable'), - self.tr('pip &Executable'), + self.selectEnvironmentAct = E5Action( + self.tr('Virtual Environment for pip'), + self.tr('&Virtual Environment for pip'), 0, 0, - self, 'pip_select_executable') - self.selectExecutableAct.setStatusTip(self.tr( - 'Selects the pip executable to be used')) - self.selectExecutableAct.setWhatsThis(self.tr( - """<b>pip Executable</b>""" - """<p>This selects the pip executable to be used. Multiple""" - """ executables can be pre-configured via the configuration""" - """ dialog.</p>""" + 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.selectExecutableAct.triggered.connect(self.__selectPipExecutable) - self.actions.append(self.selectExecutableAct) + self.selectEnvironmentAct.triggered.connect(self.__selectPipVirtualenv) + self.actions.append(self.selectEnvironmentAct) ############################################## ## Actions for listing packages @@ -184,26 +187,9 @@ """<b>Install Pip</b>""" """<p>This installs the pip package itself.</p>""" )) - self.installPipAct.triggered.connect( - lambda: self.__installPip(userSite=False)) + self.installPipAct.triggered.connect(self.__installPip) self.actions.append(self.installPipAct) - self.installPipUserAct = E5Action( - self.tr('Install Pip to User-Site'), - self.tr('Install Pip to User-Site'), - 0, 0, - self, 'pip_install_pip_user') - self.installPipUserAct.setStatusTip(self.tr( - 'Install the pip package itself to the user directory')) - self.installPipUserAct.setWhatsThis(self.tr( - """<b>Install Pip to User-Site</b>""" - """<p>This installs the pip package itself to the user""" - """ directory.</p>""" - )) - self.installPipUserAct.triggered.connect( - lambda: self.__installPip(userSite=True)) - self.actions.append(self.installPipUserAct) - self.repairPipAct = E5Action( self.tr('Repair Pip'), self.tr('Repair Pip'), @@ -371,23 +357,23 @@ def initMenu(self): """ - Public slot to initialize the Django menu. + Public slot to initialize the menu. - @return the menu generated (QMenu) + @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.selectExecutableAct) + 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.addAction(self.installPipUserAct) menu.addSeparator() menu.addAction(self.installPackagesAct) menu.addAction(self.installLocalPackageAct) @@ -420,11 +406,10 @@ """ Private slot to set the action enabled status. """ - enable = bool(self.__plugin.getPreferences("CurrentPipExecutable")) + enable = bool(self.__plugin.getPreferences("CurrentEnvironment")) for act in self.actions: - if act not in [self.selectExecutableAct, + if act not in [self.selectEnvironmentAct, self.installPipAct, - self.installPipUserAct, self.editUserConfigAct, self.editVirtualenvConfigAct, self.pipConfigAct]: @@ -434,9 +419,11 @@ """ Public method to get a reference to the requested menu. - @param name name of the menu (string) - @return reference to the menu (QMenu) or None, if no + @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] @@ -447,29 +434,30 @@ """ Public method to get the names of all menus. - @return menu names (list of string) + @return menu names + @rtype list of str """ return list(self.__menus.keys()) - def __handleTearOffMenu(self, pip): + def __handleTearOffMenu(self, venvName): """ - Private slot to handle a change of the pip executable. + Private slot to handle a change of the selected virtual environment. - @param pip path of the pip executable + @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(pip) and not enabled) or - (not bool(pip) and enabled)): + 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, cmd=""): + def runProcess(self, args, interpreter): """ Public method to execute the current pip with the given arguments. @@ -478,18 +466,16 @@ @param args list of command line arguments @type list of str - @param cmd pip executable to be used + @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) """ - if not cmd: - cmd = self.__plugin.getPreferences("CurrentPipExecutable") ioEncoding = Preferences.getSystem("IOEncoding") process = QProcess() - process.start(cmd, args) + process.start(interpreter, args) procStarted = process.waitForStarted() if procStarted: finished = process.waitForFinished(30000) @@ -499,22 +485,25 @@ 'replace') return True, output else: - return False, self.tr("pip exited with an error ({0}).")\ - .format(process.exitCode()) + 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("pip did not finish within 30 seconds.") + return False, self.tr("python did not finish within" + " 30 seconds.") - return False, self.tr("pip could not be started.") + 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 (string) + @return path of the user configuration file + @rtype str """ # Unix: ~/.config/pip/pip.conf # OS X: ~/Library/Application Support/pip/pip.conf @@ -540,7 +529,8 @@ """ Private method to get the name of the virtualenv configuration file. - @return path of the virtualenv configuration file (string) + @return path of the virtualenv configuration file + @rtype str """ # Unix, OS X: $VIRTUAL_ENV/pip.conf # Windows: %VIRTUAL_ENV%\pip.ini @@ -550,48 +540,86 @@ else: pip = "pip.conf" try: - virtualenv = os.environ["VIRTUAL_ENV"] + venvDirectory = os.environ["VIRTUAL_ENV"] except KeyError: - # determine from pip executable file - virtualenv = os.path.dirname(os.path.dirname( - self.__plugin.getPreferences("CurrentPipExecutable"))) + venvName = self.__plugin.getPreferences("CurrentEnvironment") + 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("<default>") + + def getVirtualenvInterpreter(self, venvName): + """ + Public method to get the interpreter for a virtual environment. - return os.path.join(virtualenv, pip) + @param venvName logical name for the virtual environment + @type str + @return interpreter path + @rtype str + """ + if venvName == self.getDefaultEnvironmentString(): + 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 __selectPipExecutable(self): + def __selectPipVirtualenv(self): """ - Private method to select the pip executable to be used. + Private method to select the virtual environment to be used. """ - pipExecutables = sorted(self.__plugin.getPreferences("PipExecutables")) - if pipExecutables: - currentExecutable = self.__plugin.getPreferences( - "CurrentPipExecutable") + environments = self.getVirtualenvNames() + if environments: + currentEnvironment = self.__plugin.getPreferences( + "CurrentEnvironment") try: - index = pipExecutables.index(currentExecutable) + index = environments.index(currentEnvironment) except ValueError: index = 0 - executable, ok = QInputDialog.getItem( + environment, ok = QInputDialog.getItem( None, - self.tr("pip Executable"), - self.tr("Select pip Executable to be used:"), - pipExecutables, index, False) + self.tr("Virtual Environment for pip"), + self.tr("Select the virtual environment to be used:"), + environments, index, False) - if ok and executable: - self.__plugin.setPreferences("CurrentPipExecutable", - executable) + if ok and environment: + self.__plugin.setPreferences("CurrentEnvironment", + environment) else: - res = E5MessageBox.yesNo( + E5MessageBox.warning( None, - self.tr("pip Executable"), - self.tr("""No pip executables have been configured yet.""" - """ Shall this be done now?"""), - yesDefault=True) - if res: - e5App().getObject("UserInterface").showPreferences("pipPage") + 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): """ @@ -599,7 +627,8 @@ """ from .PipListDialog import PipListDialog self.__listDialog = PipListDialog( - self, "list", self.__plugin, self.tr("Installed Packages")) + self, "list", self.__plugin.getPreferences("PipSearchIndex"), + self.tr("Installed Packages")) self.__listDialog.show() self.__listDialog.start() @@ -609,7 +638,8 @@ """ from .PipListDialog import PipListDialog self.__listUptodateDialog = PipListDialog( - self, "uptodate", self.__plugin, self.tr("Up-to-date Packages")) + self, "uptodate", self.__plugin.getPreferences("PipSearchIndex"), + self.tr("Up-to-date Packages")) self.__listUptodateDialog.show() self.__listUptodateDialog.start() @@ -619,7 +649,8 @@ """ from .PipListDialog import PipListDialog self.__listOutdatedDialog = PipListDialog( - self, "outdated", self.__plugin, self.tr("Outdated Packages")) + self, "outdated", self.__plugin.getPreferences("PipSearchIndex"), + self.tr("Outdated Packages")) self.__listOutdatedDialog.show() self.__listOutdatedDialog.start() @@ -640,7 +671,8 @@ Private method to edit a configuration. @param virtualenv flag indicating to edit the current virtualenv - configuration file (boolean) + configuration file + @type bool """ from QScintilla.MiniEditor import MiniEditor if virtualenv: @@ -652,7 +684,7 @@ E5MessageBox.critical( None, self.tr("Edit Configuration"), - self.tr("""No valid configuartion path determined.""" + self.tr("""No valid configuration path determined.""" """ Is a virtual environment selected? Aborting""")) return @@ -663,7 +695,7 @@ E5MessageBox.critical( None, self.tr("Edit Configuration"), - self.tr("""No valid configuartion path determined.""" + self.tr("""No valid configuration path determined.""" """ Is a virtual environment selected? Aborting""")) return @@ -696,50 +728,43 @@ directory @type bool """ - python = E5FileDialog.getOpenFileName( - None, - self.tr("Select Python Executable")) - if python: - python = QDir.toNativeSeparators(python) - dia = PipDialog(self.tr('Install PIP')) - if userSite: - commands = [(python, ["-m", "ensurepip", "--user"])] - else: - commands = [(python, ["-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((python, args[:])) + 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 - res = dia.startProcesses(commands) - if res: - dia.exec_() - pip = E5FileDialog.getOpenFileName( - None, - self.tr("Select PIP Executable"), - os.path.dirname(python)) - if pip: - pip = QDir.toNativeSeparators(pip) - pipExecutables = \ - self.__plugin.getPreferences("PipExecutables") - if pip not in pipExecutables: - pipExecutables.append(pip) - self.__plugin.setPreferences( - "PipExecutables", pipExecutables) + 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, pip="", userSite=False): + def upgradePip(self, venvName="", userSite=False): """ Public method to upgrade pip itself. - @param pip pip command to be used + @param venvName name of the virtual environment to be used @type str @param userSite flag indicating an install to the user install directory @@ -750,27 +775,17 @@ # Upgrading pip needs to be treated specially because # it must be done using the python executable - if not pip: + if not venvName: from .PipSelectionDialog import PipSelectionDialog - dlg = PipSelectionDialog(self.__plugin) + dlg = PipSelectionDialog(self) if dlg.exec_() != QDialog.Accepted: return - pip, userSite = dlg.getData() - - if not pip: - pip = self.__plugin.getPreferences("CurrentPipExecutable") + venvName, userSite = dlg.getData() - python = self.__getPython(pip) - if not python: - python = E5FileDialog.getOpenFileName( - None, - self.tr("Select Python Executable"), - os.path.dirname(pip)) - if python: - python = QDir.toNativeSeparators(python) - else: - return False + interpreter = self.getVirtualenvInterpreter(venvName) + if not interpreter: + return if self.__plugin.getPreferences("PipSearchIndex"): indexUrl = \ @@ -784,7 +799,7 @@ args.append("pip") dia = PipDialog(self.tr('Upgrade PIP')) - res = dia.startProcess(python, args) + res = dia.startProcess(interpreter, args) if res: dia.exec_() return res @@ -798,27 +813,16 @@ @rtype bool """ from .PipSelectionDialog import PipSelectionDialog - dlg = PipSelectionDialog(self.__plugin) + dlg = PipSelectionDialog(self) if dlg.exec_() != QDialog.Accepted: return False - pip, userSite = dlg.getData() - - if not pip: - pip = self.__plugin.getPreferences("CurrentPipExecutable") + venvName, userSite = dlg.getData() + interpreter = self.getVirtualenvInterpreter(venvName) + if not interpreter: + return - python = self.__getPython(pip) - if not python: - python = E5FileDialog.getOpenFileName( - None, - self.tr("Select Python Executable"), - os.path.dirname(pip)) - if python: - python = QDir.toNativeSeparators(python) - else: - return False - - # pip install --ignore-installed pip + # python -m pip install --ignore-installed pip if self.__plugin.getPreferences("PipSearchIndex"): indexUrl = \ self.__plugin.getPreferences("PipSearchIndex") + "/simple" @@ -831,55 +835,10 @@ args.append("pip") dia = PipDialog(self.tr('Repair PIP')) - res = dia.startProcess(python, args) + res = dia.startProcess(interpreter, args) if res: dia.exec_() - def __getPython(self, cmd): - """ - Private method to derive the path to the python executable given the - path to the pip executable. - - @param cmd path of the pip executable - @type str - @return path of the python executable - @rtype str - """ - path, prog = os.path.split(cmd) - paths = (path, os.path.split(path)[0]) # to try the parent directory - if Globals.isWindowsPlatform(): - subPatterns = ((r"\d\.\d", ""), - (r"\d\.", ".")) - for pyname in ("python", "pypy"): - python = prog.replace("pip", pyname) - for pattern, repl in subPatterns: - if re.search(pattern, python): - python = re.sub(pattern, repl, python) - break - for path in paths: - pypath = os.path.join(path, python) - if os.path.exists(pypath): - return pypath - else: - subPatterns = ((r"\.\d$", ""), - (r"\d\.\d$", ""), - (r"\d$", "")) - for pyname in ("python", "pypy"): - python = prog.replace("pip", pyname) - for path in paths: - pypath = os.path.join(path, python) - if os.path.exists(pypath): - return pypath - - for pattern, repl in subPatterns: - if re.search(pattern, cmd): - newpy = re.sub(pattern, repl, python) - pypath = os.path.join(path, newpy) - if os.path.exists(pypath): - return pypath - - return "" - def __checkUpgradePyQt(self, packages): """ Private method to check, if an upgrade of PyQt packages is attempted. @@ -906,13 +865,13 @@ return abort - def upgradePackages(self, packages, cmd="", userSite=False): + 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 cmd pip command to be used + @param venvName name of the virtual environment to be used @type str @param userSite flag indicating an install to the user install directory @@ -923,19 +882,24 @@ if self.__checkUpgradePyQt(packages): return False - if not cmd: - cmd = self.__plugin.getPreferences("CurrentPipExecutable") + 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 = ["install", "--index-url", indexUrl, "--upgrade"] + args = ["-m", "pip", "install", "--index-url", indexUrl, + "--upgrade"] else: - args = ["install", "--upgrade"] + args = ["-m", "pip", "install", "--upgrade"] if userSite: args.append("--user") args += packages dia = PipDialog(self.tr('Upgrade Packages')) - res = dia.startProcess(cmd, args) + res = dia.startProcess(interpreter, args) if res: dia.exec_() return res @@ -945,38 +909,42 @@ Private slot to upgrade packages to be given by the user. """ from .PipPackagesInputDialog import PipPackagesInputDialog - dlg = PipPackagesInputDialog( - self.__plugin, self.tr("Upgrade Packages")) + dlg = PipPackagesInputDialog(self, self.tr("Upgrade Packages")) if dlg.exec_() == QDialog.Accepted: - command, packages, user = dlg.getData() + venvName, packages, user = dlg.getData() if packages: - self.upgradePackages(packages, cmd=command, userSite=user) + self.upgradePackages(packages, venvName=venvName, + userSite=user) - def installPackages(self, packages, cmd="", userSite=False): + 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 cmd pip command to be used + @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 cmd: - cmd = self.__plugin.getPreferences("CurrentPipExecutable") + 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 = ["install", "--index-url", indexUrl] + args = ["-m", "pip", "install", "--index-url", indexUrl] else: - args = ["install"] + args = ["-m", "pip", "install"] if userSite: args.append("--user") args += packages dia = PipDialog(self.tr('Install Packages')) - res = dia.startProcess(cmd, args) + res = dia.startProcess(interpreter, args) if res: dia.exec_() @@ -988,55 +956,60 @@ dlg = PipPackagesInputDialog( self.__plugin, self.tr("Install Packages")) if dlg.exec_() == QDialog.Accepted: - command, packages, user = dlg.getData() + venvName, packages, user = dlg.getData() if packages: - self.installPackages(packages, cmd=command, userSite=user) + 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.__plugin, "package") + dlg = PipFileSelectionDialog(self, "package") if dlg.exec_() == QDialog.Accepted: - command, package, user = dlg.getData() + venvName, package, user = dlg.getData() if package and os.path.exists(package): - self.installPackages([package], cmd=command, userSite=user) + 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.__plugin, "requirements") + dlg = PipFileSelectionDialog(self, "requirements") if dlg.exec_() == QDialog.Accepted: - command, requirements, user = dlg.getData() + venvName, requirements, user = dlg.getData() if requirements and os.path.exists(requirements): - if not command: - command = self.__plugin.getPreferences( - "CurrentPipExecutable") + interpreter = self.getVirtualenvInterpreter(venvName) + if not interpreter: + return if self.__plugin.getPreferences("PipSearchIndex"): indexUrl = \ self.__plugin.getPreferences("PipSearchIndex") + \ "/simple" - args = ["install", "--index-url", indexUrl] + args = ["-m", "pip", "install", "--index-url", indexUrl] else: - args = ["install"] + args = ["-m", "pip", "install"] if user: args.append("--user") args += ["--requirement", requirements] dia = PipDialog(self.tr('Install Packages from Requirements')) - res = dia.startProcess(command, args) + res = dia.startProcess(interpreter, args) if res: dia.exec_() - def uninstallPackages(self, packages, cmd=""): + def uninstallPackages(self, packages, venvName=""): """ Public method to uninstall the given list of packages. - @param packages list of packages to uninstall (list of string) - @param cmd pip command to be used (string) - @return flag indicating a successful execution (boolean) + @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: @@ -1049,11 +1022,15 @@ "Do you really want to uninstall these packages?"), packages) if dlg.exec_() == QDialog.Accepted: - if not cmd: - cmd = self.__plugin.getPreferences("CurrentPipExecutable") - args = ["uninstall", "--yes"] + packages + 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(cmd, args) + res = dia.startProcess(interpreter, args) if res: dia.exec_() return res @@ -1064,21 +1041,21 @@ """ from .PipPackagesInputDialog import PipPackagesInputDialog dlg = PipPackagesInputDialog( - self.__plugin, self.tr("Uninstall Packages"), install=False) + self, self.tr("Uninstall Packages"), install=False) if dlg.exec_() == QDialog.Accepted: - command, packages, _user = dlg.getData() + venvName, packages, _user = dlg.getData() if packages: - self.uninstallPackages(packages, cmd=command) + 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.__plugin, "requirements", + dlg = PipFileSelectionDialog(self, "requirements", install=False) if dlg.exec_() == QDialog.Accepted: - command, requirements, _user = dlg.getData() + venvName, requirements, _user = dlg.getData() if requirements and os.path.exists(requirements): try: f = open(requirements, "r") @@ -1096,13 +1073,17 @@ "Do you really want to uninstall these packages?"), reqs) if dlg.exec_() == QDialog.Accepted: - if not command: - command = self.__plugin.getPreferences( - "CurrentPipExecutable") - args = ["uninstall", "--requirement", requirements] + 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(command, args) + res = dia.startProcess(interpreter, args) if res: dia.exec_() @@ -1111,7 +1092,7 @@ Private slot to generate the contents for a requirements file. """ from .PipFreezeDialog import PipFreezeDialog - self.__freezeDialog = PipFreezeDialog(self, self.__plugin) + self.__freezeDialog = PipFreezeDialog(self) self.__freezeDialog.show() self.__freezeDialog.start() @@ -1120,7 +1101,13 @@ Private slot to search the Python Package Index. """ from .PipSearchDialog import PipSearchDialog - self.__searchDialog = PipSearchDialog(self, self.__plugin) + + 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):