test: rename maildir messages to have integer unique portions.
[pygrader.git] / README
1 ``pygrader`` is a directory-based grade database for grading course
2 assignments.  Besides tracking grades locally, you can also use it to
3 automatically mail grades to students and professors associated with
4 the course.  For secure communication, PGP_ can be used to sign and/or
5 encrypt any of these emails.
6
7 Installation
8 ============
9
10 Packages
11 --------
12
13 Gentoo
14 ~~~~~~
15
16 I've packaged ``pygrader`` for Gentoo_.  You need layman_ and
17 my `wtk overlay`_.  Install with::
18
19   # emerge -av app-portage/layman
20   # layman --add wtk
21   # emerge -av dev-python/pygrader
22
23 Dependencies
24 ------------
25
26 ``pygrader`` is a simple package.  The only external dependency
27 outside the Python 3 standard library is my `pgp-mime`_ package.
28
29 If you are developing ``pygrader``, you can use `update-copyright`_ to
30 keep the copyright blurbs up to date.
31
32 Installing by hand
33 ------------------
34
35 ``pygrader`` is available as a Git_ repository::
36
37   $ git clone git://tremily.us/pygrader.git
38
39 See the homepage_ for details.  To install the checkout, run the
40 standard::
41
42   $ python setup.py install
43
44 Usage
45 =====
46
47 Pygrader will help keep you organized in a course where the students
48 submit homework via email, or the homework submissions are otherwise
49 digital (i.e. scanned in after submission).  You can also use it to
50 assign and `manage any type of grade via email`__.  In the following
51 sections, I'll walk you through local administration for the ``test``
52 course.
53
54 __ `Mailpipe details`_
55
56 All of the processing involves using the ``pg.py`` command.  Run::
57
58   $ pg.py --help
59
60 for details.
61
62 Sending email
63 -------------
64
65 Pygrader receives submissions and assigns grades via email.  In order
66 to send email, it needs to connect to an SMTP_ server.  See the
67 pgp-mime documentation for details on configuring you SMTP connection.
68 You can test your SMTP configuration by sending yourself a test
69 message::
70
71   $ pg.py -VVV smtp -a rincewind@uu.edu -t rincewind@uu.edu
72
73 Defining the course
74 -------------------
75
76 Once you've got email submission working, you need to configure the
77 course you'll be grading.  Each course lives in its own directory, and
78 the basic setup looks like the ``test`` example distributed with
79 pygrader.  The file that you need to get started is the config file in
80 the course directory::
81
82   $ cat test/course.conf
83   [course]
84   name: Physics 101
85   assignments: Attendance 1, Attendance 2, Attendance 3, Attendance 4,
86     Attendance 5, Attendance 6, Attendance 7, Attendance 8, Attendance 9,
87     Assignment 1, Assignment 2, Exam 1, Exam 2
88   robot: Robot101
89   professors: Gandalf
90   assistants: Sauron
91   students: Bilbo Baggins, Frodo Baggins, Aragorn
92
93   [Attendance 1]
94   points: 1
95   weight: 0.1/9
96   due: 2011-10-03
97
98   [Attendance 2]
99   points: 1
100   weight: 0.1/9
101   due: 2011-10-04
102
103   …
104
105   [Assignment 1]
106   points: 10
107   weight: 0.4/2
108   due: 2011-10-10
109   submittable: yes
110
111   …
112
113   [Exam 2]
114   points: 10
115   weight: 0.4/2
116   due: 2011-10-17
117
118   [Robot101]
119   nickname: phys-101 robot
120   emails: phys101@tower.edu
121   pgp-key: 4332B6E3
122
123   [Gandalf]
124   nickname: G-Man
125   emails: g@grey.edu
126   pgp-key: 4332B6E3
127
128   [Sauron]
129   emails: eye@tower.edu
130
131   [Bilbo Baggins]
132   nickname: Bill
133   emails: bb@shire.org, bb@greyhavens.net
134
135   …
136
137 The format is a bit wordy, but it is also explicit and easily
138 extensible.  The time it takes to construct this configuration file
139 should be a small portion of the time you will spend grading
140 submissions.
141
142 If a person has the ``pgp-key`` option set, that key will be used to
143 encrypt messages to that person and sign messages from that person
144 with PGP_.  It will also be used to authenticate ownership of incoming
145 emails.  You'll need to have GnuPG_ on your local host for this to
146 work, and the user running ``pygrader`` should have the associated
147 keys in their keychain.
148
149 The ``course.robot`` option defines a dummy person used to sign
150 automatically generated emails (e.g. responses to mailpipe-processed
151 submissions).
152
153 The ``submittable`` option marks assignments that accept direct
154 submission from students (e.g. homeworks).  You probably don't want to
155 set this option for attendance, since it would allow students to mark
156 themselves as having attended a class.  ``submittable`` default to
157 ``False``.
158
159 Processing submissions
160 ----------------------
161
162 As the due date approaches, student submissions will start arriving in
163 your inbox.  Use ``pg.py``'s ``mailpipe`` command to sort them into
164 directories (using the ``pygrader.handler.submission`` handler).  This
165 will also extract any files that were attached to the emails and place
166 them in that person's assignment directory::
167
168   $ pg.py -d test mailpipe -m maildir -i ~/.maildir -o ./mail-old
169
170 Use ``pg.py``'s ``todo`` command to check for ungraded submissions::
171
172   $ pg.py -d test todo mail grade
173
174 Then create ``grade`` files using your favorite editor.  The first
175 line of the grade file should be the student's grade for that
176 assigment, expressed in a syntax that Python's ``float()`` understands
177 (``1``, ``95``, ``2.5``, ``6.022e23``, etc.).  If you wish, you may
178 add additional comment lines after the grade line, offering
179 suggestions for improvement, etc.  This comment (if present) will be
180 mailed to the student along with the grade itself.  There are a number
181 of example grade files in the ``test`` directory in ``pygrader``'s Git
182 source.
183
184 To see how everyone's doing, you can print a table of grades with
185 ``pg.py``'s ``tabulate`` command::
186
187   $ pg.py -d test tabulate -s
188
189 When you want to notify students of their grades, you can send them
190 all out with ``pg.py``'s ``email`` command::
191
192   $ pg.py -d test email assignment 'Exam 1'
193
194 Mailpipe details
195 ~~~~~~~~~~~~~~~~
196
197 Besides accepting student submissions from incoming email,
198 ``mailpipe`` also accepts other types of requests, and can be
199 configured to respond automatically:
200
201 * Incoming student assignment submissions are archived (see the
202   ``submit`` command).
203 * Students can check their grades without having to bother anyone (see
204   the ``get`` commands).
205 * Professors and teaching assistants can request student submissions
206   so that they can grade them (see the ``get`` commands).
207 * Professors and TAs can request the grades for the entire class (see
208   the ``get`` commands).
209 * Professors and TAs can assign grades (see the ``grade`` command).
210
211 To enable automatic responses, you'll need to add the ``-r`` or
212 ``--respond`` argument when you call ``pg.py``.
213
214 If you get tired of filtering your inbox by hand using ``pg.py
215 mailpipe``, you can (depending on how your mail delivery is setup) use
216 procmail_ to automatically run ``mailpipe`` automatically on incoming
217 email.  There is an example ``.procmailrc`` in the
218 ``pygrader.mailpipe.mailpipe`` docstring that runs ``mailpipe``
219 whenever incoming emails have ``[phys160:submit]`` in their subject
220 somewhere.
221
222 The use of ``[TARGET]`` tags in the email subject allows users to
223 unambiguously specify the purpose of their email.  Currently supported
224 targets include (see the ``handlers`` argument to
225 ``pygrader.mailpipe``):
226
227 ``submit``
228   student assignment submission.  The remainder of the email subject
229   should include the case insensitive name of the assignment being
230   submitted (see ``pygrader.handler.submission._match_assignment``).
231   An example subject would be::
232
233     [submit] assignment 1
234
235 ``get``
236   request information from the grade database.  For students, the
237   remainder of the email subject is irrelevant.  Grades and comments
238   for all graded assignments are returned in a single email.  An
239   example subject would be::
240
241     [get] my grades
242
243   Professors and TAs may request either a table of all grades for the
244   course (à la ``tabulate``), the full grades for a particular
245   student, or a particular student's submission for a particular
246   assignment.  Example subjects are (respectively):
247
248     [get] don't match any student names
249     [get] Bilbo Baggins
250     [get] Bilbo Baggins Assignment 1
251
252 ``grade``
253   professors and TAs can submit a grade for a particular student on a
254   particular assignment.  The body of the (possibly signed or
255   encrypted) email should be identical to the grade file that the
256   sender wishes to create.  An example subject would be::
257
258     [grade] Bilbo Baggins Assignment 1
259
260 To allow you to easily sort the email, you can also prefix the target
261 with additional information (see
262 ``pygrader.mailpipe._get_message_target``).  For example, if you were
263 running several courses from the same email account, you'd want a way
264 for users to specify which course they were interacting with so you
265 could filter appropriately in your procmail rules.  Everything in the
266 subject tag before an optional semicolon is ignored by ``mailpipe``,
267 so the following subjects will be handled identically::
268
269   [submit] assignment 1
270   [phys101:submit] assignment 1
271   [phys101:section2:submit] assignment 1
272
273 Testing
274 =======
275
276 Run the internal unit tests using nose_::
277
278   $ nosetests --with-doctest --doctest-tests pygrader
279
280 If a Python-3-version of ``nosetests`` is not the default on your
281 system, you may need to try something like::
282
283   $ nosetests-3.2 --with-doctest --doctest-tests pygrader
284
285 Licence
286 =======
287
288 This project is distributed under the `GNU General Public License
289 Version 3`_ or greater.
290
291 Author
292 ======
293
294 W. Trevor King
295 wking@tremily.us
296
297 Related work
298 ============
299
300 For a similar project, see `Alex Heitzmann's pygrade`_, which keeps
301 the grade history in a single log file and provides more support for
302 using graphical interfaces.
303
304
305 .. _PGP: http://en.wikipedia.org/wiki/Pretty_Good_Privacy
306 .. _Gentoo: http://www.gentoo.org/
307 .. _layman: http://layman.sourceforge.net/
308 .. _wtk overlay: http://blog.tremily.us/posts/Gentoo_overlay/
309 .. _pgp-mime: http://blog.tremily.us/posts/pgp-mime/
310 .. _update-copyright: http://blog.tremily.us/posts/update-copyright/
311 .. _Git: http://git-scm.com/
312 .. _homepage: http://blog.tremily.us/posts/pygrader/
313 .. _SMTP: http://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol
314 .. _GnuPG: http://www.gnupg.org/
315 .. _procmail: http://www.procmail.org/
316 .. _nose: http://readthedocs.org/docs/nose/en/latest/
317 .. _GNU General Public License Version 3: http://www.gnu.org/licenses/gpl.html
318 .. _Alex Heitzmann's pygrade: http://code.google.com/p/pygrade/