diff options
author | James Addison <55152140+jayaddison@users.noreply.github.com> | 2023-01-07 11:53:20 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-07 12:53:20 +0100 |
commit | 89a20e2ccdb2927ac370f7c6663fc83318988e10 (patch) | |
tree | ab03368654e560fb76eb977dac31d90f32bb0bdc | |
parent | 56121344f6c9c223d8e4477c0cdb58c46c840b4b (diff) | |
download | pylint-git-89a20e2ccdb2927ac370f7c6663fc83318988e10.tar.gz |
Add new check "pointless-exception-statement" (#7939)
Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com>
-rw-r--r-- | doc/data/messages/p/pointless-exception-statement/bad.py | 1 | ||||
-rw-r--r-- | doc/data/messages/p/pointless-exception-statement/good.py | 1 | ||||
-rw-r--r-- | doc/user_guide/checkers/features.rst | 3 | ||||
-rw-r--r-- | doc/user_guide/messages/messages_overview.rst | 1 | ||||
-rw-r--r-- | doc/whatsnew/fragments/3110.new_check | 4 | ||||
-rw-r--r-- | pylint/checkers/base/basic_checker.py | 17 | ||||
-rw-r--r-- | pyproject.toml | 2 | ||||
-rw-r--r-- | requirements_test_min.txt | 2 | ||||
-rw-r--r-- | tests/functional/c/ctor_arguments.py | 2 | ||||
-rw-r--r-- | tests/functional/c/ctor_arguments.txt | 2 | ||||
-rw-r--r-- | tests/functional/s/statement_without_effect.py | 17 | ||||
-rw-r--r-- | tests/functional/s/statement_without_effect.txt | 2 |
12 files changed, 50 insertions, 4 deletions
diff --git a/doc/data/messages/p/pointless-exception-statement/bad.py b/doc/data/messages/p/pointless-exception-statement/bad.py new file mode 100644 index 000000000..3dcd1dc00 --- /dev/null +++ b/doc/data/messages/p/pointless-exception-statement/bad.py @@ -0,0 +1 @@ +Exception("This exception is a statement.") # [pointless-exception-statement] diff --git a/doc/data/messages/p/pointless-exception-statement/good.py b/doc/data/messages/p/pointless-exception-statement/good.py new file mode 100644 index 000000000..718388c87 --- /dev/null +++ b/doc/data/messages/p/pointless-exception-statement/good.py @@ -0,0 +1 @@ +raise Exception("This will raise.") diff --git a/doc/user_guide/checkers/features.rst b/doc/user_guide/checkers/features.rst index bbcd0ae58..3992d93d4 100644 --- a/doc/user_guide/checkers/features.rst +++ b/doc/user_guide/checkers/features.rst @@ -147,6 +147,9 @@ Basic checker Messages This is a particular case of W0104 with its own message so you can easily disable it if you're using those strings as documentation, instead of comments. +:pointless-exception-statement (W0132): *Exception statement has no effect* + Used when an exception is created without being assigned, raised or returned + for subsequent use elsewhere. :unnecessary-pass (W0107): *Unnecessary pass statement* Used when a "pass" statement that can be avoided is encountered. :unreachable (W0101): *Unreachable code* diff --git a/doc/user_guide/messages/messages_overview.rst b/doc/user_guide/messages/messages_overview.rst index 74b8dbb8a..648b4b373 100644 --- a/doc/user_guide/messages/messages_overview.rst +++ b/doc/user_guide/messages/messages_overview.rst @@ -287,6 +287,7 @@ All messages in the warning category: warning/overlapping-except warning/overridden-final-method warning/pointless-statement + warning/pointless-exception-statement warning/pointless-string-statement warning/possibly-unused-variable warning/preferred-module diff --git a/doc/whatsnew/fragments/3110.new_check b/doc/whatsnew/fragments/3110.new_check new file mode 100644 index 000000000..f4ae365ed --- /dev/null +++ b/doc/whatsnew/fragments/3110.new_check @@ -0,0 +1,4 @@ +Adds a ``pointless-exception-statement`` check that emits a warning when an +Exception is created and not assigned, raised or returned. + +Refs #3110 diff --git a/pylint/checkers/base/basic_checker.py b/pylint/checkers/base/basic_checker.py index a91291c91..67be99a8c 100644 --- a/pylint/checkers/base/basic_checker.py +++ b/pylint/checkers/base/basic_checker.py @@ -13,7 +13,7 @@ from collections.abc import Iterator from typing import TYPE_CHECKING, cast import astroid -from astroid import nodes +from astroid import nodes, objects from pylint import utils as lint_utils from pylint.checkers import BaseChecker, utils @@ -258,6 +258,12 @@ class BasicChecker(_BasicChecker): "Emitted if named expression is used to do a regular assignment " "outside a context like if, for, while, or a comprehension.", ), + "W0133": ( + "Exception statement has no effect", + "pointless-exception-statement", + "Used when an exception is created without being assigned, raised or returned " + "for subsequent use elsewhere.", + ), } reports = (("RP0101", "Statistics by type", report_by_type_stats),) @@ -417,6 +423,7 @@ class BasicChecker(_BasicChecker): @utils.only_required_for_messages( "pointless-statement", + "pointless-exception-statement", "pointless-string-statement", "expression-not-assigned", "named-expr-without-context", @@ -444,6 +451,14 @@ class BasicChecker(_BasicChecker): self.add_message("pointless-string-statement", node=node) return + # Warn W0133 for exceptions that are used as statements + if isinstance(expr, nodes.Call): + inferred = utils.safe_infer(expr) + if isinstance(inferred, objects.ExceptionInstance): + self.add_message( + "pointless-exception-statement", node=node, confidence=INFERENCE + ) + # Ignore if this is : # * a direct function call # * the unique child of a try/except body diff --git a/pyproject.toml b/pyproject.toml index 88733b5e3..98514b23e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,7 @@ dependencies = [ # Also upgrade requirements_test_min.txt. # Pinned to dev of second minor update to allow editable installs and fix primer issues, # see https://github.com/PyCQA/astroid/issues/1341 - "astroid>=2.12.13,<=2.14.0-dev0", + "astroid>=2.12.14,<=2.14.0-dev0", "isort>=4.2.5,<6", "mccabe>=0.6,<0.8", "tomli>=1.1.0;python_version<'3.11'", diff --git a/requirements_test_min.txt b/requirements_test_min.txt index c4099a797..391f47858 100644 --- a/requirements_test_min.txt +++ b/requirements_test_min.txt @@ -1,6 +1,6 @@ -e .[testutils,spelling] # astroid dependency is also defined in pyproject.toml -astroid==2.12.13 # Pinned to a specific version for tests +astroid==2.12.14 # Pinned to a specific version for tests typing-extensions~=4.4 py~=1.11.0 pytest~=7.2 diff --git a/tests/functional/c/ctor_arguments.py b/tests/functional/c/ctor_arguments.py index d87732f1d..4ed96c2d3 100644 --- a/tests/functional/c/ctor_arguments.py +++ b/tests/functional/c/ctor_arguments.py @@ -82,7 +82,7 @@ class BuiltinExc(Exception): def __init__(self, val=True): self.val = val -BuiltinExc(42, 24, badarg=1) # [too-many-function-args,unexpected-keyword-arg] +BuiltinExc(42, 24, badarg=1) # [line-too-long,pointless-exception-statement,too-many-function-args,unexpected-keyword-arg] class Clsmethod: diff --git a/tests/functional/c/ctor_arguments.txt b/tests/functional/c/ctor_arguments.txt index 286a56bd7..f096eed4e 100644 --- a/tests/functional/c/ctor_arguments.txt +++ b/tests/functional/c/ctor_arguments.txt @@ -15,6 +15,8 @@ too-many-function-args:60:0:60:30::Too many positional arguments for constructor too-many-function-args:63:0:63:17::Too many positional arguments for constructor call:UNDEFINED no-value-for-parameter:64:0:64:15::No value for argument 'first_argument' in constructor call:UNDEFINED unexpected-keyword-arg:64:0:64:15::Unexpected keyword argument 'one' in constructor call:UNDEFINED +line-too-long:85:0::::Line too long (122/100):UNDEFINED +pointless-exception-statement:85:0:85:28::Exception statement has no effect:INFERENCE too-many-function-args:85:0:85:28::Too many positional arguments for constructor call:UNDEFINED unexpected-keyword-arg:85:0:85:28::Unexpected keyword argument 'badarg' in constructor call:UNDEFINED too-many-function-args:95:15:95:30:Clsmethod.from_nothing:Too many positional arguments for constructor call:UNDEFINED diff --git a/tests/functional/s/statement_without_effect.py b/tests/functional/s/statement_without_effect.py index 60694ff96..0c6586e36 100644 --- a/tests/functional/s/statement_without_effect.py +++ b/tests/functional/s/statement_without_effect.py @@ -73,3 +73,20 @@ def ellipsis(): class EllipsisBody: """Test that an Ellipsis as a body does not trigger the error""" ... + + +def assigned_exception(): + """Test that an assigned exception is not flagged as a pointless statement""" + exception = ValueError("one") + return exception, ValueError("two") + + +def raised_exception(): + """Test that a raised exception is not flagged as a pointless statement""" + raise ValueError() + + +def unraised_exception(): + """Test that instantiating but not raising an exception is flagged as a pointless statement""" + ValueError("pointless-statement") # [pointless-exception-statement] + ValueError(to_be()) # [pointless-exception-statement] diff --git a/tests/functional/s/statement_without_effect.txt b/tests/functional/s/statement_without_effect.txt index 6bebf450b..39f86f33b 100644 --- a/tests/functional/s/statement_without_effect.txt +++ b/tests/functional/s/statement_without_effect.txt @@ -10,3 +10,5 @@ expression-not-assigned:32:0:32:22::"Expression ""to_be() or not to_be()"" is as expression-not-assigned:33:0:33:13::"Expression ""to_be().title"" is assigned to nothing":UNDEFINED pointless-string-statement:58:8:58:43:ClassLevelAttributeTest.__init__:String statement has no effect:UNDEFINED pointless-string-statement:65:8:65:55:ClassLevelAttributeTest.test:String statement has no effect:UNDEFINED +pointless-exception-statement:91:4:91:37:unraised_exception:Exception statement has no effect:INFERENCE +pointless-exception-statement:92:4:92:23:unraised_exception:Exception statement has no effect:INFERENCE |