← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/refactor-publishing-methods into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/refactor-publishing-methods into lp:launchpad.

Commit message:
Move some publishing methods out of the DistroSeries/DistroArchSeries model code and into archivepublisher.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/refactor-publishing-methods/+merge/226050

Move some publishing methods out of the DistroSeries/DistroArchSeries model code and into archivepublisher.  This gets code out of the webapp that doesn't need to be there, and it will make it much easier to make a follow-up change to optimise the queries performed by phase A of the publisher; as it is, it's difficult to query all the pending publications at once because the queries are hidden behind separate method calls.

ICanPublishPackages is no longer needed, and vanishes.
-- 
https://code.launchpad.net/~cjwatson/launchpad/refactor-publishing-methods/+merge/226050
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/refactor-publishing-methods into lp:launchpad.
=== modified file 'lib/lp/archivepublisher/publishing.py'
--- lib/lp/archivepublisher/publishing.py	2014-07-07 07:36:54 +0000
+++ lib/lp/archivepublisher/publishing.py	2014-07-08 23:16:10 +0000
@@ -292,12 +292,137 @@
             # provide custom builds for users who haven't upgraded yet.
             return self.distro.series
 
+    def checkLegalPocket(self, distroseries, publication, is_careful):
+        """Check if the publication can happen in the archive."""
+        # 'careful' mode re-publishes everything:
+        if is_careful:
+            return True
+
+        if not publication.archive.canModifySuite(
+                distroseries, publication.pocket):
+            self.log.error(
+                "Tried to publish %s (%s) into the %s pocket on series %s "
+                "(%s), skipping" % (
+                    publication.displayname, publication.id,
+                    publication.pocket, distroseries.displayname,
+                    distroseries.status.name))
+            return False
+
+        return True
+
+    def getPendingSourcePublications(self, distroseries, pocket, is_careful):
+        """Return the specific group of source records to be published.
+
+        If the distroseries is already released, it automatically refuses
+        to publish records to the RELEASE pocket.
+        """
+        queries = ['distroseries = %s' % sqlvalues(distroseries)]
+
+        # Query main archive for this distroseries
+        queries.append('archive=%s' % sqlvalues(self.archive))
+
+        # Careful publishing should include all PUBLISHED rows, normal run
+        # only includes PENDING ones.
+        statuses = [PackagePublishingStatus.PENDING]
+        if is_careful:
+            statuses.append(PackagePublishingStatus.PUBLISHED)
+        queries.append('status IN %s' % sqlvalues(statuses))
+
+        # Restrict to a specific pocket.
+        queries.append('pocket = %s' % sqlvalues(pocket))
+
+        # Exclude RELEASE pocket if the distroseries was already released,
+        # since it should not change for main archive.
+        # We allow RELEASE publishing for PPAs.
+        # We also allow RELEASE publishing for partner.
+        if (not distroseries.isUnstable() and
+            not self.archive.allowUpdatesToReleasePocket()):
+            queries.append(
+            'pocket != %s' % sqlvalues(PackagePublishingPocket.RELEASE))
+
+        publications = SourcePackagePublishingHistory.select(
+            " AND ".join(queries), orderBy="-id")
+
+        return publications
+
+    def publishSources(self, distroseries, pocket, is_careful=False):
+        """Publish sources for a given distroseries and pocket.
+
+        :param is_careful: If True, republish all published records (system
+            will DTRT checking the hash of all published files).
+
+        Consider records returned by getPendingSourcePublications.
+        """
+        self.log.debug("Publishing %s-%s" % (distroseries.title, pocket.name))
+        self.log.debug("Attempting to publish pending sources.")
+
+        dirty_pockets = set()
+        for spph in self.getPendingSourcePublications(
+                distroseries, pocket, is_careful):
+            if not self.checkLegalPocket(distroseries, spph, is_careful):
+                continue
+            spph.publish(self._diskpool, self.log)
+            dirty_pockets.add((distroseries.name, spph.pocket))
+        return dirty_pockets
+
+    def getPendingBinaryPublications(self, distroarchseries, pocket,
+                                     is_careful):
+        """Return the specific group of binary records to be published.
+
+        If the distroseries is already released, it automatically refuses
+        to publish records to the RELEASE pocket.
+        """
+        queries = [
+            "distroarchseries = %s AND archive = %s"
+            % sqlvalues(distroarchseries, self.archive)
+            ]
+
+        target_status = [PackagePublishingStatus.PENDING]
+        if is_careful:
+            target_status.append(PackagePublishingStatus.PUBLISHED)
+        queries.append("status IN %s" % sqlvalues(target_status))
+
+        # restrict to a specific pocket.
+        queries.append('pocket = %s' % sqlvalues(pocket))
+
+        # Exclude RELEASE pocket if the distroseries was already released,
+        # since it should not change, unless the archive allows it.
+        if (not distroarchseries.distroseries.isUnstable() and
+            not self.archive.allowUpdatesToReleasePocket()):
+            queries.append(
+            'pocket != %s' % sqlvalues(PackagePublishingPocket.RELEASE))
+
+        publications = BinaryPackagePublishingHistory.select(
+                    " AND ".join(queries), orderBy=["-id"])
+
+        return publications
+
+    def publishBinaries(self, distroarchseries, pocket, is_careful=False):
+        """Publish binaries for a given distroseries and pocket.
+
+        :param is_careful: If True, republish all published records (system
+            will DTRT checking the hash of all published files).
+
+        Consider records returned by getPendingSourcePublications.
+        """
+        self.log.debug("Attempting to publish pending binaries for %s"
+              % distroarchseries.architecturetag)
+
+        distroseries = distroarchseries.distroseries
+        dirty_pockets = set()
+        for bpph in self.getPendingBinaryPublications(
+                distroarchseries, pocket, is_careful):
+            if not self.checkLegalPocket(distroseries, bpph, is_careful):
+                continue
+            bpph.publish(self._diskpool, self.log)
+            dirty_pockets.add((distroseries.name, bpph.pocket))
+        return dirty_pockets
+
     def A_publish(self, force_publishing):
         """First step in publishing: actual package publishing.
 
-        Asks each DistroSeries to publish itself, which causes
-        publishing records to be updated, and files to be placed on disk
-        where necessary.
+        Publish each DistroSeries, which causes publishing records to be
+        updated, and files to be placed on disk where necessary.
         If self.allowed_suites is set, restrict the publication procedure
         to them.
         """
@@ -306,12 +431,12 @@
         for distroseries in self.consider_series:
             for pocket in self.archive.getPockets():
                 if self.isAllowed(distroseries, pocket):
-                    more_dirt = distroseries.publish(
-                        self._diskpool, self.log, self.archive, pocket,
-                        is_careful=force_publishing)
-
-                    self.dirty_pockets.update(more_dirt)
-
+                    self.dirty_pockets.update(self.publishSources(
+                        distroseries, pocket, is_careful=force_publishing))
+                    for distroarchseries in distroseries.architectures:
+                        self.dirty_pockets.update(self.publishBinaries(
+                            distroarchseries, pocket,
+                            is_careful=force_publishing))
                 else:
                     self.log.debug(
                         "* Skipping %s/%s", distroseries.name, pocket.name)

