Wed, 13 Jul 2022 14:55:47 +0200
Reformatted the source code using the 'Black' utility.
9214 | 1 | # -*- coding: utf-8 -*- |
2 | ||
3 | # Copyright (c) 2022 Detlev Offenbach <detlev@die-offenbachs.de> | |
4 | # | |
5 | ||
6 | """ | |
7 | Module implementing a dialog to enter the parameters for a Black formatting run. | |
8 | """ | |
9 | ||
10 | import contextlib | |
11 | import copy | |
12 | import pathlib | |
13 | ||
14 | import black | |
15 | import tomlkit | |
16 | ||
17 | from PyQt6.QtCore import pyqtSlot, Qt | |
18 | from PyQt6.QtGui import QFontMetricsF, QGuiApplication | |
19 | from PyQt6.QtWidgets import QDialog, QDialogButtonBox, QListWidgetItem | |
20 | ||
21 | from EricWidgets import EricMessageBox | |
22 | from EricWidgets.EricApplication import ericApp | |
23 | ||
24 | from .Ui_BlackConfigurationDialog import Ui_BlackConfigurationDialog | |
25 | ||
26 | from . import BlackUtilities | |
27 | ||
28 | ||
29 | class BlackConfigurationDialog(QDialog, Ui_BlackConfigurationDialog): | |
30 | """ | |
31 | Class implementing a dialog to enter the parameters for a Black formatting run. | |
32 | """ | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
33 | |
9214 | 34 | def __init__(self, withProject=True, parent=None): |
35 | """ | |
36 | Constructor | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
37 | |
9214 | 38 | @param withProject flag indicating to look for project configurations |
39 | (defaults to True) | |
40 | @type bool | |
41 | @param parent reference to the parent widget (defaults to None) | |
42 | @type QWidget (optional) | |
43 | """ | |
44 | super().__init__(parent) | |
45 | self.setupUi(self) | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
46 | |
9214 | 47 | self.__project = ericApp().getObject("Project") if withProject else None |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
48 | |
9214 | 49 | indentTabWidth = ( |
50 | QFontMetricsF(self.excludeEdit.font()).horizontalAdvance(" ") * 2 | |
51 | ) | |
52 | self.excludeEdit.document().setIndentWidth(indentTabWidth) | |
53 | self.excludeEdit.setTabStopDistance(indentTabWidth) | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
54 | |
9214 | 55 | self.__pyprojectData = {} |
56 | self.__projectData = {} | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
57 | |
9214 | 58 | self.__tomlButton = self.buttonBox.addButton( |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
59 | self.tr("Generate TOML"), QDialogButtonBox.ButtonRole.ActionRole |
9214 | 60 | ) |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
61 | self.__tomlButton.setToolTip( |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
62 | self.tr("Place a code snippet for 'pyproject.toml' into the clipboard.") |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
63 | ) |
9214 | 64 | self.__tomlButton.clicked.connect(self.__createTomlSnippet) |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
65 | |
9214 | 66 | # setup the source combobox |
67 | self.sourceComboBox.addItem("", "") | |
68 | if self.__project: | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
69 | pyprojectPath = ( |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
70 | pathlib.Path(self.__project.getProjectPath()) / "pyproject.toml" |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
71 | ) |
9214 | 72 | if pyprojectPath.exists(): |
73 | with contextlib.suppress(tomlkit.exceptions.ParseError, OSError): | |
74 | with pyprojectPath.open("r", encoding="utf-8") as f: | |
75 | data = tomlkit.load(f) | |
76 | config = data.get("tool", {}).get("black", {}) | |
77 | if config: | |
78 | self.__pyprojectData = { | |
79 | k.replace("--", "").replace("-", "_"): v | |
80 | for k, v in config.items() | |
81 | } | |
82 | self.sourceComboBox.addItem("pyproject.toml", "pyproject") | |
83 | if self.__project.getData("OTHERTOOLSPARMS", "Black") is not None: | |
84 | self.__projectData = copy.deepcopy( | |
85 | self.__project.getData("OTHERTOOLSPARMS", "Black") | |
86 | ) | |
87 | self.sourceComboBox.addItem(self.tr("Project File"), "project") | |
88 | self.sourceComboBox.addItem(self.tr("Defaults"), "default") | |
89 | self.sourceComboBox.addItem(self.tr("Configuration Below"), "dialog") | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
90 | |
9214 | 91 | self.__populateTargetVersionsList() |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
92 | |
9214 | 93 | if self.__projectData: |
94 | source = self.__projectData.get("source", "") | |
95 | self.sourceComboBox.setCurrentIndex(self.sourceComboBox.findData(source)) | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
96 | |
9214 | 97 | def __populateTargetVersionsList(self): |
98 | """ | |
99 | Private method to populate the target versions list widget with checkable | |
100 | Python version entries. | |
101 | """ | |
102 | targets = [ | |
103 | (int(t[2]), int(t[3:]), t) | |
104 | for t in dir(black.TargetVersion) | |
105 | if t.startswith("PY") | |
106 | ] | |
107 | for target in sorted(targets): | |
108 | itm = QListWidgetItem( | |
109 | "Python {0}.{1}".format(target[0], target[1]), self.targetVersionsList | |
110 | ) | |
111 | itm.setData(Qt.ItemDataRole.UserRole, target[2]) | |
112 | itm.setFlags(itm.flags() | Qt.ItemFlag.ItemIsUserCheckable) | |
113 | itm.setCheckState(Qt.CheckState.Unchecked) | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
114 | |
9214 | 115 | def __loadConfiguration(self, configurationDict): |
116 | """ | |
117 | Private method to load the configuration section with data of the given | |
118 | dictionary. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
119 | |
9214 | 120 | @param configurationDict reference to the data to be loaded |
121 | @type dict | |
122 | """ | |
123 | confDict = copy.deepcopy(BlackUtilities.getDefaultConfiguration()) | |
124 | confDict.update(configurationDict) | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
125 | |
9214 | 126 | self.lineLengthSpinBox.setValue(int(confDict["line-length"])) |
127 | self.skipStringNormalCheckBox.setChecked(confDict["skip-string-normalization"]) | |
128 | self.skipMagicCommaCheckBox.setChecked(confDict["skip-magic-trailing-comma"]) | |
129 | self.excludeEdit.setPlainText(confDict["extend-exclude"]) | |
130 | for row in range(self.targetVersionsList.count()): | |
131 | itm = self.targetVersionsList.item(row) | |
132 | itm.setCheckState( | |
133 | Qt.CheckState.Checked | |
134 | if itm.data(Qt.ItemDataRole.UserRole).lower() | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
135 | in confDict["target-version"] |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
136 | else Qt.CheckState.Unchecked |
9214 | 137 | ) |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
138 | |
9214 | 139 | @pyqtSlot(str) |
140 | def on_sourceComboBox_currentTextChanged(self, selection): | |
141 | """ | |
142 | Private slot to handle the selection of a configuration source. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
143 | |
9214 | 144 | @param selection text of the currently selected item |
145 | @type str | |
146 | """ | |
147 | self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled( | |
148 | bool(selection) | |
149 | ) | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
150 | |
9214 | 151 | source = self.sourceComboBox.currentData() |
152 | if source == "pyproject": | |
153 | self.__loadConfiguration(self.__pyprojectData) | |
154 | elif source == "project": | |
155 | self.__loadConfiguration(self.__projectData) | |
156 | elif source == "default": | |
157 | self.__loadConfiguration(BlackUtilities.getDefaultConfiguration()) | |
158 | elif source == "dialog": | |
159 | # just leave the current entries | |
160 | pass | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
161 | |
9214 | 162 | @pyqtSlot() |
163 | def on_excludeEdit_textChanged(self): | |
164 | """ | |
165 | Private slot to enable the validate button depending on the exclude text. | |
166 | """ | |
167 | self.validateButton.setEnabled(bool(self.excludeEdit.toPlainText())) | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
168 | |
9214 | 169 | @pyqtSlot() |
170 | def on_validateButton_clicked(self): | |
171 | """ | |
172 | Private slot to validate the entered exclusion regular expression. | |
173 | """ | |
174 | regexp = self.excludeEdit.toPlainText() | |
175 | valid, error = BlackUtilities.validateRegExp(regexp) | |
176 | if valid: | |
177 | EricMessageBox.information( | |
178 | self, | |
179 | self.tr("Validation"), | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
180 | self.tr("""The exclusion expression is valid."""), |
9214 | 181 | ) |
182 | else: | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
183 | EricMessageBox.critical(self, self.tr("Validation Error"), error) |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
184 | |
9214 | 185 | def __getTargetList(self): |
186 | """ | |
187 | Private method to get the list of checked target versions. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
188 | |
9214 | 189 | @return list of target versions |
190 | @rtype list of str | |
191 | """ | |
192 | targets = [] | |
193 | for row in range(self.targetVersionsList.count()): | |
194 | itm = self.targetVersionsList.item(row) | |
195 | if itm.checkState() == Qt.CheckState.Checked: | |
196 | targets.append(itm.data(Qt.ItemDataRole.UserRole).lower()) | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
197 | |
9214 | 198 | return targets |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
199 | |
9214 | 200 | @pyqtSlot() |
201 | def __createTomlSnippet(self): | |
202 | """ | |
203 | Private slot to generate a TOML snippet of the current configuration. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
204 | |
9214 | 205 | Note: Only non-default values are included in this snippet. |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
206 | |
9214 | 207 | The code snippet is copied to the clipboard and may be placed inside the |
208 | 'pyproject.toml' file. | |
209 | """ | |
210 | doc = tomlkit.document() | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
211 | |
9214 | 212 | black = tomlkit.table() |
213 | targetList = self.__getTargetList() | |
214 | if targetList: | |
215 | black["target-version"] = targetList | |
216 | black["line-length"] = self.lineLengthSpinBox.value() | |
217 | if self.skipStringNormalCheckBox.isChecked(): | |
218 | black["skip-string-normalization"] = True | |
219 | if self.skipMagicCommaCheckBox.isChecked(): | |
220 | black["skip-magic-trailing-comma"] = True | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
221 | |
9214 | 222 | excludeRegexp = self.excludeEdit.toPlainText() |
223 | if excludeRegexp and BlackUtilities.validateRegExp(excludeRegexp)[0]: | |
224 | black["extend-exclude"] = tomlkit.string( | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
225 | "\n{0}\n".format(excludeRegexp.strip()), literal=True, multiline=True |
9214 | 226 | ) |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
227 | |
9214 | 228 | doc["tool"] = tomlkit.table(is_super_table=True) |
229 | doc["tool"]["black"] = black | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
230 | |
9214 | 231 | QGuiApplication.clipboard().setText(tomlkit.dumps(doc)) |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
232 | |
9214 | 233 | EricMessageBox.information( |
234 | self, | |
9216
e89083501ce3
Updated translations.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9214
diff
changeset
|
235 | self.tr("Create TOML snippet"), |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
236 | self.tr( |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
237 | """The 'pyproject.toml' snippet was copied to the clipboard""" |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
238 | """ successfully.""" |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
239 | ), |
9214 | 240 | ) |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
241 | |
9214 | 242 | def getConfiguration(self): |
243 | """ | |
244 | Public method to get the current configuration parameters. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
245 | |
9214 | 246 | @return dictionary containing the configuration parameters |
247 | @rtype dict | |
248 | """ | |
249 | configuration = BlackUtilities.getDefaultConfiguration() | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
250 | |
9214 | 251 | configuration["source"] = self.sourceComboBox.currentData() |
252 | configuration["target-version"] = self.__getTargetList() | |
253 | configuration["line-length"] = self.lineLengthSpinBox.value() | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
254 | configuration[ |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
255 | "skip-string-normalization" |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
256 | ] = self.skipStringNormalCheckBox.isChecked() |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
257 | configuration[ |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
258 | "skip-magic-trailing-comma" |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
259 | ] = self.skipMagicCommaCheckBox.isChecked() |
9214 | 260 | configuration["extend-exclude"] = self.excludeEdit.toPlainText().strip() |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
261 | |
9214 | 262 | if self.__project: |
263 | self.__project.setData("OTHERTOOLSPARMS", "Black", configuration) | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9216
diff
changeset
|
264 | |
9214 | 265 | return configuration |