summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Sottile <asottile@umich.edu>2022-11-27 13:15:37 -0800
committerGitHub <noreply@github.com>2022-11-27 16:15:37 -0500
commit33bbb8266420e34a93ea74299177c19fd463acc0 (patch)
treec20afacd7d6392fd83b30c15db4b5dc2dcf39e11
parentc3273c54c94cb96927d730c6bf5d12383c85777f (diff)
downloadpyflakes-33bbb8266420e34a93ea74299177c19fd463acc0.tar.gz
pushScope / popScope -> with in_scope(...) (#755)
-rw-r--r--pyflakes/checker.py92
1 files changed, 45 insertions, 47 deletions
diff --git a/pyflakes/checker.py b/pyflakes/checker.py
index 7ee6a1d..e927715 100644
--- a/pyflakes/checker.py
+++ b/pyflakes/checker.py
@@ -753,19 +753,21 @@ class Checker:
if builtins:
self.builtIns = self.builtIns.union(builtins)
self.withDoctest = withDoctest
+ self.exceptHandlers = [()]
+ self.root = tree
+
+ self.scopeStack = []
try:
- self.scopeStack = [Checker._ast_node_scope[type(tree)]()]
+ scope_tp = Checker._ast_node_scope[type(tree)]
except KeyError:
raise RuntimeError('No scope implemented for the node %r' % tree)
- self.exceptHandlers = [()]
- self.root = tree
- for builtin in self.builtIns:
- self.addBinding(None, Builtin(builtin))
- self.handleChildren(tree)
- self._run_deferred()
+ with self.in_scope(scope_tp):
+ for builtin in self.builtIns:
+ self.addBinding(None, Builtin(builtin))
+ self.handleChildren(tree)
+ self._run_deferred()
- self.popScope()
self.checkDeadScopes()
if file_tokens:
@@ -830,8 +832,13 @@ class Checker:
def scope(self):
return self.scopeStack[-1]
- def popScope(self):
- self.deadScopes.append(self.scopeStack.pop())
+ @contextlib.contextmanager
+ def in_scope(self, cls):
+ self.scopeStack.append(cls())
+ try:
+ yield
+ finally:
+ self.deadScopes.append(self.scopeStack.pop())
def checkDeadScopes(self):
"""
@@ -899,9 +906,6 @@ class Checker:
messg = messages.RedefinedWhileUnused
self.report(messg, node, value.name, value.source)
- def pushScope(self, scopeClass=FunctionScope):
- self.scopeStack.append(scopeClass())
-
def report(self, messageClass, *args, **kwargs):
self.messages.append(messageClass(self.filename, *args, **kwargs))
@@ -1264,22 +1268,21 @@ class Checker:
saved_stack = self.scopeStack
self.scopeStack = [self.scopeStack[0]]
node_offset = self.offset or (0, 0)
- self.pushScope(DoctestScope)
- if '_' not in self.scopeStack[0]:
- self.addBinding(None, Builtin('_'))
- for example in examples:
- try:
- tree = ast.parse(example.source, "<doctest>")
- except SyntaxError as e:
- position = (node_lineno + example.lineno + e.lineno,
- example.indent + 4 + (e.offset or 0))
- self.report(messages.DoctestSyntaxError, node, position)
- else:
- self.offset = (node_offset[0] + node_lineno + example.lineno,
- node_offset[1] + example.indent + 4)
- self.handleChildren(tree)
- self.offset = node_offset
- self.popScope()
+ with self.in_scope(DoctestScope):
+ if '_' not in self.scopeStack[0]:
+ self.addBinding(None, Builtin('_'))
+ for example in examples:
+ try:
+ tree = ast.parse(example.source, "<doctest>")
+ except SyntaxError as e:
+ position = (node_lineno + example.lineno + e.lineno,
+ example.indent + 4 + (e.offset or 0))
+ self.report(messages.DoctestSyntaxError, node, position)
+ else:
+ self.offset = (node_offset[0] + node_lineno + example.lineno,
+ node_offset[1] + example.indent + 4)
+ self.handleChildren(tree)
+ self.offset = node_offset
self.scopeStack = saved_stack
@in_string_annotation
@@ -1825,9 +1828,8 @@ class Checker:
NONLOCAL = GLOBAL
def GENERATOREXP(self, node):
- self.pushScope(GeneratorScope)
- self.handleChildren(node)
- self.popScope()
+ with self.in_scope(GeneratorScope):
+ self.handleChildren(node)
LISTCOMP = DICTCOMP = SETCOMP = GENERATOREXP
@@ -1943,11 +1945,8 @@ class Checker:
self.handleNode(default, node)
def runFunction():
- self.pushScope()
-
- self.handleChildren(node, omit=['decorator_list', 'returns'])
-
- self.popScope()
+ with self.in_scope(FunctionScope):
+ self.handleChildren(node, omit=['decorator_list', 'returns'])
self.deferFunction(runFunction)
@@ -1969,16 +1968,15 @@ class Checker:
self.handleNode(baseNode, node)
for keywordNode in node.keywords:
self.handleNode(keywordNode, node)
- self.pushScope(ClassScope)
- # doctest does not process doctest within a doctest
- # classes within classes are processed.
- if (self.withDoctest and
- not self._in_doctest() and
- not isinstance(self.scope, FunctionScope)):
- self.deferFunction(lambda: self.handleDoctests(node))
- for stmt in node.body:
- self.handleNode(stmt, node)
- self.popScope()
+ with self.in_scope(ClassScope):
+ # doctest does not process doctest within a doctest
+ # classes within classes are processed.
+ if (self.withDoctest and
+ not self._in_doctest() and
+ not isinstance(self.scope, FunctionScope)):
+ self.deferFunction(lambda: self.handleDoctests(node))
+ for stmt in node.body:
+ self.handleNode(stmt, node)
self.addBinding(node, ClassDefinition(node.name, node))
def AUGASSIGN(self, node):