Merge lp:~stevenk/launchpad/stormier-getbuildsforbuilder into lp:launchpad

Proposed by Steve Kowalik on 2012-09-25
Status: Merged
Approved by: Steve Kowalik on 2012-09-25
Approved revision: no longer in the source branch.
Merged at revision: 16034
Proposed branch: lp:~stevenk/launchpad/stormier-getbuildsforbuilder
Merge into: lp:launchpad
Diff against target: 635 lines (+91/-227)
8 files modified
lib/lp/buildmaster/model/buildfarmjob.py (+6/-23)
lib/lp/registry/interfaces/distroseries.py (+0/-21)
lib/lp/registry/model/distributionsourcepackage.py (+0/-3)
lib/lp/registry/model/distroseries.py (+0/-23)
lib/lp/registry/model/sourcepackage.py (+9/-41)
lib/lp/registry/tests/test_distroseries.py (+0/-32)
lib/lp/soyuz/model/archive.py (+21/-3)
lib/lp/soyuz/model/binarypackagebuild.py (+55/-81)
To merge this branch: bzr merge lp:~stevenk/launchpad/stormier-getbuildsforbuilder
Reviewer Review Type Date Requested Status
William Grant code 2012-09-25 Approve on 2012-09-25
Review via email: mp+126159@code.launchpad.net

Commit Message

Switch BinaryPackageBuildSet.getBuildsByBuilder() and friends to Storm.

Description of the Change

Switch BinaryPackageBuildSet.getBuildsByBuilder() and friends to Storm. I took one look at the work to convert BinaryPackageBuildSet.getBuildsByArchIds() to Storm (since it is a callsite of handleOptionalParamsForBuildQueries()), and ran screaming. However, it already used Storm to make the query so that it could use DRS, and Storm doesn't seem to mind mixing straight clauses and quoted ones.

I have cleaned up the pylint garbage and trimmed a bit of whitespace.

To post a comment you must log in.
William Grant (wgrant) wrote :

78 +def get_archive_privacy_filter(user):
79 + return [
80 + Not(Archive._private),
81 + Archive.ownerID.is_in(
82 + Select(
83 + TeamParticipation.teamID,
84 + where=(TeamParticipation.person == user)))]

The indentation here is wrong, and it might be better to just say Or() rather than returning a list.

174 + clauses.extend(
175 + [BinaryPackageBuild.package_build == PackageBuild.id,
176 + PackageBuild.build_farm_job == BuildFarmJob.id])

The opening square bracket should probably be on the previous line.

