예제 #1
0
    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)}
        }
예제 #2
0
    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)