~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to bin/ivle-fetchsubmissions

Added new script ivle-fetchsubmissions, which pulls submissions from students
svn repos. Currently does all the busy work (takes input, gets data from db,
creates directories), but doesn't actually do any Subversion work.

Show diffs side-by-side

added added

removed removed

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