pg.py: handle command-less invocation cleanly
[pygrader.git] / bin / pg.py
index 5980b01c04f14a6c3728f0c0146e64f5cb7bda74..23f4d6386ac1f328035e50f605df8e1957ec33a6 100755 (executable)
--- a/bin/pg.py
+++ b/bin/pg.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-# Copyright (C) 2012 W. Trevor King <wking@drexel.edu>
+# Copyright (C) 2012 W. Trevor King <wking@tremily.us>
 #
 # This file is part of pygrader.
 #
@@ -24,14 +24,18 @@ from email.mime.text import MIMEText as _MIMEText
 import email.utils as _email_utils
 import inspect as _inspect
 import logging as _logging
+import logging.handlers as _logging_handlers
 import os.path as _os_path
 import sys as _sys
 
 import pgp_mime as _pgp_mime
 
+import pygrader as _pygrader
 from pygrader import __version__
 from pygrader import LOG as _LOG
+from pygrader import color as _color
 from pygrader.email import test_smtp as _test_smtp
+from pygrader.email import Responder as _Responder
 from pygrader.mailpipe import mailpipe as _mailpipe
 from pygrader.storage import initialize as _initialize
 from pygrader.storage import load_course as _load_course
@@ -45,17 +49,26 @@ from pygrader.todo import print_todo as _todo
 if __name__ == '__main__':
     from argparse import ArgumentParser as _ArgumentParser
 
-    parser = _ArgumentParser(
-        description=__doc__, version=__version__)
+    parser = _ArgumentParser(description=__doc__)
+    parser.add_argument(
+        '-v', '--version', action='version',
+        version='%(prog)s {}'.format(_pgp_mime.__version__))
     parser.add_argument(
         '-d', '--base-dir', dest='basedir', default='.',
         help='Base directory containing grade data')
+    parser.add_argument(
+        '-e', '--encoding', dest='encoding', default='utf-8',
+        help=('Override the default file encoding selection '
+              '(useful when running from procmail)'))
     parser.add_argument(
         '-c', '--color', default=False, action='store_const', const=True,
         help='Color printed output with ANSI escape sequences')
     parser.add_argument(
         '-V', '--verbose', default=0, action='count',
         help='Increase verbosity')
+    parser.add_argument(
+        '-s', '--syslog', default=False, action='store_const', const=True,
+        help='Log to syslog (rather than stderr)')
     subparsers = parser.add_subparsers(title='commands')
 
     smtp_parser = subparsers.add_parser(
@@ -137,6 +150,20 @@ if __name__ == '__main__':
         '-l', '--max-late', default=0, type=float,
         help=('Grace period in seconds before an incoming assignment is '
               'actually marked as late'))
+    mailpipe_parser.add_argument(
+        '-r', '--respond', default=False, action='store_const', const=True,
+        help=('Send automatic response emails to acknowledge incoming '
+              'messages.'))
+    mailpipe_parser.add_argument(
+        '-t', '--trust-email-infrastructure',
+        default=False, action='store_const', const=True,
+        help=('Send automatic response emails even if the target has not '
+              'registered a PGP key.'))
+    mailpipe_parser.add_argument(
+        '-c', '--continue-after-invalid-message',
+        default=False, action='store_const', const=True,
+        help=('Send responses to invalid messages and continue processing '
+              'further emails (default is to die with an error message).'))
 
     todo_parser = subparsers.add_parser(
         'todo', help=_todo.__doc__.splitlines()[0])
@@ -151,14 +178,31 @@ if __name__ == '__main__':
 
     args = parser.parse_args()
 
+    if not hasattr(args, 'func'):
+        # no command selected; print help and die
+        parser.print_help()
+        _sys.exit(0)
+
     if args.verbose:
         _LOG.setLevel(max(_logging.DEBUG, _LOG.level - 10*args.verbose))
         _pgp_mime.LOG.setLevel(_LOG.level)
+    if args.syslog:
+        syslog = _logging_handlers.SysLogHandler(address="/dev/log")
+        syslog.setFormatter(_logging.Formatter('%(name)s: %(message)s'))
+        for handler in list(_LOG.handlers):
+            _LOG.removeHandler(handler)
+        _LOG.addHandler(syslog)
+        for handler in list(_pgp_mime.LOG.handlers):
+            _pgp_mime.LOG.removeHandler(handler)
+        _pgp_mime.LOG.addHandler(syslog)
+    _color.USE_COLOR = args.color
+
+    _pygrader.ENCODING = args.encoding
 
     config = _configparser.ConfigParser()
     config.read([
             _os_path.expanduser(_os_path.join('~', '.config', 'smtplib.conf')),
-            ])
+            ], encoding=_pygrader.ENCODING)
 
     func_args = _inspect.getargspec(args.func).args
     kwargs = {}
@@ -193,7 +237,8 @@ if __name__ == '__main__':
                     else:
                         kwargs[attr].extend(course.find_people(name=person))
         for attr in ['dry_run', 'mailbox', 'output', 'input_', 'max_late',
-                     'old', 'statistics']:
+                     'old', 'statistics', 'trust_email_infrastructure',
+                     'continue_after_invalid_message']:
             if hasattr(args, attr):
                 kwargs[attr] = getattr(args, attr)
     elif args.func == _test_smtp:
@@ -215,6 +260,11 @@ if __name__ == '__main__':
         kwargs['smtp'] = _pgp_mime.get_smtp(*params)
         del params
 
+    if hasattr(args, 'respond') and getattr(args, 'respond'):
+        kwargs['respond'] = _Responder(
+            smtp=kwargs.get('smtp', None),
+            dry_run=kwargs.get('dry_run', False))
+
     _LOG.debug('execute {} with {}'.format(args.func, kwargs))
     try:
         ret = args.func(**kwargs)