• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tjcsl / tin / 17450891849

04 Sep 2025 01:49AM UTC coverage: 58.858% (+0.2%) from 58.654%
17450891849

Pull #92

github

web-flow
Merge 8c9f1d1d3 into 564991635
Pull Request #92: Allow choosing custom versions of python for graders

470 of 971 branches covered (48.4%)

Branch coverage included in aggregate %.

59 of 81 new or added lines in 12 files covered. (72.84%)

1 existing line in 1 file now uncovered.

1746 of 2794 relevant lines covered (62.49%)

0.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.92
/tin/apps/assignments/admin.py
1
from __future__ import annotations
1✔
2

3
import datetime
1✔
4

5
from django.contrib import admin, messages
1✔
6
from django.utils.translation import ngettext
1✔
7

8
from .models import (
1✔
9
    Assignment,
10
    CooldownPeriod,
11
    FileAction,
12
    Folder,
13
    Language,
14
    MossResult,
15
    Quiz,
16
    QuizLogMessage,
17
    SubmissionCap,
18
)
19

20

21
@admin.register(Folder)
1✔
22
class FolderAdmin(admin.ModelAdmin):
1✔
23
    list_display = ("name", "course", "assignments")
1✔
24
    list_filter = ("course",)
1✔
25
    ordering = ("course", "name")
1✔
26
    save_as = True
1✔
27
    search_fields = ("name",)
1✔
28
    autocomplete_fields = ("course",)
1✔
29

30
    @admin.display(description="Assignments")
1✔
31
    def assignments(self, obj):
1✔
32
        return len(obj.assignments.all())
×
33

34

35
@admin.register(Assignment)
1✔
36
class AssignmentAdmin(admin.ModelAdmin):
1✔
37
    date_hierarchy = "due"
1✔
38
    list_display = ("name", "course_name", "folder", "due", "visible", "quiz_icon")
1✔
39
    list_filter = ("language_details", "course", "due")
1✔
40
    ordering = ("-due",)
1✔
41
    save_as = True
1✔
42
    search_fields = ("name",)
1✔
43
    autocomplete_fields = ("course", "folder")
1✔
44

45
    @admin.display(description="Course")
1✔
46
    def course_name(self, obj):
1✔
47
        return obj.course.name
×
48

49
    @admin.display(description="Visible", boolean=True)
1✔
50
    def visible(self, obj):
1✔
51
        return not obj.hidden
×
52

53
    @admin.display(description="Quiz", boolean=True)
1✔
54
    def quiz_icon(self, obj):
1✔
55
        return bool(obj.is_quiz)
×
56

57

58
@admin.register(Language)
1✔
59
class LanguageAdmin(admin.ModelAdmin):
1✔
60
    list_display = ("name", "language", "info", "is_deprecated")
1✔
61
    search_fields = ("name",)
1✔
62
    ordering = ("-language", "is_deprecated", "name")
1✔
63
    save_as = True
1✔
64
    list_filter = ("language",)
1✔
65
    actions = ["make_deprecated"]
1✔
66

67
    @admin.action(description="Mark languages as deprecated")
1✔
68
    def make_deprecated(self, request, queryset) -> None:
1✔
NEW
69
        changed = 0
×
NEW
70
        for language in queryset:
×
NEW
71
            language.is_deprecated = True
×
NEW
72
            language.name = f"{language.name} (Deprecated)"
×
NEW
73
            language.save()
×
NEW
74
            changed += 1
×
75

NEW
76
        self.message_user(
×
77
            request,
78
            ngettext(
79
                "Successfully marked %d language as deprecated.",
80
                "Successfully marked %d languages as deprecated.",
81
                changed,
82
            )
83
            % changed,
84
            messages.SUCCESS,
85
        )
86

87

88
@admin.register(CooldownPeriod)
1✔
89
class CooldownPeriodAdmin(admin.ModelAdmin):
1✔
90
    date_hierarchy = "start_time"
1✔
91
    list_display = ("id", "start_time", "end_time", "assignment", "student")
1✔
92
    list_filter = ("assignment__course",)
