← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:stormify-languagepack into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:stormify-languagepack into launchpad:master.

Commit message:
Convert LanguagePack to Storm

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/394938
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:stormify-languagepack into launchpad:master.
diff --git a/lib/lp/registry/model/distroseries.py b/lib/lp/registry/model/distroseries.py
index 2811a42..464c197 100644
--- a/lib/lp/registry/model/distroseries.py
+++ b/lib/lp/registry/model/distroseries.py
@@ -35,7 +35,12 @@ from storm.expr import (
     Or,
     SQL,
     )
-from storm.locals import JSON
+from storm.locals import (
+    Int,
+    JSON,
+    Reference,
+    ReferenceSet,
+    )
 from storm.store import Store
 from zope.component import getUtility
 from zope.interface import implementer
@@ -245,20 +250,22 @@ class DistroSeries(SQLBase, BugTargetBase, HasSpecificationsMixin,
     sourcecount = IntCol(notNull=True, default=DEFAULT)
     defer_translation_imports = BoolCol(notNull=True, default=True)
     hide_all_translations = BoolCol(notNull=True, default=True)
-    language_pack_base = ForeignKey(
-        foreignKey="LanguagePack", dbName="language_pack_base", notNull=False,
-        default=None)
-    language_pack_delta = ForeignKey(
-        foreignKey="LanguagePack", dbName="language_pack_delta",
-        notNull=False, default=None)
-    language_pack_proposed = ForeignKey(
-        foreignKey="LanguagePack", dbName="language_pack_proposed",
-        notNull=False, default=None)
+    language_pack_base_id = Int(
+        name="language_pack_base", allow_none=True, default=None)
+    language_pack_base = Reference(language_pack_base_id, "LanguagePack.id")
+    language_pack_delta_id = Int(
+        name="language_pack_delta", allow_none=True, default=None)
+    language_pack_delta = Reference(language_pack_delta_id, "LanguagePack.id")
+    language_pack_proposed_id = Int(
+        name="language_pack_proposed", allow_none=True, default=None)
+    language_pack_proposed = Reference(
+        language_pack_proposed_id, "LanguagePack.id")
     language_pack_full_export_requested = BoolCol(notNull=True, default=False)
     publishing_options = JSON("publishing_options")
 
-    language_packs = SQLMultipleJoin(
-        'LanguagePack', joinColumn='distroseries', orderBy='-date_exported')
+    language_packs = ReferenceSet(
+        'id', 'LanguagePack.distroseries_id',
+        order_by=Desc('LanguagePack.date_exported'))
     sections = SQLRelatedJoin(
         'Section', joinColumn='distroseries', otherColumn='section',
         intermediateTable='SectionSelection')
@@ -794,15 +801,17 @@ class DistroSeries(SQLBase, BugTargetBase, HasSpecificationsMixin,
 
     @property
     def last_full_language_pack_exported(self):
-        return LanguagePack.selectFirstBy(
-            distroseries=self, type=LanguagePackType.FULL,
-            orderBy='-date_exported')
+        language_packs = IStore(LanguagePack).find(
+            LanguagePack, distroseries=self, type=LanguagePackType.FULL)
+        return language_packs.order_by(LanguagePack.date_exported).last()
 
     @property
     def last_delta_language_pack_exported(self):
-        return LanguagePack.selectFirstBy(
+        language_packs = IStore(LanguagePack).find(
+            LanguagePack,
             distroseries=self, type=LanguagePackType.DELTA,
-            updates=self.language_pack_base, orderBy='-date_exported')
+            updates=self.language_pack_base)
+        return language_packs.order_by(LanguagePack.date_exported).last()
 
     @property
     def backports_not_automatic(self):
diff --git a/lib/lp/translations/model/languagepack.py b/lib/lp/translations/model/languagepack.py
index 6de50f7..caa5a68 100644
--- a/lib/lp/translations/model/languagepack.py
+++ b/lib/lp/translations/model/languagepack.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).
 
 """Language pack store."""
@@ -10,16 +10,17 @@ __all__ = [
     'LanguagePackSet',
     ]
 
-from sqlobject import ForeignKey
+import pytz
+from storm.locals import (
+    DateTime,
+    Int,
+    Reference,
+    )
 from zope.interface import implementer
 
 from lp.services.database.constants import UTC_NOW
-from lp.services.database.datetimecol import UtcDateTimeCol
-from lp.services.database.enumcol import EnumCol
-from lp.services.database.sqlbase import (
-    SQLBase,
-    sqlvalues,
-    )
+from lp.services.database.enumcol import DBEnum
+from lp.services.database.stormbase import StormBase
 from lp.translations.enums import LanguagePackType
 from lp.translations.interfaces.languagepack import (
     ILanguagePack,
@@ -28,24 +29,34 @@ from lp.translations.interfaces.languagepack import (
 
 
 @implementer(ILanguagePack)
-class LanguagePack(SQLBase):
+class LanguagePack(StormBase):
+
+    __storm_table__ = 'LanguagePack'
+
+    id = Int(primary=True)
 
-    _table = 'LanguagePack'
+    file_id = Int(name='file', allow_none=False)
+    file = Reference(file_id, 'LibraryFileAlias.id')
 
-    file = ForeignKey(
-        foreignKey='LibraryFileAlias', dbName='file', notNull=True)
+    date_exported = DateTime(
+        tzinfo=pytz.UTC, allow_none=False, default=UTC_NOW)
 
-    date_exported = UtcDateTimeCol(notNull=True, default=UTC_NOW)
+    distroseries_id = Int(name='distroseries', allow_none=False)
+    distroseries = Reference(distroseries_id, 'DistroSeries.id')
 
-    distroseries = ForeignKey(
-        foreignKey='DistroSeries', dbName='distroseries', notNull=True)
+    type = DBEnum(
+        enum=LanguagePackType, allow_none=False, default=LanguagePackType.FULL)
 
-    type = EnumCol(
-        enum=LanguagePackType, notNull=True, default=LanguagePackType.FULL)
+    updates_id = Int(name='updates', allow_none=True, default=None)
+    updates = Reference(updates_id, 'LanguagePack.id')
 
-    updates = ForeignKey(
-        foreignKey='LanguagePack', dbName='updates',
-        notNull=False, default=None)
+    def __init__(self, file, date_exported, distroseries, type, updates=None):
+        super(LanguagePack, self).__init__()
+        self.file = file
+        self.date_exported = date_exported
+        self.distroseries = distroseries
+        self.type = type
+        self.updates = updates
 
 
 @implementer(ILanguagePackSet)
@@ -57,11 +68,10 @@ class LanguagePackSet:
             'Unknown language pack type: %s' % type.name)
 
         if (type == LanguagePackType.DELTA and
-            distroseries.language_pack_base is None):
+                distroseries.language_pack_base is None):
             raise AssertionError(
-                "There is no base language pack available for %s's %s to get"
-                " deltas from." % sqlvalues(
-                    distroseries.distribution.name, distroseries.name))
+                "There is no base language pack available for %s to get"
+                " deltas from." % distroseries)
 
         updates = None
         if type == LanguagePackType.DELTA:
