diff options
author | Daniƫl van Noord <13665637+DanielNoord@users.noreply.github.com> | 2021-10-23 20:54:39 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-23 20:54:39 +0200 |
commit | 8eb7ff153e951f69b4d1ff3cbddc367c797c0aa4 (patch) | |
tree | 1370821adf92646fe35454935d09bc79fb872964 /pylint | |
parent | 91f525f276ce73c436949a6128709f2dea99e64e (diff) | |
download | pylint-git-8eb7ff153e951f69b4d1ff3cbddc367c797c0aa4.tar.gz |
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>
Diffstat (limited to 'pylint')
-rw-r--r-- | pylint/checkers/variables.py | 36 |
1 files changed, 30 insertions, 6 deletions
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 |