← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~wgrant/launchpad/move-SPR-build-methods into lp:launchpad

 

William Grant has proposed merging lp:~wgrant/launchpad/move-SPR-build-methods into lp:launchpad with lp:~wgrant/launchpad/abolish-SPR-createBuild as a prerequisite.

Commit message:
Replace SourcePackageRelease.getBuildByArch with BinaryPackageBuildSet.getBySourceAndLocation.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~wgrant/launchpad/move-SPR-build-methods/+merge/240227

Replace SourcePackageRelease.getBuildByArch with BinaryPackageBuildSet.getBySourceAndLocation.
-- 
https://code.launchpad.net/~wgrant/launchpad/move-SPR-build-methods/+merge/240227
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/move-SPR-build-methods into lp:launchpad.
=== modified file 'lib/lp/archiveuploader/nascentuploadfile.py'
--- lib/lp/archiveuploader/nascentuploadfile.py	2014-10-31 08:47:29 +0000
+++ lib/lp/archiveuploader/nascentuploadfile.py	2014-10-31 08:47:29 +0000
@@ -847,8 +847,8 @@
         dar = self.policy.distroseries[self.archtag]
 
         # Check if there's a suitable existing build.
-        build = sourcepackagerelease.getBuildByArch(
-            dar, self.policy.archive)
+        build = getUtility(IBinaryPackageBuildSet).getBySourceAndLocation(
+            sourcepackagerelease, self.policy.archive, dar)
         if build is not None:
             build.updateStatus(BuildStatus.FULLYBUILT)
             self.logger.debug("Updating build for %s: %s" % (

=== modified file 'lib/lp/soyuz/doc/sourcepackagerelease-build-lookup.txt'
--- lib/lp/soyuz/doc/sourcepackagerelease-build-lookup.txt	2014-10-31 08:47:29 +0000
+++ lib/lp/soyuz/doc/sourcepackagerelease-build-lookup.txt	2014-10-31 08:47:29 +0000
@@ -5,20 +5,19 @@
 
 = Creating & Looking for Build records =
 
-ISourcePackageRelease has the ability to create Build records,
-however it needs external support to treat architecturehintlist and
-Package-architecture-specific (P-a-s) information, see further
-information in buildd-queuebuilder.txt.
+IBinaryPackageBuildSet can create and look up build records.
 
-ISourcePackageRelease also provides a 'getBuildByArch' method which
-allows the application to lookup for Build records in a given
-DistroArchSeries and Archive.
+It provides a 'getBySourceAndLocation' method which allows the
+application to lookup for BinaryPackageBuild records for
+SourcePackageRelease in a given DistroArchSeries and Archive.
 
 To demonstrate this we need to define some variables.
 
     >>> from zope.component import getUtility
+    >>> from lp.registry.interfaces.distribution import IDistributionSet
     >>> from lp.services.librarian.interfaces import ILibraryFileAliasSet
-    >>> from lp.registry.interfaces.distribution import IDistributionSet
+    >>> from lp.soyuz.interfaces.binarypackagebuild import (
+    ...     IBinaryPackageBuildSet)
 
     >>> ubuntu = getUtility(IDistributionSet).getByName('ubuntu')
     >>> hoary = ubuntu.getSeries('hoary')
@@ -64,18 +63,18 @@
     >>> print evo_build_i386.archive.displayname
     Primary Archive for Ubuntu Linux
 
-The build record can be retrieved via getBuildByArch on hoary/i386
-architecture.
+The build record can be retrieved on hoary/i386 architecture.
 
-    >>> test_build_i386 = evo_release.getBuildByArch(
-    ...     hoary_i386, ubuntu.main_archive)
+    >>> bpbs = getUtility(IBinaryPackageBuildSet)
+    >>> test_build_i386 = bpbs.getBySourceAndLocation(
+    ...     evo_release, ubuntu.main_archive, hoary_i386)
     >>> test_build_i386 == evo_build_i386
     True
 
 However a hoary/hppa build is not available.
 
-    >>> test_build_hppa = evo_release.getBuildByArch(
-    ...     hoary_hppa, ubuntu.main_archive)
+    >>> test_build_hppa = bpbs.getBySourceAndLocation(
+    ...     evo_release, ubuntu.main_archive, hoary_hppa)
     >>> print test_build_hppa
     None
 
@@ -108,8 +107,8 @@
 In practical terms it means that another build is not necessary in
 this context.
 
-    >>> breezy_autotest_build = evo_release.getBuildByArch(
-    ...     breezy_autotest_i386, ubuntu.main_archive)
+    >>> breezy_autotest_build = bpbs.getBySourceAndLocation(
+    ...     evo_release, ubuntu.main_archive, breezy_autotest_i386)
     >>> print breezy_autotest_build.title
     i386 build of evolution 1.0 in ubuntu hoary RELEASE
 
@@ -117,8 +116,8 @@
 == Sources with architecture-independent and specific binaries ==
 
 Even if the source package builds an architecture-independent package,
-no Build record will be returned by getBuildByArch() if arch-specific
-binary packages were not built (see bug #65712 for further
+no Build record will be returned by getBySourceAndLocation() if
+arch-specific binary packages were not built (see bug #65712 for further
 information).
 
 In order to be independent of the sampledata we will use the
@@ -149,8 +148,8 @@
 
 The build record for foo in hoary/i386 was created.
 
-    >>> test_build_i386 = foo_pub_src.sourcepackagerelease.getBuildByArch(
-    ...     hoary_i386, ubuntu.main_archive)
+    >>> test_build_i386 = bpbs.getBySourceAndLocation(
+    ...     foo_pub_src.sourcepackagerelease, ubuntu.main_archive, hoary_i386)
     >>> print test_build_i386.title
     i386 build of foo 1.0 in ubuntu hoary RELEASE
 
@@ -163,8 +162,8 @@
     foo-bin 1.0 in hoary i386
     foo-bin 1.0 in hoary hppa
 
-    >>> test_build_hppa = foo_pub_src.sourcepackagerelease.getBuildByArch(
-    ...     hoary_hppa, ubuntu.main_archive)
+    >>> test_build_hppa = bpbs.getBySourceAndLocation(
+    ...     foo_pub_src.sourcepackagerelease, ubuntu.main_archive, hoary_hppa)
     >>> print test_build_hppa
     None
 
@@ -182,8 +181,8 @@
 
 No suitable build will be found for it.
 
-    >>> test_build_i386_ppa = copy.sourcepackagerelease.getBuildByArch(
-    ...     hoary_i386, cprov.archive)
+    >>> test_build_i386_ppa = bpbs.getBySourceAndLocation(
+    ...     copy.sourcepackagerelease, cprov.archive, hoary_i386)
     >>> print test_build_i386_ppa
     None
 
@@ -207,15 +206,15 @@
 The copied source build lookup in the PPA returns the build created in
 the PPA context, not the PRIMARY archive one.
 
-    >>> test_build_i386_ppa = copy.sourcepackagerelease.getBuildByArch(
-    ...     hoary_i386, cprov.archive)
+    >>> test_build_i386_ppa = bpbs.getBySourceAndLocation(
+    ...     copy.sourcepackagerelease, cprov.archive, hoary_i386)
     >>> test_build_i386_ppa == evo_build_i386_ppa
     True
 
 As expected, the hoary/hppa build is still missing in both archives.
 
-    >>> test_build_hppa_ppa = copy.sourcepackagerelease.getBuildByArch(
-    ...     hoary_hppa, cprov.archive)
+    >>> test_build_hppa_ppa = bpbs.getBySourceAndLocation(
+    ...     copy.sourcepackagerelease, cprov.archive, hoary_hppa)
     >>> print test_build_hppa_ppa
     None
 
@@ -226,14 +225,13 @@
     ...     copy.sourcepackagerelease, cprov.archive, hoary_hppa,
     ...     pocket_release)
 
-    >>> test_build_hppa_ppa = copy.sourcepackagerelease.getBuildByArch(
-    ...     hoary_hppa, cprov.archive)
-
+    >>> test_build_hppa_ppa = bpbs.getBySourceAndLocation(
+    ...     copy.sourcepackagerelease, cprov.archive, hoary_hppa)
     >>> print test_build_hppa_ppa.title
     hppa build of evolution 1.0 in ubuntu hoary RELEASE
 
-    >>> test_build_hppa = evo_release.getBuildByArch(
-    ...     hoary_hppa, ubuntu.main_archive)
+    >>> test_build_hppa = bpbs.getBySourceAndLocation(
+    ...     evo_release, ubuntu.main_archive, hoary_hppa)
     >>> print test_build_hppa
     None
 
@@ -257,8 +255,8 @@
     ...     status=PackagePublishingStatus.PUBLISHED)
 
     >>> foo_source_release = foo_pub_src.sourcepackagerelease
-    >>> build_primary = foo_source_release.getBuildByArch(
-    ...     hoary_i386, ubuntu.main_archive)
+    >>> build_primary = bpbs.getBySourceAndLocation(
+    ...     foo_source_release, ubuntu.main_archive, hoary_i386)
 
     >>> print build_primary.title
     i386 build of foo 0.1 in ubuntu hoary RELEASE
@@ -283,8 +281,8 @@
 bug #181736 report for previous mistakes in this area.
 
     >>> cprov_spr = cprov_src.sourcepackagerelease
-    >>> cprov_build = cprov_spr.getBuildByArch(
-    ...     hoary_i386, cprov.archive)
+    >>> cprov_build = bpbs.getBySourceAndLocation(
+    ...     cprov_spr, cprov.archive, hoary_i386)
 
     >>> print cprov_build.title
     i386 build of foo 0.1 in ubuntu hoary RELEASE
@@ -309,8 +307,8 @@
 
     >>> copied_release = copy.sourcepackagerelease
     >>> breezy_autotest_i386 = breezy_autotest['i386']
-    >>> copied_build_candidate = copied_release.getBuildByArch(
-    ...     breezy_autotest_i386, cprov.archive)
+    >>> copied_build_candidate = bpbs.getBySourceAndLocation(
+    ...     copied_release, cprov.archive, breezy_autotest_i386)
     >>> print copied_build_candidate
     None
 
@@ -335,8 +333,8 @@
 
     >>> copied_source_release = copied_source.sourcepackagerelease
     >>> warty_i386 = warty['i386']
-    >>> copied_build_candidate = copied_source_release.getBuildByArch(
-    ...     warty_i386, cprov.archive)
+    >>> copied_build_candidate = bpbs.getBySourceAndLocation(
+    ...     copied_source_release, cprov.archive, warty_i386)
 
     >>> print copied_build_candidate.title
     i386 build of foo 0.1 in ubuntu hoary RELEASE
@@ -364,8 +362,8 @@
 original build that happened in the primary archive.
 
     >>> mark_spr = mark_src.sourcepackagerelease
-    >>> mark_build = mark_spr.getBuildByArch(
-    ...     hoary_i386, mark.archive)
+    >>> mark_build = bpbs.getBySourceAndLocation(
+    ...     mark_spr, mark.archive, hoary_i386)
 
     >>> print mark_build.title
     i386 build of foo 0.1 in ubuntu hoary RELEASE

=== modified file 'lib/lp/soyuz/interfaces/binarypackagebuild.py'
--- lib/lp/soyuz/interfaces/binarypackagebuild.py	2014-10-31 08:47:29 +0000
+++ lib/lp/soyuz/interfaces/binarypackagebuild.py	2014-10-31 08:47:29 +0000
@@ -360,6 +360,16 @@
         :return: a list of `IBuild` records not target to PPA archives.
         """
 
+    def getBySourceAndLocation(sourcepackagerelease, archive,
+                               distroarchseries):
+        """Return build for the given source, archive and distroarchseries.
+
+        It looks for a build in any state registered *directly* for the
+        given distroarchseries and archive.
+
+        Returns None if a suitable build could not be found.
+        """
+
     def getStatusSummaryForBuilds(builds):
         """Return a summary of the build status for the given builds.
 

=== modified file 'lib/lp/soyuz/interfaces/sourcepackagerelease.py'
--- lib/lp/soyuz/interfaces/sourcepackagerelease.py	2014-10-31 08:47:29 +0000
+++ lib/lp/soyuz/interfaces/sourcepackagerelease.py	2014-10-31 08:47:29 +0000
@@ -174,15 +174,6 @@
         :return the corresponding `ILibraryFileAlias` if the file was found.
         """
 
-    def getBuildByArch(distroarchseries, archive):
-        """Return build for the given distroarchseries/archive.
-
-        It looks for a build in any state registered *directly* for the
-        given distroarchseries and archive.
-
-        Returns None if a suitable build could not be found.
-        """
-
     def override(component=None, section=None, urgency=None):
         """Uniform method to override sourcepackagerelease attribute.
 

=== modified file 'lib/lp/soyuz/model/binarypackagebuild.py'
--- lib/lp/soyuz/model/binarypackagebuild.py	2014-10-31 08:47:29 +0000
+++ lib/lp/soyuz/model/binarypackagebuild.py	2014-10-31 08:47:29 +0000
@@ -24,6 +24,7 @@
     LeftJoin,
     Or,
     )
