Exemple #1
0
    def _clone_solution_comments(
        from_solution: models.Solution,
        to_solution: models.Solution,
    ) -> None:
        user_comments = models.Comment.by_solution(
            from_solution.id, ).filter(~models.Comment.is_auto)
        for comment in user_comments:
            models.Comment.create_comment(
                commenter=models.User.get_system_user(),
                line_number=comment.line_number,
                comment_text=comment.comment,
                file=to_solution.solution_files.get(),
                is_auto=True,
            )

        to_solution.checker = from_solution.checker
        to_solution.state = from_solution.state
        to_solution.save()
        notifications.send(
            kind=notifications.NotificationKind.CHECKED,
            user=to_solution.solver,
            related_id=to_solution,
            message=_(
                'הפתרון שלך לתרגיל %(subject)s נבדק.',
                subject=to_solution.exercise.subject,
            ),
            action_url=f'{routes.SOLUTIONS}/{to_solution.id}',
        )
Exemple #2
0
    def test_mark_as_checked(
        exercise: Exercise,
        student_user: User,
        staff_user: User,
        solution: Solution,
    ):
        # Basic functionality
        assert solution.state == Solution.STATES.CREATED.name
        marked = solutions.mark_as_checked(solution.id, staff_user.id)
        # HELL WITH PEEWEE!!!
        solution = Solution.get_by_id(solution.id)
        assert marked
        assert solution.state == Solution.STATES.DONE.name
        assert solution.checker == staff_user

        # Not duplicating things
        staff_user2 = conftest.create_staff_user(index=1)
        solution2 = conftest.create_solution(exercise, student_user)
        marked = solutions.mark_as_checked(solution2.id, staff_user2.id)
        solution2 = Solution.get_by_id(solution2.id)
        assert solution2.state == Solution.STATES.DONE.name
        assert solution2.checker == staff_user2

        # Creates notifications
        assert len(list(notifications.get(student_user))) == 2
Exemple #3
0
 def test_valid_solution(self, solution: models.Solution):
     solution.json_data_str = VALID_CODE
     solution.save()
     tasks.run_flake8_on_solution(solution.id)
     comments = tuple(
         models.Comment.filter(models.Comment.solution == solution))
     assert not comments
Exemple #4
0
    def test_solutions_of_user(
        staff_user: User,
        student_user: User,
        course: Course,
        solution: Solution,
        _assessments,
    ):
        conftest.create_usercourse(student_user, course)
        client = conftest.get_logged_user(staff_user.username)
        client.post(
            f'/assessment/{solution.id}',
            data=json.dumps({'assessment': 2}),
            content_type='application/json',
        )
        solution = Solution.get_by_id(solution.id)
        assert solution.assessment.name == 'Nice'

        client.post(
            f'/assessment/{solution.id}',
            data=json.dumps({'assessment': None}),
            content_type='application/json',
        )

        exercise2 = conftest.create_exercise(course, 2)
        solution2 = conftest.create_solution(exercise2, student_user)
        client.post(
            f'/assessment/{solution2.id}',
            data=json.dumps({'assessment': 3}),
            content_type='application/json',
        )
        solution2 = Solution.get_by_id(solution2.id)

        exercises = solution.of_user(student_user.id, from_all_courses=True)
        assert exercises[0].get('assessment') is None
        assert exercises[1].get('assessment') == 'Try again'
