def translate_program(cls, program):
    from core.utils import clean_spaces

    program = clean_spaces(program)
    if cls.auto_translate_program:
        result = translate_code(program)
    else:
        result = get(step_program(cls), program)
    return clean_spaces(result)
Exemple #2
0
def clean_program(program, cls):
    if callable(program) and not cls.auto_translate_program:
        program = inspect.getsource(program).splitlines()[1:]

    if not callable(program):
        program = clean_spaces(program)
        if not is_valid_syntax(program):
            cls.auto_translate_program = False

        cls.show_solution_program = program = t.translate_program(cls, program)
        return program

    func = program
    source = t.translate_program(cls, inspect.getsource(program))
    globs = func.__globals__  # noqa
    exec(source, globs)
    func = globs[t.get_code_bit(func.__name__)]
    func = MethodType(func, "")

    lines = source.splitlines()
    cls.is_function_exercise = lines[-1].strip().startswith("return ")
    if cls.is_function_exercise:
        func = func()
        assert lines[0] == f"def {t.get_code_bit('solution')}(self):"
        assert lines[-1] == f"    return {func.__name__}"
        source = clean_spaces(lines[1:-1])
        source = program = clean_solution_function(func, source)

    tree = ast.parse(source)
    if not any(
        isinstance(node, ast.Return) for node in ast.walk(tree)
    ) and not getattr(cls, "no_returns_stdout", False):
        func = returns_stdout(func)
    func = add_stdin_input_arg(func)
    func = NoMethodWrapper(func)
    cls.solution = func
    func_node = function_node(func, tree)

    if cls.is_function_exercise:
        cls.show_solution_program = ast.get_source_segment(source, func_node)
    else:
        lines = lines[func_node.body[0].lineno - 1 :]
        cls.show_solution_program = program = clean_spaces(lines)
        if hasattr(cls, "test_values"):
            [[inputs, _result]] = itertools.islice(cls.test_values(), 1)
            cls.stdin_input = inputs.pop("stdin_input", [])
            if inputs:
                inputs = inputs_string(inputs)
                program = inputs + "\n" + program

    compile(program, "<program>", "exec")  # check validity
    return program
Exemple #3
0
    def __init__(cls, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if cls.__name__ == "Page":
            return
        pages[cls.slug] = cls
        page_slugs_list.append(cls.slug)
        cls.step_names = []
        for key, value in cls.__dict__.items():
            if getattr(value, "is_step", False):
                cls.step_names.append(key)

        cls.final_text = clean_spaces(cls.final_text)
        cls.final_text = t.get(t.step_text(cls.slug, "final_text"), cls.final_text)
        cls.final_text = clean_spaces(cls.final_text)
        cls.step_names.append("final_text")
Exemple #4
0
 def __init__(self, template, *, label="", message="", max_count=0, predicate=lambda n: True, function_only=False):
     assert bool(label) ^ bool(message)
     self.label = label
     self.message = clean_spaces(message)
     self.max_count = max_count
     self.predicate = predicate
     self.function_only = function_only
     self.template = template
Exemple #5
0
    def setup(self, step_cls, i):
        label = self.label and t.get(t.disallowed_label(step_cls, i), self.label)
        message = self.message and t.get(t.disallowed_message(step_cls, i), self.message)

        if not message:
            if self.max_count > 0:
                label = t.Terms.disallowed_default_label.format(
                    max_count=self.max_count, label=label
                )

            message = t.Terms.disallowed_default_message.format(label=label)

        self.text = clean_spaces(message)
Exemple #6
0
def clean_step_class(cls):
    assert cls.__name__ != "step_name_here"

    text = cls.text or cls.__doc__
    program = cls.program
    hints = cls.hints

    solution = cls.__dict__.get("solution", "")
    assert bool(solution) ^ bool(program)

    if issubclass(cls, ExerciseStep) and not issubclass(cls, MessageStep):
        assert cls.hints, cls

    if solution:
        assert cls.tests
        assert cls.auto_translate_program
        cls.solution = MethodType(solution, "")
        program = clean_program(cls.solution, cls)  # noqa
        cls.solution = cls.wrap_solution(cls.solution)
        if not issubclass(cls, MessageStep) or cls.after_success:
            cls.test_exercise(cls.solution)
    else:
        program = clean_program(program, cls)

    assert program

    if isinstance(hints, str):
        hints = hints.strip().splitlines()
    hints = [t.get(t.hint(cls, i), hint.strip()) for i, hint in enumerate(hints)]

    text = clean_spaces(text)
    assert text
    text = t.get(cls.text_msgid, text)
    text = clean_spaces(text)
    cls.raw_text = text

    if "__program_" in text:
        text = text.replace("__program__", program)
        indented = indent(program, '    ').replace("\\", "\\\\")
        text = re.sub(r" *__program_indented__", indented, text, flags=re.MULTILINE)
    else:
        assert not cls.program_in_text, (
            "Either include __program__ or __program_indented__ in the text, "
            "or set program_in_text = False in the class.",
            cls,
            text,
        )

    assert "__program_" not in text, (cls, text)
    text = clean_spaces(text)

    for special_message in get_special_messages(cls):
        msgstr = clean_spaces(special_message.__doc__ or special_message.text)
        msgstr = t.get(t.special_message_text(cls, special_message), msgstr)
        special_message.text = msgstr
        try:
            special_message.program = t.translate_code(special_message.program)
        except SyntaxError:
            pass

    messages = []
    for name, inner_cls in inspect.getmembers(cls):
        if not (isinstance(inner_cls, type) and issubclass(inner_cls, Step)):
            continue
        assert issubclass(inner_cls, MessageStep)

        inner_cls.tests = inner_cls.tests or cls.tests
        inner_cls.generate_inputs = getattr(cls, "generate_inputs", None)
        inner_cls.page = cls.page
        inner_cls.text_msgid = t.message_step_text(cls, inner_cls)
        clean_step_class(inner_cls)

        original_inner_cls = inner_cls

        # noinspection PyAbstractClass
        class inner_cls(inner_cls, cls):
            __qualname__ = inner_cls.__qualname__
            __module__ = inner_cls.__module__

        inner_cls.__name__ = original_inner_cls.__name__

        messages.append(inner_cls)

        if inner_cls.after_success and issubclass(inner_cls, ExerciseStep):
            cls.check_exercise(inner_cls.solution)

    setattrs(cls,
             text=text,
             program=program,
             messages=messages,
             hints=hints)

    if hints:
        cls.get_solution = get_solution(cls)

    if isinstance(cls.disallowed, Disallowed):
        cls.disallowed = [cls.disallowed]
    for i, disallowed in enumerate(cls.disallowed):
        disallowed.setup(cls, i)

    if cls.expected_code_source:
        getattr(t.Terms, f"expected_mode_{cls.expected_code_source}")