@@ -1110,7 +1110,7 @@ def visit_name(self, node: nodes.Name) -> None:
1110
1110
It's important that all 'Name' nodes are visited, otherwise the
1111
1111
'NamesConsumers' won't be correct.
1112
1112
"""
1113
- stmt = node .statement ()
1113
+ stmt = node .statement (future = True )
1114
1114
if stmt .fromlineno is None :
1115
1115
# name node from an astroid built from live code, skip
1116
1116
assert not stmt .root ().file .endswith (".py" )
@@ -1261,7 +1261,7 @@ def _check_consumer(
1261
1261
return (VariableVisitConsumerAction .CONSUME , found_nodes )
1262
1262
1263
1263
defnode = utils .assign_parent (found_nodes [0 ])
1264
- defstmt = defnode .statement ()
1264
+ defstmt = defnode .statement (future = True )
1265
1265
defframe = defstmt .frame ()
1266
1266
1267
1267
# The class reuses itself in the class scope.
@@ -1515,7 +1515,10 @@ def _allow_global_unused_variables(self):
1515
1515
@staticmethod
1516
1516
def _defined_in_function_definition (node , frame ):
1517
1517
in_annotation_or_default_or_decorator = False
1518
- if isinstance (frame , nodes .FunctionDef ) and node .statement () is frame :
1518
+ if (
1519
+ isinstance (frame , nodes .FunctionDef )
1520
+ and node .statement (future = True ) is frame
1521
+ ):
1519
1522
in_annotation_or_default_or_decorator = (
1520
1523
(
1521
1524
node in frame .args .annotations
@@ -1563,8 +1566,8 @@ def _in_lambda_or_comprehension_body(
1563
1566
def _is_variable_violation (
1564
1567
node : nodes .Name ,
1565
1568
defnode ,
1566
- stmt ,
1567
- defstmt ,
1569
+ stmt : nodes . Statement ,
1570
+ defstmt : nodes . Statement ,
1568
1571
frame , # scope of statement of node
1569
1572
defframe ,
1570
1573
base_scope_type ,
@@ -1753,12 +1756,8 @@ def _is_variable_violation(
1753
1756
1754
1757
return maybe_before_assign , annotation_return , use_outer_definition
1755
1758
1756
- # pylint: disable-next=fixme
1757
- # TODO: The typing of `NodeNG.statement()` in astroid is non-specific
1758
- # After this has been updated the typing of `defstmt` should reflect this
1759
- # See: https://github.com/PyCQA/astroid/pull/1217
1760
1759
@staticmethod
1761
- def _is_only_type_assignment (node : nodes .Name , defstmt : nodes .NodeNG ) -> bool :
1760
+ def _is_only_type_assignment (node : nodes .Name , defstmt : nodes .Statement ) -> bool :
1762
1761
"""Check if variable only gets assigned a type and never a value"""
1763
1762
if not isinstance (defstmt , nodes .AnnAssign ) or defstmt .value :
1764
1763
return False
@@ -1866,7 +1865,7 @@ def _ignore_class_scope(self, node):
1866
1865
# ...
1867
1866
1868
1867
name = node .name
1869
- frame = node .statement ().scope ()
1868
+ frame = node .statement (future = True ).scope ()
1870
1869
in_annotation_or_default_or_decorator = self ._defined_in_function_definition (
1871
1870
node , frame
1872
1871
)
@@ -1890,29 +1889,36 @@ def _loopvar_name(self, node: astroid.Name) -> None:
1890
1889
# the variable is not defined.
1891
1890
scope = node .scope ()
1892
1891
if isinstance (scope , nodes .FunctionDef ) and any (
1893
- asmt .statement ().parent_of (scope ) for asmt in astmts
1892
+ asmt .scope ().parent_of (scope ) for asmt in astmts
1894
1893
):
1895
1894
return
1896
-
1897
- # filter variables according their respective scope test is_statement
1898
- # and parent to avoid #74747. This is not a total fix, which would
1895
+ # Filter variables according to their respective scope. Test parent
1896
+ # and statement to avoid #74747. This is not a total fix, which would
1899
1897
# introduce a mechanism similar to special attribute lookup in
1900
1898
# modules. Also, in order to get correct inference in this case, the
1901
1899
# scope lookup rules would need to be changed to return the initial
1902
1900
# assignment (which does not exist in code per se) as well as any later
1903
1901
# modifications.
1902
+ # pylint: disable-next=too-many-boolean-expressions
1904
1903
if (
1905
1904
not astmts
1906
- or (astmts [0 ].is_statement or astmts [0 ].parent )
1907
- and astmts [0 ].statement ().parent_of (node )
1905
+ or (
1906
+ astmts [0 ].parent == astmts [0 ].root ()
1907
+ and astmts [0 ].parent .parent_of (node )
1908
+ )
1909
+ or (
1910
+ astmts [0 ].is_statement
1911
+ or not isinstance (astmts [0 ].parent , nodes .Module )
1912
+ and astmts [0 ].statement (future = True ).parent_of (node )
1913
+ )
1908
1914
):
1909
1915
_astmts = []
1910
1916
else :
1911
1917
_astmts = astmts [:1 ]
1912
1918
for i , stmt in enumerate (astmts [1 :]):
1913
- if astmts [i ].statement ().parent_of ( stmt ) and not in_for_else_branch (
1914
- astmts [ i ]. statement (), stmt
1915
- ):
1919
+ if astmts [i ].statement (future = True ).parent_of (
1920
+ stmt
1921
+ ) and not in_for_else_branch ( astmts [ i ]. statement ( future = True ), stmt ) :
1916
1922
continue
1917
1923
_astmts .append (stmt )
1918
1924
astmts = _astmts
@@ -1922,7 +1928,7 @@ def _loopvar_name(self, node: astroid.Name) -> None:
1922
1928
assign = astmts [0 ].assign_type ()
1923
1929
if not (
1924
1930
isinstance (assign , (nodes .For , nodes .Comprehension , nodes .GeneratorExp ))
1925
- and assign .statement () is not node .statement ()
1931
+ and assign .statement (future = True ) is not node .statement (future = True )
1926
1932
):
1927
1933
return
1928
1934
@@ -2136,7 +2142,8 @@ def _check_late_binding_closure(self, node: nodes.Name) -> None:
2136
2142
maybe_for
2137
2143
and maybe_for .parent_of (node_scope )
2138
2144
and not utils .is_being_called (node_scope )
2139
- and not isinstance (node_scope .statement (), nodes .Return )
2145
+ and node_scope .parent
2146
+ and not isinstance (node_scope .statement (future = True ), nodes .Return )
2140
2147
):
2141
2148
self .add_message ("cell-var-from-loop" , node = node , args = node .name )
2142
2149
0 commit comments