Exemple #5
0
def view(
    solution_id: int,
    file_id: Optional[int] = None,
    shared_url: str = '',
):
    solution = Solution.get_or_none(Solution.id == solution_id)
    if solution is None:
        return fail(404, 'Solution does not exist.')

    viewer_is_solver = solution.solver.id == current_user.id
    has_viewer_access = current_user.role.is_viewer
    if not shared_url and not viewer_is_solver and not has_viewer_access:
        return fail(403, 'This user has no permissions to view this page.')

    versions = solution.ordered_versions()
    test_results = solution.test_results()
    is_manager = current_user.role.is_manager

    solution_files = tuple(solution.files)
    if not solution_files:
        if not is_manager:
            return fail(404, 'There are no files in this solution.')
        return done_checking(solution.exercise.id, solution.id)

    files = solutions.get_files_tree(solution.files)
    file_id = file_id or files[0]['id']
    file_to_show = next((f for f in solution_files if f.id == file_id), None)
    if file_to_show is None:
        return fail(404, 'File does not exist.')

    view_params = {
        'solution': model_to_dict(solution),
        'files': files,
        'comments': solution.comments_per_file,
        'current_file': file_to_show,
        'is_manager': is_manager,
        'role': current_user.role.name.lower(),
        'versions': versions,
        'test_results': test_results,
        'shared_url': shared_url,
    }

    if is_manager:
        view_params = {
            **view_params,
            'exercise_common_comments':
            _common_comments(exercise_id=solution.exercise),
            'all_common_comments':
            _common_comments(),
            'user_comments':
            _common_comments(user_id=current_user.id),
            'left':
            Solution.left_in_exercise(solution.exercise),
        }

    if viewer_is_solver:
        notifications.read_related(solution_id, current_user.id)

    return render_template('view.html', **view_params)
Exemple #6
0
 def test_pyflake_wont_execute_code(self, solution: models.Solution):
     solution.json_data_str = self.execute_script
     solution.save()
     tasks.run_flake8_on_solution(solution.id)
     comments = tuple(
         models.Comment.filter(models.Comment.solution == solution))
     assert not os.listdir(self.test_directory)
     assert len(comments) == 2
     exec(compile(self.execute_script, '', 'exec'))  # noqa S102
     assert os.listdir(self.test_directory) == ['some-file']
Exemple #7
0
def start_checking(exercise_id):
    if exercise_id != 0:
        next_exercise = Solution.next_unchecked_of(exercise_id)
    else:
        next_exercise = Solution.next_unchecked()
    if next_exercise and next_exercise.start_checking():
        general_tasks.reset_solution_state_if_needed.apply_async(
            args=(next_exercise.id, ),
            countdown=Solution.MAX_CHECK_TIME_SECONDS,
        )
        return redirect(f'/view/{next_exercise.id}')
    return redirect('/exercises')
Exemple #8
0
    def test_simple_course(self):
        course_1 = list(Solution.status(course_id=self.course1.id).dicts())
        course_2 = list(Solution.status(course_id=self.course2.id).dicts())
        assert len(course_1) == 2
        assert len(course_2) == 1

        ex1_1 = next(filter(lambda e: e['id'] == self.ex1_1.id, course_1))
        ex1_2 = next(filter(lambda e: e['id'] == self.ex1_2.id, course_1))
        ex2_1 = next(filter(lambda e: e['id'] == self.ex2_1.id, course_2))
        assert ex1_1['submitted'] == 2
        assert ex1_2['submitted'] == 1
        assert ex2_1['submitted'] == 1
Exemple #9
0
def upload():
    user_id = current_user.id
    user = User.get_or_none(User.id == user_id)  # should never happen
    if user is None:
        return fail(404, 'user not found')
    if request.content_length > MAX_REQUEST_SIZE:
        return fail(413, 'File is too heavy. 500KB allowed')

    file: FileStorage = request.files.get('file')
    if not file:
        return fail(422, 'No file was given')

    json_file_data = file.read()
    try:
        file_content = json.loads(json_file_data)
        exercises = list(extract_exercises(file_content))
    except (ValueError, json.JSONDecodeError):
        return fail(422, 'Invalid file format - must be ipynb')
    if not exercises:
        msg = 'No exercises were found in the notebook'
        desc = 'did you use Upload <number of exercise> ? (example: Upload 1)'
        return fail(422, f'{msg}, {desc}')
    matches, misses = set(), set()
    for exercise_id, code in exercises:
        exercise = Exercise.get_or_none(Exercise.id == exercise_id)
        if exercise is None:
            misses.add(exercise_id)
            continue
        if not exercise.open_for_new_solutions():
            misses.add(exercise_id)
            continue

        if Solution.solution_exists(
                exercise=exercise,
                solver=user,
                json_data_str=code,
        ):
            continue
        solution = Solution.create_solution(
            exercise=exercise,
            solver=user,
            json_data_str=code,
        )
        flake8_tasks.run_flake8_on_solution.apply_async(args=(solution.id, ))
        identical_tests_tasks.solve_solution_with_identical_code.apply_async(
            args=(solution.id, ))
        matches.add(exercise_id)
    return jsonify({
        'exercise_matches': list(matches),
        'exercise_misses': list(misses),
    })
