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]