+from storm.info import ClassAlias
 from storm.locals import (
     Bool,
     DateTime,
@@ -1151,6 +1152,90 @@
             Desc(BinaryPackageBuild.date_created), BinaryPackageBuild.id)
         return resultset
 
+    def _findBySourceAndLocation(self, sourcepackagerelease, archive,
+                                 distroseries):
+        """Find builds for a SourcePackageRelease by series and archive.
+
+        Looks for `BinaryPackageBuild` records for this source package
+        release, with publication records in the given distroseries.
+        There should be at most one of these per architecture.
+
+        :param distroseries: `DistroSeries` to look for.
+        :return: A dict mapping architecture tags (in string form,
+            e.g. 'i386') to `BinaryPackageBuild`s for that build.
+        """
+        # Avoid circular imports.
+        from lp.soyuz.model.distroarchseries import DistroArchSeries
+        from lp.soyuz.model.publishing import BinaryPackagePublishingHistory
+
+        BuildDAS = ClassAlias(DistroArchSeries, 'BuildDAS')
+        PublishDAS = ClassAlias(DistroArchSeries, 'PublishDAS')
+
+        query = IStore(BinaryPackageBuild).find(
+            (BuildDAS.architecturetag, BinaryPackageBuild),
+            BinaryPackageBuild.source_package_release == sourcepackagerelease,
+            BinaryPackageRelease.buildID == BinaryPackageBuild.id,
+            BuildDAS.id == BinaryPackageBuild.distro_arch_series_id,
+            BinaryPackagePublishingHistory.binarypackagereleaseID ==
+                BinaryPackageRelease.id,
+            BinaryPackagePublishingHistory.archiveID == archive.id,
+            PublishDAS.id ==
+                BinaryPackagePublishingHistory.distroarchseriesID,
+            PublishDAS.distroseriesID == distroseries.id,
+            # Architecture-independent binary package releases are built
+            # in the nominated arch-indep architecture but published in
+            # all architectures.  This condition makes sure we consider
+            # only builds that have been published in their own
+            # architecture.
+            PublishDAS.architecturetag == BuildDAS.architecturetag)
+        results = list(query.config(distinct=True))
+        mapped_results = dict(results)
+        assert len(mapped_results) == len(results), (
+            "Found multiple build candidates per architecture: %s.  "
+            "This may mean that we have a serious problem in our DB model.  "
+            "Further investigation is required."
+            % [(tag, build.id) for tag, build in results])
+        return mapped_results
+
+    def getBySourceAndLocation(self, sourcepackagerelease, archive,
+                               distroarchseries):
+        """See IBinaryPackageBuildSet."""
+        # First we try to follow any binaries built from the given source
+        # in a distroarchseries with the given architecturetag and published
+        # in the given (distroarchseries, archive) location.
+        # (Querying all architectures and then picking the right one out
+        # of the result turns out to be much faster than querying for
+        # just the architecture we want).
+        builds_by_arch = self._findBySourceAndLocation(
+            sourcepackagerelease, archive, distroarchseries.distroseries)
+        build = builds_by_arch.get(distroarchseries.architecturetag)
+        if build is not None:
+            # If there was any published binary we can use its original build.
+            # This case covers the situations when both source and binaries
+            # got copied from another location.
+            return build
+
+        # If there was no published binary we have to try to find a
+        # suitable build in all possible location across the distroseries
+        # inheritance tree. See below.
+        clause_tables = ['DistroArchSeries']
+        queries = [
+            "DistroArchSeries.id = BinaryPackageBuild.distro_arch_series AND "
+            "BinaryPackageBuild.archive = %s AND "
+            "DistroArchSeries.architecturetag = %s AND "
+            "BinaryPackageBuild.source_package_release = %s" % (
+            sqlvalues(
+                archive.id, distroarchseries.architecturetag,
+                sourcepackagerelease))]
+
+        # Query only the last build record for this sourcerelease
+        # across all possible locations.
+        query = " AND ".join(queries)
+
+        return BinaryPackageBuild.selectFirst(
+            query, clauseTables=clause_tables,
+            orderBy=['-date_created'])
+
     def getStatusSummaryForBuilds(self, builds):
         """See `IBinaryPackageBuildSet`."""
         # Create a small helper function to collect the builds for a given