=== modified file 'lib/lp/archivepublisher/tests/test_publisher.py'
--- lib/lp/archivepublisher/tests/test_publisher.py	2014-07-07 07:36:54 +0000
+++ lib/lp/archivepublisher/tests/test_publisher.py	2014-07-08 23:16:10 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2013 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2014 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Tests for publisher class."""
@@ -54,6 +54,7 @@
     ArchiveStatus,
     BinaryPackageFormat,
     PackagePublishingStatus,
+    PackageUploadStatus,
     )
 from lp.soyuz.interfaces.archive import IArchiveSet
 from lp.soyuz.tests.test_publishing import TestNativePublishingBase
@@ -86,6 +87,463 @@
         self.ubuntu = getUtility(IDistributionSet)['ubuntu']
 
 
+class TestPublisherSeries(TestNativePublishingBase):
+    """Test the `Publisher` methods that publish individual series."""
+
+    def setUp(self):
+        super(TestPublisherSeries, self).setUp()
+        self.publisher = None
+
+    def _createLinkedPublication(self, name, pocket):
+        """Return a linked pair of source and binary publications."""
+        pub_source = self.getPubSource(
+            sourcename=name, filecontent="Hello", pocket=pocket)
+
+        binaryname = '%s-bin' % name
+        pub_bin = self.getPubBinaries(
+            binaryname=binaryname, filecontent="World",
+            pub_source=pub_source, pocket=pocket)[0]
+
+        return (pub_source, pub_bin)
+
+    def _createDefaultSourcePublications(self):
+        """Create and return default source publications.
+
+        See `TestNativePublishingBase.getPubSource` for more information.
+
+        It creates the following publications in breezy-autotest context:
+
+         * a PENDING publication for RELEASE pocket;
+         * a PUBLISHED publication for RELEASE pocket;
+         * a PENDING publication for UPDATES pocket;
+
+        Returns the respective ISPPH objects as a tuple.
+        """
+        pub_pending_release = self.getPubSource(
+            sourcename='first',
+            status=PackagePublishingStatus.PENDING,
+            pocket=PackagePublishingPocket.RELEASE)
+
+        pub_published_release = self.getPubSource(
+            sourcename='second',
+            status=PackagePublishingStatus.PUBLISHED,
+            pocket=PackagePublishingPocket.RELEASE)
+
+        pub_pending_updates = self.getPubSource(
+            sourcename='third',
+            status=PackagePublishingStatus.PENDING,
+            pocket=PackagePublishingPocket.UPDATES)
+
+        return (pub_pending_release, pub_published_release,
+                pub_pending_updates)
+
+    def _createDefaultBinaryPublications(self):
+        """Create and return default binary publications.
+
+        See `TestNativePublishingBase.getPubBinaries` for more information.
+
+        It creates the following publications in breezy-autotest context:
+
+         * a PENDING publication for RELEASE pocket;
+         * a PUBLISHED publication for RELEASE pocket;
+         * a PENDING publication for UPDATES pocket;
+
+        Returns the respective IBPPH objects as a tuple.
+        """
+        pub_pending_release = self.getPubBinaries(
+            binaryname='first',
+            status=PackagePublishingStatus.PENDING,
+            pocket=PackagePublishingPocket.RELEASE)[0]
+
+        pub_published_release = self.getPubBinaries(
+            binaryname='second',
+            status=PackagePublishingStatus.PUBLISHED,
+            pocket=PackagePublishingPocket.RELEASE)[0]
+
+        pub_pending_updates = self.getPubBinaries(
+            binaryname='third',
+            status=PackagePublishingStatus.PENDING,
+            pocket=PackagePublishingPocket.UPDATES)[0]
+
+        return (pub_pending_release, pub_published_release,
+                pub_pending_updates)
+
+    def _ensurePublisher(self):
+        """Create self.publisher if needed."""
+        if self.publisher is None:
+            self.publisher = Publisher(
+                self.logger, self.config, self.disk_pool,
+                self.breezy_autotest.main_archive)
+
+    def _publish(self, pocket, is_careful=False):
+        """Publish the test IDistroSeries and its IDistroArchSeries."""
+        self._ensurePublisher()
+        self.publisher.publishSources(
+            self.breezy_autotest, pocket, is_careful=is_careful)
+        for distroarchseries in self.breezy_autotest.architectures:
+            self.publisher.publishBinaries(
+                distroarchseries, pocket, is_careful=is_careful)
+        self.layer.txn.commit()
+
+    def checkPublicationsAreConsidered(self, pocket):
+        """Check if publications are considered for a given pocket.
+
+        Source and Binary publications to the given pocket get PUBLISHED in
+        database and on disk.
+        """
+        pub_source, pub_bin = self._createLinkedPublication(
+            name='foo', pocket=pocket)
+        self._publish(pocket=pocket)
+
+        # source and binary PUBLISHED in database.
+        pub_source.sync()
+        pub_bin.sync()
+        self.assertEqual(pub_source.status, PackagePublishingStatus.PUBLISHED)
+        self.assertEqual(pub_bin.status, PackagePublishingStatus.PUBLISHED)
+
+        # source and binary PUBLISHED on disk.
+        foo_dsc = "%s/main/f/foo/foo_666.dsc" % self.pool_dir
+        self.assertEqual(open(foo_dsc).read().strip(), 'Hello')
+        foo_deb = "%s/main/f/foo/foo-bin_666_all.deb" % self.pool_dir
+        self.assertEqual(open(foo_deb).read().strip(), 'World')
+
+    def checkPublicationsAreIgnored(self, pocket):
+        """Check if publications are ignored for a given pocket.
+
+        Source and Binary publications to the given pocket are still PENDING
+        in database.
+        """
+        pub_source, pub_bin = self._createLinkedPublication(
+            name='bar', pocket=pocket)
+        self._publish(pocket=pocket)
+
+        # The publications to pocket were ignored.
+        self.assertEqual(pub_source.status, PackagePublishingStatus.PENDING)
+        self.assertEqual(pub_bin.status, PackagePublishingStatus.PENDING)
+
+    def checkSourceLookupForPocket(self, pocket, expected_result,
+                                   is_careful=False):
+        """Check the results of an IDistroSeries publishing lookup."""
+        self._ensurePublisher()
+        pub_records = self.publisher.getPendingSourcePublications(
+            self.breezy_autotest, pocket, is_careful=is_careful)
+
+        self.assertEqual(pub_records.count(), len(expected_result))
+        self.assertEqual(
+            [item.id for item in expected_result],
+            [pub.id for pub in pub_records])
+
+    def checkBinaryLookupForPocket(self, pocket, expected_result,
+                                   is_careful=False):
+        """Check the results of an IDistroArchSeries publishing lookup."""
+        self._ensurePublisher()
+        pub_records = self.publisher.getPendingBinaryPublications(
+            self.breezy_autotest_i386, pocket, is_careful=is_careful)
+
+        self.assertEqual(pub_records.count(), len(expected_result))
+        self.assertEqual(
+            [item.id for item in expected_result],
+            [pub.id for pub in pub_records])
+
+    def testPublishUnstableDistroSeries(self):
+        """Top level publication for IDistroSeries in 'unstable' states.
+
+        Publications to RELEASE pocket are considered.
+        Publication to UPDATES pocket (post-release pockets) are ignored
+        """
+        self.assertEqual(
+            self.breezy_autotest.status, SeriesStatus.EXPERIMENTAL)
+        self.assertEqual(self.breezy_autotest.isUnstable(), True)
+        self.checkPublicationsAreConsidered(PackagePublishingPocket.RELEASE)
+        self.checkPublicationsAreIgnored(PackagePublishingPocket.UPDATES)
+
+    def testPublishStableDistroSeries(self):
+        """Top level publication for IDistroSeries in 'stable' states.
+
+        Publications to RELEASE pocket are ignored.
+        Publications to UPDATES pocket are considered.
+        """
+        # Release ubuntu/breezy-autotest.
+        self.breezy_autotest.status = SeriesStatus.CURRENT
+        self.layer.commit()
+
+        self.assertEqual(
+            self.breezy_autotest.status, SeriesStatus.CURRENT)
+        self.assertEqual(self.breezy_autotest.isUnstable(), False)
+        self.checkPublicationsAreConsidered(PackagePublishingPocket.UPDATES)
+        self.checkPublicationsAreIgnored(PackagePublishingPocket.RELEASE)
+
+    def testPublishFrozenDistroSeries(self):
+        """Top level publication for IDistroSeries in FROZEN state.
+
+        Publications to both, RELEASE and UPDATES, pockets are considered.
+        """
+        # Release ubuntu/breezy-autotest.
+        self.breezy_autotest.status = SeriesStatus.FROZEN
+        self.layer.commit()
+
+        self.assertEqual(
+            self.breezy_autotest.status, SeriesStatus.FROZEN)
+        self.assertEqual(
+            self.breezy_autotest.isUnstable(), True)
+        self.checkPublicationsAreConsidered(PackagePublishingPocket.UPDATES)
+        self.checkPublicationsAreConsidered(PackagePublishingPocket.RELEASE)
+
+    def testPublicationLookUpForUnstableDistroSeries(self):
+        """Source publishing record lookup for a unstable DistroSeries.
+
+        Check if Publisher.getPendingSourcePublications() works properly for
+        a DistroSeries when it is still in development, 'unreleased'.
+        """
+        pub_pending_release, pub_published_release, pub_pending_updates = (
+            self._createDefaultSourcePublications())
+
+        # Usual publication procedure for a distroseries in development
+        # state only 'pending' publishing records for pocket RELEASE
+        # are published.
+        self.checkSourceLookupForPocket(
+            PackagePublishingPocket.RELEASE,
+            expected_result=[pub_pending_release])
+
+        # This step is unusual but checks if the pocket restriction also
+        # work for other pockets than the RELEASE.
+        self.checkSourceLookupForPocket(
+            PackagePublishingPocket.UPDATES,
+            expected_result=[pub_pending_updates])
+
+        # Restricting to a pocket with no publication returns an
+        # empty SQLResult.
+        self.checkSourceLookupForPocket(
+            PackagePublishingPocket.BACKPORTS, expected_result=[])
+
+        # Using the 'careful' mode results in the consideration
+        # of every 'pending' and 'published' records present in
+        # the given pocket. The order is also important, NEWER first.
+        self.checkSourceLookupForPocket(
+            PackagePublishingPocket.RELEASE, is_careful=True,
+            expected_result=[pub_published_release, pub_pending_release])
+
+    def testPublicationLookUpForStableDistroSeries(self):
+        """Source publishing record lookup for a stable/released DistroSeries.
+
+        Check if Publisher.getPendingSourcePublications() works properly for
+        a DistroSeries when it is not in development anymore, i.e.,
+        'released'.
+        """
+        pub_pending_release, pub_published_release, pub_pending_updates = (
+            self._createDefaultSourcePublications())
+
+        # Release 'breezy-autotest'.
+        self.breezy_autotest.status = SeriesStatus.CURRENT
+        self.layer.commit()
+
+        # Since the distroseries is stable, nothing is returned because
+        # RELEASE pocket is ignored, in both modes, careful or not.
+        self.checkSourceLookupForPocket(
+            PackagePublishingPocket.RELEASE, expected_result=[])
+
+        # XXX cprov 2007-01-05: it means that "careful" mode is useless for
+        # rebuilding released archives.
+        # This is quite right, IMHO, since republication of a released
+        # archive will, obviously contain new timestamps, which would freak
+        # mirrors/clients out.
+        # At the end, "careful" mode is such a gross hack.
+        self.checkSourceLookupForPocket(
+            PackagePublishingPocket.RELEASE, is_careful=True,
+            expected_result=[])
+
+        # Publications targeted to other pockets than RELEASE are
+        # still reachable.
+        self.checkSourceLookupForPocket(
+            PackagePublishingPocket.UPDATES,
+            expected_result=[pub_pending_updates])
+
+    def testPublicationLookUpForFrozenDistroSeries(self):
+        """Source publishing record lookup for a frozen DistroSeries.
+
+        Check if Publisher.getPendingSourcePublications() works properly for
+        a DistroSeries when it is in FROZEN state.
+        """
+        pub_pending_release, pub_published_release, pub_pending_updates = (
+            self._createDefaultSourcePublications())
+        # Freeze 'breezy-autotest'.
+        self.breezy_autotest.status = SeriesStatus.FROZEN
+        self.layer.commit()
+
+        # Usual publication procedure for a distroseries in development
+        # state only 'pending' publishing records for pocket RELEASE
+        # are published.
+        self.checkSourceLookupForPocket(
+            PackagePublishingPocket.RELEASE,
+            expected_result=[pub_pending_release])
+
+        # This step is unusual but checks if the pocket restriction also
+        # work for other pockets than the RELEASE.
+        self.checkSourceLookupForPocket(
+            PackagePublishingPocket.UPDATES,
+            expected_result=[pub_pending_updates])
+
+        # Restricting to a pocket with no publication returns an
+        # empty SQLResult.
+        self.checkSourceLookupForPocket(
+            PackagePublishingPocket.BACKPORTS, expected_result=[])
+
+        # Using the 'careful' mode results in the consideration
+        # of every 'pending' and 'published' records present in
+        # the given pocket.
+        self.checkSourceLookupForPocket(
+            PackagePublishingPocket.RELEASE, is_careful=True,
+            expected_result=[pub_published_release, pub_pending_release])
+
+    def testPublicationLookUpForUnstableDistroArchSeries(self):
+        """Binary publishing record lookup for a unstable DistroArchSeries.
+
+        Check if Publisher.getPendingBinaryPublications() works properly for
+        a DistroArchSeries when it is still in DEVELOPMENT, i.e.,
+        'unstable'.
+        """
+        pub_pending_release, pub_published_release, pub_pending_updates = (
+            self._createDefaultBinaryPublications())
+        self.layer.commit()
+
+        # Usual publication procedure for a distroseries in development
+        # state only 'pending' publishing records for pocket RELEASE
+        # are published.
+        self.checkBinaryLookupForPocket(
+            PackagePublishingPocket.RELEASE,
+            expected_result=[pub_pending_release])
+
+        # This step is unusual but checks if the pocket restriction also
+        # work for other pockets than the RELEASE.
+        self.checkBinaryLookupForPocket(
+            PackagePublishingPocket.UPDATES,
+            expected_result=[pub_pending_updates])
+
+        # Restricting to a pocket with no publication returns an
+        # empty SQLResult.
+        self.checkBinaryLookupForPocket(
+            PackagePublishingPocket.BACKPORTS, expected_result=[])
+
+        # Using the 'careful' mode results in the consideration
+        # of every 'pending' and 'published' records present in
+        # the given pocket.
+        self.checkBinaryLookupForPocket(
+            PackagePublishingPocket.RELEASE, is_careful=True,
+            expected_result=[pub_published_release, pub_pending_release])
+
+    def testPublicationLookUpForStableDistroArchSeries(self):
+        """Binary publishing record lookup for released DistroArchSeries.
+
+        Check if Publisher.getPendingBinaryPublications() works properly for
+        a DistroArchSeries when it is not in development anymore, i.e.,
+        'released'.
+
+        Released DistroArchSeries can't be modified, so we expect empty
+        results in the lookups, even if there are pending publishing
+        records available.
+        """
+        pub_pending_release, pub_published_release, pub_pending_updates = (
+            self._createDefaultBinaryPublications())
+
+        # Release 'breezy-autotest'
+        self.breezy_autotest.status = SeriesStatus.CURRENT
+        self.layer.commit()
+
+        # Since the distroseries is stable, nothing is returned because
+        # RELEASE pocket is ignored, in both modes, careful or not.
+        self.checkBinaryLookupForPocket(
+            PackagePublishingPocket.RELEASE, expected_result=[])
+
+        # XXX cprov 2007-01-05: it means that "careful" mode is useless for
+        # rebuilding released archives.
+        # This is quite right, IMHO, since republication of a released
+        # archive will, obviously contain new timestamps, which would freak
+        # mirrors/clients out.
+        # At the end, "careful" mode is such a gross hack.
+        self.checkBinaryLookupForPocket(
+            PackagePublishingPocket.RELEASE, is_careful=True,
+            expected_result=[])
+
+        # Publications targeted to other pockets than RELEASE are
+        # still reachable.
+        self.checkBinaryLookupForPocket(
+            PackagePublishingPocket.UPDATES,
+            expected_result=[pub_pending_updates])
+
+    def testPublicationLookUpForFrozenDistroArchSeries(self):
+        """Binary publishing record lookup for a frozen DistroArchSeries.
+
+        Check if Publisher.getPendingBinaryPublications() works properly for
+        a DistroArchSeries when it is frozen state.
+        """
+        pub_pending_release, pub_published_release, pub_pending_updates = (
+            self._createDefaultBinaryPublications())
+        # Freeze 'breezy-autotest'
+        self.breezy_autotest.status = SeriesStatus.FROZEN
+        self.layer.commit()
+
+        # Usual publication procedure for a distroseries in development
+        # state only 'pending' publishing records for pocket RELEASE
+        # are published.
+        self.checkBinaryLookupForPocket(
+            PackagePublishingPocket.RELEASE,
+            expected_result=[pub_pending_release])
+
+        # This step is unusual but checks if the pocket restriction also
+        # work for other pockets than the RELEASE.
+        self.checkBinaryLookupForPocket(
+            PackagePublishingPocket.UPDATES,
+            expected_result=[pub_pending_updates])
+
+        # Restricting to a pocket with no publication returns an
+        # empty SQLResult.
+        self.checkBinaryLookupForPocket(
+            PackagePublishingPocket.BACKPORTS, expected_result=[])
+
+        # Using the 'careful' mode results in the consideration
+        # of every 'pending' and 'published' records present in
+        # the given pocket.
+        self.checkBinaryLookupForPocket(
+            PackagePublishingPocket.RELEASE, is_careful=True,
+            expected_result=[pub_published_release, pub_pending_release])
+
+    def test_publishing_disabled_distroarchseries(self):
+        # Disabled DASes will not receive new publications at all.
+
+        # Make an arch-all source and some builds for it.
+        archive = self.factory.makeArchive(
+            distribution=self.ubuntutest, virtualized=False)
+        source = self.getPubSource(
+            archive=archive, architecturehintlist='all')
+        [build_i386] = source.createMissingBuilds()
+        bin_i386 = self.uploadBinaryForBuild(build_i386, 'bin-i386')
+
+        # Now make sure they have a packageupload (but no publishing
+        # records).
+        changes_file_name = '%s_%s_%s.changes' % (
+            bin_i386.name, bin_i386.version, build_i386.arch_tag)
+        pu_i386 = self.addPackageUpload(
+            build_i386.archive, build_i386.distro_arch_series.distroseries,
+            build_i386.pocket, changes_file_content='anything',
+            changes_file_name=changes_file_name,
+            upload_status=PackageUploadStatus.ACCEPTED)
+        pu_i386.addBuild(build_i386)
+
+        # Now we make hppa a disabled architecture, and then call the
+        # publish method on the packageupload.  The arch-all binary
+        # should be published only in the i386 arch, not the hppa one.
+        hppa = pu_i386.distroseries.getDistroArchSeries('hppa')
+        hppa.enabled = False
+        for pu_build in pu_i386.builds:
+            pu_build.publish()
+
+        publications = archive.getAllPublishedBinaries(name="bin-i386")
+
+        self.assertEqual(1, publications.count())
+        self.assertEqual(
+            'i386', publications[0].distroarchseries.architecturetag)
+
+
 class TestPublisher(TestPublisherBase):
     """Testing `Publisher` behaviour."""
 
@@ -533,15 +991,18 @@
         # Remove security proxy so that the publisher can call our fake
         # method.
         publisher.distro = removeSecurityProxy(publisher.distro)
+        publisher.distro['hoary-test'].status = SeriesStatus.OBSOLETE
 
         for status in (SeriesStatus.OBSOLETE, SeriesStatus.FUTURE):
             naked_breezy_autotest = publisher.distro['breezy-autotest']
             naked_breezy_autotest.status = status
-            naked_breezy_autotest.publish = FakeMethod(result=set())
+            publisher.publishSources = FakeMethod(result=set())
+            publisher.publishBinaries = FakeMethod(result=set())
 
             publisher.A_publish(False)
 
-            self.assertEqual(0, naked_breezy_autotest.publish.call_count)
+            self.assertEqual(0, publisher.publishSources.call_count)
+            self.assertEqual(0, publisher.publishBinaries.call_count)
 
     def testPublishingConsidersObsoleteFuturePPASeries(self):
         """Publisher does not skip OBSOLETE/FUTURE series in PPA archives."""
@@ -558,11 +1019,17 @@
         for status in (SeriesStatus.OBSOLETE, SeriesStatus.FUTURE):
             naked_breezy_autotest = publisher.distro['breezy-autotest']
             naked_breezy_autotest.status = status
-            naked_breezy_autotest.publish = FakeMethod(result=set())
+            publisher.publishSources = FakeMethod(result=set())
+            publisher.publishBinaries = FakeMethod(result=set())
 
             publisher.A_publish(False)
 
-            self.assertEqual(1, naked_breezy_autotest.publish.call_count)
+            self.assertIn(
+                (naked_breezy_autotest, RELEASE),
+                publisher.publishSources.extract_args())
+            self.assertIn(
+                (naked_breezy_autotest.architectures[0], RELEASE),
+                publisher.publishBinaries.extract_args())
 
     def testPublisherBuilderFunctions(self):
         """Publisher can be initialized via provided helper function.