diff --git a/lib/lp/translations/vocabularies.py b/lib/lp/translations/vocabularies.py
index 0da0c5f..99d54b3 100644
--- a/lib/lp/translations/vocabularies.py
+++ b/lib/lp/translations/vocabularies.py
@@ -1,4 +1,4 @@
-# Copyright 2009-2011 Canonical Ltd.  This software is licensed under the GNU
+# Copyright 2009-2020 Canonical Ltd.  This software is licensed under the GNU
 # Affero General Public License version 3 (see the file LICENSE).
 
 """Translations vocabularies."""
@@ -16,13 +16,18 @@ __all__ = [
     ]
 
 from sqlobject import AND
+from storm.locals import (
+    Desc,
+    Not,
+    Or,
+    )
 from zope.schema.vocabulary import SimpleTerm
 
 from lp.registry.interfaces.distroseries import IDistroSeries
-from lp.services.database.sqlbase import sqlvalues
 from lp.services.webapp.vocabulary import (
     NamedSQLObjectVocabulary,
     SQLObjectVocabularyBase,
+    StormVocabularyBase,
     )
 from lp.services.worlddata.interfaces.language import ILanguage
 from lp.services.worlddata.vocabularies import LanguageVocabulary
@@ -119,53 +124,48 @@ class TranslationTemplateVocabulary(SQLObjectVocabularyBase):
         return SimpleTerm(obj, obj.id, obj.name)
 
 
