@@ -973,13 +973,11 @@ def visit_name(self, node):
973
973
# if the current scope is a class scope but it's not the inner
974
974
# scope, ignore it. This prevents to access this scope instead of
975
975
# the globals one in function members when there are some common
976
- # names. The only exception is when the starting scope is a
977
- # comprehension and its direct outer scope is a class
978
- if (
979
- current_consumer .scope_type == "class"
980
- and i != start_index
981
- and not (base_scope_type == "comprehension" and i == start_index - 1 )
982
- ):
976
+ # names.
977
+ if current_consumer .scope_type == "class" and i != start_index :
978
+ # The only exceptions are: when the variable forms an iter within a
979
+ # comprehension scope; and/or when used as a default, decorator,
980
+ # or annotation within a function.
983
981
if self ._ignore_class_scope (node ):
984
982
continue
985
983
@@ -1268,6 +1266,35 @@ def _defined_in_function_definition(node, frame):
1268
1266
)
1269
1267
return in_annotation_or_default_or_decorator
1270
1268
1269
+ @staticmethod
1270
+ def _in_lambda_or_comprehension_body (
1271
+ node : astroid .node_classes .NodeNG , frame : astroid .node_classes .NodeNG
1272
+ ) -> bool :
1273
+ """return True if node within a lambda/comprehension body (or similar) and thus should not have access to class attributes in frame"""
1274
+ child = node
1275
+ parent = node .parent
1276
+ while parent is not None :
1277
+ if parent is frame :
1278
+ return False
1279
+ if isinstance (parent , astroid .Lambda ) and not child is parent .args :
1280
+ # Body of lambda should not have access to class attributes.
1281
+ return True
1282
+ if (
1283
+ isinstance (parent , astroid .node_classes .Comprehension )
1284
+ and not child is parent .iter
1285
+ ):
1286
+ # Only iter of list/set/dict/generator comprehension should have access.
1287
+ return True
1288
+ if isinstance (parent , astroid .scoped_nodes .ComprehensionScope ) and not (
1289
+ parent .generators and child is parent .generators [0 ]
1290
+ ):
1291
+ # Body of list/set/dict/generator comprehension should not have access to class attributes.
1292
+ # Furthermore, only the first generator (if multiple) in comprehension should have access.
1293
+ return True
1294
+ child = parent
1295
+ parent = parent .parent
1296
+ return False
1297
+
1271
1298
@staticmethod
1272
1299
def _is_variable_violation (
1273
1300
node ,
@@ -1439,6 +1466,7 @@ def _ignore_class_scope(self, node):
1439
1466
isinstance (frame , astroid .ClassDef )
1440
1467
or in_annotation_or_default_or_decorator
1441
1468
)
1469
+ and not self ._in_lambda_or_comprehension_body (node , frame )
1442
1470
and name in frame_locals
1443
1471
)
1444
1472
0 commit comments