@@ -65,7 +65,6 @@ def __init__(
6565 highlighting_disabled = None ,
6666 messages = None ,
6767 parent_state = None ,
68- pre_exercise_ast = None ,
6968 student_ast = None ,
7069 solution_ast = None ,
7170 student_ast_tokens = None ,
@@ -85,10 +84,7 @@ def __init__(
8584 self .params .append (k )
8685 setattr (self , k , v )
8786
88- if pre_exercise_ast is None :
89- _ , self .pre_exercise_ast = self .parse_internal (pre_exercise_code )
90-
91- self .ast_dispatcher = self .get_dispatcher () # use updated pre_exercise_ast
87+ self .ast_dispatcher = self .get_dispatcher ()
9288
9389 # parse code if didn't happen yet
9490 if student_ast is None :
@@ -200,7 +196,7 @@ def assert_is_not(self, klasses, fun, prev_fun):
200196 def parse_external (self , code ):
201197 res = (None , None )
202198 try :
203- return Dispatcher .parse (code )
199+ return self . ast_dispatcher .parse (code )
204200 except IndentationError as e :
205201 e .filename = "script.py"
206202 # no line info for now
@@ -228,13 +224,12 @@ def parse_external(self, code):
228224
229225 return res
230226
231- @staticmethod
232- def parse_internal (code ):
227+ def parse_internal (self , code ):
233228 try :
234- return Dispatcher .parse (code )
229+ return self . ast_dispatcher .parse (code )
235230 except Exception as e :
236231 raise InstructorError (
237- "Something went wrong when parsing PEC or solution code: %s" % str (e )
232+ "Something went wrong when parsing the solution code: %s" % str (e )
238233 )
239234
240235 def parse (self , text , test = True ):
@@ -251,21 +246,32 @@ def parse(self, text, test=True):
251246 return ast
252247
253248 def get_dispatcher (self ):
254- return Dispatcher (self .pre_exercise_ast )
249+ try :
250+ return Dispatcher (self .pre_exercise_code )
251+ except Exception as e :
252+ raise InstructorError (
253+ "Something went wrong when parsing the PEC: %s" % str (e )
254+ )
255255
256256
257257class Dispatcher (DispatcherInterface ):
258- def __init__ (self , pre_exercise_ast ):
258+ _context_cache = dict ()
259+
260+ def __init__ (self , context_code = "" ):
259261 self ._parser_cache = dict ()
260- self .pre_exercise_mappings = self ._getx (
261- FunctionParser , "mappings" , pre_exercise_ast
262+ context_ast = getattr (self ._context_cache , context_code , None )
263+ if context_ast is None :
264+ context_ast = self ._context_cache [context_code ] = self .parse (
265+ context_code
266+ )[1 ]
267+ self .context_mappings = self ._getx (
268+ FunctionParser , "mappings" , context_ast
262269 )
263270
264- def __call__ (self , name , node ):
271+ def __call__ (self , name , node , * args , ** kwargs ):
265272 return getattr (self , name )(node )
266273
267- @staticmethod
268- def parse (code ):
274+ def parse (self , code ):
269275 res = asttokens .ASTTokens (code , parse = True )
270276 return res , res .tree
271277
@@ -284,7 +290,7 @@ def _getx(self, Parser, ext_attr, tree):
284290 FunctionParser ,
285291 ObjectAccessParser ,
286292 ]:
287- p .mappings = self .pre_exercise_mappings .copy ()
293+ p .mappings = self .context_mappings .copy ()
288294 # run parser
289295 p .visit (tree )
290296 # cache
@@ -304,9 +310,6 @@ def _getx(self, Parser, ext_attr, tree):
304310prop_map = partialmethod (Dispatcher ._getx , FunctionParser , "mappings" )
305311setattr (Dispatcher , "mappings" , prop_map )
306312
307- # mappings for pre exercise code from FunctionParser
308- pec_prop_map = partialmethod (Dispatcher ._getx , FunctionParser , "mappings" )
309- setattr (Dispatcher , "pre_exercise_mappings" , pec_prop_map )
310313
311314# State subclasses based on parsed output -------------------------------------
312315State .SUBCLASSES = {
0 commit comments