Fri, 18 May 2018 19:04:15 +0200
pip Interface: added an action to install a locally available package/wheel
--- a/Plugins/UiExtensionPlugins/PipInterface/Pip.py Fri May 18 18:31:14 2018 +0200 +++ b/Plugins/UiExtensionPlugins/PipInterface/Pip.py Fri May 18 19:04:15 2018 +0200 @@ -127,7 +127,6 @@ ## Actions for installing packages ############################################## - # TODO: add action to install a downloaded wheel via pip self.installPackagesAct = E5Action( self.tr('Install Packages'), self.tr('&Install Packages'), @@ -142,6 +141,21 @@ 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'), @@ -356,6 +370,7 @@ menu.addSeparator() menu.addAction(self.installPipAct) menu.addAction(self.installPackagesAct) + menu.addAction(self.installLocalPackageAct) menu.addAction(self.installRequirementsAct) menu.addSeparator() menu.addAction(self.upgradePipAct) @@ -932,13 +947,23 @@ if packages: self.installPackages(packages, cmd=command) + def __installLocalPackage(self): + """ + Private slot to install a package available on local storage. + """ + from .PipFileSelectionDialog import PipFileSelectionDialog + dlg = PipFileSelectionDialog(self.__plugin, "package") + if dlg.exec_() == QDialog.Accepted: + command, package = dlg.getData() + if package and os.path.exists(package): + self.installPackages([package], cmd=command) + def __installRequirements(self): """ Private slot to install packages as given in a requirements file. """ - from .PipRequirementsSelectionDialog import \ - PipRequirementsSelectionDialog - dlg = PipRequirementsSelectionDialog(self.__plugin) + from .PipFileSelectionDialog import PipFileSelectionDialog + dlg = PipFileSelectionDialog(self.__plugin, "requirements") if dlg.exec_() == QDialog.Accepted: command, requirements = dlg.getData() if requirements and os.path.exists(requirements): @@ -1002,9 +1027,8 @@ """ Private slot to uninstall packages as given in a requirements file. """ - from .PipRequirementsSelectionDialog import \ - PipRequirementsSelectionDialog - dlg = PipRequirementsSelectionDialog(self.__plugin) + from .PipFileSelectionDialog import PipFileSelectionDialog + dlg = PipFileSelectionDialog(self.__plugin, "requirements") if dlg.exec_() == QDialog.Accepted: command, requirements = dlg.getData() if requirements and os.path.exists(requirements):
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UiExtensionPlugins/PipInterface/PipFileSelectionDialog.py Fri May 18 19:04:15 2018 +0200 @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2015 - 2018 Detlev Offenbach <detlev@die-offenbachs.de> +# + + +""" +Module implementing a dialog to enter a file to be processed. +""" + +from __future__ import unicode_literals + +import os + +from PyQt5.QtCore import pyqtSlot +from PyQt5.QtWidgets import QDialog, QDialogButtonBox + +from E5Gui.E5PathPicker import E5PathPickerModes + +from .Ui_PipFileSelectionDialog import Ui_PipFileSelectionDialog + +import Utilities + + +class PipFileSelectionDialog(QDialog, Ui_PipFileSelectionDialog): + """ + Class implementing a dialog to enter a file to be processed. + """ + def __init__(self, plugin, mode, parent=None): + """ + Constructor + + @param plugin reference to the plugin object + @type PipInterfacePlugin + @param mode mode of the dialog + @type str + @param parent reference to the parent widget + @type QWidget + """ + super(PipFileSelectionDialog, self).__init__(parent) + self.setupUi(self) + + if mode == "requirements": + self.fileLabel.setText(self.tr("Enter requirements file:")) + self.filePicker.setMode(E5PathPickerModes.OpenFileMode) + self.filePicker.setToolTip(self.tr( + "Press to select the requirements file through a file" + " selection dialog.")) + self.filePicker.setFilters( + self.tr("Text Files (*.txt);;All Files (*)")) + elif mode == "package": + self.fileLabel.setText(self.tr("Enter package file:")) + self.filePicker.setMode(E5PathPickerModes.OpenFileMode) + self.filePicker.setToolTip(self.tr( + "Press to select the package file through a file" + " selection dialog.")) + self.filePicker.setFilters( + self.tr("Python Wheel (*.whl);;" + "Archive Files (*.tar.gz *.zip);;" + "All Files (*)")) + else: + self.fileLabel.setText(self.tr("Enter file:")) + self.filePicker.setMode(E5PathPickerModes.OpenFileMode) + self.filePicker.setToolTip(self.tr( + "Press to select a file through a file selection dialog.")) + self.filePicker.setFilters(self.tr("All Files (*)")) + self.filePicker.setDefaultDirectory(os.path.expanduser("~")) + + self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) + + 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()) + + @pyqtSlot(str) + def on_filePicker_textChanged(self, txt): + """ + Private slot to handle entering the name of a file. + + @param txt name of the file + @type str + """ + self.buttonBox.button(QDialogButtonBox.Ok).setEnabled( + bool(txt) and + os.path.exists(Utilities.toNativeSeparators(txt)) + ) + + def getData(self): + """ + 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) + """ + command = self.pipComboBox.currentText() + if command == self.__default: + command = "" + + return command, self.filePicker.text()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UiExtensionPlugins/PipInterface/PipFileSelectionDialog.ui Fri May 18 19:04:15 2018 +0200 @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PipFileSelectionDialog</class> + <widget class="QDialog" name="PipFileSelectionDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>121</height> + </rect> + </property> + <property name="windowTitle"> + <string>Select File</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="QLabel" name="fileLabel"> + <property name="text"> + <string>Enter file name:</string> + </property> + </widget> + </item> + <item> + <widget class="E5PathPicker" name="filePicker" native="true"> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </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> + <customwidgets> + <customwidget> + <class>E5PathPicker</class> + <extends>QWidget</extends> + <header>E5Gui/E5PathPicker.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>PipFileSelectionDialog</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>PipFileSelectionDialog</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/Plugins/UiExtensionPlugins/PipInterface/PipRequirementsSelectionDialog.py Fri May 18 18:31:14 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2015 - 2018 Detlev Offenbach <detlev@die-offenbachs.de> -# - - -""" -Module implementing a dialog to enter a requirements file. -""" - -from __future__ import unicode_literals - -import os - -from PyQt5.QtCore import pyqtSlot -from PyQt5.QtWidgets import QDialog, QDialogButtonBox - -from E5Gui import E5FileDialog - -from .Ui_PipRequirementsSelectionDialog import \ - Ui_PipRequirementsSelectionDialog - -import Utilities -import UI.PixmapCache - - -class PipRequirementsSelectionDialog(QDialog, - Ui_PipRequirementsSelectionDialog): - """ - Class implementing a dialog to enter a requirements file. - """ - def __init__(self, plugin, parent=None): - """ - Constructor - - @param plugin reference to the plugin object (ToolPipPlugin) - @param parent reference to the parent widget (QWidget) - """ - super(PipRequirementsSelectionDialog, self).__init__(parent) - self.setupUi(self) - - self.fileButton.setIcon(UI.PixmapCache.getIcon("open.png")) - - self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) - - 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()) - - @pyqtSlot() - def on_fileButton_clicked(self): - """ - Private slot to enter the requirements file via a file selection - dialog. - """ - fileName = E5FileDialog.getOpenFileName( - self, - self.tr("Select the requirements file"), - self.requirementsEdit.text() or os.path.expanduser("~"), - self.tr("Text Files (*.txt);;All Files (*)") - ) - if fileName: - self.requirementsEdit.setText( - Utilities.toNativeSeparators(fileName)) - - @pyqtSlot(str) - def on_requirementsEdit_textChanged(self, txt): - """ - Private slot handling entering the name of a requirements file. - - @param txt name of the requirements file (string) - """ - self.buttonBox.button(QDialogButtonBox.Ok).setEnabled( - bool(txt) and - os.path.exists(Utilities.toNativeSeparators(txt)) - ) - - def getData(self): - """ - Public method to get the entered data. - - @return tuple with the pip command (string) and the name of the - requirements file (string) - """ - command = self.pipComboBox.currentText() - if command == self.__default: - command = "" - - return command, self.requirementsEdit.text()
--- a/Plugins/UiExtensionPlugins/PipInterface/PipRequirementsSelectionDialog.ui Fri May 18 18:31:14 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>PipRequirementsSelectionDialog</class> - <widget class="QDialog" name="PipRequirementsSelectionDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>600</width> - <height>143</height> - </rect> - </property> - <property name="windowTitle"> - <string>Select Requirements</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="QLabel" name="label_2"> - <property name="text"> - <string>Enter requirements file:</string> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QLineEdit" name="requirementsEdit"/> - </item> - <item> - <widget class="QToolButton" name="fileButton"> - <property name="toolTip"> - <string>Select the requirements file through a file selection dialog</string> - </property> - <property name="text"> - <string notr="true"/> - </property> - </widget> - </item> - </layout> - </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>PipRequirementsSelectionDialog</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>PipRequirementsSelectionDialog</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 Fri May 18 18:31:14 2018 +0200 +++ b/changelog Fri May 18 19:04:15 2018 +0200 @@ -5,6 +5,8 @@ - Editor -- added a configuration option (Editor->Style page) to show the marker map on the left or right of the editor +- pip Interface + -- added an action to install a locally available package/wheel - Web Browser (NG) -- improved the sending of the "Referer" header like it is done by Firefox
--- a/eric6.e4p Fri May 18 18:31:14 2018 +0200 +++ b/eric6.e4p Fri May 18 19:04:15 2018 +0200 @@ -534,11 +534,11 @@ <Source>Plugins/UiExtensionPlugins/PipInterface/ConfigurationPage/__init__.py</Source> <Source>Plugins/UiExtensionPlugins/PipInterface/Pip.py</Source> <Source>Plugins/UiExtensionPlugins/PipInterface/PipDialog.py</Source> + <Source>Plugins/UiExtensionPlugins/PipInterface/PipFileSelectionDialog.py</Source> <Source>Plugins/UiExtensionPlugins/PipInterface/PipFreezeDialog.py</Source> <Source>Plugins/UiExtensionPlugins/PipInterface/PipListDialog.py</Source> <Source>Plugins/UiExtensionPlugins/PipInterface/PipPackageDetailsDialog.py</Source> <Source>Plugins/UiExtensionPlugins/PipInterface/PipPackagesInputDialog.py</Source> - <Source>Plugins/UiExtensionPlugins/PipInterface/PipRequirementsSelectionDialog.py</Source> <Source>Plugins/UiExtensionPlugins/PipInterface/PipSearchDialog.py</Source> <Source>Plugins/UiExtensionPlugins/PipInterface/__init__.py</Source> <Source>Plugins/UiExtensionPlugins/Translator/ConfigurationPage/TranslatorPage.py</Source> @@ -1798,11 +1798,11 @@ <Form>Plugins/DocumentationPlugins/Ericdoc/EricdocExecDialog.ui</Form> <Form>Plugins/UiExtensionPlugins/PipInterface/ConfigurationPage/PipPage.ui</Form> <Form>Plugins/UiExtensionPlugins/PipInterface/PipDialog.ui</Form> + <Form>Plugins/UiExtensionPlugins/PipInterface/PipFileSelectionDialog.ui</Form> <Form>Plugins/UiExtensionPlugins/PipInterface/PipFreezeDialog.ui</Form> <Form>Plugins/UiExtensionPlugins/PipInterface/PipListDialog.ui</Form> <Form>Plugins/UiExtensionPlugins/PipInterface/PipPackageDetailsDialog.ui</Form> <Form>Plugins/UiExtensionPlugins/PipInterface/PipPackagesInputDialog.ui</Form> - <Form>Plugins/UiExtensionPlugins/PipInterface/PipRequirementsSelectionDialog.ui</Form> <Form>Plugins/UiExtensionPlugins/PipInterface/PipSearchDialog.ui</Form> <Form>Plugins/UiExtensionPlugins/Translator/ConfigurationPage/TranslatorPage.ui</Form> <Form>Plugins/UiExtensionPlugins/Translator/TranslatorWidget.ui</Form> @@ -2203,14 +2203,14 @@ </Resources> <Others> <Other>.hgignore</Other> - <Other>APIs/Python/zope-2.10.7.api</Other> - <Other>APIs/Python/zope-2.11.2.api</Other> - <Other>APIs/Python/zope-3.3.1.api</Other> <Other>APIs/Python3/PyQt4.bas</Other> <Other>APIs/Python3/PyQt5.bas</Other> <Other>APIs/Python3/QScintilla2.bas</Other> <Other>APIs/Python3/eric6.api</Other> <Other>APIs/Python3/eric6.bas</Other> + <Other>APIs/Python/zope-2.10.7.api</Other> + <Other>APIs/Python/zope-2.11.2.api</Other> + <Other>APIs/Python/zope-3.3.1.api</Other> <Other>APIs/QSS/qss.api</Other> <Other>APIs/Ruby/Ruby-1.8.7.api</Other> <Other>APIs/Ruby/Ruby-1.8.7.bas</Other>