1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
|
Queue Notify
============
PackageUpload has a notify() method to send emails. We need to be logged
into the security model in order to get any further.
>>> login('foo.bar@canonical.com')
Get a packageupload object for netapplet, which has a relatively intact
set of supporting sample data. It has rows in distribution,
distroseries, sourcepackagerelease, person and a librarian entry for the
changes file which are all needed for successful operation of notify().
>>> from lp.soyuz.interfaces.queue import IPackageUploadSet
>>> netapplet_upload = getUtility(IPackageUploadSet)[3]
>>> print netapplet_upload.displayname
netapplet
Set up some library files for the netapplet source package. These are
not already present in the sample data.
>>> from lp.services.librarian.interfaces import (
... ILibraryFileAliasSet)
>>> from lp.archiveuploader.tests import datadir
>>> import os
>>> netapplet_spr = netapplet_upload.sources[0].sourcepackagerelease
>>> librarian = getUtility(ILibraryFileAliasSet)
>>> files = [
... 'netapplet_1.0-1.dsc',
... 'netapplet_1.0.orig.tar.gz',
... 'netapplet_1.0-1.diff.gz',
... ]
>>> for file in files:
... filepath = datadir('suite/netapplet_1.0-1/%s' % file)
... fileobj = open(filepath, 'rb')
... filesize = os.stat(filepath).st_size
... lfa = librarian.create(file, filesize, fileobj, 'dummytype')
... sprf = netapplet_spr.addFile(lfa)
... fileobj.close()
The notify() method generates one email here on this unsigned package.
It requires an announcement list email address, a "changes_file_object"
that is just an open file object for the original changes file, and a
special logger object that will extract tracebacks for the purposes of
this doctest.
>>> changes_file_path = datadir(
... 'suite/netapplet_1.0-1/netapplet_1.0-1_source.changes')
>>> changes_file = open(changes_file_path,'r')
>>> from lp.services.log.logger import FakeLogger
>>> netapplet_upload.notify(
... changes_file_object=changes_file, logger=FakeLogger())
DEBUG Building recipients list.
DEBUG Changes file is unsigned; adding changer as recipient.
...
DEBUG Sent a mail:
...
DEBUG Recipients: ... Silverstone ...
...
DEBUG above if files already exist in other distroseries.
...
DEBUG signer of the above package.
Helper functions to examine emails that were sent:
>>> from lp.services.mail import stub
>>> from lp.testing.mail_helpers import pop_notifications
There's only one email generated from the preceding upload:
>>> [notification] = pop_notifications()
The mail headers contain our To: as set on the notify() call. The
subject contains "Accepted", the package name, its version and whether
it's source or binary. The Bcc field also always contains the
uploader's email address.
>>> notification['To']
'Daniel Silverstone <daniel.silverstone@canonical.com>'
>>> notification['Bcc']
'Root <root@localhost>'
>>> notification['Subject']
'[ubuntu/breezy-autotest] netapplet 0.99.6-1 (New)'
The mail body contains a list of files that were accepted:
>>> print notification.get_payload(0) # doctest: -NORMALIZE_WHITESPACE
From nobody ...
...
NEW: netapplet_1.0-1.dsc
NEW: netapplet_1.0.orig.tar.gz
NEW: netapplet_1.0-1.diff.gz
<BLANKLINE>
...
You may have gotten the distroseries wrong. If so, you may get warnings
above if files already exist in other distroseries.
<BLANKLINE>
-- =
<BLANKLINE>
You are receiving this email because you are the uploader, maintainer or
signer of the above package.
<BLANKLINE>
Now we will process a signed package. Signed packages will potentially
have a different recipient list to unsigned ones; recipients for signed
package uploads can be the signer, the maintainer and the changer, where
these people are different. Unsigned packages only send notifications
to the changer.
>>> from zope.security.proxy import removeSecurityProxy
>>> from lp.registry.interfaces.gpg import IGPGKeySet
>>> gpgkey = getUtility(IGPGKeySet).get(1)
>>> removeSecurityProxy(netapplet_upload).signing_key = gpgkey
Now request the email:
>>> changes_file_path = datadir(
... 'suite/netapplet_1.0-1-signed/netapplet_1.0-1_source.changes')
>>> changes_file = open(changes_file_path,'r')
>>> netapplet_upload.setAccepted()
>>> netapplet_upload.notify(
... changes_file_object=changes_file, logger=FakeLogger())
DEBUG Building recipients list.
...
DEBUG Sent a mail:
...
DEBUG Recipients: ... Bar ...
...
DEBUG Announcing to autotest_changes@ubuntu.com
...
DEBUG Sent a mail:
...
There are two emails, the upload acknowledgement and the announcement,
because this upload is already accepted.
>>> msgs = pop_notifications()
>>> len(msgs)
2
The mail 'To:' addresses contain the signer and the changer's email.
The announcement email contains the serieses changeslist.
>>> def to_lower(address):
... """Return lower-case version of email address."""
... return address.lower()
>>> def extract_addresses(header_field):
... """Extract and sort addresses from an email header field."""
... return sorted(
... [addr.strip() for addr in header_field.split(',')],
... key=to_lower)
>>> for addr in extract_addresses(msgs[0]['To']):
... print addr
Daniel Silverstone <daniel.silverstone@canonical.com>
Foo Bar <foo.bar@canonical.com>
>>> print msgs[1]['To']
autotest_changes@ubuntu.com
The mail 'Bcc:' address is the uploader. The announcement has the
uploader and the Debian derivatives address for the package uploaded.
>>> for msg in msgs:
... print extract_addresses(msg['Bcc'])
['Root <root@localhost>']
['netapplet_derivatives@packages.qa.debian.org', 'Root <root@localhost>']
The mail 'From:' addresses are the uploader and the changer.
>>> for msg in msgs:
... print msg['From']
Root <root@localhost>
Daniel Silverstone <daniel.silverstone@canonical.com>
>>> print notification['Subject']
[ubuntu/breezy-autotest] netapplet 0.99.6-1 (New)
The mail body contains the same list of files again:
>>> print notification.get_payload(0) # doctest: -NORMALIZE_WHITESPACE
From nobody ...
...
NEW: netapplet_1.0-1.dsc
NEW: netapplet_1.0.orig.tar.gz
NEW: netapplet_1.0-1.diff.gz
<BLANKLINE>
...
You may have gotten the distroseries wrong. If so, you may get warnings
above if files already exist in other distroseries.
<BLANKLINE>
-- =
<BLANKLINE>
You are receiving this email because you are the uploader, maintainer or
signer of the above package.
<BLANKLINE>
notify() will also work without passing the changes_file_object
parameter provided that everything is already committed to the database
(which is not the case when nascent upload runs). This example
demonstrates this usage:
>>> from canonical.librarian.testing.server import fillLibrarianFile
>>> changes_file = open(changes_file_path,"r")
>>> fillLibrarianFile(1, content=changes_file.read())
>>> changes_file.close()
>>> netapplet_upload.setNew()
>>> netapplet_upload.notify(logger=FakeLogger())
DEBUG Building recipients list.
...
DEBUG Sent a mail:
...
DEBUG Recipients: ... Silverstone ...
...
DEBUG above if files already exist in other distroseries.
...
DEBUG signer of the above package.
Only one email is generated:
>>> [notification] = pop_notifications()
The mail headers are the same as before:
>>> for addr in extract_addresses(notification['To']):
... print addr
Daniel Silverstone <daniel.silverstone@canonical.com>
Foo Bar <foo.bar@canonical.com>
>>> print notification['Bcc']
Root <root@localhost>
>>> print notification['Subject']
[ubuntu/breezy-autotest] netapplet 0.99.6-1 (New)
The mail body contains the same list of files again:
>>> print notification.get_payload(0) # doctest: -NORMALIZE_WHITESPACE
From nobody ...
...
NEW: netapplet_1.0-1.dsc
NEW: netapplet_1.0.orig.tar.gz
NEW: netapplet_1.0-1.diff.gz
<BLANKLINE>
...
You may have gotten the distroseries wrong. If so, you may get warnings
above if files already exist in other distroseries.
<BLANKLINE>
-- =
<BLANKLINE>
You are receiving this email because you are the uploader, maintainer or
signer of the above package.
<BLANKLINE>
notify() will also generate rejection notices if the upload failed. The
summary_text argument is text that is appended to any auto-generated
text for the summary. Rejections don't currently auto-generate
anything.
>>> netapplet_upload.setRejected()
>>> netapplet_upload.notify(
... summary_text="Testing rejection message", logger=FakeLogger())
DEBUG Building recipients list.
...
DEBUG Sending rejection email.
...
DEBUG Subject: [ubuntu/breezy-autotest] netapplet 0.99.6-1 (Rejected)
DEBUG Sender: Root <root@localhost>
DEBUG Recipients: ... Bar ...
DEBUG Bcc: Root <root@localhost>
DEBUG Body:
DEBUG Rejected:
DEBUG Testing rejection message
...
DEBUG If you don't understand why your files were rejected, or if the
...
DEBUG signer of the above package.
Only one email is generated:
>>> transaction.commit()
>>> len(stub.test_emails)
1
Clean up, otherwise stuff is left lying around in /var/tmp.
>>> from canonical.testing.layers import LibrarianLayer
>>> LibrarianLayer.librarian_fixture.clear()
|