← Back to team overview

launchpad-reviewers team mailing list archive

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

 

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

Commit message:
Convert Component* and Section* to Storm

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/428083
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:stormify-component-section into launchpad:master.
diff --git a/lib/lp/archivepublisher/model/ftparchive.py b/lib/lp/archivepublisher/model/ftparchive.py
index 15bf6e6..710fee5 100644
--- a/lib/lp/archivepublisher/model/ftparchive.py
+++ b/lib/lp/archivepublisher/model/ftparchive.py
@@ -297,10 +297,11 @@ class FTPArchiveHandler:
             SourcePackagePublishingHistory,
             Join(
                 Component,
-                Component.id == SourcePackagePublishingHistory.componentID,
+                Component.id == SourcePackagePublishingHistory.component_id,
             ),
             Join(
-                Section, Section.id == SourcePackagePublishingHistory.sectionID
+                Section,
+                Section.id == SourcePackagePublishingHistory.section_id,
             ),
             Join(
                 SourcePackageRelease,
@@ -346,10 +347,11 @@ class FTPArchiveHandler:
             BinaryPackagePublishingHistory,
             Join(
                 Component,
-                Component.id == BinaryPackagePublishingHistory.componentID,
+                Component.id == BinaryPackagePublishingHistory.component_id,
             ),
             Join(
-                Section, Section.id == BinaryPackagePublishingHistory.sectionID
+                Section,
+                Section.id == BinaryPackagePublishingHistory.section_id,
             ),
             Join(
                 BinaryPackageRelease,
@@ -674,7 +676,7 @@ class FTPArchiveHandler:
             SourcePackageName.id
             == SourcePackagePublishingHistory.sourcepackagenameID,
             LibraryFileAlias.id == SourcePackageReleaseFile.libraryfileID,
-            Component.id == SourcePackagePublishingHistory.componentID,
+            Component.id == SourcePackagePublishingHistory.component_id,
         ]
         select_conditions = [
             SourcePackagePublishingHistory.archive == self.publisher.archive,
@@ -718,7 +720,7 @@ class FTPArchiveHandler:
             LibraryFileAlias.id == BinaryPackageFile.libraryfileID,
             DistroArchSeries.id
             == BinaryPackagePublishingHistory.distroarchseriesID,
-            Component.id == BinaryPackagePublishingHistory.componentID,
+            Component.id == BinaryPackagePublishingHistory.component_id,
         ]
         select_conditions = [
             DistroArchSeries.distroseriesID == distroseries.id,
diff --git a/lib/lp/archiveuploader/tests/test_ppauploadprocessor.py b/lib/lp/archiveuploader/tests/test_ppauploadprocessor.py
index ce409a5..5965539 100644
--- a/lib/lp/archiveuploader/tests/test_ppauploadprocessor.py
+++ b/lib/lp/archiveuploader/tests/test_ppauploadprocessor.py
@@ -28,11 +28,11 @@ from lp.soyuz.enums import (
     SourcePackageFormat,
 )
 from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
+from lp.soyuz.interfaces.component import IComponentSet
 from lp.soyuz.interfaces.queue import NonBuildableSourceUploadError
 from lp.soyuz.interfaces.sourcepackageformat import (
     ISourcePackageFormatSelectionSet,
 )
-from lp.soyuz.model.component import Component
 from lp.soyuz.model.publishing import BinaryPackagePublishingHistory
 from lp.soyuz.tests.fakepackager import FakePackager
 from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
@@ -758,7 +758,7 @@ class TestPPAUploadProcessor(TestPPAUploadProcessorBase):
         """
         # The component contrib does not exist in the sample data, so
         # add it here.
-        Component(name="contrib")
+        getUtility(IComponentSet).new("contrib")
 
         # Upload a source package first.
         upload_dir = self.queueUpload(
diff --git a/lib/lp/archiveuploader/tests/test_uploadprocessor.py b/lib/lp/archiveuploader/tests/test_uploadprocessor.py
index e80db4a..29d3024 100644
--- a/lib/lp/archiveuploader/tests/test_uploadprocessor.py
+++ b/lib/lp/archiveuploader/tests/test_uploadprocessor.py
@@ -82,7 +82,6 @@ from lp.soyuz.interfaces.sourcepackageformat import (
 from lp.soyuz.model.archivepermission import ArchivePermission
 from lp.soyuz.model.binarypackagename import BinaryPackageName
 from lp.soyuz.model.binarypackagerelease import BinaryPackageRelease
-from lp.soyuz.model.component import Component
 from lp.soyuz.model.publishing import (
     BinaryPackagePublishingHistory,
     SourcePackagePublishingHistory,
@@ -1454,7 +1453,7 @@ class TestUploadProcessor(StatsMixin, TestUploadProcessorBase):
         """Test the overriding of the contrib component on uploads."""
         # The component contrib does not exist in the sample data, so
         # add it here.
-        Component(name="contrib")
+        getUtility(IComponentSet).new("contrib")
         self.checkComponentOverride(
             "bar_1.0-1_contrib_component", "multiverse"
         )
@@ -1463,7 +1462,7 @@ class TestUploadProcessor(StatsMixin, TestUploadProcessorBase):
         """Test the overriding of the non-free component on uploads."""
         # The component non-free does not exist in the sample data, so
         # add it here.
-        Component(name="non-free")
+        getUtility(IComponentSet).new("non-free")
         self.checkComponentOverride(
             "bar_1.0-1_nonfree_component", "multiverse"
         )
diff --git a/lib/lp/bugs/model/bugtasksearch.py b/lib/lp/bugs/model/bugtasksearch.py
index 88dd83a..19598bc 100644
--- a/lib/lp/bugs/model/bugtasksearch.py
+++ b/lib/lp/bugs/model/bugtasksearch.py
@@ -657,7 +657,7 @@ def _build_query(params):
                         ),
                         SourcePackagePublishingHistory.distroseries
                         == distroseries,
-                        SourcePackagePublishingHistory.componentID.is_in(
+                        SourcePackagePublishingHistory.component_id.is_in(
                             c.id for c in components
                         ),
                         SourcePackagePublishingHistory.status
diff --git a/lib/lp/registry/doc/distroseries.rst b/lib/lp/registry/doc/distroseries.rst
index 691b145..e6979da 100644
--- a/lib/lp/registry/doc/distroseries.rst
+++ b/lib/lp/registry/doc/distroseries.rst
@@ -233,9 +233,9 @@ other things) the uploader for validating incoming uploads.
     translations
 
     >>> from lp.soyuz.interfaces.section import ISectionSet
+    >>> from lp.soyuz.model.section import SectionSelection
     >>> python = getUtility(ISectionSet).ensure('python')
-
-    >>> hoary.addSection(python)
+    >>> _ = SectionSelection(distroseries=hoary, section=python)
 
     >>> for c in hoary.components:
     ...     print(c.name)
diff --git a/lib/lp/registry/doc/sourcepackage.rst b/lib/lp/registry/doc/sourcepackage.rst
index 1b69a70..c471752 100644
--- a/lib/lp/registry/doc/sourcepackage.rst
+++ b/lib/lp/registry/doc/sourcepackage.rst
@@ -135,7 +135,7 @@ upload, even though it gets changed in the publishing record.
 
     >>> latest_publishing = IStore(SourcePackagePublishingHistory).get(
     ...     SourcePackagePublishingHistory, publishing_history.last().id)
-    >>> universe = Component.byName('universe')
+    >>> universe = IStore(Component).find(Component, name='universe').one()
     >>> latest_publishing.component = universe
     >>> flush_database_caches()
 
diff --git a/lib/lp/registry/interfaces/distroseries.py b/lib/lp/registry/interfaces/distroseries.py
index f8c5fa4..03e6d68 100644
--- a/lib/lp/registry/interfaces/distroseries.py
+++ b/lib/lp/registry/interfaces/distroseries.py
@@ -918,9 +918,6 @@ class IDistroSeriesPublic(
         list for this distroseries.
         """
 
-    def addSection(section):
-        """SQLObject provided method to fill a related join key section."""
-
     def searchPackages(text):
         """Search through the package cache for this distroseries and return
         DistroSeriesBinaryPackage objects that match the given text.
diff --git a/lib/lp/registry/model/distroseries.py b/lib/lp/registry/model/distroseries.py
index edf2223..c3f912d 100644
--- a/lib/lp/registry/model/distroseries.py
+++ b/lib/lp/registry/model/distroseries.py
@@ -74,7 +74,6 @@ from lp.services.database.sqlobject import (
     IntCol,
     SQLMultipleJoin,
     SQLObjectNotFound,
-    SQLRelatedJoin,
     StringCol,
 )
 from lp.services.database.stormexpr import IsTrue, WithMaterialized, fti_search
@@ -101,7 +100,7 @@ from lp.soyuz.interfaces.sourcepackageformat import (
     ISourcePackageFormatSelectionSet,
 )
 from lp.soyuz.model.binarypackagename import BinaryPackageName
-from lp.soyuz.model.component import Component
+from lp.soyuz.model.component import Component, ComponentSelection
 from lp.soyuz.model.distributionsourcepackagerelease import (
     DistributionSourcePackageRelease,
 )
@@ -241,11 +240,11 @@ class DistroSeries(
         "LanguagePack.distroseries_id",
         order_by=Desc("LanguagePack.date_exported"),
     )
-    sections = SQLRelatedJoin(
-        "Section",
-        joinColumn="distroseries",
-        otherColumn="section",
-        intermediateTable="SectionSelection",
+    sections = ReferenceSet(
+        "id",
+        "SectionSelection.distroseries_id",
+        "SectionSelection.section_id",
+        "Section.id",
     )
 
     def __init__(self, *args, **kwargs):
@@ -285,13 +284,10 @@ class DistroSeries(
     @property
     def upload_components(self):
         """See `IDistroSeries`."""
-        return Component.select(
-            """
-            ComponentSelection.distroseries = %s AND
-            Component.id = ComponentSelection.component
-            """
-            % self.id,
-            clauseTables=["ComponentSelection"],
+        return IStore(Component).find(
+            Component,
+            ComponentSelection.distroseries == self,
+            ComponentSelection.component == Component.id,
         )
 
     @cachedproperty
@@ -301,14 +297,11 @@ class DistroSeries(
         # This is filtering out the partner component for now, until
         # the second stage of the partner repo arrives in 1.1.8.
         return list(
-            Component.select(
-                """
-            ComponentSelection.distroseries = %s AND
-            Component.id = ComponentSelection.component AND
-            Component.name != 'partner'
-            """
-                % self.id,
-                clauseTables=["ComponentSelection"],
+            IStore(Component).find(
+                Component,
+                ComponentSelection.distroseries == self,
+                ComponentSelection.component == Component.id,
+                Component.name != "partner",
             )
         )
 
@@ -1266,7 +1259,7 @@ class DistroSeries(
 
     def getComponentByName(self, name):
         """See `IDistroSeries`."""
-        comp = Component.byName(name)
+        comp = IStore(Component).find(Component, name=name).one()
         if comp is None:
             raise NotFoundError(name)
         permitted = set(self.components)
diff --git a/lib/lp/services/database/tests/test_bulk.py b/lib/lp/services/database/tests/test_bulk.py
index 975250a..4422d64 100644
--- a/lib/lp/services/database/tests/test_bulk.py
+++ b/lib/lp/services/database/tests/test_bulk.py
@@ -198,6 +198,7 @@ class TestLoaders(TestCaseWithFactory):
             self.factory.makeComponent(),
             self.factory.makeComponent(),
         ]
+        IStore(db_objects[-1]).flush()
         db_object_ids = [db_object.id for db_object in db_objects]
         self.assertEqual(
             set(bulk.load(Component, db_object_ids)), set(db_objects)
diff --git a/lib/lp/soyuz/adapters/overrides.py b/lib/lp/soyuz/adapters/overrides.py
index 31153d0..1a008c0 100644
--- a/lib/lp/soyuz/adapters/overrides.py
+++ b/lib/lp/soyuz/adapters/overrides.py
@@ -270,8 +270,8 @@ class FromExistingOverridePolicy(BaseOverridePolicy):
             store.find(
                 (
                     SourcePackagePublishingHistory.sourcepackagenameID,
-                    SourcePackagePublishingHistory.componentID,
-                    SourcePackagePublishingHistory.sectionID,
+                    SourcePackagePublishingHistory.component_id,
+                    SourcePackagePublishingHistory.section_id,
                     SourcePackagePublishingHistory.status,
                     SourcePackageRelease.version,
                 ),
@@ -360,8 +360,8 @@ class FromExistingOverridePolicy(BaseOverridePolicy):
                 (
                     BinaryPackagePublishingHistory.binarypackagenameID,
                     BinaryPackagePublishingHistory.distroarchseriesID,
-                    BinaryPackagePublishingHistory.componentID,
-                    BinaryPackagePublishingHistory.sectionID,
+                    BinaryPackagePublishingHistory.component_id,
+                    BinaryPackagePublishingHistory.section_id,
                     BinaryPackagePublishingHistory.priority,
                     BinaryPackagePublishingHistory.status,
                     BinaryPackageRelease.version,
diff --git a/lib/lp/soyuz/configure.zcml b/lib/lp/soyuz/configure.zcml
index 96cecb2..0740ee5 100644
--- a/lib/lp/soyuz/configure.zcml
+++ b/lib/lp/soyuz/configure.zcml
@@ -714,7 +714,7 @@
             interface="lp.soyuz.interfaces.section.ISection"/>
     </class>
 
-    <!-- Section -->
+    <!-- SectionSelection -->
 
     <class
         class="lp.soyuz.model.section.SectionSelection">
diff --git a/lib/lp/soyuz/doc/components-and-sections.rst b/lib/lp/soyuz/doc/components-and-sections.rst
index a3fbd62..fb63385 100644
--- a/lib/lp/soyuz/doc/components-and-sections.rst
+++ b/lib/lp/soyuz/doc/components-and-sections.rst
@@ -11,12 +11,13 @@ Zope auxiliary test toolchain:
 
 Importing Component content class and its interface:
 
+    >>> from lp.services.database.interfaces import IStore
     >>> from lp.soyuz.interfaces.component import IComponent
     >>> from lp.soyuz.model.component import Component
 
 Get an Component instance from the current sampledata:
 
-    >>> main = Component.get(1)
+    >>> main = IStore(Component).get(Component, 1)
 
 Test some attributes:
 
@@ -82,7 +83,7 @@ Importing Section content class and its interface:
 
 Get a Section instance from the current sampledata:
 
-    >>> base = Section.get(1)
+    >>> base = IStore(Section).get(Section, 1)
 
 Test some attributes:
 
diff --git a/lib/lp/soyuz/doc/distroarchseriesbinarypackage.rst b/lib/lp/soyuz/doc/distroarchseriesbinarypackage.rst
index e23d5f9..3a145a5 100644
--- a/lib/lp/soyuz/doc/distroarchseriesbinarypackage.rst
+++ b/lib/lp/soyuz/doc/distroarchseriesbinarypackage.rst
@@ -26,12 +26,13 @@ builds that are in sampledata!
     >>> from lp.soyuz.model.publishing import (
     ...        BinaryPackagePublishingHistory)
     >>> from lp.services.database.constants import UTC_NOW
+    >>> from lp.services.database.interfaces import IStore
     >>> from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild
     >>> from lp.soyuz.model.component import Component
     >>> from lp.soyuz.model.section import Section
 
-    >>> main_component = Component.selectOneBy(name="main")
-    >>> misc_section = Section.selectOneBy(name="base")
+    >>> main_component = IStore(Component).find(Component, name="main").one()
+    >>> misc_section = IStore(Section).find(Section, name="base").one()
     >>> from lp.soyuz.enums import BinaryPackageFormat
     >>> binpackageformat = BinaryPackageFormat.DEB
     >>> from lp.soyuz.enums import (
@@ -242,7 +243,6 @@ Then, supersede all pmount publications in warty for pmount (this sets
 us up to demonstrate bug 208233).
 
     >>> switch_dbuser('archivepublisher')
-    >>> from lp.services.database.interfaces import IStore
     >>> from lp.soyuz.model.binarypackagename import BinaryPackageName
     >>> from lp.soyuz.model.distroarchseries import DistroArchSeries
     >>> from lp.soyuz.model.distroarchseriesbinarypackage import (
diff --git a/lib/lp/soyuz/doc/gina.rst b/lib/lp/soyuz/doc/gina.rst
index 94bc0df..78356eb 100644
--- a/lib/lp/soyuz/doc/gina.rst
+++ b/lib/lp/soyuz/doc/gina.rst
@@ -32,7 +32,7 @@ Get the current counts of stuff in the database:
     >>> orig_build_count = BinaryPackageBuild.select().count()
     >>> orig_sbpph_count = SBPPH.select().count()
     >>> orig_sspph_main_count = SSPPH.selectBy(
-    ...     componentID=1, pocket=PackagePublishingPocket.RELEASE).count()
+    ...     component_id=1, pocket=PackagePublishingPocket.RELEASE).count()
 
 Create a distribution release and an arch release for breezy:
 
@@ -367,7 +367,7 @@ successfully processed.
     21
 
     >>> new_count = SSPPH.selectBy(
-    ...     componentID=1,
+    ...     component_id=1,
     ...     pocket=PackagePublishingPocket.RELEASE).count()
     >>> print(new_count - orig_sspph_main_count)
     21
diff --git a/lib/lp/soyuz/interfaces/publishing.py b/lib/lp/soyuz/interfaces/publishing.py
index 2507a53..aa5d14f 100644
--- a/lib/lp/soyuz/interfaces/publishing.py
+++ b/lib/lp/soyuz/interfaces/publishing.py
@@ -256,7 +256,7 @@ class ISourcePackagePublishingHistoryPublic(IPublishingView):
         required=False,
         readonly=False,
     )
-    sectionID = Attribute("DB ID for the section")
+    section_id = Attribute("DB ID for the section")
     section = Int(
         title=_("The section being published into"),
         required=False,
diff --git a/lib/lp/soyuz/model/archive.py b/lib/lp/soyuz/model/archive.py
index edac91f..02581d4 100644
--- a/lib/lp/soyuz/model/archive.py
+++ b/lib/lp/soyuz/model/archive.py
@@ -718,7 +718,8 @@ class Archive(SQLBase):
         if component_name is not None:
             clauses.extend(
                 [
-                    SourcePackagePublishingHistory.componentID == Component.id,
+                    SourcePackagePublishingHistory.component_id
+                    == Component.id,
                     Component.name == component_name,
                 ]
             )
@@ -776,7 +777,7 @@ class Archive(SQLBase):
             ids.discard(None)
             if ids:
                 list(store.find(DistroSeries, DistroSeries.id.is_in(ids)))
-            ids = set(map(attrgetter("sectionID"), rows))
+            ids = set(map(attrgetter("section_id"), rows))
             ids.discard(None)
             if ids:
                 list(store.find(Section, Section.id.is_in(ids)))
@@ -994,7 +995,8 @@ class Archive(SQLBase):
         if component_name is not None:
             clauses.extend(
                 [
-                    BinaryPackagePublishingHistory.componentID == Component.id,
+                    BinaryPackagePublishingHistory.component_id
+                    == Component.id,
                     Component.name == component_name,
                 ]
             )
@@ -1053,8 +1055,8 @@ class Archive(SQLBase):
                 SourcePackageRelease, bpbs, ["source_package_release_id"]
             )
             load_related(SourcePackageName, sprs, ["sourcepackagenameID"])
-            load_related(Component, bpphs, ["componentID"])
-            load_related(Section, bpphs, ["sectionID"])
+            load_related(Component, bpphs, ["component_id"])
+            load_related(Section, bpphs, ["section_id"])
             dases = load_related(
                 DistroArchSeries, bpphs, ["distroarchseriesID"]
             )
@@ -1290,7 +1292,7 @@ class Archive(SQLBase):
                 == distro_arch_series,
                 BinaryPackagePublishingHistory.status
                 == PackagePublishingStatus.PUBLISHED,
-                BinaryPackagePublishingHistory.componentID == Component.id,
+                BinaryPackagePublishingHistory.component_id == Component.id,
                 archive_clause,
             )
             .order_by(Desc(BinaryPackagePublishingHistory.id))
diff --git a/lib/lp/soyuz/model/binarypackagerelease.py b/lib/lp/soyuz/model/binarypackagerelease.py
index ac1f4f3..41ac6b5 100644
--- a/lib/lp/soyuz/model/binarypackagerelease.py
+++ b/lib/lp/soyuz/model/binarypackagerelease.py
@@ -129,11 +129,11 @@ class BinaryPackageRelease(SQLBase):
         name="binpackageformat", allow_none=False, enum=BinaryPackageFormat
     )
     # DB constraint: non-nullable for BinaryPackageFormat.{DEB,UDEB,DDEB}.
-    component = ForeignKey(
-        dbName="component", foreignKey="Component", notNull=False
-    )
+    component_id = Int(name="component", allow_none=True)
+    component = Reference(component_id, "Component.id")
     # DB constraint: non-nullable for BinaryPackageFormat.{DEB,UDEB,DDEB}.
-    section = ForeignKey(dbName="section", foreignKey="Section", notNull=False)
+    section_id = Int(name="section", allow_none=True)
+    section = Reference(section_id, "Section.id")
     # DB constraint: non-nullable for BinaryPackageFormat.{DEB,UDEB,DDEB}.
     priority = DBEnum(
         name="priority", allow_none=True, enum=PackagePublishingPriority
diff --git a/lib/lp/soyuz/model/component.py b/lib/lp/soyuz/model/component.py
index 3854e67..6a9f90d 100644
--- a/lib/lp/soyuz/model/component.py
+++ b/lib/lp/soyuz/model/component.py
@@ -3,11 +3,12 @@
 
 __all__ = ["Component", "ComponentSelection", "ComponentSet"]
 
+from storm.locals import Int, Reference, Unicode
 from zope.interface import implementer
 
 from lp.app.errors import NotFoundError
-from lp.services.database.sqlbase import SQLBase
-from lp.services.database.sqlobject import ForeignKey, StringCol
+from lp.services.database.interfaces import IStore
+from lp.services.database.stormbase import StormBase
 from lp.soyuz.interfaces.component import (
     IComponent,
     IComponentSelection,
@@ -16,29 +17,42 @@ from lp.soyuz.interfaces.component import (
 
 
 @implementer(IComponent)
-class Component(SQLBase):
+class Component(StormBase):
     """See IComponent."""
 
-    _defaultOrder = ["id"]
+    __storm_table__ = "Component"
+    __storm_order__ = ["id"]
 
-    name = StringCol(notNull=True, alternateID=True)
+    id = Int(primary=True)
+
+    name = Unicode(name="name", allow_none=False)
+
+    def __init__(self, name):
+        super().__init__()
+        self.name = name
 
     def __repr__(self):
         return "<%s '%s'>" % (self.__class__.__name__, self.name)
 
 
 @implementer(IComponentSelection)
-class ComponentSelection(SQLBase):
+class ComponentSelection(StormBase):
     """See IComponentSelection."""
 
-    _defaultOrder = ["id"]
+    __storm_table__ = "ComponentSelection"
+    __storm_order__ = ["id"]
+
+    id = Int(primary=True)
+
+    distroseries_id = Int(name="distroseries", allow_none=False)
+    distroseries = Reference(distroseries_id, "DistroSeries.id")
+    component_id = Int(name="component", allow_none=False)
+    component = Reference(component_id, "Component.id")
 
-    distroseries = ForeignKey(
-        dbName="distroseries", foreignKey="DistroSeries", notNull=True
-    )
-    component = ForeignKey(
-        dbName="component", foreignKey="Component", notNull=True
-    )
+    def __init__(self, distroseries, component):
+        super().__init__()
+        self.distroseries = distroseries
+        self.component = component
 
 
 @implementer(IComponentSet)
@@ -47,26 +61,28 @@ class ComponentSet:
 
     def __iter__(self):
         """See IComponentSet."""
-        return iter(Component.select())
+        return iter(IStore(Component).find(Component))
 
     def __getitem__(self, name):
         """See IComponentSet."""
-        component = Component.selectOneBy(name=name)
+        component = IStore(Component).find(Component, name=name).one()
         if component is not None:
             return component
         raise NotFoundError(name)
 
     def get(self, component_id):
         """See IComponentSet."""
-        return Component.get(component_id)
+        return IStore(Component).get(Component, component_id)
 
     def ensure(self, name):
         """See IComponentSet."""
-        component = Component.selectOneBy(name=name)
+        component = IStore(Component).find(Component, name=name).one()
         if component is not None:
             return component
         return self.new(name)
 
     def new(self, name):
         """See IComponentSet."""
-        return Component(name=name)
+        component = Component(name=name)
+        IStore(Component).add(component)
+        return component
diff --git a/lib/lp/soyuz/model/publishing.py b/lib/lp/soyuz/model/publishing.py
index 05a9653..2a7a3e1 100644
--- a/lib/lp/soyuz/model/publishing.py
+++ b/lib/lp/soyuz/model/publishing.py
@@ -239,9 +239,11 @@ class SourcePackagePublishingHistory(SQLBase, ArchivePublisherBase):
     )
     distroseries = ForeignKey(foreignKey="DistroSeries", dbName="distroseries")
     # DB constraint: non-nullable for SourcePackageType.DPKG.
-    component = ForeignKey(foreignKey="Component", dbName="component")
+    component_id = Int(name="component", allow_none=True)
+    component = Reference(component_id, "Component.id")
     # DB constraint: non-nullable for SourcePackageType.DPKG.
-    section = ForeignKey(foreignKey="Section", dbName="section")
+    section_id = Int(name="section", allow_none=True)
+    section = Reference(section_id, "Section.id")
     status = DBEnum(enum=PackagePublishingStatus)
     scheduleddeletiondate = UtcDateTimeCol(default=None)
     datepublished = UtcDateTimeCol(default=None)
@@ -747,11 +749,11 @@ class BinaryPackagePublishingHistory(SQLBase, ArchivePublisherBase):
         foreignKey="DistroArchSeries", dbName="distroarchseries"
     )
     # DB constraint: non-nullable for BinaryPackageFormat.{DEB,UDEB,DDEB}.
-    component = ForeignKey(
-        foreignKey="Component", dbName="component", notNull=False
-    )
+    component_id = Int(name="component", allow_none=True)
+    component = Reference(component_id, "Component.id")
     # DB constraint: non-nullable for BinaryPackageFormat.{DEB,UDEB,DDEB}.
-    section = ForeignKey(foreignKey="Section", dbName="section", notNull=False)
+    section_id = Int(name="section", allow_none=True)
+    section = Reference(section_id, "Section.id")
     # DB constraint: non-nullable for BinaryPackageFormat.{DEB,UDEB,DDEB}.
     priority = DBEnum(
         name="priority", enum=PackagePublishingPriority, allow_none=True
@@ -1962,7 +1964,7 @@ class PublishingSet:
         def eager_load(spphs):
             # Preload everything which will be used by archivepublisher's
             # build_source_stanza_fields.
-            bulk.load_related(Section, spphs, ["sectionID"])
+            bulk.load_related(Section, spphs, ["section_id"])
             sprs = bulk.load_related(
                 SourcePackageRelease, spphs, ["sourcepackagereleaseID"]
             )
@@ -2021,7 +2023,7 @@ class PublishingSet:
         def eager_load(bpphs):
             # Preload everything which will be used by archivepublisher's
             # build_binary_stanza_fields.
-            bulk.load_related(Section, bpphs, ["sectionID"])
+            bulk.load_related(Section, bpphs, ["section_id"])
             bprs = bulk.load_related(
                 BinaryPackageRelease, bpphs, ["binarypackagereleaseID"]
             )
@@ -2272,8 +2274,8 @@ class PublishingSet:
                 deb_bpph.archiveID == debug_bpph.archiveID,
                 deb_bpph.distroarchseriesID == debug_bpph.distroarchseriesID,
                 deb_bpph.pocket == debug_bpph.pocket,
-                deb_bpph.componentID == debug_bpph.componentID,
-                deb_bpph.sectionID == debug_bpph.sectionID,
+                deb_bpph.component_id == debug_bpph.component_id,
+                deb_bpph.section_id == debug_bpph.section_id,
                 deb_bpph.priority == debug_bpph.priority,
                 Not(
                     IsDistinctFrom(
diff --git a/lib/lp/soyuz/model/queue.py b/lib/lp/soyuz/model/queue.py
index 95f0e05..f99e2e9 100644
--- a/lib/lp/soyuz/model/queue.py
+++ b/lib/lp/soyuz/model/queue.py
@@ -1883,8 +1883,8 @@ def prefill_packageupload_caches(uploads, puses, pubs, pucs, logs):
     sprs = source_sprs + binary_sprs
 
     load_related(SourcePackageName, sprs, ["sourcepackagenameID"])
-    load_related(Section, sprs + bprs, ["sectionID"])
-    load_related(Component, sprs, ["componentID"])
+    load_related(Section, sprs + bprs, ["section_id"])
+    load_related(Component, sprs, ["component_id"])
     load_related(LibraryFileAlias, uploads, ["changes_file_id"])
     publications = load_referencing(
         SourcePackagePublishingHistory, sprs, ["sourcepackagereleaseID"]
diff --git a/lib/lp/soyuz/model/section.py b/lib/lp/soyuz/model/section.py
index 2ebc670..2567011 100644
--- a/lib/lp/soyuz/model/section.py
+++ b/lib/lp/soyuz/model/section.py
@@ -3,11 +3,12 @@
 
 __all__ = ["Section", "SectionSelection", "SectionSet"]
 
+from storm.locals import Int, Reference, Unicode
 from zope.interface import implementer
 
 from lp.app.errors import NotFoundError
-from lp.services.database.sqlbase import SQLBase
-from lp.services.database.sqlobject import ForeignKey, StringCol
+from lp.services.database.interfaces import IStore
+from lp.services.database.stormbase import StormBase
 from lp.soyuz.interfaces.section import (
     ISection,
     ISectionSelection,
@@ -16,24 +17,39 @@ from lp.soyuz.interfaces.section import (
 
 
 @implementer(ISection)
-class Section(SQLBase):
+class Section(StormBase):
     """See ISection"""
 
-    _defaultOrder = ["id"]
+    __storm_table__ = "Section"
+    __storm_order__ = ["id"]
 
-    name = StringCol(notNull=True, alternateID=True)
+    id = Int(primary=True)
+
+    name = Unicode(name="name", allow_none=False)
+
+    def __init__(self, name):
+        super().__init__()
+        self.name = name
 
 
 @implementer(ISectionSelection)
-class SectionSelection(SQLBase):
+class SectionSelection(StormBase):
     """See ISectionSelection."""
 
-    _defaultOrder = ["id"]
+    __storm_table__ = "SectionSelection"
+    __storm_order__ = ["id"]
+
+    id = Int(primary=True)
+
+    distroseries_id = Int(name="distroseries", allow_none=False)
+    distroseries = Reference(distroseries_id, "DistroSeries.id")
+    section_id = Int(name="section", allow_none=False)
+    section = Reference(section_id, "Section.id")
 
-    distroseries = ForeignKey(
-        dbName="distroseries", foreignKey="DistroSeries", notNull=True
-    )
-    section = ForeignKey(dbName="section", foreignKey="Section", notNull=True)
+    def __init__(self, distroseries, section):
+        super().__init__()
+        self.distroseries = distroseries
+        self.section = section
 
 
 @implementer(ISectionSet)
@@ -42,26 +58,28 @@ class SectionSet:
 
     def __iter__(self):
         """See ISectionSet."""
-        return iter(Section.select())
+        return iter(IStore(Section).find(Section))
 
     def __getitem__(self, name):
         """See ISectionSet."""
-        section = Section.selectOneBy(name=name)
+        section = IStore(Section).find(Section, name=name).one()
         if section is not None:
             return section
         raise NotFoundError(name)
 
     def get(self, section_id):
         """See ISectionSet."""
-        return Section.get(section_id)
+        return IStore(Section).get(Section, section_id)
 
     def ensure(self, name):
         """See ISectionSet."""
-        section = Section.selectOneBy(name=name)
+        section = IStore(Section).find(Section, name=name).one()
         if section is not None:
             return section
         return self.new(name)
 
     def new(self, name):
         """See ISectionSet."""
-        return Section(name=name)
+        section = Section(name=name)
+        IStore(Section).add(section)
+        return section
diff --git a/lib/lp/soyuz/model/sourcepackagerelease.py b/lib/lp/soyuz/model/sourcepackagerelease.py
index 68abb4b..0dcd8da 100644
--- a/lib/lp/soyuz/model/sourcepackagerelease.py
+++ b/lib/lp/soyuz/model/sourcepackagerelease.py
@@ -63,7 +63,8 @@ class SourcePackageRelease(SQLBase):
     _table = "SourcePackageRelease"
 
     # DB constraint: non-nullable for SourcePackageType.DPKG.
-    section = ForeignKey(foreignKey="Section", dbName="section")
+    section_id = Int(name="section", allow_none=True)
+    section = Reference(section_id, "Section.id")
     creator = ForeignKey(
         dbName="creator",
         foreignKey="Person",
@@ -71,7 +72,8 @@ class SourcePackageRelease(SQLBase):
         notNull=True,
     )
     # DB constraint: non-nullable for SourcePackageType.DPKG.
-    component = ForeignKey(foreignKey="Component", dbName="component")
+    component_id = Int(name="component", allow_none=True)
+    component = Reference(component_id, "Component.id")
     sourcepackagename = ForeignKey(
         foreignKey="SourcePackageName",
         dbName="sourcepackagename",
diff --git a/lib/lp/soyuz/scripts/gina/handlers.py b/lib/lp/soyuz/scripts/gina/handlers.py
index 23ef512..aee887f 100644
--- a/lib/lp/soyuz/scripts/gina/handlers.py
+++ b/lib/lp/soyuz/scripts/gina/handlers.py
@@ -27,6 +27,7 @@ from storm.exceptions import NotOneError
 from storm.expr import Cast, Desc
 from zope.component import getUtility
 
+from lp.app.errors import NotFoundError
 from lp.archivepublisher.diskpool import poolify
 from lp.archiveuploader.changesfile import ChangesFile
 from lp.archiveuploader.tagfiles import parse_tagfile
@@ -54,21 +55,21 @@ from lp.soyuz.interfaces.binarysourcereference import (
     IBinarySourceReferenceSet,
     UnparsableBuiltUsing,
 )
+from lp.soyuz.interfaces.component import IComponentSet
 from lp.soyuz.interfaces.publishing import (
     IPublishingSet,
     active_publishing_status,
 )
+from lp.soyuz.interfaces.section import ISectionSet
 from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild
 from lp.soyuz.model.binarypackagename import BinaryPackageName
 from lp.soyuz.model.binarypackagerelease import BinaryPackageRelease
-from lp.soyuz.model.component import Component
 from lp.soyuz.model.distroarchseries import DistroArchSeries
 from lp.soyuz.model.files import BinaryPackageFile
 from lp.soyuz.model.publishing import (
     BinaryPackagePublishingHistory,
     SourcePackagePublishingHistory,
 )
-from lp.soyuz.model.section import Section
 from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease
 from lp.soyuz.scripts.gina.library import getLibraryAlias
 from lp.soyuz.scripts.gina.packages import (
@@ -443,9 +444,9 @@ class DistroHandler:
         if component in self.compcache:
             return self.compcache[component]
 
-        ret = Component.selectOneBy(name=component)
-
-        if not ret:
+        try:
+            ret = getUtility(IComponentSet)[component]
+        except NotFoundError:
             raise ValueError("Component %s not found" % component)
 
         self.compcache[component] = ret
@@ -458,10 +459,7 @@ class DistroHandler:
         if section in self.sectcache:
             return self.sectcache[section]
 
-        ret = Section.selectOneBy(name=section)
-        if not ret:
-            ret = Section(name=section)
-
+        ret = getUtility(ISectionSet).ensure(section)
         self.sectcache[section] = ret
         return ret
 
diff --git a/lib/lp/soyuz/vocabularies.py b/lib/lp/soyuz/vocabularies.py
index 18cdda5..2abe4f5 100644
--- a/lib/lp/soyuz/vocabularies.py
+++ b/lib/lp/soyuz/vocabularies.py
@@ -25,6 +25,7 @@ from lp.services.webapp.interfaces import ILaunchBag
 from lp.services.webapp.vocabulary import (
     IHugeVocabulary,
     SQLObjectVocabularyBase,
+    StormVocabularyBase,
 )
 from lp.soyuz.enums import ArchivePurpose
 from lp.soyuz.interfaces.archive import IArchiveSet
@@ -34,10 +35,10 @@ from lp.soyuz.model.distroarchseries import DistroArchSeries
 from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease
 
 
-class ComponentVocabulary(SQLObjectVocabularyBase):
+class ComponentVocabulary(StormVocabularyBase):
 
     _table = Component
-    _orderBy = "name"
+    _order_by = "name"
 
     def toTerm(self, obj):
         return SimpleTerm(obj, obj.id, obj.name)