--- 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")