Merge lp:~thumper/launchpad/move-mailout-functions into lp:launchpad

Proposed by Tim Penhey
Status: Merged
Approved by: Michael Hudson-Doyle
Approved revision: no longer in the source branch.
Merged at revision: 10549
Proposed branch: lp:~thumper/launchpad/move-mailout-functions
Merge into: lp:launchpad
Diff against target: 225 lines (+80/-74)
5 files modified
lib/canonical/launchpad/mailout/__init__.py (+0/-70)
lib/lp/code/mail/codereviewcomment.py (+3/-3)
lib/lp/services/mail/basemailer.py (+1/-1)
lib/lp/services/mail/sendmail.py (+21/-0)
lib/lp/services/utils.py (+55/-0)
To merge this branch: bzr merge lp:~thumper/launchpad/move-mailout-functions
Reviewer Review Type Date Requested Status
Michael Hudson-Doyle Approve
Review via email: mp+21689@code.launchpad.net

Commit message

Move functions from canonical.launchpad.mailout into lp.services.utils and lp.services.mail.sendmail.

Description of the change

A simple refactoring moving some functions from canonical.launchpad.mailout into lp.services.mail.

This makes the canonical.launchpad.mailout completely empty, so removes that module as well.

To post a comment you must log in.
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

It looks good. Some minor pedantry:

1) I don't think the docstring of value_string should mention SQLObject any more.

2) The imports in lp.services.util are not properly sorted.

