@@ -753,19 +753,21 @@ def __init__(self, tree, filename='(none)', builtins=None,
753
753
if builtins :
754
754
self .builtIns = self .builtIns .union (builtins )
755
755
self .withDoctest = withDoctest
756
+ self .exceptHandlers = [()]
757
+ self .root = tree
758
+
759
+ self .scopeStack = []
756
760
try :
757
- self . scopeStack = [ Checker ._ast_node_scope [type (tree )]( )]
761
+ scope_tp = Checker ._ast_node_scope [type (tree )]
758
762
except KeyError :
759
763
raise RuntimeError ('No scope implemented for the node %r' % tree )
760
- self .exceptHandlers = [()]
761
- self .root = tree
762
- for builtin in self .builtIns :
763
- self .addBinding (None , Builtin (builtin ))
764
- self .handleChildren (tree )
765
764
766
- self ._run_deferred ()
765
+ with self .in_scope (scope_tp ):
766
+ for builtin in self .builtIns :
767
+ self .addBinding (None , Builtin (builtin ))
768
+ self .handleChildren (tree )
769
+ self ._run_deferred ()
767
770
768
- self .popScope ()
769
771
self .checkDeadScopes ()
770
772
771
773
if file_tokens :
@@ -830,8 +832,13 @@ def annotationsFutureEnabled(self, value):
830
832
def scope (self ):
831
833
return self .scopeStack [- 1 ]
832
834
833
- def popScope (self ):
834
- self .deadScopes .append (self .scopeStack .pop ())
835
+ @contextlib .contextmanager
836
+ def in_scope (self , cls ):
837
+ self .scopeStack .append (cls ())
838
+ try :
839
+ yield
840
+ finally :
841
+ self .deadScopes .append (self .scopeStack .pop ())
835
842
836
843
def checkDeadScopes (self ):
837
844
"""
@@ -899,9 +906,6 @@ def checkDeadScopes(self):
899
906
messg = messages .RedefinedWhileUnused
900
907
self .report (messg , node , value .name , value .source )
901
908
902
- def pushScope (self , scopeClass = FunctionScope ):
903
- self .scopeStack .append (scopeClass ())
904
-
905
909
def report (self , messageClass , * args , ** kwargs ):
906
910
self .messages .append (messageClass (self .filename , * args , ** kwargs ))
907
911
@@ -1264,22 +1268,21 @@ def handleDoctests(self, node):
1264
1268
saved_stack = self .scopeStack
1265
1269
self .scopeStack = [self .scopeStack [0 ]]
1266
1270
node_offset = self .offset or (0 , 0 )
1267
- self .pushScope (DoctestScope )
1268
- if '_' not in self .scopeStack [0 ]:
1269
- self .addBinding (None , Builtin ('_' ))
1270
- for example in examples :
1271
- try :
1272
- tree = ast .parse (example .source , "<doctest>" )
1273
- except SyntaxError as e :
1274
- position = (node_lineno + example .lineno + e .lineno ,
1275
- example .indent + 4 + (e .offset or 0 ))
1276
- self .report (messages .DoctestSyntaxError , node , position )
1277
- else :
1278
- self .offset = (node_offset [0 ] + node_lineno + example .lineno ,
1279
- node_offset [1 ] + example .indent + 4 )
1280
- self .handleChildren (tree )
1281
- self .offset = node_offset
1282
- self .popScope ()
1271
+ with self .in_scope (DoctestScope ):
1272
+ if '_' not in self .scopeStack [0 ]:
1273
+ self .addBinding (None , Builtin ('_' ))
1274
+ for example in examples :
1275
+ try :
1276
+ tree = ast .parse (example .source , "<doctest>" )
1277
+ except SyntaxError as e :
1278
+ position = (node_lineno + example .lineno + e .lineno ,
1279
+ example .indent + 4 + (e .offset or 0 ))
1280
+ self .report (messages .DoctestSyntaxError , node , position )
1281
+ else :
1282
+ self .offset = (node_offset [0 ] + node_lineno + example .lineno ,
1283
+ node_offset [1 ] + example .indent + 4 )
1284
+ self .handleChildren (tree )
1285
+ self .offset = node_offset
1283
1286
self .scopeStack = saved_stack
1284
1287
1285
1288
@in_string_annotation
@@ -1825,9 +1828,8 @@ def GLOBAL(self, node):
1825
1828
NONLOCAL = GLOBAL
1826
1829
1827
1830
def GENERATOREXP (self , node ):
1828
- self .pushScope (GeneratorScope )
1829
- self .handleChildren (node )
1830
- self .popScope ()
1831
+ with self .in_scope (GeneratorScope ):
1832
+ self .handleChildren (node )
1831
1833
1832
1834
LISTCOMP = DICTCOMP = SETCOMP = GENERATOREXP
1833
1835
@@ -1943,11 +1945,8 @@ def LAMBDA(self, node):
1943
1945
self .handleNode (default , node )
1944
1946
1945
1947
def runFunction ():
1946
- self .pushScope ()
1947
-
1948
- self .handleChildren (node , omit = ['decorator_list' , 'returns' ])
1949
-
1950
- self .popScope ()
1948
+ with self .in_scope (FunctionScope ):
1949
+ self .handleChildren (node , omit = ['decorator_list' , 'returns' ])
1951
1950
1952
1951
self .deferFunction (runFunction )
1953
1952
@@ -1969,16 +1968,15 @@ def CLASSDEF(self, node):
1969
1968
self .handleNode (baseNode , node )
1970
1969
for keywordNode in node .keywords :
1971
1970
self .handleNode (keywordNode , node )
1972
- self .pushScope (ClassScope )
1973
- # doctest does not process doctest within a doctest
1974
- # classes within classes are processed.
1975
- if (self .withDoctest and
1976
- not self ._in_doctest () and
1977
- not isinstance (self .scope , FunctionScope )):
1978
- self .deferFunction (lambda : self .handleDoctests (node ))
1979
- for stmt in node .body :
1980
- self .handleNode (stmt , node )
1981
- self .popScope ()
1971
+ with self .in_scope (ClassScope ):
1972
+ # doctest does not process doctest within a doctest
1973
+ # classes within classes are processed.
1974
+ if (self .withDoctest and
1975
+ not self ._in_doctest () and
1976
+ not isinstance (self .scope , FunctionScope )):
1977
+ self .deferFunction (lambda : self .handleDoctests (node ))
1978
+ for stmt in node .body :
1979
+ self .handleNode (stmt , node )
1982
1980
self .addBinding (node , ClassDefinition (node .name , node ))
1983
1981
1984
1982
def AUGASSIGN (self , node ):
0 commit comments