launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #25794
[Merge] ~cjwatson/launchpad:stormify-featuredproject into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:stormify-featuredproject into launchpad:master.
Commit message:
Convert FeaturedProject to Storm
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/394874
This also removes the last user of NamedSQLObjectHugeVocabulary.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:stormify-featuredproject into launchpad:master.
diff --git a/lib/lp/registry/model/featuredproject.py b/lib/lp/registry/model/featuredproject.py
index 6440064..35d3579 100644
--- a/lib/lp/registry/model/featuredproject.py
+++ b/lib/lp/registry/model/featuredproject.py
@@ -1,4 +1,4 @@
-# Copyright 2009 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2020 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Database class for Featured Projects."""
@@ -8,15 +8,19 @@ __all__ = [
'FeaturedProject',
]
-from sqlobject import IntCol
+from storm.locals import (
+ Int,
+ Reference,
+ )
from zope.interface import implementer
from lp.registry.interfaces.featuredproject import IFeaturedProject
-from lp.services.database.sqlbase import SQLBase
+from lp.services.database.interfaces import IStore
+from lp.services.database.stormbase import StormBase
@implementer(IFeaturedProject)
-class FeaturedProject(SQLBase):
+class FeaturedProject(StormBase):
"""A featured project reference.
This is a reference to the name of a project, product or distribution
@@ -24,6 +28,16 @@ class FeaturedProject(SQLBase):
page.
"""
- _defaultOrder = ['id']
+ __storm_table__ = 'FeaturedProject'
+ __storm_order__ = ['id']
- pillar_name = IntCol(notNull=True)
+ id = Int(primary=True)
+ pillar_name_id = Int(name='pillar_name', allow_none=False)
+ pillar_name = Reference(pillar_name_id, 'PillarName.id')
+
+ def __init__(self, pillar_name):
+ super(FeaturedProject, self).__init__()
+ self.pillar_name = pillar_name
+
+ def destroySelf(self):
+ IStore(self).remove(self)
diff --git a/lib/lp/registry/model/pillar.py b/lib/lp/registry/model/pillar.py
index 8bfc356..3482abb 100644
--- a/lib/lp/registry/model/pillar.py
+++ b/lib/lp/registry/model/pillar.py
@@ -1,4 +1,4 @@
-# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2020 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Launchpad Pillars share a namespace.
@@ -249,24 +249,23 @@ class PillarNameSet:
def add_featured_project(self, project):
"""See `IPillarSet`."""
- query = """
- PillarName.name = %s
- AND PillarName.id = FeaturedProject.pillar_name
- """ % sqlvalues(project.name)
- existing = FeaturedProject.selectOne(
- query, clauseTables=['PillarName'])
+ existing = IStore(FeaturedProject).find(
+ FeaturedProject,
+ PillarName.name == project.name,
+ PillarName.id == FeaturedProject.pillar_name_id).one()
if existing is None:
- pillar_name = PillarName.selectOneBy(name=project.name)
- return FeaturedProject(pillar_name=pillar_name.id)
+ pillar_name = IStore(PillarName).find(
+ PillarName, name=project.name).one()
+ featured_project = FeaturedProject(pillar_name=pillar_name)
+ IStore(FeaturedProject).add(featured_project)
+ return featured_project
def remove_featured_project(self, project):
"""See `IPillarSet`."""
- query = """
- PillarName.name = %s
- AND PillarName.id = FeaturedProject.pillar_name
- """ % sqlvalues(project.name)
- existing = FeaturedProject.selectOne(
- query, clauseTables=['PillarName'])
+ existing = IStore(FeaturedProject).find(
+ FeaturedProject,
+ PillarName.name == project.name,
+ PillarName.id == FeaturedProject.pillar_name_id).one()
if existing is not None:
existing.destroySelf()
@@ -280,7 +279,7 @@ class PillarNameSet:
store = IStore(PillarName)
pillar_names = store.find(
- PillarName, PillarName.id == FeaturedProject.pillar_name)
+ PillarName, PillarName.id == FeaturedProject.pillar_name_id)
def preload_pillars(rows):
pillar_names = (
diff --git a/lib/lp/registry/vocabularies.py b/lib/lp/registry/vocabularies.py
index 31d9f3d..008dcbc 100644
--- a/lib/lp/registry/vocabularies.py
+++ b/lib/lp/registry/vocabularies.py
@@ -211,7 +211,6 @@ from lp.services.webapp.vocabulary import (
CountableIterator,
FilteredVocabularyBase,
IHugeVocabulary,
- NamedSQLObjectHugeVocabulary,
NamedSQLObjectVocabulary,
NamedStormHugeVocabulary,
SQLObjectVocabularyBase,
@@ -1827,7 +1826,7 @@ class VocabularyFilterDistribution(VocabularyFilter):
return [PillarName.distribution != None]
-class PillarVocabularyBase(NamedSQLObjectHugeVocabulary):
+class PillarVocabularyBase(NamedStormHugeVocabulary):
"""Active `IPillar` objects vocabulary."""
displayname = 'Needs to be overridden'
_table = PillarName
@@ -1872,8 +1871,8 @@ class PillarVocabularyBase(NamedSQLObjectHugeVocabulary):
]
base_clauses = [
ProductSet.getProductPrivacyFilter(getUtility(ILaunchBag).user)]
- if self._filter:
- base_clauses.extend(self._filter)
+ if self._clauses:
+ base_clauses.extend(self._clauses)
if vocab_filter:
base_clauses.extend(vocab_filter.filter_terms)
equal_clauses = base_clauses + [PillarName.name == query]
@@ -1898,7 +1897,7 @@ class PillarVocabularyBase(NamedSQLObjectHugeVocabulary):
class DistributionOrProductVocabulary(PillarVocabularyBase):
"""Active `IDistribution` or `IProduct` objects vocabulary."""
displayname = 'Select a project'
- _filter = [PillarName.projectgroup == None, PillarName.active == True]
+ _clauses = [PillarName.projectgroup == None, PillarName.active == True]
def __contains__(self, obj):
if IProduct.providedBy(obj):
@@ -1917,7 +1916,7 @@ class DistributionOrProductVocabulary(PillarVocabularyBase):
class DistributionOrProductOrProjectGroupVocabulary(PillarVocabularyBase):
"""Active `IProduct`, `IProjectGroup` or `IDistribution` vocabulary."""
displayname = 'Select a project'
- _filter = [PillarName.active == True]
+ _clauses = [PillarName.active == True]
def __contains__(self, obj):
if IProduct.providedBy(obj) or IProjectGroup.providedBy(obj):
@@ -1938,16 +1937,17 @@ class FeaturedProjectVocabulary(
DistributionOrProductOrProjectGroupVocabulary):
"""Vocabulary of projects that are featured on the LP Home Page."""
- _filter = AND(PillarName.q.id == FeaturedProject.q.pillar_name,
- PillarName.q.active == True)
- _clauseTables = ['FeaturedProject']
+ _clauses = [
+ PillarName.id == FeaturedProject.pillar_name_id,
+ PillarName.active == True,
+ ]
def __contains__(self, obj):
"""See `IVocabulary`."""
- query = """PillarName.id=FeaturedProject.pillar_name
- AND PillarName.name = %s""" % sqlvalues(obj.name)
- return PillarName.selectOne(
- query, clauseTables=['FeaturedProject']) is not None
+ return IStore(PillarName).find(
+ PillarName,
+ PillarName.id == FeaturedProject.pillar_name_id,
+ PillarName.name == obj.name).one()
class SourcePackageNameIterator(BatchedCountableIterator):
diff --git a/lib/lp/services/webapp/vocabulary.py b/lib/lp/services/webapp/vocabulary.py
index 8ccb7b2..b77961f 100644
--- a/lib/lp/services/webapp/vocabulary.py
+++ b/lib/lp/services/webapp/vocabulary.py
@@ -1,4 +1,4 @@
-# Copyright 2009-2016 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2020 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Vocabularies pulling stuff from the database.
@@ -15,7 +15,6 @@ __all__ = [
'FilteredVocabularyBase',
'ForgivingSimpleVocabulary',
'IHugeVocabulary',
- 'NamedSQLObjectHugeVocabulary',
'NamedSQLObjectVocabulary',
'NamedStormHugeVocabulary',
'NamedStormVocabulary',
@@ -214,10 +213,9 @@ class BatchedCountableIterator(CountableIterator):
"""A wrapping iterator with hook to create descriptions for its terms."""
# XXX kiko 2007-01-18: note that this class doesn't use the item_wrapper
# at all. I hate compatibility shims. We can't remove it from the __init__
- # because it is always supplied by NamedSQLObjectHugeVocabulary, and
- # we don't want child classes to have to reimplement it. This
- # probably indicates we need to reconsider how these classes are
- # split.
+ # because it is always supplied by NamedStormVocabulary, and we don't
+ # want child classes to have to reimplement it. This probably indicates
+ # we need to reconsider how these classes are split.
def __iter__(self):
"""See CountableIterator"""
return iter(self.getTermsWithDescriptions(self._iterator))
@@ -437,40 +435,6 @@ class NamedSQLObjectVocabulary(SQLObjectVocabularyBase):
return self.emptySelectResults()
-@implementer(IHugeVocabulary)
-class NamedSQLObjectHugeVocabulary(NamedSQLObjectVocabulary):
- """A NamedSQLObjectVocabulary that implements IHugeVocabulary."""
- _orderBy = 'name'
- displayname = None
- step_title = 'Search'
- # The iterator class will be used to wrap the results; its iteration
- # methods should return SimpleTerms, as the reference implementation
- # CountableIterator does.
- iterator = CountableIterator
-
- def __init__(self, context=None):
- NamedSQLObjectVocabulary.__init__(self, context)
- if self.displayname is None:
- self.displayname = 'Select %s' % self.__class__.__name__
-
- def search(self, query, vocab_filter=None):
- # XXX kiko 2007-01-17: this is a transitional shim; we're going to
- # get rid of search() altogether, but for now we've only done it for
- # the NamedSQLObjectHugeVocabulary.
- raise NotImplementedError
-
- def searchForTerms(self, query=None, vocab_filter=None):
- if not query:
- return self.emptySelectResults()
-
- query = ensure_unicode(query).lower()
- clause = CONTAINSSTRING(self._table.q.name, query)
- if self._filter:
- clause = AND(clause, self._filter)
- results = self._table.select(clause, orderBy=self._orderBy)
- return self.iterator(results.count(), results, self.toTerm)
-
-
@implementer(IVocabulary, IVocabularyTokenized)
class StormVocabularyBase(FilteredVocabularyBase):
"""A base class for widgets that are rendered to collect values