예제 #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]
예제 #2
0
 def arg_names(cls):
     return list(inspect.signature(bind_self(cls.solution)).parameters)