Yay for killing stuff in canonical.launchpad! Please land.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== removed directory 'lib/canonical/launchpad/mailout'
=== removed file 'lib/canonical/launchpad/mailout/__init__.py'
--- lib/canonical/launchpad/mailout/__init__.py 2009-06-25 05:39:50 +0000
+++ lib/canonical/launchpad/mailout/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,70 +0,0 @@
1# Copyright 2009 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4from zope.security.proxy import isinstance as zope_isinstance
5from lazr.enum import BaseItem
6
7def value_string(item):
8 """Return a unicode string representing an SQLObject value."""
9 if item is None:
10 return '(not set)'
11 elif zope_isinstance(item, BaseItem):
12 return item.title
13 else:
14 return unicode(item)
15
16
17def text_delta(instance_delta, delta_names, state_names, interface):
18 """Return a textual delta for a Delta object.
19
20 A list of strings is returned.
21
22 Only modified members of the delta will be shown.
23
24 :param instance_delta: The delta to generate a textual representation of.
25 :param delta_names: The names of all members to show changes to.
26 :param state_names: The names of all members to show only the new state
27 of.
28 :param interface: The Zope interface that the input delta compared.
29 """
30 output = []
31 indent = ' ' * 4
32
33 # Fields for which we have old and new values.
34 for field_name in delta_names:
35 delta = getattr(instance_delta, field_name, None)
36 if delta is None:
37 continue
38 title = interface[field_name].title
39 old_item = value_string(delta['old'])
40 new_item = value_string(delta['new'])
41 output.append("%s%s: %s => %s" % (indent, title, old_item, new_item))
42 for field_name in state_names:
43 delta = getattr(instance_delta, field_name, None)
44 if delta is None:
45 continue
46 title = interface[field_name].title
47 if output:
48 output.append('')
49 output.append('%s changed to:\n\n%s' % (title, delta))
50 return '\n'.join(output)
51
52
53def append_footer(main, footer):
54 """Append a footer to an email, following signature conventions.
55
56 If there is no footer, do nothing.
57 If there is already a signature, append an additional footer.
58 If there is no existing signature, append '-- \n' and a footer.
59
60 :param main: The main content, which may have a signature.
61 :param footer: An additional footer to append.
62 :return: a new version of main that includes the footer.
63 """
64 if footer == '':
65 footer_separator = ''
66 elif '\n-- \n' in main:
67 footer_separator = '\n'
68 else:
69 footer_separator = '\n-- \n'
70 return ''.join((main, footer_separator, footer))
710
=== removed directory 'lib/canonical/launchpad/mailout/tests'
=== removed file 'lib/canonical/launchpad/mailout/tests/__init__.py'
=== modified file 'lib/lp/code/mail/codereviewcomment.py'
--- lib/lp/code/mail/codereviewcomment.py 2010-02-22 23:11:20 +0000
+++ lib/lp/code/mail/codereviewcomment.py 2010-03-18 22:56:30 +0000
@@ -7,11 +7,11 @@
7__metaclass__ = type7__metaclass__ = type
88
99
10from canonical.launchpad.webapp import canonical_url
11
10from lp.code.enums import CodeReviewNotificationLevel12from lp.code.enums import CodeReviewNotificationLevel
11from canonical.launchpad.mail import format_address
12from canonical.launchpad.mailout import append_footer
13from lp.code.mail.branchmergeproposal import BMPMailer13from lp.code.mail.branchmergeproposal import BMPMailer
14from canonical.launchpad.webapp import canonical_url14from lp.services.mail.sendmail import append_footer, format_address
1515
1616
17def send(comment, event):17def send(comment, event):
1818
=== modified file 'lib/lp/services/mail/basemailer.py'
--- lib/lp/services/mail/basemailer.py 2009-09-04 05:02:48 +0000
+++ lib/lp/services/mail/basemailer.py 2010-03-18 22:56:30 +0000
@@ -11,11 +11,11 @@
11from smtplib import SMTPException11from smtplib import SMTPException
1212
13from canonical.launchpad.helpers import get_email_template13from canonical.launchpad.helpers import get_email_template
14from canonical.launchpad.mailout import text_delta
1514
16from lp.services.mail.notificationrecipientset import (15from lp.services.mail.notificationrecipientset import (
17 NotificationRecipientSet)16 NotificationRecipientSet)
18from lp.services.mail.sendmail import format_address, MailController17from lp.services.mail.sendmail import format_address, MailController
18from lp.services.utils import text_delta
1919
2020
21class BaseMailer:21class BaseMailer:
2222
=== modified file 'lib/lp/services/mail/sendmail.py'
--- lib/lp/services/mail/sendmail.py 2010-02-12 21:40:26 +0000
+++ lib/lp/services/mail/sendmail.py 2010-03-18 22:56:30 +0000
@@ -15,6 +15,7 @@
15"""15"""
1616
17__all__ = [17__all__ = [
18 'append_footer',
18 'format_address',19 'format_address',
19 'get_msgid',20 'get_msgid',
20 'MailController',21 'MailController',
@@ -91,6 +92,26 @@
91 "Address contains carriage returns: %r" % (addr,))92 "Address contains carriage returns: %r" % (addr,))
9293
9394
95def append_footer(main, footer):
96 """Append a footer to an email, following signature conventions.
97
98 If there is no footer, do nothing.
99 If there is already a signature, append an additional footer.
100 If there is no existing signature, append '-- \n' and a footer.
101
102 :param main: The main content, which may have a signature.
103 :param footer: An additional footer to append.
104 :return: a new version of main that includes the footer.
105 """
106 if footer == '':
107 footer_separator = ''
108 elif '\n-- \n' in main:
109 footer_separator = '\n'
110 else:
111 footer_separator = '\n-- \n'
112 return ''.join((main, footer_separator, footer))
113
114
94def format_address(name, address):115def format_address(name, address):
95 r"""Formats a name and address to be used as an email header.116 r"""Formats a name and address to be used as an email header.
96117
97118
=== modified file 'lib/lp/services/utils.py'
--- lib/lp/services/utils.py 2009-10-19 05:40:52 +0000
+++ lib/lp/services/utils.py 2010-03-18 22:56:30 +0000
@@ -7,9 +7,15 @@
7__metaclass__ = type7__metaclass__ = type
8__all__ = [8__all__ = [
9 'iter_split',9 'iter_split',
10 'text_delta',
11 'value_string',
10 ]12 ]
1113
1214
15from lazr.enum import BaseItem
16from zope.security.proxy import isinstance as zope_isinstance
17
18
13def iter_split(string, splitter):19def iter_split(string, splitter):
14 """Iterate over ways to split 'string' in two with 'splitter'.20 """Iterate over ways to split 'string' in two with 'splitter'.
1521
@@ -27,3 +33,52 @@
27 tokens = string.split(splitter)33 tokens = string.split(splitter)
28 for i in reversed(range(1, len(tokens) + 1)):34 for i in reversed(range(1, len(tokens) + 1)):
29 yield splitter.join(tokens[:i]), splitter.join(tokens[i:])35 yield splitter.join(tokens[:i]), splitter.join(tokens[i:])
36
37
38def value_string(item):
39 """Return a unicode string representing value.
40
41 This text is special cased for enumerated types.
42 """
43 if item is None:
44 return '(not set)'
45 elif zope_isinstance(item, BaseItem):
46 return item.title
47 else:
48 return unicode(item)
49
50
51def text_delta(instance_delta, delta_names, state_names, interface):
52 """Return a textual delta for a Delta object.
53
54 A list of strings is returned.
55
56 Only modified members of the delta will be shown.
57
58 :param instance_delta: The delta to generate a textual representation of.
59 :param delta_names: The names of all members to show changes to.
60 :param state_names: The names of all members to show only the new state
61 of.
62 :param interface: The Zope interface that the input delta compared.
63 """
64 output = []
65 indent = ' ' * 4
66
67 # Fields for which we have old and new values.
68 for field_name in delta_names:
69 delta = getattr(instance_delta, field_name, None)
70 if delta is None:
71 continue
72 title = interface[field_name].title
73 old_item = value_string(delta['old'])
74 new_item = value_string(delta['new'])
75 output.append("%s%s: %s => %s" % (indent, title, old_item, new_item))
76 for field_name in state_names:
77 delta = getattr(instance_delta, field_name, None)
78 if delta is None:
79 continue
80 title = interface[field_name].title
81 if output:
82 output.append('')
83 output.append('%s changed to:\n\n%s' % (title, delta))
84 return '\n'.join(output)