Exemple #10
0
def view(
    solution_id: int, file_id: Optional[int] = None, shared_url: str = '',
):
    solution = Solution.get_or_none(Solution.id == solution_id)
    if solution is None:
        return fail(404, 'Solution does not exist.')

    viewer_is_solver = solution.solver.id == current_user.id
    has_viewer_access = current_user.role.is_viewer
    if not shared_url and not viewer_is_solver and not has_viewer_access:
        return fail(403, 'This user has no permissions to view this page.')

    is_manager = current_user.role.is_manager

    solution_files = tuple(solution.files)
    if not solution_files:
        if not is_manager:
            return fail(404, 'There are no files in this solution.')
        return done_checking(solution.exercise.id, solution.id)

    try:
        view_params = solutions.get_view_parameters(
            solution, file_id, shared_url, is_manager,
            solution_files, viewer_is_solver,
        )
    except LmsError as e:
        error_message, status_code = e.args
        return fail(status_code, error_message)

    return render_template('view.html', **view_params)
Exemple #11
0
def _upload_to_db(
    exercise_number: int,
    course_id: int,
    user_id: int,
    files: List[File],
    solution_hash: Optional[str] = None,
) -> Solution:
    exercise = Exercise.get_or_none(course=course_id, number=exercise_number)
    user = User.get_by_id(user_id)
    if exercise is None:
        raise UploadError(f'No such exercise id: {exercise_number}')
    elif not user.has_course(course_id):
        raise UploadError(
            f'Exercise {exercise_number} is invalid for this user.', )
    elif not exercise.open_for_new_solutions():
        raise UploadError(
            f'Exercise {exercise_number} is closed for new solutions.')

    if solution_hash and _is_uploaded_before(user, exercise, solution_hash):
        raise AlreadyExists('You try to reupload an old solution.')
    elif not files:
        raise UploadError(
            f'There are no files to upload for {exercise_number}.', )

    return Solution.create_solution(
        exercise=exercise,
        solver=user,
        files=files,
        hash_=solution_hash,
    )
Exemple #12
0
def download(download_id: str):
    """Downloading a zip file of the code files.

    Args:
        download_id (str): Can be on each side of
                           a solution.id and sharedsolution.shared_url.
    """
    solution = Solution.get_or_none(Solution.id == download_id)
    shared_solution = SharedSolution.get_or_none(
        SharedSolution.shared_url == download_id,
    )
    if solution is None and shared_solution is None:
        return fail(404, 'Solution does not exist.')

    if shared_solution is None:
        viewer_is_solver = solution.solver.id == current_user.id
        has_viewer_access = current_user.role.is_viewer
        if not viewer_is_solver and not has_viewer_access:
            return fail(403, 'This user has no permissions to view this page.')
        files = solution.files
        filename = solution.exercise.subject
    else:
        files = shared_solution.solution.files
        filename = shared_solution.solution.exercise.subject

    response = make_response(solutions.create_zip_from_solution(files))
    response.headers.set('Content-Type', 'zip')
    response.headers.set(
        'Content-Disposition', 'attachment',
        filename=f'{filename}.zip',
    )
    return response
