Пример #1
0
    def check(self):
        if self.code_source == "shell":
            return False

        function_name = self.solution.__name__

        if function_name == "solution":
            return check_exercise(
                self.input,
                self.solution,
                self.test_exercise,
                self.generate_inputs,
                functionise=True,
            )
        else:
            if function_name not in self.console.locals:
                return dict(message=f"You must define a function `{function_name}`")

            func = self.console.locals[function_name]
            if not inspect.isfunction(func):
                return dict(message=f"`{function_name}` is not a function.")

            actual_signature = basic_signature(func)
            needed_signature = basic_signature(self.solution)
            if actual_signature != needed_signature:
                return dict(
                    message=f"The signature should be:\n\n"
                            f"    def {function_name}{needed_signature}:\n\n"
                            f"not:\n\n"
                            f"    def {function_name}{actual_signature}:"
                )

            return check_exercise(
                func,
                self.solution,
                self.test_exercise,
                self.generate_inputs,
            )
Пример #2
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]
Пример #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)
Пример #4
0
 def check_exercise(self, *args, **kwargs):
     if self.code_source != "shell":
         return check_exercise(self.input, *args, **kwargs)