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.
16 I've packaged ``pygrader`` for Gentoo_. You need layman_ and
17 my `wtk overlay`_. Install with::
19 # emerge -av app-portage/layman
21 # emerge -av dev-python/pygrader
26 If you're installing by hand or packaging pycomedi for another
27 distribution, you'll need the following dependencies:
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 ========= ===================== ================ =========================
38 If NumPy is not installed, we'll fall back to internal implementations
39 of the various statistical calculations.
41 If you are developing ``pygrader``, you can use `update-copyright`_ to
42 keep the copyright blurbs up to date.
44 .. [#pm] In the `wtk overlay`_.
49 ``pygrader`` is available as a Git_ repository::
51 $ git clone git://tremily.us/pygrader.git
53 See the homepage_ for details. To install the checkout, run the
56 $ python setup.py install
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::
70 $ git submodule init pgp-mime pyassuan
72 If you want all of the submodules, use::
76 Git submodule will fetch (when necessary) and unpack the gitlinked
77 commit of initialized submodules with::
79 $ git submodule update
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::
86 $ PYTHONPATH=dep ./bin/pg.py ...
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``
98 __ `Mailpipe details`_
100 All of the processing involves using the ``pg.py`` command. Run::
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
115 $ pg.py -VVV smtp -a rincewind@uu.edu -t rincewind@uu.edu
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::
126 $ cat test/course.conf
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
135 students: Bilbo Baggins, Frodo Baggins, Aragorn
163 nickname: phys-101 robot
164 emails: phys101@tower.edu
173 emails: eye@tower.edu
177 emails: bb@shire.org, bb@greyhavens.net
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
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.
193 The ``course.robot`` option defines a dummy person used to sign
194 automatically generated emails (e.g. responses to mailpipe-processed
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
203 Processing submissions
204 ----------------------
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::
212 $ pg.py -d test mailpipe -m maildir -i ~/.maildir -o ./mail-old
214 Use ``pg.py``'s ``todo`` command to check for ungraded submissions::
216 $ pg.py -d test todo mail grade
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
228 To see how everyone's doing, you can print a table of grades with
229 ``pg.py``'s ``tabulate`` command::
231 $ pg.py -d test tabulate -s
233 When you want to notify students of their grades, you can send them
234 all out with ``pg.py``'s ``email`` command::
236 $ pg.py -d test email assignment 'Exam 1'
241 Besides accepting student submissions from incoming email,
242 ``mailpipe`` also accepts other types of requests, and can be
243 configured to respond automatically:
245 * Incoming student assignment submissions are archived (see the
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).
255 To enable automatic responses, you'll need to add the ``-r`` or
256 ``--respond`` argument when you call ``pg.py``.
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
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``):
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::
277 [submit] assignment 1
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::
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):
292 [get] don't match any student names
294 [get] Bilbo Baggins Assignment 1
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::
302 [grade] Bilbo Baggins Assignment 1
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::
313 [submit] assignment 1
314 [phys101:submit] assignment 1
315 [phys101:section2:submit] assignment 1
320 Run the internal unit tests using nose_::
322 $ nosetests --with-doctest --doctest-tests pygrader
324 If a Python-3-version of ``nosetests`` is not the default on your
325 system, you may need to try something like::
327 $ nosetests-3.2 --with-doctest --doctest-tests pygrader
332 This project is distributed under the `GNU General Public License
333 Version 3`_ or greater.
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.
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/