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
1=== removed directory 'lib/canonical/launchpad/mailout'
2=== removed file 'lib/canonical/launchpad/mailout/__init__.py'
3--- lib/canonical/launchpad/mailout/__init__.py 2009-06-25 05:39:50 +0000
4+++ lib/canonical/launchpad/mailout/__init__.py 1970-01-01 00:00:00 +0000
5@@ -1,70 +0,0 @@
6-# Copyright 2009 Canonical Ltd. This software is licensed under the
7-# GNU Affero General Public License version 3 (see the file LICENSE).
8-
9-from zope.security.proxy import isinstance as zope_isinstance
10-from lazr.enum import BaseItem
11-
12-def value_string(item):
13- """Return a unicode string representing an SQLObject value."""
14- if item is None:
15- return '(not set)'
16- elif zope_isinstance(item, BaseItem):
17- return item.title
18- else:
19- return unicode(item)
20-
21-
22-def text_delta(instance_delta, delta_names, state_names, interface):
23- """Return a textual delta for a Delta object.
24-
25- A list of strings is returned.
26-
27- Only modified members of the delta will be shown.
28-
29- :param instance_delta: The delta to generate a textual representation of.
30- :param delta_names: The names of all members to show changes to.
31- :param state_names: The names of all members to show only the new state
32- of.
33- :param interface: The Zope interface that the input delta compared.
34- """
35- output = []
36- indent = ' ' * 4
37-
38- # Fields for which we have old and new values.
39- for field_name in delta_names:
40- delta = getattr(instance_delta, field_name, None)
41- if delta is None:
42- continue
43- title = interface[field_name].title
44- old_item = value_string(delta['old'])
45- new_item = value_string(delta['new'])
46- output.append("%s%s: %s => %s" % (indent, title, old_item, new_item))
47- for field_name in state_names:
48- delta = getattr(instance_delta, field_name, None)
49- if delta is None:
50- continue
51- title = interface[field_name].title
52- if output:
53- output.append('')
54- output.append('%s changed to:\n\n%s' % (title, delta))
55- return '\n'.join(output)
56-
57-
58-def append_footer(main, footer):
59- """Append a footer to an email, following signature conventions.
60-
61- If there is no footer, do nothing.
62- If there is already a signature, append an additional footer.
63- If there is no existing signature, append '-- \n' and a footer.
64-
65- :param main: The main content, which may have a signature.
66- :param footer: An additional footer to append.
67- :return: a new version of main that includes the footer.
68- """
69- if footer == '':
70- footer_separator = ''
71- elif '\n-- \n' in main:
72- footer_separator = '\n'
73- else:
74- footer_separator = '\n-- \n'
75- return ''.join((main, footer_separator, footer))
76
77=== removed directory 'lib/canonical/launchpad/mailout/tests'
78=== removed file 'lib/canonical/launchpad/mailout/tests/__init__.py'
79=== modified file 'lib/lp/code/mail/codereviewcomment.py'
80--- lib/lp/code/mail/codereviewcomment.py 2010-02-22 23:11:20 +0000
81+++ lib/lp/code/mail/codereviewcomment.py 2010-03-18 22:56:30 +0000
82@@ -7,11 +7,11 @@
83 __metaclass__ = type
84
85
86+from canonical.launchpad.webapp import canonical_url
87+
88 from lp.code.enums import CodeReviewNotificationLevel
89-from canonical.launchpad.mail import format_address
90-from canonical.launchpad.mailout import append_footer
91 from lp.code.mail.branchmergeproposal import BMPMailer
92-from canonical.launchpad.webapp import canonical_url
93+from lp.services.mail.sendmail import append_footer, format_address
94
95
96 def send(comment, event):
97
98=== modified file 'lib/lp/services/mail/basemailer.py'
99--- lib/lp/services/mail/basemailer.py 2009-09-04 05:02:48 +0000
100+++ lib/lp/services/mail/basemailer.py 2010-03-18 22:56:30 +0000
101@@ -11,11 +11,11 @@
102 from smtplib import SMTPException
103
104 from canonical.launchpad.helpers import get_email_template
105-from canonical.launchpad.mailout import text_delta
106
107 from lp.services.mail.notificationrecipientset import (
108 NotificationRecipientSet)
109 from lp.services.mail.sendmail import format_address, MailController
110+from lp.services.utils import text_delta
111
112
113 class BaseMailer:
114
115=== modified file 'lib/lp/services/mail/sendmail.py'
116--- lib/lp/services/mail/sendmail.py 2010-02-12 21:40:26 +0000
117+++ lib/lp/services/mail/sendmail.py 2010-03-18 22:56:30 +0000
118@@ -15,6 +15,7 @@
119 """
120
121 __all__ = [
122+ 'append_footer',
123 'format_address',
124 'get_msgid',
125 'MailController',
126@@ -91,6 +92,26 @@
127 "Address contains carriage returns: %r" % (addr,))
128
129
130+def append_footer(main, footer):
131+ """Append a footer to an email, following signature conventions.
132+
133+ If there is no footer, do nothing.
134+ If there is already a signature, append an additional footer.
135+ If there is no existing signature, append '-- \n' and a footer.
136+
137+ :param main: The main content, which may have a signature.
138+ :param footer: An additional footer to append.
139+ :return: a new version of main that includes the footer.
140+ """
141+ if footer == '':
142+ footer_separator = ''
143+ elif '\n-- \n' in main:
144+ footer_separator = '\n'
145+ else:
146+ footer_separator = '\n-- \n'
147+ return ''.join((main, footer_separator, footer))
148+
149+
150 def format_address(name, address):
151 r"""Formats a name and address to be used as an email header.
152
153
154=== modified file 'lib/lp/services/utils.py'
155--- lib/lp/services/utils.py 2009-10-19 05:40:52 +0000
156+++ lib/lp/services/utils.py 2010-03-18 22:56:30 +0000
157@@ -7,9 +7,15 @@
158 __metaclass__ = type
159 __all__ = [
160 'iter_split',
161+ 'text_delta',
162+ 'value_string',
163 ]
164
165
166+from lazr.enum import BaseItem
167+from zope.security.proxy import isinstance as zope_isinstance
168+
169+
170 def iter_split(string, splitter):
171 """Iterate over ways to split 'string' in two with 'splitter'.
172
173@@ -27,3 +33,52 @@
174 tokens = string.split(splitter)
175 for i in reversed(range(1, len(tokens) + 1)):
176 yield splitter.join(tokens[:i]), splitter.join(tokens[i:])
177+
178+
179+def value_string(item):
180+ """Return a unicode string representing value.
181+
182+ This text is special cased for enumerated types.
183+ """
184+ if item is None:
185+ return '(not set)'
186+ elif zope_isinstance(item, BaseItem):
187+ return item.title
188+ else:
189+ return unicode(item)
190+
191+
192+def text_delta(instance_delta, delta_names, state_names, interface):
193+ """Return a textual delta for a Delta object.
194+
195+ A list of strings is returned.
196+
197+ Only modified members of the delta will be shown.
198+
199+ :param instance_delta: The delta to generate a textual representation of.
200+ :param delta_names: The names of all members to show changes to.
201+ :param state_names: The names of all members to show only the new state
202+ of.
203+ :param interface: The Zope interface that the input delta compared.
204+ """
205+ output = []
206+ indent = ' ' * 4
207+
208+ # Fields for which we have old and new values.
209+ for field_name in delta_names:
210+ delta = getattr(instance_delta, field_name, None)
211+ if delta is None:
212+ continue
213+ title = interface[field_name].title
214+ old_item = value_string(delta['old'])
215+ new_item = value_string(delta['new'])
216+ output.append("%s%s: %s => %s" % (indent, title, old_item, new_item))
217+ for field_name in state_names:
218+ delta = getattr(instance_delta, field_name, None)
219+ if delta is None:
220+ continue
221+ title = interface[field_name].title
222+ if output:
223+ output.append('')
224+ output.append('%s changed to:\n\n%s' % (title, delta))
225+ return '\n'.join(output)