← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~stevenk/launchpad/moar-preload-distroseries-queue-redux into lp:launchpad

 

Steve Kowalik has proposed merging lp:~stevenk/launchpad/moar-preload-distroseries-queue-redux into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #835645 in Launchpad itself: "DistroSeries:+queue timeout paginating"
  https://bugs.launchpad.net/launchpad/+bug/835645
  Bug #1032176 in Launchpad itself: "DistroSeries.getPackageUploads timing out due to authorization checking "
  https://bugs.launchpad.net/launchpad/+bug/1032176

For more details, see:
https://code.launchpad.net/~stevenk/launchpad/moar-preload-distroseries-queue-redux/+merge/142056

Preload all the things for IPackageUploadSet.getAll().

Turn ISourcePackageRelease.package_diffs into a cachedproperty, invalidate it when requestDiffTo is called and set it inside the preloading magic for IPackageUploadSet.getAll().

Rip apart the preloading for SPRF and BPF to make use of load_referencing and load_related, which allows both I{Binary,SourcePackage}ReleaseFileSet and its tests to all be consigned to a watery grave.

Also rewrite one of the internal functions that crafted a dictionary of SPR ID to PUS to not make use of IPackageUpload.getSourceBySourcePackageReleaseIDs(), so delete that too, since not even tests made use of it.
-- 
https://code.launchpad.net/~stevenk/launchpad/moar-preload-distroseries-queue-redux/+merge/142056
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/moar-preload-distroseries-queue-redux into lp:launchpad.
=== modified file 'lib/lp/soyuz/browser/queue.py'
--- lib/lp/soyuz/browser/queue.py	2013-01-02 22:59:10 +0000
+++ lib/lp/soyuz/browser/queue.py	2013-01-08 02:19:46 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2012 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2013 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Browser views for package queue."""
@@ -27,6 +27,10 @@
     )
 from lp.services.job.model.job import Job
 from lp.services.librarian.browser import FileNavigationMixin
+from lp.services.librarian.model import (
+    LibraryFileAlias,
+    LibraryFileContent,
+    )
 from lp.services.webapp import (
     GetitemNavigation,
     LaunchpadView,
@@ -41,10 +45,6 @@
 from lp.soyuz.interfaces.archivepermission import IArchivePermissionSet
 from lp.soyuz.interfaces.binarypackagename import IBinaryPackageNameSet
 from lp.soyuz.interfaces.component import IComponentSet
-from lp.soyuz.interfaces.files import (
-    IBinaryPackageFileSet,
-    ISourcePackageReleaseFileSet,
-    )
 from lp.soyuz.interfaces.packageset import IPackagesetSet
 from lp.soyuz.interfaces.publishing import name_priority_map
 from lp.soyuz.interfaces.queue import (
@@ -55,10 +55,17 @@
     )
 from lp.soyuz.interfaces.section import ISectionSet
 from lp.soyuz.model.archive import Archive
-from lp.soyuz.model.component import Component
+from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild
+from lp.soyuz.model.binarypackagerelease import BinaryPackageRelease
+from lp.soyuz.model.files import (
+    BinaryPackageFile,
+    SourcePackageReleaseFile,
+    )
 from lp.soyuz.model.packagecopyjob import PackageCopyJob
-from lp.soyuz.model.queue import PackageUploadSource
-from lp.soyuz.model.section import Section
+from lp.soyuz.model.queue import (
+    PackageUploadBuild,
+    PackageUploadSource,
+    )
 from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease
 
 
@@ -152,22 +159,14 @@
             build_upload_files[upload_id].append(binary_file)
         return build_upload_files, binary_package_names
 
-    def source_dict(self, upload_ids, source_files):
+    def source_dict(self, puses):
         """Return a dictionary of PackageUploadSource keyed on SPR ID.
 
