Fri, 22 Feb 2019 19:34:44 +0100
PipInterface: continued with the pip interface widget.
--- a/PipInterface/Pip.py Thu Feb 21 19:55:35 2019 +0100 +++ b/PipInterface/Pip.py Fri Feb 22 19:34:44 2019 +0100 @@ -17,19 +17,25 @@ import sys import json -from PyQt5.QtCore import pyqtSlot, QObject, QProcess -from PyQt5.QtWidgets import QMenu, QInputDialog, QDialog +from PyQt5.QtCore import pyqtSlot, QObject, QProcess, QUrl, QCoreApplication +from PyQt5.QtWidgets import QDialog +from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, \ + QNetworkReply from E5Gui import E5MessageBox -from E5Gui.E5Action import E5Action from E5Gui.E5Application import e5App +from E5Network.E5NetworkProxyFactory import proxyAuthenticationRequired +try: + from E5Network.E5SslErrorHandler import E5SslErrorHandler + SSL_AVAILABLE = True +except ImportError: + SSL_AVAILABLE = False + from .PipDialog import PipDialog import Preferences import Globals -## -##import UI.PixmapCache class Pip(QObject): @@ -48,413 +54,16 @@ @type QObject """ super(Pip, self).__init__(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() -## menu.setTearOffEnabled(True) -## menu.setIcon(UI.PixmapCache.getIcon("pypi.png")) -## -## 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(Preferences.getPip("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() + + # attributes for the network objects + self.__networkManager = QNetworkAccessManager(self) + self.__networkManager.proxyAuthenticationRequired.connect( + proxyAuthenticationRequired) + if SSL_AVAILABLE: + self.__sslErrorHandler = E5SslErrorHandler(self) + self.__networkManager.sslErrors.connect( + self.__sslErrorHandler.sslErrorsReply) + self.__replies = [] ########################################################################## ## Methods below implement some utility functions @@ -501,9 +110,9 @@ return False, self.tr("python could not be started.") - def __getUserConfig(self): + def getUserConfig(self): """ - Private method to get the name of the user configuration file. + Public method to get the name of the user configuration file. @return path of the user configuration file @rtype str @@ -528,33 +137,28 @@ return config - def __getVirtualenvConfig(self): + def getVirtualenvConfig(self, venvName): """ - Private method to get the name of the virtualenv configuration file. + Public method to get the name of the virtualenv configuration file. + @param venvName name of the environment to get config file path for + @type str @return path of the virtualenv configuration file @rtype str """ # Unix, OS X: $VIRTUAL_ENV/pip.conf # Windows: %VIRTUAL_ENV%\pip.ini - # TODO: modify to use venvName if Globals.isWindowsPlatform(): pip = "pip.ini" else: pip = "pip.conf" - try: - venvDirectory = os.environ["VIRTUAL_ENV"] - except KeyError: - venvName = Preferences.getPip("CurrentEnvironment") - if not venvName: - self.__selectPipVirtualenv() - venvName = Preferences.getPip("CurrentEnvironment") - venvManager = e5App().getObject("VirtualEnvManager") - if venvManager.isGlobalEnvironment(venvName): - venvDirectory = self.__getUserConfig() - else: - venvDirectory = venvManager.getVirtualenvDirectory(venvName) + + venvManager = e5App().getObject("VirtualEnvManager") + if venvManager.isGlobalEnvironment(venvName): + venvDirectory = self.__getUserConfig() + else: + venvDirectory = venvManager.getVirtualenvDirectory(venvName) if venvDirectory: config = os.path.join(venvDirectory, pip) @@ -563,15 +167,6 @@ return config -## 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. @@ -593,16 +188,12 @@ @return interpreter path @rtype str """ -## if venvName == self.getDefaultEnvironmentString(): -## venvName = Preferences.getPip("CurrentEnvironment") if venvName == self.getProjectEnvironmentString(): venvName = \ e5App().getObject("Project").getDebugProperty("VIRTUALENV") if not venvName: # fall back to interpreter used to run eric6 return sys.executable -## # fall back to standard if not defined -## venvName = Preferences.getPip("CurrentEnvironment") interpreter = \ e5App().getObject("VirtualEnvManager").getVirtualenvInterpreter( @@ -626,137 +217,6 @@ return sorted( e5App().getObject("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 = Preferences.getPip("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: -## Preferences.getPip("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", Preferences.getPip("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", Preferences.getPip("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", Preferences.getPip("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() -## if not cfgFile: -## return -## 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, venvName, userSite=False): """ Public method to install pip. @@ -791,50 +251,6 @@ 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 Preferences.getPip("PipSearchIndex"): -## indexUrl = Preferences.getPip("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, venvName): """ @@ -842,8 +258,6 @@ @param venvName name of the environment to install pip into @type str - @return flag indicating a successful execution - @rtype bool """ interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: @@ -873,14 +287,15 @@ @rtype bool """ pyqtPackages = [p for p in packages - if p.lower() in ["pyqt5", "qscintilla", "sip"]] + if p.lower() in ["pyqt5", "pyqt5-sip", "pyqtwebengine", + "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""" + """You are trying to upgrade PyQt packages. This might""" """ not work for the current instance of Python ({0}).""" """ Do you want to continue?""").format(sys.executable), icon=E5MessageBox.Critical) @@ -889,7 +304,7 @@ return abort - def upgradePackages(self, packages, venvName="", userSite=False): + def upgradePackages(self, packages, venvName, userSite=False): """ Public method to upgrade the given list of packages. @@ -907,10 +322,11 @@ return False if not venvName: - venvName = Preferences.getPip("CurrentEnvironment") + return False + interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: - return + return False if Preferences.getPip("PipSearchIndex"): indexUrl = Preferences.getPip("PipSearchIndex") + "/simple" @@ -927,19 +343,7 @@ 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): + def installPackages(self, packages, venvName, userSite=False): """ Public method to install the given list of packages. @@ -951,62 +355,40 @@ directory @type bool """ - if not venvName: - venvName = Preferences.getPip("CurrentEnvironment") - interpreter = self.getVirtualenvInterpreter(venvName) - if not interpreter: - return + if venvName: + interpreter = self.getVirtualenvInterpreter(venvName) + if not interpreter: + return + + if Preferences.getPip("PipSearchIndex"): + indexUrl = Preferences.getPip("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 installRequirements(self, venvName): + """ + Public method to install packages as given in a requirements file. - if Preferences.getPip("PipSearchIndex"): - indexUrl = Preferences.getPip("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. + @param venvName name of the virtual environment to be used + @type str """ from .PipFileSelectionDialog import PipFileSelectionDialog dlg = PipFileSelectionDialog(self, "requirements") if dlg.exec_() == QDialog.Accepted: - venvName, requirements, user = dlg.getData() + requirements, user = dlg.getData() if requirements and os.path.exists(requirements): interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: return + if Preferences.getPip("PipSearchIndex"): indexUrl = Preferences.getPip("PipSearchIndex") + \ "/simple" @@ -1021,7 +403,7 @@ if res: dia.exec_() - def uninstallPackages(self, packages, venvName=""): + def uninstallPackages(self, packages, venvName): """ Public method to uninstall the given list of packages. @@ -1033,7 +415,7 @@ @rtype bool """ res = False - if packages: + if packages and venvName: from UI.DeleteFilesConfirmationDialog import \ DeleteFilesConfirmationDialog dlg = DeleteFilesConfirmationDialog( @@ -1043,8 +425,6 @@ "Do you really want to uninstall these packages?"), packages) if dlg.exec_() == QDialog.Accepted: - if not venvName: - venvName = Preferences.getPip("CurrentEnvironment") interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: return @@ -1055,80 +435,48 @@ 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): + def uninstallRequirements(self, venvName): """ - Private slot to uninstall packages as given in a requirements file. + Public method to uninstall packages as given in a requirements file. + + @param venvName name of the virtual environment to be used + @type str """ - 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 = Preferences.getPip("CurrentEnvironment") - interpreter = self.getVirtualenvInterpreter(venvName) - if not interpreter: + if venvName: + from .PipFileSelectionDialog import PipFileSelectionDialog + dlg = PipFileSelectionDialog(self, "requirements", + install=False) + if dlg.exec_() == QDialog.Accepted: + 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 - args = ["-m", "pip", "uninstall", "--requirement", - requirements] - dia = PipDialog( - self.tr('Uninstall Packages from Requirements')) - res = dia.startProcess(interpreter, args) - if res: - dia.exec_() + + 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: + 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 Preferences.getPip("PipSearchIndex"): -## indexUrl = Preferences.getPip("PipSearchIndex") + "/pypi" -## else: -## indexUrl = DefaultIndexUrlXml -## -## self.__searchDialog = PipSearchDialog(self, indexUrl) -## self.__searchDialog.show() -## def getIndexUrl(self): """ Public method to get the index URL for PyPI. @@ -1271,9 +619,36 @@ )) return packages -## -## def __pipConfigure(self): -## """ -## Private slot to open the configuration page. -## """ -## e5App().getObject("UserInterface").showPreferences("pipPage") + + def getPackageDetails(self, name, version): + """ + Public method to get package details using the PyPI JSON interface. + + @param name package name + @type str + @param version package version + @type str + @return dictionary containing PyPI package data + @rtype dict + """ + result = {} + + if name and version: + url = "https://pypi.org/pypi/{0}/{1}/json".format(name, version) + request = QNetworkRequest(QUrl(url)) + reply = self.__networkManager.get(request) + while not reply.isFinished(): + QCoreApplication.processEvents() + + reply.deleteLater() + if reply.error() == QNetworkReply.NoError: + data = str(reply.readAll(), + Preferences.getSystem("IOEncoding"), + 'replace') + try: + result = json.loads(data) + except Exception: + # ignore JSON exceptions + pass + + return result
--- a/PipInterface/PipFreezeDialog.py Thu Feb 21 19:55:35 2019 +0100 +++ b/PipInterface/PipFreezeDialog.py Fri Feb 22 19:34:44 2019 +0100 @@ -54,12 +54,6 @@ self.__pip = pip - self.venvComboBox.addItem(pip.getDefaultEnvironmentString()) - projectVenv = self.__pip.getProjectEnvironmentString() - if projectVenv: - self.venvComboBox.addItem(projectVenv) - self.venvComboBox.addItems(pip.getVirtualenvNames()) - self.__requirementsEdited = False self.__requirementsAvailable = False @@ -75,16 +69,6 @@ QApplication.restoreOverrideCursor() e.accept() - @pyqtSlot(str) - def on_venvComboBox_activated(self, txt): - """ - Private slot handling the selection of a virtual environment. - - @param txt virtual environment - @type str - """ - self.__refresh() - @pyqtSlot(bool) def on_localCheckBox_clicked(self, checked): """ @@ -140,14 +124,16 @@ if ok: self.start() - def start(self): + def start(self, venvName): """ Public method to start the command. + + @param venvName name of the environment to act upon + @type str """ self.requirementsEdit.clear() self.__requirementsAvailable = False - venvName = self.venvComboBox.currentText() interpreter = self.__pip.getVirtualenvInterpreter(venvName) if not interpreter: return
--- a/PipInterface/PipFreezeDialog.ui Thu Feb 21 19:55:35 2019 +0100 +++ b/PipInterface/PipFreezeDialog.ui Fri Feb 22 19:34:44 2019 +0100 @@ -21,30 +21,6 @@ </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Virtual Environment:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="venvComboBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="toolTip"> - <string>Select the virtual environment to be used</string> - </property> - </widget> - </item> - </layout> - </item> - <item> <widget class="QCheckBox" name="localCheckBox"> <property name="toolTip"> <string>Select to show requirements for locally-installed packages only</string> @@ -183,7 +159,6 @@ </customwidget> </customwidgets> <tabstops> - <tabstop>venvComboBox</tabstop> <tabstop>localCheckBox</tabstop> <tabstop>requirementsFilePicker</tabstop> <tabstop>requirementsEdit</tabstop>
--- a/PipInterface/PipPackageDetailsDialog.py Thu Feb 21 19:55:35 2019 +0100 +++ b/PipInterface/PipPackageDetailsDialog.py Fri Feb 22 19:34:44 2019 +0100 @@ -24,14 +24,12 @@ """ Class implementing a dialog to show details about a package. """ - def __init__(self, detailsData, downloadsData, parent=None): + def __init__(self, detailsData, parent=None): """ Constructor @param detailsData package details @type dict - @param downloadsData downloads information - @type dict @param parent reference to the parent widget @type QWidget """ @@ -51,9 +49,9 @@ "bdist_dumb": self.tr("Archive"), } - self.__populateDetails(detailsData) - self.__populateDownloadUrls(downloadsData) - self.__populateRequiresProvides(detailsData) + self.__populateDetails(detailsData["info"]) + self.__populateDownloadUrls(detailsData["urls"]) + self.__populateRequiresProvides(detailsData["info"]) def __populateDetails(self, detailsData): """ @@ -147,17 +145,17 @@ """ populatedItems = 0 - if "requires" in detailsData: + if "requires" in detailsData and detailsData["requires"]: self.requiredPackagesList.addItems(detailsData["requires"]) populatedItems += len(detailsData["requires"]) - if "requires_dist" in detailsData: + if "requires_dist" in detailsData and detailsData["requires_dist"]: self.requiredDistributionsList.addItems( detailsData["requires_dist"]) populatedItems += len(detailsData["requires_dist"]) - if "provides" in detailsData: + if "provides" in detailsData and detailsData["provides"]: self.providedPackagesList.addItems(detailsData["provides"]) populatedItems += len(detailsData["provides"]) - if "provides_dist" in detailsData: + if "provides_dist" in detailsData and detailsData["provides_dist"]: self.providedDistributionsList.addItems( detailsData["provides_dist"]) populatedItems += len(detailsData["provides_dist"])
--- a/PipInterface/PipPackagesWidget.py Thu Feb 21 19:55:35 2019 +0100 +++ b/PipInterface/PipPackagesWidget.py Fri Feb 22 19:34:44 2019 +0100 @@ -29,6 +29,8 @@ from .Pip import Pip +# TODO: use icons for action buttons +# TODO: show package details for installed packages class PipPackagesWidget(QWidget, Ui_PipPackagesWidget): """ Class implementing the pip packages management widget. @@ -111,8 +113,8 @@ self.statusLabel.hide() self.searchWidget.hide() - self.__detailsData = {} - self.__query = [] + self.__queryName = [] + self.__querySummary = [] self.__packageDetailsDialog = None @@ -471,7 +473,8 @@ Private method to update the state of the search button. """ self.searchButton.setEnabled( - bool(self.searchEdit.text()) and + (bool(self.searchEditName.text()) or + bool(self.searchEditSummary.text())) and self.__isPipAvailable() ) @@ -486,14 +489,14 @@ self.searchWidget.setVisible(checked) if checked: - self.searchEdit.setFocus(Qt.OtherFocusReason) - self.searchEdit.selectAll() + self.searchEditName.setFocus(Qt.OtherFocusReason) + self.searchEditName.selectAll() self.__updateSearchActionButtons() self.__updateSearchButton() @pyqtSlot(str) - def on_searchEdit_textChanged(self, txt): + def on_searchEditName_textChanged(self, txt): """ Private slot handling a change of the search term. @@ -503,7 +506,24 @@ self.__updateSearchButton() @pyqtSlot() - def on_searchEdit_returnPressed(self): + def on_searchEditName_returnPressed(self): + """ + Private slot initiating a search via a press of the Return key. + """ + self.__search() + + @pyqtSlot(str) + def on_searchEditSummary_textChanged(self, txt): + """ + Private slot handling a change of the search term. + + @param txt search term + @type str + """ + self.__updateSearchButton() + + @pyqtSlot() + def on_searchEditSummary_returnPressed(self): """ Private slot initiating a search via a press of the Return key. """ @@ -534,11 +554,19 @@ QApplication.setOverrideCursor(Qt.WaitCursor) QApplication.processEvents(QEventLoop.ExcludeUserInputEvents) - self.__query = [term for term in self.searchEdit.text().strip().split() - if term not in self.SearchStopwords] + self.__queryName = [ + term for term in self.searchEditName.text().strip().split() + if term not in self.SearchStopwords + ] + self.__querySummary = [ + term for term in self.searchEditSummary.text().strip().split() + if term not in self.SearchStopwords + ] self.__client.call( "search", - ({"name": self.__query, "summary": self.__query}, "or"), + ({"name": self.__queryName, + "summary": self.__querySummary}, + self.searchTermCombineComboBox.currentText()), self.__processSearchResult, self.__searchError ) @@ -616,7 +644,7 @@ self.__updateSearchActionButtons() self.__updateSearchButton() - self.searchEdit.setFocus(Qt.OtherFocusReason) + self.searchEditName.setFocus(Qt.OtherFocusReason) def __searchError(self, errorCode, errorString): """ @@ -682,12 +710,13 @@ @rtype int """ score = 0 - for queryTerm in self.__query: + for queryTerm in self.__queryName: if queryTerm.lower() in name.lower(): score += 4 if queryTerm.lower() == name.lower(): score += 4 + for queryTerm in self.__querySummary: if queryTerm.lower() in summary.lower(): if QRegExp(r'\b{0}\b'.format(QRegExp.escape(queryTerm)), Qt.CaseInsensitive).indexIn(summary) != -1: @@ -758,8 +787,6 @@ QApplication.setOverrideCursor(Qt.WaitCursor) QApplication.processEvents(QEventLoop.ExcludeUserInputEvents) - self.__detailsData = {} - if not item: item = self.searchResultList.selectedItems()[0] @@ -777,86 +804,28 @@ 0, False) if not ok: return - packageName = item.text(0) - self.__client.call( - "release_data", - (packageName, packageVersion), - lambda d: self.__getPackageDownloadsData(packageName, - packageVersion, - d), - lambda c, s: self.__detailsError(packageName, c, s) - ) - - def __getPackageDownloadsData(self, packageName, packageVersion, data): - """ - Private method to store the details data and get downloads - information. + packageData = self.__pip.getPackageDetails(packageName, packageVersion) - @param packageName name of the package - @type str - @param packageVersion version info - @type str - @param data result data with package details in the first - element - @type tuple - """ - if data and data[0]: - self.__detailsData = data[0] - self.__client.call( - "release_urls", - (packageName, packageVersion), - self.__displayPackageDetails, - lambda c, s: self.__detailsError(packageName, c, s) - ) + QApplication.restoreOverrideCursor() + if packageData: + from .PipPackageDetailsDialog import PipPackageDetailsDialog + + self.showDetailsButton.setEnabled(True) + + if self.__packageDetailsDialog is not None: + self.__packageDetailsDialog.close() + + self.__packageDetailsDialog = \ + PipPackageDetailsDialog(packageData, self) + self.__packageDetailsDialog.show() else: - QApplication.restoreOverrideCursor() E5MessageBox.warning( self, self.tr("Search PyPI"), self.tr("""<p>No package details info for <b>{0}</b>""" """ available.</p>""").format(packageName)) - def __displayPackageDetails(self, data): - """ - Private method to display the returned package details. - - @param data result data with downloads information in the first element - @type tuple - """ - from .PipPackageDetailsDialog import PipPackageDetailsDialog - - QApplication.restoreOverrideCursor() - self.showDetailsButton.setEnabled(True) - - if self.__packageDetailsDialog is not None: - self.__packageDetailsDialog.close() - - self.__packageDetailsDialog = \ - PipPackageDetailsDialog(self.__detailsData, data[0], self) - self.__packageDetailsDialog.show() - - def __detailsError(self, packageName, errorCode, errorString): - """ - Private method handling a details error. - - @param packageName name of the package - @type str - @param errorCode code of the error - @type int - @param errorString error message - @type str - """ - QApplication.restoreOverrideCursor() - self.showDetailsButton.setEnabled(True) - E5MessageBox.warning( - self, - self.tr("Search PyPI"), - self.tr("""<p>Package details info for <b>{0}</b> could not be""" - """ retrieved.</p><p>Reason: {1}</p>""") - .format(packageName, errorString) - ) - ####################################################################### ## Menu related methods below ####################################################################### @@ -993,27 +962,32 @@ @pyqtSlot() def __installRequirements(self): """ - + Private slot to install packages as given in a requirements file. """ - # TODO: call pip.installRequirements() + venvName = self.environmentsComboBox.currentText() + if venvName: + self.__pip.installRequirements(venvName) @pyqtSlot() def __uninstallRequirements(self): """ - + Private slot to uninstall packages as given in a requirements file. """ - # TODO: call pip.uninstallRequirements() + venvName = self.environmentsComboBox.currentText() + if venvName: + self.__pip.uninstallRequirements(venvName) @pyqtSlot() def __generateRequirements(self): """ Private slot to generate the contents for a requirements file. """ - # TODO: modify to get selected environment - from .PipFreezeDialog import PipFreezeDialog - self.__freezeDialog = PipFreezeDialog(self) - self.__freezeDialog.show() - self.__freezeDialog.start() + venvName = self.environmentsComboBox.currentText() + if venvName: + from .PipFreezeDialog import PipFreezeDialog + self.__freezeDialog = PipFreezeDialog(self.__pip, self) + self.__freezeDialog.show() + self.__freezeDialog.start(venvName) @pyqtSlot() def __editUserConfiguration(self): @@ -1025,34 +999,33 @@ @pyqtSlot() def __editVirtualenvConfiguration(self): """ - Private slot to edit the current virtualenv configuration. + Private slot to edit the configuration of the selected environment. """ - # TODO: modify to get selected environment - self.__editConfiguration(virtualenv=True) + venvName = self.environmentsComboBox.currentText() + if venvName: + self.__editConfiguration(venvName=venvName) - def __editConfiguration(self, virtualenv=False): + def __editConfiguration(self, venvName=""): """ Private method to edit a configuration. - @param virtualenv flag indicating to edit the current virtualenv - configuration file - @type bool + @param venvName name of the environment to act upon + @type str """ - # TODO: modify to use venvName from QScintilla.MiniEditor import MiniEditor - if virtualenv: - cfgFile = self.__getVirtualenvConfig() + if venvName: + cfgFile = self.__pip.getVirtualenvConfig(venvName) if not cfgFile: return else: - cfgFile = self.__getUserConfig() + cfgFile = self.__pip.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""")) + """ Aborting""")) return try: @@ -1063,7 +1036,7 @@ None, self.tr("Edit Configuration"), self.tr("""No valid configuration path determined.""" - """ Is a virtual environment selected? Aborting""")) + """ Aborting""")) return if not os.path.exists(cfgFile): @@ -1081,7 +1054,7 @@ None, self.tr("Edit Configuration"), self.tr("""No valid configuartion path determined.""" - """ Is a virtual environment selected? Aborting""")) + """ Aborting""")) return self.__editor = MiniEditor(cfgFile, "Properties")
--- a/PipInterface/PipPackagesWidget.ui Thu Feb 21 19:55:35 2019 +0100 +++ b/PipInterface/PipPackagesWidget.ui Fri Feb 22 19:34:44 2019 +0100 @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>500</width> - <height>600</height> + <height>700</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout_5"> @@ -313,18 +313,42 @@ <number>0</number> </property> <item> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <item> - <widget class="QLineEdit" name="searchEdit"> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Name:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="searchEditName"> <property name="toolTip"> - <string>Enter the search term</string> + <string>Enter the search term for the package name</string> </property> <property name="placeholderText"> <string>Enter search term</string> </property> </widget> </item> - <item> + <item row="0" column="2" rowspan="2"> + <widget class="QComboBox" name="searchTermCombineComboBox"> + <property name="toolTip"> + <string>Select the search term combination operation</string> + </property> + <item> + <property name="text"> + <string notr="true">and</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">or</string> + </property> + </item> + </widget> + </item> + <item row="0" column="3" rowspan="2"> <widget class="QPushButton" name="searchButton"> <property name="enabled"> <bool>false</bool> @@ -337,6 +361,23 @@ </property> </widget> </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Summary:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="searchEditSummary"> + <property name="toolTip"> + <string>Enter the search term for the package summary</string> + </property> + <property name="placeholderText"> + <string>Enter search term</string> + </property> + </widget> + </item> </layout> </item> <item> @@ -469,16 +510,25 @@ <tabstops> <tabstop>environmentsComboBox</tabstop> <tabstop>pipMenuButton</tabstop> + <tabstop>localCheckBox</tabstop> + <tabstop>notRequiredCheckBox</tabstop> + <tabstop>userCheckBox</tabstop> <tabstop>packagesList</tabstop> + <tabstop>verboseCheckBox</tabstop> + <tabstop>installedFilesCheckBox</tabstop> + <tabstop>infoWidget</tabstop> <tabstop>refreshButton</tabstop> <tabstop>upgradeButton</tabstop> <tabstop>upgradeAllButton</tabstop> <tabstop>uninstallButton</tabstop> <tabstop>searchToggleButton</tabstop> - <tabstop>searchEdit</tabstop> + <tabstop>searchEditName</tabstop> + <tabstop>searchTermCombineComboBox</tabstop> + <tabstop>searchEditSummary</tabstop> <tabstop>searchButton</tabstop> <tabstop>searchResultList</tabstop> <tabstop>installButton</tabstop> + <tabstop>installUserSiteButton</tabstop> <tabstop>showDetailsButton</tabstop> </tabstops> <resources/>
--- a/Plugins/PluginPipInterface.py Thu Feb 21 19:55:35 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,235 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Module implementing the pip interface plug-in. -""" - -from __future__ import unicode_literals - - -from PyQt5.QtCore import pyqtSignal, QObject, QCoreApplication - -from E5Gui.E5Application import e5App - -import Preferences -import UI.Info - -# Start-Of-Header -name = "pip Interface Plug-in" -author = "Detlev Offenbach <detlev@die-offenbachs.de>" -autoactivate = True -deactivateable = True -version = UI.Info.VersionOnly -className = "PipInterfacePlugin" -packageName = "__core__" -shortDescription = "Plug-in implementing a simple GUI for the pip command." -longDescription = ( - """Plug-in implementing a simple GUI for the pip command.""" -) -needsRestart = False -pyqtApi = 2 -python2Compatible = True -# End-Of-Header - -error = "" - -pipPluginObject = None - - -##def exeDisplayDataList(): -## """ -## Module function to support the display of some executable info. -## -## @return list of dictionaries containing the data to query the presence of -## the executable -## """ -## global pipPluginObject -## -## dataList = [] -## data = { -## "programEntry": True, -## "header": QCoreApplication.translate( -## "PipInterfacePlugin", "Package Management - pip"), -## "exe": "dummyExe", -## "versionCommand": "--version", -## "versionStartsWith": "pip", -## "versionPosition": 1, -## "version": "", -## "versionCleanup": None, -## "exeModule": ["-m", "pip"], -## } -## virtualenvManager = e5App().getObject("VirtualEnvManager") -## for venvName in virtualenvManager.getVirtualenvNames(): -## interpreter = virtualenvManager.getVirtualenvInterpreter(venvName) -## data["exe"] = interpreter -## dataList.append(data.copy()) -## return dataList -## -## -##def createPipPage(configDlg): -## """ -## Module function to create the pip configuration page. -## -## @param configDlg reference to the configuration dialog -## @return reference to the configuration page -## """ -## global pipPluginObject -## from UiExtensionPlugins.PipInterface.ConfigurationPage.PipPage import \ -## PipPage -## page = PipPage(pipPluginObject) -## return page -## -## -##def getConfigData(): -## """ -## Module function returning data as required by the configuration dialog. -## -## @return dictionary containing the relevant data -## """ -## return { -## "pipPage": [ -## QCoreApplication.translate( -## "PipInterfacePlugin", "Python Package Management"), -## "pypi.png", -## createPipPage, None, None -## ], -## } -## -## -##def prepareUninstall(): -## """ -## Module function to prepare for an un-installation. -## """ -## Preferences.Prefs.settings.remove(PipInterfacePlugin.PreferencesKey) - - -class PipInterfacePlugin(QObject): - """ - Class implementing the pip interface plug-in. - - @signal currentEnvironmentChanged(str) emitted to signal a change of the - currently selected virtual environment - """ - PreferencesKey = "PipPlugin" - - currentEnvironmentChanged = pyqtSignal(str) - - def __init__(self, ui): - """ - Constructor - - @param ui reference to the user interface object (UI.UserInterface) - """ - super(PipInterfacePlugin, self).__init__(ui) - self.__ui = ui - self.__initialize() - - self.__defaults = { - "CurrentEnvironment": "", - "PipSearchIndex": "", # used by the search command - } - - def __initialize(self): - """ - Private slot to (re)initialize the plugin. - """ - self.__object = None - - self.__mainAct = None - self.__mainMenu = None - - def activate(self): - """ - Public method to activate this plugin. - - @return tuple of None and activation status - @rtype tuple of (None, bool) - """ - global error - error = "" # clear previous error - - global pipPluginObject - pipPluginObject = self - - from UiExtensionPlugins.PipInterface.Pip import Pip - self.__object = Pip(self, self.__ui) - self.__object.initActions() - e5App().registerPluginObject("PipGui", self.__object) - - menu = self.__ui.getMenu("extras") - self.__mainMenu = self.__object.initMenu() - self.__mainAct = menu.addMenu(self.__mainMenu) - - return None, True - - def deactivate(self): - """ - Public method to deactivate this plugin. - """ - e5App().unregisterPluginObject("PipGui") - - menu = self.__ui.getMenu("extras") - menu.removeAction(self.__mainAct) - self.__mainAct = None - - self.__initialize() -## -## def getPreferences(self, key): -## """ -## Public method to retrieve the various pip related settings. -## -## @param key the key of the value to get -## @type str -## @return the requested setting -## @rtype any -## """ -## return Preferences.Prefs.settings.value( -## self.PreferencesKey + "/" + key, self.__defaults[key]) -## -## def setPreferences(self, key, value): -## """ -## Public method to store the various pip related settings. -## -## @param key the key of the setting to be set -## @type str -## @param value the value to be set -## @type any -## """ -## Preferences.Prefs.settings.setValue( -## self.PreferencesKey + "/" + key, value) -## -## if key == "CurrentEnvironment": -## self.currentEnvironmentChanged.emit(value) - - 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 self.__object is not None: - return self.__object.getMenu(name) - else: - return None - - def getMenuNames(self): - """ - Public method to get the names of all menus. - - @return menu names - @rtype list of str - """ - if self.__object is not None: - return list(self.__menus.keys()) - else: - return [] - -# -# eflag: noqa = M801
--- a/Preferences/__init__.py Thu Feb 21 19:55:35 2019 +0100 +++ b/Preferences/__init__.py Fri Feb 22 19:34:44 2019 +0100 @@ -1591,7 +1591,6 @@ # defaults for pip pipDefaults = { - "CurrentEnvironment": "", "PipSearchIndex": "", # used by the search command }
--- a/eric6.e4p Thu Feb 21 19:55:35 2019 +0100 +++ b/eric6.e4p Fri Feb 22 19:34:44 2019 +0100 @@ -527,7 +527,6 @@ <Source>Plugins/PluginCodeStyleChecker.py</Source> <Source>Plugins/PluginEricapi.py</Source> <Source>Plugins/PluginEricdoc.py</Source> - <Source>Plugins/PluginPipInterface.py</Source> <Source>Plugins/PluginSyntaxChecker.py</Source> <Source>Plugins/PluginTabnanny.py</Source> <Source>Plugins/PluginTranslator.py</Source> @@ -2256,14 +2255,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>