8000 global / nonlocal can also appear in class bodies (#836) · PyCQA/pyflakes@9228d60 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9228d60

Browse files
authored
global / nonlocal can also appear in class bodies (#836)
1 parent 2441e9c commit 9228d60

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

pyflakes/checker.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,10 @@ def __repr__(self):
526526

527527

528528
class ClassScope(Scope):
529-
pass
529+
def __init__(self):
530+
super().__init__()
531+
# {name: node}
532+
self.indirect_assignments = {}
530533

531534

532535
class FunctionScope(Scope):
@@ -566,9 +569,6 @@ def unused_annotations(self):
566569
if not binding.used and isinstance(binding, Annotation):
567570
yield name, binding
568571

569-
def unused_indirect_assignments(self):
570-
return self.indirect_assignments.items()
571-
572572

573573
class TypeScope(Scope):
574574
pass
@@ -835,6 +835,10 @@ def checkDeadScopes(self):
835835
which were imported but unused.
836836
"""
837837
for scope in self.deadScopes:
838+
if isinstance(scope, (ClassScope, FunctionScope)):
839+
for name, node in scope.indirect_assignments.items():
840+
self.report(messages.UnusedIndirectAssignment, node, name)
841+
838842
# imports in classes are public members
839843
if isinstance(scope, ClassScope):
840844
continue
@@ -844,8 +848,6 @@ def checkDeadScopes(self):
844848
self.report(messages.UnusedVariable, binding.source, name)
845849
for name, binding in scope.unused_annotations():
846850
self.report(messages.UnusedAnnotation, binding.source, name)
847-
for name, node in scope.unused_indirect_assignments():
848-
self.report(messages.UnusedIndirectAssignment, node, name)
849851

850852
all_binding = scope.get('__all__')
851853
if all_binding and not isinstance(all_binding, ExportBinding):
@@ -988,7 +990,7 @@ def addBinding(self, node, value):
988990
self.report(messages.RedefinedWhileUnused,
989991
node, value.name, existing.source)
990992

991-
if isinstance(scope, FunctionScope):
993+
if isinstance(scope, (ClassScope, FunctionScope)):
992994
scope.indirect_assignments.pop(value.name, None)
993995

994996
elif isinstance(existing, Importation) and value.redefines(existing):
@@ -1191,7 +1193,7 @@ def on_conditional_branch():
11911193
# be executed.
11921194
return
11931195

1194-
if isinstance(self.scope, FunctionScope):
1196+
if isinstance(self.scope, (ClassScope, FunctionScope)):
11951197
self.scope.indirect_assignments.pop(name, None)
11961198

11971199
if isinstance(self.scope, FunctionScope) and name in self.scope.globals:

pyflakes/test/test_other.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,36 @@ def f2():
11211121
g = 2
11221122
''', m.UnusedIndirectAssignment, m.UnusedVariable)
11231123

1124+
def test_global_nonlocal_in_class_bodies(self):
1125+
self.flakes('''
1126+
g = 0
1127+
class C:
1128+
global g
1129+
g = 1
1130+
def f():
1131+
nl = 0
1132+
class C:
1133+
nonlocal nl
1134+
nl = 1
1135+
''')
1136+
1137+
def test_unused_global_in_class(self):
1138+
self.flakes('''
1139+
g = 0
1140+
class C:
1141+
global g
1142+
u = g
1143+
''', m.UnusedIndirectAssignment)
1144+
1145+
def test_unused_nonlocal_in_clas(self):
1146+
self.flakes('''
1147+
def f():
1148+
nl = 1
1149+
class C:
1150+
nonlocal nl
1151+
u = nl
1152+
''', m.UnusedIndirectAssignment)
1153+
11241154
def test_function_arguments(self):
11251155
"""
11261156
Test to traverse ARG and ARGUMENT handler

0 commit comments

Comments
 (0)
0