Esempio n. 1
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)
    assert text
    no_weird_whitespace(text)

    if solution:
        assert cls.tests
        program, cls.solution = clean_program(solution, cls)
    else:
        program, _ = clean_program(program, cls)
    assert program

    if isinstance(hints, str):
        hints = hints.strip().splitlines()
    hints = [highlighted_markdown(hint) for hint in hints]

    if "__program_" in text:
        text = text.replace("__program__", program)
        indented = indent(program, '    ')
        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."

    assert "__program_" not in text

    text = highlighted_markdown(dedent(text).strip())

    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
        clean_step_class(inner_cls)

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

        messages.append(inner_cls)

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

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

    if hints:
        cls.get_solution = get_solution(cls)

    if cls.predicted_output_choices:
        cls.predicted_output_choices.append("Error")
        cls.predicted_output_choices = [
            s.rstrip()
            for s in cls.predicted_output_choices
        ]
        if not cls.correct_output:
            cls.correct_output = get_stdout(cls.program).rstrip()
            assert cls.correct_output in cls.predicted_output_choices
            assert cls.correct_output != "Error"
        assert cls.correct_output

    if isinstance(cls.disallowed, Disallowed):
        cls.disallowed = [cls.disallowed]
Esempio n. 2
0
 def __init__(self, *args, **kwargs):
     super().__init__(*args, **kwargs)
     self.helper = FormHelper(self)
     setattrs(self.helper, **self.helper_attrs)
Esempio n. 3
0
def clean_step_class(cls, clean_inner=True):
    text = cls.text or cls.__doc__
    program = cls.program
    hints = cls.hints

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

    if solution:
        assert cls.tests
        # noinspection PyUnresolvedReferences
        inputs = list(cls.test_values())[0][0]
        program = clean_program(solution, inputs)
    else:
        program = clean_program(program)
    assert program

    if isinstance(hints, str):
        hints = hints.strip().splitlines()
    hints = [markdown(hint) for hint in hints]

    if "__program_" in text:
        text = text.replace("__program__", program)
        indented = indent(program, '    ')
        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."

    assert "__program_" not in text

    text = markdown(dedent(text).strip())

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

            if issubclass(inner_cls, MessageStep):
                inner_cls.tests = inner_cls.tests or cls.tests
                clean_step_class(inner_cls)

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

                messages.append(inner_cls)

                if inner_cls.after_success and issubclass(
                        inner_cls, ExerciseStep):
                    check_exercise(
                        partial(inner_cls.solution, None),
                        partial(cls.solution, None),
                        cls.test_exercise,
                        cls.generate_inputs,
                    )

            clean_step_class(inner_cls, clean_inner=False)

    setattrs(cls, text=text, program=program, messages=messages, hints=hints)
Esempio n. 4
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}")