=== modified file 'lib/lp/registry/configure.zcml'
--- lib/lp/registry/configure.zcml	2014-02-25 06:24:21 +0000
+++ lib/lp/registry/configure.zcml	2014-07-08 23:16:10 +0000
@@ -1,4 +1,4 @@
-<!-- Copyright 2009-2013 Canonical Ltd.  This software is licensed under the
+<!-- Copyright 2009-2014 Canonical Ltd.  This software is licensed under the
      GNU Affero General Public License version 3 (see the file LICENSE).
 -->
 
@@ -246,8 +246,6 @@
             interface="lp.bugs.interfaces.bugtarget.ISeriesBugTarget"/>
         <allow
             interface="lp.soyuz.interfaces.queue.IHasQueueItems"/>
-        <allow
-            interface="lp.soyuz.interfaces.publishing.ICanPublishPackages"/>
         <require
             permission="launchpad.Edit"
             set_schema="lp.app.interfaces.launchpad.IServiceUsage"/>

=== modified file 'lib/lp/registry/model/distroseries.py'
--- lib/lp/registry/model/distroseries.py	2014-06-11 15:32:06 +0000
+++ lib/lp/registry/model/distroseries.py	2014-07-08 23:16:10 +0000
@@ -132,10 +132,7 @@
 from lp.soyuz.interfaces.distributionjob import (
     IInitializeDistroSeriesJobSource,
     )
