--- a/src/eric7/CodeFormatting/BlackFormattingDialog.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/CodeFormatting/BlackFormattingDialog.py Wed Jul 13 14:55:47 2022 +0200 @@ -19,7 +19,7 @@ QDialog, QDialogButtonBox, QHeaderView, - QTreeWidgetItem + QTreeWidgetItem, ) from EricWidgets import EricMessageBox @@ -37,17 +37,24 @@ """ Class implementing a dialog showing the code formatting progress and the result. """ + DataTypeRole = Qt.ItemDataRole.UserRole DataRole = Qt.ItemDataRole.UserRole + 1 - + StatusColumn = 0 FileNameColumn = 1 - - def __init__(self, configuration, filesList, project=None, - action=BlackFormattingAction.Format, parent=None): + + def __init__( + self, + configuration, + filesList, + project=None, + action=BlackFormattingAction.Format, + parent=None, + ): """ Constructor - + @param configuration dictionary containing the configuration parameters @type dict @param filesList list of absolute file paths to be processed @@ -61,42 +68,42 @@ """ super().__init__(parent) self.setupUi(self) - + self.progressBar.setMaximum(len(filesList)) self.progressBar.setValue(0) - + self.resultsList.header().setSortIndicator(1, Qt.SortOrder.AscendingOrder) - + self.statisticsGroup.setVisible(False) - + self.__report = BlackReport(self) self.__report.check = action is BlackFormattingAction.Check self.__report.diff = action is BlackFormattingAction.Diff - + self.__config = copy.deepcopy(configuration) self.__project = project self.__action = action - + self.__cancelled = False self.__diffDialog = None - + self.__allFilter = self.tr("<all>") - + self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(True) self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False) self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True) - + self.show() QCoreApplication.processEvents() - + self.__files = self.__filterFiles(filesList) self.__formatFiles() - + def __filterFiles(self, filesList): """ Private method to filter the given list of files according the configuration parameters. - + @param filesList list of files @type list of str @return list of filtered files @@ -105,10 +112,11 @@ filterRegExps = [ BlackUtilities.compileRegExp(self.__config[k]) for k in ["force-exclude", "extend-exclude", "exclude"] - if k in self.__config and bool(self.__config[k]) + if k in self.__config + and bool(self.__config[k]) and BlackUtilities.validateRegExp(self.__config[k])[0] ] - + files = [] for file in filesList: file = Utilities.fromNativeSeparators(file) @@ -119,25 +127,27 @@ break else: files.append(file) - + return files - + def __resort(self): """ Private method to resort the result list. """ self.resultsList.sortItems( self.resultsList.sortColumn(), - self.resultsList.header().sortIndicatorOrder()) - + self.resultsList.header().sortIndicatorOrder(), + ) + def __resizeColumns(self): """ Private method to resize the columns of the result list. """ self.resultsList.header().resizeSections( - QHeaderView.ResizeMode.ResizeToContents) + QHeaderView.ResizeMode.ResizeToContents + ) self.resultsList.header().setStretchLastSection(True) - + def __populateStatusFilterCombo(self): """ Private method to populate the status filter combo box with allowed selections. @@ -149,26 +159,26 @@ BlackFormattingDialog.StatusColumn ) ) - + self.statusFilterComboBox.addItem(self.__allFilter) self.statusFilterComboBox.addItems(sorted(allowedSelections)) - + def __finish(self): """ Private method to perform some actions after the run was performed or canceled. """ self.__resort() self.__resizeColumns() - + self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(False) self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(True) self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setDefault(True) - + self.progressBar.setVisible(False) - + self.__updateStatistics() self.__populateStatusFilterCombo() - + def __updateStatistics(self): """ Private method to update the statistics about the recent formatting run and @@ -176,27 +186,27 @@ """ self.reformattedLabel.setText( self.tr("reformatted") - if self.__action is BlackFormattingAction.Format else - self.tr("would reformat") + if self.__action is BlackFormattingAction.Format + else self.tr("would reformat") ) - + total = self.progressBar.maximum() processed = total - self.__report.ignored_count - + self.totalCountLabel.setText("{0:n}".format(total)) self.excludedCountLabel.setText("{0:n}".format(self.__report.ignored_count)) self.failuresCountLabel.setText("{0:n}".format(self.__report.failure_count)) self.processedCountLabel.setText("{0:n}".format(processed)) self.reformattedCountLabel.setText("{0:n}".format(self.__report.change_count)) self.unchangedCountLabel.setText("{0:n}".format(self.__report.same_count)) - + self.statisticsGroup.setVisible(True) - + @pyqtSlot(QAbstractButton) def on_buttonBox_clicked(self, button): """ Private slot to handle button presses of the dialog buttons. - + @param button reference to the pressed button @type QAbstractButton """ @@ -204,12 +214,12 @@ self.__cancelled = True elif button == self.buttonBox.button(QDialogButtonBox.StandardButton.Close): self.accept() - + @pyqtSlot(QTreeWidgetItem, int) def on_resultsList_itemDoubleClicked(self, item, column): """ Private slot handling a double click of a result item. - + @param item reference to the double clicked item @type QTreeWidgetItem @param column column number that was double clicked @@ -220,19 +230,19 @@ EricMessageBox.critical( self, self.tr("Formatting Failure"), - self.tr( - "<p>Formatting failed due to this error.</p><p>{0}</p>" - ).format(item.data(0, BlackFormattingDialog.DataRole)) + self.tr("<p>Formatting failed due to this error.</p><p>{0}</p>").format( + item.data(0, BlackFormattingDialog.DataRole) + ), ) elif dataType == "diff": if self.__diffDialog is None: self.__diffDialog = BlackDiffWidget() self.__diffDialog.showDiff(item.data(0, BlackFormattingDialog.DataRole)) - + def addResultEntry(self, status, fileName, isError=False, data=None): """ Public method to add an entry to the result list. - + @param status status of the operation @type str @param fileName name of the processed file @@ -245,52 +255,47 @@ """ if self.__project: fileName = self.__project.getRelativePath(fileName) - + itm = QTreeWidgetItem(self.resultsList, [status, fileName]) if data: itm.setData( - 0, - BlackFormattingDialog.DataTypeRole, - "error" if isError else "diff" + 0, BlackFormattingDialog.DataTypeRole, "error" if isError else "diff" ) itm.setData(0, BlackFormattingDialog.DataRole, data) - + self.progressBar.setValue(self.progressBar.value() + 1) - + QCoreApplication.processEvents() - + def __formatFiles(self): """ Private method to format the list of files according the configuration. """ writeBack = black.WriteBack.from_configuration( check=self.__action is BlackFormattingAction.Check, - diff=self.__action is BlackFormattingAction.Diff + diff=self.__action is BlackFormattingAction.Diff, ) - + versions = ( { black.TargetVersion[target.upper()] for target in self.__config["target-version"] } - if self.__config["target-version"] else - set() + if self.__config["target-version"] + else set() ) - + mode = black.Mode( target_versions=versions, line_length=int(self.__config["line-length"]), string_normalization=not self.__config["skip-string-normalization"], - magic_trailing_comma=not self.__config["skip-magic-trailing-comma"] + magic_trailing_comma=not self.__config["skip-magic-trailing-comma"], ) - + for file in self.__files: if self.__action is BlackFormattingAction.Diff: self.__diffFormatFile( - pathlib.Path(file), - fast=False, - mode=mode, - report=self.__report + pathlib.Path(file), fast=False, mode=mode, report=self.__report ) else: black.reformat_one( @@ -298,19 +303,19 @@ fast=False, write_back=writeBack, mode=mode, - report=self.__report + report=self.__report, ) - + if self.__cancelled: break - + self.__finish() - + def __diffFormatFile(self, src, fast, mode, report): """ Private method to check, if the given files need to be reformatted, and generate a unified diff. - + @param src path of file to be checked @type pathlib.Path @param fast flag indicating fast operation @@ -328,33 +333,33 @@ except black.NothingChanged: report.done(src, black.Changed.NO) return - + fileName = str(src) if self.__project: fileName = self.__project.getRelativePath(fileName) - + now = datetime.datetime.utcnow() srcName = f"{fileName}\t{then} +0000" dstName = f"{fileName}\t{now} +0000" diffContents = black.diff(srcContents, dstContents, srcName, dstName) report.done(src, black.Changed.YES, diff=diffContents) - + def closeEvent(self, evt): """ Protected slot implementing a close event handler. - + @param evt reference to the close event @type QCloseEvent """ if self.__diffDialog is not None: self.__diffDialog.close() evt.accept() - + @pyqtSlot(str) def on_statusFilterComboBox_currentTextChanged(self, status): """ Private slot handling the selection of a status for items to be shown. - + @param status selected status @type str """ @@ -370,23 +375,24 @@ """ Class extending the black Report to work with our dialog. """ + def __init__(self, dialog): """ Constructor - + @param dialog reference to the result dialog @type QDialog """ super().__init__() - + self.ignored_count = 0 - + self.__dialog = dialog - + def done(self, src, changed, diff=""): """ Public method to handle the end of a reformat. - + @param src name of the processed file @type pathlib.Path @param changed change status @@ -397,28 +403,28 @@ if changed is black.Changed.YES: status = ( QCoreApplication.translate("BlackFormattingDialog", "would reformat") - if self.check or self.diff else - QCoreApplication.translate("BlackFormattingDialog", "reformatted") + if self.check or self.diff + else QCoreApplication.translate("BlackFormattingDialog", "reformatted") ) self.change_count += 1 - + elif changed is black.Changed.NO: status = QCoreApplication.translate("BlackFormattingDialog", "unchanged") self.same_count += 1 - + elif changed is black.Changed.CACHED: status = QCoreApplication.translate("BlackFormattingDialog", "unmodified") self.same_count += 1 - + if self.diff: self.__dialog.addResultEntry(status, str(src), data=diff) else: self.__dialog.addResultEntry(status, str(src)) - + def failed(self, src, message): """ Public method to handle a reformat failure. - + @param src name of the processed file @type pathlib.Path @param message error message @@ -426,13 +432,13 @@ """ status = QCoreApplication.translate("BlackFormattingDialog", "failed") self.failure_count += 1 - + self.__dialog.addResultEntry(status, str(src), isError=True, data=message) - + def path_ignored(self, src, message=""): """ Public method handling an ignored path. - + @param src name of the processed file @type pathlib.Path or str @param message ignore message (default to "") @@ -440,5 +446,5 @@ """ status = QCoreApplication.translate("BlackFormattingDialog", "ignored") self.ignored_count += 1 - + self.__dialog.addResultEntry(status, str(src))