-class FilteredLanguagePackVocabularyBase(SQLObjectVocabularyBase):
+class FilteredLanguagePackVocabularyBase(StormVocabularyBase):
     """Base vocabulary class to retrieve language packs for a distroseries."""
     _table = LanguagePack
-    _orderBy = '-date_exported'
+    _order_by = Desc(LanguagePack.date_exported)
+
+    def __init__(self, context=None):
+        if not IDistroSeries.providedBy(context):
+            raise AssertionError(
+                "%s is only useful from a DistroSeries context." %
+                self.__class__.__name__)
+        super(FilteredLanguagePackVocabularyBase, self).__init__(context)
 
     def toTerm(self, obj):
         return SimpleTerm(
             obj, obj.id, '%s' % obj.date_exported.strftime('%F %T %Z'))
 
-    def _baseQueryList(self):
-        """Return a list of sentences that defines the specific filtering.
-
-        That list will be linked with an ' AND '.
-        """
-        raise NotImplementedError
-
-    def __iter__(self):
-        if not IDistroSeries.providedBy(self.context):
-            # This vocabulary is only useful from a DistroSeries context.
-            return
-
-        query = self._baseQueryList()
-        query.append('distroseries = %s' % sqlvalues(self.context))
-        language_packs = self._table.select(
-            ' AND '.join(query), orderBy=self._orderBy)
-
-        for language_pack in language_packs:
-            yield self.toTerm(language_pack)
+    @property
+    def _clauses(self):
+        return [LanguagePack.distroseries == self.context]
 
 
 class FilteredFullLanguagePackVocabulary(FilteredLanguagePackVocabularyBase):
     """Full export Language Pack for a distribution series."""
     displayname = 'Select a full export language pack'
 
-    def _baseQueryList(self):
-        """See `FilteredLanguagePackVocabularyBase`."""
-        return ['type = %s' % sqlvalues(LanguagePackType.FULL)]
+    @property
+    def _clauses(self):
+        return (
+            super(FilteredFullLanguagePackVocabulary, self)._clauses +
+            [LanguagePack.type == LanguagePackType.FULL])
 
 
 class FilteredDeltaLanguagePackVocabulary(FilteredLanguagePackVocabularyBase):
     """Delta export Language Pack for a distribution series."""
     displayname = 'Select a delta export language pack'
 
-    def _baseQueryList(self):
-        """See `FilteredLanguagePackVocabularyBase`."""
-        return ['(type = %s AND updates = %s)' % sqlvalues(
-            LanguagePackType.DELTA, self.context.language_pack_base)]
+    @property
+    def _clauses(self):
+        return (
+            super(FilteredDeltaLanguagePackVocabulary, self)._clauses +
+            [LanguagePack.type == LanguagePackType.DELTA,
+             LanguagePack.updates == self.context.language_pack_base])
 
 
 class FilteredLanguagePackVocabulary(FilteredLanguagePackVocabularyBase):
@@ -176,8 +176,8 @@ class FilteredLanguagePackVocabulary(FilteredLanguagePackVocabularyBase):
             obj, obj.id, '%s (%s)' % (
                 obj.date_exported.strftime('%F %T %Z'), obj.type.title))
 
-    def _baseQueryList(self):
-        """See `FilteredLanguagePackVocabularyBase`."""
+    @property
+    def _clauses(self):
         # We are interested on any full language pack or language pack
         # that is a delta of the current base lanuage pack type,
         # except the ones already used.
@@ -186,9 +186,10 @@ class FilteredLanguagePackVocabulary(FilteredLanguagePackVocabularyBase):
             used_lang_packs.append(self.context.language_pack_base.id)
         if self.context.language_pack_delta is not None:
             used_lang_packs.append(self.context.language_pack_delta.id)
-        query = []
+        clauses = []
         if used_lang_packs:
-            query.append('id NOT IN %s' % sqlvalues(used_lang_packs))
-        query.append('(updates is NULL OR updates = %s)' % sqlvalues(
-            self.context.language_pack_base))
-        return query
+            clauses.append(Not(LanguagePack.id.is_in(used_lang_packs)))
+        clauses.append(Or(
+            LanguagePack.updates == None,
+            LanguagePack.updates == self.context.language_pack_base))
+        return super(FilteredLanguagePackVocabulary, self)._clauses + clauses