-        :param upload_ids: A list of PackageUpload IDs.
+        :param puses: A list of `PackageUploadSource`s.
         """
-        sourcepackagerelease_ids = [
-            source_file.sourcepackagerelease.id
-            for source_file in source_files]
-
-        upload_set = getUtility(IPackageUploadSet)
-        pkg_upload_sources = upload_set.getSourceBySourcePackageReleaseIDs(
-            sourcepackagerelease_ids)
         package_upload_source_dict = {}
-        for pkg_upload_source in pkg_upload_sources:
-            package_upload_source_dict[
-                pkg_upload_source.sourcepackagerelease.id] = pkg_upload_source
+        for pus in puses:
+            package_upload_source_dict[pus.sourcepackagereleaseID] = pus
         return package_upload_source_dict
 
     def source_files_dict(self, package_upload_source_dict, source_files):
@@ -226,19 +225,22 @@
             return None
 
         upload_ids = [upload.id for upload in uploads]
-        binary_file_set = getUtility(IBinaryPackageFileSet)
-        binary_files = list(binary_file_set.getByPackageUploadIDs(upload_ids))
-        binary_file_set.loadLibraryFiles(binary_files)
-        packageuploadsources = load_referencing(
+        puses = load_referencing(
             PackageUploadSource, uploads, ['packageuploadID'])
-        source_file_set = getUtility(ISourcePackageReleaseFileSet)
-        source_files = list(source_file_set.getByPackageUploadIDs(upload_ids))
+        pubs = load_referencing(
+            PackageUploadBuild, uploads, ['packageuploadID'])
+
         source_sprs = load_related(
-            SourcePackageRelease, packageuploadsources,
-            ['sourcepackagereleaseID'])
-
-        load_related(Section, source_sprs, ['sectionID'])
-        load_related(Component, source_sprs, ['componentID'])
+            SourcePackageRelease, puses, ['sourcepackagereleaseID'])
+        bpbs = load_related(BinaryPackageBuild, pubs, ['buildID'])
+        bprs = load_referencing(BinaryPackageRelease, bpbs, ['buildID'])
+        source_files = load_referencing(
+            SourcePackageReleaseFile, source_sprs, ['sourcepackagereleaseID'])
+        binary_files = load_referencing(
+            BinaryPackageFile, bprs, ['binarypackagereleaseID'])
+        file_lfas = load_related(
+            LibraryFileAlias, source_files + binary_files, ['libraryfileID'])
+        load_related(LibraryFileContent, file_lfas, ['contentID'])
 
         # Get a dictionary of lists of binary files keyed by upload ID.
         package_upload_builds_dict = self.builds_dict(upload_ids, binary_files)
@@ -247,8 +249,7 @@
             package_upload_builds_dict, binary_files)
 
         # Get a dictionary of lists of source files keyed by upload ID.
-        package_upload_source_dict = self.source_dict(
-            upload_ids, source_files)
+        package_upload_source_dict = self.source_dict(puses)
         source_upload_files = self.source_files_dict(
             package_upload_source_dict, source_files)
 

=== modified file 'lib/lp/soyuz/browser/tests/test_queue.py'
--- lib/lp/soyuz/browser/tests/test_queue.py	2013-01-02 22:59:10 +0000
+++ lib/lp/soyuz/browser/tests/test_queue.py	2013-01-08 02:19:46 +0000
@@ -1,4 +1,4 @@
-# Copyright 2010-2012 Canonical Ltd.  This software is licensed under the
+# Copyright 2010-2013 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Unit tests for QueueItemsView."""
@@ -368,20 +368,37 @@
     def test_query_count(self):
         login(ADMIN_EMAIL)
         uploads = []
+        sprs = []
         distroseries = self.factory.makeDistroSeries()
+        dsc = self.factory.makeLibraryFileAlias(filename='foo_0.1.dsc')
+        deb = self.factory.makeLibraryFileAlias(filename='foo.deb')
+        transaction.commit()
         for i in range(5):
             uploads.append(self.factory.makeSourcePackageUpload(distroseries))
+            sprs.append(uploads[-1].sources[0].sourcepackagerelease)
+            sprs[-1].addFile(dsc)
             uploads.append(self.factory.makeCustomPackageUpload(distroseries))
             uploads.append(self.factory.makeCopyJobPackageUpload(distroseries))
+        self.factory.makePackageset(
+            packages=(sprs[0].sourcepackagename, sprs[2].sourcepackagename,
+                sprs[4].sourcepackagename),
+            distroseries=distroseries)
+        self.factory.makePackageset(
+            packages=(sprs[1].sourcepackagename,), distroseries=distroseries)
+        self.factory.makePackageset(
+            packages=(sprs[3].sourcepackagename,), distroseries=distroseries)
+        for i in (0, 2, 3):
+            self.factory.makePackageDiff(to_source=sprs[i])
         for i in range(15):
             uploads.append(self.factory.makeBuildPackageUpload(distroseries))
+            uploads[-1].builds[0].build.binarypackages[0].addFile(deb)
         queue_admin = self.factory.makeArchiveAdmin(distroseries.main_archive)
         Store.of(uploads[0]).invalidate()
         with person_logged_in(queue_admin):
             with StormStatementRecorder() as recorder:
                 view = self.makeView(distroseries, queue_admin)
-                view()   
-        self.assertThat(recorder, HasQueryCount(Equals(52)))
+                view()
+        self.assertThat(recorder, HasQueryCount(Equals(56)))
 
 
 class TestCompletePackageUpload(TestCaseWithFactory):

=== modified file 'lib/lp/soyuz/configure.zcml'
--- lib/lp/soyuz/configure.zcml	2013-01-02 06:05:27 +0000
+++ lib/lp/soyuz/configure.zcml	2013-01-08 02:19:46 +0000
@@ -1,4 +1,4 @@
-<!-- Copyright 2009-2012 Canonical Ltd.  This software is licensed under the
+<!-- Copyright 2009-2013 Canonical Ltd.  This software is licensed under the
      GNU Affero General Public License version 3 (see the file LICENSE).
 -->
 
@@ -779,18 +779,6 @@
             permission="launchpad.Edit"
             set_schema="lp.soyuz.interfaces.files.IBinaryPackageFile"/>
     </class>
-    <securedutility
-        class="lp.soyuz.model.files.BinaryPackageFileSet"
-        provides="lp.soyuz.interfaces.files.IBinaryPackageFileSet">
-        <allow
-            interface="lp.soyuz.interfaces.files.IBinaryPackageFileSet"/>
-    </securedutility>
-    <securedutility
-        class="lp.soyuz.model.files.SourcePackageReleaseFileSet"
-        provides="lp.soyuz.interfaces.files.ISourcePackageReleaseFileSet">
-        <allow
-            interface="lp.soyuz.interfaces.files.ISourcePackageReleaseFileSet"/>
-    </securedutility>
 
     <!-- Packageset -->
 

=== modified file 'lib/lp/soyuz/doc/soyuz-files.txt'
--- lib/lp/soyuz/doc/soyuz-files.txt	2012-12-26 01:32:19 +0000
+++ lib/lp/soyuz/doc/soyuz-files.txt	2013-01-08 02:19:46 +0000
@@ -1,4 +1,5 @@
-= Soyuz Files =
+Soyuz Files
+===========
 
 Soyuz keeps a collection of source and binary packages classified as
 SourcePackageRelease and BinaryPackageRelease respectively, each of
@@ -10,20 +11,21 @@
 SourcePackageReleaseFile or BinaryPackageFile are available via the
 'files' attribute on its parent.
 
- >>> from zope.component import getUtility
- >>> from lp.testing import verifyObject
-
- >>> from lp.services.librarian.interfaces import ILibraryFileAlias
- >>> from lp.registry.interfaces.distribution import IDistributionSet
- >>> from lp.soyuz.interfaces.files import (
- ...     IBinaryPackageFile,
- ...     ISourcePackageReleaseFile,
- ...     )
-
- >>> warty = getUtility(IDistributionSet)['ubuntu']['warty']
-
-
-== Source Files ==
+    >>> from zope.component import getUtility
+    >>> from lp.testing import verifyObject
+
+    >>> from lp.services.librarian.interfaces import ILibraryFileAlias
+    >>> from lp.registry.interfaces.distribution import IDistributionSet
+    >>> from lp.soyuz.interfaces.files import (
+    ...     IBinaryPackageFile,
+    ...     ISourcePackageReleaseFile,
+    ...     )
+
+    >>> warty = getUtility(IDistributionSet)['ubuntu']['warty']
+
+
+Source Files
+------------
 
 An ISourcePackageRelease contains the file that make up the source
 package for that release:
@@ -33,118 +35,48 @@
      upstream source.
    * A '.dsc' package description file.
 
- >>> warty_firefox_srcpkg = warty.getSourcePackage(
- ...     'mozilla-firefox').currentrelease
-
- >>> srcfile = warty_firefox_srcpkg.files[0]
-
- >>> verifyObject(ISourcePackageReleaseFile, srcfile)
- True
-
- >>> verifyObject(ILibraryFileAlias, srcfile.libraryfile)
- True
-
- >>> srcfile.libraryfile.filename
- u'firefox_0.9.2.orig.tar.gz'
-
- >>> srcfile.libraryfile.http_url
- 'http://.../3/firefox_0.9.2.orig.tar.gz'
-
-
-== Binary Files ==
+    >>> warty_firefox_srcpkg = warty.getSourcePackage(
+    ...     'mozilla-firefox').currentrelease
+
+    >>> srcfile = warty_firefox_srcpkg.files[0]
+
+    >>> verifyObject(ISourcePackageReleaseFile, srcfile)
+    True
+
+    >>> verifyObject(ILibraryFileAlias, srcfile.libraryfile)
+    True
+
+    >>> srcfile.libraryfile.filename
+    u'firefox_0.9.2.orig.tar.gz'
+
+    >>> srcfile.libraryfile.http_url
+    'http://.../3/firefox_0.9.2.orig.tar.gz'
+
+
+Binary Files
+------------
 
 An IBinaryPackageRelease contains only one file which is the
 instalable debian-format file:
 
    * An '.deb'
 
- >>> warty_i386_pmount_binpkg = warty['i386'].getBinaryPackage(
- ...    'pmount')['2:1.9-1']
-
- >>> warty_i386_pmount_binpkg.name
- u'pmount'
-
- >>> debfile = warty_i386_pmount_binpkg.files[0]
-
- >>> verifyObject(IBinaryPackageFile, debfile)
- True
-
- >>> verifyObject(ILibraryFileAlias, debfile.libraryfile)
- True
-
- >>> debfile.libraryfile.filename
- u'pmount_1.9-1_all.deb'
-
- >>> debfile.libraryfile.http_url
- 'http://.../37/pmount_1.9-1_all.deb'
-
-
-== Utilities ==
-
-There is a utility class IBinaryPackageFileSet that will return
-BinaryPackageFile records.
-
-    >>> from lp.soyuz.interfaces.files import (
-    ...     IBinaryPackageFileSet)
-    >>> file_set = getUtility(IBinaryPackageFileSet)
-
-It only contains one method, getByPackageUploadIDs(), that will return
-all the BinaryPackageFiles that are associated with the supplied
-PackageUpload IDs.
-
-    >>> ids = (2,)
-    >>> binary_package_files = file_set.getByPackageUploadIDs(ids)
-    >>> for binary_package_file in binary_package_files:
-    ...     print binary_package_file.libraryfile.filename
-    pmount_1.0-1_all.deb
-
-Additional IDs may also be passed and if they don't have any
-BinaryPackageFiles they are ignored and don't affect the results.
-
-    >>> ids = (1,2,3,4,5)
-    >>> binary_package_files = file_set.getByPackageUploadIDs(ids)
-    >>> for binary_package_file in binary_package_files:
-    ...     print binary_package_file.libraryfile.filename
-    pmount_1.0-1_all.deb
-
-If no IDs or None is passed, an empty list is returned.
-
-    >>> file_set.getByPackageUploadIDs([])
-    []
-
-    >>> file_set.getByPackageUploadIDs(None)
-    []
-
-There is also a utility called SourcePackageReleaseFileSet which has the
-same method, getByPackageUploadIDs(), and performs the same function.
-
-    >>> import operator
-    >>> from lp.soyuz.interfaces.files import (
-    ...     ISourcePackageReleaseFileSet)
-    >>> source_file_set = getUtility(ISourcePackageReleaseFileSet)
-    >>> ids = (15,)
-    >>> source_files = source_file_set.getByPackageUploadIDs(ids)
-    >>> for source_file in sorted(source_files,
-    ...     key=operator.attrgetter('id')):
-    ...     print source_file.libraryfile.filename
-    firefox_0.9.2.orig.tar.gz
-    iceweasel-1.0.dsc
-
-As with the same method for binary files, it will ignore IDs for which
-there are no uploads:
-
-    >>> ids = (14, 15)
-    >>> source_files = source_file_set.getByPackageUploadIDs(ids)
-    >>> for source_file in sorted(source_files,
-    ...     key=operator.attrgetter('id')):
-    ...     print source_file.libraryfile.filename
-    firefox_0.9.2.orig.tar.gz
-    iceweasel-1.0.dsc
-
-If no IDs or None is passed, an empty list is returned.
-
-    >>> source_file_set.getByPackageUploadIDs([])
-    []
-
-    >>> source_file_set.getByPackageUploadIDs(None)
-    []
+    >>> warty_i386_pmount_binpkg = warty['i386'].getBinaryPackage(
+    ...    'pmount')['2:1.9-1']
+
+    >>> warty_i386_pmount_binpkg.name
+    u'pmount'
+
+    >>> debfile = warty_i386_pmount_binpkg.files[0]
+
+    >>> verifyObject(IBinaryPackageFile, debfile)
+    True
+
+    >>> verifyObject(ILibraryFileAlias, debfile.libraryfile)
+    True
+
+    >>> debfile.libraryfile.filename
+    u'pmount_1.9-1_all.deb'
+
+    >>> debfile.libraryfile.http_url
+    'http://.../37/pmount_1.9-1_all.deb'

=== modified file 'lib/lp/soyuz/interfaces/files.py'
--- lib/lp/soyuz/interfaces/files.py	2013-01-07 02:40:55 +0000
+++ lib/lp/soyuz/interfaces/files.py	2013-01-08 02:19:46 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2011 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2013 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Package file interfaces."""
@@ -7,9 +7,7 @@
 
 __all__ = [
     'IBinaryPackageFile',
-    'IBinaryPackageFileSet',
     'ISourcePackageReleaseFile',
-    'ISourcePackageReleaseFileSet',
     ]
 
 from lazr.restful.fields import Reference
@@ -48,21 +46,6 @@
             )
 
 
-class IBinaryPackageFileSet(Interface):
-    """The set of all `BinaryPackageFile`s."""
-
-    def getByPackageUploadIDs(package_upload_ids):
-        """Return `BinaryPackageFile`s for the `PackageUpload` IDs."""
-
-    def loadLibraryFiles(binary_files):
-        """Bulk-load Librarian files associated with `binary_files`.
-
-        This loads the `LibraryFileAlias` and `LibraryFileContent` for each
-        of `binary_files` into the ORM cache, and returns an iterable of
-        `LibraryFileAlias`.
-        """
-
-
 class ISourcePackageReleaseFile(Interface):
     """A source package release to librarian link record."""
 
@@ -93,10 +76,3 @@
             title=_('Whether this file is an original tarball'),
             required=True, readonly=False,
             )
-
-
-class ISourcePackageReleaseFileSet(Interface):
-    """The set of all `SourcePackageRelease`s."""
-
-    def getByPackageUploadIDs(package_upload_ids):
-        """Return `SourcePackageReleaseFile`s for the `PackageUpload` IDs."""

=== modified file 'lib/lp/soyuz/interfaces/queue.py'
--- lib/lp/soyuz/interfaces/queue.py	2012-12-10 06:27:12 +0000
+++ lib/lp/soyuz/interfaces/queue.py	2013-01-08 02:19:46 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2012 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2013 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Queue interfaces."""
@@ -775,9 +775,6 @@
     def getBuildByBuildIDs(build_ids):
         """Return `PackageUploadBuilds`s for the supplied build IDs."""
 
-    def getSourceBySourcePackageReleaseIDs(spr_ids):
-        """Return `PackageUploadSource`s for the sourcepackagerelease IDs."""
-
     def getByPackageCopyJobIDs(pcj_ids):
         """Return `PackageUpload`s using `PackageCopyJob`s.
 

=== modified file 'lib/lp/soyuz/model/files.py'
--- lib/lp/soyuz/model/files.py	2013-01-07 02:40:55 +0000
+++ lib/lp/soyuz/model/files.py	2013-01-08 02:19:46 +0000
@@ -1,10 +1,9 @@
-# Copyright 2009 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2013 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 __metaclass__ = type
 __all__ = [
     'BinaryPackageFile',
-    'BinaryPackageFileSet',
     'SourceFileMixin',
     'SourcePackageReleaseFile',
     ]
@@ -13,22 +12,12 @@
 from zope.interface import implements
 
 from lp.registry.interfaces.sourcepackage import SourcePackageFileType
-from lp.services.database.bulk import load_related
 from lp.services.database.enumcol import EnumCol
-from lp.services.database.sqlbase import (
-    SQLBase,
-    sqlvalues,
-    )
-from lp.services.librarian.model import (
-    LibraryFileAlias,
-    LibraryFileContent,
-    )
+from lp.services.database.sqlbase import SQLBase
 from lp.soyuz.enums import BinaryPackageFileType
 from lp.soyuz.interfaces.files import (
     IBinaryPackageFile,
-    IBinaryPackageFileSet,
     ISourcePackageReleaseFile,
-    ISourcePackageReleaseFileSet,
     )
 
 
@@ -46,33 +35,6 @@
                        schema=BinaryPackageFileType)
 
 
-class BinaryPackageFileSet:
-    """See `IBinaryPackageFileSet`."""
-    implements(IBinaryPackageFileSet)
-
-    def getByPackageUploadIDs(self, package_upload_ids):
-        """See `IBinaryPackageFileSet`."""
-        if package_upload_ids is None or len(package_upload_ids) == 0:
-            return []
-        return BinaryPackageFile.select("""
-            PackageUploadBuild.packageupload = PackageUpload.id AND
-            PackageUpload.id IN %s AND
-            BinaryPackageBuild.id = PackageUploadBuild.build AND
-            BinaryPackageRelease.build = BinaryPackageBuild.id AND
-            BinaryPackageFile.binarypackagerelease = BinaryPackageRelease.id
-            """ % sqlvalues(package_upload_ids),
-            clauseTables=["PackageUpload", "PackageUploadBuild",
-                          "BinaryPackageBuild", "BinaryPackageRelease"],
-            prejoins=["binarypackagerelease", "binarypackagerelease.build",
-                      "binarypackagerelease.binarypackagename"])
-
-    def loadLibraryFiles(self, binary_files):
-        """See `IBinaryPackageFileSet`."""
-        lfas = load_related(LibraryFileAlias, binary_files, ['libraryfileID'])
-        load_related(LibraryFileContent, lfas, ['contentID'])
-        return lfas
-
-
 class SourceFileMixin:
     """Mix-in class for common functionality between source file classes."""
 
@@ -94,23 +56,3 @@
     libraryfile = ForeignKey(foreignKey='LibraryFileAlias',
                              dbName='libraryfile')
     filetype = EnumCol(schema=SourcePackageFileType)
-
-
-class SourcePackageReleaseFileSet:
-    """See `ISourcePackageReleaseFileSet`."""
-    implements(ISourcePackageReleaseFileSet)
-
-    def getByPackageUploadIDs(self, package_upload_ids):
-        """See `ISourcePackageReleaseFileSet`."""
-        if package_upload_ids is None or len(package_upload_ids) == 0:
-            return []
-        return SourcePackageReleaseFile.select("""
-            PackageUploadSource.packageupload = PackageUpload.id AND
-            PackageUpload.id IN %s AND
-            SourcePackageReleaseFile.sourcepackagerelease =
-                PackageUploadSource.sourcepackagerelease
-            """ % sqlvalues(package_upload_ids),
-            clauseTables=["PackageUpload", "PackageUploadSource"],
-            prejoins=["libraryfile", "libraryfile.content",
-                      "sourcepackagerelease",
-                      "sourcepackagerelease.sourcepackagename"])

=== modified file 'lib/lp/soyuz/model/queue.py'
--- lib/lp/soyuz/model/queue.py	2013-01-02 22:59:10 +0000
+++ lib/lp/soyuz/model/queue.py	2013-01-08 02:19:46 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2012 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2013 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 __metaclass__ = type
@@ -48,6 +48,7 @@
 from lp.archivepublisher.customupload import CustomUploadError
 from lp.archivepublisher.debversion import Version
 from lp.archiveuploader.tagfiles import parse_tagfile_content
+from lp.buildmaster.model.packagebuild import PackageBuild
 from lp.registry.interfaces.pocket import PackagePublishingPocket
 from lp.registry.model.sourcepackagename import SourcePackageName
 from lp.services.auditor.client import AuditorClient
@@ -75,7 +76,10 @@
 from lp.services.features import getFeatureFlag
 from lp.services.librarian.browser import ProxiedLibraryFileAlias
 from lp.services.librarian.interfaces.client import DownloadFailed
-from lp.services.librarian.model import LibraryFileAlias
+from lp.services.librarian.model import (
+    LibraryFileAlias,
+    LibraryFileContent,
+    )
 from lp.services.librarian.utils import copy_and_close
 from lp.services.mail.signedmessage import strip_pgp_signature
 from lp.services.propertycache import (
@@ -96,6 +100,7 @@
 from lp.soyuz.interfaces.archivepermission import IArchivePermissionSet
 from lp.soyuz.interfaces.component import IComponentSet
 from lp.soyuz.interfaces.packagecopyjob import IPackageCopyJobSource
+from lp.soyuz.interfaces.packagediff import IPackageDiffSet
 from lp.soyuz.interfaces.publishing import (
     IPublishingSet,
     name_priority_map,
@@ -115,7 +120,11 @@
     QueueStateWriteProtectedError,
     )
 from lp.soyuz.interfaces.section import ISectionSet
+from lp.soyuz.model.binarypackagename import BinaryPackageName
+from lp.soyuz.model.binarypackagerelease import BinaryPackageRelease
+from lp.soyuz.model.component import Component
 from lp.soyuz.model.distroarchseries import DistroArchSeries
+from lp.soyuz.model.section import Section
 from lp.soyuz.pas import BuildDaemonPackagesArchSpecific
 
 # There are imports below in PackageUploadCustom for various bits
@@ -1683,17 +1692,8 @@
         """See `IPackageUploadSet`."""
         if build_ids is None or len(build_ids) == 0:
             return []
-        return PackageUploadBuild.select("""
-            PackageUploadBuild.build IN %s
-            """ % sqlvalues(build_ids))
-
-    def getSourceBySourcePackageReleaseIDs(self, spr_ids):
-        """See `IPackageUploadSet`."""
-        if spr_ids is None or len(spr_ids) == 0:
-            return []
-        return PackageUploadSource.select("""
-            PackageUploadSource.sourcepackagerelease IN %s
-            """ % sqlvalues(spr_ids))
+        return PackageUploadBuild.select(
+            "PackageUploadBuild.build IN %s" % sqlvalues(build_ids))
 
     def getByPackageCopyJobIDs(self, pcj_ids):
         """See `IPackageUploadSet`."""
@@ -1728,18 +1728,32 @@
     source_sprs = load_related(
         SourcePackageRelease, puses, ['sourcepackagereleaseID'])
     bpbs = load_related(BinaryPackageBuild, pubs, ['buildID'])
+    load_related(PackageBuild, bpbs, ['package_build_id'])
     load_related(DistroArchSeries, bpbs, ['distro_arch_series_id'])
     binary_sprs = load_related(
         SourcePackageRelease, bpbs, ['source_package_release_id'])
+    bprs = load_referencing(BinaryPackageRelease, bpbs, ['buildID'])
+    load_related(BinaryPackageName, bprs, ['binarypackagenameID'])
     sprs = source_sprs + binary_sprs
 
     load_related(SourcePackageName, sprs, ['sourcepackagenameID'])
+    load_related(Section, sprs + bprs, ['sectionID'])
+    load_related(Component, sprs, ['componentID'])
     load_related(LibraryFileAlias, uploads, ['changes_file_id'])
     publications = load_referencing(
         SourcePackagePublishingHistory, sprs, ['sourcepackagereleaseID'])
     load_related(Archive, publications, ['archiveID'])
+    diffs = getUtility(IPackageDiffSet).getDiffsToReleases(
+        sprs, preload_for_display=True)
+
+    puc_lfas = load_related(LibraryFileAlias, pucs, ['libraryfilealiasID'])
+    load_related(LibraryFileContent, puc_lfas, ['contentID'])
+
     for spr_cache in sprs:
         get_property_cache(spr_cache).published_archives = []
+        get_property_cache(spr_cache).package_diffs = []
     for publication in publications:
         spr_cache = get_property_cache(publication.sourcepackagerelease)
         spr_cache.published_archives.append(publication.archive)
+    for diff in diffs:
+        get_property_cache(diff.to_source).package_diffs.append(diff)

=== modified file 'lib/lp/soyuz/model/sourcepackagerelease.py'
--- lib/lp/soyuz/model/sourcepackagerelease.py	2013-01-02 22:59:10 +0000
+++ lib/lp/soyuz/model/sourcepackagerelease.py	2013-01-08 02:19:46 +0000
@@ -30,6 +30,7 @@
 from storm.info import ClassAlias
 from storm.locals import (
     Int,
+    Desc,
     Reference,
     )
 from storm.store import Store
@@ -59,7 +60,10 @@
     LibraryFileAlias,
     LibraryFileContent,
     )
-from lp.services.propertycache import cachedproperty
+from lp.services.propertycache import (
+    cachedproperty,
+    get_property_cache,
+    )
 from lp.soyuz.enums import PackageDiffStatus
 from lp.soyuz.interfaces.archive import MAIN_ARCHIVE_PURPOSES
 from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
@@ -165,8 +169,6 @@
         joinColumn='sourcepackagerelease', orderBy="libraryfile")
     publishings = SQLMultipleJoin('SourcePackagePublishingHistory',
         joinColumn='sourcepackagerelease', orderBy="-datecreated")
-    package_diffs = SQLMultipleJoin(
-        'PackageDiff', joinColumn='to_source', orderBy="-date_requested")
 
     _user_defined_fields = StringCol(dbName='user_defined_fields')
 
@@ -209,6 +211,12 @@
             return []
         return simplejson.loads(self._user_defined_fields)
 
+    @cachedproperty
+    def package_diffs(self):
+        return list(Store.of(self).find(
+            PackageDiff, to_source=self).order_by(
+                Desc(PackageDiff.date_requested)))
+
     @property
     def builds(self):
         """See `ISourcePackageRelease`."""
@@ -584,6 +592,8 @@
         else:
             status = PackageDiffStatus.PENDING
 
+        Store.of(to_sourcepackagerelease).flush()
+        del get_property_cache(to_sourcepackagerelease).package_diffs
         return PackageDiff(
             from_source=self, to_source=to_sourcepackagerelease,
             requester=requester, status=status)

=== removed file 'lib/lp/soyuz/tests/test_binarypackagefile.py'
--- lib/lp/soyuz/tests/test_binarypackagefile.py	2012-01-01 02:58:52 +0000
+++ lib/lp/soyuz/tests/test_binarypackagefile.py	1970-01-01 00:00:00 +0000
@@ -1,26 +0,0 @@
-# Copyright 2011 Canonical Ltd.  This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Unit tests for `IBinaryPackageFile` and `IBinaryPackageFileSet`."""
-
-__metaclass__ = type
-
-from zope.component import getUtility
-
-from lp.soyuz.interfaces.files import IBinaryPackageFileSet
-from lp.testing import TestCaseWithFactory
-from lp.testing.layers import LaunchpadZopelessLayer
-from lp.testing.matchers import Provides
-
-
-class TestBinaryPackageFileSet(TestCaseWithFactory):
-    layer = LaunchpadZopelessLayer
-
-    def test_implements_interface(self):
-        file_set = getUtility(IBinaryPackageFileSet)
-        self.assertThat(file_set, Provides(IBinaryPackageFileSet))
-
-    def test_loadLibraryFiles_returns_associated_lfas(self):
-        bpf = self.factory.makeBinaryPackageFile()
-        lfas = getUtility(IBinaryPackageFileSet).loadLibraryFiles([bpf])
-        self.assertContentEqual([bpf.libraryfile], lfas)

=== modified file 'lib/lp/soyuz/tests/test_packageupload.py'
--- lib/lp/soyuz/tests/test_packageupload.py	2013-01-02 06:26:34 +0000
+++ lib/lp/soyuz/tests/test_packageupload.py	2013-01-08 02:19:46 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2012 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2013 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Test Build features."""
@@ -1304,4 +1304,4 @@
         IStore(uploads[0].__class__).invalidate()
         with StormStatementRecorder() as recorder:
             ws_distroseries.getPackageUploads()
-        self.assertThat(recorder, HasQueryCount(Equals(27)))
+        self.assertThat(recorder, HasQueryCount(Equals(33)))