← Back to team overview

launchpad-reviewers team mailing list archive

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

 

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

Commit message:
Convert Distribution to Storm

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/451160
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:stormify-distribution into launchpad:master.
diff --git a/lib/lp/answers/vocabulary.py b/lib/lp/answers/vocabulary.py
index e92382b..12f912c 100644
--- a/lib/lp/answers/vocabulary.py
+++ b/lib/lp/answers/vocabulary.py
@@ -9,7 +9,7 @@ __all__ = [
     "UsesAnswersProductVocabulary",
 ]
 
-from storm.expr import And
+from storm.expr import And, Is, Or
 from zope.interface import implementer
 from zope.schema.vocabulary import SimpleTerm
 
@@ -18,7 +18,6 @@ from lp.answers.interfaces.faqtarget import IFAQTarget
 from lp.registry.interfaces.distribution import IDistribution
 from lp.registry.model.product import Product
 from lp.registry.vocabularies import DistributionVocabulary, ProductVocabulary
-from lp.services.database.sqlobject import OR
 from lp.services.webapp.vocabulary import (
     CountableIterator,
     FilteredVocabularyBase,
@@ -106,11 +105,14 @@ class UsesAnswersDistributionVocabulary(DistributionVocabulary):
         self.distribution = IDistribution(self.context, None)
 
     @property
-    def _filter(self):
+    def _clauses(self):
         if self.distribution is None:
             distro_id = 0
         else:
             distro_id = self.distribution.id
-        return OR(
-            self._table.q.official_answers == True, self._table.id == distro_id
-        )
+        return [
+            Or(
+                Is(self._table.official_answers, True),
+                self._table.id == distro_id,
+            )
+        ]
diff --git a/lib/lp/archivepublisher/scripts/sync_signingkeys.py b/lib/lp/archivepublisher/scripts/sync_signingkeys.py
index 7bb200a..3b0046f 100644
--- a/lib/lp/archivepublisher/scripts/sync_signingkeys.py
+++ b/lib/lp/archivepublisher/scripts/sync_signingkeys.py
@@ -100,7 +100,7 @@ class SyncSigningKeysScript(LaunchpadScript):
         else:
             archives = IStore(Archive).find(
                 Archive,
-                PublisherConfig.distribution_id == Archive.distributionID,
+                PublisherConfig.distribution_id == Archive.distribution_id,
             )
             archives = archives.order_by(Archive.id)
         start = self.options.offset if self.options.offset else 0
diff --git a/lib/lp/archivepublisher/tests/test_sync_signingkeys.py b/lib/lp/archivepublisher/tests/test_sync_signingkeys.py
index bf5a5a2..3c73754 100644
--- a/lib/lp/archivepublisher/tests/test_sync_signingkeys.py
+++ b/lib/lp/archivepublisher/tests/test_sync_signingkeys.py
@@ -86,7 +86,7 @@ class TestSyncSigningKeysScript(TestCaseWithFactory):
     def makeArchives(self):
         for i in range(10):
             self.factory.makeArchive()
-        conditions = PublisherConfig.distribution_id == Archive.distributionID
+        conditions = PublisherConfig.distribution_id == Archive.distribution_id
         return IStore(Archive).find(Archive, conditions).order_by(Archive.id)
 
     def makeArchiveSigningDir(self, ppa, series=None):
diff --git a/lib/lp/bugs/doc/bugnotificationrecipients.rst b/lib/lp/bugs/doc/bugnotificationrecipients.rst
index ecbe624..d9415f5 100644
--- a/lib/lp/bugs/doc/bugnotificationrecipients.rst
+++ b/lib/lp/bugs/doc/bugnotificationrecipients.rst
@@ -69,7 +69,7 @@ Let's up some data for our test:
     >>> from lp.bugs.mail.bugnotificationrecipients import (
     ...     BugNotificationRecipients,
     ... )
-    >>> debian = Distribution.selectOneBy(name="debian")
+    >>> debian = IStore(Distribution).find(Distribution, name="debian").one()
     >>> pmount = debian.getSourcePackage("pmount")
     >>> alsa_utils = IStore(Product).find(Product, name="alsa-utils").one()
     >>> gnomebaker = IStore(Product).find(Product, name="gnomebaker").one()
diff --git a/lib/lp/bugs/doc/cve.rst b/lib/lp/bugs/doc/cve.rst
index 86b2a3f..986bb2c 100644
--- a/lib/lp/bugs/doc/cve.rst
+++ b/lib/lp/bugs/doc/cve.rst
@@ -171,7 +171,7 @@ ICveSet.getBugCvesForBugTasks:
     >>> from lp.bugs.interfaces.bugtasksearch import BugTaskSearchParams
     >>> from lp.registry.model.distribution import Distribution
     >>> params = BugTaskSearchParams(None)
-    >>> ubuntu = Distribution.selectOneBy(name="ubuntu")
+    >>> ubuntu = IStore(Distribution).find(Distribution, name="ubuntu").one()
     >>> ubuntu_tasks = ubuntu.searchTasks(params)
     >>> bugcves = cveset.getBugCvesForBugTasks(ubuntu_tasks)
     >>> for bug, cve in bugcves:
diff --git a/lib/lp/bugs/vocabularies.py b/lib/lp/bugs/vocabularies.py
index fd7fd08..aad87b8 100644
--- a/lib/lp/bugs/vocabularies.py
+++ b/lib/lp/bugs/vocabularies.py
@@ -18,7 +18,7 @@ __all__ = [
     "WebBugTrackerVocabulary",
 ]
 
-from storm.expr import And, Or
+from storm.expr import And, Is, Or
 from zope.component import getUtility
 from zope.interface import implementer
 from zope.schema.interfaces import IVocabularyTokenized
@@ -48,7 +48,6 @@ from lp.registry.model.milestone import milestone_sort_key
 from lp.registry.model.productseries import ProductSeries
 from lp.registry.vocabularies import DistributionVocabulary
 from lp.services.database.interfaces import IStore
-from lp.services.database.sqlobject import OR
 from lp.services.helpers import shortlist
 from lp.services.webapp.escaping import html_escape, structured
 from lp.services.webapp.interfaces import ILaunchBag
@@ -74,14 +73,17 @@ class UsesBugsDistributionVocabulary(DistributionVocabulary):
         self.distribution = IDistribution(self.context, None)
 
     @property
-    def _filter(self):
+    def _clauses(self):
         if self.distribution is None:
             distro_id = 0
         else:
             distro_id = self.distribution.id
-        return OR(
-            self._table.q.official_malone == True, self._table.id == distro_id
-        )
+        return [
+            Or(
+                Is(self._table.official_malone, True),
+                self._table.id == distro_id,
+            )
+        ]
 
 
 class BugVocabulary(StormVocabularyBase):
@@ -208,21 +210,27 @@ class BugWatchVocabulary(StormVocabularyBase):
 class DistributionUsingMaloneVocabulary:
     """All the distributions that uses Malone officially."""
 
-    _orderBy = "display_name"
+    _order_by = Distribution.display_name
 
     def __init__(self, context=None):
         self.context = context
 
     def __iter__(self):
         """Return an iterator which provides the terms from the vocabulary."""
-        distributions_using_malone = Distribution.selectBy(
-            official_malone=True, orderBy=self._orderBy
+        distributions_using_malone = (
+            IStore(Distribution)
+            .find(Distribution, official_malone=True)
+            .order_by(self._order_by)
         )
         for distribution in distributions_using_malone:
             yield self.getTerm(distribution)
 
     def __len__(self):
-        return Distribution.selectBy(official_malone=True).count()
+        return (
+            IStore(Distribution)
+            .find(Distribution, official_malone=True)
+            .count()
+        )
 
     def __contains__(self, obj):
         return (
@@ -236,7 +244,11 @@ class DistributionUsingMaloneVocabulary:
         return SimpleTerm(obj, obj.name, obj.displayname)
 
     def getTermByToken(self, token):
-        found_dist = Distribution.selectOneBy(name=token, official_malone=True)
+        found_dist = (
+            IStore(Distribution)
+            .find(Distribution, name=token, official_malone=True)
+            .one()
+        )
         if found_dist is None:
             raise LookupError(token)
         return self.getTerm(found_dist)
diff --git a/lib/lp/registry/model/distribution.py b/lib/lp/registry/model/distribution.py
index bd3e4fe..8f4bb03 100644
--- a/lib/lp/registry/model/distribution.py
+++ b/lib/lp/registry/model/distribution.py
@@ -30,7 +30,7 @@ from storm.expr import (
     Table,
 )
 from storm.info import ClassAlias
-from storm.locals import Int, List, Reference
+from storm.locals import Bool, DateTime, Int, List, Reference, Unicode
 from storm.store import Store
 from zope.component import getUtility
 from zope.interface import implementer
@@ -155,12 +155,11 @@ from lp.registry.model.sourcepackagename import SourcePackageName
 from lp.registry.model.teammembership import TeamParticipation
 from lp.services.database.bulk import load_referencing, load_related
 from lp.services.database.constants import UTC_NOW
-from lp.services.database.datetimecol import UtcDateTimeCol
 from lp.services.database.decoratedresultset import DecoratedResultSet
 from lp.services.database.enumcol import DBEnum
 from lp.services.database.interfaces import IStore
-from lp.services.database.sqlbase import SQLBase, sqlvalues
-from lp.services.database.sqlobject import BoolCol, ForeignKey, StringCol
+from lp.services.database.sqlbase import sqlvalues
+from lp.services.database.stormbase import StormBase
 from lp.services.database.stormexpr import (
     ArrayAgg,
     ArrayIntersects,
@@ -223,7 +222,7 @@ specification_policy_default = {
 
 @implementer(IBugSummaryDimension, IDistribution)
 class Distribution(
-    SQLBase,
+    StormBase,
     BugTargetBase,
     MakesAnnouncements,
     HasSpecificationsMixin,
@@ -243,45 +242,42 @@ class Distribution(
 ):
     """A distribution of an operating system, e.g. Debian GNU/Linux."""
 
-    _table = "Distribution"
-    _defaultOrder = "name"
+    __storm_table__ = "Distribution"
+    __storm_order__ = "name"
 
-    name = StringCol(notNull=True, alternateID=True, unique=True)
-    display_name = StringCol(dbName="displayname", notNull=True)
-    _title = StringCol(dbName="title", notNull=True)
-    summary = StringCol(notNull=True)
-    description = StringCol(notNull=True)
-    homepage_content = StringCol(default=None)
+    id = Int(primary=True)
+    name = Unicode(allow_none=False)
+    display_name = Unicode(name="displayname", allow_none=False)
+    _title = Unicode(name="title", allow_none=False)
+    summary = Unicode(allow_none=False)
+    description = Unicode(allow_none=False)
+    homepage_content = Unicode(default=None)
     icon_id = Int(name="icon", default=None)
     icon = Reference(icon_id, "LibraryFileAlias.id")
-    logo = ForeignKey(
-        dbName="logo", foreignKey="LibraryFileAlias", default=None
-    )
-    mugshot = ForeignKey(
-        dbName="mugshot", foreignKey="LibraryFileAlias", default=None
-    )
-    domainname = StringCol(notNull=True)
+    logo_id = Int(name="logo", default=None)
+    logo = Reference(logo_id, "LibraryFileAlias.id")
+    mugshot_id = Int(name="mugshot", default=None)
+    mugshot = Reference(mugshot_id, "LibraryFileAlias.id")
+    domainname = Unicode(allow_none=False)
     owner_id = Int(
         name="owner",
         validator=validate_person_or_closed_team,
         allow_none=False,
     )
     owner = Reference(owner_id, "Person.id")
-    registrant = ForeignKey(
-        dbName="registrant",
-        foreignKey="Person",
-        storm_validator=validate_public_person,
-        notNull=True,
+    registrant_id = Int(
+        name="registrant", validator=validate_public_person, allow_none=False
     )
-    bug_supervisor = ForeignKey(
-        dbName="bug_supervisor",
-        foreignKey="Person",
-        storm_validator=validate_person,
-        notNull=False,
+    registrant = Reference(registrant_id, "Person.id")
+    bug_supervisor_id = Int(
+        name="bug_supervisor",
+        validator=validate_person,
+        allow_none=True,
         default=None,
     )
-    bug_reporting_guidelines = StringCol(default=None)
-    bug_reported_acknowledgement = StringCol(default=None)
+    bug_supervisor = Reference(bug_supervisor_id, "Person.id")
+    bug_reporting_guidelines = Unicode(default=None)
+    bug_reported_acknowledgement = Unicode(default=None)
     driver_id = Int(
         name="driver",
         validator=validate_public_person,
@@ -289,25 +285,21 @@ class Distribution(
         default=None,
     )
     driver = Reference(driver_id, "Person.id")
-    members = ForeignKey(
-        dbName="members",
-        foreignKey="Person",
-        storm_validator=validate_public_person,
-        notNull=True,
+    members_id = Int(
+        name="members", validator=validate_public_person, allow_none=False
     )
-    mirror_admin = ForeignKey(
-        dbName="mirror_admin",
-        foreignKey="Person",
-        storm_validator=validate_public_person,
-        notNull=True,
+    members = Reference(members_id, "Person.id")
+    mirror_admin_id = Int(
+        name="mirror_admin", validator=validate_public_person, allow_none=False
     )
-    oci_project_admin = ForeignKey(
-        dbName="oci_project_admin",
-        foreignKey="Person",
-        storm_validator=validate_public_person,
-        notNull=False,
+    mirror_admin = Reference(mirror_admin_id, "Person.id")
+    oci_project_admin_id = Int(
+        name="oci_project_admin",
+        validator=validate_public_person,
+        allow_none=True,
         default=None,
     )
+    oci_project_admin = Reference(oci_project_admin_id, "Person.id")
     translationgroup_id = Int(
         name="translationgroup", allow_none=True, default=None
     )
@@ -321,19 +313,19 @@ class Distribution(
     # Distributions can't be deactivated.  This is just here in order to
     # implement the `IPillar` interface.
     active = True
-    official_packages = BoolCol(notNull=True, default=False)
-    supports_ppas = BoolCol(notNull=True, default=False)
-    supports_mirrors = BoolCol(notNull=True, default=False)
-    package_derivatives_email = StringCol(notNull=False, default=None)
-    redirect_release_uploads = BoolCol(notNull=True, default=False)
-    development_series_alias = StringCol(notNull=False, default=None)
+    official_packages = Bool(allow_none=False, default=False)
+    supports_ppas = Bool(allow_none=False, default=False)
+    supports_mirrors = Bool(allow_none=False, default=False)
+    package_derivatives_email = Unicode(allow_none=True, default=None)
+    redirect_release_uploads = Bool(allow_none=False, default=False)
+    development_series_alias = Unicode(allow_none=True, default=None)
     vcs = DBEnum(enum=VCSType, allow_none=True)
     default_traversal_policy = DBEnum(
         enum=DistributionDefaultTraversalPolicy,
         allow_none=True,
         default=DistributionDefaultTraversalPolicy.SERIES,
     )
-    redirect_default_traversal = BoolCol(notNull=False, default=False)
+    redirect_default_traversal = Bool(allow_none=True, default=False)
     oci_registry_credentials_id = Int(name="oci_credentials", allow_none=True)
     oci_registry_credentials = Reference(
         oci_registry_credentials_id, "OCIRegistryCredentials.id"
@@ -630,14 +622,14 @@ class Distribution(
 
         return distro_uploaders
 
-    official_answers = BoolCol(
-        dbName="official_answers", notNull=True, default=False
+    official_answers = Bool(
+        name="official_answers", allow_none=False, default=False
     )
-    official_blueprints = BoolCol(
-        dbName="official_blueprints", notNull=True, default=False
+    official_blueprints = Bool(
+        name="official_blueprints", allow_none=False, default=False
     )
-    official_malone = BoolCol(
-        dbName="official_malone", notNull=True, default=False
+    official_malone = Bool(
+        name="official_malone", allow_none=False, default=False
     )
 
     @property
@@ -751,28 +743,30 @@ class Distribution(
         """Does this distribution actually use Launchpad?"""
         return self.official_anything
 
-    enable_bug_expiration = BoolCol(
-        dbName="enable_bug_expiration", notNull=True, default=False
+    enable_bug_expiration = Bool(
+        name="enable_bug_expiration", allow_none=False, default=False
     )
     translation_focus_id = Int(
         name="translation_focus", allow_none=True, default=None
     )
     translation_focus = Reference(translation_focus_id, "DistroSeries.id")
-    date_created = UtcDateTimeCol(notNull=False, default=UTC_NOW)
-    language_pack_admin = ForeignKey(
-        dbName="language_pack_admin",
-        foreignKey="Person",
-        storm_validator=validate_public_person,
-        notNull=False,
+    date_created = DateTime(
+        allow_none=True, default=UTC_NOW, tzinfo=timezone.utc
+    )
+    language_pack_admin_id = Int(
+        name="language_pack_admin",
+        validator=validate_public_person,
+        allow_none=True,
         default=None,
     )
-    security_admin = ForeignKey(
-        dbName="security_admin",
-        foreignKey="Person",
-        storm_validator=validate_public_person,
-        notNull=False,
+    language_pack_admin = Reference(language_pack_admin_id, "Person.id")
+    security_admin_id = Int(
+        name="security_admin",
+        validator=validate_public_person,
+        allow_none=True,
         default=None,
     )
+    security_admin = Reference(security_admin_id, "Person.id")
     code_admin_id = Int(
         name="code_admin",
         validator=validate_public_person,
@@ -1889,7 +1883,7 @@ class Distribution(
         PackageUpload.archive = Archive.id AND
         PackageUpload.status = %s
         """ % sqlvalues(
-            ArchivePurpose.PPA, self, PackageUploadStatus.ACCEPTED
+            ArchivePurpose.PPA, self.id, PackageUploadStatus.ACCEPTED
         )
 
         return Archive.select(
@@ -2130,10 +2124,10 @@ class Distribution(
         distribution to have a task, we give no more weighting to a
         distroseries task than any other.
         """
-        distributionID = self.id
+        distribution_id = self.id
 
         def weight_function(bugtask):
-            if bugtask.distribution_id == distributionID:
+            if bugtask.distribution_id == distribution_id:
                 return OrderedBugTask(1, bugtask.id, bugtask)
             return OrderedBugTask(2, bugtask.id, bugtask)
 
@@ -2323,15 +2317,15 @@ class DistributionSet:
 
     def get(self, distributionid):
         """See `IDistributionSet`."""
-        return Distribution.get(distributionid)
+        return IStore(Distribution).get(Distribution, distributionid)
 
     def count(self):
         """See `IDistributionSet`."""
-        return Distribution.select().count()
+        return IStore(Distribution).find(Distribution).count()
 
     def getDistros(self):
         """See `IDistributionSet`."""
-        distros = Distribution.select()
+        distros = IStore(Distribution).find(Distribution)
         return sorted(
             shortlist(distros, 100), key=lambda distro: distro._sort_key
         )
diff --git a/lib/lp/registry/model/distroseriesdifference.py b/lib/lp/registry/model/distroseriesdifference.py
index 28859ba..e82e975 100644
--- a/lib/lp/registry/model/distroseriesdifference.py
+++ b/lib/lp/registry/model/distroseriesdifference.py
@@ -98,7 +98,7 @@ def most_recent_publications(dsds, in_parent, statuses, match_version=False):
         tables=[Archive, DistroSeries],
         where=And(
             DistroSeries.id == series_col,
-            Archive.distributionID == DistroSeries.distribution_id,
+            Archive.distribution_id == DistroSeries.distribution_id,
             Archive.purpose == ArchivePurpose.PRIMARY,
         ),
     )
diff --git a/lib/lp/registry/model/pillar.py b/lib/lp/registry/model/pillar.py
index de817fb..ad9af3a 100644
--- a/lib/lp/registry/model/pillar.py
+++ b/lib/lp/registry/model/pillar.py
@@ -312,7 +312,7 @@ class PillarNameSet:
                 load_related(ProjectGroup, pillar_names, ["projectgroup_id"])
             )
             pillars.extend(
-                load_related(Distribution, pillar_names, ["distributionID"])
+                load_related(Distribution, pillar_names, ["distribution_id"])
             )
             load_related(LibraryFileAlias, pillars, ["icon_id"])
 
@@ -337,7 +337,8 @@ class PillarName(SQLBase):
     product = Reference(product_id, "Product.id")
     projectgroup_id = Int(name="project", allow_none=True)
     projectgroup = Reference(projectgroup_id, "ProjectGroup.id")
-    distribution = ForeignKey(foreignKey="Distribution", dbName="distribution")
+    distribution_id = Int(name="distribution", allow_none=True)
+    distribution = Reference(distribution_id, "Distribution.id")
     active = BoolCol(dbName="active", notNull=True, default=True)
     alias_for = ForeignKey(
         foreignKey="PillarName", dbName="alias_for", default=None
diff --git a/lib/lp/registry/stories/milestone/xx-create-milestone-on-distribution.rst b/lib/lp/registry/stories/milestone/xx-create-milestone-on-distribution.rst
index 00d9abe..069de27 100644
--- a/lib/lp/registry/stories/milestone/xx-create-milestone-on-distribution.rst
+++ b/lib/lp/registry/stories/milestone/xx-create-milestone-on-distribution.rst
@@ -42,7 +42,8 @@ Try to target a distribution bug to this milestone.  The form uses the
 database ID for the milestone, so we find the ID:
 
     >>> from lp.registry.model.distribution import Distribution
-    >>> ubuntu = Distribution.byName("ubuntu")
+    >>> from lp.services.database.interfaces import IStore
+    >>> ubuntu = IStore(Distribution).find(Distribution, name="ubuntu").one()
     >>> for milestone in ubuntu.milestones:
     ...     if milestone.name == "sounder01":
     ...         break
diff --git a/lib/lp/registry/vocabularies.py b/lib/lp/registry/vocabularies.py
index d87766e..3ef19fe 100644
--- a/lib/lp/registry/vocabularies.py
+++ b/lib/lp/registry/vocabularies.py
@@ -174,7 +174,6 @@ from lp.services.webapp.vocabulary import (
     CountableIterator,
     FilteredVocabularyBase,
     IHugeVocabulary,
-    NamedSQLObjectVocabulary,
     NamedStormHugeVocabulary,
     NamedStormVocabulary,
     SQLObjectVocabularyBase,
@@ -1592,11 +1591,11 @@ class CommercialProjectsVocabulary(NamedStormVocabulary):
         return self.context.inTeam(project.owner)
 
 
-class DistributionVocabulary(NamedSQLObjectVocabulary):
+class DistributionVocabulary(NamedStormVocabulary):
     """All `IDistribution` objects vocabulary."""
 
     _table = Distribution
-    _orderBy = "name"
+    _order_by = "name"
 
     def getTermByToken(self, token):
         """See `IVocabularyTokenized`."""
@@ -1612,11 +1611,10 @@ class DistributionVocabulary(NamedSQLObjectVocabulary):
             return self.emptySelectResults()
 
         rows = IStore(self._table).find(
-            self._table,
-            self._table.name.contains_string(six.ensure_text(query).lower()),
+            self._table, self._table.name.contains_string(query.lower())
         )
-        if self._orderBy:
-            rows = rows.order_by(self._orderBy)
+        if self._order_by:
+            rows = rows.order_by(self._order_by)
         return rows
 
 
diff --git a/lib/lp/scripts/garbo.py b/lib/lp/scripts/garbo.py
index 1461757..eab11db 100644
--- a/lib/lp/scripts/garbo.py
+++ b/lib/lp/scripts/garbo.py
@@ -505,7 +505,7 @@ class PopulateDistributionSourcePackageCache(TunableLoop):
             (
                 SourcePackagePublishingHistory.id,
                 Archive.id,
-                Archive.distributionID,
+                Archive.distribution_id,
                 SourcePackageName.id,
                 SourcePackageName.name,
             ),
diff --git a/lib/lp/scripts/harness.py b/lib/lp/scripts/harness.py
index b3b23aa..1949e57 100644
--- a/lib/lp/scripts/harness.py
+++ b/lib/lp/scripts/harness.py
@@ -72,7 +72,7 @@ def _get_locals():
     if dbuser == "launchpad":
         # Create a few variables "in case they come in handy."
         # Do we really use these?  Are they worth carrying around?
-        d = Distribution.get(1)
+        d = store.get(Distribution, 1)
         p = Person.get(1)
         ds = store.get(DistroSeries, 1)
         prod = store.get(Product, 1)
diff --git a/lib/lp/soyuz/doc/package-meta-classes.rst b/lib/lp/soyuz/doc/package-meta-classes.rst
index 3e39f54..5b4c498 100644
--- a/lib/lp/soyuz/doc/package-meta-classes.rst
+++ b/lib/lp/soyuz/doc/package-meta-classes.rst
@@ -24,7 +24,7 @@ DistributionSourcePackage class is tested in:
 
 Combining Distribution and SourcePackageRelease:
 
-    >>> distribution = Distribution.get(1)
+    >>> distribution = IStore(Distribution).get(Distribution, 1)
     >>> print(distribution.name)
     ubuntu
 
diff --git a/lib/lp/soyuz/doc/soyuz-set-of-uploads.rst b/lib/lp/soyuz/doc/soyuz-set-of-uploads.rst
index 2cda351..bb8e464 100644
--- a/lib/lp/soyuz/doc/soyuz-set-of-uploads.rst
+++ b/lib/lp/soyuz/doc/soyuz-set-of-uploads.rst
@@ -75,15 +75,18 @@ Having set up that infrastructure we need to prepare a breezy distroseries
 for the ubuntutest distribution.
 
     >>> from lp.registry.model.distribution import Distribution
+    >>> from lp.services.database.interfaces import IStore
     >>> from lp.soyuz.enums import PackageUploadStatus
     >>> from lp.soyuz.scripts.initialize_distroseries import (
     ...     InitializeDistroSeries,
     ... )
     >>> from lp.services.librarian.model import LibraryFileAlias
     >>> from lp.testing.factory import LaunchpadObjectFactory
-    >>> ubuntu = Distribution.byName("ubuntu")
+    >>> ubuntu = IStore(Distribution).find(Distribution, name="ubuntu").one()
     >>> breezy_autotest = ubuntu["breezy-autotest"]
-    >>> ubuntutest = Distribution.byName("ubuntutest")
+    >>> ubuntutest = (
+    ...     IStore(Distribution).find(Distribution, name="ubuntutest").one()
+    ... )
     >>> breezy = ubuntutest.newSeries(
     ...     "breezy",
     ...     "Breezy Badger",
@@ -215,7 +218,6 @@ Finally, as a very simplistic publishing process, we may need to punt any
 given upload into the published state, so here's a very simplistic publisher
 
     >>> from lp.registry.model.distroseries import DistroSeries
-    >>> from lp.services.database.interfaces import IStore
     >>> from lp.soyuz.model.distroarchseries import DistroArchSeries
     >>> from lp.soyuz.model.publishing import (
     ...     SourcePackagePublishingHistory as SPPH,
diff --git a/lib/lp/soyuz/model/archive.py b/lib/lp/soyuz/model/archive.py
index 9cae655..bae615f 100644
--- a/lib/lp/soyuz/model/archive.py
+++ b/lib/lp/soyuz/model/archive.py
@@ -285,9 +285,8 @@ class Archive(SQLBase):
 
     description = StringCol(dbName="description", notNull=False, default=None)
 
-    distribution = ForeignKey(
-        foreignKey="Distribution", dbName="distribution", notNull=False
-    )
+    distribution_id = Int(name="distribution", allow_none=True)
+    distribution = Reference(distribution_id, "Distribution.id")
 
     purpose = DBEnum(name="purpose", allow_none=False, enum=ArchivePurpose)
 
@@ -3591,7 +3590,7 @@ class ArchiveSet:
         store = Store.of(user)
         result = store.find(
             Distribution,
-            Distribution.id == Archive.distributionID,
+            Distribution.id == Archive.distribution_id,
             self._getPPAsForUserClause(user),
         )
         return result.config(distinct=True)
@@ -3657,7 +3656,7 @@ class ArchiveSet:
              ORDER BY C DESC, a.id
              LIMIT 5
         """ % sqlvalues(
-            distribution, ArchivePurpose.PPA
+            distribution.id, ArchivePurpose.PPA
         )
 
         cur.execute(query)
diff --git a/lib/lp/soyuz/model/packagecopyjob.py b/lib/lp/soyuz/model/packagecopyjob.py
index d441a99..16dd6f2 100644
--- a/lib/lp/soyuz/model/packagecopyjob.py
+++ b/lib/lp/soyuz/model/packagecopyjob.py
@@ -874,7 +874,7 @@ class PlainPackageCopyJob(PackageCopyJobDerived):
         # coming from, and the version number in the DSD may have
         # changed.  We can however filter out DSDs that are from
         # different distributions, based on the job's target archive.
-        source_distro_id = self.source_archive.distributionID
+        source_distro_id = self.source_archive.distribution_id
         return [
             dsd
             for dsd in candidates
diff --git a/lib/lp/soyuz/model/packagediff.py b/lib/lp/soyuz/model/packagediff.py
index 47ed2b2..e21de8b 100644
--- a/lib/lp/soyuz/model/packagediff.py
+++ b/lib/lp/soyuz/model/packagediff.py
@@ -354,7 +354,7 @@ class PackageDiffSet:
                 ),
             )
             archives = load(Archive, (spr.upload_archive_id for spr in sprs))
-            load(Distribution, (a.distributionID for a in archives))
+            load(Distribution, (a.distribution_id for a in archives))
 
         if preload_for_display:
             return DecoratedResultSet(result, pre_iter_hook=preload_hook)
diff --git a/lib/lp/soyuz/model/queue.py b/lib/lp/soyuz/model/queue.py
index 89fe2f9..639640a 100644
--- a/lib/lp/soyuz/model/queue.py
+++ b/lib/lp/soyuz/model/queue.py
@@ -451,7 +451,7 @@ class PackageUpload(StormBase):
                 AND bpf.libraryfile = lfa.id
                 AND lfa.filename IN (%%s)
         """ % sqlvalues(
-            self.archive, self.distroseries.distribution
+            self.archive, self.distroseries.distribution.id
         )
         # Inject the inner query.
         query %= inner_query
@@ -1914,4 +1914,4 @@ def prefill_packageupload_caches(uploads, puses, pubs, pucs, logs):
         PackageCopyJob, uploads, ["package_copy_job_id"]
     )
     archives = load_related(Archive, package_copy_jobs, ["source_archive_id"])
-    load_related(Distribution, archives, ["distributionID"])
+    load_related(Distribution, archives, ["distribution_id"])
diff --git a/lib/lp/soyuz/scripts/gina/handlers.py b/lib/lp/soyuz/scripts/gina/handlers.py
index 60b047c..39d70f6 100644
--- a/lib/lp/soyuz/scripts/gina/handlers.py
+++ b/lib/lp/soyuz/scripts/gina/handlers.py
@@ -238,7 +238,7 @@ class ImporterHandler:
 
     def _get_distro(self, name):
         """Return the distro database object by name."""
-        distro = Distribution.selectOneBy(name=name)
+        distro = IStore(Distribution).find(Distribution, name=name).one()
         if not distro:
             raise DataSetupError("Error finding distribution %r" % name)
         return distro
diff --git a/lib/lp/translations/model/translationsoverview.py b/lib/lp/translations/model/translationsoverview.py
index 793b1e5..a51ca0c 100644
--- a/lib/lp/translations/model/translationsoverview.py
+++ b/lib/lp/translations/model/translationsoverview.py
@@ -97,7 +97,7 @@ class TranslationsOverview:
             if product_id is not None:
                 pillar = IStore(Product).get(Product, product_id)
             elif distro_id is not None:
-                pillar = Distribution.get(distro_id)
+                pillar = IStore(Distribution).get(Distribution, distro_id)
             else:
                 raise MalformedKarmaCacheData(
                     "Lots of karma for non-existing product or distribution."
diff --git a/lib/lp/translations/tests/test_autoapproval.py b/lib/lp/translations/tests/test_autoapproval.py
index ef4c11f..2e91839 100644
--- a/lib/lp/translations/tests/test_autoapproval.py
+++ b/lib/lp/translations/tests/test_autoapproval.py
@@ -22,7 +22,7 @@ from lp.registry.interfaces.series import SeriesStatus
 from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet
 from lp.registry.model.distribution import Distribution
 from lp.registry.model.sourcepackagename import SourcePackageNameSet
-from lp.services.database.interfaces import IPrimaryStore
+from lp.services.database.interfaces import IPrimaryStore, IStore
 from lp.services.worlddata.interfaces.language import ILanguageSet
 from lp.testing import TestCaseWithFactory, verifyObject
 from lp.testing.fakemethod import FakeMethod
@@ -84,7 +84,9 @@ class TestCustomLanguageCode(TestCaseWithFactory):
             language=getUtility(ILanguageSet).getLanguageByCode("pt"),
         )
 
-        self.distro = Distribution.byName("ubuntu")
+        self.distro = (
+            IStore(Distribution).find(Distribution, name="ubuntu").one()
+        )
         self.sourcepackagename = getUtility(ISourcePackageNameSet)["evolution"]
         self.package_codes["Brazilian"] = CustomLanguageCode(
             translation_target=self.distro.getSourcePackage(
@@ -109,7 +111,9 @@ class TestCustomLanguageCode(TestCaseWithFactory):
         self.assertEqual(fresh_product.getCustomLanguageCode("nocode"), None)
         self.assertEqual(fresh_product.getCustomLanguageCode("pt_PT"), None)
 
-        fresh_distro = Distribution.byName("gentoo")
+        fresh_distro = (
+            IStore(Distribution).find(Distribution, name="gentoo").one()
+        )
         gentoo_package = fresh_distro.getSourcePackage(self.sourcepackagename)
         nocode = gentoo_package.getCustomLanguageCode("nocode")
         self.assertEqual(nocode, None)