Exemple #13
0
def view(solution_id):
    solution = Solution.get_or_none(Solution.id == solution_id)
    if solution is None:
        return fail(404, 'Solution does not exist.')

    is_manager = current_user.role.is_manager
    if solution.solver.id != current_user.id and not is_manager:
        return fail(403, 'This user has no permissions to view this page.')

    versions = solution.ordered_versions()
    view_params = {
        'solution': model_to_dict(solution),
        'is_manager': is_manager,
        'role': current_user.role.name.lower(),
        'versions': versions,
    }

    if is_manager:
        view_params = {
            **view_params,
            'exercise_common_comments':
            _common_comments(exercise_id=solution.exercise),
            'all_common_comments':
            _common_comments(),
            'user_comments':
            _common_comments(user_id=current_user.id),
        }

    return render_template('view.html', **view_params)
Exemple #14
0
    def test_strange_solution_with_no_files(
        exercise: Exercise,
        student_user: User,
        staff_user: User,
    ):
        solution = conftest.create_solution(
            exercise,
            student_user,
            files=[],
            hash_='koko',
        )

        staff_client = conftest.get_logged_user(staff_user.username)
        view_response = staff_client.get(f'{routes.SOLUTIONS}/{solution.id}')
        assert view_response.status_code == 200
        solution = Solution.get_by_id(solution.id)
        assert solution.state == Solution.STATES.DONE.name

        to_show_in_view = {
            'solution': solution,
            'file_id': None,
            'shared_url': '',
            'is_manager': False,
            'solution_files': (),
            'viewer_is_solver': True,
        }

        with pytest.raises(ResourceNotFound):
            assert get_view_parameters(**to_show_in_view)

        user_client = conftest.get_logged_user(student_user.username)
        assert len(list(notifications.get(student_user))) == 1
        view_response = user_client.get(f'{routes.SOLUTIONS}/{solution.id}')
        assert view_response.status_code == 404
Exemple #15
0
def get_view_parameters(
    solution: Solution,
    file_id: Optional[int],
    shared_url: str,
    is_manager: bool,
    solution_files: Tuple[SolutionFile, ...],
    viewer_is_solver: bool,
) -> Dict[str, Any]:
    versions = solution.ordered_versions()
    test_results = solution.test_results()
    files = get_files_tree(solution.files)
    file_id = file_id or (files[0]['id'] if files else None)
    file_to_show = next((f for f in solution_files if f.id == file_id), None)
    if file_to_show is None:
        raise ResourceNotFound('File does not exist.', 404)

    view_params = {
        'solution': model_to_dict(solution),
        'files': files,
        'comments': solution.comments_per_file,
        'current_file': file_to_show,
        'is_manager': is_manager,
        'role': current_user.role.name.lower(),
        'versions': versions,
        'test_results': test_results,
        'shared_url': shared_url,
        'image_extensions': ALLOWED_IMAGES_EXTENSIONS,
    }

    if is_manager:
        view_params = {
            **view_params,
            'exercise_common_comments':
            comments._common_comments(exercise_id=solution.exercise),
            'all_common_comments':
            comments._common_comments(),
            'user_comments':
            comments._common_comments(user_id=current_user.id),
            'left':
            Solution.left_in_exercise(solution.exercise),
        }

    if viewer_is_solver:
        notifications.read_related(solution.id, current_user.id)

    return view_params
Exemple #16
0
    def test_next_exercise_with_cleanest_code(
        self,
        comment: Comment,
        staff_user: User,
    ):
        student_user: User = conftest.create_student_user(index=1)
        first_solution = comment.solution
        comment_text = comment.comment
        second_solution = conftest.create_solution(comment.solution.exercise,
                                                   student_user)

        # comment exists on first solution - second one should be the first
        next_unchecked = Solution.next_unchecked()
        assert next_unchecked is not None
        assert next_unchecked.id == second_solution.id

        # delete the comment should give us back the first solution
        Comment.delete_by_id(comment.id)
        next_unchecked = Solution.next_unchecked()
        assert next_unchecked is not None
        assert next_unchecked.id == first_solution.id

        # if second_solution has comments we should get first solution
        Comment.create_comment(
            commenter=staff_user,
            line_number=1,
            comment_text=comment_text,
            file=second_solution.solution_files.get(),
            is_auto=False,
        )
        next_unchecked = Solution.next_unchecked()
        assert next_unchecked is not None
        assert next_unchecked.id == first_solution.id

        # both have comments - the first one should be the first solution
        Comment.create_comment(
            commenter=staff_user,
            line_number=1,
            comment_text=comment_text,
            file=first_solution.solution_files.get(),
            is_auto=False,
        )
        next_unchecked = Solution.next_unchecked()
        assert next_unchecked is not None
        assert next_unchecked.id == first_solution.id
