Skip to content

Commit a073fde

Browse files
committed
Mark bindings as used by locals()
Fixes PyCQA#136 Fixes PyCQA#333
1 parent 3169fe6 commit a073fde

File tree

2 files changed

+21
-6
lines changed

2 files changed

+21
-6
lines changed

pyflakes/checker.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,6 @@ class FunctionScope(Scope):
409409
410410
@ivar globals: Names declared 'global' in this function.
411411
"""
412-
usesLocals = False
413412
alwaysUsed = {'__tracebackhide__', '__traceback_info__',
414413
'__traceback_supplement__'}
415414

@@ -426,7 +425,6 @@ def unusedAssignments(self):
426425
"""
427426
for name, binding in self.items():
428427
if (not binding.used and name not in self.globals
429-
and not self.usesLocals
430428
and isinstance(binding, Assignment)):
431429
yield name, binding
432430

@@ -708,6 +706,16 @@ def handleNodeLoad(self, node):
708706
in_generators = None
709707
importStarred = None
710708

709+
if node.id == 'locals' and isinstance(node.parent, ast.Call):
710+
# we are doing locals() call, which marks names currently
711+
# in scope as used.
712+
scope = self.scope
713+
if isinstance(scope, GeneratorScope):
714+
scope = self.scopeStack[-2]
715+
if isinstance(scope, FunctionScope):
716+
for binding in scope.values():
717+
binding.used = (self.scope, node)
718+
711719
# try enclosing function scopes and global scope
712720
for scope in self.scopeStack[-1::-1]:
713721
if isinstance(scope, ClassScope):
@@ -1094,10 +1102,6 @@ def NAME(self, node):
10941102
# Locate the name in locals / function / globals scopes.
10951103
if isinstance(node.ctx, (ast.Load, ast.AugLoad)):
10961104
self.handleNodeLoad(node)
1097-
if (node.id == 'locals' and isinstance(self.scope, FunctionScope)
1098-
and isinstance(node.parent, ast.Call)):
1099-
# we are doing locals() call in current scope
1100-
self.scope.usesLocals = True
11011105
elif isinstance(node.ctx, (ast.Store, ast.AugStore)):
11021106
self.handleNodeStore(node)
11031107
elif isinstance(node.ctx, ast.Del):

pyflakes/test/test_other.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,17 @@ def a():
11851185
return locals()
11861186
''')
11871187

1188+
def test_unusedVariableWithLocalsInComprehension(self):
1189+
"""
1190+
Using locals() in comprehension it is perfectly valid
1191+
to have unused variables
1192+
"""
1193+
self.flakes('''
1194+
def a():
1195+
b = 1
1196+
return (i for i in locals())
1197+
''')
1198+
11881199
def test_unusedVariableNoLocals(self):
11891200
"""
11901201
Using locals() in wrong scope should not matter

0 commit comments

Comments
 (0)