221 - AND SourcepackageName.name LIKE '%%%%' || %s || '%%%%'
222 - ''' % quote_like(name))
223 + clauses.append(SourcePackageName.name.like(name))

These aren't equivalent. You need to use quote_like and wrap it in % to get a substring match; see Distribution.searchSourcePackageCaches's LIKE stuff for an example of hacking around Storm. There's also another instance of this in the following block.

274 + if user is None:
275 + clauses.append(Not(Archive._private))
276 + elif not IPersonRoles(user).in_admin:
277 + clauses.append(*get_archive_privacy_filter(user))

Shouldn't this be in get_archive_privacy_filter?

279 + clauses.append(BuildFarmJob.builder_id == builder_id)

Can you put this in the initial clauses?

288 - queries = []
289 - clauseTables = []
290 + clauses = []
291 + origin = [PackageBuild]

Why the new table?

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/buildmaster/model/buildfarmjob.py'
2--- lib/lp/buildmaster/model/buildfarmjob.py 2012-09-11 06:18:18 +0000
3+++ lib/lp/buildmaster/model/buildfarmjob.py 2012-09-26 04:19:22 +0000
4@@ -16,9 +16,7 @@
5 from storm.expr import (
6 Desc,
7 LeftJoin,
8- Not,
9 Or,
10- Select,
11 )
12 from storm.locals import (
13 Bool,
14@@ -53,8 +51,6 @@
15 ISpecificBuildFarmJobSource,
16 )
17 from lp.buildmaster.interfaces.buildqueue import IBuildQueueSet
18-from lp.registry.interfaces.role import IPersonRoles
19-from lp.registry.model.teammembership import TeamParticipation
20 from lp.services.database.constants import UTC_NOW
21 from lp.services.database.enumcol import DBEnum
22 from lp.services.database.lpstorm import (
23@@ -418,9 +414,12 @@
24 """See `IBuildFarmJobSet`."""
25 # Imported here to avoid circular imports.
26 from lp.buildmaster.model.packagebuild import PackageBuild
27- from lp.soyuz.model.archive import Archive
28+ from lp.soyuz.model.archive import (
29+ Archive, get_archive_privacy_filter)
30
31- clauses = [BuildFarmJob.builder == builder_id]
32+ clauses = [
33+ BuildFarmJob.builder == builder_id,
34+ Or(PackageBuild.id == None, get_archive_privacy_filter(user))]
35 if status is not None:
36 clauses.append(BuildFarmJob.status == status)
37
38@@ -433,25 +432,9 @@
39 LeftJoin(
40 PackageBuild,
41 PackageBuild.build_farm_job == BuildFarmJob.id),
42+ LeftJoin(Archive, Archive.id == PackageBuild.archive_id),
43 ]
44
45- if user is None:
46- # Anonymous requests don't get to see private builds at all.
47- origin.append(
48- LeftJoin(Archive, Archive.id == PackageBuild.archive_id))
49- clauses.append(Or(PackageBuild.id == None, Not(Archive._private)))
50- elif not IPersonRoles(user).in_admin:
51- # Non-admin users see all public builds and the specific
52- # private builds to which they have access.
53- origin.append(
54- LeftJoin(Archive, Archive.id == PackageBuild.archive_id))
55- clauses.append(
56- Or(PackageBuild.id == None, Not(Archive._private),
57- Archive.ownerID.is_in(
58- Select(
59- TeamParticipation.teamID,
60- where=(TeamParticipation.person == user)))))
61-
62 return IStore(BuildFarmJob).using(*origin).find(
63 BuildFarmJob, *clauses).order_by(
64 Desc(BuildFarmJob.date_finished), BuildFarmJob.id)
65
66=== modified file 'lib/lp/registry/interfaces/distroseries.py'
67--- lib/lp/registry/interfaces/distroseries.py 2012-09-07 05:13:57 +0000
68+++ lib/lp/registry/interfaces/distroseries.py 2012-09-26 04:19:22 +0000
69@@ -1,8 +1,6 @@
70 # Copyright 2009-2012 Canonical Ltd. This software is licensed under the
71 # GNU Affero General Public License version 3 (see the file LICENSE).
72
73-# pylint: disable-msg=E0211,E0213
74-
75 """Interfaces including and related to IDistroSeries."""
76
77 __metaclass__ = type
78@@ -380,9 +378,6 @@
79 on clients, which requires downloading Packages files for
80 multiple architectures.""")))
81
82- def priorReleasedSeries():
83- """Prior series *by date* from the same distribution."""
84-
85 main_archive = exported(
86 Reference(
87 Interface, # Really IArchive, see below for circular import fix.
88@@ -1071,24 +1066,8 @@
89 released == None will do no filtering on status.
90 """
91
92- def priorReleasedSeries(distribution, prior_to_date):
93- """Find distroseries for the supplied distro released before a
94- certain date.
95-
96- :param distribution: An `IDistribution` in which to search for its
97- series.
98- :param prior_to_date: A `datetime`
99-
100- :return: `IResultSet` of `IDistroSeries` that were released before
101- prior_to_date, ordered in increasing order of age.
102- """
103-
104
105 @error_status(httplib.BAD_REQUEST)
106 class DerivationError(Exception):
107 """Raised when there is a problem deriving a distroseries."""
108 _message_prefix = "Error deriving distro series"
109-
110-
111-# Monkey patch for circular import avoidance done in
112-# _schema_circular_imports.py
113
114=== modified file 'lib/lp/registry/model/distributionsourcepackage.py'
115--- lib/lp/registry/model/distributionsourcepackage.py 2012-08-08 05:36:44 +0000
116+++ lib/lp/registry/model/distributionsourcepackage.py 2012-09-26 04:19:22 +0000
117@@ -1,8 +1,6 @@
118 # Copyright 2009-2012 Canonical Ltd. This software is licensed under the
119 # GNU Affero General Public License version 3 (see the file LICENSE).
120
121-# pylint: disable-msg=E0611,W0212
122-
123 """Classes to represent source packages in a distribution."""
124
125 __metaclass__ = type
126@@ -35,7 +33,6 @@
127 from zope.interface import implements
128
129 from lp.bugs.interfaces.bugsummary import IBugSummaryDimension
130-from lp.bugs.model.bug import BugSet
131 from lp.bugs.model.bugtarget import BugTargetBase
132 from lp.bugs.model.bugtask import BugTask
133 from lp.bugs.model.structuralsubscription import (
134
135=== modified file 'lib/lp/registry/model/distroseries.py'
136--- lib/lp/registry/model/distroseries.py 2012-09-11 19:14:41 +0000
137+++ lib/lp/registry/model/distroseries.py 2012-09-26 04:19:22 +0000
138@@ -1,8 +1,6 @@
139 # Copyright 2009-2012 Canonical Ltd. This software is licensed under the
140 # GNU Affero General Public License version 3 (see the file LICENSE).
141
142-# pylint: disable-msg=E0611,W0212
143-
144 """Database classes for a distribution series."""
145
146 __metaclass__ = type
147@@ -689,15 +687,6 @@
148 orderBy=["Language.englishname"])
149 return result
150
151- def priorReleasedSeries(self):
152- """See `IDistroSeries`."""
153- datereleased = self.datereleased
154- # if this one is unreleased, use the last released one
155- if not datereleased:
156- datereleased = UTC_NOW
157- return getUtility(IDistroSeriesSet).priorReleasedSeries(
158- self.distribution, datereleased)
159-
160 @property
161 def bug_reporting_guidelines(self):
162 """See `IBugTarget`."""
163@@ -1728,15 +1717,3 @@
164 else:
165
166 return DistroSeries.select(where_clause)
167-
168- def priorReleasedSeries(self, distribution, prior_to_date):
169- """See `IDistroSeriesSet`."""
170- store = Store.of(distribution)
171- results = store.find(
172- DistroSeries,
173- DistroSeries.distributionID == distribution.id,
174- DistroSeries.datereleased < prior_to_date,
175- DistroSeries.datereleased != None
176- ).order_by(Desc(DistroSeries.datereleased))
177-
178- return results
179
180=== modified file 'lib/lp/registry/model/sourcepackage.py'
181--- lib/lp/registry/model/sourcepackage.py 2012-08-08 05:36:44 +0000
182+++ lib/lp/registry/model/sourcepackage.py 2012-09-26 04:19:22 +0000
183@@ -1,7 +1,6 @@
184-# Copyright 2009, 2011 Canonical Ltd. This software is licensed under the
185+# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
186 # GNU Affero General Public License version 3 (see the file LICENSE).
187
188-# pylint: disable-msg=E0611,W0212
189 """Database classes that implement SourcePackage items."""
190
191 __metaclass__ = type
192@@ -156,10 +155,6 @@
193 return recipients
194
195 @property
196- def _store(self):
197- return Store.of(self.sourcepackagename)
198-
199- @property
200 def answer_contacts(self):
201 """See `IQuestionTarget`."""
202 answer_contacts = set()
203@@ -222,18 +217,6 @@
204 return '<%s %r %r %r>' % (self.__class__.__name__,
205 self.distribution, self.distroseries, self.sourcepackagename)
206
207- def _get_ubuntu(self):
208- # XXX: kiko 2006-03-20: Ideally, it would be possible to just do
209- # ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
210- # and not need this method. However, importd currently depends
211- # on SourcePackage methods that require the ubuntu celebrity,
212- # and given it does not execute_zcml_for_scripts, we are forced
213- # here to do this hack instead of using components. Ideally,
214- # imports is rewritten to not use SourcePackage, or it
215- # initializes the component architecture correctly.
216- from lp.registry.model.distribution import Distribution
217- return Distribution.byName("ubuntu")
218-
219 def _getPublishingHistory(self, version=None, include_status=None,
220 exclude_status=None, order_by=None):
221 """Build a query and return a list of SourcePackagePublishingHistory.
222@@ -423,32 +406,17 @@
223 """See `ISourcePackage`"""
224 # First we look to see if there is packaging data for this
225 # distroseries and sourcepackagename. If not, we look up through
226- # parent distroseries, and when we hit Ubuntu, we look backwards in
227- # time through Ubuntu series till we find packaging information or
228- # blow past the Warty Warthog.
229+ # parent distroseries.
230
231- # see if there is a direct packaging
232 result = self.direct_packaging
233 if result is not None:
234 return result
235
236- ubuntu = self._get_ubuntu()
237- # if we are an ubuntu sourcepackage, try the previous series of
238- # ubuntu
239- if self.distribution == ubuntu:
240- ubuntuseries = self.distroseries.priorReleasedSeries()
241- previous_ubuntu_series = ubuntuseries.first()
242- if previous_ubuntu_series is not None:
243- sp = SourcePackage(sourcepackagename=self.sourcepackagename,
244- distroseries=previous_ubuntu_series)
245- return sp.packaging
246- # if we have a parent distroseries, try that
247+ # If we have a parent distroseries, try that.
248 if self.distroseries.previous_series is not None:
249 sp = SourcePackage(sourcepackagename=self.sourcepackagename,
250 distroseries=self.distroseries.previous_series)
251 return sp.packaging
252- # capitulate
253- return None
254
255 @property
256 def published_by_pocket(self):
257@@ -626,7 +594,7 @@
258 # binary_only parameter as a source package can only have
259 # binary builds.
260
261- clauseTables = ['SourcePackageRelease',
262+ clauseTables = ['SourcePackageRelease', 'PackageBuild',
263 'SourcePackagePublishingHistory']
264
265 condition_clauses = ["""
266@@ -673,17 +641,17 @@
267 clauseTables.append('BuildQueue')
268 condition_clauses.append('BuildQueue.job = BuildPackageJob.job')
269 elif build_state == BuildStatus.SUPERSEDED or build_state is None:
270- orderBy = ["-BuildFarmJob.date_created"]
271+ orderBy = [Desc("BuildFarmJob.date_created")]
272 else:
273- orderBy = ["-BuildFarmJob.date_finished"]
274+ orderBy = [Desc("BuildFarmJob.date_finished")]
275
276 # Fallback to ordering by -id as a tie-breaker.
277- orderBy.append("-id")
278+ orderBy.append(Desc("id"))
279
280 # End of duplication (see XXX cprov 2006-09-25 above).
281
282- return BinaryPackageBuild.select(' AND '.join(condition_clauses),
283- clauseTables=clauseTables, orderBy=orderBy)
284+ return IStore(BinaryPackageBuild).using(clauseTables).find(
285+ BinaryPackageBuild, *condition_clauses).order_by(*orderBy)
286
287 @property
288 def latest_published_component(self):
289
290=== modified file 'lib/lp/registry/tests/test_distroseries.py'
291--- lib/lp/registry/tests/test_distroseries.py 2012-06-06 16:04:34 +0000
292+++ lib/lp/registry/tests/test_distroseries.py 2012-09-26 04:19:22 +0000
293@@ -9,7 +9,6 @@
294 'CurrentSourceReleasesMixin',
295 ]
296
297-from datetime import timedelta
298 from logging import getLogger
299
300 import transaction
301@@ -20,7 +19,6 @@
302 from lp.registry.interfaces.distroseries import IDistroSeriesSet
303 from lp.registry.interfaces.pocket import PackagePublishingPocket
304 from lp.registry.interfaces.series import SeriesStatus
305-from lp.services.utils import utc_now
306 from lp.soyuz.enums import (
307 ArchivePurpose,
308 PackagePublishingStatus,
309@@ -281,36 +279,6 @@
310 job = job_source.create(distroseries, [parent_distroseries.id])
311 self.assertEqual(job, distroseries.getInitializationJob())
312
313- def test_priorReleasedSeries(self):
314- # Make sure that previousReleasedSeries returns all series with a
315- # release date less than the contextual series,
316- # ordered by descending date.
317- distro = self.factory.makeDistribution()
318- # Make an unreleased series.
319- self.factory.makeDistroSeries(distribution=distro)
320- ds1 = self.factory.makeDistroSeries(distribution=distro)
321- ds2 = self.factory.makeDistroSeries(distribution=distro)
322- ds3 = self.factory.makeDistroSeries(distribution=distro)
323- ds4 = self.factory.makeDistroSeries(distribution=distro)
324-
325- now = utc_now()
326- older = now - timedelta(days=5)
327- oldest = now - timedelta(days=10)
328- newer = now + timedelta(days=15)
329- removeSecurityProxy(ds1).datereleased = oldest
330- removeSecurityProxy(ds2).datereleased = older
331- removeSecurityProxy(ds3).datereleased = now
332- removeSecurityProxy(ds4).datereleased = newer
333-
334- # The data set up here is 5 distroseries. where one is unreleased,
335- # ds1 and ds2 are released and in the past and ds4 is released but
336- # in the future compared to ds3.
337-
338- prior = ds3.priorReleasedSeries()
339- self.assertEqual(
340- [ds2, ds1],
341- list(prior))
342-
343 def test_getDifferenceComments_gets_DistroSeriesDifferenceComments(self):
344 distroseries = self.factory.makeDistroSeries()
345 dsd = self.factory.makeDistroSeriesDifference(
346
347=== modified file 'lib/lp/soyuz/model/archive.py'
348--- lib/lp/soyuz/model/archive.py 2012-09-21 07:02:26 +0000
349+++ lib/lp/soyuz/model/archive.py 2012-09-26 04:19:22 +0000
350@@ -1,8 +1,6 @@
351 # Copyright 2009-2012 Canonical Ltd. This software is licensed under the
352 # GNU Affero General Public License version 3 (see the file LICENSE).
353
354-# pylint: disable-msg=E0611,W0212
355-
356 """Database class for table Archive."""
357
358 __metaclass__ = type
359@@ -10,6 +8,7 @@
360 __all__ = [
361 'Archive',
362 'ArchiveSet',
363+ 'get_archive_privacy_filter',
364 'validate_ppa',
365 ]
366
367@@ -28,6 +27,7 @@
368 And,
369 Desc,
370 Or,
371+ Not,
372 Select,
373 SQL,
374 Sum,
375@@ -68,7 +68,10 @@
376 validate_person,
377 )
378 from lp.registry.interfaces.pocket import PackagePublishingPocket
379-from lp.registry.interfaces.role import IHasOwner
380+from lp.registry.interfaces.role import (
381+ IHasOwner,
382+ IPersonRoles,
383+ )
384 from lp.registry.interfaces.series import SeriesStatus
385 from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet
386 from lp.registry.model.sourcepackagename import SourcePackageName
387@@ -2574,3 +2577,18 @@
388 )
389
390 return results.order_by(SourcePackagePublishingHistory.id)
391+
392+
393+def get_archive_privacy_filter(user):
394+ if user is None:
395+ privacy_filter = Not(Archive._private)
396+ elif IPersonRoles(user).in_admin:
397+ privacy_filter = True
398+ else:
399+ privacy_filter = Or(
400+ Not(Archive._private),
401+ Archive.ownerID.is_in(
402+ Select(
403+ TeamParticipation.teamID,
404+ where=(TeamParticipation.person == user))))
405+ return privacy_filter
406
407=== modified file 'lib/lp/soyuz/model/binarypackagebuild.py'
408--- lib/lp/soyuz/model/binarypackagebuild.py 2012-07-05 09:13:42 +0000
409+++ lib/lp/soyuz/model/binarypackagebuild.py 2012-09-26 04:19:22 +0000
410@@ -1,8 +1,6 @@
411 # Copyright 2009-2012 Canonical Ltd. This software is licensed under the
412 # GNU Affero General Public License version 3 (see the file LICENSE).
413
414-# pylint: disable-msg=E0611,W0212
415-
416 __metaclass__ = type
417 __all__ = [
418 'BinaryPackageBuild',
419@@ -872,15 +870,9 @@
420
421 def preloadBuildsData(self, builds):
422 # Circular imports.
423- from lp.soyuz.model.distroarchseries import (
424- DistroArchSeries
425- )
426- from lp.registry.model.distroseries import (
427- DistroSeries
428- )
429- from lp.registry.model.distribution import (
430- Distribution
431- )
432+ from lp.soyuz.model.distroarchseries import DistroArchSeries
433+ from lp.registry.model.distroseries import DistroSeries
434+ from lp.registry.model.distribution import Distribution
435 from lp.soyuz.model.archive import Archive
436 from lp.registry.model.person import Person
437 self._prefetchBuildData(builds)
438@@ -926,15 +918,15 @@
439 BuildFarmJob.status == BuildStatus.NEEDSBUILD)
440
441 def handleOptionalParamsForBuildQueries(
442- self, queries, tables, status=None, name=None, pocket=None,
443+ self, clauses, origin, status=None, name=None, pocket=None,
444 arch_tag=None):
445 """Construct query clauses needed/shared by all getBuild..() methods.
446
447 This method is not exposed via the public interface as it is only
448 used to DRY-up trusted code.
449
450- :param queries: container to which to add any resulting query clauses.
451- :param tables: container to which to add joined tables.
452+ :param clauses: container to which to add any resulting query clauses.
453+ :param origin: container to which to add joined tables.
454 :param status: optional build state for which to add a query clause if
455 present.
456 :param name: optional source package release name (or list of source
457@@ -945,112 +937,96 @@
458 :param arch_tag: optional architecture tag for which to add a
459 query clause if present.
460 """
461+ # Circular. :(
462+ from lp.registry.model.sourcepackagename import SourcePackageName
463+ from lp.soyuz.model.distroarchseries import DistroArchSeries
464+ from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease
465
466 # Ensure the underlying buildfarmjob and package build tables
467 # are included.
468- queries.append('BinaryPackageBuild.package_build = PackageBuild.id')
469- queries.append('PackageBuild.build_farm_job = BuildFarmJob.id')
470- tables.extend(['PackageBuild', 'BuildFarmJob'])
471+ clauses.extend([
472+ BinaryPackageBuild.package_build == PackageBuild.id,
473+ PackageBuild.build_farm_job == BuildFarmJob.id])
474+ origin.extend([BinaryPackageBuild, BuildFarmJob])
475
476 # Add query clause that filters on build state if the latter is
477 # provided.
478 if status is not None:
479- queries.append('BuildFarmJob.status=%s' % sqlvalues(status))
480+ clauses.append(BuildFarmJob.status == status)
481
482 # Add query clause that filters on pocket if the latter is provided.
483 if pocket:
484 if not isinstance(pocket, (list, tuple)):
485 pocket = (pocket,)
486-
487- queries.append('PackageBuild.pocket IN %s' % sqlvalues(pocket))
488+ clauses.append(PackageBuild.pocket.is_in(pocket))
489
490 # Add query clause that filters on architecture tag if provided.
491 if arch_tag is not None:
492- queries.append('''
493- BinaryPackageBuild.distro_arch_series = DistroArchSeries.id
494- AND DistroArchSeries.architecturetag = %s
495- ''' % sqlvalues(arch_tag))
496- tables.extend(['DistroArchSeries'])
497+ clauses.extend([
498+ BinaryPackageBuild.distro_arch_series_id ==
499+ DistroArchSeries.id,
500+ DistroArchSeries.architecturetag == arch_tag])
501+ origin.append(DistroArchSeries)
502
503 # Add query clause that filters on source package release name if the
504 # latter is provided.
505 if name is not None:
506+ clauses.extend(
507+ [BinaryPackageBuild.source_package_release_id ==
508+ SourcePackageRelease.id,
509+ SourcePackageRelease.sourcepackagenameID ==
510+ SourcePackageName.id])
511+ origin.extend([SourcePackageRelease, SourcePackageName])
512 if not isinstance(name, (list, tuple)):
513- queries.append('''
514- BinaryPackageBuild.source_package_release =
515- SourcePackageRelease.id AND
516- SourcePackageRelease.sourcepackagename =
517- SourcePackageName.id
518- AND SourcepackageName.name LIKE '%%%%' || %s || '%%%%'
519- ''' % quote_like(name))
520+ clauses.append(
521+ "SourcepackageName.name LIKE '%%%%' || %s || '%%%%'" % (
522+ quote_like(name)))
523 else:
524- queries.append('''
525- BinaryPackageBuild.source_package_release =
526- SourcePackageRelease.id AND
527- SourcePackageRelease.sourcepackagename =
528- SourcePackageName.id
529- AND SourcepackageName.name IN %s
530- ''' % sqlvalues(name))
531- tables.extend(['SourcePackageRelease', 'SourcePackageName'])
532+ clauses.append(SourcePackageName.name.is_in(name))
533
534 def getBuildsForBuilder(self, builder_id, status=None, name=None,
535 arch_tag=None, user=None):
536 """See `IBinaryPackageBuildSet`."""
537- queries = []
538- clauseTables = []
539+ # Circular. :(
540+ from lp.soyuz.model.archive import (
541+ Archive, get_archive_privacy_filter)
542+
543+ clauses = [
544+ PackageBuild.archive_id == Archive.id,
545+ BuildFarmJob.builder_id == builder_id,
546+ get_archive_privacy_filter(user)]
547+ origin = [PackageBuild, Archive]
548
549 self.handleOptionalParamsForBuildQueries(
550- queries, clauseTables, status, name, pocket=None,
551- arch_tag=arch_tag)
552-
553- # This code MUST match the logic in the Build security adapter,
554- # otherwise users are likely to get 403 errors, or worse.
555- queries.append("Archive.id = PackageBuild.archive")
556- clauseTables.append('Archive')
557- if user is not None:
558- if not user.inTeam(getUtility(ILaunchpadCelebrities).admin):
559- queries.append("""
560- (Archive.private = FALSE
561- OR %s IN (SELECT TeamParticipation.person
562- FROM TeamParticipation
563- WHERE TeamParticipation.person = %s
564- AND TeamParticipation.team = Archive.owner)
565- )""" % sqlvalues(user, user))
566- else:
567- queries.append("Archive.private = FALSE")
568-
569- queries.append("builder=%s" % builder_id)
570-
571- return BinaryPackageBuild.select(
572- " AND ".join(queries), clauseTables=clauseTables,
573- orderBy=["-BuildFarmJob.date_finished", "id"])
574+ clauses, origin, status, name, pocket=None, arch_tag=arch_tag)
575+
576+ return IStore(BinaryPackageBuild).using(*origin).find(
577+ BinaryPackageBuild, *clauses).order_by(
578+ Desc(BuildFarmJob.date_finished), BinaryPackageBuild.id)
579
580 def getBuildsForArchive(self, archive, status=None, name=None,
581 pocket=None, arch_tag=None):
582 """See `IBinaryPackageBuildSet`."""
583- queries = []
584- clauseTables = []
585+ clauses = [PackageBuild.archive_id == archive.id]
586+ origin = [PackageBuild]
587
588 self.handleOptionalParamsForBuildQueries(
589- queries, clauseTables, status, name, pocket, arch_tag)
590+ clauses, origin, status, name, pocket, arch_tag)
591
592 # Ordering according status
593 # * SUPERSEDED & All by -datecreated
594 # * FULLYBUILT & FAILURES by -datebuilt
595 # It should present the builds in a more natural order.
596 if status == BuildStatus.SUPERSEDED or status is None:
597- orderBy = ["-BuildFarmJob.date_created"]
598+ orderBy = [Desc(BuildFarmJob.date_created)]
599 else:
600- orderBy = ["-BuildFarmJob.date_finished"]
601+ orderBy = [Desc(BuildFarmJob.date_finished)]
602 # All orders fallback to id if the primary order doesn't succeed
603- orderBy.append("id")
604-
605- queries.append("archive=%s" % sqlvalues(archive))
606- clause = " AND ".join(queries)
607+ orderBy.append(BinaryPackageBuild.id)
608
609 return self._decorate_with_prejoins(
610- BinaryPackageBuild.select(
611- clause, clauseTables=clauseTables, orderBy=orderBy))
612+ IStore(BinaryPackageBuild).using(*origin).find(
613+ BinaryPackageBuild, *clauses).order_by(*orderBy))
614
615 def getBuildsByArchIds(self, distribution, arch_ids, status=None,
616 name=None, pocket=None):
617@@ -1059,7 +1035,7 @@
618 if not arch_ids:
619 return EmptyResultSet()
620
621- clauseTables = []
622+ clauseTables = [PackageBuild]
623
624 # format clause according single/multiple architecture(s) form
625 if len(arch_ids) == 1:
626@@ -1124,9 +1100,7 @@
627 "PackageBuild.archive IN %s" %
628 sqlvalues(list(distribution.all_distro_archive_ids)))
629
630- store = Store.of(distribution)
631- clauseTables = [BinaryPackageBuild] + clauseTables
632- result_set = store.using(*clauseTables).find(
633+ result_set = Store.of(distribution).using(*clauseTables).find(
634 (BinaryPackageBuild, order_by_table), *condition_clauses)
635 result_set.order_by(*order_by)
636