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