Exemple #17
0
    def test_last_view_status(
        solution: Solution,
        student_user: User,
        staff_user: User,
    ):
        client = conftest.get_logged_user(student_user.username)
        assert solution.last_status_view == SolutionStatusView.UPLOADED.name

        client.get(f'/view/{solution.id}')
        solution = Solution.get_by_id(solution.id)
        assert solution.last_status_view == SolutionStatusView.NOT_CHECKED.name

        solutions.mark_as_checked(solution.id, staff_user.id)
        solution = Solution.get_by_id(solution.id)
        assert solution.last_status_view == SolutionStatusView.NOT_CHECKED.name
        client.get(f'/view/{solution.id}')
        solution = Solution.get_by_id(solution.id)
        assert solution.last_status_view == SolutionStatusView.CHECKED.name
Exemple #18
0
def exercises_page():
    fetch_archived = bool(request.args.get('archived'))
    exercises = Solution.of_user(current_user.id, fetch_archived)
    is_manager = current_user.role.is_manager
    return render_template(
        'exercises.html',
        exercises=exercises,
        is_manager=is_manager,
        fetch_archived=fetch_archived,
    )
Exemple #19
0
    def test_all_together(self):
        all_courses = list(Solution.status().dicts())
        assert len(all_courses) == 3

        ex1_1 = next(filter(lambda e: e['id'] == self.ex1_1.id, all_courses))
        ex1_2 = next(filter(lambda e: e['id'] == self.ex1_2.id, all_courses))
        ex2_1 = next(filter(lambda e: e['id'] == self.ex2_1.id, all_courses))
        assert ex1_1['submitted'] == 2
        assert ex1_2['submitted'] == 1
        assert ex2_1['submitted'] == 1
Exemple #20
0
def _is_uploaded_before(
    user: User,
    exercise: Exercise,
    file_hash: str,
) -> bool:
    return Solution.is_duplicate(
        file_hash,
        user,
        exercise,
        already_hashed=True,
    )
Exemple #21
0
 def test_invalid_solution(self, solution: models.Solution):
     solution.json_data_str = INVALID_CODE
     solution.save()
     tasks.run_flake8_on_solution(solution.id)
     comments = tuple(
         models.Comment.filter(models.Comment.solution == solution))
     assert comments
     assert len(comments) == 1
     comment = comments[0].comment
     assert comment.text == INVALID_CODE_MESSAGE
     assert comment.flake8_key == INVALID_CODE_KEY
     user_notifications = notifications.get_notifications_for_user(
         for_user=solution.solver)
     assert len(user_notifications) == 1
     assert user_notifications
     parameters = user_notifications[0]['message_parameters']
     subject = parameters['exercise_name']
     errors = parameters['errors']
     assert solution.exercise.subject == subject
     assert 1 == errors
