def parse_node(cls, node): normal_args = cls.get_arg_tuples(node.args.args, node.args.defaults) kwonlyargs = cls.get_arg_tuples(node.args.kwonlyargs, node.args.kw_defaults) # TODO: all single args should be tuples like this vararg = cls.get_arg(node.args.vararg) kwarg = cls.get_arg(node.args.kwarg) # create context variables target_vars = [arg[0] for arg in normal_args] if vararg: target_vars.append(vararg) if kwarg: target_vars.append(kwarg) args = cls.get_arg_parts(node.args.args, node.args.defaults, 'arg') kw_args = cls.get_arg_parts(node.args.kwonlyargs, node.args.kw_defaults, 'kwonly') varargs = cls.get_arg_part(node.args.vararg, None, 'vararg') kwargs = cls.get_arg_part(node.args.kwarg, None, 'kwarg') all_args = [*args, varargs, *kw_args, kwargs] if isinstance(node, ast.Lambda): body_node = node.body else: bodyMod = wrap_in_module(node.body) body_node = FunctionBodyTransformer().visit(bodyMod) return { "node": node, "name": getattr(node, 'name', None), "args": IndexedDict([ (p['name'], p) for p in all_args if p is not None]), # TODO: arg is the node counterpart to target_vars "_spec1_args": args, "*args": varargs, "**kwargs": kwargs, "body": {'node': body_node, 'target_vars': TargetVars(target_vars)} }
def to_child_state(self, student_subtree=None, solution_subtree=None, student_context=None, solution_context=None, student_env=None, solution_env=None, student_parts=None, solution_parts=None, highlight=None, highlighting_disabled=None, append_message="", node_name=""): """Dive into nested tree. Set the current state as a state with a subtree of this syntax tree as student tree and solution tree. This is necessary when testing if statements or for loops for example. """ if isinstance(student_subtree, list): student_subtree = wrap_in_module(student_subtree) if isinstance(solution_subtree, list): solution_subtree = wrap_in_module(solution_subtree) # get new contexts if solution_context is not None: solution_context = self.solution_context.update_ctx( solution_context) else: solution_context = self.solution_context if student_context is not None: student_context = self.student_context.update_ctx(student_context) else: student_context = self.student_context # get new envs if solution_env is not None: solution_env = self.solution_env.update_ctx(solution_env) else: solution_env = self.solution_env if student_env is not None: student_env = self.student_env.update_ctx(student_env) else: student_env = self.student_env if highlighting_disabled is None: highlighting_disabled = self.highlighting_disabled if not isinstance(append_message, dict): append_message = {'msg': append_message, 'kwargs': {}} messages = [*self.messages, append_message] if not (solution_subtree and student_subtree): return self.update(student_context=student_context, solution_context=solution_context, student_env=student_env, solution_env=solution_env, highlight=highlight, highlighting_disabled=highlighting_disabled, messages=messages) klass = State if not node_name else self.SUBCLASSES[node_name] child = klass( student_code=self.student_tree_tokens.get_text(student_subtree), solution_code=self.solution_tree_tokens.get_text(solution_subtree), student_tree_tokens=self.student_tree_tokens, solution_tree_tokens=self.solution_tree_tokens, pre_exercise_code=self.pre_exercise_code, student_context=student_context, solution_context=solution_context, student_env=student_env, solution_env=solution_env, student_process=self.student_process, solution_process=self.solution_process, raw_student_output=self.raw_student_output, pre_exercise_tree=self.pre_exercise_tree, student_tree=student_subtree, solution_tree=solution_subtree, student_parts=student_parts, solution_parts=solution_parts, highlight=highlight, highlighting_disabled=highlighting_disabled, messages=messages, parent_state=self, force_diagnose=self.force_diagnose) return (child)