From 142fd78d6751b88a87c1eb507ee78ec42f91e776 Mon Sep 17 00:00:00 2001 From: akamat10 Date: Thu, 12 Sep 2024 23:17:29 -0400 Subject: [PATCH 1/7] Remove old-style classes code, remove check for new-style class (Python 3 is only new style classes) --- pylint/checkers/classes/class_checker.py | 2 +- pylint/checkers/exceptions.py | 15 ++- pylint/checkers/newstyle.py | 96 +++++++++---------- .../invalid_exceptions_raised.py | 18 +--- .../invalid_exceptions_raised.txt | 20 ++-- .../r/raising/raising_non_exception.txt | 2 +- 6 files changed, 66 insertions(+), 87 deletions(-) diff --git a/pylint/checkers/classes/class_checker.py b/pylint/checkers/classes/class_checker.py index ced5048eb1..0caeeadcdf 100644 --- a/pylint/checkers/classes/class_checker.py +++ b/pylint/checkers/classes/class_checker.py @@ -1778,7 +1778,7 @@ def _check_in_slots(self, node: nodes.AssignAttr) -> None: klass = inferred._proxied if not has_known_bases(klass): return - if "__slots__" not in klass.locals or not klass.newstyle: + if "__slots__" not in klass.locals: return # If `__setattr__` is defined on the class, then we can't reason about # what will happen when assigning to an attribute. diff --git a/pylint/checkers/exceptions.py b/pylint/checkers/exceptions.py index 688dc829a0..0fcc5cc478 100644 --- a/pylint/checkers/exceptions.py +++ b/pylint/checkers/exceptions.py @@ -92,9 +92,9 @@ def _is_raising(body: list[nodes.NodeNG]) -> bool: {"old_names": [("E0703", "bad-exception-context")]}, ), "E0710": ( - "Raising a new style class which doesn't inherit from BaseException", + "Raising a class which doesn't inherit from BaseException", "raising-non-exception", - "Used when a new style class which doesn't inherit from " + "Used when a class which doesn't inherit from " "BaseException is raised.", ), "E0711": ( @@ -262,12 +262,11 @@ def visit_instance(self, instance: objects.ExceptionInstance) -> None: def visit_classdef(self, node: nodes.ClassDef) -> None: if not utils.inherit_from_std_ex(node) and utils.has_known_bases(node): - if node.newstyle: - self._checker.add_message( - "raising-non-exception", - node=self._node, - confidence=INFERENCE, - ) + self._checker.add_message( + "raising-non-exception", + node=self._node, + confidence=INFERENCE, + ) def visit_tuple(self, _: nodes.Tuple) -> None: self._checker.add_message( diff --git a/pylint/checkers/newstyle.py b/pylint/checkers/newstyle.py index 0c2c559fe8..cafcbee07a 100644 --- a/pylint/checkers/newstyle.py +++ b/pylint/checkers/newstyle.py @@ -72,55 +72,53 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None: ): continue - # super should not be used on an old style class - if klass.newstyle or not has_known_bases(klass): - # super first arg should not be the class - if not call.args: - continue - - # calling super(type(self), self) can lead to recursion loop - # in derived classes - arg0 = call.args[0] - if ( - isinstance(arg0, nodes.Call) - and isinstance(arg0.func, nodes.Name) - and arg0.func.name == "type" - ): - self.add_message("bad-super-call", node=call, args=("type",)) - continue - - # calling super(self.__class__, self) can lead to recursion loop - # in derived classes - if ( - len(call.args) >= 2 - and isinstance(call.args[1], nodes.Name) - and call.args[1].name == "self" - and isinstance(arg0, nodes.Attribute) - and arg0.attrname == "__class__" - ): - self.add_message( - "bad-super-call", node=call, args=("self.__class__",) - ) - continue - - try: - supcls = call.args and next(call.args[0].infer(), None) - except astroid.InferenceError: - continue - - # If the supcls is in the ancestors of klass super can be used to skip - # a step in the mro() and get a method from a higher parent - if klass is not supcls and all(i != supcls for i in klass.ancestors()): - name = None - # if supcls is not Uninferable, then supcls was inferred - # and use its name. Otherwise, try to look - # for call.args[0].name - if supcls: - name = supcls.name - elif call.args and hasattr(call.args[0], "name"): - name = call.args[0].name - if name: - self.add_message("bad-super-call", node=call, args=(name,)) + # super first arg should not be the class + if not call.args: + continue + + # calling super(type(self), self) can lead to recursion loop + # in derived classes + arg0 = call.args[0] + if ( + isinstance(arg0, nodes.Call) + and isinstance(arg0.func, nodes.Name) + and arg0.func.name == "type" + ): + self.add_message("bad-super-call", node=call, args=("type",)) + continue + + # calling super(self.__class__, self) can lead to recursion loop + # in derived classes + if ( + len(call.args) >= 2 + and isinstance(call.args[1], nodes.Name) + and call.args[1].name == "self" + and isinstance(arg0, nodes.Attribute) + and arg0.attrname == "__class__" + ): + self.add_message( + "bad-super-call", node=call, args=("self.__class__",) + ) + continue + + try: + supcls = call.args and next(call.args[0].infer(), None) + except astroid.InferenceError: + continue + + # If the supcls is in the ancestors of klass super can be used to skip + # a step in the mro() and get a method from a higher parent + if klass is not supcls and all(i != supcls for i in klass.ancestors()): + name = None + # if supcls is not Uninferable, then supcls was inferred + # and use its name. Otherwise, try to look + # for call.args[0].name + if supcls: + name = supcls.name + elif call.args and hasattr(call.args[0], "name"): + name = call.args[0].name + if name: + self.add_message("bad-super-call", node=call, args=(name,)) visit_asyncfunctiondef = visit_functiondef diff --git a/tests/functional/i/invalid/invalid_exceptions/invalid_exceptions_raised.py b/tests/functional/i/invalid/invalid_exceptions/invalid_exceptions_raised.py index aa37a45306..3189fb8f44 100644 --- a/tests/functional/i/invalid/invalid_exceptions/invalid_exceptions_raised.py +++ b/tests/functional/i/invalid/invalid_exceptions/invalid_exceptions_raised.py @@ -1,17 +1,13 @@ # pylint:disable=too-few-public-methods,import-error,missing-docstring, not-callable, import-outside-toplevel -"""test pb with exceptions and old/new style classes""" +"""test pb with exceptions and classes""" class ValidException(Exception): """Valid Exception.""" -class OldStyleClass: - """Not an exception.""" - class NewStyleClass: """Not an exception.""" - def good_case(): """raise""" raise ValidException('hop') @@ -31,22 +27,10 @@ def good_case3(): import io raise io.BlockingIOError -def bad_case0(): - """raise""" - # +2:<3.0:[nonstandard-exception] - # +1:>=3.0:[raising-non-exception] - raise OldStyleClass('hop') - def bad_case1(): """raise""" raise NewStyleClass() # [raising-non-exception] -def bad_case2(): - """raise""" - # +2:<3.0:[nonstandard-exception] - # +1:>=3.0:[raising-non-exception] - raise OldStyleClass('hop') - def bad_case3(): """raise""" raise NewStyleClass # [raising-non-exception] diff --git a/tests/functional/i/invalid/invalid_exceptions/invalid_exceptions_raised.txt b/tests/functional/i/invalid/invalid_exceptions/invalid_exceptions_raised.txt index f2ccd8a052..863e5baf37 100644 --- a/tests/functional/i/invalid/invalid_exceptions/invalid_exceptions_raised.txt +++ b/tests/functional/i/invalid/invalid_exceptions/invalid_exceptions_raised.txt @@ -1,11 +1,9 @@ -raising-non-exception:38:4:38:30:bad_case0:Raising a new style class which doesn't inherit from BaseException:INFERENCE -raising-non-exception:42:4:42:25:bad_case1:Raising a new style class which doesn't inherit from BaseException:INFERENCE -raising-non-exception:48:4:48:30:bad_case2:Raising a new style class which doesn't inherit from BaseException:INFERENCE -raising-non-exception:52:4:52:23:bad_case3:Raising a new style class which doesn't inherit from BaseException:INFERENCE -notimplemented-raised:56:4:56:31:bad_case4:NotImplemented raised - should raise NotImplementedError:HIGH -raising-bad-type:60:4:60:11:bad_case5:Raising int while only classes or instances are allowed:INFERENCE -raising-bad-type:64:4:64:14:bad_case6:Raising NoneType while only classes or instances are allowed:INFERENCE -raising-non-exception:68:4:68:14:bad_case7:Raising a new style class which doesn't inherit from BaseException:INFERENCE -raising-non-exception:72:4:72:15:bad_case8:Raising a new style class which doesn't inherit from BaseException:INFERENCE -raising-non-exception:76:4:76:14:bad_case9:Raising a new style class which doesn't inherit from BaseException:INFERENCE -raising-bad-type:110:4:110:18:bad_case10:Raising str while only classes or instances are allowed:INFERENCE +raising-non-exception:32:4:32:25:bad_case1:Raising a class which doesn't inherit from BaseException:INFERENCE +raising-non-exception:36:4:36:23:bad_case3:Raising a class which doesn't inherit from BaseException:INFERENCE +notimplemented-raised:40:4:40:31:bad_case4:NotImplemented raised - should raise NotImplementedError:HIGH +raising-bad-type:44:4:44:11:bad_case5:Raising int while only classes or instances are allowed:INFERENCE +raising-bad-type:48:4:48:14:bad_case6:Raising NoneType while only classes or instances are allowed:INFERENCE +raising-non-exception:52:4:52:14:bad_case7:Raising a class which doesn't inherit from BaseException:INFERENCE +raising-non-exception:56:4:56:15:bad_case8:Raising a class which doesn't inherit from BaseException:INFERENCE +raising-non-exception:60:4:60:14:bad_case9:Raising a class which doesn't inherit from BaseException:INFERENCE +raising-bad-type:94:4:94:18:bad_case10:Raising str while only classes or instances are allowed:INFERENCE diff --git a/tests/functional/r/raising/raising_non_exception.txt b/tests/functional/r/raising/raising_non_exception.txt index 5cab168463..86c4f70b1a 100644 --- a/tests/functional/r/raising/raising_non_exception.txt +++ b/tests/functional/r/raising/raising_non_exception.txt @@ -1 +1 @@ -raising-non-exception:13:0:13:22::Raising a new style class which doesn't inherit from BaseException:INFERENCE +raising-non-exception:13:0:13:22::Raising a class which doesn't inherit from BaseException:INFERENCE From 414791bc7a4937c57229da26b39f94748a4f6022 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2024 03:31:17 +0000 Subject: [PATCH 2/7] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- pylint/checkers/exceptions.py | 3 +-- pylint/checkers/newstyle.py | 10 ++-------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/pylint/checkers/exceptions.py b/pylint/checkers/exceptions.py index 0fcc5cc478..ddbd0af6b2 100644 --- a/pylint/checkers/exceptions.py +++ b/pylint/checkers/exceptions.py @@ -94,8 +94,7 @@ def _is_raising(body: list[nodes.NodeNG]) -> bool: "E0710": ( "Raising a class which doesn't inherit from BaseException", "raising-non-exception", - "Used when a class which doesn't inherit from " - "BaseException is raised.", + "Used when a class which doesn't inherit from " "BaseException is raised.", ), "E0711": ( "NotImplemented raised - should raise NotImplementedError", diff --git a/pylint/checkers/newstyle.py b/pylint/checkers/newstyle.py index cafcbee07a..920c8cc41e 100644 --- a/pylint/checkers/newstyle.py +++ b/pylint/checkers/newstyle.py @@ -12,11 +12,7 @@ from astroid import nodes from pylint.checkers import BaseChecker -from pylint.checkers.utils import ( - has_known_bases, - node_frame_class, - only_required_for_messages, -) +from pylint.checkers.utils import node_frame_class, only_required_for_messages from pylint.typing import MessageDefinitionTuple if TYPE_CHECKING: @@ -96,9 +92,7 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None: and isinstance(arg0, nodes.Attribute) and arg0.attrname == "__class__" ): - self.add_message( - "bad-super-call", node=call, args=("self.__class__",) - ) + self.add_message("bad-super-call", node=call, args=("self.__class__",)) continue try: From a7c25f75f353d21fa6dc2d9f747dfb84ee775882 Mon Sep 17 00:00:00 2001 From: akamat10 Date: Thu, 12 Sep 2024 23:35:09 -0400 Subject: [PATCH 3/7] Update changelog --- doc/whatsnew/fragments/9925.internal.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/whatsnew/fragments/9925.internal.rst diff --git a/doc/whatsnew/fragments/9925.internal.rst b/doc/whatsnew/fragments/9925.internal.rst new file mode 100644 index 0000000000..1cb4e64bf0 --- /dev/null +++ b/doc/whatsnew/fragments/9925.internal.rst @@ -0,0 +1 @@ +Remove old-style classes (Python 2) code and remove check for new-style class since everything is new-style in Python 3. Updated doc for exception checker to remove reference to new style class. From f26e88887b806c8b1224e83e095f40d117663f20 Mon Sep 17 00:00:00 2001 From: akamat10 Date: Mon, 16 Sep 2024 09:14:23 -0400 Subject: [PATCH 4/7] Fix pylint warning --- pylint/checkers/exceptions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylint/checkers/exceptions.py b/pylint/checkers/exceptions.py index ddbd0af6b2..a503000560 100644 --- a/pylint/checkers/exceptions.py +++ b/pylint/checkers/exceptions.py @@ -94,7 +94,7 @@ def _is_raising(body: list[nodes.NodeNG]) -> bool: "E0710": ( "Raising a class which doesn't inherit from BaseException", "raising-non-exception", - "Used when a class which doesn't inherit from " "BaseException is raised.", + "Used when a class which doesn't inherit from BaseException is raised.", ), "E0711": ( "NotImplemented raised - should raise NotImplementedError", From 54f94d857c57df8b639a7e542788aca3585040ba Mon Sep 17 00:00:00 2001 From: akamat10 Date: Mon, 16 Sep 2024 09:23:22 -0400 Subject: [PATCH 5/7] Fix fragment --- doc/whatsnew/fragments/9925.internal.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/whatsnew/fragments/9925.internal.rst b/doc/whatsnew/fragments/9925.internal.rst index 1cb4e64bf0..145fe4a947 100644 --- a/doc/whatsnew/fragments/9925.internal.rst +++ b/doc/whatsnew/fragments/9925.internal.rst @@ -1 +1,3 @@ Remove old-style classes (Python 2) code and remove check for new-style class since everything is new-style in Python 3. Updated doc for exception checker to remove reference to new style class. + +Refs #9925 From b372a3fc89d0ed22c79b351ade7a9739e5ca2ccc Mon Sep 17 00:00:00 2001 From: akamat10 Date: Mon, 16 Sep 2024 09:28:02 -0400 Subject: [PATCH 6/7] Fix fragment name --- doc/whatsnew/fragments/{9925.internal.rst => 9925.internal} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename doc/whatsnew/fragments/{9925.internal.rst => 9925.internal} (100%) diff --git a/doc/whatsnew/fragments/9925.internal.rst b/doc/whatsnew/fragments/9925.internal similarity index 100% rename from doc/whatsnew/fragments/9925.internal.rst rename to doc/whatsnew/fragments/9925.internal From ededf779e97d20820bc4ff50959c1d374d6a2b2e Mon Sep 17 00:00:00 2001 From: akamat10 Date: Mon, 16 Sep 2024 20:57:26 -0400 Subject: [PATCH 7/7] update rst for document update --- doc/user_guide/checkers/features.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/user_guide/checkers/features.rst b/doc/user_guide/checkers/features.rst index fd7f07d716..3c92594e42 100644 --- a/doc/user_guide/checkers/features.rst +++ b/doc/user_guide/checkers/features.rst @@ -474,9 +474,8 @@ Exceptions checker Messages :raising-bad-type (E0702): *Raising %s while only classes or instances are allowed* Used when something which is neither a class nor an instance is raised (i.e. a `TypeError` will be raised). -:raising-non-exception (E0710): *Raising a new style class which doesn't inherit from BaseException* - Used when a new style class which doesn't inherit from BaseException is - raised. +:raising-non-exception (E0710): *Raising a class which doesn't inherit from BaseException* + Used when a class which doesn't inherit from BaseException is raised. :misplaced-bare-raise (E0704): *The raise statement is not inside an except clause* Used when a bare raise is not used inside an except clause. This generates an error, since there are no active exceptions to be reraised. An exception to