Exemple #22
0
    def test_new_solution_override_old_solutions(
        self,
        exercise: Exercise,
        student_user: User,
    ):
        first_solution = conftest.create_solution(exercise, student_user)
        second_solution = conftest.create_solution(exercise, student_user)
        assert second_solution.state == self.created_state
        assert first_solution.refresh().state == self.old_solution_state

        next_unchecked = Solution.next_unchecked()
        assert next_unchecked is not None
        assert next_unchecked.id == second_solution.id
        next_unchecked = Solution.next_unchecked_of(exercise.id)
        assert next_unchecked is not None
        assert next_unchecked.id == second_solution.id
        assert next_unchecked.start_checking()
        assert next_unchecked.refresh().state == self.in_checking_state

        assert Solution.next_unchecked() is None
        assert Solution.next_unchecked_of(exercise.id) is None

        general_tasks.reset_solution_state_if_needed(second_solution.id)
        next_unchecked = Solution.next_unchecked()
        next_unchecked_by_id = Solution.next_unchecked_of(exercise.id)
        assert next_unchecked is not None and next_unchecked_by_id is not None
        assert next_unchecked.id == second_solution.id
        assert next_unchecked_by_id.id == second_solution.id

        third_solution = conftest.create_solution(
            exercise,
            student_user,
            code='123',
        )
        fourth_solution = conftest.create_solution(
            exercise,
            student_user,
            code='1234',
        )
        assert not Solution.is_duplicate(
            third_solution.hashed,
            student_user,
            exercise,
            already_hashed=True,
        )
        assert Solution.is_duplicate(
            fourth_solution.hashed,
            student_user,
            exercise,
            already_hashed=True,
        )
Exemple #23
0
def done_checking(exercise_id, solution_id):
    checked_solution: Solution = Solution.get_by_id(solution_id)
    is_updated = checked_solution.set_state(new_state=Solution.STATES.DONE)
    if is_updated:
        notifications.create_notification(
            notification_type=(
                notifications.SolutionCheckedNotification.notification_type()),
            for_user=checked_solution.solver,
            solution=checked_solution,
        )
    identical_tests_tasks.check_if_other_solutions_can_be_solved.apply_async(
        args=(solution_id, ))
    next_exercise = None
    solution = Solution.next_unchecked_of(exercise_id)
    if solution and solution.start_checking():
        general_tasks.reset_solution_state_if_needed.apply_async(
            args=(solution.id, ),
            countdown=Solution.MAX_CHECK_TIME_SECONDS,
        )
        next_exercise = solution.id
    return jsonify({'success': is_updated, 'next': next_exercise})
Exemple #24
0
def user(user_id):
    if user_id != current_user.id and not current_user.role.is_manager:
        return fail(403, "You aren't allowed to watch this page.")
    target_user = User.get_or_none(User.id == user_id)
    if target_user is None:
        return fail(404, 'There is no such user.')

    return render_template(
        'user.html',
        solutions=Solution.of_user(target_user.id, with_archived=True),
        user=target_user,
    )
Exemple #25
0
    def test_new_solution_override_old_solutions(
        self,
        exercise: Exercise,
        student_user: User,
    ):
        first_solution = conftest.create_solution(exercise, student_user)
        second_solution = conftest.create_solution(exercise, student_user)
        assert second_solution.state == self.created_state
        assert first_solution.refresh().state == self.old_solution_state

        next_unchecked = Solution.next_unchecked()
        assert next_unchecked is not None
        assert next_unchecked.id == second_solution.id
        next_unchecked = Solution.next_unchecked_of(exercise.id)
        assert next_unchecked is not None
        assert next_unchecked.id == second_solution.id
        assert next_unchecked.start_checking()
        assert next_unchecked.refresh().state == self.in_checking_state

        assert Solution.next_unchecked() is None
        assert Solution.next_unchecked_of(exercise.id) is None

        general_tasks.reset_solution_state_if_needed(second_solution.id)
        next_unchecked = Solution.next_unchecked()
        next_unchecked_by_id = Solution.next_unchecked_of(exercise.id)
        assert next_unchecked is not None and next_unchecked_by_id is not None
        assert next_unchecked.id == second_solution.id
        assert next_unchecked_by_id.id == second_solution.id
Exemple #26
0
def create_solution(
    exercise: Exercise,
    student_user: User,
    code: Optional[str] = None,
) -> Solution:
    if code is None:
        code = ''.join(random.choices(string.printable, k=100))

    return Solution.create_solution(
        exercise=exercise,
        solver=student_user,
        files=[File('exercise.py', code)],
    )
