@@ -1110,7 +1110,7 @@ def visit_name(self, node: nodes.Name) -> None:
11101110 It's important that all 'Name' nodes are visited, otherwise the
11111111 'NamesConsumers' won't be correct.
11121112 """
1113- stmt = node .statement ()
1113+ stmt = node .statement (future = True )
11141114 if stmt .fromlineno is None :
11151115 # name node from an astroid built from live code, skip
11161116 assert not stmt .root ().file .endswith (".py" )
@@ -1261,7 +1261,7 @@ def _check_consumer(
12611261 return (VariableVisitConsumerAction .CONSUME , found_nodes )
12621262
12631263 defnode = utils .assign_parent (found_nodes [0 ])
1264- defstmt = defnode .statement ()
1264+ defstmt = defnode .statement (future = True )
12651265 defframe = defstmt .frame ()
12661266
12671267 # The class reuses itself in the class scope.
@@ -1515,7 +1515,10 @@ def _allow_global_unused_variables(self):
15151515 @staticmethod
15161516 def _defined_in_function_definition (node , frame ):
15171517 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+ ):
15191522 in_annotation_or_default_or_decorator = (
15201523 (
15211524 node in frame .args .annotations
@@ -1563,8 +1566,8 @@ def _in_lambda_or_comprehension_body(
15631566 def _is_variable_violation (
15641567 node : nodes .Name ,
15651568 defnode ,
1566- stmt ,
1567- defstmt ,
1569+ stmt : nodes . Statement ,
1570+ defstmt : nodes . Statement ,
15681571 frame , # scope of statement of node
15691572 defframe ,
15701573 base_scope_type ,
@@ -1753,12 +1756,8 @@ def _is_variable_violation(
17531756
17541757 return maybe_before_assign , annotation_return , use_outer_definition
17551758
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
17601759 @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 :
17621761 """Check if variable only gets assigned a type and never a value"""
17631762 if not isinstance (defstmt , nodes .AnnAssign ) or defstmt .value :
17641763 return False
@@ -1866,7 +1865,7 @@ def _ignore_class_scope(self, node):
18661865 # ...
18671866
18681867 name = node .name
1869- frame = node .statement ().scope ()
1868+ frame = node .statement (future = True ).scope ()
18701869 in_annotation_or_default_or_decorator = self ._defined_in_function_definition (
18711870 node , frame
18721871 )
@@ -1890,29 +1889,36 @@ def _loopvar_name(self, node: astroid.Name) -> None:
18901889 # the variable is not defined.
18911890 scope = node .scope ()
18921891 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
18941893 ):
18951894 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
18991897 # introduce a mechanism similar to special attribute lookup in
19001898 # modules. Also, in order to get correct inference in this case, the
19011899 # scope lookup rules would need to be changed to return the initial
19021900 # assignment (which does not exist in code per se) as well as any later
19031901 # modifications.
1902+ # pylint: disable-next=too-many-boolean-expressions
19041903 if (
19051904 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+ )
19081914 ):
19091915 _astmts = []
19101916 else :
19111917 _astmts = astmts [:1 ]
19121918 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 ) :
19161922 continue
19171923 _astmts .append (stmt )
19181924 astmts = _astmts
@@ -1922,7 +1928,7 @@ def _loopvar_name(self, node: astroid.Name) -> None:
19221928 assign = astmts [0 ].assign_type ()
19231929 if not (
19241930 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 )
19261932 ):
19271933 return
19281934
@@ -2136,7 +2142,8 @@ def _check_late_binding_closure(self, node: nodes.Name) -> None:
21362142 maybe_for
21372143 and maybe_for .parent_of (node_scope )
21382144 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 )
21402147 ):
21412148 self .add_message ("cell-var-from-loop" , node = node , args = node .name )
21422149
0 commit comments