← Back to team overview

launchpad-reviewers team mailing list archive

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

 

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

Commit message:
Convert several Person/ValidPersonCache queries to Storm style

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/451588

`Person` is used all over the place, so converting it all to the Storm style in one go results in a rather large diff.  These queries can be converted in advance to make review easier.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:stormify-person-queries into launchpad:master.
diff --git a/lib/lp/blueprints/doc/specification.rst b/lib/lp/blueprints/doc/specification.rst
index 7ba3314..ede5c54 100644
--- a/lib/lp/blueprints/doc/specification.rst
+++ b/lib/lp/blueprints/doc/specification.rst
@@ -21,11 +21,12 @@ IMilestoneSet can be accessed as a utility.
 To create a new Specification, use ISpecificationSet.new:
 
     >>> from lp.registry.interfaces.product import IProductSet
+    >>> from lp.registry.model.person import Person
+    >>> from lp.services.database.interfaces import IStore
 
     >>> productset = getUtility(IProductSet)
     >>> upstream_firefox = productset.get(4)
-    >>> from lp.registry.model.person import Person
-    >>> mark = Person.byName("mark")
+    >>> mark = IStore(Person).find(Person, name="mark").one()
     >>> newspec = specset.new(
     ...     "mng",
     ...     "Support MNG Format",
@@ -78,7 +79,7 @@ We attach now a spec to a distribution.
 
     >>> from lp.app.interfaces.launchpad import ILaunchpadCelebrities
     >>> ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
-    >>> mark = Person.byName("mark")
+    >>> mark = IStore(Person).find(Person, name="mark").one()
     >>> ubuspec = specset.new(
     ...     "fix-spec-permissions",
     ...     "Fix Specification Permissions",
@@ -99,7 +100,7 @@ member, and therefore should be able to edit any spec attached to it
     >>> print(ubuntu.owner.name)
     ubuntu-team
 
-    >>> jdub = Person.byName("jdub")
+    >>> jdub = IStore(Person).find(Person, name="jdub").one()
     >>> jdub.inTeam(ubuntu.owner)
     True
 
diff --git a/lib/lp/bugs/stories/bugs/xx-bug-text-pages.rst b/lib/lp/bugs/stories/bugs/xx-bug-text-pages.rst
index 116baaa..9b64266 100644
--- a/lib/lp/bugs/stories/bugs/xx-bug-text-pages.rst
+++ b/lib/lp/bugs/stories/bugs/xx-bug-text-pages.rst
@@ -15,7 +15,7 @@ We'll start by adding some attachments to the bug:
     >>> from lp.services.database.sqlbase import flush_database_updates
     >>> from lp.testing import login, logout
     >>> login("foo.bar@xxxxxxxxxxxxx")
-    >>> mark = Person.selectOneBy(name="mark")
+    >>> mark = IStore(Person).find(Person, name="mark").one()
     >>> mark.display_name = "M\xe1rk Sh\xfattlew\xf2rth"
     >>> bug = IStore(Bug).get(Bug, 1)
     >>> content = BytesIO(b"<html><body>bogus</body></html>")
diff --git a/lib/lp/codehosting/tests/test_acceptance.py b/lib/lp/codehosting/tests/test_acceptance.py
index ece2d62..a03af35 100644
--- a/lib/lp/codehosting/tests/test_acceptance.py
+++ b/lib/lp/codehosting/tests/test_acceptance.py
@@ -207,7 +207,7 @@ class SSHTestCase(TestCaseWithTransport, LoomTestMixin, TestCaseWithFactory):
 
     def getDatabaseBranch(self, personName, productName, branchName):
         """Look up and return the specified branch from the database."""
-        owner = Person.byName(personName)
+        owner = IStore(Person).find(Person, name=personName).one()
         if productName is None:
             product = None
         else:
@@ -335,7 +335,7 @@ class AcceptanceTests(WithScenarios, SSHTestCase):
         branch_type=BranchType.HOSTED,
     ):
         """Create a new branch in the database."""
-        owner = Person.selectOneBy(name=owner_name)
+        owner = IStore(Person).find(Person, name=owner_name).one()
         if product_name == "+junk":
             product = None
         else:
@@ -508,8 +508,10 @@ class AcceptanceTests(WithScenarios, SSHTestCase):
         # the branch doesn't exist.
 
         # 'salgado' is a member of landscape-developers.
-        salgado = Person.selectOneBy(name="salgado")
-        landscape_dev = Person.selectOneBy(name="landscape-developers")
+        salgado = IStore(Person).find(Person, name="salgado").one()
+        landscape_dev = (
+            IStore(Person).find(Person, name="landscape-developers").one()
+        )
         self.assertTrue(
             salgado.inTeam(landscape_dev),
             "salgado should be a member of landscape-developers, but isn't.",
@@ -547,7 +549,7 @@ class AcceptanceTests(WithScenarios, SSHTestCase):
         # Hack 'firefox' so we have permission to do this.
         ZopelessAppServerLayer.txn.begin()
         firefox = IStore(Product).find(Product, name="firefox").one()
-        testuser = Person.selectOneBy(name="testuser")
+        testuser = IStore(Person).find(Person, name="testuser").one()
         firefox.development_focus.owner = testuser
         ZopelessAppServerLayer.txn.commit()
         remote_url = self.getTransportURL("+branch/firefox")
diff --git a/lib/lp/registry/doc/person-account.rst b/lib/lp/registry/doc/person-account.rst
index 21bb628..6495c01 100644
--- a/lib/lp/registry/doc/person-account.rst
+++ b/lib/lp/registry/doc/person-account.rst
@@ -130,7 +130,7 @@ will cause this spec to be reassigned.
     >>> len(foobar_pillars) > 0
     True
 
-    >>> foobar_teams = list(Person.selectBy(teamowner=foobar))
+    >>> foobar_teams = list(IStore(Person).find(Person, teamowner=foobar))
     >>> len(foobar_teams) > 0
     True
 
@@ -202,7 +202,7 @@ adds a '-deactivatedaccount' suffix to the person's name...
 
 ...no owned teams...
 
-    >>> Person.selectBy(teamowner=foobar).is_empty()
+    >>> IStore(Person).find(Person, teamowner=foobar).is_empty()
     True
 
 ...no owned or driven pillars...
@@ -226,7 +226,9 @@ Bar are now owned/driven by the registry admins team.
     >>> registry_pillars.issuperset(foobar_pillars)
     True
 
-    >>> registry_teams = set(Person.selectBy(teamowner=registry_experts))
+    >>> registry_teams = set(
+    ...     IStore(Person).find(Person, teamowner=registry_experts)
+    ... )
     >>> registry_teams.issuperset(foobar_teams)
     True
 
diff --git a/lib/lp/registry/interfaces/person.py b/lib/lp/registry/interfaces/person.py
index ec14854..fe77d12 100644
--- a/lib/lp/registry/interfaces/person.py
+++ b/lib/lp/registry/interfaces/person.py
@@ -128,6 +128,7 @@ from lp.registry.interfaces.teammembership import (
     TeamMembershipStatus,
 )
 from lp.registry.interfaces.wikiname import IWikiName
+from lp.services.database.interfaces import IStore
 from lp.services.database.sqlbase import block_implicit_flushes
 from lp.services.fields import (
     BlocklistableContentNameField,
@@ -172,7 +173,7 @@ def validate_person_common(
     # Importing here to avoid a cyclic import.
     from lp.registry.model.person import Person
 
-    person = Person.get(value)
+    person = IStore(Person).get(Person, value)
     if not validate_func(person):
         raise error_class(
             "Cannot link person (name=%s, visibility=%s) to %s (name=%s)"
diff --git a/lib/lp/registry/model/person.py b/lib/lp/registry/model/person.py
index 8aef249..e0e5548 100644
--- a/lib/lp/registry/model/person.py
+++ b/lib/lp/registry/model/person.py
@@ -209,7 +209,6 @@ from lp.services.database.sqlobject import (
     BoolCol,
     ForeignKey,
     IntCol,
-    SQLObjectNotFound,
     StringCol,
 )
 from lp.services.database.stormbase import StormBase
@@ -1370,11 +1369,9 @@ class Person(
         # This is prepopulated by various queries in and out of person.py.
         if self.is_team:
             return False
-        try:
-            ValidPersonCache.get(self.id)
-            return True
-        except SQLObjectNotFound:
-            return False
+        return (
+            IStore(ValidPersonCache).get(ValidPersonCache, self.id) is not None
+        )
 
     @property
     def is_probationary(self):
@@ -2607,7 +2604,7 @@ class Person(
             spec.assignee = None
 
         registry_experts = getUtility(ILaunchpadCelebrities).registry_experts
-        for team in Person.selectBy(teamowner=self):
+        for team in IStore(Person).find(Person, teamowner=self):
             team.teamowner = registry_experts
         for pillar_name in self.getAffiliatedPillars(self):
             pillar = pillar_name.pillar
@@ -2664,7 +2661,7 @@ class Person(
         """Return a unique name."""
         new_name = base_new_name
         count = 1
-        while Person.selectOneBy(name=new_name) is not None:
+        while not IStore(Person).find(Person, name=new_name).is_empty():
             new_name = base_new_name + str(count)
             count += 1
         return new_name
@@ -3834,17 +3831,21 @@ class PersonSet:
         """See `IPersonSet`."""
         # The odd ordering here is to ensure we hit the PostgreSQL
         # indexes. It will not make any real difference outside of tests.
-        query = (
-            """
-            id IN (
-                SELECT person FROM KarmaTotalCache
-                ORDER BY karma_total DESC, person DESC
-                LIMIT %s
-                )
-            """
-            % limit
+        top_people = shortlist(
+            IStore(Person).find(
+                Person,
+                Person.id.is_in(
+                    Select(
+                        KarmaTotalCache.person_id,
+                        order_by=(
+                            Desc(KarmaTotalCache.karma_total),
+                            Desc(KarmaTotalCache.person_id),
+                        ),
+                        limit=limit,
+                    )
+                ),
+            )
         )
-        top_people = shortlist(Person.select(query))
         return sorted(
             top_people,
             key=lambda obj: (obj.karma, obj.displayname, obj.id),
@@ -4304,10 +4305,10 @@ class PersonSet:
 
     def getByName(self, name, ignore_merged=True):
         """See `IPersonSet`."""
-        query = Person.name == name
+        clauses = [Person.name == name]
         if ignore_merged:
-            query = And(query, Person.mergedID == None)
-        return Person.selectOne(query)
+            clauses.append(Is(Person.mergedID, None))
+        return IStore(Person).find(Person, *clauses).one()
 
     def getByAccount(self, account):
         """See `IPersonSet`."""
@@ -4316,14 +4317,26 @@ class PersonSet:
     def updateStatistics(self):
         """See `IPersonSet`."""
         stats = getUtility(ILaunchpadStatisticSet)
-        people_count = Person.select(
-            And(Person.teamownerID == None, Person.mergedID == None)
-        ).count()
+        people_count = (
+            IStore(Person)
+            .find(
+                Person,
+                Is(Person.teamownerID, None),
+                Is(Person.mergedID, None),
+            )
+            .count()
+        )
         stats.update("people_count", people_count)
         transaction.commit()
-        teams_count = Person.select(
-            And(Person.q.teamownerID != None, Person.q.mergedID == None)
-        ).count()
+        teams_count = (
+            IStore(Person)
+            .find(
+                Person,
+                IsNot(Person.teamownerID, None),
+                Is(Person.mergedID, None),
+            )
+            .count()
+        )
         stats.update("teams_count", teams_count)
         transaction.commit()
 
@@ -4483,10 +4496,7 @@ class PersonSet:
 
     def get(self, personid):
         """See `IPersonSet`."""
-        try:
-            return Person.get(personid)
-        except SQLObjectNotFound:
-            return None
+        return IStore(Person).get(Person, personid)
 
     def getByEmail(self, email, filter_status=True):
         """See `IPersonSet`."""
@@ -4543,8 +4553,8 @@ class PersonSet:
         # not hit the DB.
         valid_person_ids = {
             person_id.id
-            for person_id in ValidPersonCache.select(
-                "id IN %s" % sqlvalues(person_ids)
+            for person_id in IStore(ValidPersonCache).find(
+                ValidPersonCache, ValidPersonCache.id.is_in(person_ids)
             )
         }
         return [person for person in persons if person.id in valid_person_ids]
diff --git a/lib/lp/registry/stories/distributionmirror/xx-reassign-distributionmirror.rst b/lib/lp/registry/stories/distributionmirror/xx-reassign-distributionmirror.rst
index 9db9db6..89ff351 100644
--- a/lib/lp/registry/stories/distributionmirror/xx-reassign-distributionmirror.rst
+++ b/lib/lp/registry/stories/distributionmirror/xx-reassign-distributionmirror.rst
@@ -52,7 +52,10 @@ We also try to use the name of an unvalidated account, which can't be used as
 the owner of something.
 
     >>> from lp.registry.model.person import Person
-    >>> Person.byName("matsubara").is_valid_person_or_team
+    >>> from lp.services.database.interfaces import IStore
+    >>> IStore(Person).find(
+    ...     Person, name="matsubara"
+    ... ).one().is_valid_person_or_team
     False
     >>> browser.getControl(name="field.owner").value = "matsubara"
     >>> browser.getControl("Change").click()
@@ -80,7 +83,7 @@ Now we try to create a team using a name that is already taken.
 Okay, let's do it properly now and reassign it to an existing (and validated)
 account.
 
-    >>> salgado = Person.byName("salgado")
+    >>> salgado = IStore(Person).find(Person, name="salgado").one()
     >>> salgado.is_valid_person_or_team
     True
 
diff --git a/lib/lp/registry/stories/person/xx-approve-members.rst b/lib/lp/registry/stories/person/xx-approve-members.rst
index 6428641..bb6c369 100644
--- a/lib/lp/registry/stories/person/xx-approve-members.rst
+++ b/lib/lp/registry/stories/person/xx-approve-members.rst
@@ -66,8 +66,10 @@ as an inactive one.
     # listed anywhere.
     >>> from lp.registry.model.person import Person
     >>> from lp.registry.model.teammembership import TeamMembershipSet
+    >>> from lp.services.database.interfaces import IStore
     >>> membership = TeamMembershipSet().getByPersonAndTeam(
-    ...     Person.byName("name12"), Person.byName("ubuntu-team")
+    ...     IStore(Person).find(Person, name="name12").one(),
+    ...     IStore(Person).find(Person, name="ubuntu-team").one(),
     ... )
     >>> membership.status.title
     'Declined'
diff --git a/lib/lp/registry/stories/productrelease/xx-productrelease-basics.rst b/lib/lp/registry/stories/productrelease/xx-productrelease-basics.rst
index f25171d..036b0e7 100644
--- a/lib/lp/registry/stories/productrelease/xx-productrelease-basics.rst
+++ b/lib/lp/registry/stories/productrelease/xx-productrelease-basics.rst
@@ -169,7 +169,7 @@ Celso is a member of ubuntu-team, so he can edit this release too:
 
 And if no-priv drives the series...
 
-    >>> no_priv = Person.selectOneBy(name="no-priv")
+    >>> no_priv = IStore(Person).find(Person, name="no-priv").one()
     >>> tomcat.getSeries("trunk").driver = no_priv
 
 ... they can edit existing releases as well, even if they are owned by
diff --git a/lib/lp/registry/stories/teammembership/xx-add-member.rst b/lib/lp/registry/stories/teammembership/xx-add-member.rst
index b80bb89..c8ea2b2 100644
--- a/lib/lp/registry/stories/teammembership/xx-add-member.rst
+++ b/lib/lp/registry/stories/teammembership/xx-add-member.rst
@@ -23,8 +23,10 @@ Let's make sure that 'cprov' is now an Approved member of
     >>> from lp.registry.model.person import Person
     >>> from lp.registry.model.teammembership import TeamMembership
     >>> from lp.services.database.interfaces import IStore
-    >>> cprov = Person.byName("cprov")
-    >>> landscape_team = Person.byName("landscape-developers")
+    >>> cprov = IStore(Person).find(Person, name="cprov").one()
+    >>> landscape_team = (
+    ...     IStore(Person).find(Person, name="landscape-developers").one()
+    ... )
     >>> cprov_landscape_membership = (
     ...     IStore(TeamMembership)
     ...     .find(TeamMembership, person=cprov, team=landscape_team)
@@ -56,7 +58,7 @@ become a member.
 As we can see, the launchpad team will not be one of the team's active
 members.
 
-    >>> launchpad = Person.byName("launchpad")
+    >>> launchpad = IStore(Person).find(Person, name="launchpad").one()
     >>> launchpad in landscape_team.activemembers
     False
     >>> membership = (
diff --git a/lib/lp/registry/stories/teammembership/xx-teammembership.rst b/lib/lp/registry/stories/teammembership/xx-teammembership.rst
index a7b5a3b..9d1e8a7 100644
--- a/lib/lp/registry/stories/teammembership/xx-teammembership.rst
+++ b/lib/lp/registry/stories/teammembership/xx-teammembership.rst
@@ -28,9 +28,11 @@ Regular users can create teams.
 The owner of a team is always added as an administrator of their team.
 
     >>> from lp.registry.model.person import Person
-    >>> for a in Person.byName("myemail").adminmembers:
+    >>> from lp.services.database.interfaces import IStore
+    >>> for a in (
+    ...     IStore(Person).find(Person, name="myemail").one().adminmembers
+    ... ):
     ...     print(a.name)
-    ...
     name12
 
 
@@ -90,8 +92,7 @@ approved, though.
 
     >>> from storm.locals import Store
     >>> from lp.registry.interfaces.person import TeamMembershipPolicy
-    >>> from lp.registry.model.person import Person
-    >>> myemail = Person.selectOneBy(name="myemail")
+    >>> myemail = IStore(Person).find(Person, name="myemail").one()
     >>> myemail.membership_policy = TeamMembershipPolicy.MODERATED
     >>> Store.of(myemail).flush()
 
diff --git a/lib/lp/registry/tests/test_person.py b/lib/lp/registry/tests/test_person.py
index 131ceff..cb3a5a7 100644
--- a/lib/lp/registry/tests/test_person.py
+++ b/lib/lp/registry/tests/test_person.py
@@ -946,12 +946,12 @@ class TestPersonStates(TestCaseWithFactory):
         is already in use. If this happens, we'll simply append an integer to
         that name until we can find one that is free.
         """
-        sample_person = Person.byName("name12")
+        sample_person = IStore(Person).find(Person, name="name12").one()
         login(sample_person.preferredemail.email)
         sample_person.deactivate(comment="blah!")
         self.assertEqual(sample_person.name, "name12-deactivatedaccount")
         # Now that name12 is free Foo Bar can use it.
-        foo_bar = Person.byName("name16")
+        foo_bar = IStore(Person).find(Person, name="name16").one()
         foo_bar.name = "name12"
         # If Foo Bar deactivates their account, though, we'll have to use a
         # name other than name12-deactivatedaccount because that is already
@@ -980,9 +980,9 @@ class TestPersonStates(TestCaseWithFactory):
         self.assertIs(None, product.bug_supervisor)
 
     def test_getDirectMemberIParticipateIn(self):
-        sample_person = Person.byName("name12")
-        warty_team = Person.byName("name20")
-        ubuntu_team = Person.byName("ubuntu-team")
+        sample_person = IStore(Person).find(Person, name="name12").one()
+        warty_team = IStore(Person).find(Person, name="name20").one()
+        ubuntu_team = IStore(Person).find(Person, name="ubuntu-team").one()
         # Sample Person is an active member of Warty Security Team which in
         # turn is a proposed member of Ubuntu Team. That means
         # sample_person._getDirectMemberIParticipateIn(ubuntu_team) will fail
@@ -1061,7 +1061,7 @@ class TestPersonStates(TestCaseWithFactory):
     def test_visibility_validator_team_ss_prod_pub_to_private(self):
         # A PUBLIC team with a structural subscription to a product can
         # convert to a PRIVATE team.
-        foo_bar = Person.byName("name16")
+        foo_bar = IStore(Person).find(Person, name="name16").one()
         self.bzr.addSubscription(self.otherteam, foo_bar)
         self.otherteam.visibility = PersonVisibility.PRIVATE
 
diff --git a/lib/lp/scripts/harness.py b/lib/lp/scripts/harness.py
index 1949e57..4d65d31 100644
--- a/lib/lp/scripts/harness.py
+++ b/lib/lp/scripts/harness.py
@@ -73,7 +73,7 @@ def _get_locals():
         # Create a few variables "in case they come in handy."
         # Do we really use these?  Are they worth carrying around?
         d = store.get(Distribution, 1)
-        p = Person.get(1)
+        p = store.get(Person, 1)
         ds = store.get(DistroSeries, 1)
         prod = store.get(Product, 1)
         proj = store.get(ProjectGroup, 1)
diff --git a/lib/lp/services/database/doc/security-proxies.rst b/lib/lp/services/database/doc/security-proxies.rst
index 3675907..ac20f99 100644
--- a/lib/lp/services/database/doc/security-proxies.rst
+++ b/lib/lp/services/database/doc/security-proxies.rst
@@ -1,7 +1,7 @@
 Security proxies
 ----------------
 
-SQLObjects that are security proxied should still behave normally, this
+Storm objects that are security proxied should still behave normally, this
 includes being comparable with non-security proxied objects.
 
 First, some imports and set up::
@@ -9,11 +9,12 @@ First, some imports and set up::
     >>> from zope.component import getUtility
     >>> from lp.registry.interfaces.person import IPersonSet
     >>> from lp.registry.model.person import Person
+    >>> from lp.services.database.interfaces import IStore
 
 Get a proxied and unproxied person object for the same person, and demonstrate
 working comparisons::
 
-    >>> mark = Person.get(1)
+    >>> mark = IStore(Person).get(Person, 1)
     >>> mark_proxied = getUtility(IPersonSet).get(1)
     >>> mark is mark_proxied
     False
@@ -26,8 +27,7 @@ working comparisons::
     >>> mark_proxied == mark_proxied
     True
 
-A dbschema Item can also be given to sqlobject's select() method, or any
-of its variants.
+A ``lazr.enum.DBItem`` can also be given to Storm's find() method.
 
     >>> proxied_policy = mark_proxied.membership_policy
     >>> type(proxied_policy)
@@ -35,19 +35,21 @@ of its variants.
 
     # We don't want this test to fail when we add new person entries, so we
     # compare it against a base number.
-    >>> Person.select(
-    ...     Person.q.membership_policy == proxied_policy
+    >>> IStore(Person).find(
+    ...     Person, membership_policy=proxied_policy
     ... ).count() > 60
     True
-    >>> person = Person.select(Person.q.membership_policy == proxied_policy)[
-    ...     0
-    ... ]
+    >>> person = (
+    ...     IStore(Person)
+    ...     .find(Person, membership_policy=proxied_policy)
+    ...     .first()
+    ... )
     >>> person.membership_policy.name
     'MODERATED'
 
 XXX: stevea: 20051018: Rewrite this test to use security proxies directly
 XXX: bug 3315
-DB schema objects should be comparable correctly when proxied...
+``lazr.enum.DBItem`` objects are comparable correctly when proxied.
 
     >>> from lp.registry.interfaces.distroseries import IDistroSeriesSet
     >>> from lp.registry.interfaces.series import SeriesStatus
diff --git a/lib/lp/services/verification/doc/logintoken.rst b/lib/lp/services/verification/doc/logintoken.rst
index 2cd0377..95c25e3 100644
--- a/lib/lp/services/verification/doc/logintoken.rst
+++ b/lib/lp/services/verification/doc/logintoken.rst
@@ -19,17 +19,18 @@ follows:
     4) The token is now marked as consumed, together with any other
        tokens of the same type and for the same email address.
 
+    >>> import transaction
+    >>> from lp.registry.model.person import Person
+    >>> from lp.services.database.interfaces import IStore
+    >>> from lp.services.database.sqlbase import flush_database_updates
+    >>> from lp.services.mail import stub
     >>> from lp.services.verification.interfaces.authtoken import (
     ...     LoginTokenType,
     ... )
-    >>> from lp.registry.model.person import Person
     >>> from lp.services.verification.interfaces.logintoken import (
     ...     ILoginTokenSet,
     ... )
-    >>> from lp.services.database.sqlbase import flush_database_updates
-    >>> from lp.services.mail import stub
-    >>> import transaction
-    >>> foobar = Person.byName("name16")
+    >>> foobar = IStore(Person).find(Person, name="name16").one()
 
 Let's create a new LoginToken to confirm an email address for foobar.
 
diff --git a/lib/lp/soyuz/doc/gina-multiple-arch.rst b/lib/lp/soyuz/doc/gina-multiple-arch.rst
index d36a2fe..a8ad558 100644
--- a/lib/lp/soyuz/doc/gina-multiple-arch.rst
+++ b/lib/lp/soyuz/doc/gina-multiple-arch.rst
@@ -21,7 +21,7 @@ Get the current counts of stuff in the database:
     ...     IStore(SourcePackageRelease).find(SourcePackageRelease).count()
     ... )
     >>> orig_sspph_count = IStore(SSPPH).find(SSPPH).count()
-    >>> orig_person_count = Person.select().count()
+    >>> orig_person_count = IStore(Person).find(Person).count()
     >>> orig_tp_count = (
     ...     IStore(TeamParticipation).find(TeamParticipation).count()
     ... )
@@ -147,7 +147,7 @@ breezy:
 Each source package has its own maintainer (in this case, fabbione and
 porridge):
 
-    >>> print(Person.select().count() - orig_person_count)
+    >>> print(IStore(Person).find(Person).count() - orig_person_count)
     2
     >>> print(
     ...     IStore(TeamParticipation).find(TeamParticipation).count()
diff --git a/lib/lp/soyuz/doc/gina.rst b/lib/lp/soyuz/doc/gina.rst
index aac6267..49bbc15 100644
--- a/lib/lp/soyuz/doc/gina.rst
+++ b/lib/lp/soyuz/doc/gina.rst
@@ -28,7 +28,7 @@ Get the current counts of stuff in the database:
     ...     IStore(SourcePackageRelease).find(SourcePackageRelease).count()
     ... )
     >>> orig_sspph_count = IStore(SSPPH).find(SSPPH).count()
-    >>> orig_person_count = Person.select().count()
+    >>> orig_person_count = IStore(Person).find(Person).count()
     >>> orig_tp_count = (
     ...     IStore(TeamParticipation).find(TeamParticipation).count()
     ... )
@@ -612,11 +612,14 @@ Ensure only one Kamion was created (he's an uploader on multiple packages),
 and that we imported exactly 9 people (13 packages with 3 being uploaded by
 Kamion, 2 being uploaded by mdz and 2 by doko).
 
-    >>> from lp.services.database.sqlobject import LIKE
-    >>> p = Person.selectOne(LIKE(Person.q.name, "cjwatson%"))
+    >>> p = (
+    ...     IStore(Person)
+    ...     .find(Person, Person.name.startswith("cjwatson"))
+    ...     .one()
+    ... )
     >>> print(p.name)
     cjwatson
-    >>> print(Person.select().count() - orig_person_count)
+    >>> print(IStore(Person).find(Person).count() - orig_person_count)
     13
     >>> print(
     ...     IStore(TeamParticipation).find(TeamParticipation).count()
@@ -717,7 +720,7 @@ changed, etc.
     ...     - orig_spr_count
     ... )
     17
-    >>> print(Person.select().count() - orig_person_count)
+    >>> print(IStore(Person).find(Person).count() - orig_person_count)
     13
     >>> print(
     ...     IStore(TeamParticipation).find(TeamParticipation).count()
diff --git a/lib/lp/soyuz/vocabularies.py b/lib/lp/soyuz/vocabularies.py
index 1b640b8..b8dbf55 100644
--- a/lib/lp/soyuz/vocabularies.py
+++ b/lib/lp/soyuz/vocabularies.py
@@ -95,7 +95,7 @@ class PPAVocabulary(SQLObjectVocabularyBase):
     # longer see.
     _filter = And(
         Archive._enabled == True,
-        Person.q.id == Archive.q.ownerID,
+        Archive.owner == Person.id,
         Archive.q.purpose == ArchivePurpose.PPA,
     )
     displayname = "Select a PPA"
diff --git a/lib/lp/translations/doc/rosetta-translation.rst b/lib/lp/translations/doc/rosetta-translation.rst
index 866b444..8c26c18 100644
--- a/lib/lp/translations/doc/rosetta-translation.rst
+++ b/lib/lp/translations/doc/rosetta-translation.rst
@@ -42,7 +42,7 @@ Get a translation for a particular message and check it has a translation.
 Get a person to create a translation with.
 
     >>> from lp.registry.model.person import Person
-    >>> person = Person.get(1)
+    >>> person = IStore(Person).get(Person, 1)
     >>> pofile.canEditTranslations(person)
     True
 
@@ -96,9 +96,9 @@ Now we want to test the interaction of the "upstream" translations with the
 "active translations". There are several things we want to be able to test.
 First, let's setup some useful variables.
 
-    >>> Pa = Person.get(50)
-    >>> Pb = Person.get(46)
-    >>> Pc = Person.get(16)
+    >>> Pa = IStore(Person).get(Person, 50)
+    >>> Pb = IStore(Person).get(Person, 46)
+    >>> Pc = IStore(Person).get(Person, 16)
 
 Pa, Pb and Pc are three useful Person's.