summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/data/messages/p/pointless-exception-statement/bad.py1
-rw-r--r--doc/data/messages/p/pointless-exception-statement/good.py1
-rw-r--r--doc/user_guide/checkers/features.rst3
-rw-r--r--doc/user_guide/messages/messages_overview.rst1
-rw-r--r--doc/whatsnew/fragments/3110.new_check4
-rw-r--r--pylint/checkers/base/basic_checker.py17
-rw-r--r--pyproject.toml2
-rw-r--r--requirements_test_min.txt2
-rw-r--r--tests/functional/c/ctor_arguments.py2
-rw-r--r--tests/functional/c/ctor_arguments.txt2
-rw-r--r--tests/functional/s/statement_without_effect.py17
-rw-r--r--tests/functional/s/statement_without_effect.txt2
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