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