diff options
author | Anthony Sottile <asottile@umich.edu> | 2022-11-27 13:15:37 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-27 16:15:37 -0500 |
commit | 33bbb8266420e34a93ea74299177c19fd463acc0 (patch) | |
tree | c20afacd7d6392fd83b30c15db4b5dc2dcf39e11 | |
parent | c3273c54c94cb96927d730c6bf5d12383c85777f (diff) | |
download | pyflakes-33bbb8266420e34a93ea74299177c19fd463acc0.tar.gz |
pushScope / popScope -> with in_scope(...) (#755)
-rw-r--r-- | pyflakes/checker.py | 92 |
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): |