Coverage for e2xgrader/exchange/release_assignment.py: 20%
46 statements
« prev ^ index » next coverage.py v7.4.2, created at 2024-03-14 13:22 +0100
« prev ^ index » next coverage.py v7.4.2, created at 2024-03-14 13:22 +0100
1import os
2import shutil
3from stat import (
4 S_IRGRP,
5 S_IROTH,
6 S_IRUSR,
7 S_ISGID,
8 S_IWGRP,
9 S_IWOTH,
10 S_IWUSR,
11 S_IXGRP,
12 S_IXOTH,
13 S_IXUSR,
14)
16from nbgrader.exchange.default import ExchangeReleaseAssignment
18from .exchange import E2xExchange
21class E2xExchangeReleaseAssignment(E2xExchange, ExchangeReleaseAssignment):
22 def init_dest(self):
23 if self.coursedir.course_id == "":
24 self.fail("No course id specified. Re-run with --course flag.")
26 self.course_path = os.path.join(self.root, self.coursedir.course_id)
27 self.outbound_path = os.path.join(self.course_path, self.outbound_directory)
28 self.inbound_path = os.path.join(self.course_path, self.inbound_directory)
30 # 0755
31 # groupshared: +2040
32 self.ensure_directory(
33 self.course_path,
34 S_IRUSR
35 | S_IWUSR
36 | S_IXUSR
37 | S_IRGRP
38 | S_IXGRP
39 | S_IROTH
40 | S_IXOTH
41 | ((S_ISGID | S_IWGRP) if self.coursedir.groupshared else 0),
42 )
44 if self.personalized_outbound:
45 # the dest path is <exchange_root>/personalized-outbound/<username>/<assignment_id>
46 # <username> is created by either grader via formgrader or student during spawning
47 # <username> here is deterministic and has to be in the release directory
48 self.dest_path = self.outbound_path
50 # 0777 for personalized_outbound
51 # groupshared: +2040
52 self.ensure_directory(
53 self.dest_path,
54 S_IRUSR
55 | S_IWUSR
56 | S_IXUSR
57 | S_IRGRP
58 | S_IWGRP
59 | S_IXGRP
60 | S_IROTH
61 | S_IWOTH
62 | S_IXOTH
63 | ((S_ISGID | S_IWGRP) if self.coursedir.groupshared else 0),
64 )
65 else:
66 self.dest_path = os.path.join(
67 self.outbound_path, self.coursedir.assignment_id
68 )
70 # 0755
71 # groupshared: +2040
72 self.ensure_directory(
73 self.outbound_path,
74 S_IRUSR
75 | S_IWUSR
76 | S_IXUSR
77 | S_IRGRP
78 | S_IXGRP
79 | S_IROTH
80 | S_IXOTH
81 | ((S_ISGID | S_IWGRP) if self.coursedir.groupshared else 0),
82 )
84 # 0733 with set GID so student submission will have the instructors group
85 # groupshared: +0040
86 self.ensure_directory(
87 self.inbound_path,
88 S_ISGID
89 | S_IRUSR
90 | S_IWUSR
91 | S_IXUSR
92 | S_IWGRP
93 | S_IXGRP
94 | S_IWOTH
95 | S_IXOTH
96 | (S_IRGRP if self.coursedir.groupshared else 0),
97 )
99 def copy_files(self):
100 if self.personalized_outbound:
101 # check available users under course_path/<assignmet_dir>/<username>
102 user_list = [
103 user
104 for user in os.listdir(self.src_path)
105 if os.path.isdir(os.path.join(self.src_path, user))
106 and user != self.coursedir.assignment_id
107 ]
108 for user in user_list:
109 released_assignment_root = os.path.join(self.dest_path, user)
110 released_user_assignment = os.path.join(
111 released_assignment_root, self.coursedir.assignment_id
112 )
113 if os.path.isdir(released_user_assignment):
114 shutil.rmtree(released_user_assignment)
116 src_assignment = os.path.join(self.src_path, user)
117 if os.path.isdir(src_assignment):
118 self.log.info(f"Source: {src_assignment}")
119 self.log.info(f"Destination: {released_user_assignment}")
120 self.do_copy(src_assignment, released_user_assignment)
121 self.set_released_assignment_perm(released_user_assignment)
122 else:
123 self.log.info(f"Src assignment not found: {src_assignment}")
124 else:
125 if os.path.isdir(self.dest_path):
126 if self.force:
127 self.log.info(
128 "Overwriting files: {} {}".format(
129 self.coursedir.course_id, self.coursedir.assignment_id
130 )
131 )
132 shutil.rmtree(self.dest_path)
133 else:
134 self.fail(
135 "Destination already exists, add --force to overwrite: {} {}".format(
136 self.coursedir.course_id, self.coursedir.assignment_id
137 )
138 )
140 self.log.info(f"Source: {self.src_path}")
141 self.log.info(f"Destination: {self.dest_path}")
142 self.do_copy(self.src_path, self.dest_path)
143 self.set_released_assignment_perm(self.dest_path)
144 self.log.info(
145 "Released as: {} {}".format(
146 self.coursedir.course_id, self.coursedir.assignment_id
147 )
148 )
150 def set_released_assignment_perm(self, path):
151 self.set_perms(
152 path,
153 fileperms=(
154 S_IRUSR
155 | S_IWUSR
156 | S_IRGRP
157 | S_IROTH
158 | (S_IWGRP if self.coursedir.groupshared else 0)
159 ),
160 dirperms=(
161 S_IRUSR
162 | S_IWUSR
163 | S_IXUSR
164 | S_IRGRP
165 | S_IXGRP
166 | S_IROTH
167 | S_IXOTH
168 | ((S_ISGID | S_IWGRP) if self.coursedir.groupshared else 0)
169 ),
170 )