2
2
# GNU Affero General Public License version 3 (see the file LICENSE).
4
4
"""Classes and utilities for Launchpad to send and receive email."""
6
from zope.security.proxy import isinstance as zope_isinstance
7
from lazr.enum import BaseItem
10
def value_string(item):
11
"""Return a unicode string representing an SQLObject value."""
14
elif zope_isinstance(item, BaseItem):
20
def text_delta(instance_delta, delta_names, state_names, interface):
21
"""Return a textual delta for a Delta object.
23
A list of strings is returned.
25
Only modified members of the delta will be shown.
27
:param instance_delta: The delta to generate a textual representation of.
28
:param delta_names: The names of all members to show changes to.
29
:param state_names: The names of all members to show only the new state
31
:param interface: The Zope interface that the input delta compared.
36
# Fields for which we have old and new values.
37
for field_name in delta_names:
38
delta = getattr(instance_delta, field_name, None)
41
title = interface[field_name].title
42
old_item = value_string(delta['old'])
43
new_item = value_string(delta['new'])
44
output.append("%s%s: %s => %s" % (indent, title, old_item, new_item))
45
for field_name in state_names:
46
delta = getattr(instance_delta, field_name, None)
49
title = interface[field_name].title
52
output.append('%s changed to:\n\n%s' % (title, delta))
53
return '\n'.join(output)
56
def append_footer(main, footer):
57
"""Append a footer to an email, following signature conventions.
59
If there is no footer, do nothing.
60
If there is already a signature, append an additional footer.
61
If there is no existing signature, append '-- \n' and a footer.
63
:param main: The main content, which may have a signature.
64
:param footer: An additional footer to append.
65
:return: a new version of main that includes the footer.
69
elif '\n-- \n' in main:
70
footer_separator = '\n'
72
footer_separator = '\n-- \n'
73
return ''.join((main, footer_separator, footer))