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