Skip to content

Commit c546317

Browse files
committed
Add some naive support for nonlocals
1 parent 7fd42fc commit c546317

File tree

3 files changed

+42
-3
lines changed

3 files changed

+42
-3
lines changed

pyflakes/checker.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1854,7 +1854,7 @@ def ASSERT(self, node):
18541854
self.report(messages.AssertTuple, node)
18551855
self.handleChildren(node)
18561856

1857-
def GLOBAL(self, node):
1857+
def GLOBAL(self, node, assign_by_default=False):
18581858
"""
18591859
Keep track of globals declarations.
18601860
"""
@@ -1866,7 +1866,7 @@ def GLOBAL(self, node):
18661866

18671867
# One 'global' statement can bind multiple (comma-delimited) names.
18681868
for node_name in node.names:
1869-
node_value = Assignment(node_name, node, assigned=False)
1869+
node_value = Assignment(node_name, node, assigned=assign_by_default)
18701870

18711871
# Remove UndefinedName messages already reported for this name.
18721872
self.messages = [
@@ -1882,7 +1882,11 @@ def GLOBAL(self, node):
18821882
for scope in self.scopeStack[global_scope_index + 1:]:
18831883
scope[node_name] = node_value
18841884

1885-
NONLOCAL = GLOBAL
1885+
def NONLOCAL(self, node):
1886+
for node_name in node.names:
1887+
if not any(node_name in scope for scope in self.scopeStack[:-1]):
1888+
self.report(messages.NoBindingForNonlocal, node, node_name)
1889+
self.GLOBAL(node, assign_by_default=True)
18861890

18871891
def GENERATOREXP(self, node):
18881892
self.pushScope(GeneratorScope)

pyflakes/messages.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ def __init__(self, filename, loc, name):
7373
self.message_args = (name,)
7474

7575

76+
class NoBindingForNonlocal(Message):
77+
message = 'no binding for nonlocal %r found'
78+
79+
def __init__(self, filename, loc, name):
80+
Message.__init__(self, filename, loc)
81+
self.message_args = (name,)
82+
83+
7684
class DoctestSyntaxError(Message):
7785
message = 'syntax error in doctest'
7886

pyflakes/test/test_undefined_names.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,33 @@ def a():
327327
fu
328328
''', m.UndefinedName)
329329

330+
def test_scope_defined_nonlocal(self):
331+
"""
332+
If a "nonlocal" is declared in a previous scope,
333+
it is defined
334+
"""
335+
self.flakes('''
336+
def a():
337+
fu = 1
338+
def b():
339+
nonlocal fu
340+
fu
341+
''')
342+
343+
def test_scope_undefined_nonlocal(self):
344+
"""
345+
If a "nonlocal" is never given a value, it is undefined
346+
"""
347+
self.flakes('''
348+
def a():
349+
nonlocal fu
350+
''', m.NoBindingForNonlocal)
351+
352+
self.flakes('''
353+
def a():
354+
nonlocal fu, bar
355+
''', m.NoBindingForNonlocal, m.NoBindingForNonlocal)
356+
330357
def test_definedByGlobalMultipleNames(self):
331358
"""
332359
"global" can accept multiple names.

0 commit comments

Comments
 (0)