diff --git a/doc/whatsnew/fragments/7767.breaking b/doc/whatsnew/fragments/7767.breaking
new file mode 100644
index 0000000000..bbe9949572
--- /dev/null
+++ b/doc/whatsnew/fragments/7767.breaking
@@ -0,0 +1,4 @@
+Disables placed in a ``try`` block now apply to the ``except`` block.
+Previously, they only happened to do so in the presence of an ``else`` clause.
+
+Refs #7767
diff --git a/doc/whatsnew/fragments/7767.false_positive b/doc/whatsnew/fragments/7767.false_positive
new file mode 100644
index 0000000000..69d7d23846
--- /dev/null
+++ b/doc/whatsnew/fragments/7767.false_positive
@@ -0,0 +1,5 @@
+Fix false negatives and false positives for ``too-many-try-statements``,
+``too-complex``, and ``too-many-branches`` by correctly counting statements
+under a ``try``.
+
+Refs #7767
diff --git a/pylint/checkers/base/basic_checker.py b/pylint/checkers/base/basic_checker.py
index 107e623930..3505ee7082 100644
--- a/pylint/checkers/base/basic_checker.py
+++ b/pylint/checkers/base/basic_checker.py
@@ -272,13 +272,13 @@ class BasicChecker(_BasicChecker):
def __init__(self, linter: PyLinter) -> None:
super().__init__(linter)
- self._tryfinallys: list[nodes.TryFinally] | None = None
+ self._trys: list[nodes.Try]
def open(self) -> None:
"""Initialize visit variables and statistics."""
py_version = self.linter.config.py_version
self._py38_plus = py_version >= (3, 8)
- self._tryfinallys = []
+ self._trys = []
self.linter.stats.reset_node_count()
@utils.only_required_for_messages(
@@ -478,7 +478,7 @@ def visit_expr(self, node: nodes.Expr) -> None:
# side effects), else pointless-statement
if (
isinstance(expr, (nodes.Yield, nodes.Await))
- or (isinstance(node.parent, nodes.TryExcept) and node.parent.body == [node])
+ or (isinstance(node.parent, nodes.Try) and node.parent.body == [node])
or (isinstance(expr, nodes.Const) and expr.value is Ellipsis)
):
return
@@ -768,19 +768,17 @@ def visit_set(self, node: nodes.Set) -> None:
)
values.add(value)
- def visit_tryfinally(self, node: nodes.TryFinally) -> None:
- """Update try...finally flag."""
- assert self._tryfinallys is not None
- self._tryfinallys.append(node)
+ def visit_try(self, node: nodes.Try) -> None:
+ """Update try block flag."""
+ self._trys.append(node)
for final_node in node.finalbody:
for return_node in final_node.nodes_of_class(nodes.Return):
self.add_message("return-in-finally", node=return_node, confidence=HIGH)
- def leave_tryfinally(self, _: nodes.TryFinally) -> None:
- """Update try...finally flag."""
- assert self._tryfinallys is not None
- self._tryfinallys.pop()
+ def leave_try(self, _: nodes.Try) -> None:
+ """Update try block flag."""
+ self._trys.pop()
def _check_unreachable(
self,
@@ -816,8 +814,8 @@ def _check_not_in_finally(
If we find a parent which type is in breaker_classes before
a 'try...finally' block we skip the whole check.
"""
- # if self._tryfinallys is empty, we're not an in try...finally block
- if not self._tryfinallys:
+ # if self._trys is empty, we're not an in try block
+ if not self._trys:
return
# the node could be a grand-grand...-child of the 'try...finally'
_parent = node.parent
diff --git a/pylint/checkers/base/basic_error_checker.py b/pylint/checkers/base/basic_error_checker.py
index b90ddcda5c..5eda75609c 100644
--- a/pylint/checkers/base/basic_error_checker.py
+++ b/pylint/checkers/base/basic_error_checker.py
@@ -496,7 +496,7 @@ def _check_in_loop(
if isinstance(parent, (nodes.ClassDef, nodes.FunctionDef)):
break
if (
- isinstance(parent, nodes.TryFinally)
+ isinstance(parent, nodes.Try)
and node in parent.finalbody
and isinstance(node, nodes.Continue)
and not self._py38_plus
diff --git a/pylint/checkers/design_analysis.py b/pylint/checkers/design_analysis.py
index a9c5a13afd..bea1ef53cc 100644
--- a/pylint/checkers/design_analysis.py
+++ b/pylint/checkers/design_analysis.py
@@ -593,19 +593,16 @@ def visit_default(self, node: nodes.NodeNG) -> None:
if node.is_statement:
self._inc_all_stmts(1)
- def visit_tryexcept(self, node: nodes.TryExcept) -> None:
+ def visit_try(self, node: nodes.Try) -> None:
"""Increments the branches counter."""
branches = len(node.handlers)
if node.orelse:
branches += 1
+ if node.finalbody:
+ branches += 1
self._inc_branch(node, branches)
self._inc_all_stmts(branches)
- def visit_tryfinally(self, node: nodes.TryFinally) -> None:
- """Increments the branches counter."""
- self._inc_branch(node, 2)
- self._inc_all_stmts(2)
-
@only_required_for_messages("too-many-boolean-expressions", "too-many-branches")
def visit_if(self, node: nodes.If) -> None:
"""Increments the branches counter and checks boolean expressions."""
diff --git a/pylint/checkers/exceptions.py b/pylint/checkers/exceptions.py
index 58e491e493..ce3f9367f0 100644
--- a/pylint/checkers/exceptions.py
+++ b/pylint/checkers/exceptions.py
@@ -348,7 +348,7 @@ def _check_misplaced_bare_raise(self, node: nodes.Raise) -> None:
current = node
# Stop when a new scope is generated or when the raise
- # statement is found inside a TryFinally.
+ # statement is found inside a Try.
ignores = (nodes.ExceptHandler, nodes.FunctionDef)
while current and not isinstance(current.parent, ignores):
current = current.parent
@@ -473,7 +473,7 @@ def _check_catching_non_exception(
"catching-non-exception", node=handler.type, args=(exc.name,)
)
- def _check_try_except_raise(self, node: nodes.TryExcept) -> None:
+ def _check_try_except_raise(self, node: nodes.Try) -> None:
def gather_exceptions_from_handler(
handler: nodes.ExceptHandler,
) -> list[InferenceResult] | None:
@@ -556,7 +556,7 @@ def visit_compare(self, node: nodes.Compare) -> None:
"catching-non-exception",
"duplicate-except",
)
- def visit_tryexcept(self, node: nodes.TryExcept) -> None:
+ def visit_try(self, node: nodes.Try) -> None:
"""Check for empty except."""
self._check_try_except_raise(node)
exceptions_classes: list[Any] = []
diff --git a/pylint/checkers/format.py b/pylint/checkers/format.py
index 7295110241..f4de616598 100644
--- a/pylint/checkers/format.py
+++ b/pylint/checkers/format.py
@@ -496,14 +496,6 @@ def visit_default(self, node: nodes.NodeNG) -> None:
prev_sibl = node.previous_sibling()
if prev_sibl is not None:
prev_line = prev_sibl.fromlineno
- # The line on which a 'finally': occurs in a 'try/finally'
- # is not directly represented in the AST. We infer it
- # by taking the last line of the body and adding 1, which
- # should be the line of finally:
- elif (
- isinstance(node.parent, nodes.TryFinally) and node in node.parent.finalbody
- ):
- prev_line = node.parent.body[0].tolineno + 1
elif isinstance(node.parent, nodes.Module):
prev_line = 0
else:
@@ -534,12 +526,6 @@ def _check_multi_statement_line(self, node: nodes.NodeNG, line: int) -> None:
# in with statements.
if isinstance(node, nodes.With):
return
- # For try... except... finally..., the two nodes
- # appear to be on the same line due to how the AST is built.
- if isinstance(node, nodes.TryExcept) and isinstance(
- node.parent, nodes.TryFinally
- ):
- return
if (
isinstance(node.parent, nodes.If)
and not node.parent.orelse
diff --git a/pylint/checkers/imports.py b/pylint/checkers/imports.py
index 3de762aed4..624c1dc0ae 100644
--- a/pylint/checkers/imports.py
+++ b/pylint/checkers/imports.py
@@ -614,8 +614,7 @@ def compute_first_non_import_node(
| nodes.IfExp
| nodes.Assign
| nodes.AssignAttr
- | nodes.TryExcept
- | nodes.TryFinally,
+ | nodes.Try,
) -> None:
# if the node does not contain an import instruction, and if it is the
# first node of the module, keep a track of it (all the import positions
@@ -625,11 +624,7 @@ def compute_first_non_import_node(
return
if not isinstance(node.parent, nodes.Module):
return
- nested_allowed = [nodes.TryExcept, nodes.TryFinally]
- is_nested_allowed = [
- allowed for allowed in nested_allowed if isinstance(node, allowed)
- ]
- if is_nested_allowed and any(
+ if isinstance(node, nodes.Try) and any(
node.nodes_of_class((nodes.Import, nodes.ImportFrom))
):
return
@@ -646,9 +641,7 @@ def compute_first_non_import_node(
return
self._first_non_import_node = node
- visit_tryfinally = (
- visit_tryexcept
- ) = (
+ visit_try = (
visit_assignattr
) = (
visit_assign
@@ -672,7 +665,7 @@ def visit_functiondef(
while not isinstance(root.parent, nodes.Module):
root = root.parent
- if isinstance(root, (nodes.If, nodes.TryFinally, nodes.TryExcept)):
+ if isinstance(root, (nodes.If, nodes.Try)):
if any(root.nodes_of_class((nodes.Import, nodes.ImportFrom))):
return
diff --git a/pylint/checkers/refactoring/refactoring_checker.py b/pylint/checkers/refactoring/refactoring_checker.py
index fb0c3cbc26..088b7c472b 100644
--- a/pylint/checkers/refactoring/refactoring_checker.py
+++ b/pylint/checkers/refactoring/refactoring_checker.py
@@ -27,9 +27,7 @@
from pylint.lint import PyLinter
-NodesWithNestedBlocks = Union[
- nodes.TryExcept, nodes.TryFinally, nodes.While, nodes.For, nodes.If
-]
+NodesWithNestedBlocks = Union[nodes.Try, nodes.While, nodes.For, nodes.If]
KNOWN_INFINITE_ITERATORS = {"itertools.count", "itertools.cycle"}
BUILTIN_EXIT_FUNCS = frozenset(("quit", "exit"))
@@ -71,7 +69,7 @@ def _if_statement_is_always_returning(
def _except_statement_is_always_returning(
- node: nodes.TryExcept, returning_node_class: nodes.NodeNG
+ node: nodes.Try, returning_node_class: nodes.NodeNG
) -> bool:
"""Detect if all except statements return."""
return all(
@@ -653,15 +651,13 @@ def leave_module(self, _: nodes.Module) -> None:
self._init()
@utils.only_required_for_messages("too-many-nested-blocks", "no-else-return")
- def visit_tryexcept(self, node: nodes.TryExcept | nodes.TryFinally) -> None:
+ def visit_try(self, node: nodes.Try) -> None:
self._check_nested_blocks(node)
- if isinstance(node, nodes.TryExcept):
- self._check_superfluous_else_return(node)
- self._check_superfluous_else_raise(node)
+ self._check_superfluous_else_return(node)
+ self._check_superfluous_else_raise(node)
- visit_tryfinally = visit_tryexcept
- visit_while = visit_tryexcept
+ visit_while = visit_try
def _check_redefined_argument_from_local(self, name_node: nodes.AssignName) -> None:
if self._dummy_rgx and self._dummy_rgx.match(name_node.name):
@@ -723,13 +719,11 @@ def visit_with(self, node: nodes.With) -> None:
def _check_superfluous_else(
self,
- node: nodes.If | nodes.TryExcept,
+ node: nodes.If | nodes.Try,
msg_id: str,
returning_node_class: nodes.NodeNG,
) -> None:
- if isinstance(node, nodes.TryExcept) and isinstance(
- node.parent, nodes.TryFinally
- ):
+ if isinstance(node, nodes.Try) and node.finalbody:
# Not interested in try/except/else/finally statements.
return
@@ -745,7 +739,8 @@ def _check_superfluous_else(
isinstance(node, nodes.If)
and _if_statement_is_always_returning(node, returning_node_class)
) or (
- isinstance(node, nodes.TryExcept)
+ isinstance(node, nodes.Try)
+ and not node.finalbody
and _except_statement_is_always_returning(node, returning_node_class)
):
orelse = node.orelse[0]
@@ -1962,7 +1957,7 @@ def _is_node_return_ended(self, node: nodes.NodeNG) -> bool:
return self._is_raise_node_return_ended(node)
if isinstance(node, nodes.If):
return self._is_if_node_return_ended(node)
- if isinstance(node, nodes.TryExcept):
+ if isinstance(node, nodes.Try):
handlers = {
_child
for _child in node.get_children()
diff --git a/pylint/checkers/utils.py b/pylint/checkers/utils.py
index 5e02d45114..edb0aa6c3b 100644
--- a/pylint/checkers/utils.py
+++ b/pylint/checkers/utils.py
@@ -379,8 +379,7 @@ def is_defined_before(var_node: nodes.Name) -> bool:
nodes.For,
nodes.While,
nodes.With,
- nodes.TryExcept,
- nodes.TryFinally,
+ nodes.Try,
nodes.ExceptHandler,
),
):
@@ -988,10 +987,10 @@ def unimplemented_abstract_methods(
def find_try_except_wrapper_node(
node: nodes.NodeNG,
-) -> nodes.ExceptHandler | nodes.TryExcept | None:
- """Return the ExceptHandler or the TryExcept node in which the node is."""
+) -> nodes.ExceptHandler | nodes.Try | None:
+ """Return the ExceptHandler or the Try node in which the node is."""
current = node
- ignores = (nodes.ExceptHandler, nodes.TryExcept)
+ ignores = (nodes.ExceptHandler, nodes.Try)
while current and not isinstance(current.parent, ignores):
current = current.parent
@@ -1002,7 +1001,7 @@ def find_try_except_wrapper_node(
def find_except_wrapper_node_in_scope(
node: nodes.NodeNG,
-) -> nodes.ExceptHandler | nodes.TryExcept | None:
+) -> nodes.ExceptHandler | None:
"""Return the ExceptHandler in which the node is, without going out of scope."""
for current in node.node_ancestors():
if isinstance(current, astroid.scoped_nodes.LocalsDictNodeNG):
@@ -1062,7 +1061,7 @@ def get_exception_handlers(
list: the collection of handlers that are handling the exception or None.
"""
context = find_try_except_wrapper_node(node)
- if isinstance(context, nodes.TryExcept):
+ if isinstance(context, nodes.Try):
return [
handler for handler in context.handlers if error_of_type(handler, exception)
]
@@ -1133,13 +1132,13 @@ def is_node_inside_try_except(node: nodes.Raise) -> bool:
bool: True if the node is inside a try/except statement, False otherwise.
"""
context = find_try_except_wrapper_node(node)
- return isinstance(context, nodes.TryExcept)
+ return isinstance(context, nodes.Try)
def node_ignores_exception(
node: nodes.NodeNG, exception: type[Exception] | str = Exception
) -> bool:
- """Check if the node is in a TryExcept which handles the given exception.
+ """Check if the node is in a Try which handles the given exception.
If the exception is not given, the function is going to look for bare
excepts.
@@ -1918,7 +1917,7 @@ def get_node_first_ancestor_of_type_and_its_child(
descendant visited directly before reaching the sought ancestor.
Useful for extracting whether a statement is guarded by a try, except, or finally
- when searching for a TryFinally ancestor.
+ when searching for a Try ancestor.
"""
child = node
for ancestor in node.node_ancestors():
diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py
index fbe7f5e0b0..b520558db1 100644
--- a/pylint/checkers/variables.py
+++ b/pylint/checkers/variables.py
@@ -689,12 +689,12 @@ def _inferred_to_define_name_raise_or_return(name: str, node: nodes.NodeNG) -> b
that is inferred to define `name`, raise, or return.
"""
# Handle try and with
- if isinstance(node, (nodes.TryExcept, nodes.TryFinally)):
+ if isinstance(node, nodes.Try):
# Allow either a path through try/else/finally OR a path through ALL except handlers
try_except_node = node
- if isinstance(node, nodes.TryFinally):
+ if node.finalbody:
try_except_node = next(
- (child for child in node.nodes_of_class(nodes.TryExcept)),
+ (child for child in node.nodes_of_class(nodes.Try)),
None,
)
handlers = try_except_node.handlers if try_except_node else []
@@ -751,8 +751,7 @@ def _branch_handles_name(name: str, body: Iterable[nodes.NodeNG]) -> bool:
if_body_stmt,
(
nodes.If,
- nodes.TryExcept,
- nodes.TryFinally,
+ nodes.Try,
nodes.With,
nodes.For,
nodes.While,
@@ -855,7 +854,7 @@ def _uncertain_nodes_in_except_blocks(
uncertain_nodes = []
for other_node in found_nodes:
other_node_statement = other_node.statement()
- # Only testing for statements in the except block of TryExcept
+ # Only testing for statements in the except block of Try
closest_except_handler = utils.get_node_first_ancestor_of_type(
other_node_statement, nodes.ExceptHandler
)
@@ -864,7 +863,7 @@ def _uncertain_nodes_in_except_blocks(
# If the other node is in the same scope as this node, assume it executes
if closest_except_handler.parent_of(node):
continue
- closest_try_except: nodes.TryExcept = closest_except_handler.parent
+ closest_try_except: nodes.Try = closest_except_handler.parent
# If the try or else blocks return, assume the except blocks execute.
try_block_returns = any(
isinstance(try_statement, nodes.Return)
@@ -885,14 +884,14 @@ def _uncertain_nodes_in_except_blocks(
# Exception: if this node is in the final block of the other_node_statement,
# it will execute before returning. Assume the except statements are uncertain.
if (
- isinstance(node_statement.parent, nodes.TryFinally)
+ isinstance(node_statement.parent, nodes.Try)
and node_statement in node_statement.parent.finalbody
and closest_try_except.parent.parent_of(node_statement)
):
uncertain_nodes.append(other_node)
- # Or the node_statement is in the else block of the relevant TryExcept
+ # Or the node_statement is in the else block of the relevant Try
elif (
- isinstance(node_statement.parent, nodes.TryExcept)
+ isinstance(node_statement.parent, nodes.Try)
and node_statement in node_statement.parent.orelse
and closest_try_except.parent.parent_of(node_statement)
):
@@ -974,15 +973,17 @@ def _defines_name_raises_or_returns_recursive(
for nested_stmt in stmt.get_children()
):
return True
- if isinstance(
- stmt, nodes.TryExcept
- ) and NamesConsumer._defines_name_raises_or_returns_recursive(name, stmt):
+ if (
+ isinstance(stmt, nodes.Try)
+ and not stmt.finalbody
+ and NamesConsumer._defines_name_raises_or_returns_recursive(name, stmt)
+ ):
return True
return False
@staticmethod
def _check_loop_finishes_via_except(
- node: nodes.NodeNG, other_node_try_except: nodes.TryExcept
+ node: nodes.NodeNG, other_node_try_except: nodes.Try
) -> bool:
"""Check for a specific control flow scenario.
@@ -1026,7 +1027,7 @@ def _check_loop_finishes_via_except(
return False
def _try_in_loop_body(
- other_node_try_except: nodes.TryExcept, loop: nodes.For | nodes.While
+ other_node_try_except: nodes.Try, loop: nodes.For | nodes.While
) -> bool:
"""Return True if `other_node_try_except` is a descendant of `loop`."""
return any(
@@ -1099,7 +1100,7 @@ def _uncertain_nodes_in_try_blocks_when_evaluating_except_blocks(
other_node_try_ancestor,
other_node_try_ancestor_visited_child,
) = utils.get_node_first_ancestor_of_type_and_its_child(
- other_node_statement, nodes.TryExcept
+ other_node_statement, nodes.Try
)
if other_node_try_ancestor is None:
continue
@@ -1131,7 +1132,7 @@ def _uncertain_nodes_in_try_blocks_when_evaluating_finally_blocks(
closest_try_finally_ancestor,
child_of_closest_try_finally_ancestor,
) = utils.get_node_first_ancestor_of_type_and_its_child(
- node_statement, nodes.TryFinally
+ node_statement, nodes.Try
)
if closest_try_finally_ancestor is None:
return uncertain_nodes
@@ -1146,7 +1147,7 @@ def _uncertain_nodes_in_try_blocks_when_evaluating_finally_blocks(
other_node_try_finally_ancestor,
child_of_other_node_try_finally_ancestor,
) = utils.get_node_first_ancestor_of_type_and_its_child(
- other_node_statement, nodes.TryFinally
+ other_node_statement, nodes.Try
)
if other_node_try_finally_ancestor is None:
continue
diff --git a/pylint/extensions/broad_try_clause.py b/pylint/extensions/broad_try_clause.py
index 762055a258..90168909a9 100644
--- a/pylint/extensions/broad_try_clause.py
+++ b/pylint/extensions/broad_try_clause.py
@@ -46,16 +46,18 @@ class BroadTryClauseChecker(checkers.BaseChecker):
),
)
- def _count_statements(self, try_node: nodes.TryExcept | nodes.TryFinally) -> int:
- statement_count = len(try_node.body)
+ def _count_statements(
+ self, node: nodes.For | nodes.If | nodes.Try | nodes.While | nodes.With
+ ) -> int:
+ statement_count = len(node.body)
- for body_node in try_node.body:
+ for body_node in node.body:
if isinstance(body_node, (nodes.For, nodes.If, nodes.While, nodes.With)):
statement_count += self._count_statements(body_node)
return statement_count
- def visit_tryexcept(self, node: nodes.TryExcept | nodes.TryFinally) -> None:
+ def visit_try(self, node: nodes.Try) -> None:
try_clause_statements = self._count_statements(node)
if try_clause_statements > self.linter.config.max_try_statements:
msg = (
@@ -66,8 +68,6 @@ def visit_tryexcept(self, node: nodes.TryExcept | nodes.TryFinally) -> None:
"too-many-try-statements", node.lineno, node=node, args=msg
)
- visit_tryfinally = visit_tryexcept
-
def register(linter: PyLinter) -> None:
linter.register_checker(BroadTryClauseChecker(linter))
diff --git a/pylint/extensions/mccabe.py b/pylint/extensions/mccabe.py
index 604360fb7a..5c4a621d85 100644
--- a/pylint/extensions/mccabe.py
+++ b/pylint/extensions/mccabe.py
@@ -39,7 +39,7 @@
nodes.Await,
]
-_SubGraphNodes = Union[nodes.If, nodes.TryExcept, nodes.For, nodes.While]
+_SubGraphNodes = Union[nodes.If, nodes.Try, nodes.For, nodes.While]
_AppendableNodeT = TypeVar(
"_AppendableNodeT", bound=Union[_StatementNodes, nodes.While, nodes.FunctionDef]
)
diff --git a/pylint/extensions/overlapping_exceptions.py b/pylint/extensions/overlapping_exceptions.py
index ddcf24e7c3..8d35e4ce32 100644
--- a/pylint/extensions/overlapping_exceptions.py
+++ b/pylint/extensions/overlapping_exceptions.py
@@ -37,7 +37,7 @@ class OverlappingExceptionsChecker(checkers.BaseChecker):
options = ()
@utils.only_required_for_messages("overlapping-except")
- def visit_tryexcept(self, node: nodes.TryExcept) -> None:
+ def visit_try(self, node: nodes.Try) -> None:
"""Check for empty except."""
for handler in node.handlers:
if handler.type is None:
diff --git a/pyproject.toml b/pyproject.toml
index 862dbf9bdf..3926a6de41 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/pylint-dev/astroid/issues/1341
- "astroid @ git+https://github.com/pylint-dev/astroid.git@a7ab0880dea776e45c4c7e440298c4041d945e6d",
+ "astroid>=3.0.0a7,<=3.1.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 f6bb6003bd..16b6eb9299 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 @ git+https://github.com/pylint-dev/astroid.git@a7ab0880dea776e45c4c7e440298c4041d945e6d
+astroid==3.0.0a7 # Pinned to a specific version for tests
typing-extensions~=4.7
py~=1.11.0
pytest~=7.4
diff --git a/tests/functional/a/async_functions.py b/tests/functional/a/async_functions.py
index 315055e9ca..75fa684dff 100644
--- a/tests/functional/a/async_functions.py
+++ b/tests/functional/a/async_functions.py
@@ -39,6 +39,8 @@ async def complex_function(this, function, has, more, arguments, than,
return than
try:
return one
+ except TypeError:
+ pass
finally:
pass
if 2:
diff --git a/tests/functional/a/async_functions.txt b/tests/functional/a/async_functions.txt
index 63823cced7..985fddec2d 100644
--- a/tests/functional/a/async_functions.txt
+++ b/tests/functional/a/async_functions.txt
@@ -4,7 +4,7 @@ bad-super-call:22:8:22:31:Class.some_method:Bad first argument 'OtherClass' give
too-many-arguments:26:0:26:26:complex_function:Too many arguments (10/5):UNDEFINED
too-many-branches:26:0:26:26:complex_function:Too many branches (13/12):UNDEFINED
too-many-return-statements:26:0:26:26:complex_function:Too many return statements (10/6):UNDEFINED
-dangerous-default-value:57:0:57:14:func:Dangerous default value [] as argument:UNDEFINED
-duplicate-argument-name:57:18:57:19:func:Duplicate argument name a in function definition:HIGH
-disallowed-name:62:0:62:13:foo:"Disallowed name ""foo""":HIGH
-empty-docstring:62:0:62:13:foo:Empty function docstring:HIGH
+dangerous-default-value:59:0:59:14:func:Dangerous default value [] as argument:UNDEFINED
+duplicate-argument-name:59:18:59:19:func:Duplicate argument name a in function definition:HIGH
+disallowed-name:64:0:64:13:foo:"Disallowed name ""foo""":HIGH
+empty-docstring:64:0:64:13:foo:Empty function docstring:HIGH
diff --git a/tests/functional/ext/broad_try_clause/broad_try_clause_extension.txt b/tests/functional/ext/broad_try_clause/broad_try_clause_extension.txt
index d8d2c3e77c..221d3a4c4d 100644
--- a/tests/functional/ext/broad_try_clause/broad_try_clause_extension.txt
+++ b/tests/functional/ext/broad_try_clause/broad_try_clause_extension.txt
@@ -1,4 +1,4 @@
too-many-try-statements:5:0:10:8::try clause contains 3 statements, expected at most 1:UNDEFINED
too-many-try-statements:12:0:17:8::try clause contains 3 statements, expected at most 1:UNDEFINED
-too-many-try-statements:19:0:25:8::try clause contains 4 statements, expected at most 1:UNDEFINED
+too-many-try-statements:19:0:27:8::try clause contains 4 statements, expected at most 1:UNDEFINED
too-many-try-statements:29:0:44:8::try clause contains 7 statements, expected at most 1:UNDEFINED
diff --git a/tests/functional/ext/mccabe/mccabe.py b/tests/functional/ext/mccabe/mccabe.py
index 92623cd1c1..2c6d57a70b 100644
--- a/tests/functional/ext/mccabe/mccabe.py
+++ b/tests/functional/ext/mccabe/mccabe.py
@@ -140,7 +140,7 @@ def method1(): # [too-complex]
pass
def method2(self, param1): # [too-complex, too-many-branches]
- """McCabe rating: 18"""
+ """McCabe rating: 15"""
if not param1:
pass
pass
@@ -205,7 +205,7 @@ def method2(self, param1): # [too-complex, too-many-branches]
def method3(self): # [too-complex]
- """McCabe rating: 2"""
+ """McCabe rating: 3"""
try:
if True:
pass
diff --git a/tests/functional/ext/mccabe/mccabe.txt b/tests/functional/ext/mccabe/mccabe.txt
index d031943bbd..3ff80e86cd 100644
--- a/tests/functional/ext/mccabe/mccabe.txt
+++ b/tests/functional/ext/mccabe/mccabe.txt
@@ -9,7 +9,7 @@ too-complex:68:0:68:6:f8:'f8' is too complex. The McCabe rating is 4:HIGH
too-complex:80:0:80:6:f9:'f9' is too complex. The McCabe rating is 9:HIGH
too-complex:106:0:106:7:f10:'f10' is too complex. The McCabe rating is 11:HIGH
too-complex:138:4:138:15:MyClass1.method1:'method1' is too complex. The McCabe rating is 1:HIGH
-too-complex:142:4:142:15:MyClass1.method2:'method2' is too complex. The McCabe rating is 18:HIGH
-too-many-branches:142:4:142:15:MyClass1.method2:Too many branches (20/12):UNDEFINED
+too-complex:142:4:142:15:MyClass1.method2:'method2' is too complex. The McCabe rating is 15:HIGH
+too-many-branches:142:4:142:15:MyClass1.method2:Too many branches (19/12):UNDEFINED
too-complex:198:0:204:15::This 'for' is too complex. The McCabe rating is 4:HIGH
-too-complex:207:0:207:11:method3:'method3' is too complex. The McCabe rating is 2:HIGH
+too-complex:207:0:207:11:method3:'method3' is too complex. The McCabe rating is 3:HIGH
diff --git a/tests/functional/t/too/too_many_branches.py b/tests/functional/t/too/too_many_branches.py
index 7b0b068adf..d7a3913e41 100644
--- a/tests/functional/t/too/too_many_branches.py
+++ b/tests/functional/t/too/too_many_branches.py
@@ -16,6 +16,8 @@ def wrong(): # [too-many-branches]
pass
try:
pass
+ except TypeError:
+ pass
finally:
pass
if 2:
diff --git a/tests/functional/u/used/used_before_assignment_issue2615.py b/tests/functional/u/used/used_before_assignment_issue2615.py
index e2e5a4181d..0ab493104e 100644
--- a/tests/functional/u/used/used_before_assignment_issue2615.py
+++ b/tests/functional/u/used/used_before_assignment_issue2615.py
@@ -33,8 +33,8 @@ def nested_except_blocks():
def consecutive_except_blocks():
- """An assignment assumed to execute in one TryExcept should continue to be
- assumed to execute in a consecutive TryExcept.
+ """An assignment assumed to execute in one Try should continue to be
+ assumed to execute in a consecutive Try.
"""
try:
res = 100
diff --git a/tests/lint/unittest_lint.py b/tests/lint/unittest_lint.py
index 918533795d..914b2efbbd 100644
--- a/tests/lint/unittest_lint.py
+++ b/tests/lint/unittest_lint.py
@@ -311,7 +311,7 @@ def test_enable_message_block(initialized_linter: PyLinter) -> None:
# meth6
assert not linter.is_message_enabled("E1101", 57)
assert linter.is_message_enabled("E1101", 61)
- assert not linter.is_message_enabled("E1101", 64)
+ assert linter.is_message_enabled("E1101", 64)
assert not linter.is_message_enabled("E1101", 66)
assert linter.is_message_enabled("E0602", 57)
diff --git a/tests/pyreverse/functional/class_diagrams/colorized_output/colorized.puml b/tests/pyreverse/functional/class_diagrams/colorized_output/colorized.puml
index 10575159d8..dc9b7034ba 100644
--- a/tests/pyreverse/functional/class_diagrams/colorized_output/colorized.puml
+++ b/tests/pyreverse/functional/class_diagrams/colorized_output/colorized.puml
@@ -20,7 +20,7 @@ class "ExceptionsChecker" as pylint.checkers.exceptions.ExceptionsChecker #44BB9
visit_binop(node: nodes.BinOp) -> None
visit_compare(node: nodes.Compare) -> None
visit_raise(node: nodes.Raise) -> None
- visit_tryexcept(node: nodes.TryExcept) -> None
+ visit_try(node: nodes.Try) -> None
}
class "StdlibChecker" as pylint.checkers.stdlib.StdlibChecker #44BB99 {
msgs : dict[str, MessageDefinitionTuple]
diff --git a/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.dot b/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.dot
index 7263cf8f52..84c8142a35 100644
--- a/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.dot
+++ b/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.dot
@@ -3,7 +3,7 @@ rankdir=BT
charset="utf-8"
"custom_colors.CheckerCollector" [color="red", fontcolor="black", label=<{CheckerCollector|checker1
checker2
checker3
|}>, shape="record", style="filled"];
"pylint.extensions.check_elif.ElseifUsedChecker" [color="#44BB88", fontcolor="black", label=<{ElseifUsedChecker|msgs : dict
name : str
|leave_module(_: nodes.Module): None
process_tokens(tokens: list[TokenInfo]): None
visit_if(node: nodes.If): None
}>, shape="record", style="filled"];
-"pylint.checkers.exceptions.ExceptionsChecker" [color="yellow", fontcolor="black", label=<{ExceptionsChecker|msgs : dict
name : str
options : tuple
|open(): None
visit_binop(node: nodes.BinOp): None
visit_compare(node: nodes.Compare): None
visit_raise(node: nodes.Raise): None
visit_tryexcept(node: nodes.TryExcept): None
}>, shape="record", style="filled"];
+"pylint.checkers.exceptions.ExceptionsChecker" [color="yellow", fontcolor="black", label=<{ExceptionsChecker|msgs : dict
name : str
options : tuple
|open(): None
visit_binop(node: nodes.BinOp): None
visit_compare(node: nodes.Compare): None
visit_raise(node: nodes.Raise): None
visit_try(node: nodes.Try): None
}>, shape="record", style="filled"];
"pylint.checkers.stdlib.StdlibChecker" [color="yellow", fontcolor="black", label=<{StdlibChecker|msgs : dict[str, MessageDefinitionTuple]
name : str
|deprecated_arguments(method: str): tuple[tuple[int \| None, str], ...]
deprecated_classes(module: str): Iterable[str]
deprecated_decorators(): Iterable[str]
deprecated_methods(): set[str]
visit_boolop(node: nodes.BoolOp): None
visit_call(node: nodes.Call): None
visit_functiondef(node: nodes.FunctionDef): None
visit_if(node: nodes.If): None
visit_ifexp(node: nodes.IfExp): None
visit_unaryop(node: nodes.UnaryOp): None
}>, shape="record", style="filled"];
"pylint.checkers.exceptions.ExceptionsChecker" -> "custom_colors.CheckerCollector" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="checker1", style="solid"];
"pylint.checkers.stdlib.StdlibChecker" -> "custom_colors.CheckerCollector" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="checker3", style="solid"];
diff --git a/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.puml b/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.puml
index f2cea9f63e..7119900639 100644
--- a/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.puml
+++ b/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.puml
@@ -20,7 +20,7 @@ class "ExceptionsChecker" as pylint.checkers.exceptions.ExceptionsChecker #yello
visit_binop(node: nodes.BinOp) -> None
visit_compare(node: nodes.Compare) -> None
visit_raise(node: nodes.Raise) -> None
- visit_tryexcept(node: nodes.TryExcept) -> None
+ visit_try(node: nodes.Try) -> None
}
class "StdlibChecker" as pylint.checkers.stdlib.StdlibChecker #yellow {
msgs : dict[str, MessageDefinitionTuple]