Exemplo n.º 1
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 = []
        cls.step_texts = []
        for key, value in cls.__dict__.items():
            if getattr(value, "is_step", False):
                clean_step_class(value)
                cls.step_names.append(key)
                cls.step_texts.append(value.text)

        assert isinstance(cls.final_text, str)
        no_weird_whitespace(cls.final_text)
        cls.final_text = highlighted_markdown(cls.final_text.strip())
        cls.step_names.append("final_text")
        cls.step_texts.append(cls.final_text)
        assert "__copyable__" not in str(cls.step_texts)
Exemplo n.º 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]
Exemplo n.º 3
0
class API:
    def __init__(self, request):
        self.request = request

    @property
    def user(self) -> User:
        return self.request.user

    def run_code(self, code, source, page_index, step_index):
        page_slug = page_slugs_list[page_index]
        entry_dict = dict(
            input=code,
            source=source,
            page_slug=page_slug,
            step_name=pages[page_slug].step_names[step_index],
            user_id=self.user.id,
        )

        entry = None
        if settings.SAVE_CODE_ENTRIES:
            entry = CodeEntry.objects.create(**entry_dict)

        result = worker_result(entry_dict)

        if settings.SAVE_CODE_ENTRIES:
            entry.output = result["output"]
            entry.save()

        if result["error"]:
            return dict(error=result["error"])

        if passed := result["passed"]:
            self.move_step(page_index, step_index + 1)

        output_parts = result["output_parts"]
        if not result["awaiting_input"]:
            output_parts.append(dict(text=">>> ", color="white"))

        birdseye_url = None
        birdseye_objects = result["birdseye_objects"]
        if birdseye_objects:
            functions = birdseye_objects["functions"]
            top_old_function_id = only(f["id"] for f in functions
                                       if f["name"] == "<module>")
            function_ids = [d.pop('id') for d in functions]
            functions = [
                eye.db.Function(**{
                    **d, 'hash': uuid4().hex
                }) for d in functions
            ]
            with eye.db.session_scope() as session:
                for func in functions:
                    session.add(func)
                session.commit()
                function_ids = {
                    old: func.id
                    for old, func in zip(function_ids, functions)
                }

                call_id = None
                for call in birdseye_objects["calls"]:
                    old_function_id = call["function_id"]
                    is_top_call = old_function_id == top_old_function_id
                    call["function_id"] = function_ids[old_function_id]
                    call["start_time"] = datetime.fromisoformat(
                        call["start_time"])
                    call = eye.db.Call(**call)
                    session.add(call)
                    if is_top_call:
                        call_id = call.id

            birdseye_url = f"/birdseye/call/{call_id}"

        return dict(
            result=output_parts,
            message=highlighted_markdown(result["message"]),
            state=self.current_state(),
            birdseye_url=birdseye_url,
            passed=passed,
        )