Exemple #27
0
    def _clone_solution_comments(
        from_solution: models.Solution,
        to_solution: models.Solution,
    ) -> None:
        user_comments = models.Comment.by_solution(
            from_solution.id, ).filter(~models.Comment.is_auto)
        for comment in user_comments:
            models.Comment.create_comment(
                commenter=models.User.get_system_user(),
                line_number=comment.line_number,
                comment_text=comment.comment.comment_id,
                solution=to_solution,
                is_auto=True,
            )

        to_solution.checker = from_solution.checker
        to_solution.state = from_solution.state
        to_solution.save()
        notifications.create_notification(
            notification_type=(
                notifications.SolutionCheckedNotification.notification_type()),
            for_user=to_solution.solver,
            solution=to_solution,
        )
Exemple #28
0
def mark_as_checked(solution_id: int, checker_id: int) -> bool:
    checked_solution: Solution = Solution.get_by_id(solution_id)
    is_updated = checked_solution.mark_as_checked(by=checker_id)
    msg = f'הפתרון שלך לתרגיל "{checked_solution.exercise.subject}" נבדק.'
    if is_updated:
        notifications.send(
            kind=notifications.NotificationKind.CHECKED,
            user=checked_solution.solver,
            related_id=solution_id,
            message=msg,
            action_url=f'{routes.SOLUTIONS}/{solution_id}',
        )
    if config.FEATURE_FLAG_CHECK_IDENTICAL_CODE_ON:
        (identical_tests_tasks.check_if_other_solutions_can_be_solved.
         apply_async(args=(solution_id, )))
    return is_updated
Exemple #29
0
def comment():
    act = request.args.get('act') or request.json.get('act')

    if request.method == 'POST':
        solution_id = int(request.json.get('solutionId', 0))
    else:  # it's a GET
        solution_id = int(request.args.get('solutionId', 0))

    solution = Solution.get_or_none(Solution.id == solution_id)
    if solution is None:
        return fail(404, f'No such solution {solution_id}')

    solver_id = solution.solver.id
    if solver_id != current_user.id and not current_user.role.is_manager:
        return fail(401, "You aren't allowed to watch this page.")

    if act == 'fetch':
        return jsonify(Comment.get_solutions(solution_id))

    if act == 'delete':
        comment_id = int(request.args.get('commentId'))
        comment_ = Comment.get_or_none(Comment.id == comment_id)
        if comment_ is not None:
            comment_.delete_instance()
        return jsonify({'success': 'true'})

    if act == 'create':
        kind = request.json.get('kind', '')
        comment_id, comment_text = None, None
        try:
            line_number = int(request.json.get('line', 0))
        except ValueError:
            line_number = 0
        if kind.lower() == 'id':
            comment_id = int(request.json.get('comment', 0))
        if kind.lower() == 'text':
            comment_text = request.json.get('comment', '')
        return _create_comment(
            current_user.id,
            solution,
            kind,
            line_number,
            comment_text,
            comment_id,
        )

    return fail(400, f'Unknown or unset act value "{act}"')
Exemple #30
0
    def test_start_checking(exercise: Exercise, student_user: User):
        student_user2 = conftest.create_student_user(index=1)
        exercise2 = conftest.create_exercise(1)
        solution1 = conftest.create_solution(exercise, student_user)
        solution2 = conftest.create_solution(exercise2, student_user)
        solution3 = conftest.create_solution(exercise, student_user2)

        is_checking = solutions.start_checking(solution=None)
        assert not is_checking

        with no_celery:
            for solution in (solution1, solution2, solution3):
                assert solution.state == Solution.STATES.CREATED.name
                is_checking = solutions.start_checking(solution=solution)
                assert is_checking
                the_solution = Solution.get_by_id(solution.id)
                assert the_solution.state == Solution.STATES.IN_CHECKING.name