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]
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper(self) setattrs(self.helper, **self.helper_attrs)
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)
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}")