Dependencies
------------
-``pygrader`` is a simple package. The only external dependency
-outside the Python 3 standard library is my `pgp-mime`_ package.
+If you're installing by hand or packaging ``pygrader`` for another
+distribution, you'll need the following dependencies:
+
+======== ===================== ================ =========================
+Package Purpose Debian_ Gentoo_
+======== ===================== ================ =========================
+Jinja_ email templating python-jinja2 dev-python/jinja
+pgp-mime_ secure email dev-python/pgp-mime [#pm]
+nose_ testing (optional) python-nose dev-python/nose
+NumPy_ statistics (optional) python-numpy dev-python/numpy
+========= ===================== ================ =========================
+
+If NumPy is not installed, we'll fall back to internal implementations
+of the various statistical calculations.
If you are developing ``pygrader``, you can use `update-copyright`_ to
keep the copyright blurbs up to date.
+.. [#pm] In the `wtk overlay`_.
+
Installing by hand
------------------
$ python setup.py install
+Submodules
+----------
+
+pgp-mime_ depends on pyassuan_, which requires Python 3.3. If your
+distribution doesn't package Jinja_ or ``pgp-mime`` for Python 3.3,
+you can use ``pygrader``'s Git submodules to easily fetch compatible
+versions. The submodules are stored in the ``dep/src`` directory with
+symbolic links in ``dep`` itself. For example, the ``pgp-mime``
+submodule is kept in ``dep/src/pgp-mime`` with the symlink
+``dep/pgp_mime`` pointing to ``dep/pgp-mime/pgp_mime``. If you only
+need a few submodules, you can initialize them explicitly::
+
+ $ git submodule init pgp-mime pyassuan
+
+If you want all of the submodules, use::
+
+ $ git submodule init
+
+Git submodule will fetch (when necessary) and unpack the gitlinked
+commit of initialized submodules with::
+
+ $ git submodule update
+
+You'll want to run ``update`` again after any superproject (in this
+case, ``pygrader``) action that updates the gitlinks. Once you have
+checked out the dependencies you need, point ``PYTHONPATH`` to the
+``dep`` directory whenever you run ``pygrader``. For example::
+
+ $ PYTHONPATH=dep ./bin/pg.py ...
+
Usage
=====
Pygrader will help keep you organized in a course where the students
submit homework via email, or the homework submissions are otherwise
-digital (i.e. scanned in after submission). There is currently no
-support for multiple graders, although I will likely add this in the
-future. In the following sections, I'll walk you through
-administering the homework for the ``test`` course.
+digital (i.e. scanned in after submission). You can also use it to
+assign and `manage any type of grade via email`__. In the following
+sections, I'll walk you through local administration for the ``test``
+course.
+
+__ `Mailpipe details`_
All of the processing involves using the ``pg.py`` command. Run::
$ cat test/course.conf
[course]
+ name: Physics 101
assignments: Attendance 1, Attendance 2, Attendance 3, Attendance 4,
Attendance 5, Attendance 6, Attendance 7, Attendance 8, Attendance 9,
Assignment 1, Assignment 2, Exam 1, Exam 2
+ robot: Robot101
professors: Gandalf
assistants: Sauron
students: Bilbo Baggins, Frodo Baggins, Aragorn
…
+ [Assignment 1]
+ points: 10
+ weight: 0.4/2
+ due: 2011-10-10
+ submittable: yes
+
+ …
+
[Exam 2]
points: 10
weight: 0.4/2
due: 2011-10-17
+ [Robot101]
+ nickname: phys-101 robot
+ emails: phys101@tower.edu
+ pgp-key: 4332B6E3
+
[Gandalf]
nickname: G-Man
emails: g@grey.edu
encrypt messages to that person and sign messages from that person
with PGP_. It will also be used to authenticate ownership of incoming
emails. You'll need to have GnuPG_ on your local host for this to
-work, and the user running pygrader should have the associated keys in
-their keychain.
+work, and the user running ``pygrader`` should have the associated
+keys in their keychain.
+
+The ``course.robot`` option defines a dummy person used to sign
+automatically generated emails (e.g. responses to mailpipe-processed
+submissions).
+
+The ``submittable`` option marks assignments that accept direct
+submission from students (e.g. homeworks). You probably don't want to
+set this option for attendance, since it would allow students to mark
+themselves as having attended a class. ``submittable`` default to
+``False``.
Processing submissions
----------------------
As the due date approaches, student submissions will start arriving in
your inbox. Use ``pg.py``'s ``mailpipe`` command to sort them into
-directories. This will also extract any files that were attached to
-the emails and place them in that persons assignment directory::
+directories (using the ``pygrader.handler.submission`` handler). This
+will also extract any files that were attached to the emails and place
+them in that person's assignment directory::
$ pg.py -d test mailpipe -m maildir -i ~/.maildir -o ./mail-old
$ pg.py -d test todo mail grade
+Then create ``grade`` files using your favorite editor. The first
+line of the grade file should be the student's grade for that
+assigment, expressed in a syntax that Python's ``float()`` understands
+(``1``, ``95``, ``2.5``, ``6.022e23``, etc.). If you wish, you may
+add additional comment lines after the grade line, offering
+suggestions for improvement, etc. This comment (if present) will be
+mailed to the student along with the grade itself. There are a number
+of example grade files in the ``test`` directory in ``pygrader``'s Git
+source.
+
To see how everyone's doing, you can print a table of grades with
``pg.py``'s ``tabulate`` command::
$ pg.py -d test email assignment 'Exam 1'
+Mailpipe details
+~~~~~~~~~~~~~~~~
+
+Besides accepting student submissions from incoming email,
+``mailpipe`` also accepts other types of requests, and can be
+configured to respond automatically:
+
+* Incoming student assignment submissions are archived (see the
+ ``submit`` command).
+* Students can check their grades without having to bother anyone (see
+ the ``get`` commands).
+* Professors and teaching assistants can request student submissions
+ so that they can grade them (see the ``get`` commands).
+* Professors and TAs can request the grades for the entire class (see
+ the ``get`` commands).
+* Professors and TAs can assign grades (see the ``grade`` command).
+
+To enable automatic responses, you'll need to add the ``-r`` or
+``--respond`` argument when you call ``pg.py``.
+
+If you get tired of filtering your inbox by hand using ``pg.py
+mailpipe``, you can (depending on how your mail delivery is setup) use
+procmail_ to automatically run ``mailpipe`` automatically on incoming
+email. There is an example ``.procmailrc`` in the
+``pygrader.mailpipe.mailpipe`` docstring that runs ``mailpipe``
+whenever incoming emails have ``[phys160:submit]`` in their subject
+somewhere.
+
+The use of ``[TARGET]`` tags in the email subject allows users to
+unambiguously specify the purpose of their email. Currently supported
+targets include (see the ``handlers`` argument to
+``pygrader.mailpipe``):
+
+``submit``
+ student assignment submission. The remainder of the email subject
+ should include the case insensitive name of the assignment being
+ submitted (see ``pygrader.handler.submission._match_assignment``).
+ An example subject would be::
+
+ [submit] assignment 1
+
+``get``
+ request information from the grade database. For students, the
+ remainder of the email subject is irrelevant. Grades and comments
+ for all graded assignments are returned in a single email. An
+ example subject would be::
+
+ [get] my grades
+
+ Professors and TAs may request either a table of all grades for the
+ course (à la ``tabulate``), the full grades for a particular
+ student, or a particular student's submission for a particular
+ assignment. Example subjects are (respectively):
+
+ [get] don't match any student names
+ [get] Bilbo Baggins
+ [get] Bilbo Baggins Assignment 1
+
+``grade``
+ professors and TAs can submit a grade for a particular student on a
+ particular assignment. The body of the (possibly signed or
+ encrypted) email should be identical to the grade file that the
+ sender wishes to create. An example subject would be::
+
+ [grade] Bilbo Baggins Assignment 1
+
+To allow you to easily sort the email, you can also prefix the target
+with additional information (see
+``pygrader.mailpipe._get_message_target``). For example, if you were
+running several courses from the same email account, you'd want a way
+for users to specify which course they were interacting with so you
+could filter appropriately in your procmail rules. Everything in the
+subject tag before an optional semicolon is ignored by ``mailpipe``,
+so the following subjects will be handled identically::
+
+ [submit] assignment 1
+ [phys101:submit] assignment 1
+ [phys101:section2:submit] assignment 1
+
Testing
=======
.. _Gentoo: http://www.gentoo.org/
.. _layman: http://layman.sourceforge.net/
.. _wtk overlay: http://blog.tremily.us/posts/Gentoo_overlay/
+.. _Debian: http://www.debian.org/
+.. _Gentoo: http://www.gentoo.org/
+.. _Jinja: http://jinja.pocoo.org/
.. _pgp-mime: http://blog.tremily.us/posts/pgp-mime/
+.. _pyassuan: http://blog.tremily.us/posts/pyassuan/
+.. _NumPy: http://numpy.scipy.org/
.. _update-copyright: http://blog.tremily.us/posts/update-copyright/
.. _Git: http://git-scm.com/
.. _homepage: http://blog.tremily.us/posts/pygrader/
.. _SMTP: http://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol
.. _GnuPG: http://www.gnupg.org/
+.. _procmail: http://www.procmail.org/
.. _nose: http://readthedocs.org/docs/nose/en/latest/
.. _GNU General Public License Version 3: http://www.gnu.org/licenses/gpl.html
.. _Alex Heitzmann's pygrade: http://code.google.com/p/pygrade/