Merge ~cjwatson/launchpad:stormify-featuredproject into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: 08d6f98631d824d381da559afacc0663b93859a9
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:stormify-featuredproject
Merge into: launchpad:master
Diff against target: 257 lines (+52/-75)
4 files modified
lib/lp/registry/model/featuredproject.py (+20/-6)
lib/lp/registry/model/pillar.py (+15/-16)
lib/lp/registry/vocabularies.py (+13/-13)
lib/lp/services/webapp/vocabulary.py (+4/-40)
Reviewer Review Type Date Requested Status
Ioana Lasc (community) Approve
Review via email: mp+394874@code.launchpad.net

Commit message

Convert FeaturedProject to Storm

Description of the change

This also removes the last user of NamedSQLObjectHugeVocabulary.

To post a comment you must log in.
Revision history for this message
Ioana Lasc (ilasc) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/lp/registry/model/featuredproject.py b/lib/lp/registry/model/featuredproject.py
2index 6440064..35d3579 100644
3--- a/lib/lp/registry/model/featuredproject.py
4+++ b/lib/lp/registry/model/featuredproject.py
5@@ -1,4 +1,4 @@
6-# Copyright 2009 Canonical Ltd. This software is licensed under the
7+# Copyright 2009-2020 Canonical Ltd. This software is licensed under the
8 # GNU Affero General Public License version 3 (see the file LICENSE).
9
10 """Database class for Featured Projects."""
11@@ -8,15 +8,19 @@ __all__ = [
12 'FeaturedProject',
13 ]
14
15-from sqlobject import IntCol
16+from storm.locals import (
17+ Int,
18+ Reference,
19+ )
20 from zope.interface import implementer
21
22 from lp.registry.interfaces.featuredproject import IFeaturedProject
23-from lp.services.database.sqlbase import SQLBase
24+from lp.services.database.interfaces import IStore
25+from lp.services.database.stormbase import StormBase
26
27
28 @implementer(IFeaturedProject)
29-class FeaturedProject(SQLBase):
30+class FeaturedProject(StormBase):
31 """A featured project reference.
32
33 This is a reference to the name of a project, product or distribution
34@@ -24,6 +28,16 @@ class FeaturedProject(SQLBase):
35 page.
36 """
37
38- _defaultOrder = ['id']
39+ __storm_table__ = 'FeaturedProject'
40+ __storm_order__ = ['id']
41
42- pillar_name = IntCol(notNull=True)
43+ id = Int(primary=True)
44+ pillar_name_id = Int(name='pillar_name', allow_none=False)
45+ pillar_name = Reference(pillar_name_id, 'PillarName.id')
46+
47+ def __init__(self, pillar_name):
48+ super(FeaturedProject, self).__init__()
49+ self.pillar_name = pillar_name
50+
51+ def destroySelf(self):
52+ IStore(self).remove(self)
53diff --git a/lib/lp/registry/model/pillar.py b/lib/lp/registry/model/pillar.py
54index 8bfc356..3482abb 100644
55--- a/lib/lp/registry/model/pillar.py
56+++ b/lib/lp/registry/model/pillar.py
57@@ -1,4 +1,4 @@
58-# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
59+# Copyright 2009-2020 Canonical Ltd. This software is licensed under the
60 # GNU Affero General Public License version 3 (see the file LICENSE).
61
62 """Launchpad Pillars share a namespace.
63@@ -249,24 +249,23 @@ class PillarNameSet:
64
65 def add_featured_project(self, project):
66 """See `IPillarSet`."""
67- query = """
68- PillarName.name = %s
69- AND PillarName.id = FeaturedProject.pillar_name
70- """ % sqlvalues(project.name)
71- existing = FeaturedProject.selectOne(
72- query, clauseTables=['PillarName'])
73+ existing = IStore(FeaturedProject).find(
74+ FeaturedProject,
75+ PillarName.name == project.name,
76+ PillarName.id == FeaturedProject.pillar_name_id).one()
77 if existing is None:
78- pillar_name = PillarName.selectOneBy(name=project.name)
79- return FeaturedProject(pillar_name=pillar_name.id)
80+ pillar_name = IStore(PillarName).find(
81+ PillarName, name=project.name).one()
82+ featured_project = FeaturedProject(pillar_name=pillar_name)
83+ IStore(FeaturedProject).add(featured_project)
84+ return featured_project
85
86 def remove_featured_project(self, project):
87 """See `IPillarSet`."""
88- query = """
89- PillarName.name = %s
90- AND PillarName.id = FeaturedProject.pillar_name
91- """ % sqlvalues(project.name)
92- existing = FeaturedProject.selectOne(
93- query, clauseTables=['PillarName'])
94+ existing = IStore(FeaturedProject).find(
95+ FeaturedProject,
96+ PillarName.name == project.name,
97+ PillarName.id == FeaturedProject.pillar_name_id).one()
98 if existing is not None:
99 existing.destroySelf()
100
101@@ -280,7 +279,7 @@ class PillarNameSet:
102
103 store = IStore(PillarName)
104 pillar_names = store.find(
105- PillarName, PillarName.id == FeaturedProject.pillar_name)
106+ PillarName, PillarName.id == FeaturedProject.pillar_name_id)
107
108 def preload_pillars(rows):
109 pillar_names = (
110diff --git a/lib/lp/registry/vocabularies.py b/lib/lp/registry/vocabularies.py
111index 31d9f3d..008dcbc 100644
112--- a/lib/lp/registry/vocabularies.py
113+++ b/lib/lp/registry/vocabularies.py
114@@ -211,7 +211,6 @@ from lp.services.webapp.vocabulary import (
115 CountableIterator,
116 FilteredVocabularyBase,
117 IHugeVocabulary,
118- NamedSQLObjectHugeVocabulary,
119 NamedSQLObjectVocabulary,
120 NamedStormHugeVocabulary,
121 SQLObjectVocabularyBase,
122@@ -1827,7 +1826,7 @@ class VocabularyFilterDistribution(VocabularyFilter):
123 return [PillarName.distribution != None]
124
125
126-class PillarVocabularyBase(NamedSQLObjectHugeVocabulary):
127+class PillarVocabularyBase(NamedStormHugeVocabulary):
128 """Active `IPillar` objects vocabulary."""
129 displayname = 'Needs to be overridden'
130 _table = PillarName
131@@ -1872,8 +1871,8 @@ class PillarVocabularyBase(NamedSQLObjectHugeVocabulary):
132 ]
133 base_clauses = [
134 ProductSet.getProductPrivacyFilter(getUtility(ILaunchBag).user)]
135- if self._filter:
136- base_clauses.extend(self._filter)
137+ if self._clauses:
138+ base_clauses.extend(self._clauses)
139 if vocab_filter:
140 base_clauses.extend(vocab_filter.filter_terms)
141 equal_clauses = base_clauses + [PillarName.name == query]
142@@ -1898,7 +1897,7 @@ class PillarVocabularyBase(NamedSQLObjectHugeVocabulary):
143 class DistributionOrProductVocabulary(PillarVocabularyBase):
144 """Active `IDistribution` or `IProduct` objects vocabulary."""
145 displayname = 'Select a project'
146- _filter = [PillarName.projectgroup == None, PillarName.active == True]
147+ _clauses = [PillarName.projectgroup == None, PillarName.active == True]
148
149 def __contains__(self, obj):
150 if IProduct.providedBy(obj):
151@@ -1917,7 +1916,7 @@ class DistributionOrProductVocabulary(PillarVocabularyBase):
152 class DistributionOrProductOrProjectGroupVocabulary(PillarVocabularyBase):
153 """Active `IProduct`, `IProjectGroup` or `IDistribution` vocabulary."""
154 displayname = 'Select a project'
155- _filter = [PillarName.active == True]
156+ _clauses = [PillarName.active == True]
157
158 def __contains__(self, obj):
159 if IProduct.providedBy(obj) or IProjectGroup.providedBy(obj):
160@@ -1938,16 +1937,17 @@ class FeaturedProjectVocabulary(
161 DistributionOrProductOrProjectGroupVocabulary):
162 """Vocabulary of projects that are featured on the LP Home Page."""
163
164- _filter = AND(PillarName.q.id == FeaturedProject.q.pillar_name,
165- PillarName.q.active == True)
166- _clauseTables = ['FeaturedProject']
167+ _clauses = [
168+ PillarName.id == FeaturedProject.pillar_name_id,
169+ PillarName.active == True,
170+ ]
171
172 def __contains__(self, obj):
173 """See `IVocabulary`."""
174- query = """PillarName.id=FeaturedProject.pillar_name
175- AND PillarName.name = %s""" % sqlvalues(obj.name)
176- return PillarName.selectOne(
177- query, clauseTables=['FeaturedProject']) is not None
178+ return IStore(PillarName).find(
179+ PillarName,
180+ PillarName.id == FeaturedProject.pillar_name_id,
181+ PillarName.name == obj.name).one()
182
183
184 class SourcePackageNameIterator(BatchedCountableIterator):
185diff --git a/lib/lp/services/webapp/vocabulary.py b/lib/lp/services/webapp/vocabulary.py
186index 8ccb7b2..b77961f 100644
187--- a/lib/lp/services/webapp/vocabulary.py
188+++ b/lib/lp/services/webapp/vocabulary.py
189@@ -1,4 +1,4 @@
190-# Copyright 2009-2016 Canonical Ltd. This software is licensed under the
191+# Copyright 2009-2020 Canonical Ltd. This software is licensed under the
192 # GNU Affero General Public License version 3 (see the file LICENSE).
193
194 """Vocabularies pulling stuff from the database.
195@@ -15,7 +15,6 @@ __all__ = [
196 'FilteredVocabularyBase',
197 'ForgivingSimpleVocabulary',
198 'IHugeVocabulary',
199- 'NamedSQLObjectHugeVocabulary',
200 'NamedSQLObjectVocabulary',
201 'NamedStormHugeVocabulary',
202 'NamedStormVocabulary',
203@@ -214,10 +213,9 @@ class BatchedCountableIterator(CountableIterator):
204 """A wrapping iterator with hook to create descriptions for its terms."""
205 # XXX kiko 2007-01-18: note that this class doesn't use the item_wrapper
206 # at all. I hate compatibility shims. We can't remove it from the __init__
207- # because it is always supplied by NamedSQLObjectHugeVocabulary, and
208- # we don't want child classes to have to reimplement it. This
209- # probably indicates we need to reconsider how these classes are
210- # split.
211+ # because it is always supplied by NamedStormVocabulary, and we don't
212+ # want child classes to have to reimplement it. This probably indicates
213+ # we need to reconsider how these classes are split.
214 def __iter__(self):
215 """See CountableIterator"""
216 return iter(self.getTermsWithDescriptions(self._iterator))
217@@ -437,40 +435,6 @@ class NamedSQLObjectVocabulary(SQLObjectVocabularyBase):
218 return self.emptySelectResults()
219
220
221-@implementer(IHugeVocabulary)
222-class NamedSQLObjectHugeVocabulary(NamedSQLObjectVocabulary):
223- """A NamedSQLObjectVocabulary that implements IHugeVocabulary."""
224- _orderBy = 'name'
225- displayname = None
226- step_title = 'Search'
227- # The iterator class will be used to wrap the results; its iteration
228- # methods should return SimpleTerms, as the reference implementation
229- # CountableIterator does.
230- iterator = CountableIterator
231-
232- def __init__(self, context=None):
233- NamedSQLObjectVocabulary.__init__(self, context)
234- if self.displayname is None:
235- self.displayname = 'Select %s' % self.__class__.__name__
236-
237- def search(self, query, vocab_filter=None):
238- # XXX kiko 2007-01-17: this is a transitional shim; we're going to
239- # get rid of search() altogether, but for now we've only done it for
240- # the NamedSQLObjectHugeVocabulary.
241- raise NotImplementedError
242-
243- def searchForTerms(self, query=None, vocab_filter=None):
244- if not query:
245- return self.emptySelectResults()
246-
247- query = ensure_unicode(query).lower()
248- clause = CONTAINSSTRING(self._table.q.name, query)
249- if self._filter:
250- clause = AND(clause, self._filter)
251- results = self._table.select(clause, orderBy=self._orderBy)
252- return self.iterator(results.count(), results, self.toTerm)
253-
254-
255 @implementer(IVocabulary, IVocabularyTokenized)
256 class StormVocabularyBase(FilteredVocabularyBase):
257 """A base class for widgets that are rendered to collect values

Subscribers

People subscribed via source and target branches

to status/vote changes: