def _get_rest(course: models.Course) -> t.Mapping[str, t.Any]: if helpers.extended_requested(): snippets: t.Sequence[models.CourseSnippet] = [] if (current_user.has_permission(GPerm.can_use_snippets) and current_user.has_permission( CPerm.can_view_course_snippets, course_id=course.id)): snippets = course.snippets return { 'assignments': course.get_all_visible_assignments(), 'group_sets': course.group_sets, 'snippets': snippets, **course.__to_json__(), } return course.__to_json__()
def get_feedback_from_submission(submission_id: int) -> JSONResponse[Feedback]: """Get all feedback for a submission .. :quickref: Submission; Get all (linter, user and general) feedback. :>json general: The general feedback given on this submission. :>json user: A mapping between file id and a mapping that is between line and feedback. So for example: ``{5: {0: 'Nice job!'}}`` means that file with ``id`` 5 has feedback on line 0. :>json linter: A mapping that is almost the same the user feedback mapping, only the final key is not a string but a list of tuples where the first item is the linter code and the second item is a :class:`.models.LinterComment`. :>json authors: The authors of the user feedback. In the example above the author of the feedback 'Nice job!' would be at ``{5: {0: $USER}}``. """ work = helpers.get_or_404(models.Work, submission_id) auth.ensure_can_see_grade(work) can_view_author = current_user.has_permission(CPerm.can_see_assignee, work.assignment.course_id) # The authors dict gets filled if `can_view_authors` is set to `True`. This # value is used so that `mypy` wont complain about indexing null values. authors: t.MutableMapping[int, t.MutableMapping[ int, models.User]] = defaultdict(dict) res: Feedback = { 'general': work.comment or '', 'user': defaultdict(dict), 'linter': defaultdict(lambda: defaultdict(list)), 'authors': authors if can_view_author else None, } comments = models.Comment.query.filter( t.cast(DbColumn[models.File], models.Comment.file).has(work=work), ).order_by( t.cast(DbColumn[int], models.Comment.file_id).asc(), t.cast(DbColumn[int], models.Comment.line).asc(), ) for comment in comments: res['user'][comment.file_id][comment.line] = comment.comment if can_view_author: authors[comment.file_id][comment.line] = comment.user linter_comments = models.LinterComment.query.filter( t.cast(DbColumn[models.File], models.LinterComment.file).has(work=work)).order_by( t.cast(DbColumn[int], models.LinterComment.file_id).asc(), t.cast(DbColumn[int], models.LinterComment.line).asc(), ) if features.has_feature(features.Feature.LINTERS): for lcomment in linter_comments: res['linter'][lcomment.file_id][lcomment.line].append( (lcomment.linter_code, lcomment)) return jsonify(res)
def get_all_works_for_assignment( assignment_id: int ) -> t.Union[JSONResponse[WorkList], ExtendedJSONResponse[WorkList]]: """Return all :class:`.models.Work` objects for the given :class:`.models.Assignment`. .. :quickref: Assignment; Get all works for an assignment. :qparam boolean extended: Whether to get extended or normal :class:`.models.Work` objects. The default value is ``false``, you can enable extended by passing ``true``, ``1`` or an empty string. :param int assignment_id: The id of the assignment :returns: A response containing the JSON serialized submissions. :raises PermissionException: If there is no logged in user. (NOT_LOGGED_IN) :raises PermissionException: If the assignment is hidden and the user is not allowed to view it. (INCORRECT_PERMISSION) """ assignment = helpers.get_or_404(models.Assignment, assignment_id) auth.ensure_permission('can_see_assignments', assignment.course_id) if assignment.is_hidden: auth.ensure_permission( 'can_see_hidden_assignments', assignment.course_id ) obj = models.Work.query.filter_by( assignment_id=assignment_id, ).options(joinedload( models.Work.selected_items, )).order_by(t.cast(t.Any, models.Work.created_at).desc()) if not current_user.has_permission( 'can_see_others_work', course_id=assignment.course_id ): obj = obj.filter_by(user_id=current_user.id) extended = request.args.get('extended', 'false').lower() if extended in {'true', '1', ''}: obj = obj.options(undefer(models.Work.comment)) return extended_jsonify( obj.all(), use_extended=lambda obj: isinstance(obj, models.Work), ) else: return jsonify(obj.all())
def get_all_assignments() -> JSONResponse[t.Sequence[models.Assignment]]: """Get all the :class:`.models.Assignment` objects that the current user can see. .. :quickref: Assignment; Get all assignments. :returns: An array of :py:class:`.models.Assignment` items encoded in JSON. :raises PermissionException: If there is no logged in user. (NOT_LOGGED_IN) """ perm_can_see: models.Permission = models.Permission.query.filter_by( name='can_see_assignments' ).first() courses = [] for course_role in current_user.courses.values(): if course_role.has_permission(perm_can_see): courses.append(course_role.course_id) res = [] if courses: for assignment, has_linter in db.session.query( models.Assignment, t.cast(models.DbColumn[str], models.AssignmentLinter.id).isnot(None) ).filter( t.cast( models.DbColumn[int], models.Assignment.course_id, ).in_(courses) ).join( models.AssignmentLinter, sql.expression.and_( models.Assignment.id == models.AssignmentLinter.assignment_id, models.AssignmentLinter.name == 'MixedWhitespace' ), isouter=True ).all(): has_perm = current_user.has_permission( 'can_see_hidden_assignments', assignment.course_id ) assignment.whitespace_linter_exists = has_linter if ((not assignment.is_hidden) or has_perm): res.append(assignment) return jsonify(res)