def comment(): act = request.args.get('act') or request.json.get('act') if request.method == 'POST': file_id = int(request.json.get('fileId', 0)) else: # it's a GET file_id = int(request.args.get('fileId', 0)) file = SolutionFile.get_or_none(file_id) if file is None: return fail(404, f'No such file {file_id}.') solver_id = file.solution.solver.id if solver_id != current_user.id and not current_user.role.is_manager: return fail(403, "You aren't allowed to access this page.") if act == 'fetch': return jsonify(Comment.by_file(file_id)) if ( not webapp.config.get('USERS_COMMENTS', False) and not current_user.role.is_manager ): return fail(403, "You aren't allowed to access this page.") if act == 'delete': comment_id = int(request.args.get('commentId')) comment_ = Comment.get_or_none(Comment.id == comment_id) if ( comment_.commenter.id != current_user.id and not current_user.role.is_manager ): return fail(403, "You aren't allowed to access this page.") 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 comments._create_comment( current_user.id, file, kind, line_number, comment_text, comment_id, ) return fail(400, f'Unknown or unset act value "{act}".')
def test_valid_solution(self, solution: Solution): solution_file = solution.solution_files.get() solution_file.code = VALID_CODE solution_file.save() tasks.run_linter_on_solution(solution.id) comments = tuple(Comment.by_solution(solution)) assert not comments
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}"')
def comment(staff_user, solution): return Comment.create_comment( commenter=staff_user, file=solution.solution_files.get(), comment_text=CommentText.create_comment(text='very good!'), line_number=1, is_auto=False, )[0]
def test_pyflake_wont_execute_code(self, solution: Solution): solution_file = solution.solution_files.get() solution_file.code = self.execute_script solution_file.save() tasks.run_linter_on_solution(solution.id) comments = tuple(Comment.by_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']
def test_invalid_solution(self, solution: Solution): solution_file = solution.solution_files.get() solution_file.path = 'sql.sql' solution_file.code = INVALID_CODE solution_file.save() tasks.run_linter_on_solution(solution.id) comments = tuple(Comment.by_solution(solution)) assert comments assert len(comments) == 1 assert comments[0].comment.text == INVALID_CODE_MESSAGE
def delete(): comment_id = int(request.args.get('commentId')) comment_ = Comment.get_or_none(Comment.id == comment_id) if (comment_.commenter.id != current_user.id and not current_user.role.is_manager): raise ForbiddenPermission( "You aren't allowed to access this page.", 403, ) if comment_ is not None: comment_.delete_instance()
def test_invalid_solution(self, solution: Solution): solution_file = solution.solution_files.get() solution_file.path = 'index.html' solution_file.code = INVALID_CODE solution_file.save() tasks.run_linter_on_solution(solution.id) comments = tuple(Comment.by_solution(solution)) assert comments assert len(comments) == 3 comment_texts = {comment.comment.text for comment in comments} assert comment_texts == INVALID_CODE_MESSAGES
def _create_comment( user_id: int, file: SolutionFile, kind: str, line_number: int, comment_text: Optional[str] = None, # set when kind == text comment_id: Optional[int] = None, # set when kind == id ): user = User.get_or_none(User.id == user_id) if user is None: # should never happen, we checked session_id == solver_id return fail(404, 'No such user.') if (not kind) or (kind not in ('id', 'text')): return fail(400, 'Invalid kind.') if line_number <= 0: return fail(422, f'Invalid line number: {line_number}.') if kind == 'id': new_comment_id = comment_id elif kind == 'text': if not comment_text: return fail(422, 'Empty comments are not allowed.') new_comment_id = CommentText.create_comment(text=comment_text).id else: # should never happend, kind was checked before return fail(400, 'Invalid kind.') solutions.notify_comment_after_check(user, file.solution) comment_ = Comment.create( commenter=user, line_number=line_number, comment=new_comment_id, file=file, ) return jsonify({ 'success': 'true', 'text': comment_.comment.text, 'author_name': user.fullname, 'author_role': user.role.id, 'is_auto': False, 'id': comment_.id, 'line_number': line_number, })
def test_invalid_solution(self, solution: Solution): solution_file = solution.solution_files.get() solution_file.code = INVALID_CODE solution_file.save() tasks.run_linter_on_solution(solution.id) comments = tuple(Comment.by_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(user=solution.solver) assert len(user_notifications) == 1 assert user_notifications subject = user_notifications[0].message assert solution.exercise.subject in subject assert '1' in subject
def comment(): act = request.args.get('act') or request.json.get('act') if request.method == 'POST': file_id = int(request.json.get('fileId', 0)) else: # it's a GET file_id = int(request.args.get('fileId', 0)) file = SolutionFile.get_or_none(file_id) if file is None: return fail(404, f'No such file {file_id}.') solver_id = file.solution.solver.id if solver_id != current_user.id and not current_user.role.is_manager: return fail(403, "You aren't allowed to access this page.") if act == 'fetch': return jsonify(Comment.by_file(file_id)) if (not webapp.config.get('USERS_COMMENTS', False) and not current_user.role.is_manager): return fail(403, "You aren't allowed to access this page.") if act == 'delete': return try_or_fail(comments.delete) if act == 'create': user = User.get_or_none(User.id == current_user.id) try: comment_ = comments.create(file=file, user=user) except LmsError as e: error_message, status_code = e.args return fail(status_code, error_message) return jsonify({ 'success': 'true', 'text': comment_.comment.text, 'is_auto': False, 'author_name': user.fullname, 'author_role': user.role.id, 'id': comment_.id, 'line_number': comment_.line_number, }) return fail(400, f'Unknown or unset act value "{act}".')
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
def _create_comment( user: User, file: SolutionFile, kind: str, line_number: int, comment_text: Optional[str] = None, # set when kind == text comment_id: Optional[int] = None, # set when kind == id ): if user is None: # should never happen, we checked session_id == solver_id raise ResourceNotFound('No such user.', 404) if (not kind) or (kind not in ('id', 'text')): raise NotValidRequest('Invalid kind.', 400) if line_number <= 0: raise UnprocessableRequest(f'Invalid line number: {line_number}.', 422) if kind == 'id': new_comment_id = comment_id elif kind == 'text': if not comment_text: raise UnprocessableRequest('Empty comments are not allowed.', 422) new_comment_id = CommentText.create_comment(text=comment_text).id else: # should never happend, kind was checked before raise NotValidRequest('Invalid kind.', 400) solutions.notify_comment_after_check(user, file.solution) return Comment.create( commenter=user, line_number=line_number, comment=new_comment_id, file=file, )