Merge lp:~cjwatson/launchpad/recipe-vocab-many-ppas-timeout into lp:launchpad

Proposed by Colin Watson on 2018-06-27
Status: Merged
Merged at revision: 18705
Proposed branch: lp:~cjwatson/launchpad/recipe-vocab-many-ppas-timeout
Merge into: lp:launchpad
Diff against target: 159 lines (+64/-22)
4 files modified
lib/lp/code/vocabularies/sourcepackagerecipe.py (+3/-3)
lib/lp/soyuz/doc/archive.txt (+16/-0)
lib/lp/soyuz/interfaces/archive.py (+3/-0)
lib/lp/soyuz/model/archive.py (+42/-19)
To merge this branch: bzr merge lp:~cjwatson/launchpad/recipe-vocab-many-ppas-timeout
Reviewer Review Type Date Requested Status
William Grant code 2018-06-27 Approve on 2018-06-27
Review via email: mp+348569@code.launchpad.net

Commit message

Optimise BuildableDistroSeries.findSeries.

Description of the change

I'm not sure whether this will be all of it or whether target_ppas_vocabulary will need some work too, but it's a start.

To post a comment you must log in.
William Grant (wgrant) :
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/code/vocabularies/sourcepackagerecipe.py'
2--- lib/lp/code/vocabularies/sourcepackagerecipe.py 2015-07-08 16:05:11 +0000
3+++ lib/lp/code/vocabularies/sourcepackagerecipe.py 2018-06-27 01:01:06 +0000
4@@ -1,4 +1,4 @@
5-# Copyright 2010-2013 Canonical Ltd. This software is licensed under the
6+# Copyright 2010-2018 Canonical Ltd. This software is licensed under the
7 # GNU Affero General Public License version 3 (see the file LICENSE).
8
9 """Source Package Recipe vocabularies used in the lp/code modules."""
10@@ -37,8 +37,8 @@
11
12 @classmethod
13 def findSeries(self, user):
14- ppas = getUtility(IArchiveSet).getPPAsForUser(user)
15- supported_distros = set([ppa.distribution for ppa in ppas])
16+ supported_distros = set(
17+ getUtility(IArchiveSet).getPPADistributionsForUser(user))
18 # Now add in Ubuntu.
19 supported_distros.add(getUtility(ILaunchpadCelebrities).ubuntu)
20 all_series = getUtility(IDistroSeriesSet).search()
21
22=== modified file 'lib/lp/soyuz/doc/archive.txt'
23--- lib/lp/soyuz/doc/archive.txt 2018-05-27 18:32:33 +0000
24+++ lib/lp/soyuz/doc/archive.txt 2018-06-27 01:01:06 +0000
25@@ -1208,6 +1208,22 @@
26 >>> jblack_ppas.count()
27 0
28
29+'getPPADistributionsForUser' returns the distinct distributions for all the
30+PPAs that a given user participates in.
31+
32+ >>> for distribution in archive_set.getPPADistributionsForUser(cprov):
33+ ... print(distribution.display_name)
34+ Ubuntu
35+ >>> for distribution in archive_set.getPPADistributionsForUser(no_priv):
36+ ... print(distribution.display_name)
37+ Ubuntu
38+ >>> for distribution in archive_set.getPPADistributionsForUser(
39+ ... indirect_uploader):
40+ ... print(distribution.display_name)
41+ Ubuntu
42+ >>> for distribution in archive_set.getPPADistributionsForUser(jblack):
43+ ... print(distribution.display_name)
44+
45 The method getPrivatePPAs() will return a result set of all PPAs that are
46 private.
47
48
49=== modified file 'lib/lp/soyuz/interfaces/archive.py'
50--- lib/lp/soyuz/interfaces/archive.py 2018-05-04 21:59:32 +0000
51+++ lib/lp/soyuz/interfaces/archive.py 2018-06-27 01:01:06 +0000
52@@ -2383,6 +2383,9 @@
53 The result is ordered by PPA displayname.
54 """
55
56+ def getPPADistributionsForUser(user):
57+ """Return the `Distribution`s of all PPAs for the given user."""
58+
59 def getPPAsPendingSigningKey():
60 """Return all PPAs pending signing key generation.
61
62
63=== modified file 'lib/lp/soyuz/model/archive.py'
64--- lib/lp/soyuz/model/archive.py 2018-05-04 21:59:32 +0000
65+++ lib/lp/soyuz/model/archive.py 2018-06-27 01:01:06 +0000
66@@ -33,6 +33,7 @@
67 Or,
68 Select,
69 Sum,
70+ Union,
71 )
72 from storm.properties import (
73 Int,
74@@ -40,7 +41,10 @@
75 Unicode,
76 )
77 from storm.references import Reference
78-from storm.store import Store
79+from storm.store import (
80+ EmptyResultSet,
81+ Store,
82+ )
83 from zope.component import (
84 getAdapter,
85 getUtility,
86@@ -2747,29 +2751,35 @@
87 SourcePackagePublishingHistory.archive == Archive.id)
88 return store.find(Archive, *clause).order_by(Archive.id).first()
89
90+ def _getPPAsForUserClause(self, user):
91+ """Base clause for getPPAsForUser and getPPADistributionsForUser."""
92+ direct_membership = Select(
93+ Archive.id,
94+ where=And(
95+ Archive._enabled == True,
96+ Archive.purpose == ArchivePurpose.PPA,
97+ TeamParticipation.team == Archive.ownerID,
98+ TeamParticipation.person == user,
99+ ))
100+ third_party_upload_acl = Select(
101+ Archive.id,
102+ where=And(
103+ Archive.purpose == ArchivePurpose.PPA,
104+ ArchivePermission.archiveID == Archive.id,
105+ TeamParticipation.person == user,
106+ TeamParticipation.team == ArchivePermission.personID,
107+ ))
108+ return Archive.id.is_in(
109+ Union(direct_membership, third_party_upload_acl))
110+
111 def getPPAsForUser(self, user):
112 """See `IArchiveSet`."""
113 from lp.registry.model.person import Person
114- # If there's no user logged in, then there's no archives.
115+ # If there's no user logged in, then there are no archives.
116 if user is None:
117- return []
118+ return EmptyResultSet()
119 store = Store.of(user)
120- direct_membership = store.find(
121- Archive,
122- Archive._enabled == True,
123- Archive.purpose == ArchivePurpose.PPA,
124- TeamParticipation.team == Archive.ownerID,
125- TeamParticipation.person == user,
126- )
127- third_party_upload_acl = store.find(
128- Archive,
129- Archive.purpose == ArchivePurpose.PPA,
130- ArchivePermission.archiveID == Archive.id,
131- TeamParticipation.person == user,
132- TeamParticipation.team == ArchivePermission.personID,
133- )
134-
135- result = direct_membership.union(third_party_upload_acl)
136+ result = store.find(Archive, self._getPPAsForUserClause(user))
137 result.order_by(Archive.displayname)
138
139 def preload_owners(rows):
140@@ -2777,6 +2787,19 @@
141
142 return DecoratedResultSet(result, pre_iter_hook=preload_owners)
143
144+ def getPPADistributionsForUser(self, user):
145+ """See `IArchiveSet`."""
146+ from lp.registry.model.distribution import Distribution
147+ # If there's no user logged in, then there are no archives.
148+ if user is None:
149+ return EmptyResultSet()
150+ store = Store.of(user)
151+ result = store.find(
152+ Distribution,
153+ Distribution.id == Archive.distributionID,
154+ self._getPPAsForUserClause(user))
155+ return result.config(distinct=True)
156+
157 def getPPAsPendingSigningKey(self):
158 """See `IArchiveSet`."""
159 origin = (