aboutsummaryrefslogtreecommitdiffstats
path: root/interfaces/email/interactive/be-handle-mail
diff options
context:
space:
mode:
Diffstat (limited to 'interfaces/email/interactive/be-handle-mail')
-rwxr-xr-xinterfaces/email/interactive/be-handle-mail115
1 files changed, 104 insertions, 11 deletions
diff --git a/interfaces/email/interactive/be-handle-mail b/interfaces/email/interactive/be-handle-mail
index 1feba92..a82f723 100755
--- a/interfaces/email/interactive/be-handle-mail
+++ b/interfaces/email/interactive/be-handle-mail
@@ -50,6 +50,8 @@ import send_pgp_mime
import sys
import time
import traceback
+import doctest
+import unittest
HANDLER_ADDRESS = u"BE Bugs <wking@thor.physics.drexel.edu>"
_THIS_DIR = os.path.abspath(os.path.dirname(__file__))
@@ -57,12 +59,13 @@ BE_DIR = _THIS_DIR
LOGPATH = os.path.join(_THIS_DIR, u"be-handle-mail.log")
LOGFILE = None
-SUBJECT_TAG_BASE = u"[be-bug"
-SUBJECT_TAG_RESPONSE = u"%s]" % SUBJECT_TAG_BASE
-SUBJECT_TAG_NEW = u"%s:submit]" % SUBJECT_TAG_BASE
-SUBJECT_TAG_COMMENT = re.compile(u"%s:([\-0-9a-z]*)]"
- % SUBJECT_TAG_BASE.replace("[","\["))
-SUBJECT_TAG_CONTROL = SUBJECT_TAG_RESPONSE
+# Tag strings generated by generate_global_tags()
+SUBJECT_TAG_BASE = u"be-bug"
+SUBJECT_TAG_RESPONSE = None
+SUBJECT_TAG_START = None
+SUBJECT_TAG_NEW = None
+SUBJECT_TAG_COMMENT = None
+SUBJECT_TAG_CONTROL = None
BREAK = u"--"
NEW_REQUIRED_PSEUDOHEADERS = [u"Version"]
@@ -70,8 +73,8 @@ NEW_OPTIONAL_PSEUDOHEADERS = [u"Reporter", u"Assign", u"Depend", u"Severity",
u"Status", u"Tag", u"Target"]
CONTROL_COMMENT = u"#"
ALLOWED_COMMANDS = [u"assign", u"comment", u"commit", u"depend", u"help",
- u"list", u"merge", u"new", u"open", u"severity", u"status",
- u"tag", u"target"]
+ u"list", u"merge", u"new", u"open", u"severity", u"show",
+ u"status", u"tag", u"target"]
AUTOCOMMIT = True
@@ -321,9 +324,9 @@ class Message (object):
Validate the subject line.
"""
tag,subject = self._split_subject()
- if not tag.startswith(SUBJECT_TAG_BASE):
+ if not tag.startswith(SUBJECT_TAG_START):
raise InvalidSubject(
- self, u"Subject must start with '%s'" % SUBJECT_TAG_BASE)
+ self, u"Subject must start with '%s'" % SUBJECT_TAG_START)
tag_type,value = self._subject_tag_type()
if tag_type == None:
raise InvalidSubject(self, u"Invalid tag '%s'" % tag)
@@ -483,6 +486,19 @@ class Message (object):
response_body.attach(message)
return send_pgp_mime.attach_root(self.response_header, response_body)
+def generate_global_tags(tag_base=u"be-bug"):
+ """
+ Generate a series of tags from a base tag string.
+ """
+ global SUBJECT_TAG_BASE, SUBJECT_TAG_START, SUBJECT_TAG_RESPONSE, \
+ SUBJECT_TAG_NEW, SUBJECT_TAG_COMMENT, SUBJECT_TAG_CONTROL
+ SUBJECT_TAG_BASE = tag_base
+ SUBJECT_TAG_START = u"[%s" % tag_base
+ SUBJECT_TAG_RESPONSE = u"[%s]" % tag_base
+ SUBJECT_TAG_NEW = u"[%s:submit]" % tag_base
+ SUBJECT_TAG_COMMENT = re.compile(u"\[%s:([\-0-9a-z]*)]" % tag_base)
+ SUBJECT_TAG_CONTROL = SUBJECT_TAG_RESPONSE
+
def open_logfile(logpath=None):
"""
If logpath=None, default to global LOGPATH.
@@ -511,13 +527,27 @@ def close_logfile():
if LOGFILE != None and LOGPATH not in [u"stderr", u"none"]:
LOGFILE.close()
+def test():
+ unitsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
+ suite = unittest.TestSuite([unitsuite, doctest.DocTestSuite()])
+ result = unittest.TextTestRunner(verbosity=2).run(suite)
+ num_errors = len(result.errors)
+ num_failures = len(result.failures)
+ num_bad = num_errors + num_failures
+ return num_bad
def main():
from optparse import OptionParser
- global AUTOCOMMIT
+ global AUTOCOMMIT, BE_DIR
usage="be-handle-mail [options]\n\n%s" % (__doc__)
parser = OptionParser(usage=usage)
+ parser.add_option('-b', '--be-dir', dest='be_dir', default=BE_DIR,
+ metavar="DIR",
+ help='Select the BE directory to serve (%default).')
+ parser.add_option('-t', '--tag-base', dest='tag_base',
+ default=SUBJECT_TAG_BASE, metavar="TAG",
+ help='Set the subject tag base (%default).')
parser.add_option('-o', '--output', dest='output', action='store_true',
help="Don't mail the generated message, print it to stdout instead. Useful for testing be-handle-mail functionality without the whole mail transfer agent and procmail setup.")
parser.add_option('-l', '--logfile', dest='logfile', metavar='LOGFILE',
@@ -525,9 +555,20 @@ def main():
parser.add_option('-a', '--disable-autocommit', dest='autocommit',
default=True, action='store_false',
help='Disable the autocommit after parsing the email.')
+ parser.add_option('--test', dest='test', action='store_true',
+ help='Run internal unit-tests and exit.')
options,args = parser.parse_args()
+
+ if options.test == True:
+ num_bad = test()
+ if num_bad > 126:
+ num_bad = 1
+ sys.exit(num_bad)
+
+ BE_DIR = options.be_dir
AUTOCOMMIT = options.autocommit
+ generate_global_tags(options.tag_base)
msg_text = sys.stdin.read()
libbe.encoding.set_IO_stream_encodings(ENCODING) # _after_ reading message
@@ -560,5 +601,57 @@ def main():
send_pgp_mime.mail(response, send_pgp_mime.sendmail)
close_logfile()
+class GenerateGlobalTagsTestCase (unittest.TestCase):
+ def setUp(self):
+ super(GenerateGlobalTagsTestCase, self).setUp()
+ self.save_global_tags()
+ def tearDown(self):
+ self.restore_global_tags()
+ super(GenerateGlobalTagsTestCase, self).tearDown()
+ def save_global_tags(self):
+ self.saved_globals = [SUBJECT_TAG_BASE, SUBJECT_TAG_START,
+ SUBJECT_TAG_RESPONSE, SUBJECT_TAG_NEW,
+ SUBJECT_TAG_COMMENT, SUBJECT_TAG_CONTROL]
+ def restore_global_tags(self):
+ global SUBJECT_TAG_BASE, SUBJECT_TAG_START, SUBJECT_TAG_RESPONSE, \
+ SUBJECT_TAG_NEW, SUBJECT_TAG_COMMENT, SUBJECT_TAG_CONTROL
+ SUBJECT_TAG_BASE, SUBJECT_TAG_START, SUBJECT_TAG_RESPONSE, \
+ SUBJECT_TAG_NEW, SUBJECT_TAG_COMMENT, SUBJECT_TAG_CONTROL = \
+ self.saved_globals
+ def test_restore_global_tags(self):
+ "Test global tag restoration by teardown function."
+ global SUBJECT_TAG_BASE
+ self.failUnlessEqual(SUBJECT_TAG_BASE, u"be-bug")
+ SUBJECT_TAG_BASE = "projectX-bug"
+ self.failUnlessEqual(SUBJECT_TAG_BASE, u"projectX-bug")
+ self.restore_global_tags()
+ self.failUnlessEqual(SUBJECT_TAG_BASE, u"be-bug")
+ def test_subject_tag_base(self):
+ "Should set SUBJECT_TAG_BASE global correctly"
+ generate_global_tags(u"projectX-bug")
+ self.failUnlessEqual(SUBJECT_TAG_BASE, u"projectX-bug")
+ def test_subject_tag_start(self):
+ "Should set SUBJECT_TAG_START global correctly"
+ generate_global_tags(u"projectX-bug")
+ self.failUnlessEqual(SUBJECT_TAG_START, u"[projectX-bug")
+ def test_subject_tag_response(self):
+ "Should set SUBJECT_TAG_RESPONSE global correctly"
+ generate_global_tags(u"projectX-bug")
+ self.failUnlessEqual(SUBJECT_TAG_RESPONSE, u"[projectX-bug]")
+ def test_subject_tag_new(self):
+ "Should set SUBJECT_TAG_NEW global correctly"
+ generate_global_tags(u"projectX-bug")
+ self.failUnlessEqual(SUBJECT_TAG_NEW, u"[projectX-bug:submit]")
+ def test_subject_tag_control(self):
+ "Should set SUBJECT_TAG_CONTROL global correctly"
+ generate_global_tags(u"projectX-bug")
+ self.failUnlessEqual(SUBJECT_TAG_CONTROL, u"[projectX-bug]")
+ def test_subject_tag_comment(self):
+ "Should set SUBJECT_TAG_COMMENT global correctly"
+ generate_global_tags(u"projectX-bug")
+ m = SUBJECT_TAG_COMMENT.match("[projectX-bug:xyz-123]")
+ self.failUnlessEqual(len(m.groups()), 1)
+ self.failUnlessEqual(m.group(1), u"xyz-123")
+
if __name__ == "__main__":
main()