Sat, 08 Jun 2024 15:01:47 +0200
Code Style Checker
- Updated the Annotations checker to `flake8-annotations v3.1.1`.
--- a/docs/ThirdParty.md Fri Jun 07 13:51:43 2024 +0200 +++ b/docs/ThirdParty.md Sat Jun 08 15:01:47 2024 +0200 @@ -20,7 +20,7 @@ |:-----------------------------:|:---------:|:-----------------------------------| | bandit | 1.7.8 | Apache License 2.0 | | flake8-alphabetize | 0.0.21 | MIT License (MIT No Attribution) | -| flake8-annotations | 3.0.1 | MIT License (MIT) | +| flake8-annotations | 3.1.1 | MIT License (MIT) | | flake8-annotations-complexity | 0.0.8 | MIT License (MIT) | | flake8-annotations-coverage | 0.0.6 | MIT License (MIT) | | flake8-async | 22.11.14 | MIT License (MIT) |
--- a/docs/changelog.md Fri Jun 07 13:51:43 2024 +0200 +++ b/docs/changelog.md Sat Jun 08 15:01:47 2024 +0200 @@ -2,6 +2,9 @@ ### Version 24.7 - bug fixes +- Code Style Checker + - Updated these checkers. + - Annotations to `flake8-annotations` 3.1.1 - MicroPython - Added a few boards to the list of know MicroPython boards. - pip Interface
--- a/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsChecker.py Fri Jun 07 13:51:43 2024 +0200 +++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsChecker.py Sat Jun 08 15:01:47 2024 +0200 @@ -201,6 +201,13 @@ """ from .AnnotationsFunctionVisitor import FunctionVisitor + # Type ignores are provided by ast at the module level & we'll need them later + # when deciding whether or not to emit errors for a given function + typeIgnoreLineno = {ti.lineno for ti in self.__tree.type_ignores} + hasMypyIgnoreErrors = ( + any("# mypy: ignore-errors" in line for line in self.__source[:5]) + ) + suppressNoneReturning = self.__args.get( "SuppressNoneReturning", AnnotationsCheckerDefaultArgs["SuppressNoneReturning"], @@ -220,6 +227,9 @@ allowStarArgAny = self.__args.get( "AllowStarArgAny", AnnotationsCheckerDefaultArgs["AllowStarArgAny"] ) + respectTypeIgnore = self.__args.get( + "RespectTypeIgnore", AnnotationsCheckerDefaultArgs["RespectTypeIgnore"] + ) # Store decorator lists as sets for easier lookup dispatchDecorators = set( @@ -285,6 +295,21 @@ if function.hasDecorator(overloadDecorators): lastOverloadDecoratedFunctionName = function.name + # Optionally respect a 'type: ignore' comment + # These are considered at the function level & tags are not considered + if respectTypeIgnore: + if function.lineno in typeIgnoreLineno: + # function-level ignore + continue + elif ( + any(lineno in typeIgnoreLineno for lineno in range(1, 6)) + or hasMypyIgnoreErrors + ): + # module-level ignore + # lineno from ast is 1-indexed + # check first five lines + continue + # Record explicit errors for arguments that are missing annotations for arg in function.getMissedAnnotations(): # Check for type comments here since we're not considering them as
--- a/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsCheckerDefaults.py Fri Jun 07 13:51:43 2024 +0200 +++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsCheckerDefaults.py Sat Jun 08 15:01:47 2024 +0200 @@ -15,6 +15,7 @@ "AllowUntypedNested": False, "MypyInitReturn": False, "AllowStarArgAny": False, + "RespectTypeIgnore": False, "DispatchDecorators": ["singledispatch", "singledispatchmethod"], "OverloadDecorators": ["overload"], # Annotation Coverage
--- a/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsFunctionVisitor.py Fri Jun 07 13:51:43 2024 +0200 +++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsFunctionVisitor.py Sat Jun 08 15:01:47 2024 +0200 @@ -571,8 +571,8 @@ """ if node.value is not None: # In the event of an explicit `None` return (`return None`), the - # node body will be an instance `ast.Constant` (3.8+), which we - # need to check to see if it's actually `None` + # node body will be an instance of `ast.Constant`, which we need to + # check to see if it's actually `None` if isinstance(node.value, ast.Constant) and node.value.value is None: return
--- a/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleCheckerDialog.py Fri Jun 07 13:51:43 2024 +0200 +++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleCheckerDialog.py Sat Jun 08 15:01:47 2024 +0200 @@ -610,6 +610,11 @@ self.__data["AnnotationsChecker"]["ExemptedTypingSymbols"] = ( defaultParameters["AnnotationsChecker"]["ExemptedTypingSymbols"] ) + if "RespectTypeIgnore" not in self.__data["AnnotationsChecker"]: + # fifth extension + self.__data["AnnotationsChecker"]["RespectTypeIgnore"] = ( + defaultParameters["AnnotationsChecker"]["RespectTypeIgnore"] + ) self.__initCategoriesList(self.__data["EnabledCheckerCategories"]) self.excludeFilesEdit.setText(self.__data["ExcludeFiles"]) @@ -677,6 +682,9 @@ self.simplifiedTypesCheckBox.setChecked( self.__data["AnnotationsChecker"]["CheckFutureAnnotations"] ) + self.typeIgnoreCheckBox.setChecked( + self.__data["AnnotationsChecker"]["RespectTypeIgnore"] + ) self.dispatchDecoratorEdit.setText( ", ".join(self.__data["AnnotationsChecker"]["DispatchDecorators"]) ) @@ -926,6 +934,7 @@ self.forceFutureAnnotationsCheckBox.isChecked() ), "CheckFutureAnnotations": self.simplifiedTypesCheckBox.isChecked(), + "RespectTypeIgnore": self.typeIgnoreCheckBox.isChecked(), "DispatchDecorators": [ d.strip() for d in self.dispatchDecoratorEdit.text().split(",") ], @@ -1396,6 +1405,7 @@ self.forceFutureAnnotationsCheckBox.isChecked() ), "CheckFutureAnnotations": self.simplifiedTypesCheckBox.isChecked(), + "RespectTypeIgnore": self.typeIgnoreCheckBox.isChecked(), "DispatchDecorators": [ d.strip() for d in self.dispatchDecoratorEdit.text().split(",") ], @@ -1874,6 +1884,14 @@ ) ) ) + self.typeIgnoreCheckBox.setChecked( + Preferences.toBool( + settings.value( + "PEP8/RespectTypeIgnore", + defaultParameters["AnnotationsChecker"]["RespectTypeIgnore"], + ) + ) + ) self.dispatchDecoratorEdit.setText( ", ".join( Preferences.toList( @@ -2237,6 +2255,9 @@ "PEP8/CheckFutureAnnotations", self.simplifiedTypesCheckBox.isChecked() ) settings.setValue( + "PEP8/RespectTypeIgnore", self.typeIgnoreCheckBox.isChecked() + ) + settings.setValue( "PEP8/DispatchDecorators", [d.strip() for d in self.dispatchDecoratorEdit.text().split(",")], ) @@ -2451,6 +2472,10 @@ defaultParameters["AnnotationsChecker"]["CheckFutureAnnotations"], ) settings.setValue( + "PEP8/RespectTypeIgnore", + defaultParameters["AnnotationsChecker"]["RespectTypeIgnore"], + ) + settings.setValue( "PEP8/DispatchDecorators", defaultParameters["AnnotationsChecker"]["DispatchDecorators"], )
--- a/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleCheckerDialog.ui Fri Jun 07 13:51:43 2024 +0200 +++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleCheckerDialog.ui Sat Jun 08 15:01:47 2024 +0200 @@ -20,7 +20,7 @@ <item> <widget class="QTabWidget" name="mainWidget"> <property name="currentIndex"> - <number>2</number> + <number>0</number> </property> <widget class="QWidget" name="configureTab"> <attribute name="title"> @@ -30,7 +30,7 @@ <item> <widget class="QTabWidget" name="optionsTabWidget"> <property name="currentIndex"> - <number>7</number> + <number>0</number> </property> <widget class="QWidget" name="globalOptionsTab"> <attribute name="title"> @@ -262,7 +262,7 @@ <rect> <x>0</x> <y>0</y> - <width>367</width> + <width>617</width> <height>905</height> </rect> </property> @@ -932,16 +932,6 @@ </item> <item> <layout class="QGridLayout" name="gridLayout_9"> - <item row="0" column="0"> - <widget class="QCheckBox" name="suppressNoneReturningCheckBox"> - <property name="toolTip"> - <string>Select to not report functions without returns or with only bare returns</string> - </property> - <property name="text"> - <string>Suppress 'None' return</string> - </property> - </widget> - </item> <item row="0" column="1"> <widget class="QCheckBox" name="suppressDummyArgsCheckBox"> <property name="toolTip"> @@ -962,23 +952,13 @@ </property> </widget> </item> - <item row="1" column="1"> - <widget class="QCheckBox" name="allowUntypedNestedCheckBox"> + <item row="0" column="0"> + <widget class="QCheckBox" name="suppressNoneReturningCheckBox"> <property name="toolTip"> - <string>Select to not report dynamically typed nested functions</string> + <string>Select to not report functions without returns or with only bare returns</string> </property> <property name="text"> - <string>Allow Untyped Nested Functions</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QCheckBox" name="mypyInitReturnCheckBox"> - <property name="toolTip"> - <string>Select to not report unhinted '__init__' return</string> - </property> - <property name="text"> - <string>Allow Untyped '__init__' function</string> + <string>Suppress 'None' return</string> </property> </widget> </item> @@ -992,6 +972,16 @@ </property> </widget> </item> + <item row="1" column="1"> + <widget class="QCheckBox" name="allowUntypedNestedCheckBox"> + <property name="toolTip"> + <string>Select to not report dynamically typed nested functions</string> + </property> + <property name="text"> + <string>Allow Untyped Nested Functions</string> + </property> + </widget> + </item> <item row="3" column="0"> <widget class="QCheckBox" name="forceFutureAnnotationsCheckBox"> <property name="toolTip"> @@ -1012,6 +1002,26 @@ </property> </widget> </item> + <item row="2" column="0"> + <widget class="QCheckBox" name="mypyInitReturnCheckBox"> + <property name="toolTip"> + <string>Select to not report unhinted '__init__' return</string> + </property> + <property name="text"> + <string>Allow Untyped '__init__' function</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QCheckBox" name="typeIgnoreCheckBox"> + <property name="toolTip"> + <string>Select to supress errors for functions annotated with a 'type: ignore' comment.</string> + </property> + <property name="text"> + <string>Respect 'type: ignore' comments</string> + </property> + </widget> + </item> </layout> </item> <item> @@ -2085,6 +2095,7 @@ <tabstop>allowStarArgAnyCheckBox</tabstop> <tabstop>forceFutureAnnotationsCheckBox</tabstop> <tabstop>simplifiedTypesCheckBox</tabstop> + <tabstop>typeIgnoreCheckBox</tabstop> <tabstop>dispatchDecoratorEdit</tabstop> <tabstop>overloadDecoratorEdit</tabstop> <tabstop>exemptedTypingSymbolsEdit</tabstop>
--- a/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Ui_CodeStyleCheckerDialog.py Fri Jun 07 13:51:43 2024 +0200 +++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Ui_CodeStyleCheckerDialog.py Sat Jun 08 15:01:47 2024 +0200 @@ -1,4 +1,4 @@ -# Form implementation generated from reading ui file 'src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleCheckerDialog.ui' +# Form implementation generated from reading ui file '/home/detlev/Development/Python/Eric/eric7_default/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleCheckerDialog.ui' # # Created by: PyQt6 UI code generator 6.7.0 # @@ -112,7 +112,7 @@ self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName("scrollArea") self.scrollAreaWidgetContents = QtWidgets.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 367, 905)) + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 617, 905)) self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents") self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_4.setObjectName("verticalLayout_4") @@ -376,30 +376,33 @@ self.verticalLayout_3.addLayout(self.gridLayout_6) self.gridLayout_9 = QtWidgets.QGridLayout() self.gridLayout_9.setObjectName("gridLayout_9") - self.suppressNoneReturningCheckBox = QtWidgets.QCheckBox(parent=self.groupBox_10) - self.suppressNoneReturningCheckBox.setObjectName("suppressNoneReturningCheckBox") - self.gridLayout_9.addWidget(self.suppressNoneReturningCheckBox, 0, 0, 1, 1) self.suppressDummyArgsCheckBox = QtWidgets.QCheckBox(parent=self.groupBox_10) self.suppressDummyArgsCheckBox.setObjectName("suppressDummyArgsCheckBox") self.gridLayout_9.addWidget(self.suppressDummyArgsCheckBox, 0, 1, 1, 1) self.allowUntypedDefsCheckBox = QtWidgets.QCheckBox(parent=self.groupBox_10) self.allowUntypedDefsCheckBox.setObjectName("allowUntypedDefsCheckBox") self.gridLayout_9.addWidget(self.allowUntypedDefsCheckBox, 1, 0, 1, 1) + self.suppressNoneReturningCheckBox = QtWidgets.QCheckBox(parent=self.groupBox_10) + self.suppressNoneReturningCheckBox.setObjectName("suppressNoneReturningCheckBox") + self.gridLayout_9.addWidget(self.suppressNoneReturningCheckBox, 0, 0, 1, 1) + self.allowStarArgAnyCheckBox = QtWidgets.QCheckBox(parent=self.groupBox_10) + self.allowStarArgAnyCheckBox.setObjectName("allowStarArgAnyCheckBox") + self.gridLayout_9.addWidget(self.allowStarArgAnyCheckBox, 2, 1, 1, 1) self.allowUntypedNestedCheckBox = QtWidgets.QCheckBox(parent=self.groupBox_10) self.allowUntypedNestedCheckBox.setObjectName("allowUntypedNestedCheckBox") self.gridLayout_9.addWidget(self.allowUntypedNestedCheckBox, 1, 1, 1, 1) - self.mypyInitReturnCheckBox = QtWidgets.QCheckBox(parent=self.groupBox_10) - self.mypyInitReturnCheckBox.setObjectName("mypyInitReturnCheckBox") - self.gridLayout_9.addWidget(self.mypyInitReturnCheckBox, 2, 0, 1, 1) - self.allowStarArgAnyCheckBox = QtWidgets.QCheckBox(parent=self.groupBox_10) - self.allowStarArgAnyCheckBox.setObjectName("allowStarArgAnyCheckBox") - self.gridLayout_9.addWidget(self.allowStarArgAnyCheckBox, 2, 1, 1, 1) self.forceFutureAnnotationsCheckBox = QtWidgets.QCheckBox(parent=self.groupBox_10) self.forceFutureAnnotationsCheckBox.setObjectName("forceFutureAnnotationsCheckBox") self.gridLayout_9.addWidget(self.forceFutureAnnotationsCheckBox, 3, 0, 1, 1) self.simplifiedTypesCheckBox = QtWidgets.QCheckBox(parent=self.groupBox_10) self.simplifiedTypesCheckBox.setObjectName("simplifiedTypesCheckBox") self.gridLayout_9.addWidget(self.simplifiedTypesCheckBox, 3, 1, 1, 1) + self.mypyInitReturnCheckBox = QtWidgets.QCheckBox(parent=self.groupBox_10) + self.mypyInitReturnCheckBox.setObjectName("mypyInitReturnCheckBox") + self.gridLayout_9.addWidget(self.mypyInitReturnCheckBox, 2, 0, 1, 1) + self.typeIgnoreCheckBox = QtWidgets.QCheckBox(parent=self.groupBox_10) + self.typeIgnoreCheckBox.setObjectName("typeIgnoreCheckBox") + self.gridLayout_9.addWidget(self.typeIgnoreCheckBox, 4, 0, 1, 1) self.verticalLayout_3.addLayout(self.gridLayout_9) self.label_33 = QtWidgets.QLabel(parent=self.groupBox_10) self.label_33.setObjectName("label_33") @@ -787,8 +790,8 @@ self.verticalLayout_13.addWidget(self.buttonBox) self.retranslateUi(CodeStyleCheckerDialog) - self.mainWidget.setCurrentIndex(2) - self.optionsTabWidget.setCurrentIndex(7) + self.mainWidget.setCurrentIndex(0) + self.optionsTabWidget.setCurrentIndex(0) self.repeatCheckBox.toggled['bool'].connect(self.fixIssuesCheckBox.setEnabled) # type: ignore self.repeatCheckBox.toggled['bool'].connect(self.ignoredCheckBox.setEnabled) # type: ignore QtCore.QMetaObject.connectSlotsByName(CodeStyleCheckerDialog) @@ -838,7 +841,8 @@ CodeStyleCheckerDialog.setTabOrder(self.mypyInitReturnCheckBox, self.allowStarArgAnyCheckBox) CodeStyleCheckerDialog.setTabOrder(self.allowStarArgAnyCheckBox, self.forceFutureAnnotationsCheckBox) CodeStyleCheckerDialog.setTabOrder(self.forceFutureAnnotationsCheckBox, self.simplifiedTypesCheckBox) - CodeStyleCheckerDialog.setTabOrder(self.simplifiedTypesCheckBox, self.dispatchDecoratorEdit) + CodeStyleCheckerDialog.setTabOrder(self.simplifiedTypesCheckBox, self.typeIgnoreCheckBox) + CodeStyleCheckerDialog.setTabOrder(self.typeIgnoreCheckBox, self.dispatchDecoratorEdit) CodeStyleCheckerDialog.setTabOrder(self.dispatchDecoratorEdit, self.overloadDecoratorEdit) CodeStyleCheckerDialog.setTabOrder(self.overloadDecoratorEdit, self.exemptedTypingSymbolsEdit) CodeStyleCheckerDialog.setTabOrder(self.exemptedTypingSymbolsEdit, self.tmpDirectoriesEdit) @@ -969,22 +973,24 @@ self.maxAnnotationsComplexitySpinBox.setToolTip(_translate("CodeStyleCheckerDialog", "Enter the maximum type annotation complexity")) self.label_32.setText(_translate("CodeStyleCheckerDialog", "Max. Length:")) self.maxAnnotationsLengthSpinBox.setToolTip(_translate("CodeStyleCheckerDialog", "Enter the maximum type annotation length")) - self.suppressNoneReturningCheckBox.setToolTip(_translate("CodeStyleCheckerDialog", "Select to not report functions without returns or with only bare returns")) - self.suppressNoneReturningCheckBox.setText(_translate("CodeStyleCheckerDialog", "Suppress \'None\' return")) self.suppressDummyArgsCheckBox.setToolTip(_translate("CodeStyleCheckerDialog", "Select to not report dummy (i.e. \'_\') arguments")) self.suppressDummyArgsCheckBox.setText(_translate("CodeStyleCheckerDialog", "Suppress Dummy Arguments")) self.allowUntypedDefsCheckBox.setToolTip(_translate("CodeStyleCheckerDialog", "Select to not report dynamically typed functions")) self.allowUntypedDefsCheckBox.setText(_translate("CodeStyleCheckerDialog", "Allow Untyped Functions")) + self.suppressNoneReturningCheckBox.setToolTip(_translate("CodeStyleCheckerDialog", "Select to not report functions without returns or with only bare returns")) + self.suppressNoneReturningCheckBox.setText(_translate("CodeStyleCheckerDialog", "Suppress \'None\' return")) + self.allowStarArgAnyCheckBox.setToolTip(_translate("CodeStyleCheckerDialog", "Allow dynamically typed *args and **kwargs")) + self.allowStarArgAnyCheckBox.setText(_translate("CodeStyleCheckerDialog", "Allow dynamically typed * Arguments")) self.allowUntypedNestedCheckBox.setToolTip(_translate("CodeStyleCheckerDialog", "Select to not report dynamically typed nested functions")) self.allowUntypedNestedCheckBox.setText(_translate("CodeStyleCheckerDialog", "Allow Untyped Nested Functions")) - self.mypyInitReturnCheckBox.setToolTip(_translate("CodeStyleCheckerDialog", "Select to not report unhinted \'__init__\' return")) - self.mypyInitReturnCheckBox.setText(_translate("CodeStyleCheckerDialog", "Allow Untyped \'__init__\' function")) - self.allowStarArgAnyCheckBox.setToolTip(_translate("CodeStyleCheckerDialog", "Allow dynamically typed *args and **kwargs")) - self.allowStarArgAnyCheckBox.setText(_translate("CodeStyleCheckerDialog", "Allow dynamically typed * Arguments")) self.forceFutureAnnotationsCheckBox.setToolTip(_translate("CodeStyleCheckerDialog", "Enforce the presence of a \'from __future__ import annotations\' statement")) self.forceFutureAnnotationsCheckBox.setText(_translate("CodeStyleCheckerDialog", "Enforce \'__future__\' statement")) self.simplifiedTypesCheckBox.setToolTip(_translate("CodeStyleCheckerDialog", "Verifies <3.10 code with simplified types uses \'from __future__ import annotations\'.")) self.simplifiedTypesCheckBox.setText(_translate("CodeStyleCheckerDialog", "Check use of simplified types")) + self.mypyInitReturnCheckBox.setToolTip(_translate("CodeStyleCheckerDialog", "Select to not report unhinted \'__init__\' return")) + self.mypyInitReturnCheckBox.setText(_translate("CodeStyleCheckerDialog", "Allow Untyped \'__init__\' function")) + self.typeIgnoreCheckBox.setToolTip(_translate("CodeStyleCheckerDialog", "Select to supress errors for functions annotated with a \'type: ignore\' comment.")) + self.typeIgnoreCheckBox.setText(_translate("CodeStyleCheckerDialog", "Respect \'type: ignore\' comments")) self.label_33.setText(_translate("CodeStyleCheckerDialog", "Dispatch Decorators:")) self.dispatchDecoratorEdit.setToolTip(_translate("CodeStyleCheckerDialog", "Enter the list of dispatch decorators separated by comma")) self.label_34.setText(_translate("CodeStyleCheckerDialog", "Overload Decorators:"))