Merge lp:~al-maisan/launchpad/changes-url-474876 into lp:launchpad/db-devel

Proposed by Muharem Hrnjadovic
Status: Merged
Approved by: Gavin Panella
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~al-maisan/launchpad/changes-url-474876
Merge into: lp:launchpad/db-devel
Diff against target: 714 lines (+180/-99)
5 files modified
lib/lp/soyuz/doc/publishing.txt (+117/-78)
lib/lp/soyuz/interfaces/publishing.py (+16/-6)
lib/lp/soyuz/model/publishing.py (+30/-14)
lib/lp/soyuz/stories/webservice/xx-source-package-publishing.txt (+4/-1)
lib/lp/soyuz/tests/test_publishing_models.py (+13/-0)
To merge this branch: bzr merge lp:~al-maisan/launchpad/changes-url-474876
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Review via email: mp+16228@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Muharem Hrnjadovic (al-maisan) wrote :

Hello there!

This branch optimizes the database query behind the

    SourcePackagePublishingHistory.changes_file_url

property (bug #474876).

The old query (http://pastebin.ubuntu.com/342524/) joins on the following
tables:

    LibraryFileAlias, LibraryFileContent, PackageUpload, PackageUploadSource,
    SourcePackagePublishingHistory, SourcePackageRelease

In contrast, the new query (http://pastebin.ubuntu.com/342528/) only uses
these tables:

    LibraryFileAlias, PackageUpload, PackageUploadSource

The new query specifically avoids the SourcePackagePublishingHistory and the
SourcePackageRelease tables (with 758673 and 459354 rows respectively).

Please note that I refactored the lib/lp/soyuz/doc/publishing.txt test so
it is easier to read and debug it.
In order to make sure that the changes are proper, I have run the changed
test in a fresh branch that has no changes otherwise.

Tests to run:

    bin/test -vv -t publishing

No pertinent "make lint" errors or warnings.

Revision history for this message
Muharem Hrnjadovic (al-maisan) wrote :

Q/A on Soyuz dogfood:

Used an lpapi script (http://pastebin.ubuntu.com/342563/) to obtain a bunch of .changes file URLs and downloaded these using wget.

Revision history for this message
Gavin Panella (allenap) wrote :

Looks good, with the addition of the comment and unit test as we
discussed. Thanks!

<allenap> al-maisan_: Line 332, does getPublishedSources() sort the results?
<al-maisan_> allenap: yes, it does.
<allenap> al-maisan_: getChangesFilesForSources() seems to now only be used in lib/lp/soyuz/adapters/archivesourcepublication.py. Is there any way to change that to use your new query?
<al-maisan_> allenap: I am not sure, that method is selecting and pre-joining a lot more data and that probably makes sense for the web UI
<allenap> al-maisan_: Okay. Do you think you could comment in getChangesFilesForSources() that getChangesFileLFA() contains a potentially more efficient query, depending on what you need out of it.
<al-maisan_> allenap: sure, will do that.
<allenap> al-maisan_: There aren't any unit tests for getChangesFileLFA(). I can see that changes_file_url is tested in a few places, but it's not quite the same thing. Unless there's a good reason not to, could you add this?
<al-maisan_> allenap: good point, I'll add unit tests for getChangesFileLFA().

review: Approve
Revision history for this message
Muharem Hrnjadovic (al-maisan) wrote :

Hello Gavin,

I have added the comment and the unit test as discussed.

Furthermore, I converted the property into a method in order to avoid it
being computed every time someone requests a SPPH instance on the
Launchpad API.

Can you please take another quick look before I land the branch?

 http://pastebin.ubuntu.com/344031/

Thanks -- Muharem

Gavin Panella wrote:
> Review: Approve
> Looks good, with the addition of the comment and unit test as we
> discussed. Thanks!
>
> <allenap> al-maisan_: Line 332, does getPublishedSources() sort the
> results?
> <al-maisan_> allenap: yes, it does.
> <allenap> al-maisan_: getChangesFilesForSources() seems to now only be
> used in lib/lp/soyuz/adapters/archivesourcepublication.py. Is there
> any way to change that to use your new query?
> <al-maisan_> allenap: I am not sure, that method is selecting and
> pre-joining a lot more data and that probably makes sense for the web
> UI
> <allenap> al-maisan_: Okay. Do you think you could comment in
> getChangesFilesForSources() that getChangesFileLFA() contains a
> potentially more efficient query, depending on what you need out of
> it.
> <al-maisan_> allenap: sure, will do that.
Comment added.

> <allenap> al-maisan_: There aren't any unit tests for
> getChangesFileLFA(). I can see that changes_file_url is tested in a
> few places, but it's not quite the same thing. Unless there's a good
> reason not to, could you add this?
> <al-maisan_> allenap: good point, I'll add unit tests for
> getChangesFileLFA().
Done.

Best regards

--
Muharem Hrnjadovic <email address hidden>
Public key id : B2BBFCFC
Key fingerprint : A5A3 CC67 2B87 D641 103F 5602 219F 6B60 B2BB FCFC

Revision history for this message
Gavin Panella (allenap) wrote :

Your post-review changes all look good.

<allenap> al-maisan: Is it very expensive to calculate changes_file_url?
<al-maisan> allenap: it is somewhat expensive and it is calculated for each SourcePackagePublishingHistory on the LP API -- whether you're interested in it or not.
<allenap> al-maisan: By making it a method, Launchpad must field an extra HTTP request for every SPPH. Maybe that's a bigger overhead? Or do you expect that it will be called rarely?
<al-maisan> allenap: it would seem that it's not a datum of general interest .. there are some LP API apps that use it: e.g. code imports or scripts written by kees
<al-maisan> but my feeling is that it's data that's not necessarily needed whenever we access a SPPH instance
<al-maisan> .. and calculating the 'changes_file_url' property now leads the Soyuz OOPS top-10 by a big margin
<allenap> al-maisan: Okay, sounds like you have a handle on it. It can be changed later if it turns out to be otherwise, so I'm not too worried.
<allenap> al-maisan: Timeout or error?
<al-maisan> allenap: time out
<allenap> al-maisan: Wow.
<al-maisan> yeah
<allenap> al-maisan: Okay, one other thing. The test_changesFileLFA method is misnamed; I think it should be test_getChangesFileLFA(). Everything else looks fine.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/soyuz/doc/publishing.txt'
2--- lib/lp/soyuz/doc/publishing.txt 2009-12-14 13:49:03 +0000
3+++ lib/lp/soyuz/doc/publishing.txt 2009-12-21 11:43:12 +0000
4@@ -93,7 +93,7 @@
5 >>> print spph.package_signer
6 None
7
8-There is also a property that returns the changesfile URL. This is proxied
9+There is also a method that returns the .changes file URL. This is proxied
10 through the webapp rather than being a librarian URL because the changesfile
11 could be private and thus in the restricted librarian.
12
13@@ -103,13 +103,13 @@
14
15 The pmount source has no packageupload in the sampledata:
16
17- >>> print spph.changes_file_url
18+ >>> print spph.changesFileUrl()
19 None
20
21 The iceweasel source has good data:
22
23 >>> pub = spph.archive.getPublishedSources(name="iceweasel")[0]
24- >>> print pub.changes_file_url
25+ >>> print pub.changesFileUrl()
26 http://launchpad.dev/ubuntu/+archive/primary/+files/mozilla-firefox_0.9_i386.changes
27
28 There is also a helper property to determine whether the current release for
29@@ -140,7 +140,8 @@
30 'pending' state when builds are fully built but not yet published.
31
32 >>> from lp.soyuz.interfaces.build import BuildStatus
33- >>> spph = test_publisher.getPubSource(architecturehintlist='any')
34+ >>> spph = test_publisher.getPubSource(
35+ ... sourcename='abc', architecturehintlist='any')
36 >>> builds = spph.createMissingBuilds()
37 >>> for build in builds:
38 ... build.buildstate = BuildStatus.FULLYBUILT
39@@ -154,15 +155,15 @@
40 >>> build_status_summary = spph.getStatusSummaryForBuilds()
41 >>> print_build_status_summary(build_status_summary)
42 FULLYBUILT_PENDING
43- hppa build of foo 666 in ubuntutest breezy-autotest RELEASE
44- i386 build of foo 666 in ubuntutest breezy-autotest RELEASE
45+ hppa build of abc 666 in ubuntutest breezy-autotest RELEASE
46+ i386 build of abc 666 in ubuntutest breezy-autotest RELEASE
47
48 The underlying method being used here is getUnpublishedBuilds():
49
50 >>> for build in spph.getUnpublishedBuilds():
51 ... print build.title
52- hppa build of foo 666 in ubuntutest breezy-autotest RELEASE
53- i386 build of foo 666 in ubuntutest breezy-autotest RELEASE
54+ hppa build of abc 666 in ubuntutest breezy-autotest RELEASE
55+ i386 build of abc 666 in ubuntutest breezy-autotest RELEASE
56
57 Note: if the related archive for this source package publishing is
58 a rebuild archive then the status summary will always display
59@@ -173,8 +174,8 @@
60 >>> build_status_summary = spph.getStatusSummaryForBuilds()
61 >>> print_build_status_summary(build_status_summary)
62 FULLYBUILT
63- hppa build of foo 666 in ubuntutest breezy-autotest RELEASE
64- i386 build of foo 666 in ubuntutest breezy-autotest RELEASE
65+ hppa build of abc 666 in ubuntutest breezy-autotest RELEASE
66+ i386 build of abc 666 in ubuntutest breezy-autotest RELEASE
67
68 # Just set the purpose back before continuing on.
69 >>> spph.archive.purpose = ArchivePurpose.PRIMARY
70@@ -183,18 +184,18 @@
71
72 >>> from lp.soyuz.interfaces.publishing import (
73 ... PackagePublishingStatus)
74- >>> bpr = test_publisher.uploadBinaryForBuild(builds[0], 'foo-bin')
75+ >>> bpr = test_publisher.uploadBinaryForBuild(builds[0], 'abc-bin')
76 >>> bpph = test_publisher.publishBinaryInArchive(bpr, spph.archive,
77 ... status=PackagePublishingStatus.PUBLISHED)
78 >>> print_build_status_summary(spph.getStatusSummaryForBuilds())
79 FULLYBUILT_PENDING
80- i386 build of foo 666 in ubuntutest breezy-autotest RELEASE
81+ i386 build of abc 666 in ubuntutest breezy-autotest RELEASE
82
83 Nor will it be included in the unpublished builds:
84
85 >>> for build in spph.getUnpublishedBuilds():
86 ... print build.title
87- i386 build of foo 666 in ubuntutest breezy-autotest RELEASE
88+ i386 build of abc 666 in ubuntutest breezy-autotest RELEASE
89
90 By default, only FULLYBUILT builds are included in the returned
91 unpublished builds:
92@@ -210,7 +211,7 @@
93 ... BuildStatus.SUPERSEDED
94 ... ]):
95 ... print build.title
96- i386 build of foo 666 in ubuntutest breezy-autotest RELEASE
97+ i386 build of abc 666 in ubuntutest breezy-autotest RELEASE
98
99 Just switch it back to FULLYBUILT before continuing:
100
101@@ -219,14 +220,14 @@
102 After publishing the second binary, the status changes to FULLYBUILT as
103 per normal:
104
105- >>> bpr = test_publisher.uploadBinaryForBuild(builds[1], 'foo-bin')
106+ >>> bpr = test_publisher.uploadBinaryForBuild(builds[1], 'abc-bin')
107 >>> bpph = test_publisher.publishBinaryInArchive(
108 ... bpr, spph.archive,
109 ... status=PackagePublishingStatus.PUBLISHED)
110 >>> print_build_status_summary(spph.getStatusSummaryForBuilds())
111 FULLYBUILT
112- hppa build of foo 666 in ubuntutest breezy-autotest RELEASE
113- i386 build of foo 666 in ubuntutest breezy-autotest RELEASE
114+ hppa build of abc 666 in ubuntutest breezy-autotest RELEASE
115+ i386 build of abc 666 in ubuntutest breezy-autotest RELEASE
116
117 There are no longer any unpublished builds for the source package:
118
119@@ -242,41 +243,42 @@
120 >>> transaction.commit()
121 >>> print_build_status_summary(spph.getStatusSummaryForBuilds())
122 FULLYBUILT
123- hppa build of foo 666 in ubuntutest breezy-autotest RELEASE
124- i386 build of foo 666 in ubuntutest breezy-autotest RELEASE
125+ hppa build of abc 666 in ubuntutest breezy-autotest RELEASE
126+ i386 build of abc 666 in ubuntutest breezy-autotest RELEASE
127
128 If a build of a SourcePackagePublishingHistory is manually set to
129 superseded (just to cancel the build) even though the SPPH is itself
130 not marked as superseded, the status summary will not include
131 that build:
132
133- >>> spph = test_publisher.getPubSource(architecturehintlist='any')
134+ >>> spph = test_publisher.getPubSource(
135+ ... sourcename='def', architecturehintlist='any')
136 >>> builds = spph.createMissingBuilds()
137 >>> builds[0].buildstate = BuildStatus.SUPERSEDED
138 >>> builds[1].buildstate = BuildStatus.FULLYBUILT
139 >>> build_status_summary = spph.getStatusSummaryForBuilds()
140 >>> print_build_status_summary(build_status_summary)
141 FULLYBUILT_PENDING
142- i386 build of foo 666 in ubuntutest breezy-autotest RELEASE
143+ i386 build of def 666 in ubuntutest breezy-autotest RELEASE
144
145 And after publishing the other build, the normal FULLY_BUILT status
146 is achieved (without the 'canceled' build):
147
148- >>> bpr = test_publisher.uploadBinaryForBuild(builds[1], 'foo-bin')
149+ >>> bpr = test_publisher.uploadBinaryForBuild(builds[1], 'def-bin')
150 >>> bpph = test_publisher.publishBinaryInArchive(bpr, spph.archive,
151 ... status=PackagePublishingStatus.PUBLISHED)
152 >>> print_build_status_summary(spph.getStatusSummaryForBuilds())
153 FULLYBUILT
154- i386 build of foo 666 in ubuntutest breezy-autotest RELEASE
155+ i386 build of def 666 in ubuntutest breezy-autotest RELEASE
156
157 IBinaryPackagePublishingHistory also contains similar API conveniences.
158
159- >>> bpph = test_publisher.getPubBinaries()[0]
160+ >>> bpph = test_publisher.getPubBinaries(binaryname='def-bin')[0]
161 >>> verifyObject(IBinaryPackagePublishingHistory, bpph)
162 True
163
164 >>> print bpph.binary_package_name
165- foo-bin
166+ def-bin
167
168 >>> print bpph.binary_package_version
169 666
170@@ -409,23 +411,25 @@
171 two architecture-specific binaries in ubuntu/breezy-autotest.
172
173 >>> from lp.registry.interfaces.pocket import PackagePublishingPocket
174- >>> source = test_publisher.getPubSource(
175+ >>> source = test_publisher.getPubSource(
176+ ... sourcename='ghi',
177 ... architecturehintlist='any',
178 ... status=PackagePublishingStatus.PUBLISHED,
179 ... pocket=PackagePublishingPocket.PROPOSED)
180
181 >>> binaries = test_publisher.getPubBinaries(
182+ ... binaryname='ghi-bin',
183 ... pub_source=source,
184 ... status=PackagePublishingStatus.PUBLISHED,
185 ... pocket=PackagePublishingPocket.PROPOSED)
186
187 >>> print source.displayname
188- foo 666 in breezy-autotest
189+ ghi 666 in breezy-autotest
190
191 >>> for bin in binaries:
192 ... print bin.displayname
193- foo-bin 666 in breezy-autotest i386
194- foo-bin 666 in breezy-autotest hppa
195+ ghi-bin 666 in breezy-autotest i386
196+ ghi-bin 666 in breezy-autotest hppa
197
198 Using the source publication, ISecureSourcePackagePublishingHistory, we
199 can obtain the published binaries.
200@@ -440,8 +444,8 @@
201
202 >>> for build in source.getBuilds():
203 ... print build.title
204- hppa build of foo 666 in ubuntutest breezy-autotest PROPOSED
205- i386 build of foo 666 in ubuntutest breezy-autotest PROPOSED
206+ hppa build of ghi 666 in ubuntutest breezy-autotest PROPOSED
207+ i386 build of ghi 666 in ubuntutest breezy-autotest PROPOSED
208
209 Now that we know how to retrieve generated binary publication related
210 to a source publication we can exercise the API provided to copy
211@@ -513,13 +517,13 @@
212
213 >>> for bin in source.getPublishedBinaries():
214 ... print bin.displayname, bin.pocket.name, bin.status.name
215- foo-bin 666 in breezy-autotest hppa PROPOSED PUBLISHED
216- foo-bin 666 in breezy-autotest i386 PROPOSED PUBLISHED
217+ ghi-bin 666 in breezy-autotest hppa PROPOSED PUBLISHED
218+ ghi-bin 666 in breezy-autotest i386 PROPOSED PUBLISHED
219
220 >>> for bin in copied_source.getPublishedBinaries():
221 ... print bin.displayname, bin.pocket.name, bin.status.name
222- foo-bin 666 in breezy-autotest hppa UPDATES PENDING
223- foo-bin 666 in breezy-autotest i386 UPDATES PENDING
224+ ghi-bin 666 in breezy-autotest hppa UPDATES PENDING
225+ ghi-bin 666 in breezy-autotest i386 UPDATES PENDING
226
227 Note that even PENDING binary publications are returned by
228 getPublishedBinaries(), it considers both PENDING and PUBLISHED status
229@@ -609,9 +613,9 @@
230
231 >>> for pub in copied_source.getPublishedBinaries():
232 ... print pub.displayname, pub.component.name
233- foo-bin 666 in breezy-autotest hppa universe
234- foo-bin 666 in breezy-autotest hppa main
235- foo-bin 666 in breezy-autotest i386 main
236+ ghi-bin 666 in breezy-autotest hppa universe
237+ ghi-bin 666 in breezy-autotest hppa main
238+ ghi-bin 666 in breezy-autotest i386 main
239
240 The publication duplication is solved in the publishing pipeline,
241 specifically in the 'domination' state. See
242@@ -622,8 +626,8 @@
243
244 >>> for pub in copied_source.getBuiltBinaries():
245 ... print pub.displayname, pub.component.name
246- foo-bin 666 in breezy-autotest hppa universe
247- foo-bin 666 in breezy-autotest i386 main
248+ ghi-bin 666 in breezy-autotest hppa universe
249+ ghi-bin 666 in breezy-autotest i386 main
250
251 We have to re-publish the superseded and the deleted publications above
252 because it's used below.
253@@ -725,19 +729,21 @@
254 >>> cprov = getUtility(IPersonSet).getByName('cprov')
255
256 >>> ppa_source = test_publisher.getPubSource(
257+ ... sourcename='jkl',
258 ... archive=cprov.archive,
259 ... status=PackagePublishingStatus.PUBLISHED)
260 >>> ppa_binaries = test_publisher.getPubBinaries(
261+ ... binaryname='jkl-bin',
262 ... pub_source=ppa_source,
263 ... status=PackagePublishingStatus.PUBLISHED)
264
265 >>> print ppa_source.displayname, ppa_source.archive.displayname
266- foo 666 in breezy-autotest PPA for Celso Providelo
267+ jkl 666 in breezy-autotest PPA for Celso Providelo
268
269 >>> for bin in ppa_binaries:
270 ... print bin.displayname, bin.archive.displayname
271- foo-bin 666 in breezy-autotest i386 PPA for Celso Providelo
272- foo-bin 666 in breezy-autotest hppa PPA for Celso Providelo
273+ jkl-bin 666 in breezy-autotest i386 PPA for Celso Providelo
274+ jkl-bin 666 in breezy-autotest hppa PPA for Celso Providelo
275
276 Now we will copy only the source from Celso's PPA breezy-autotest to
277 hoary-test.
278@@ -764,7 +770,7 @@
279
280 >>> for build in builds:
281 ... print build.title
282- i386 build of foo 666 in ubuntutest hoary-test RELEASE
283+ i386 build of jkl 666 in ubuntutest hoary-test RELEASE
284
285 If createMissingBuilds get called again on either sources no builds
286 will get created.
287@@ -808,10 +814,12 @@
288 architecture-independent sources.
289
290 >>> ppa_source = test_publisher.getPubSource(
291+ ... sourcename='mno',
292 ... archive=cprov.archive, version="999",
293 ... status=PackagePublishingStatus.PUBLISHED)
294
295 >>> ppa_binaries = test_publisher.getPubBinaries(
296+ ... binaryname='mno-bin',
297 ... pub_source=ppa_source,
298 ... status=PackagePublishingStatus.PUBLISHED)
299
300@@ -825,7 +833,7 @@
301
302 >>> ppa_binary_i386 = ppa_binaries[0]
303 >>> print ppa_binary_i386.displayname
304- foo-bin 999 in breezy-autotest i386
305+ mno-bin 999 in breezy-autotest i386
306
307 >>> copied_binary = ppa_binary_i386.copyTo(series, pocket, archive)
308
309@@ -833,12 +841,12 @@
310
311 >>> copied_source = SourcePackagePublishingHistory.get(copied_source.id)
312 >>> print copied_source.displayname
313- foo 999 in hoary-test
314+ mno 999 in hoary-test
315
316 >>> for bin in copied_source.getPublishedBinaries():
317 ... print bin.displayname
318- foo-bin 999 in hoary-test amd64
319- foo-bin 999 in hoary-test i386
320+ mno-bin 999 in hoary-test amd64
321+ mno-bin 999 in hoary-test i386
322
323 So, no builds are created.
324
325@@ -856,23 +864,25 @@
326
327 >>> for file in source.getSourceAndBinaryLibraryFiles():
328 ... print file.filename
329- foo-bin_666_hppa.deb
330- foo-bin_666_i386.deb
331- foo_666.dsc
332+ ghi-bin_666_hppa.deb
333+ ghi-bin_666_i386.deb
334+ ghi_666.dsc
335
336 We can also publish a package in a PPA and query on its files:
337
338 >>> ppa_source = test_publisher.getPubSource(
339+ ... sourcename='pqr',
340 ... status=PackagePublishingStatus.PUBLISHED,
341 ... archive=cprov.archive)
342 >>> ppa_binaries= test_publisher.getPubBinaries(
343+ ... binaryname='pqr-bin',
344 ... pub_source=ppa_source,
345 ... status=PackagePublishingStatus.PUBLISHED)
346
347 >>> for file in ppa_source.getSourceAndBinaryLibraryFiles():
348 ... print file.filename
349- foo-bin_666_all.deb
350- foo_666.dsc
351+ pqr-bin_666_all.deb
352+ pqr_666.dsc
353
354
355 Publishing records age
356@@ -1064,6 +1074,16 @@
357 >>> cprov_sources = list(cprov.archive.getPublishedSources())
358 >>> len(cprov_sources)
359 8
360+ >>> for spph in cprov_sources:
361+ ... print spph.displayname
362+ cdrkit 1.0 in breezy-autotest
363+ iceweasel 1.0 in warty
364+ jkl 666 in hoary-test
365+ jkl 666 in breezy-autotest
366+ mno 999 in hoary-test
367+ mno 999 in breezy-autotest
368+ pmount 0.1-1 in warty
369+ pqr 666 in breezy-autotest
370
371 Now that we have a set of source publications let's get the builds in
372 its context.
373@@ -1138,7 +1158,8 @@
374 >>> sources = []
375 >>> builds = []
376 >>> for count in range(2):
377- ... spph = test_publisher.getPubSource(architecturehintlist='any')
378+ ... spph = test_publisher.getPubSource(
379+ ... sourcename='stu', architecturehintlist='any')
380 ... missing_builds = spph.createMissingBuilds()
381 ... for build in missing_builds:
382 ... build.buildstate = BuildStatus.FULLYBUILT
383@@ -1184,16 +1205,16 @@
384 ... arch) = cprov_binaries.last()
385
386 >>> print source_pub.displayname
387- foo 666 in breezy-autotest
388+ pqr 666 in breezy-autotest
389
390 >>> print binary_pub.displayname
391- foo-bin 666 in breezy-autotest i386
392+ pqr-bin 666 in breezy-autotest i386
393
394 >>> print binary.title
395- foo-bin-666
396+ pqr-bin-666
397
398 >>> print binary_name.name
399- foo-bin
400+ pqr-bin
401
402 >>> print arch.displayname
403 ubuntutest Breezy Badger Autotest i386
404@@ -1237,14 +1258,15 @@
405 >>> file_ids = [file.id for source, file, content in binary_files]
406 >>> file_ids == sorted(file_ids)
407 True
408+
409 >>> for source, file, content in binary_files:
410 ... print file.filename
411 mozilla-firefox_0.9_i386.deb
412- foo-bin_666_all.deb
413- foo-bin_666_all.deb
414- foo-bin_999_all.deb
415- foo-bin_999_all.deb
416- foo-bin_666_all.deb
417+ jkl-bin_666_all.deb
418+ jkl-bin_666_all.deb
419+ mno-bin_999_all.deb
420+ mno-bin_999_all.deb
421+ pqr-bin_666_all.deb
422
423 getPackageDiffsForSources() is also provided by `IPublishingSet`, it
424 allows callsites to retrieve all related `PackageDiff` records based
425@@ -1262,11 +1284,11 @@
426 For testing purposes we will create a `PackageDiff` for Celso's
427 'pmount' and another for Celso's 'iceweasel' sources.
428
429- >>> a_source = cprov_sources[-2]
430+ >>> a_source = cprov_sources[1]
431 >>> print a_source.displayname
432 iceweasel 1.0 in warty
433
434- >>> to_source = cprov_sources[-1]
435+ >>> to_source = cprov_sources[-2]
436 >>> print to_source.displayname
437 pmount 0.1-1 in warty
438
439@@ -1346,7 +1368,7 @@
440 None
441
442 getChangesFilesForSources(), provided by IPublishingSet, allows
443-call sites to retrieve all changesfiles related to a set of source
444+call sites to retrieve all .changes files related to a set of source
445 publications.
446
447 >>> cprov_changes = publishing_set.getChangesFilesForSources(
448@@ -1460,6 +1482,12 @@
449 >>> cprov = getUtility(IPersonSet).getByName('cprov')
450 >>> cprov_published_sources = cprov.archive.getPublishedSources(
451 ... status=PackagePublishingStatus.PUBLISHED)
452+ >>> for spph in cprov_published_sources:
453+ ... print spph.displayname
454+ jkl 666 in breezy-autotest
455+ mno 999 in breezy-autotest
456+ pmount 0.1-1 in warty
457+ pqr 666 in breezy-autotest
458
459 We use the source publications to initialise
460 `ArchiveSourcePublications`.
461@@ -1541,7 +1569,7 @@
462 a dictionary, keyed by `SourcePackagePublishingHistory `, in way they
463 can be quickly looked up when building `ArchiveSourcePublications`.
464
465- >>> real_pub = cprov_published_sources[0]
466+ >>> real_pub = cprov_published_sources[1]
467
468 Builds by source.
469
470@@ -1562,15 +1590,26 @@
471 Matches
472
473 getChangesFileBySources() returns a dictionary mapping each individual
474-source package publication to its corresponding changesfile (as a
475+source package publication to its corresponding .changes file (as a
476 LibraryFileAlias).
477
478 >>> all_cprov_sources = cprov.archive.getPublishedSources()
479+ >>> for spph in all_cprov_sources:
480+ ... print spph.displayname
481+ cdrkit 1.0 in breezy-autotest
482+ foo 666 in breezy-autotest
483+ iceweasel 1.0 in warty
484+ jkl 666 in hoary-test
485+ jkl 666 in breezy-autotest
486+ mno 999 in hoary-test
487+ mno 999 in breezy-autotest
488+ pmount 0.1-1 in warty
489+ pqr 666 in breezy-autotest
490
491 We select the only available publication in Celso's PPA with a valid
492-changesfile in the sampledata.
493+.changes file in the sampledata.
494
495- >>> pub_with_changes = all_cprov_sources[-2]
496+ >>> pub_with_changes = all_cprov_sources[2]
497 >>> the_source = pub_with_changes.sourcepackagerelease
498 >>> the_change = the_source.upload_changesfile
499 >>> print the_change.filename
500@@ -1592,7 +1631,7 @@
501 whole difference when rendering PPA pages with many source
502 publications.
503
504- >>> decorated_pub = list(decorated_set)[0]
505+ >>> decorated_pub = list(decorated_set)[1]
506
507 >>> print decorated_pub
508 <...ArchiveSourcePublication ...>
509@@ -1625,17 +1664,17 @@
510 `PackageUpload.changesfile` in both, the real and the decorated
511 objects.
512
513- >>> pub_with_changes = cprov_published_sources[0]
514+ >>> pub_with_changes = cprov_published_sources[1]
515 >>> the_source = pub_with_changes.sourcepackagerelease
516 >>> changesfile = the_source.upload_changesfile
517 >>> print '%s (%s)' % (changesfile.filename, changesfile.content.md5)
518- foo_999_source.changes (6168e17ba012fc3db6dc77e255243bd1)
519+ mno_999_source.changes (6168e17ba012fc3db6dc77e255243bd1)
520
521- >>> decorated_pub_with_changes = list(decorated_set)[0]
522+ >>> decorated_pub_with_changes = list(decorated_set)[1]
523 >>> decorated_source = decorated_pub_with_changes.sourcepackagerelease
524 >>> changesfile = decorated_source.upload_changesfile
525 >>> print '%s (%s)' % (changesfile.filename, changesfile.content.md5)
526- foo_999_source.changes (6168e17ba012fc3db6dc77e255243bd1)
527+ mno_999_source.changes (6168e17ba012fc3db6dc77e255243bd1)
528
529 `ArchiveSourcePublication` also has a decorated version of the
530 getStatusSummaryForBuilds() method.
531@@ -1643,7 +1682,7 @@
532 >>> print_build_status_summary(
533 ... decorated_pub.getStatusSummaryForBuilds())
534 FULLYBUILT
535- i386 build of foo 999 in ubuntutest breezy-autotest RELEASE
536+ i386 build of mno 999 in ubuntutest breezy-autotest RELEASE
537
538 We can verify that this decorated version is in fact using the cached
539 builds by explicitly modifying the cached builds on the delegate. We'll
540@@ -1653,8 +1692,8 @@
541 >>> print_build_status_summary(
542 ... decorated_pub.getStatusSummaryForBuilds())
543 FULLYBUILT
544- i386 build of foo 999 in ubuntutest breezy-autotest RELEASE
545- i386 build of foo 999 in ubuntutest breezy-autotest RELEASE
546+ i386 build of mno 999 in ubuntutest breezy-autotest RELEASE
547+ i386 build of mno 999 in ubuntutest breezy-autotest RELEASE
548
549
550 IPublishingSet.getBuildStatusSummariesForSourceIdsAndArchive()
551
552=== modified file 'lib/lp/soyuz/interfaces/publishing.py'
553--- lib/lp/soyuz/interfaces/publishing.py 2009-12-12 03:25:27 +0000
554+++ lib/lp/soyuz/interfaces/publishing.py 2009-12-21 11:43:12 +0000
555@@ -527,12 +527,6 @@
556 title=_("Source Package Version"),
557 required=False, readonly=True))
558
559- changes_file_url = exported(
560- Text(
561- title=_("Changes File URL"),
562- description=_("A URL for this source publication's changes file "
563- "for the source upload.")))
564-
565 source_file_urls = exported(
566 List(
567 value_type=Text(),
568@@ -612,6 +606,13 @@
569 :return: a list of `IBuilds`.
570 """
571
572+ @export_read_operation()
573+ def changesFileUrl():
574+ """The .changes file URL for this source publication.
575+
576+ :return: the .changes file URL for this source (a string).
577+ """
578+
579 def getUnpublishedBuilds(build_states=None):
580 """Return a resultset of `IBuild` objects in this context that are
581 not published.
582@@ -1089,6 +1090,15 @@
583 `SourcePackageRelease`, `LibraryFileAlias`, `LibraryFileContent`)
584 """
585
586+ def getChangesFileLFA(spr):
587+ """The changes file for the given `SourcePackageRelease`.
588+
589+ :param spr: the `SourcePackageRelease` for which to return the
590+ changes file `LibraryFileAlias`.
591+
592+ :return: a `LibraryFileAlias` instance or None
593+ """
594+
595 def requestDeletion(sources, removed_by, removal_comment=None):
596 """Delete the source and binary publications specified.
597
598
599=== modified file 'lib/lp/soyuz/model/publishing.py'
600--- lib/lp/soyuz/model/publishing.py 2009-12-14 13:49:03 +0000
601+++ lib/lp/soyuz/model/publishing.py 2009-12-21 11:43:12 +0000
602@@ -593,29 +593,28 @@
603
604 return DecoratedResultSet(result_set, result_to_build)
605
606- @property
607- def changes_file_url(self):
608+ def changesFileUrl(self):
609 """See `ISourcePackagePublishingHistory`."""
610- results = getUtility(IPublishingSet).getChangesFilesForSources(
611- self)
612+ # We use getChangesFileLFA() as opposed to getChangesFilesForSources()
613+ # because the latter is more geared towards the web UI and taxes the
614+ # db much more in terms of the join width and the pre-joined data.
615+ #
616+ # This method is accessed overwhelmingly via the LP API and calling
617+ # getChangesFileLFA() which is much lighter on the db has the
618+ # potential of performing significantly better.
619+ changes_lfa = getUtility(IPublishingSet).getChangesFileLFA(
620+ self.sourcepackagerelease)
621
622- result = results.one()
623- if result is None:
624+ if changes_lfa is None:
625 # This should not happen in practice, but the code should
626 # not blow up because of bad data.
627 return None
628- source, packageupload, spr, changesfile, lfc = result
629
630 # Return a webapp-proxied LibraryFileAlias so that restricted
631 # librarian files are accessible. Non-restricted files will get
632 # a 302 so that webapp threads are not tied up.
633-
634- # Avoid circular imports.
635- from canonical.launchpad.browser.librarian import (
636- ProxiedLibraryFileAlias)
637-
638- proxied_file = ProxiedLibraryFileAlias(changesfile, self.archive)
639- return proxied_file.http_url
640+ the_url = self._proxied_urls((changes_lfa,), self.archive)[0]
641+ return the_url
642
643 def createMissingBuilds(self, architectures_available=None,
644 pas_verify=None, logger=None):
645@@ -1584,6 +1583,23 @@
646 result_set.order_by(SourcePackagePublishingHistory.id)
647 return result_set
648
649+ def getChangesFileLFA(self, spr):
650+ """See `IPublishingSet`."""
651+ # Import PackageUpload and PackageUploadSource locally to avoid
652+ # circular imports.
653+ from lp.soyuz.model.queue import PackageUpload, PackageUploadSource
654+
655+ store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR)
656+ result_set = store.find(
657+ LibraryFileAlias,
658+ LibraryFileAlias.id == PackageUpload.changesfileID,
659+ PackageUpload.status == PackageUploadStatus.DONE,
660+ PackageUpload.distroseriesID == spr.upload_distroseriesID,
661+ PackageUpload.archiveID == spr.upload_archiveID,
662+ PackageUpload.id == PackageUploadSource.packageuploadID,
663+ PackageUploadSource.sourcepackagereleaseID == spr.id)
664+ return result_set.one()
665+
666 def getBuildStatusSummariesForSourceIdsAndArchive(self,
667 source_ids,
668 archive):
669
670=== modified file 'lib/lp/soyuz/stories/webservice/xx-source-package-publishing.txt'
671--- lib/lp/soyuz/stories/webservice/xx-source-package-publishing.txt 2009-12-10 13:21:06 +0000
672+++ lib/lp/soyuz/stories/webservice/xx-source-package-publishing.txt 2009-12-21 11:43:12 +0000
673@@ -112,7 +112,6 @@
674 >>> pprint_entry(pubs['entries'][0])
675 archive_link: u'http://.../~cprov/+archive/ppa'
676 binary_file_urls: []
677- changes_file_url: u'http://launchpad.dev/~cprov/+archive/ppa/+files/testwebservice_666_source.changes'
678 component_name: u'main'
679 date_created: ...
680 date_made_pending: None
681@@ -136,6 +135,10 @@
682 source_package_version: u'666'
683 status: u'Pending'
684
685+ >>> webservice.named_get(
686+ ... pubs['entries'][0]['self_link'], 'changesFileUrl').jsonBody()
687+ u'http://launchpad.dev/~cprov/+archive/ppa/+files/testwebservice_666_source.changes'
688+
689
690 Unsigned sources
691 ================
692
693=== modified file 'lib/lp/soyuz/tests/test_publishing_models.py'
694--- lib/lp/soyuz/tests/test_publishing_models.py 2009-07-17 02:25:09 +0000
695+++ lib/lp/soyuz/tests/test_publishing_models.py 2009-12-21 11:43:12 +0000
696@@ -76,5 +76,18 @@
697 # even though it is no longer published.
698 self.assertContentEqual(self.builds[1:3], unpublished_builds)
699
700+ def test_getChangesFileLFA(self):
701+ # The getChangesFileLFA() method finds the right LFAs.
702+ lfas = (
703+ self.publishing_set.getChangesFileLFA(hist.sourcepackagerelease)
704+ for hist in self.sources)
705+ urls = [lfa.http_url for lfa in lfas]
706+ self.assertEqual(urls, [
707+ 'http://localhost:58000/94/gedit_666_source.changes',
708+ 'http://localhost:58000/96/firefox_666_source.changes',
709+ 'http://localhost:58000/98/getting-things-gnome_666_source.changes'
710+ ])
711+
712+
713 def test_suite():
714 return unittest.TestLoader().loadTestsFromName(__name__)

Subscribers

People subscribed via source and target branches

to status/vote changes: