From: W. Trevor King Date: Mon, 27 Jul 2009 18:42:17 +0000 (-0400) Subject: Cleaned up be-handle-mail's subscriber notification emails (fewer attachments). X-Git-Tag: 1.0.0~62^2~46^2~4 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=f5fdbda0472ad3b37e098561fcd52df6bf06199f;p=be.git Cleaned up be-handle-mail's subscriber notification emails (fewer attachments). Previously, every node in the DiffTree created it's own attachment. Now they're consolidated into a single attachment per bug. higher level nodes are still one attachment per node. Also: * added send_pgp_mime.append_text() * pulled guess_encoding() out of send_pgp_mime.encodedMIMEText(). * renamed data_string -> data_part in libbe.diff, since it needn't be a string. --- diff --git a/interfaces/email/interactive/be-handle-mail b/interfaces/email/interactive/be-handle-mail index 47c108e..d491a74 100755 --- a/interfaces/email/interactive/be-handle-mail +++ b/interfaces/email/interactive/be-handle-mail @@ -53,8 +53,8 @@ import doctest import unittest from becommands import subscribe -import libbe.cmdutil, libbe.encoding, libbe.utility, libbe.bugdir -import libbe.diff +import libbe.cmdutil, libbe.encoding, libbe.utility, libbe.diff, \ + libbe.bugdir, libbe.bug, libbe.comment import send_pgp_mime THIS_SERVER = u"thor.physics.drexel.edu" @@ -272,15 +272,53 @@ class Command (object): return response_generator.plain() class DiffTree (libbe.diff.DiffTree): + """ + In order to avoid tons of tiny MIMEText attachments, bug-level + nodes set .add_child_text=True (in .join()), which is propogated + on to their descendents. Instead of creating their own + attachement, each of these descendents appends his data_part to + the end of the bug-level MIMEText attachment. + + For the example tree in the libbe.diff.Diff unittests: + bugdir + bugdir/settings + bugdir/bugs + bugdir/bugs/new + bugdir/bugs/new/c <- sets .add_child_text + bugdir/bugs/rem + bugdir/bugs/rem/b <- sets .add_child_text + bugdir/bugs/mod + bugdir/bugs/mod/a <- sets .add_child_text + bugdir/bugs/mod/a/settings + bugdir/bugs/mod/a/comments + bugdir/bugs/mod/a/comments/new + bugdir/bugs/mod/a/comments/new/acom + bugdir/bugs/mod/a/comments/rem + bugdir/bugs/mod/a/comments/mod + """ def report_string(self): return send_pgp_mime.flatten(self.report(), to_unicode=True) def make_root(self): return MIMEMultipart() - def join(self, root, part): - if part != None: - root.attach(send_pgp_mime.encodedMIMEText(part)) - def data_string(self, depth, indent=False): - return libbe.diff.DiffTree.data_string(self, depth, indent=indent) + def join(self, root, parent, data_part): + if hasattr(parent, "attach_child_text"): + self.attach_child_text = True + if data_part != None: + send_pgp_mime.append_text(parent.data_mime_part, u"\n\n%s" % (data_part)) + self.data_mime_part = parent.data_mime_part + else: + self.data_mime_part = None + if data_part != None: + self.data_mime_part = send_pgp_mime.encodedMIMEText(data_part) + if parent != None and parent.name in ["new", "rem", "mod"]: + self.attach_child_text = True + if data_part == None: # make blank data_mime_part for children's appends + self.data_mime_part = send_pgp_mime.encodedMIMEText("") + if self.data_mime_part != None: + self.data_mime_part["Content-Description"] = self.name + root.attach(self.data_mime_part) + def data_part(self, depth, indent=False): + return libbe.diff.DiffTree.data_part(self, depth, indent=indent) class Diff (libbe.diff.Diff): def bug_add_string(self, bug): @@ -717,7 +755,7 @@ def main(): if options.notify_since != None: if options.subscribers == True: - libbe.encoding.set_IO_stream_encodings(ENCODING) # _after_ reading message + libbe.encoding.set_IO_stream_encodings(ENCODING) open_logfile(options.logfile) if LOGFILE != None: LOGFILE.write(u"Checking for subscribers to notify since revision %s\n" diff --git a/interfaces/email/interactive/send_pgp_mime.py b/interfaces/email/interactive/send_pgp_mime.py index 09ac0ed..55767b3 100644 --- a/interfaces/email/interactive/send_pgp_mime.py +++ b/interfaces/email/interactive/send_pgp_mime.py @@ -153,25 +153,35 @@ def header_from_text(text, encoding="us-ascii"): p = Parser() return p.parsestr(text, headersonly=True) +def guess_encoding(text): + if type(text) == types.StringType: + encoding = "us-ascii" + elif type(text) == types.UnicodeType: + for encoding in ["us-ascii", "iso-8859-1", "utf-8"]: + try: + text.encode(encoding) + except UnicodeError: + pass + else: + break + assert encoding != None + return encoding + def encodedMIMEText(body, encoding=None): if encoding == None: - if type(body) == types.StringType: - encoding = "us-ascii" - elif type(body) == types.UnicodeType: - for encoding in ["us-ascii", "iso-8859-1", "utf-8"]: - try: - body.encode(encoding) - except UnicodeError: - pass - else: - break - assert encoding != None - # Create the message ('plain' stands for Content-Type: text/plain) + encoding = guess_encoding(body) if encoding == "us-ascii": return MIMEText(body) else: + # Create the message ('plain' stands for Content-Type: text/plain) return MIMEText(body.encode(encoding), 'plain', encoding) +def append_text(text_part, new_text): + original_payload = text_part.get_payload(decode=True) + new_payload = u"%s%s" % (original_payload, new_text) + new_encoding = guess_encoding(new_payload) + text_part.set_payload(new_payload.encode(new_encoding), new_encoding) + def attach_root(header, root_part): """ Attach the email.Message root_part to the email.Message header diff --git a/libbe/diff.py b/libbe/diff.py index 0956624..69ccff8 100644 --- a/libbe/diff.py +++ b/libbe/diff.py @@ -59,12 +59,12 @@ class DiffTree (tree.Tree): >>> print all.report_string() target: None -> 1.0 """ - def __init__(self, name, data=None, data_string_fn=str, + def __init__(self, name, data=None, data_part_fn=str, requires_children=False, masked=False): tree.Tree.__init__(self) self.name = name self.data = data - self.data_string_fn = data_string_fn + self.data_part_fn = data_part_fn self.requires_children = requires_children self.masked = masked def paths(self, parent_path=None): @@ -98,38 +98,38 @@ class DiffTree (tree.Tree): raise KeyError, "%s points to child not in %s" % (names, [c.name for c in self]) def report_string(self): return "\n".join(self.report()) - def report(self, root=None, depth=0): + def report(self, root=None, parent=None, depth=0): if root == None: root = self.make_root() if self.masked == True: return None - data_string = self.data_string(depth) - if self.data == None: - pass - elif self.requires_children == True and len(self) == 0: + data_part = self.data_part(depth) + if self.requires_children == True and len(self) == 0: pass else: - self.join(root, data_string) + self.join(root, parent, data_part) depth += 1 for child in self: - child.report(root, depth) + child.report(root, self, depth) return root def make_root(self): return [] - def join(self, root, part): - if part != None: - root.append(part) - def data_string(self, depth, indent=True): - if hasattr(self, "_cached_data_string"): - return self._cached_data_string - data_string = self.data_string_fn(self.data) + def join(self, root, parent, data_part): + if data_part != None: + root.append(data_part) + def data_part(self, depth, indent=True): + if self.data == None: + return None + if hasattr(self, "_cached_data_part"): + return self._cached_data_part + data_part = self.data_part_fn(self.data) if indent == True: - data_string_lines = data_string.splitlines() + data_part_lines = data_part.splitlines() indent = " "*(depth) line_sep = "\n"+indent - data_string = indent+line_sep.join(data_string_lines) - self._cached_data_string = data_string - return data_string + data_part = indent+line_sep.join(data_part_lines) + self._cached_data_part = data_part + return data_part class Diff (object): """