-from lp.soyuz.interfaces.publishing import (
-    active_publishing_status,
-    ICanPublishPackages,
-    )
+from lp.soyuz.interfaces.publishing import active_publishing_status
 from lp.soyuz.interfaces.queue import (
     IHasQueueItems,
     IPackageUploadSet,
@@ -200,9 +197,8 @@
                    StructuralSubscriptionTargetMixin):
     """A particular series of a distribution."""
     implements(
-        ICanPublishPackages, IBugSummaryDimension, IDistroSeries,
-        IHasBuildRecords, IHasQueueItems, IServiceUsage,
-        ISeriesBugTarget)
+        IBugSummaryDimension, IDistroSeries, IHasBuildRecords, IHasQueueItems,
+        IServiceUsage, ISeriesBugTarget)
 
     delegates(ISpecificationTarget, 'distribution')
 
@@ -1335,73 +1331,6 @@
         contributors = contributors.config(distinct=True)
         return contributors
 
-    def getPendingPublications(self, archive, pocket, is_careful):
-        """See ICanPublishPackages."""
-        queries = ['distroseries = %s' % sqlvalues(self)]
-
-        # Query main archive for this distroseries
-        queries.append('archive=%s' % sqlvalues(archive))
-
-        # Careful publishing should include all PUBLISHED rows, normal run
-        # only includes PENDING ones.
-        statuses = [PackagePublishingStatus.PENDING]
-        if is_careful:
-            statuses.append(PackagePublishingStatus.PUBLISHED)
-        queries.append('status IN %s' % sqlvalues(statuses))
-
-        # Restrict to a specific pocket.
-        queries.append('pocket = %s' % sqlvalues(pocket))
-
-        # Exclude RELEASE pocket if the distroseries was already released,
-        # since it should not change for main archive.
-        # We allow RELEASE publishing for PPAs.
-        # We also allow RELEASE publishing for partner.
-        if (not self.isUnstable() and
-            not archive.allowUpdatesToReleasePocket()):
-            queries.append(
-            'pocket != %s' % sqlvalues(PackagePublishingPocket.RELEASE))
-
-        publications = SourcePackagePublishingHistory.select(
-            " AND ".join(queries), orderBy="-id")
-
-        return publications
-
-    def publish(self, diskpool, log, archive, pocket, is_careful=False):
-        """See ICanPublishPackages."""
-        log.debug("Publishing %s-%s" % (self.title, pocket.name))
-        log.debug("Attempting to publish pending sources.")
-
-        dirty_pockets = set()
-        for spph in self.getPendingPublications(archive, pocket, is_careful):
-            if not self.checkLegalPocket(spph, is_careful, log):
-                continue
-            spph.publish(diskpool, log)
-            dirty_pockets.add((self.name, spph.pocket))
-
-        # propagate publication request to each distroarchseries.
-        for dar in self.architectures:
-            more_dirt = dar.publish(
-                diskpool, log, archive, pocket, is_careful)
-            dirty_pockets.update(more_dirt)
-
-        return dirty_pockets
-
-    def checkLegalPocket(self, publication, is_careful, log):
-        """Check if the publication can happen in the archive."""
-        # 'careful' mode re-publishes everything:
-        if is_careful:
-            return True
-
-        if not publication.archive.canModifySuite(self, publication.pocket):
-            log.error(
-                "Tried to publish %s (%s) into the %s pocket on series %s "
-                "(%s), skipping" % (
-                    publication.displayname, publication.id,
-                    publication.pocket, self.displayname, self.status.name))
-            return False
-
-        return True
-
     @property
     def main_archive(self):
         return self.distribution.main_archive