@@ -1344,7 +1429,8 @@
         Return the just-created `IBinaryPackageBuild` record already
         scored or None if a suitable build is already present.
         """
-        build_candidate = sourcepackagerelease.getBuildByArch(arch, archive)
+        build_candidate = self.getBySourceAndLocation(
+            sourcepackagerelease, archive, arch)
 
         # Check DistroArchSeries database IDs because the object belongs
         # to different transactions (architecture_available is cached).

=== modified file 'lib/lp/soyuz/model/sourcepackagerelease.py'
--- lib/lp/soyuz/model/sourcepackagerelease.py	2014-10-31 08:47:29 +0000
+++ lib/lp/soyuz/model/sourcepackagerelease.py	2014-10-31 08:47:29 +0000
@@ -26,7 +26,6 @@
     StringCol,
     )
 from storm.expr import Join
-from storm.info import ClassAlias
 from storm.locals import (
     Desc,
     Int,
@@ -63,6 +62,7 @@
     )
 from lp.soyuz.enums import PackageDiffStatus
 from lp.soyuz.interfaces.archive import MAIN_ARCHIVE_PURPOSES
+from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
 from lp.soyuz.interfaces.packagediff import PackageDiffAlreadyRequested
 from lp.soyuz.interfaces.packagediffjob import IPackageDiffJobSource
 from lp.soyuz.interfaces.queue import QueueInconsistentStateError
@@ -296,88 +296,6 @@
         else:
             return 0.0
 
-    def findBuildsByArchitecture(self, distroseries, archive):
-        """Find associated builds, by architecture.
-
-        Looks for `BinaryPackageBuild` records for this source package
-        release, with publication records in the distroseries associated with
-        `distroarchseries`.  There should be at most one of these per
-        architecture.
-
-        :param distroarchseries: `DistroArchSeries` to look for.
-        :return: A dict mapping architecture tags (in string form,
-            e.g. 'i386') to `BinaryPackageBuild`s for that build.
-        """
-        # Avoid circular imports.
-        from lp.soyuz.model.binarypackagerelease import BinaryPackageRelease
-        from lp.soyuz.model.distroarchseries import DistroArchSeries
-        from lp.soyuz.model.publishing import BinaryPackagePublishingHistory
-
-        BuildDAS = ClassAlias(DistroArchSeries, 'BuildDAS')
-        PublishDAS = ClassAlias(DistroArchSeries, 'PublishDAS')
-
-        query = Store.of(self).find(
-            (BuildDAS.architecturetag, BinaryPackageBuild),
-            BinaryPackageBuild.source_package_release == self,
-            BinaryPackageRelease.buildID == BinaryPackageBuild.id,
-            BuildDAS.id == BinaryPackageBuild.distro_arch_series_id,
-            BinaryPackagePublishingHistory.binarypackagereleaseID ==
-                BinaryPackageRelease.id,
-            BinaryPackagePublishingHistory.archiveID == archive.id,
-            PublishDAS.id ==
-                BinaryPackagePublishingHistory.distroarchseriesID,
-            PublishDAS.distroseriesID == distroseries.id,
-            # Architecture-independent binary package releases are built
-            # in the nominated arch-indep architecture but published in
-            # all architectures.  This condition makes sure we consider
-            # only builds that have been published in their own
-            # architecture.
-            PublishDAS.architecturetag == BuildDAS.architecturetag)
-        results = list(query.config(distinct=True))
-        mapped_results = dict(results)
-        assert len(mapped_results) == len(results), (
-            "Found multiple build candidates per architecture: %s.  "
-            "This may mean that we have a serious problem in our DB model.  "
-            "Further investigation is required."
-            % [(tag, build.id) for tag, build in results])
-        return mapped_results
-
-    def getBuildByArch(self, distroarchseries, archive):
-        """See ISourcePackageRelease."""
-        # First we try to follow any binaries built from the given source
-        # in a distroarchseries with the given architecturetag and published
-        # in the given (distroarchseries, archive) location.
-        # (Querying all architectures and then picking the right one out
-        # of the result turns out to be much faster than querying for
-        # just the architecture we want).
-        builds_by_arch = self.findBuildsByArchitecture(
-            distroarchseries.distroseries, archive)
-        build = builds_by_arch.get(distroarchseries.architecturetag)
-        if build is not None:
-            # If there was any published binary we can use its original build.
-            # This case covers the situations when both source and binaries
-            # got copied from another location.
-            return build
-
-        # If there was no published binary we have to try to find a
-        # suitable build in all possible location across the distroseries
-        # inheritance tree. See below.
-        clause_tables = ['DistroArchSeries']
-        queries = [
-            "DistroArchSeries.id = BinaryPackageBuild.distro_arch_series AND "
-            "BinaryPackageBuild.archive = %s AND "
-            "DistroArchSeries.architecturetag = %s AND "
-            "BinaryPackageBuild.source_package_release = %s" % (
-            sqlvalues(archive.id, distroarchseries.architecturetag, self))]
-
-        # Query only the last build record for this sourcerelease
-        # across all possible locations.
-        query = " AND ".join(queries)
-
-        return BinaryPackageBuild.selectFirst(
-            query, clauseTables=clause_tables,
-            orderBy=['-date_created'])
-
     def override(self, component=None, section=None, urgency=None):
         """See ISourcePackageRelease."""
         if component is not None:

=== modified file 'lib/lp/soyuz/scripts/tests/test_add_missing_builds.py'
--- lib/lp/soyuz/scripts/tests/test_add_missing_builds.py	2013-05-31 05:47:53 +0000
+++ lib/lp/soyuz/scripts/tests/test_add_missing_builds.py	2014-10-31 08:47:29 +0000
@@ -7,6 +7,8 @@
 import subprocess
 import sys
 
+from zope.component import getUtility
+
 from lp.registry.interfaces.pocket import PackagePublishingPocket
 from lp.services.config import config
 from lp.services.database.sqlbase import (
@@ -18,6 +20,7 @@
     ArchivePurpose,
     PackagePublishingStatus,
     )
+from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
 from lp.soyuz.scripts.add_missing_builds import AddMissingBuilds
 from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
 from lp.testing import TestCaseWithFactory
@@ -78,14 +81,19 @@
 
     def getBuilds(self):
         """Helper to return build records."""
-        any_build_i386 = self.any.sourcepackagerelease.getBuildByArch(
-            self.stp.breezy_autotest_i386, self.ppa)
-        any_build_hppa = self.any.sourcepackagerelease.getBuildByArch(
-            self.stp.breezy_autotest_hppa, self.ppa)
-        all_build_i386 = self.all.sourcepackagerelease.getBuildByArch(
-            self.stp.breezy_autotest_i386, self.ppa)
-        all_build_hppa = self.all.sourcepackagerelease.getBuildByArch(
-            self.stp.breezy_autotest_hppa, self.ppa)
+        bpbs = getUtility(IBinaryPackageBuildSet)
+        any_build_i386 = bpbs.getBySourceAndLocation(
+            self.any.sourcepackagerelease, self.ppa,
+            self.stp.breezy_autotest_i386)
+        any_build_hppa = bpbs.getBySourceAndLocation(
+            self.any.sourcepackagerelease, self.ppa,
+            self.stp.breezy_autotest_hppa)
+        all_build_i386 = bpbs.getBySourceAndLocation(
+            self.all.sourcepackagerelease, self.ppa,
+            self.stp.breezy_autotest_i386)
+        all_build_hppa = bpbs.getBySourceAndLocation(
+            self.all.sourcepackagerelease, self.ppa,
+            self.stp.breezy_autotest_hppa)
         return (
             any_build_i386, any_build_hppa, all_build_i386, all_build_hppa)
 
@@ -142,10 +150,13 @@
         # The arch-all package is architecture-independent, so it will
         # only get a build for i386 which is the nominated architecture-
         # independent build arch.
-        all_build_i386 = self.all.sourcepackagerelease.getBuildByArch(
-            self.stp.breezy_autotest_i386, self.ppa)
-        all_build_hppa = self.all.sourcepackagerelease.getBuildByArch(
-            self.stp.breezy_autotest_hppa, self.ppa)
+        bpbs = getUtility(IBinaryPackageBuildSet)
+        all_build_i386 = bpbs.getBySourceAndLocation(
+            self.all.sourcepackagerelease, self.ppa,
+            self.stp.breezy_autotest_i386)
+        all_build_hppa = bpbs.getBySourceAndLocation(
+            self.all.sourcepackagerelease, self.ppa,
+            self.stp.breezy_autotest_hppa)
         self.assertIsNot(all_build_i386, None)
         self.assertIs(all_build_hppa, None)
 

=== modified file 'lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py'
--- lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py	2014-07-25 00:23:51 +0000
+++ lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py	2014-10-31 08:47:29 +0000
@@ -22,6 +22,7 @@
     SourcePackageFormat,
     )
 from lp.soyuz.interfaces.archivepermission import IArchivePermissionSet
+from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
 from lp.soyuz.interfaces.component import IComponentSet
 from lp.soyuz.interfaces.packageset import (
     IPackagesetSet,
@@ -596,11 +597,11 @@
         udev_src = udev_bin.build.source_package_release
         self.assertEqual(udev_src.title, u'udev - 0.1-1')
         # The build of udev 0.1-1 has been copied across.
-        child_udev = udev_src.getBuildByArch(
-            child[parent_das.architecturetag], child.main_archive)
-        parent_udev = udev_src.getBuildByArch(
-            parent[parent_das.architecturetag],
-            parent.main_archive)
+        bpbs = getUtility(IBinaryPackageBuildSet)
+        child_udev = bpbs.getBySourceAndLocation(
+            udev_src, child.main_archive, child[parent_das.architecturetag])
+        parent_udev = bpbs.getBySourceAndLocation(
+            udev_src, parent.main_archive, parent[parent_das.architecturetag])
         self.assertEqual(parent_udev.id, child_udev.id)
         # We also inherit the permitted source formats from our parent.
         self.assertTrue(

=== modified file 'lib/lp/soyuz/tests/test_build_set.py'
--- lib/lp/soyuz/tests/test_build_set.py	2014-10-31 03:12:58 +0000
+++ lib/lp/soyuz/tests/test_build_set.py	2014-10-31 08:47:29 +0000
@@ -9,13 +9,20 @@
 from lp.buildmaster.enums import BuildStatus
 from lp.registry.interfaces.person import IPersonSet
 from lp.registry.interfaces.pocket import PackagePublishingPocket
-from lp.soyuz.enums import ArchivePurpose
+from lp.soyuz.enums import (
+    ArchivePurpose,
+    SourcePackageFormat,
+    )
 from lp.soyuz.interfaces.archivearch import IArchiveArchSet
 from lp.soyuz.interfaces.binarypackagebuild import (
     BuildSetStatus,
     IBinaryPackageBuildSet,
     )
+from lp.soyuz.interfaces.sourcepackageformat import (
+    ISourcePackageFormatSelectionSet,
+    )
 from lp.soyuz.model.binarypackagebuild import BinaryPackageBuildSet
+from lp.soyuz.scripts.packagecopier import do_copy
 from lp.soyuz.tests.test_publishing import (
     SoyuzTestPublisher,
     TestNativePublishingBase,
@@ -24,7 +31,10 @@
     person_logged_in,
     TestCaseWithFactory,
     )
-from lp.testing.layers import LaunchpadFunctionalLayer
+from lp.testing.layers import (
+    LaunchpadFunctionalLayer,
+    ZopelessDatabaseLayer,
+    )
 from lp.testing.sampledata import ADMIN_EMAIL
 
 
@@ -306,3 +316,92 @@
         self.assertEqual(2, len(builds))
         self.assertEqual(self.avr_distroarch, builds[0].distro_arch_series)
         self.assertEqual(self.sparc_distroarch, builds[1].distro_arch_series)
+
+
+class TestFindBySourceAndLocation(TestCaseWithFactory):
+    """Tests for the _findBySourceAndLocation helper."""
+
+    layer = ZopelessDatabaseLayer
+
+    def test_finds_build_with_matching_pub(self):
+        # _findBySourceAndLocation finds builds for a source package
+        # release.  In particular, an arch-independent BPR is published in
+        # multiple architectures.  But findBuildsByArchitecture only counts
+        # the publication for the same architecture it was built in.
+        distroseries = self.factory.makeDistroSeries()
+        archive = distroseries.main_archive
+        # The series has a nominated arch-indep architecture.
+        distroseries.nominatedarchindep = self.factory.makeDistroArchSeries(
+            distroseries=distroseries)
+
+        bpb = self.factory.makeBinaryPackageBuild(
+            distroarchseries=distroseries.nominatedarchindep)
+        bpr = self.factory.makeBinaryPackageRelease(
+            build=bpb, architecturespecific=False)
+        spr = bpr.build.source_package_release
+
+        # The series also has other architectures.
+        self.factory.makeDistroArchSeries(distroseries=distroseries)
+
+        # makeBinaryPackagePublishingHistory will actually publish an
+        # arch-indep BPR everywhere.
+        self.factory.makeBinaryPackagePublishingHistory(
+            binarypackagerelease=bpr, archive=archive,
+            distroarchseries=distroseries.nominatedarchindep)
+
+        naked_spr = removeSecurityProxy(spr)
+        self.assertEqual(
+            {distroseries.nominatedarchindep.architecturetag: bpr.build},
+            BinaryPackageBuildSet()._findBySourceAndLocation(
+                naked_spr, archive, distroseries))
+
+
+class TestGetBySourceAndLocation(TestCaseWithFactory):
+    """Tests for BinaryPackageBuildSet.getBySourceAndLocation()."""
+
+    layer = ZopelessDatabaseLayer
+
+    def test_can_find_build_in_derived_distro_parent(self):
+        # If a derived distribution inherited its binaries from its
+        # parent then getBySourceAndLocation() should look in the parent
+        # to find the build.
+        dsp = self.factory.makeDistroSeriesParent()
+        parent_archive = dsp.parent_series.main_archive
+
+        # Create a built, published package in the parent archive.
+        spr = self.factory.makeSourcePackageRelease(
+            architecturehintlist='any')
+        parent_source_pub = self.factory.makeSourcePackagePublishingHistory(
+            sourcepackagerelease=spr, archive=parent_archive,
+            distroseries=dsp.parent_series)
+        das = self.factory.makeDistroArchSeries(
+            distroseries=dsp.parent_series, supports_virtualized=True)
+        orig_build = getUtility(IBinaryPackageBuildSet).new(
+            spr, parent_archive, das, PackagePublishingPocket.RELEASE,
+            status=BuildStatus.FULLYBUILT)
+        bpr = self.factory.makeBinaryPackageRelease(build=orig_build)
+        self.factory.makeBinaryPackagePublishingHistory(
+            binarypackagerelease=bpr, distroarchseries=das,
+            archive=parent_archive)
+
+        # Make an architecture in the derived series with the same
+        # archtag as the parent.
+        das_derived = self.factory.makeDistroArchSeries(
+            dsp.derived_series, architecturetag=das.architecturetag,
+            processor=das.processor, supports_virtualized=True)
+        # Now copy the package to the derived series, with binary.
+        derived_archive = dsp.derived_series.main_archive
+        getUtility(ISourcePackageFormatSelectionSet).add(
+            dsp.derived_series, SourcePackageFormat.FORMAT_1_0)
+
+        do_copy(
+            [parent_source_pub], derived_archive, dsp.derived_series,
+            PackagePublishingPocket.RELEASE, include_binaries=True,
+            check_permissions=False)
+
+        # Searching for the build in the derived series architecture
+        # should automatically pick it up from the parent.
+        found_build = getUtility(
+            IBinaryPackageBuildSet).getBySourceAndLocation(
+                spr, derived_archive, das_derived)
+        self.assertEqual(orig_build, found_build)

=== modified file 'lib/lp/soyuz/tests/test_sourcepackagerelease.py'
--- lib/lp/soyuz/tests/test_sourcepackagerelease.py	2014-10-31 08:47:29 +0000
+++ lib/lp/soyuz/tests/test_sourcepackagerelease.py	2014-10-31 08:47:29 +0000
@@ -20,14 +20,9 @@
 from lp.soyuz.enums import (
     ArchivePurpose,
     PackagePublishingStatus,
-    SourcePackageFormat,
     )
 from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
 from lp.soyuz.interfaces.publishing import active_publishing_status
-from lp.soyuz.interfaces.sourcepackageformat import (
-    ISourcePackageFormatSelectionSet,
-    )
-from lp.soyuz.scripts.packagecopier import do_copy
 from lp.testing import (
     TestCaseWithFactory,
     )
@@ -209,89 +204,3 @@
             [by_status[status] for status in active_publishing_status],
             spr.getActiveArchSpecificPublications(
                 bpphs[0].archive, bpphs[0].distroseries, bpphs[0].pocket))
-
-
-class TestSourcePackageReleaseGetBuildByArch(TestCaseWithFactory):
-    """Tests for SourcePackageRelease.getBuildByArch()."""
-
-    layer = ZopelessDatabaseLayer
-
-    def test_can_find_build_in_derived_distro_parent(self):
-        # If a derived distribution inherited its binaries from its
-        # parent then getBuildByArch() should look in the parent to find
-        # the build.
-        dsp = self.factory.makeDistroSeriesParent()
-        parent_archive = dsp.parent_series.main_archive
-
-        # Create a built, published package in the parent archive.
-        spr = self.factory.makeSourcePackageRelease(
-            architecturehintlist='any')
-        parent_source_pub = self.factory.makeSourcePackagePublishingHistory(
-            sourcepackagerelease=spr, archive=parent_archive,
-            distroseries=dsp.parent_series)
-        das = self.factory.makeDistroArchSeries(
-            distroseries=dsp.parent_series, supports_virtualized=True)
-        orig_build = getUtility(IBinaryPackageBuildSet).new(
-            spr, parent_archive, das, PackagePublishingPocket.RELEASE,
-            status=BuildStatus.FULLYBUILT)
-        bpr = self.factory.makeBinaryPackageRelease(build=orig_build)
-        self.factory.makeBinaryPackagePublishingHistory(
-            binarypackagerelease=bpr, distroarchseries=das,
-            archive=parent_archive)
-
-        # Make an architecture in the derived series with the same
-        # archtag as the parent.
-        das_derived = self.factory.makeDistroArchSeries(
-            dsp.derived_series, architecturetag=das.architecturetag,
-            processor=das.processor, supports_virtualized=True)
-        # Now copy the package to the derived series, with binary.
-        derived_archive = dsp.derived_series.main_archive
-        getUtility(ISourcePackageFormatSelectionSet).add(
-            dsp.derived_series, SourcePackageFormat.FORMAT_1_0)
-
-        do_copy(
-            [parent_source_pub], derived_archive, dsp.derived_series,
-            PackagePublishingPocket.RELEASE, include_binaries=True,
-            check_permissions=False)
-
-        # Searching for the build in the derived series architecture
-        # should automatically pick it up from the parent.
-        found_build = spr.getBuildByArch(das_derived, derived_archive)
-        self.assertEqual(orig_build, found_build)
-
-
-class TestFindBuildsByArchitecture(TestCaseWithFactory):
-    """Tests for SourcePackageRelease.findBuildsByArchitecture."""
-
-    layer = ZopelessDatabaseLayer
-
-    def test_finds_build_with_matching_pub(self):
-        # findBuildsByArchitecture finds builds for a source package
-        # release.  In particular, an arch-independent BPR is published in
-        # multiple architectures.  But findBuildsByArchitecture only counts
-        # the publication for the same architecture it was built in.
-        distroseries = self.factory.makeDistroSeries()
-        archive = distroseries.main_archive
-        # The series has a nominated arch-indep architecture.
-        distroseries.nominatedarchindep = self.factory.makeDistroArchSeries(
-            distroseries=distroseries)
-
-        bpb = self.factory.makeBinaryPackageBuild(
-            distroarchseries=distroseries.nominatedarchindep)
-        bpr = self.factory.makeBinaryPackageRelease(
-            build=bpb, architecturespecific=False)
-        spr = bpr.build.source_package_release
-
-        # The series also has other architectures.
-        self.factory.makeDistroArchSeries(distroseries=distroseries)
-
-        # makeBinaryPackagePublishingHistory will actually publish an
-        # arch-indep BPR everywhere.
-        self.factory.makeBinaryPackagePublishingHistory(
-            binarypackagerelease=bpr, archive=archive,
-            distroarchseries=distroseries.nominatedarchindep)
-
-        naked_spr = removeSecurityProxy(spr)
-        self.assertEqual(
-            {distroseries.nominatedarchindep.architecturetag: bpr.build},
-            naked_spr.findBuildsByArchitecture(distroseries, archive))


Follow ups