1✔
93
    ordering = ("-start_time",)
1✔
94
    save_as = True
1✔
95
    search_fields = ("assignment__name", "student__username")
1✔
96
    autocomplete_fields = ("assignment", "student")
1✔
97

98
    @admin.display(description="End Time")
1✔
99
    def end_time(self, obj):
1✔
100
        return obj.start_time + datetime.timedelta(minutes=obj.assignment.submission_limit_cooldown)
×
101

102

103
@admin.register(Quiz)
1✔
104
class QuizAdmin(admin.ModelAdmin):
1✔
105
    date_hierarchy = "assignment__due"
1✔
106
    list_display = ("assignment", "course_name", "folder_name", "due", "action", "visible")
1✔
107
    list_filter = ("action",)
1✔
108
    ordering = ("-assignment__due",)
1✔
109
    save_as = True
1✔
110
    search_fields = ("assignment__name",)
1✔
111
    autocomplete_fields = ("assignment",)
1✔
112

113
    @admin.display(description="Due")
1✔
114
    def due(self, obj):
1✔
115
        return obj.assignment.due
×
116

117
    @admin.display(description="Course")
1✔
118
    def course_name(self, obj):
1✔
119
        return obj.assignment.course.name
×
120

121
    @admin.display(description="Folder")
1✔
122
    def folder_name(self, obj):
1✔
123
        return obj.assignment.folder.name if obj.assignment.folder else None
×
124

125
    @admin.display(description="Visible", boolean=True)
1✔
126
    def visible(self, obj):
1✔
127
        return not obj.assignment.hidden
×
128

129

130
@admin.register(QuizLogMessage)
1✔
131
class QuizLogMessageAdmin(admin.ModelAdmin):
1✔
132
    date_hierarchy = "date"
1✔
133
    list_display = ("content", "assignment", "student", "date", "severity")
1✔
134
    list_filter = ("student", "severity")
1✔
135
    ordering = ("-date",)
1✔
136
    save_as = True
1✔
137
    search_fields = ("assignment__name", "student__username", "content")
1✔
138
    autocomplete_fields = ("assignment", "student")
1✔
139

140

141
@admin.register(MossResult)
1✔
142
class MossResultAdmin(admin.ModelAdmin):
1✔
143
    date_hierarchy = "date"
1✔
144
    list_display = ("date", "assignment", "course_name", "language", "user_id", "status")
1✔
145
    list_filter = ("assignment__course", "language", "user_id")
1✔
146
    ordering = ("-date",)
1✔
147
    save_as = True
1✔
148
    search_fields = ("assignment__name", "url")
1✔
149
    autocomplete_fields = ("assignment",)
1✔
150

151
    @admin.display(description="Course")
1✔
152
    def course_name(self, obj):
1✔
153
        return obj.assignment.course.name
×
154

155

156
@admin.register(FileAction)
1✔
157
class FileActionAdmin(admin.ModelAdmin):
1✔
158
    list_display = ("name", "command", "match", "is_sandboxed")
1✔
159
    list_filter = ("is_sandboxed",)
1✔
160
    save_as = True
1✔
161
    search_fields = (
1✔
162
        "name",
163
        "match_value",
164
    )
165
    filter_horizontal = ("courses",)
1✔
166

167
    @admin.display(description="Match")
1✔
168
    def match(self, obj):
1✔
169
        if obj.match_type == "S":
×
170
            return f"{obj.match_value}*"
×
171
        elif obj.match_type == "E":
×
172
            return f"*{obj.match_value}"
×
173
        elif obj.match_type == "C":
×
174
            return f"*{obj.match_value}*"
×
175
        return ""
×
176

177

178
@admin.register(SubmissionCap)
1✔
179
class SubmissionCapAdmin(admin.ModelAdmin):
1✔
180
    list_display = ("assignment", "submission_cap", "submission_cap_after_due", "student")
1✔
181
    search_fields = ("assignment__name", "student__username")
1✔
182
    list_filter = ("assignment",)
1✔
183
    save_as = True
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc