Wed, 06 Jun 2018 20:05:39 +0200
pip Interface: started to add support for the '--user' option.
--- a/Plugins/UiExtensionPlugins/PipInterface/Pip.py Tue Jun 05 19:14:10 2018 +0200 +++ b/Plugins/UiExtensionPlugins/PipInterface/Pip.py Wed Jun 06 20:05:39 2018 +0200 @@ -669,6 +669,7 @@ self.__editor = MiniEditor(cfgFile, "Properties") self.__editor.show() + # TODO: add support for --user def __installPip(self): """ Private slot to install pip. @@ -708,12 +709,15 @@ "PipExecutables", pipExecutables) @pyqtSlot() - def upgradePip(self, pip=""): + def upgradePip(self, pip="", userSite=False): """ Public method to upgrade pip itself. @param pip pip command 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 """ @@ -721,19 +725,14 @@ # it must be done using the python executable if not pip: - default = self.tr("<Default>") - pipExecutables = sorted( - self.__plugin.getPreferences("PipExecutables")) - pip, ok = QInputDialog.getItem( - None, - self.tr("Upgrade pip"), - self.tr("Select pip Executable:"), - [default] + pipExecutables, - 0, False) - if not ok or not pip: - return False + from .PipSelectionDialog import PipSelectionDialog + dlg = PipSelectionDialog(self.__plugin) + if dlg.exec_() != QDialog.Accepted: + return - if pip == default: + pip, userSite = dlg.getData() + + if not pip: pip = self.__plugin.getPreferences("CurrentPipExecutable") python = self.__getPython(pip) @@ -751,15 +750,20 @@ indexUrl = \ self.__plugin.getPreferences("PipSearchIndex") + "/simple" args = ["-m", "pip", "install", "--index-url", indexUrl, - "--upgrade", "pip"] + "--upgrade"] else: - args = ["-m", "pip", "install", "--upgrade", "pip"] + args = ["-m", "pip", "install", "--upgrade"] + if userSite: + args.append("--user") + args.append("pip") + dia = PipDialog(self.tr('Upgrade PIP')) res = dia.startProcess(python, args) if res: dia.exec_() return res + # TODO: add support for --user @pyqtSlot() def __repairPip(self): """ @@ -878,14 +882,19 @@ return abort - # TODO: add parameter userSite=False; arg: --user - def upgradePackages(self, packages, cmd=""): + def upgradePackages(self, packages, cmd="", userSite=False): """ Public method to upgrade the given list of packages. - @param packages list of packages to upgrade (list of string) - @param cmd pip command to be used (string) - @return flag indicating a successful execution (boolean) + @param packages list of packages to upgrade + @type list of str + @param cmd pip command 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 @@ -898,6 +907,8 @@ args = ["install", "--index-url", indexUrl, "--upgrade"] else: args = ["install", "--upgrade"] + if userSite: + args.append("--user") args += packages dia = PipDialog(self.tr('Upgrade Packages')) res = dia.startProcess(cmd, args) @@ -913,17 +924,21 @@ dlg = PipPackagesInputDialog( self.__plugin, self.tr("Upgrade Packages")) if dlg.exec_() == QDialog.Accepted: - command, packages = dlg.getData() + command, packages, user = dlg.getData() if packages: - self.upgradePackages(packages, cmd=command) + self.upgradePackages(packages, cmd=command, userSite=user) - # TODO: add parameter userSite=False; arg: --user - def installPackages(self, packages, cmd=""): + def installPackages(self, packages, cmd="", userSite=False): """ Public method to install the given list of packages. - @param packages list of packages to install (list of string) - @param cmd pip command to be used (string) + @param packages list of packages to install + @type list of str + @param cmd pip command 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") @@ -933,6 +948,8 @@ args = ["install", "--index-url", indexUrl] else: args = ["install"] + if userSite: + args.append("--user") args += packages dia = PipDialog(self.tr('Install Packages')) res = dia.startProcess(cmd, args) @@ -947,9 +964,9 @@ dlg = PipPackagesInputDialog( self.__plugin, self.tr("Install Packages")) if dlg.exec_() == QDialog.Accepted: - command, packages = dlg.getData() + command, packages, user = dlg.getData() if packages: - self.installPackages(packages, cmd=command) + self.installPackages(packages, cmd=command, userSite=user) def __installLocalPackage(self): """ @@ -958,9 +975,9 @@ from .PipFileSelectionDialog import PipFileSelectionDialog dlg = PipFileSelectionDialog(self.__plugin, "package") if dlg.exec_() == QDialog.Accepted: - command, package = dlg.getData() + command, package, user = dlg.getData() if package and os.path.exists(package): - self.installPackages([package], cmd=command) + self.installPackages([package], cmd=command, userSite=user) def __installRequirements(self): """ @@ -969,7 +986,7 @@ from .PipFileSelectionDialog import PipFileSelectionDialog dlg = PipFileSelectionDialog(self.__plugin, "requirements") if dlg.exec_() == QDialog.Accepted: - command, requirements = dlg.getData() + command, requirements, user = dlg.getData() if requirements and os.path.exists(requirements): if not command: command = self.__plugin.getPreferences( @@ -981,6 +998,8 @@ args = ["install", "--index-url", indexUrl] else: args = ["install"] + if user: + args.append("--user") args += ["--requirement", requirements] dia = PipDialog(self.tr('Install Packages from Requirements')) res = dia.startProcess(command, args) @@ -1021,9 +1040,9 @@ """ from .PipPackagesInputDialog import PipPackagesInputDialog dlg = PipPackagesInputDialog( - self.__plugin, self.tr("Uninstall Packages")) + self.__plugin, self.tr("Uninstall Packages"), install=False) if dlg.exec_() == QDialog.Accepted: - command, packages = dlg.getData() + command, packages, _user = dlg.getData() if packages: self.uninstallPackages(packages, cmd=command) @@ -1032,9 +1051,10 @@ Private slot to uninstall packages as given in a requirements file. """ from .PipFileSelectionDialog import PipFileSelectionDialog - dlg = PipFileSelectionDialog(self.__plugin, "requirements") + dlg = PipFileSelectionDialog(self.__plugin, "requirements", + install=False) if dlg.exec_() == QDialog.Accepted: - command, requirements = dlg.getData() + command, requirements, _user = dlg.getData() if requirements and os.path.exists(requirements): try: f = open(requirements, "r")
--- a/Plugins/UiExtensionPlugins/PipInterface/PipFileSelectionDialog.py Tue Jun 05 19:14:10 2018 +0200 +++ b/Plugins/UiExtensionPlugins/PipInterface/PipFileSelectionDialog.py Wed Jun 06 20:05:39 2018 +0200 @@ -22,12 +22,11 @@ import Utilities -# TODO: add checkbox to select an installation into 'user site' class PipFileSelectionDialog(QDialog, Ui_PipFileSelectionDialog): """ Class implementing a dialog to enter a file to be processed. """ - def __init__(self, plugin, mode, parent=None): + def __init__(self, plugin, mode, install=True, parent=None): """ Constructor @@ -35,6 +34,8 @@ @type PipInterfacePlugin @param mode mode of the dialog @type str + @param install flag indicating an install action + @type bool @param parent reference to the parent widget @type QWidget """ @@ -74,6 +75,8 @@ self.pipComboBox.addItem(self.__default) self.pipComboBox.addItems(pipExecutables) + self.userCheckBox.setVisible(install) + msh = self.minimumSizeHint() self.resize(max(self.width(), msh.width()), msh.height()) @@ -94,12 +97,14 @@ """ Public method to get the entered data. - @return tuple with the pip command and the name of the - selected file - @rtype tuple of (str, str) + @return tuple with the pip command, the name of the + selected file and a flag indicating to install to the + user install directory + @rtype tuple of (str, str, bool) """ command = self.pipComboBox.currentText() if command == self.__default: command = "" - return command, self.filePicker.text() + return (command, self.filePicker.text(), + self.userCheckBox.isChecked())
--- a/Plugins/UiExtensionPlugins/PipInterface/PipFileSelectionDialog.ui Tue Jun 05 19:14:10 2018 +0200 +++ b/Plugins/UiExtensionPlugins/PipInterface/PipFileSelectionDialog.ui Wed Jun 06 20:05:39 2018 +0200 @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>600</width> - <height>121</height> + <height>144</height> </rect> </property> <property name="windowTitle"> @@ -46,6 +46,16 @@ </widget> </item> <item> + <widget class="QCheckBox" name="userCheckBox"> + <property name="toolTip"> + <string>Select to install to the Python user install directory</string> + </property> + <property name="text"> + <string>Install into User Directory</string> + </property> + </widget> + </item> + <item> <widget class="QDialogButtonBox" name="buttonBox"> <property name="orientation"> <enum>Qt::Horizontal</enum>
--- a/Plugins/UiExtensionPlugins/PipInterface/PipListDialog.py Tue Jun 05 19:14:10 2018 +0200 +++ b/Plugins/UiExtensionPlugins/PipInterface/PipListDialog.py Wed Jun 06 20:05:39 2018 +0200 @@ -26,7 +26,6 @@ import Preferences -# TODO: add support for --user (User Site only) class PipListDialog(QDialog, Ui_PipListDialog): """ Class implementing a dialog to list installed packages. @@ -271,6 +270,8 @@ args.append("--local") if self.notRequiredCheckBox.isChecked(): args.append("--not-required") + if self.userCheckBox.isChecked(): + args.append("--user") if self.__indexUrl: args.append("--index-url") @@ -350,7 +351,8 @@ """ Private slot handling the switching of the local mode. - @param checked state of the local check box (boolean) + @param checked state of the local check box + @type bool """ self.__refresh() @@ -359,7 +361,18 @@ """ Private slot handling the switching of the 'not required' mode. - @param checked state of the 'not required' check box (boolean) + @param checked state of the 'not required' check box + @type bool + """ + self.__refresh() + + @pyqtSlot(bool) + def on_userCheckBox_clicked(self, checked): + """ + Private slot handling the switching of the 'user-site' mode. + + @param checked state of the 'user-site' check box + @type bool """ self.__refresh() @@ -455,7 +468,6 @@ """ self.on_packageList_itemSelectionChanged() - # TODO: add support for --user def __upgradePackages(self): """ Private slot to upgrade the selected packages. @@ -470,7 +482,6 @@ else: self.__executeUpgradePackages(packages) - # TODO: add support for --user def __upgradeAllPackages(self): """ Private slot to upgrade all listed packages. @@ -486,7 +497,6 @@ else: self.__executeUpgradePackages(packages) - # TODO: add support for --user def __upgradePip(self): """ Private slot to upgrade pip itself. @@ -495,11 +505,11 @@ if pip == self.__default: pip = "" - res = self.__pip.upgradePip(pip=pip) + res = self.__pip.upgradePip( + pip=pip, userSite=self.userCheckBox.isChecked()) if res: self.__refresh() - # TODO: add support for --user def __executeUpgradePackages(self, packages): """ Private method to execute the pip upgrade command. @@ -511,7 +521,8 @@ if command == self.__default: command = "" - res = self.__pip.upgradePackages(packages, cmd=command) + res = self.__pip.upgradePackages( + packages, cmd=command, userSite=self.userCheckBox.isChecked()) if res: self.__refresh()
--- a/Plugins/UiExtensionPlugins/PipInterface/PipListDialog.ui Tue Jun 05 19:14:10 2018 +0200 +++ b/Plugins/UiExtensionPlugins/PipInterface/PipListDialog.ui Wed Jun 06 20:05:39 2018 +0200 @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>600</width> - <height>550</height> + <height>650</height> </rect> </property> <property name="windowTitle"> @@ -25,15 +25,15 @@ </widget> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> <widget class="QLabel" name="infoLabel"> <property name="text"> <string notr="true">TextLabel</string> </property> </widget> </item> - <item> + <item row="0" column="1"> <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> @@ -46,7 +46,7 @@ </property> </spacer> </item> - <item> + <item row="0" column="2"> <widget class="QCheckBox" name="localCheckBox"> <property name="toolTip"> <string>Select to show only locally-installed packages</string> @@ -59,7 +59,7 @@ </property> </widget> </item> - <item> + <item row="0" column="3"> <widget class="QCheckBox" name="notRequiredCheckBox"> <property name="toolTip"> <string>Select to list packages that are not dependencies of installed packages</string> @@ -69,6 +69,16 @@ </property> </widget> </item> + <item row="1" column="2"> + <widget class="QCheckBox" name="userCheckBox"> + <property name="toolTip"> + <string>Select to show only packages installed to the user-site</string> + </property> + <property name="text"> + <string>User-Site only</string> + </property> + </widget> + </item> </layout> </item> <item> @@ -215,6 +225,7 @@ <tabstop>pipComboBox</tabstop> <tabstop>localCheckBox</tabstop> <tabstop>notRequiredCheckBox</tabstop> + <tabstop>userCheckBox</tabstop> <tabstop>packageList</tabstop> <tabstop>verboseCheckBox</tabstop> <tabstop>installedFilesCheckBox</tabstop>
--- a/Plugins/UiExtensionPlugins/PipInterface/PipPackagesInputDialog.py Tue Jun 05 19:14:10 2018 +0200 +++ b/Plugins/UiExtensionPlugins/PipInterface/PipPackagesInputDialog.py Wed Jun 06 20:05:39 2018 +0200 @@ -15,18 +15,22 @@ from .Ui_PipPackagesInputDialog import Ui_PipPackagesInputDialog -# TODO: add checkbox to select an installation into 'user site' class PipPackagesInputDialog(QDialog, Ui_PipPackagesInputDialog): """ Class implementing a dialog to enter package specifications. """ - def __init__(self, plugin, title, parent=None): + def __init__(self, plugin, title, install=True, parent=None): """ Constructor - @param plugin reference to the plugin object (ToolPipPlugin) - @param title dialog title (string) - @param parent reference to the parent widget (QWidget) + @param plugin reference to the plugin object + @type ToolPipPlugin + @param title dialog title + @type str + @param install flag indicating an install action + @type bool + @param parent reference to the parent widget + @type QWidget """ super(PipPackagesInputDialog, self).__init__(parent) self.setupUi(self) @@ -40,6 +44,8 @@ self.pipComboBox.addItem(self.__default) self.pipComboBox.addItems(pipExecutables) + self.userCheckBox.setVisible(install) + msh = self.minimumSizeHint() self.resize(max(self.width(), msh.width()), msh.height()) @@ -56,12 +62,13 @@ """ Public method to get the entered data. - @return tuple with the pip command (string) and the list of - package specifications (list of string) + @return tuple with the pip command, the list of package specifications + and a flag indicating to install to the user install directory + @rtype tuple of (str, list of str, bool) """ command = self.pipComboBox.currentText() if command == self.__default: command = "" packages = [p.strip() for p in self.packagesEdit.text().split()] - return command, packages + return command, packages, self.userCheckBox.isChecked()
--- a/Plugins/UiExtensionPlugins/PipInterface/PipPackagesInputDialog.ui Tue Jun 05 19:14:10 2018 +0200 +++ b/Plugins/UiExtensionPlugins/PipInterface/PipPackagesInputDialog.ui Wed Jun 06 20:05:39 2018 +0200 @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>600</width> - <height>143</height> + <height>154</height> </rect> </property> <property name="windowTitle"> @@ -42,6 +42,16 @@ <widget class="QLineEdit" name="packagesEdit"/> </item> <item> + <widget class="QCheckBox" name="userCheckBox"> + <property name="toolTip"> + <string>Select to install to the Python user install directory</string> + </property> + <property name="text"> + <string>Install into User Directory</string> + </property> + </widget> + </item> + <item> <widget class="QDialogButtonBox" name="buttonBox"> <property name="orientation"> <enum>Qt::Horizontal</enum>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UiExtensionPlugins/PipInterface/PipSelectionDialog.py Wed Jun 06 20:05:39 2018 +0200 @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2018 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog to select the pip executable to be used. +""" + +from __future__ import unicode_literals + +from PyQt5.QtWidgets import QDialog + +from .Ui_PipSelectionDialog import Ui_PipSelectionDialog + + +class PipSelectionDialog(QDialog, Ui_PipSelectionDialog): + """ + Class implementing a dialog to select the pip executable to be used. + """ + def __init__(self, plugin, parent=None): + """ + Constructor + + @param plugin reference to the plugin object + @type ToolPipPlugin + @param parent reference to the parent widget + @type QWidget + """ + super(PipSelectionDialog, self).__init__(parent) + self.setupUi(self) + + self.__default = self.tr("<Default>") + pipExecutables = sorted(plugin.getPreferences("PipExecutables")) + self.pipComboBox.addItem(self.__default) + self.pipComboBox.addItems(pipExecutables) + + msh = self.minimumSizeHint() + self.resize(max(self.width(), msh.width()), msh.height()) + + def getData(self): + """ + Public method to get the entered data. + + @return tuple with the pip command and a flag indicating to install + to the user install directory + @rtype tuple of (str, bool) + """ + command = self.pipComboBox.currentText() + if command == self.__default: + command = "" + + return command, self.userCheckBox.isChecked()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UiExtensionPlugins/PipInterface/PipSelectionDialog.ui Wed Jun 06 20:05:39 2018 +0200 @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PipSelectionDialog</class> + <widget class="QDialog" name="PipSelectionDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>130</height> + </rect> + </property> + <property name="windowTitle"> + <string>Select pip</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Select the pip executable to be used:</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="pipComboBox"> + <property name="toolTip"> + <string>Select the pip command to use</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="userCheckBox"> + <property name="toolTip"> + <string>Select to install to the Python user install directory</string> + </property> + <property name="text"> + <string>Install into User Directory</string> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>PipSelectionDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>PipSelectionDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui>
--- a/changelog Tue Jun 05 19:14:10 2018 +0200 +++ b/changelog Wed Jun 06 20:05:39 2018 +0200 @@ -5,6 +5,8 @@ - Git Interface -- added capability to change the URL and/or user credentials for a remote repository +- pip Interface + -- added support for the '--user' option of install and list commands Version 18.06: - bug fixes
--- a/eric6.e4p Tue Jun 05 19:14:10 2018 +0200 +++ b/eric6.e4p Wed Jun 06 20:05:39 2018 +0200 @@ -1806,6 +1806,7 @@ <Form>Plugins/UiExtensionPlugins/PipInterface/PipPackageDetailsDialog.ui</Form> <Form>Plugins/UiExtensionPlugins/PipInterface/PipPackagesInputDialog.ui</Form> <Form>Plugins/UiExtensionPlugins/PipInterface/PipSearchDialog.ui</Form> + <Form>Plugins/UiExtensionPlugins/PipInterface/PipSelectionDialog.ui</Form> <Form>Plugins/UiExtensionPlugins/Translator/ConfigurationPage/TranslatorPage.ui</Form> <Form>Plugins/UiExtensionPlugins/Translator/TranslatorWidget.ui</Form> <Form>Plugins/UiExtensionPlugins/VirtualenvInterface/VirtualenvConfigurationDialog.ui</Form>