Merge lp:~stevenk/launchpad/moar-preload-distroseries-queue into lp:launchpad
- moar-preload-distroseries-queue
- Merge into devel
Proposed by
Steve Kowalik
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Approved by: | Steve Kowalik | ||||||||
Approved revision: | no longer in the source branch. | ||||||||
Merged at revision: | 16396 | ||||||||
Proposed branch: | lp:~stevenk/launchpad/moar-preload-distroseries-queue | ||||||||
Merge into: | lp:launchpad | ||||||||
Diff against target: |
568 lines (+139/-84) 11 files modified
lib/lp/security.py (+4/-6) lib/lp/services/webapp/adapter.py (+0/-4) lib/lp/soyuz/browser/queue.py (+19/-22) lib/lp/soyuz/browser/tests/test_queue.py (+23/-2) lib/lp/soyuz/configure.zcml (+2/-1) lib/lp/soyuz/model/archive.py (+1/-1) lib/lp/soyuz/model/binarypackagebuild.py (+1/-1) lib/lp/soyuz/model/publishing.py (+12/-19) lib/lp/soyuz/model/queue.py (+60/-21) lib/lp/soyuz/model/sourcepackagerelease.py (+4/-7) lib/lp/soyuz/tests/test_packageupload.py (+13/-0) |
||||||||
To merge this branch: | bzr merge lp:~stevenk/launchpad/moar-preload-distroseries-queue | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
William Grant | code | Approve | |
Review via email: mp+141581@code.launchpad.net |
Commit message
Teach IPackageUploadS
Description of the change
Force the PackageUpload security adapter to use the cachedproperties on it, after making sure they are set carefully in add{Source,
Do lots of preloading in IPackageUploadS
Write two query count tests, one for DistroSeries:
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/security.py' |
2 | --- lib/lp/security.py 2012-12-19 22:01:13 +0000 |
3 | +++ lib/lp/security.py 2013-01-03 00:18:23 +0000 |
4 | @@ -1,8 +1,6 @@ |
5 | # Copyright 2009-2012 Canonical Ltd. This software is licensed under the |
6 | # GNU Affero General Public License version 3 (see the file LICENSE). |
7 | |
8 | -# pylint: disable-msg=F0401 |
9 | - |
10 | """Security policies for using content objects.""" |
11 | |
12 | __metaclass__ = type |
13 | @@ -1836,10 +1834,10 @@ |
14 | # We cannot use self.obj.sourcepackagerelease, as that causes |
15 | # interference with the property cache if we are called in the |
16 | # process of adding a source or a build. |
17 | - if not self.obj._sources.is_empty(): |
18 | - spr = self.obj._sources[0].sourcepackagerelease |
19 | - elif not self.obj._builds.is_empty(): |
20 | - spr = self.obj._builds[0].build.source_package_release |
21 | + if self.obj.sources: |
22 | + spr = self.obj.sources[0].sourcepackagerelease |
23 | + elif self.obj.builds: |
24 | + spr = self.obj.builds[0].build.source_package_release |
25 | else: |
26 | spr = None |
27 | if spr is not None: |
28 | |
29 | === modified file 'lib/lp/services/webapp/adapter.py' |
30 | --- lib/lp/services/webapp/adapter.py 2012-11-29 18:08:12 +0000 |
31 | +++ lib/lp/services/webapp/adapter.py 2013-01-03 00:18:23 +0000 |
32 | @@ -1,9 +1,6 @@ |
33 | # Copyright 2009-2011 Canonical Ltd. This software is licensed under the |
34 | # GNU Affero General Public License version 3 (see the file LICENSE). |
35 | |
36 | -# We use global in this module. |
37 | -# pylint: disable-msg=W0602 |
38 | - |
39 | __metaclass__ = type |
40 | |
41 | from functools import partial |
42 | @@ -442,7 +439,6 @@ |
43 | for using connections from the main thread. |
44 | """ |
45 | # Record the ID of the main thread. |
46 | - # pylint: disable-msg=W0603 |
47 | global _main_thread_id |
48 | _main_thread_id = thread.get_ident() |
49 | |
50 | |
51 | === modified file 'lib/lp/soyuz/browser/queue.py' |
52 | --- lib/lp/soyuz/browser/queue.py 2012-12-12 03:35:48 +0000 |
53 | +++ lib/lp/soyuz/browser/queue.py 2013-01-03 00:18:23 +0000 |
54 | @@ -10,7 +10,7 @@ |
55 | 'QueueItemsView', |
56 | ] |
57 | |
58 | -import operator |
59 | +from operator import attrgetter |
60 | |
61 | from lazr.delegates import delegates |
62 | from zope.component import getUtility |
63 | @@ -20,7 +20,7 @@ |
64 | NotFoundError, |
65 | UnexpectedFormData, |
66 | ) |
67 | -from lp.registry.model.person import Person |
68 | +from lp.registry.interfaces.person import IPersonSet |
69 | from lp.services.database.bulk import ( |
70 | load_referencing, |
71 | load_related, |
72 | @@ -55,8 +55,10 @@ |
73 | ) |
74 | from lp.soyuz.interfaces.section import ISectionSet |
75 | from lp.soyuz.model.archive import Archive |
76 | +from lp.soyuz.model.component import Component |
77 | from lp.soyuz.model.packagecopyjob import PackageCopyJob |
78 | from lp.soyuz.model.queue import PackageUploadSource |
79 | +from lp.soyuz.model.section import Section |
80 | from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease |
81 | |
82 | |
83 | @@ -124,8 +126,7 @@ |
84 | build_ids = [binary_file.binarypackagerelease.build.id |
85 | for binary_file in binary_files] |
86 | upload_set = getUtility(IPackageUploadSet) |
87 | - package_upload_builds = upload_set.getBuildByBuildIDs( |
88 | - build_ids) |
89 | + package_upload_builds = upload_set.getBuildByBuildIDs(build_ids) |
90 | package_upload_builds_dict = {} |
91 | for package_upload_build in package_upload_builds: |
92 | package_upload_builds_dict[ |
93 | @@ -135,8 +136,8 @@ |
94 | def binary_files_dict(self, package_upload_builds_dict, binary_files): |
95 | """Build a dictionary of lists of binary files keyed by upload ID. |
96 | |
97 | - To do this efficiently we need to get all the PacakgeUploadBuild |
98 | - records at once, otherwise the Ibuild.package_upload property |
99 | + To do this efficiently we need to get all the PackageUploadBuild |
100 | + records at once, otherwise the IBuild.package_upload property |
101 | causes one query per iteration of the loop. |
102 | """ |
103 | build_upload_files = {} |
104 | @@ -208,7 +209,9 @@ |
105 | PackageCopyJob, uploads, ['package_copy_job_id']) |
106 | load_related(Archive, package_copy_jobs, ['source_archive_id']) |
107 | jobs = load_related(Job, package_copy_jobs, ['job_id']) |
108 | - load_related(Person, jobs, ['requester_id']) |
109 | + person_ids = map(attrgetter('requester_id'), jobs) |
110 | + list(getUtility(IPersonSet).getPrecachedPersonsFromIDs( |
111 | + person_ids, need_validity=True)) |
112 | |
113 | def decoratedQueueBatch(self): |
114 | """Return the current batch, converted to decorated objects. |
115 | @@ -224,20 +227,21 @@ |
116 | |
117 | upload_ids = [upload.id for upload in uploads] |
118 | binary_file_set = getUtility(IBinaryPackageFileSet) |
119 | - binary_files = binary_file_set.getByPackageUploadIDs(upload_ids) |
120 | + binary_files = list(binary_file_set.getByPackageUploadIDs(upload_ids)) |
121 | binary_file_set.loadLibraryFiles(binary_files) |
122 | packageuploadsources = load_referencing( |
123 | PackageUploadSource, uploads, ['packageuploadID']) |
124 | source_file_set = getUtility(ISourcePackageReleaseFileSet) |
125 | - source_files = source_file_set.getByPackageUploadIDs(upload_ids) |
126 | - |
127 | + source_files = list(source_file_set.getByPackageUploadIDs(upload_ids)) |
128 | source_sprs = load_related( |
129 | SourcePackageRelease, packageuploadsources, |
130 | ['sourcepackagereleaseID']) |
131 | |
132 | + load_related(Section, source_sprs, ['sectionID']) |
133 | + load_related(Component, source_sprs, ['componentID']) |
134 | + |
135 | # Get a dictionary of lists of binary files keyed by upload ID. |
136 | - package_upload_builds_dict = self.builds_dict( |
137 | - upload_ids, binary_files) |
138 | + package_upload_builds_dict = self.builds_dict(upload_ids, binary_files) |
139 | |
140 | build_upload_files, binary_package_names = self.binary_files_dict( |
141 | package_upload_builds_dict, binary_files) |
142 | @@ -461,7 +465,7 @@ |
143 | sorted by their name. |
144 | """ |
145 | return sorted( |
146 | - self.context.sections, key=operator.attrgetter('name')) |
147 | + self.context.sections, key=attrgetter('name')) |
148 | |
149 | def priorities(self): |
150 | """An iterable of priorities from PackagePublishingPriority.""" |
151 | @@ -516,8 +520,6 @@ |
152 | |
153 | if self.contains_source: |
154 | self.sourcepackagerelease = self.sources[0].sourcepackagerelease |
155 | - |
156 | - if self.contains_source: |
157 | self.package_sets = package_sets.get( |
158 | self.sourcepackagerelease.sourcepackagenameID, []) |
159 | else: |
160 | @@ -561,8 +563,7 @@ |
161 | if title is None: |
162 | title = alt |
163 | return structured( |
164 | - '<img alt="[%s]" src="/@@/%s" title="%s" />', |
165 | - alt, icon, title) |
166 | + '<img alt="[%s]" src="/@@/%s" title="%s" />', alt, icon, title) |
167 | |
168 | def composeIconList(self): |
169 | """List icons that should be shown for this upload.""" |
170 | @@ -599,9 +600,5 @@ |
171 | icon_string = structured('\n'.join(['%s'] * len(icons)), *icons) |
172 | link = self.composeNameAndChangesLink() |
173 | return structured( |
174 | - """<div id="%s"> |
175 | - %s |
176 | - %s |
177 | - (%s) |
178 | - </div>""", |
179 | + """<div id="%s"> %s %s (%s)</div>""", |
180 | iconlist_id, icon_string, link, self.displayarchs).escapedtext |
181 | |
182 | === modified file 'lib/lp/soyuz/browser/tests/test_queue.py' |
183 | --- lib/lp/soyuz/browser/tests/test_queue.py 2012-12-12 04:59:52 +0000 |
184 | +++ lib/lp/soyuz/browser/tests/test_queue.py 2013-01-03 00:18:23 +0000 |
185 | @@ -6,6 +6,8 @@ |
186 | __metaclass__ = type |
187 | |
188 | from lxml import html |
189 | +from storm.store import Store |
190 | +from testtools.matchers import Equals |
191 | import transaction |
192 | from zope.component import ( |
193 | getUtility, |
194 | @@ -26,12 +28,14 @@ |
195 | login_person, |
196 | logout, |
197 | person_logged_in, |
198 | + StormStatementRecorder, |
199 | TestCaseWithFactory, |
200 | ) |
201 | from lp.testing.layers import ( |
202 | LaunchpadFunctionalLayer, |
203 | LaunchpadZopelessLayer, |
204 | ) |
205 | +from lp.testing.matchers import HasQueryCount |
206 | from lp.testing.sampledata import ADMIN_EMAIL |
207 | from lp.testing.views import create_initialized_view |
208 | |
209 | @@ -361,14 +365,31 @@ |
210 | self.assertIn( |
211 | upload.package_copy_job.job.requester.displayname, html_text) |
212 | |
213 | + def test_query_count(self): |
214 | + login(ADMIN_EMAIL) |
215 | + uploads = [] |
216 | + distroseries = self.factory.makeDistroSeries() |
217 | + for i in range(5): |
218 | + uploads.append(self.factory.makeSourcePackageUpload(distroseries)) |
219 | + uploads.append(self.factory.makeCustomPackageUpload(distroseries)) |
220 | + uploads.append(self.factory.makeCopyJobPackageUpload(distroseries)) |
221 | + for i in range(15): |
222 | + uploads.append(self.factory.makeBuildPackageUpload(distroseries)) |
223 | + queue_admin = self.factory.makeArchiveAdmin(distroseries.main_archive) |
224 | + Store.of(uploads[0]).invalidate() |
225 | + with person_logged_in(queue_admin): |
226 | + with StormStatementRecorder() as recorder: |
227 | + view = self.makeView(distroseries, queue_admin) |
228 | + view() |
229 | + self.assertThat(recorder, HasQueryCount(Equals(52))) |
230 | + |
231 | |
232 | class TestCompletePackageUpload(TestCaseWithFactory): |
233 | |
234 | layer = LaunchpadZopelessLayer |
235 | |
236 | def makeCompletePackageUpload(self, upload=None, build_upload_files=None, |
237 | - source_upload_files=None, |
238 | - package_sets=None): |
239 | + source_upload_files=None, package_sets=None): |
240 | if upload is None: |
241 | upload = self.factory.makeSourcePackageUpload() |
242 | if build_upload_files is None: |
243 | |
244 | === modified file 'lib/lp/soyuz/configure.zcml' |
245 | --- lib/lp/soyuz/configure.zcml 2012-12-10 06:27:12 +0000 |
246 | +++ lib/lp/soyuz/configure.zcml 2013-01-03 00:18:23 +0000 |
247 | @@ -192,7 +192,8 @@ |
248 | section_name |
249 | components |
250 | searchable_names |
251 | - searchable_versions"/> |
252 | + searchable_versions |
253 | + changes_file_id"/> |
254 | <require |
255 | permission="launchpad.Edit" |
256 | attributes=" |
257 | |
258 | === modified file 'lib/lp/soyuz/model/archive.py' |
259 | --- lib/lp/soyuz/model/archive.py 2012-11-13 13:43:31 +0000 |
260 | +++ lib/lp/soyuz/model/archive.py 2013-01-03 00:18:23 +0000 |
261 | @@ -1554,7 +1554,7 @@ |
262 | PackageUploadSource.sourcepackagereleaseID, |
263 | PackageUploadSource.packageuploadID == PackageUpload.id, |
264 | PackageUpload.status == PackageUploadStatus.DONE, |
265 | - PackageUpload.changesfileID == LibraryFileAlias.id, |
266 | + PackageUpload.changes_file_id == LibraryFileAlias.id, |
267 | ) |
268 | else: |
269 | raise NotFoundError(filename) |
270 | |
271 | === modified file 'lib/lp/soyuz/model/binarypackagebuild.py' |
272 | --- lib/lp/soyuz/model/binarypackagebuild.py 2012-11-15 01:42:33 +0000 |
273 | +++ lib/lp/soyuz/model/binarypackagebuild.py 2013-01-03 00:18:23 +0000 |
274 | @@ -180,7 +180,7 @@ |
275 | Join(PackageUpload, |
276 | PackageUploadBuild.packageuploadID == PackageUpload.id), |
277 | Join(LibraryFileAlias, |
278 | - LibraryFileAlias.id == PackageUpload.changesfileID), |
279 | + LibraryFileAlias.id == PackageUpload.changes_file_id), |
280 | Join(LibraryFileContent, |
281 | LibraryFileContent.id == LibraryFileAlias.contentID), |
282 | ] |
283 | |
284 | === modified file 'lib/lp/soyuz/model/publishing.py' |
285 | --- lib/lp/soyuz/model/publishing.py 2012-11-15 23:28:13 +0000 |
286 | +++ lib/lp/soyuz/model/publishing.py 2013-01-03 00:18:23 +0000 |
287 | @@ -1,8 +1,6 @@ |
288 | # Copyright 2009-2012 Canonical Ltd. This software is licensed under the |
289 | # GNU Affero General Public License version 3 (see the file LICENSE). |
290 | |
291 | -# pylint: disable-msg=E0611,W0212 |
292 | - |
293 | __metaclass__ = type |
294 | |
295 | __all__ = [ |
296 | @@ -1560,12 +1558,12 @@ |
297 | packageupload=packageupload) |
298 | DistributionSourcePackage.ensure(pub) |
299 | |
300 | - if create_dsd_job: |
301 | - if archive == distroseries.main_archive: |
302 | - dsd_job_source = getUtility(IDistroSeriesDifferenceJobSource) |
303 | - dsd_job_source.createForPackagePublication( |
304 | - distroseries, sourcepackagerelease.sourcepackagename, |
305 | - pocket) |
306 | + if create_dsd_job and archive == distroseries.main_archive: |
307 | + dsd_job_source = getUtility(IDistroSeriesDifferenceJobSource) |
308 | + dsd_job_source.createForPackagePublication( |
309 | + distroseries, sourcepackagerelease.sourcepackagename, pocket) |
310 | + Store.of(sourcepackagerelease).flush() |
311 | + del get_property_cache(sourcepackagerelease).published_archives |
312 | return pub |
313 | |
314 | def getBuildsForSourceIds(self, source_publication_ids, archive=None, |
315 | @@ -1802,8 +1800,7 @@ |
316 | |
317 | return result_set |
318 | |
319 | - def getBinaryPublicationsForSources(self, |
320 | - one_or_more_source_publications): |
321 | + def getBinaryPublicationsForSources(self, one_or_more_source_publications): |
322 | """See `IPublishingSet`.""" |
323 | source_publication_ids = self._extractIDs( |
324 | one_or_more_source_publications) |
325 | @@ -1850,11 +1847,8 @@ |
326 | |
327 | def getChangesFilesForSources(self, one_or_more_source_publications): |
328 | """See `IPublishingSet`.""" |
329 | - # Import PackageUpload and PackageUploadSource locally |
330 | - # to avoid circular imports, since PackageUpload uses |
331 | - # SourcePackagePublishingHistory. |
332 | - from lp.soyuz.model.queue import ( |
333 | - PackageUpload, PackageUploadSource) |
334 | + # Avoid circular imports. |
335 | + from lp.soyuz.model.queue import PackageUpload, PackageUploadSource |
336 | |
337 | source_publication_ids = self._extractIDs( |
338 | one_or_more_source_publications) |
339 | @@ -1864,7 +1858,7 @@ |
340 | (SourcePackagePublishingHistory, PackageUpload, |
341 | SourcePackageRelease, LibraryFileAlias, LibraryFileContent), |
342 | LibraryFileContent.id == LibraryFileAlias.contentID, |
343 | - LibraryFileAlias.id == PackageUpload.changesfileID, |
344 | + LibraryFileAlias.id == PackageUpload.changes_file_id, |
345 | PackageUpload.id == PackageUploadSource.packageuploadID, |
346 | PackageUpload.status == PackageUploadStatus.DONE, |
347 | PackageUpload.distroseriesID == |
348 | @@ -1882,14 +1876,13 @@ |
349 | |
350 | def getChangesFileLFA(self, spr): |
351 | """See `IPublishingSet`.""" |
352 | - # Import PackageUpload and PackageUploadSource locally to avoid |
353 | - # circular imports. |
354 | + # Avoid circular imports. |
355 | from lp.soyuz.model.queue import PackageUpload, PackageUploadSource |
356 | |
357 | store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR) |
358 | result_set = store.find( |
359 | LibraryFileAlias, |
360 | - LibraryFileAlias.id == PackageUpload.changesfileID, |
361 | + LibraryFileAlias.id == PackageUpload.changes_file_id, |
362 | PackageUpload.status == PackageUploadStatus.DONE, |
363 | PackageUpload.distroseriesID == spr.upload_distroseries.id, |
364 | PackageUpload.archiveID == spr.upload_archive.id, |
365 | |
366 | === modified file 'lib/lp/soyuz/model/queue.py' |
367 | --- lib/lp/soyuz/model/queue.py 2012-12-26 01:04:05 +0000 |
368 | +++ lib/lp/soyuz/model/queue.py 2013-01-03 00:18:23 +0000 |
369 | @@ -52,7 +52,10 @@ |
370 | from lp.registry.model.sourcepackagename import SourcePackageName |
371 | from lp.services.auditor.client import AuditorClient |
372 | from lp.services.config import config |
373 | -from lp.services.database.bulk import load_referencing |
374 | +from lp.services.database.bulk import ( |
375 | + load_referencing, |
376 | + load_related, |
377 | + ) |
378 | from lp.services.database.constants import UTC_NOW |
379 | from lp.services.database.datetimecol import UtcDateTimeCol |
380 | from lp.services.database.decoratedresultset import DecoratedResultSet |
381 | @@ -112,6 +115,7 @@ |
382 | QueueStateWriteProtectedError, |
383 | ) |
384 | from lp.soyuz.interfaces.section import ISectionSet |
385 | +from lp.soyuz.model.distroarchseries import DistroArchSeries |
386 | from lp.soyuz.pas import BuildDaemonPackagesArchSpecific |
387 | |
388 | # There are imports below in PackageUploadCustom for various bits |
389 | @@ -174,8 +178,8 @@ |
390 | dbName='pocket', unique=False, notNull=True, |
391 | schema=PackagePublishingPocket) |
392 | |
393 | - changesfile = ForeignKey( |
394 | - dbName='changesfile', foreignKey="LibraryFileAlias", notNull=False) |
395 | + changes_file_id = Int(name='changesfile') |
396 | + changesfile = Reference(changes_file_id, 'LibraryFileAlias.id') |
397 | |
398 | archive = ForeignKey(dbName="archive", foreignKey="Archive", notNull=True) |
399 | |
400 | @@ -814,15 +818,16 @@ |
401 | |
402 | def addSource(self, spr): |
403 | """See `IPackageUpload`.""" |
404 | - del get_property_cache(self).sources |
405 | self.addSearchableNames([spr.name]) |
406 | self.addSearchableVersions([spr.version]) |
407 | - return PackageUploadSource( |
408 | + pus = PackageUploadSource( |
409 | packageupload=self, sourcepackagerelease=spr.id) |
410 | + Store.of(self).flush() |
411 | + del get_property_cache(self).sources |
412 | + return pus |
413 | |
414 | def addBuild(self, build): |
415 | """See `IPackageUpload`.""" |
416 | - del get_property_cache(self).builds |
417 | names = [build.source_package_release.name] |
418 | versions = [] |
419 | for bpr in build.binarypackages: |
420 | @@ -830,15 +835,20 @@ |
421 | versions.append(bpr.version) |
422 | self.addSearchableNames(names) |
423 | self.addSearchableVersions(versions) |
424 | - return PackageUploadBuild(packageupload=self, build=build.id) |
425 | + pub = PackageUploadBuild(packageupload=self, build=build.id) |
426 | + Store.of(self).flush() |
427 | + del get_property_cache(self).builds |
428 | + return pub |
429 | |
430 | def addCustom(self, library_file, custom_type): |
431 | """See `IPackageUpload`.""" |
432 | - del get_property_cache(self).customfiles |
433 | self.addSearchableNames([library_file.filename]) |
434 | - return PackageUploadCustom( |
435 | + puc = PackageUploadCustom( |
436 | packageupload=self, libraryfilealias=library_file.id, |
437 | customformat=custom_type) |
438 | + Store.of(self).flush() |
439 | + del get_property_cache(self).customfiles |
440 | + return puc |
441 | |
442 | def isPPA(self): |
443 | """See `IPackageUpload`.""" |
444 | @@ -1665,18 +1675,7 @@ |
445 | pucs = load_referencing( |
446 | PackageUploadCustom, rows, ["packageuploadID"]) |
447 | |
448 | - for pu in rows: |
449 | - cache = get_property_cache(pu) |
450 | - cache.sources = [] |
451 | - cache.builds = [] |
452 | - cache.customfiles = [] |
453 | - |
454 | - for pus in puses: |
455 | - get_property_cache(pus.packageupload).sources.append(pus) |
456 | - for pub in pubs: |
457 | - get_property_cache(pub.packageupload).builds.append(pub) |
458 | - for puc in pucs: |
459 | - get_property_cache(puc.packageupload).customfiles.append(puc) |
460 | + prefill_packageupload_caches(rows, puses, pubs, pucs) |
461 | |
462 | return DecoratedResultSet(query, pre_iter_hook=preload_hook) |
463 | |
464 | @@ -1704,3 +1703,43 @@ |
465 | return IStore(PackageUpload).find( |
466 | PackageUpload, |
467 | PackageUpload.package_copy_job_id.is_in(pcj_ids)) |
468 | + |
469 | + |
470 | +def prefill_packageupload_caches(uploads, puses, pubs, pucs): |
471 | + # Circular imports. |
472 | + from lp.soyuz.model.archive import Archive |
473 | + from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild |
474 | + from lp.soyuz.model.publishing import SourcePackagePublishingHistory |
475 | + from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease |
476 | + |
477 | + for pu in uploads: |
478 | + cache = get_property_cache(pu) |
479 | + cache.sources = [] |
480 | + cache.builds = [] |
481 | + cache.customfiles = [] |
482 | + |
483 | + for pus in puses: |
484 | + get_property_cache(pus.packageupload).sources.append(pus) |
485 | + for pub in pubs: |
486 | + get_property_cache(pub.packageupload).builds.append(pub) |
487 | + for puc in pucs: |
488 | + get_property_cache(puc.packageupload).customfiles.append(puc) |
489 | + |
490 | + source_sprs = load_related( |
491 | + SourcePackageRelease, puses, ['sourcepackagereleaseID']) |
492 | + bpbs = load_related(BinaryPackageBuild, pubs, ['buildID']) |
493 | + load_related(DistroArchSeries, bpbs, ['distro_arch_series_id']) |
494 | + binary_sprs = load_related( |
495 | + SourcePackageRelease, bpbs, ['source_package_release_id']) |
496 | + sprs = source_sprs + binary_sprs |
497 | + |
498 | + load_related(SourcePackageName, sprs, ['sourcepackagenameID']) |
499 | + load_related(LibraryFileAlias, uploads, ['changes_file_id']) |
500 | + publications = load_referencing( |
501 | + SourcePackagePublishingHistory, sprs, ['sourcepackagereleaseID']) |
502 | + load_related(Archive, publications, ['archiveID']) |
503 | + for spr_cache in sprs: |
504 | + get_property_cache(spr_cache).published_archives = [] |
505 | + for publication in publications: |
506 | + spr_cache = get_property_cache(publication.sourcepackagerelease) |
507 | + spr_cache.published_archives.append(publication.archive) |
508 | |
509 | === modified file 'lib/lp/soyuz/model/sourcepackagerelease.py' |
510 | --- lib/lp/soyuz/model/sourcepackagerelease.py 2012-11-26 12:53:30 +0000 |
511 | +++ lib/lp/soyuz/model/sourcepackagerelease.py 2013-01-03 00:18:23 +0000 |
512 | @@ -1,8 +1,6 @@ |
513 | # Copyright 2009-2012 Canonical Ltd. This software is licensed under the |
514 | # GNU Affero General Public License version 3 (see the file LICENSE). |
515 | |
516 | -# pylint: disable-msg=E0611,W0212 |
517 | - |
518 | __metaclass__ = type |
519 | __all__ = [ |
520 | 'SourcePackageRelease', |
521 | @@ -291,14 +289,13 @@ |
522 | @property |
523 | def current_publishings(self): |
524 | """See ISourcePackageRelease.""" |
525 | - from lp.soyuz.model.distroseriessourcepackagerelease \ |
526 | - import DistroSeriesSourcePackageRelease |
527 | + from lp.soyuz.model.distroseriessourcepackagerelease import ( |
528 | + DistroSeriesSourcePackageRelease) |
529 | return [DistroSeriesSourcePackageRelease(pub.distroseries, self) |
530 | for pub in self.publishings] |
531 | |
532 | - @property |
533 | + @cachedproperty |
534 | def published_archives(self): |
535 | - """See `ISourcePackageRelease`.""" |
536 | archives = set( |
537 | pub.archive for pub in self.publishings.prejoin(['archive'])) |
538 | return sorted(archives, key=operator.attrgetter('id')) |
539 | @@ -503,7 +500,7 @@ |
540 | Join(PackageUpload, |
541 | PackageUploadSource.packageuploadID == PackageUpload.id), |
542 | Join(LibraryFileAlias, |
543 | - LibraryFileAlias.id == PackageUpload.changesfileID), |
544 | + LibraryFileAlias.id == PackageUpload.changes_file_id), |
545 | Join(LibraryFileContent, |
546 | LibraryFileContent.id == LibraryFileAlias.contentID), |
547 | ] |
548 | |
549 | === modified file 'lib/lp/soyuz/tests/test_packageupload.py' |
550 | --- lib/lp/soyuz/tests/test_packageupload.py 2012-12-17 05:10:29 +0000 |
551 | +++ lib/lp/soyuz/tests/test_packageupload.py 2013-01-03 00:18:23 +0000 |
552 | @@ -1292,3 +1292,16 @@ |
553 | "customformat": "raw-translations", |
554 | } |
555 | self.assertEqual(expected_custom, ws_binaries[-1]) |
556 | + |
557 | + def test_getPackageUploads_query_count(self): |
558 | + person = self.makeQueueAdmin([self.universe]) |
559 | + uploads = [] |
560 | + for i in range(5): |
561 | + upload, _ = self.makeBinaryPackageUpload( |
562 | + person, component=self.universe) |
563 | + uploads.append(upload) |
564 | + ws_distroseries = self.load(self.distroseries, person) |
565 | + IStore(uploads[0].__class__).invalidate() |
566 | + with StormStatementRecorder() as recorder: |
567 | + ws_distroseries.getPackageUploads() |
568 | + self.assertThat(recorder, HasQueryCount(Equals(27))) |
143 + sprs = prefill_ packageupload_ caches( urces, pubs, pucs)
144 + uploads, packageuploadso
Is this not already done by the underlying model method?
444 +def prefill_ packageupload_ caches( uploads, puses, pubs, pucs):
My eyes are burning.
Oh, god, they burn.
Can you add a bit of VWS, perhaps? There are several logical sections which could be separated.
468 + for spr in sprs: cache(spr) .published_ archives = []
469 + get_property_
The other three caches get away without this. Are they initialised elsewhere? Perhaps move them into this function as well.
471 + spr = get_property_ cache(publicati on.sourcepackag erelease)
That's no SPR.
506 + @cachedproperty archives( self): _published_ archives( ))
507 + def published_
508 + return list(self.
There's no need for a separate _published_archives here, as nothing needs the actual ResultSet. Just inline it.
Additionally, you might want to invalidate this sometimes, though it's not used much so it's not hugely important. But IIRC SPPH creation is well encapsulated in PS.newSourcePub lication,