From 8eb7ff153e951f69b4d1ff3cbddc367c797c0aa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Noord?= <13665637+DanielNoord@users.noreply.github.com> Date: Sat, 23 Oct 2021 20:54:39 +0200 Subject: Fix regression for ``_is_only_type_assignment`` (#5163) * Fix regression for ``_is_only_type_assignment`` This closes #5162 * Remove references to `name` * Better tests for assignment * Move walrus tests to different file * Fix tests with incorrect typing * Update typing of `defstmt` Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com> --- pylint/checkers/variables.py | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'pylint') diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py index c8d1f4f5d..bbcf855a3 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -1571,18 +1571,42 @@ class VariablesChecker(BaseChecker): return maybee0601, annotation_return, use_outer_definition + # pylint: disable-next=fixme + # TODO: The typing of `NodeNG.statement()` in astroid is non-specific + # After this has been updated the typing of `defstmt` should reflect this + # See: https://github.com/PyCQA/astroid/pull/1217 @staticmethod - def _is_only_type_assignment(node: nodes.Name, defstmt: nodes.Statement) -> bool: + def _is_only_type_assignment(node: nodes.Name, defstmt: nodes.NodeNG) -> bool: """Check if variable only gets assigned a type and never a value""" if not isinstance(defstmt, nodes.AnnAssign) or defstmt.value: return False - for ref_node in node.scope().locals[node.name][1:]: - if ref_node.lineno < node.lineno: - if not ( - isinstance(ref_node.parent, nodes.AnnAssign) - and ref_node.parent.value + + defstmt_frame = defstmt.frame() + node_frame = node.frame() + + parent = node + while parent is not defstmt_frame.parent: + parent_scope = parent.scope() + local_refs = parent_scope.locals.get(node.name, []) + for ref_node in local_refs: + # If local ref is in the same frame as our node, but on a later lineno + # we don't actually care about this local ref. + # Local refs are ordered, so we break. + # print(var) + # var = 1 # <- irrelevant + if defstmt_frame == node_frame and not ref_node.lineno < node.lineno: + break + + # If the parent of the local refence is anything but a AnnAssign + # Or if the AnnAssign adds a value the variable will now have a value + # var = 1 # OR + # var: int = 1 + if ( + not isinstance(ref_node.parent, nodes.AnnAssign) + or ref_node.parent.value ): return False + parent = parent_scope.parent return True @staticmethod -- cgit v1.2.1