=== modified file 'lib/lp/soyuz/configure.zcml'
--- lib/lp/soyuz/configure.zcml	2014-06-17 11:01:51 +0000
+++ lib/lp/soyuz/configure.zcml	2014-07-08 23:16:10 +0000
@@ -605,8 +605,6 @@
             class="lp.soyuz.model.distroarchseries.DistroArchSeries">
             <allow
                 interface="lp.soyuz.interfaces.distroarchseries.IDistroArchSeriesPublic"/>
-            <allow
-                interface="lp.soyuz.interfaces.publishing.ICanPublishPackages"/>
             <require
                 permission="launchpad.Admin"
                 set_schema="lp.soyuz.interfaces.distroarchseries.IDistroArchSeriesPublic"/>

=== modified file 'lib/lp/soyuz/interfaces/publishing.py'
--- lib/lp/soyuz/interfaces/publishing.py	2014-05-06 06:32:46 +0000
+++ lib/lp/soyuz/interfaces/publishing.py	2014-07-08 23:16:10 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2013 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2014 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Publishing interfaces."""
@@ -12,7 +12,6 @@
     'IBinaryPackagePublishingHistory',
     'IBinaryPackagePublishingHistoryEdit',
     'IBinaryPackagePublishingHistoryPublic',
-    'ICanPublishPackages',
     'IFilePublishing',
     'IPublishingEdit',
     'IPublishingSet',
@@ -127,36 +126,6 @@
 #
 
 
-class ICanPublishPackages(Interface):
-    """Denotes the ability to publish associated publishing records."""
-
-    def getPendingPublications(archive, pocket, is_careful):
-        """Return the specific group of records to be published.
-
-        IDistroSeries -> ISourcePackagePublishing
-        IDistroArchSeries -> IBinaryPackagePublishing
-
-        'pocket' & 'archive' are mandatory arguments, they  restrict the
-        results to the given value.
-
-        If the distroseries is already released, it automatically refuses
-        to publish records to RELEASE pocket.
-        """
-
-    def publish(diskpool, log, archive, pocket, careful=False):
-        """Publish associated publishing records targeted for a given pocket.
-
-        Require an initialized diskpool instance and a logger instance.
-        Require an 'archive' which will restrict the publications.
-        'careful' argument would cause the 'republication' of all published
-        records if True (system will DTRT checking hash of all
-        published files.)
-
-        Consider records returned by the local implementation of
-        getPendingPublications.
-        """
-
-
 class IArchiveSafePublisher(Interface):
     """Safe Publication methods"""
 

=== modified file 'lib/lp/soyuz/model/distroarchseries.py'
--- lib/lp/soyuz/model/distroarchseries.py	2014-02-28 11:12:31 +0000
+++ lib/lp/soyuz/model/distroarchseries.py	2014-07-08 23:16:10 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2013 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2014 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 __metaclass__ = type
@@ -56,14 +56,13 @@
     InvalidChrootUploaded,
     IPocketChroot,
     )
-from lp.soyuz.interfaces.publishing import ICanPublishPackages
 from lp.soyuz.model.binarypackagename import BinaryPackageName
 from lp.soyuz.model.binarypackagerelease import BinaryPackageRelease
 from lp.soyuz.model.processor import Processor
 
 
 class DistroArchSeries(SQLBase):
-    implements(IDistroArchSeries, IHasBuildRecords, ICanPublishPackages)
+    implements(IDistroArchSeries, IHasBuildRecords)
     _table = 'DistroArchSeries'
     _defaultOrder = 'id'
 
@@ -314,51 +313,6 @@
 
         return shortlist(published)
 
-    def getPendingPublications(self, archive, pocket, is_careful):
-        """See `ICanPublishPackages`."""
-        from lp.soyuz.model.publishing import BinaryPackagePublishingHistory
-
-        queries = [
-            "distroarchseries = %s AND archive = %s"
-            % sqlvalues(self, archive)
-            ]
-
-        target_status = [PackagePublishingStatus.PENDING]
-        if is_careful:
-            target_status.append(PackagePublishingStatus.PUBLISHED)
-        queries.append("status IN %s" % sqlvalues(target_status))
-
-        # restrict to a specific pocket.
-        queries.append('pocket = %s' % sqlvalues(pocket))
-
-        # Exclude RELEASE pocket if the distroseries was already released,
-        # since it should not change, unless the archive allows it.
-        if (not self.distroseries.isUnstable() and
-            not archive.allowUpdatesToReleasePocket()):
-            queries.append(
-            'pocket != %s' % sqlvalues(PackagePublishingPocket.RELEASE))
-
-        publications = BinaryPackagePublishingHistory.select(
-                    " AND ".join(queries), orderBy=["-id"])
-
-        return publications
-
-    def publish(self, diskpool, log, archive, pocket, is_careful=False):
-        """See `ICanPublishPackages`."""
-        log.debug("Attempting to publish pending binaries for %s"
-              % self.architecturetag)
-
-        dirty_pockets = set()
-
-        for bpph in self.getPendingPublications(archive, pocket, is_careful):
-            if not self.distroseries.checkLegalPocket(
-                bpph, is_careful, log):
-                continue
-            bpph.publish(diskpool, log)
-            dirty_pockets.add((self.distroseries.name, bpph.pocket))
-
-        return dirty_pockets
-
     @property
     def main_archive(self):
         return self.distroseries.distribution.main_archive

=== removed file 'lib/lp/soyuz/tests/test_publishing_top_level_api.py'
--- lib/lp/soyuz/tests/test_publishing_top_level_api.py	2010-10-06 11:46:51 +0000
+++ lib/lp/soyuz/tests/test_publishing_top_level_api.py	1970-01-01 00:00:00 +0000
@@ -1,460 +0,0 @@
-# Copyright 2009-2010 Canonical Ltd.  This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Test top-level publication API in Soyuz."""
-
-from lp.registry.interfaces.pocket import PackagePublishingPocket
-from lp.registry.interfaces.series import SeriesStatus
-from lp.soyuz.enums import (
-    PackagePublishingStatus,
-    PackageUploadStatus,
-    )
-from lp.soyuz.tests.test_publishing import TestNativePublishingBase
-
-
-class TestICanPublishPackagesAPI(TestNativePublishingBase):
-
-    def _createLinkedPublication(self, name, pocket):
-        """Return a linked pair of source and binary publications."""
-        pub_source = self.getPubSource(
-            sourcename=name, filecontent="Hello", pocket=pocket)
-
-        binaryname = '%s-bin' % name
-        pub_bin = self.getPubBinaries(
-            binaryname=binaryname, filecontent="World",
-            pub_source=pub_source, pocket=pocket)[0]
-
-        return (pub_source, pub_bin)
-
-    def _createDefaulSourcePublications(self):
-        """Create and return default source publications.
-
-        See `TestNativePublishingBase.getPubSource` for more information.
-
-        It creates the following publications in breezy-autotest context:
-
-         * a PENDING publication for RELEASE pocket;
-         * a PUBLISHED publication for RELEASE pocket;
-         * a PENDING publication for UPDATES pocket;
-
-        Returns the respective ISPPH objects as a tuple.
-        """
-        pub_pending_release = self.getPubSource(
-            sourcename='first',
-            status=PackagePublishingStatus.PENDING,
-            pocket=PackagePublishingPocket.RELEASE)
-
-        pub_published_release = self.getPubSource(
-            sourcename='second',
-            status=PackagePublishingStatus.PUBLISHED,
-            pocket=PackagePublishingPocket.RELEASE)
-
-        pub_pending_updates = self.getPubSource(
-            sourcename='third',
-            status=PackagePublishingStatus.PENDING,
-            pocket=PackagePublishingPocket.UPDATES)
-
-        return (pub_pending_release, pub_published_release,
-                pub_pending_updates)
-
-    def _createDefaulBinaryPublications(self):
-        """Create and return default binary publications.
-
-        See `TestNativePublishingBase.getPubBinaries` for more information.
-
-        It creates the following publications in breezy-autotest context:
-
-         * a PENDING publication for RELEASE pocket;
-         * a PUBLISHED publication for RELEASE pocket;
-         * a PENDING publication for UPDATES pocket;
-
-        Returns the respective IBPPH objects as a tuple.
-        """
-        pub_pending_release = self.getPubBinaries(
-            binaryname='first',
-            status=PackagePublishingStatus.PENDING,
-            pocket=PackagePublishingPocket.RELEASE)[0]
-
-        pub_published_release = self.getPubBinaries(
-            binaryname='second',
-            status=PackagePublishingStatus.PUBLISHED,
-            pocket=PackagePublishingPocket.RELEASE)[0]
-
-        pub_pending_updates = self.getPubBinaries(
-            binaryname='third',
-            status=PackagePublishingStatus.PENDING,
-            pocket=PackagePublishingPocket.UPDATES)[0]
-
-        return (pub_pending_release, pub_published_release,
-                pub_pending_updates)
-
-    def _publish(self, pocket, is_careful=False):
-        """Publish the test IDistroSeries.
-
-        Note that it also issues IDistroArchSeries.publish() API, since it's
-        invoked/chained inside IDistroSeries.publish().
-        """
-        self.breezy_autotest.publish(
-            self.disk_pool, self.logger,
-            archive=self.breezy_autotest.main_archive,
-            pocket=pocket, is_careful=is_careful)
-        self.layer.txn.commit()
-
-    def checkPublicationsAreConsidered(self, pocket):
-        """Check if publications are considered for a given pocket.
-
-        Source and Binary publications to the given pocket get PUBLISHED in
-        database and on disk.
-        """
-        pub_source, pub_bin = self._createLinkedPublication(
-            name='foo', pocket=pocket)
-        self._publish(pocket=pocket)
-
-        # source and binary PUBLISHED in database.
-        pub_source.sync()
-        pub_bin.sync()
-        self.assertEqual(pub_source.status, PackagePublishingStatus.PUBLISHED)
-        self.assertEqual(pub_bin.status, PackagePublishingStatus.PUBLISHED)
-
-        # source and binary PUBLISHED on disk.
-        foo_dsc = "%s/main/f/foo/foo_666.dsc" % self.pool_dir
-        self.assertEqual(open(foo_dsc).read().strip(), 'Hello')
-        foo_deb = "%s/main/f/foo/foo-bin_666_all.deb" % self.pool_dir
-        self.assertEqual(open(foo_deb).read().strip(), 'World')
-
-    def checkPublicationsAreIgnored(self, pocket):
-        """Check if publications are ignored for a given pocket.
-
-        Source and Binary publications to the given pocket are still PENDING
-        in database.
-        """
-        pub_source, pub_bin = self._createLinkedPublication(
-            name='bar', pocket=pocket)
-        self._publish(pocket=pocket)
-
-        # The publications to pocket were ignored.
-        self.assertEqual(pub_source.status, PackagePublishingStatus.PENDING)
-        self.assertEqual(pub_bin.status, PackagePublishingStatus.PENDING)
-
-    def checkSourceLookupForPocket(self, pocket, expected_result,
-                                   is_careful=False):
-        """Check the results of an IDistroSeries publishing lookup."""
-        pub_records = self.breezy_autotest.getPendingPublications(
-            archive=self.breezy_autotest.main_archive,
-            pocket=pocket, is_careful=is_careful)
-
-        self.assertEqual(pub_records.count(), len(expected_result))
-        self.assertEqual(
-            [item.id for item in expected_result],
-            [pub.id for pub in pub_records])
-
-    def checkBinaryLookupForPocket(self, pocket, expected_result,
-                                   is_careful=False):
-        """Check the results of an IDistroArchSeries publishing lookup."""
-        pub_records = self.breezy_autotest_i386.getPendingPublications(
-            archive=self.breezy_autotest.main_archive,
-            pocket=pocket, is_careful=is_careful)
-
-        self.assertEqual(pub_records.count(), len(expected_result))
-        self.assertEqual(
-            [item.id for item in expected_result],
-            [pub.id for pub in pub_records])
-
-    def testPublishUnstableDistroSeries(self):
-        """Top level publication for IDistroSeries in 'unstable' states.
-
-        Publications to RELEASE pocket are considered.
-        Publication to UPDATES pocket (post-release pockets) are ignored
-        """
-        self.assertEqual(
-            self.breezy_autotest.status, SeriesStatus.EXPERIMENTAL)
-        self.assertEqual(self.breezy_autotest.isUnstable(), True)
-        self.checkPublicationsAreConsidered(PackagePublishingPocket.RELEASE)
-        self.checkPublicationsAreIgnored(PackagePublishingPocket.UPDATES)
-
-    def testPublishStableDistroSeries(self):
-        """Top level publication for IDistroSeries in 'stable' states.
-
-        Publications to RELEASE pocket are ignored.
-        Publications to UPDATES pocket are considered.
-        """
-        # Release ubuntu/breezy-autotest.
-        self.breezy_autotest.status = SeriesStatus.CURRENT
-        self.layer.commit()
-
-        self.assertEqual(
-            self.breezy_autotest.status, SeriesStatus.CURRENT)
-        self.assertEqual(self.breezy_autotest.isUnstable(), False)
-        self.checkPublicationsAreConsidered(PackagePublishingPocket.UPDATES)
-        self.checkPublicationsAreIgnored(PackagePublishingPocket.RELEASE)
-
-    def testPublishFrozenDistroSeries(self):
-        """Top level publication for IDistroSeries in FROZEN state.
-
-        Publications to both, RELEASE and UPDATES, pockets are considered.
-        """
-        # Release ubuntu/breezy-autotest.
-        self.breezy_autotest.status = SeriesStatus.FROZEN
-        self.layer.commit()
-
-        self.assertEqual(
-            self.breezy_autotest.status, SeriesStatus.FROZEN)
-        self.assertEqual(
-            self.breezy_autotest.isUnstable(), True)
-        self.checkPublicationsAreConsidered(PackagePublishingPocket.UPDATES)
-        self.checkPublicationsAreConsidered(PackagePublishingPocket.RELEASE)
-
-    def testPublicationLookUpForUnstableDistroSeries(self):
-        """Source publishing record lookup for a unstable DistroSeries.
-
-        Check if the ICanPublishPackages.getPendingPublications() works
-        properly for a DistroSeries when it is still in development,
-        'unreleased'.
-        """
-        pub_pending_release, pub_published_release, pub_pending_updates = (
-            self._createDefaulSourcePublications())
-
-        # Usual publication procedure for a distroseries in development
-        # state only 'pending' publishing records for pocket RELEASE
-        # are published.
-        self.checkSourceLookupForPocket(
-            PackagePublishingPocket.RELEASE,
-            expected_result=[pub_pending_release])
-
-        # This step is unusual but checks if the pocket restriction also
-        # work for other pockets than the RELEASE.
-        self.checkSourceLookupForPocket(
-            PackagePublishingPocket.UPDATES,
-            expected_result=[pub_pending_updates])
-
-        # Restricting to a pocket with no publication returns an
-        # empty SQLResult.
-        self.checkSourceLookupForPocket(
-            PackagePublishingPocket.BACKPORTS, expected_result=[])
-
-        # Using the 'careful' mode results in the consideration
-        # of every 'pending' and 'published' records present in
-        # the given pocket. The order is also important, NEWER first.
-        self.checkSourceLookupForPocket(
-            PackagePublishingPocket.RELEASE, is_careful=True,
-            expected_result=[pub_published_release, pub_pending_release])
-
-    def testPublicationLookUpForStableDistroSeries(self):
-        """Source publishing record lookup for a stable/released DistroSeries.
-
-        Check if the ICanPublishPackages.getPendingPublications() works
-        properly for a DistroSeries when it is not in development anymore,
-        i.e., 'released'.
-        """
-        pub_pending_release, pub_published_release, pub_pending_updates = (
-            self._createDefaulSourcePublications())
-
-        # Release 'breezy-autotest'.
-        self.breezy_autotest.status = SeriesStatus.CURRENT
-        self.layer.commit()
-
-        # Since the distroseries is stable, nothing is returned because
-        # RELEASE pocket is ignored, in both modes, careful or not.
-        self.checkSourceLookupForPocket(
-            PackagePublishingPocket.RELEASE, expected_result=[])
-
-        # XXX cprov 2007-01-05: it means that "careful" mode is useless for
-        # rebuilding released archives.
-        # This is quite right, IMHO, since republication of a released
-        # archive will, obviously contain new timestamps, which would freak
-        # mirrors/clients out.
-        # At the end, "careful" mode is such a gross hack.
-        self.checkSourceLookupForPocket(
-            PackagePublishingPocket.RELEASE, is_careful=True,
-            expected_result=[])
-
-        # Publications targeted to other pockets than RELEASE are
-        # still reachable.
-        self.checkSourceLookupForPocket(
-            PackagePublishingPocket.UPDATES,
-            expected_result=[pub_pending_updates])
-
-    def testPublicationLookUpForFrozenDistroSeries(self):
-        """Source publishing record lookup for a frozen DistroSeries.
-
-        Check if the ICanPublishPackages.getPendingPubliations() works
-        properly for a DistroSeries when it is in FROZEN state.
-        """
-        pub_pending_release, pub_published_release, pub_pending_updates = (
-            self._createDefaulSourcePublications())
-        # Freeze 'breezy-autotest'.
-        self.breezy_autotest.status = SeriesStatus.FROZEN
-        self.layer.commit()
-
-        # Usual publication procedure for a distroseries in development
-        # state only 'pending' publishing records for pocket RELEASE
-        # are published.
-        self.checkSourceLookupForPocket(
-            PackagePublishingPocket.RELEASE,
-            expected_result=[pub_pending_release])
-
-        # This step is unusual but checks if the pocket restriction also
-        # work for other pockets than the RELEASE.
-        self.checkSourceLookupForPocket(
-            PackagePublishingPocket.UPDATES,
-            expected_result=[pub_pending_updates])
-
-        # Restricting to a pocket with no publication returns an
-        # empty SQLResult.
-        self.checkSourceLookupForPocket(
-            PackagePublishingPocket.BACKPORTS, expected_result=[])
-
-        # Using the 'careful' mode results in the consideration
-        # of every 'pending' and 'published' records present in
-        # the given pocket.
-        self.checkSourceLookupForPocket(
-            PackagePublishingPocket.RELEASE, is_careful=True,
-            expected_result=[pub_published_release, pub_pending_release])
-
-    def testPublicationLookUpForUnstableDistroArchSeries(self):
-        """Binary publishing record lookup for a unstable DistroArchSeries.
-
-        Check if the ICanPublishPackages.getPendingPublications() works
-        properly for a DistroArchSeries when it is still in DEVELOPMENT,
-        i.e., 'unstable'.
-        """
-        pub_pending_release, pub_published_release, pub_pending_updates = (
-            self._createDefaulBinaryPublications())
-        self.layer.commit()
-
-        # Usual publication procedure for a distroseries in development
-        # state only 'pending' publishing records for pocket RELEASE
-        # are published.
-        self.checkBinaryLookupForPocket(
-            PackagePublishingPocket.RELEASE,
-            expected_result=[pub_pending_release])
-
-        # This step is unusual but checks if the pocket restriction also
-        # work for other pockets than the RELEASE.
-        self.checkBinaryLookupForPocket(
-            PackagePublishingPocket.UPDATES,
-            expected_result=[pub_pending_updates])
-
-        # Restricting to a pocket with no publication returns an
-        # empty SQLResult.
-        self.checkBinaryLookupForPocket(
-            PackagePublishingPocket.BACKPORTS, expected_result=[])
-
-        # Using the 'careful' mode results in the consideration
-        # of every 'pending' and 'published' records present in
-        # the given pocket.
-        self.checkBinaryLookupForPocket(
-            PackagePublishingPocket.RELEASE, is_careful=True,
-            expected_result=[pub_published_release, pub_pending_release])
-
-    def testPublicationLookUpForStableDistroArchSeries(self):
-        """Binary publishing record lookup for released DistroArchSeries.
-
-        Check if the ICanPublishPackages.getPendingPublications() works
-        properly for a DistroArchSeries when it is not in development
-        anymore, i.e., 'released'.
-
-        Released DistroArchSeries can't be modified, so we expect empty
-        results in the lookups, even if there are pending publishing
-        records available.
-        """
-        pub_pending_release, pub_published_release, pub_pending_updates = (
-            self._createDefaulBinaryPublications())
-
-        # Release 'breezy-autotest'
-        self.breezy_autotest.status = SeriesStatus.CURRENT
-        self.layer.commit()
-
-        # Since the distroseries is stable, nothing is returned because
-        # RELEASE pocket is ignored, in both modes, careful or not.
-        self.checkBinaryLookupForPocket(
-            PackagePublishingPocket.RELEASE, expected_result=[])
-
-        # XXX cprov 2007-01-05: it means that "careful" mode is useless for
-        # rebuilding released archives.
-        # This is quite right, IMHO, since republication of a released
-        # archive will, obviously contain new timestamps, which would freak
-        # mirrors/clients out.
-        # At the end, "careful" mode is such a gross hack.
-        self.checkBinaryLookupForPocket(
-            PackagePublishingPocket.RELEASE, is_careful=True,
-            expected_result=[])
-
-        # Publications targeted to other pockets than RELEASE are
-        # still reachable.
-        self.checkBinaryLookupForPocket(
-            PackagePublishingPocket.UPDATES,
-            expected_result=[pub_pending_updates])
-
-    def testPublicationLookUpForFrozenDistroArchSeries(self):
-        """Binary publishing record lookup for a frozen DistroArchSeries.
-
-        Check if the ICanPublishPackages.getPendingPublications() works
-        properly for a DistroArchSeries when it is frozen state.
-        """
-        pub_pending_release, pub_published_release, pub_pending_updates = (
-            self._createDefaulBinaryPublications())
-        # Freeze 'breezy-autotest'
-        self.breezy_autotest.status = SeriesStatus.FROZEN
-        self.layer.commit()
-
-        # Usual publication procedure for a distroseries in development
-        # state only 'pending' publishing records for pocket RELEASE
-        # are published.
-        self.checkBinaryLookupForPocket(
-            PackagePublishingPocket.RELEASE,
-            expected_result=[pub_pending_release])
-
-        # This step is unusual but checks if the pocket restriction also
-        # work for other pockets than the RELEASE.
-        self.checkBinaryLookupForPocket(
-            PackagePublishingPocket.UPDATES,
-            expected_result=[pub_pending_updates])
-
-        # Restricting to a pocket with no publication returns an
-        # empty SQLResult.
-        self.checkBinaryLookupForPocket(
-            PackagePublishingPocket.BACKPORTS, expected_result=[])
-
-        # Using the 'careful' mode results in the consideration
-        # of every 'pending' and 'published' records present in
-        # the given pocket.
-        self.checkBinaryLookupForPocket(
-            PackagePublishingPocket.RELEASE, is_careful=True,
-            expected_result=[pub_published_release, pub_pending_release])
-
-    def test_publishing_disabled_distroarchseries(self):
-        # Disabled DASes will not receive new publications at all.
-
-        # Make an arch-all source and some builds for it.
-        archive = self.factory.makeArchive(
-            distribution=self.ubuntutest, virtualized=False)
-        source = self.getPubSource(
-            archive=archive, architecturehintlist='all')
-        [build_i386] = source.createMissingBuilds()
-        bin_i386 = self.uploadBinaryForBuild(build_i386, 'bin-i386')
-
-        # Now make sure they have a packageupload (but no publishing
-        # records).
-        changes_file_name = '%s_%s_%s.changes' % (
-            bin_i386.name, bin_i386.version, build_i386.arch_tag)
-        pu_i386 = self.addPackageUpload(
-            build_i386.archive, build_i386.distro_arch_series.distroseries,
-            build_i386.pocket, changes_file_content='anything',
-            changes_file_name=changes_file_name,
-            upload_status=PackageUploadStatus.ACCEPTED)
-        pu_i386.addBuild(build_i386)
-
-        # Now we make hppa a disabled architecture, and then call the
-        # publish method on the packageupload.  The arch-all binary
-        # should be published only in the i386 arch, not the hppa one.
-        hppa = pu_i386.distroseries.getDistroArchSeries('hppa')
-        hppa.enabled = False
-        for pu_build in pu_i386.builds:
-            pu_build.publish()
-
-        publications = archive.getAllPublishedBinaries(name="bin-i386")
-
-        self.assertEqual(1, publications.count())
-        self.assertEqual(
-            'i386', publications[0].distroarchseries.architecturetag)


Follow ups