1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
#!/usr/bin/env python
# IVLE - Informatics Virtual Learning Environment
# Copyright (C) 2007-2009 The University of Melbourne
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# Program: Fetch Submissions
# Author: Matt Giuca
# Script to retrieve all submissions for a particular project.
# Requires root to run.
import sys
import os
import datetime
import optparse
if os.getuid() != 0:
print >>sys.stderr, "Must run %s as root." % os.path.basename(sys.argv[0])
sys.exit()
import ivle.config
import ivle.database
from ivle.database import Project, ProjectSet, Offering, Subject
def fetch_submission(submission, target):
"""Fetch a submission from a user's repository, and dump it in a given
directory.
@param submission: Submission object, detailing the submission.
@param target: Target directory for the project (will create a
subdirectory for each submission).
"""
# submission_name is the name of the user or group who owns the repo
submission_name = submission.assessed.principal.name
# target_final is the directory to place the files in
target_final = os.path.join(target, submission.assessed.principal.name)
if not os.path.exists(target_final):
os.makedirs(target_final)
# TODO: Actually get the repo and extract the files
print "Submission by %s, path %s" % (
submission.assessed.principal.name, submission.path)
def main(argv=None):
global store
if argv is None:
argv = sys.argv
usage = """usage: %prog [options] subject projname
(requires root)
Retrieves all submissions for a given project.
projname is the project's short name."""
# Parse arguments
parser = optparse.OptionParser(usage)
parser.add_option("-s", "--semester",
action="store", dest="semester", metavar="YEAR/SEMESTER",
help="Semester of the subject's offering (eg. 2009/1). "
"Defaults to the currently active semester.",
default=None)
parser.add_option("-c", "--cutoff",
action="store", dest="cutoff", metavar="DATE",
help="Cutoff date (retrieve the submissions as of this date)."
"YYYY-MM-DD H:M:S.",
default=None)
parser.add_option("-d", "--dest",
action="store", dest="dest", metavar="PATH",
help="Destination directory (default to '.', creates a subdirectory, "
"so will not pollute PATH).",
default=".")
(options, args) = parser.parse_args(argv[1:])
if len(args) < 2:
parser.print_help()
parser.exit()
subject_name = unicode(args[0])
project_name = unicode(args[1])
if options.semester is None:
year, semester = None, None
else:
try:
year, semester = options.semester.split('/')
if len(year) == 0 or len(semester) == 0:
raise ValueError()
except ValueError:
parser.error('Invalid semester (must have form "year/semester")')
if options.cutoff is not None:
try:
cutoff = datetime.datetime.strptime(options.cutoff,
"%Y-%m-%d %H:%M:%S")
except ValueError:
parser.error("Invalid date format: '%s' "
"(must be YYYY-MM-DD H:M:S)." % options.cutoff)
else:
cutoff = None
store = ivle.database.get_store(ivle.config.Config(plugins=False))
# Get the subject from the DB
subject = store.find(Subject,
Subject.short_name == subject_name).one()
if subject is None:
print >>sys.stderr, "No subject with short name '%s'" % subject_name
return 1
# Get the offering from the DB
if semester is None:
# None specified - get the current offering from the DB
offerings = list(subject.active_offerings())
if len(offerings) == 0:
print >>sys.stderr, ("No active offering for subject '%s'"
% subject_name)
return 1
elif len(offerings) > 1:
print >>sys.stderr, ("Multiple active offerings for subject '%s':"
% subject_name)
print >>sys.stderr, "Please use one of:"
for offering in offerings:
print >>sys.stderr, (" --semester=%s/%s"
% (offering.semester.year, offering.semester.semester))
return 1
else:
offering = offerings[0]
else:
# Get the offering for the specified semester
offering = subject.offering_for_semester(year, semester)
if offering is None:
print >>sys.stderr, (
"No offering for subject '%s' in semester %s/%s"
% (subject_name, year, semester))
return 1
# Get the project from the DB
project = store.find(Project,
Project.project_set_id == ProjectSet.id,
ProjectSet.offering == offering,
Project.short_name == project_name).one()
if project is None:
print >>sys.stderr, "No project with short name '%s'" % project_name
return 1
# Target directory is DEST/subject/year/semester/project
target_dir = os.path.join(options.dest, subject_name,
offering.semester.year, offering.semester.semester, project_name)
if not os.path.exists(target_dir):
os.makedirs(target_dir)
for submission in project.latest_submissions:
fetch_submission(submission, target_dir)
if __name__ == "__main__":
sys.exit(main(sys.argv))
|