← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~wgrant/launchpad/overrides-take-overrides into lp:launchpad

 

William Grant has proposed merging lp:~wgrant/launchpad/overrides-take-overrides into lp:launchpad.

Commit message:
Start generalising lp.soyuz.adapters.overrides for use in archiveuploader: kwargs, archtags, and dehackified UnknownOverridePolicies abound.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~wgrant/launchpad/overrides-take-overrides/+merge/227191

This is the first stage of modernising lp.soyuz.adapters.overrides so it can be used by archiveuploader instead of just in the copier. It currently implements a seriously simplified version of the primary archive override policy, which is sort of mostly adequate for copies but totally insufficient for uploads.

The main change is that calculateSourceOverrides and calculateBinaryOverridesno longer take a list of SPNs and a list of (BPN, DAS) pairs respectively. Instead they take what they return: a list of SourceOverrides or BinaryOverrides. This is mostly so UnknownOverridePolicy can inspect the upload component to override to universe or multiverse as appropriate, rather than implementing that rather hackishly using a source_component argument in packagecopier. This will also later be used to make binaries inherit their source's component.

BinaryOverride also now has an architecture_tag rather than a DistroArchSeries. This will be important when we start supporting arch-indep lookups as architecture_tag=None in the next branch.

And since a single override object rarely uses all the attributes, the optional bits (component, section, etc.) are now kwargs.
-- 
https://code.launchpad.net/~wgrant/launchpad/overrides-take-overrides/+merge/227191
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/overrides-take-overrides into lp:launchpad.
=== modified file 'lib/lp/soyuz/adapters/overrides.py'
--- lib/lp/soyuz/adapters/overrides.py	2013-07-16 08:10:32 +0000
+++ lib/lp/soyuz/adapters/overrides.py	2014-07-17 13:39:24 +0000
@@ -27,6 +27,7 @@
     implements,
     Interface,
     )
+from zope.security.proxy import isinstance as zope_isinstance
 
 from lp.registry.model.sourcepackagename import SourcePackageName
 from lp.services.database import bulk
@@ -66,8 +67,8 @@
 
     binary_package_name = Attribute(
         "The IBinaryPackageName that's being overridden")
-    distro_arch_series = Attribute(
-        "The IDistroArchSeries for the publication")
+    architecture_tag = Attribute(
+        "The architecture tag for the publication")
     priority = Attribute(
         "The PackagePublishingPriority that's being overridden")
     phased_update_percentage = Attribute(
@@ -95,7 +96,7 @@
     """See `ISourceOverride`."""
     implements(ISourceOverride)
 
-    def __init__(self, source_package_name, component, section):
+    def __init__(self, source_package_name, component=None, section=None):
         super(SourceOverride, self).__init__(component, section)
         self.source_package_name = source_package_name
 
@@ -105,35 +106,42 @@
             self.component == other.component and
             self.section == other.section)
 
+    def __repr__(self):
+        return (
+            "<%s at %x source_package_name=%r component=%r section=%r>" %
+            (self.__class__.__name__, id(self), self.source_package_name,
+             self.component, self.section))
+
 
 class BinaryOverride(Override):
     """See `IBinaryOverride`."""
     implements(IBinaryOverride)
 
-    def __init__(self, binary_package_name, distro_arch_series, component,
-                 section, priority, phased_update_percentage):
+    def __init__(self, binary_package_name, architecture_tag, component=None,
+                 section=None, priority=None, phased_update_percentage=None):
         super(BinaryOverride, self).__init__(component, section)
         self.binary_package_name = binary_package_name
-        self.distro_arch_series = distro_arch_series
+        self.architecture_tag = architecture_tag
         self.priority = priority
         self.phased_update_percentage = phased_update_percentage
 
     def __eq__(self, other):
         return (
             self.binary_package_name == other.binary_package_name and
-            self.distro_arch_series == other.distro_arch_series and
+            self.architecture_tag == other.architecture_tag and
             self.component == other.component and
             self.section == other.section and
             self.priority == other.priority and
             self.phased_update_percentage == other.phased_update_percentage)
 
     def __repr__(self):
-        return ("<BinaryOverride at %x component=%r section=%r "
-            "binary_package_name=%r distro_arch_series=%r priority=%r "
+        return (
+            "<%s at %x binary_package_name=%r architecture_tag=%r "
+            "component=%r section=%r priority=%r "
             "phased_update_percentage=%r>" %
-            (id(self), self.component, self.section, self.binary_package_name,
-             self.distro_arch_series, self.priority,
-             self.phased_update_percentage))
+            (self.__class__.__name__, id(self), self.binary_package_name,
+             self.architecture_tag, self.component, self.section,
+             self.priority, self.phased_update_percentage))
 
 
 class IOverridePolicy(Interface):
@@ -149,15 +157,13 @@
     phased_update_percentage = Attribute(
         "The phased update percentage to apply to binary publications.")
 
-    def calculateSourceOverrides(archive, distroseries, pocket, sources,
-                                 source_component=None):
+    def calculateSourceOverrides(archive, distroseries, pocket, sources):
         """Calculate source overrides.
 
         :param archive: The target `IArchive`.
         :param distroseries: The target `IDistroSeries`.
         :param pocket: The target `PackagePublishingPocket`.
-        :param sources: A tuple of `ISourcePackageName`s.
-        :param source_component: The sources' `IComponent` (optional).
+        :param sources: A tuple of `ISourceOverride`s.
 
         :return: A list of `ISourceOverride`
         """
@@ -186,8 +192,7 @@
         super(BaseOverridePolicy, self).__init__()
         self.phased_update_percentage = phased_update_percentage
 
-    def calculateSourceOverrides(self, archive, distroseries, pocket,
-                                 sources, source_component=None):
+    def calculateSourceOverrides(self, archive, distroseries, pocket, sources):
         raise NotImplementedError()
 
     def calculateBinaryOverrides(self, archive, distroseries, pocket,
@@ -200,7 +205,7 @@
 
     Override policy that returns the SourcePackageName, component and
     section for the latest published source publication, or the
-    BinaryPackageName, DistroArchSeries, component, section and priority
+    BinaryPackageName, architecture_tag, component, section and priority
     for the latest published binary publication.
     """
 
@@ -213,12 +218,13 @@
             status.append(PackagePublishingStatus.DELETED)
         return status
 
-    def calculateSourceOverrides(self, archive, distroseries, pocket, spns,
-                                 source_component=None, include_deleted=False):
+    def calculateSourceOverrides(self, archive, distroseries, pockets, sources,
+                                 include_deleted=False):
         def eager_load(rows):
             bulk.load(Component, (row[1] for row in rows))
             bulk.load(Section, (row[2] for row in rows))
 
+        spns = [override.source_package_name for override in sources]
         store = IStore(SourcePackagePublishingHistory)
         already_published = DecoratedResultSet(
             store.find(
@@ -241,7 +247,7 @@
             id_resolver((SourcePackageName, Component, Section)),
             pre_iter_hook=eager_load)
         return [
-            SourceOverride(name, component, section)
+            SourceOverride(name, component=component, section=section)
             for (name, component, section) in already_published]
 
     def calculateBinaryOverrides(self, archive, distroseries, pocket,
@@ -251,7 +257,10 @@
             bulk.load(Section, (row[3] for row in rows))
 
         store = IStore(BinaryPackagePublishingHistory)
-        expanded = calculate_target_das(distroseries, binaries)
+        expanded = calculate_target_das(
+            distroseries,
+            [(override.binary_package_name, override.architecture_tag)
+             for override in binaries])
 
         candidates = [
             make_package_condition(archive, das, bpn)
@@ -283,10 +292,13 @@
                 (BinaryPackageName, DistroArchSeries, Component, Section,
                 None)),
             pre_iter_hook=eager_load)
+        # XXX: This should return None for arch-indep, not the
+        # nominatedarchindep archtag.
         return [
             BinaryOverride(
-                name, das, component, section, priority,
-                self.phased_update_percentage)
+                name, das.architecturetag, component=component,
+                section=section, priority=priority,
+                phased_update_percentage=self.phased_update_percentage)
             for name, das, component, section, priority in already_published]
 
 
@@ -317,7 +329,7 @@
     @classmethod
     def getComponentOverride(cls, component=None, return_component=False):
         # component can be a Component object or a component name.
-        if isinstance(component, Component):
+        if zope_isinstance(component, Component):
             component = component.name
         override_component_name = cls.DEBIAN_COMPONENT_OVERRIDE_MAP.get(
             component, cls.DEFAULT_OVERRIDE_COMPONENT)
@@ -326,15 +338,15 @@
         else:
             return override_component_name
 
-    def calculateSourceOverrides(self, archive, distroseries, pocket,
-                                 sources, source_component=None):
-        default_component = (
-            archive.default_component or
-            UnknownOverridePolicy.getComponentOverride(
-                source_component, return_component=True))
+    def calculateSourceOverrides(self, archive, distroseries, pocket, sources):
         return [
-            SourceOverride(source, default_component, None)
-            for source in sources]
+            SourceOverride(
+                override.source_package_name,
+                component=(
+                    archive.default_component or
+                    UnknownOverridePolicy.getComponentOverride(
+                        override.component, return_component=True)))
+            for override in sources]
 
     def calculateBinaryOverrides(self, archive, distroseries, pocket,
                                  binaries):
@@ -342,9 +354,10 @@
             IComponentSet)['universe']
         return [
             BinaryOverride(
-                binary, das, default_component, None, None,
-                self.phased_update_percentage)
-            for binary, das in calculate_target_das(distroseries, binaries)]
+                override.binary_package_name, override.architecture_tag,
+                component=default_component,
+                phased_update_percentage=self.phased_update_percentage)
+            for override in binaries]
 
 
 class UbuntuOverridePolicy(FromExistingOverridePolicy,
@@ -355,36 +368,39 @@
     unknown policy.
     """
 
-    def calculateSourceOverrides(self, archive, distroseries, pocket,
-                                 sources, source_component=None):
-        total = set(sources)
+    def calculateSourceOverrides(self, archive, distroseries, pocket, sources):
+        spns = [override.source_package_name for override in sources]
+        total = set(spns)
         overrides = FromExistingOverridePolicy.calculateSourceOverrides(
-            self, archive, distroseries, pocket, sources, source_component,
-            include_deleted=True)
+            self, archive, distroseries, pocket, sources, include_deleted=True)
         existing = set(override.source_package_name for override in overrides)
         missing = total.difference(existing)
         if missing:
             unknown = UnknownOverridePolicy.calculateSourceOverrides(
-                self, archive, distroseries, pocket, missing, source_component)
+                self, archive, distroseries, pocket,
+                [override for override in sources
+                 if override.source_package_name in missing])
             overrides.extend(unknown)
         return overrides
 
     def calculateBinaryOverrides(self, archive, distroseries, pocket,
                                  binaries):
-        total = set(binaries)
+        total = set(
+            (override.binary_package_name, override.architecture_tag)
+            for override in binaries)
         overrides = FromExistingOverridePolicy.calculateBinaryOverrides(
             self, archive, distroseries, pocket, binaries,
             include_deleted=True)
         existing = set(
-            (
-                override.binary_package_name,
-                override.distro_arch_series.architecturetag,
-            )
+            (override.binary_package_name, override.architecture_tag)
             for override in overrides)
         missing = total.difference(existing)
         if missing:
             unknown = UnknownOverridePolicy.calculateBinaryOverrides(
-                self, archive, distroseries, pocket, missing)
+                self, archive, distroseries, pocket,
+                [override for override in binaries
+                 if (override.binary_package_name, override.architecture_tag)
+                 in missing])
             overrides.extend(unknown)
         return overrides
 

=== modified file 'lib/lp/soyuz/adapters/tests/test_overrides.py'
--- lib/lp/soyuz/adapters/tests/test_overrides.py	2013-06-21 09:36:02 +0000
+++ lib/lp/soyuz/adapters/tests/test_overrides.py	2014-07-17 13:39:24 +0000
@@ -8,6 +8,7 @@
 from testtools.matchers import Equals
 from zope.component import getUtility
 
+from lp.registry.interfaces.pocket import PackagePublishingPocket
 from lp.services.database import bulk
 from lp.services.database.sqlbase import flush_database_caches
 from lp.soyuz.adapters.overrides import (
@@ -23,23 +24,24 @@
     StormStatementRecorder,
     TestCaseWithFactory,
     )
-from lp.testing.layers import LaunchpadZopelessLayer
+from lp.testing.layers import ZopelessDatabaseLayer
 from lp.testing.matchers import HasQueryCount
 
 
-class TestOverrides(TestCaseWithFactory):
+class TestFromExistingOverridePolicy(TestCaseWithFactory):
 
-    layer = LaunchpadZopelessLayer
+    layer = ZopelessDatabaseLayer
 
     def test_no_source_overrides(self):
-        # If the spn is not published in the given archive/distroseries, an
-        # empty list is returned.
+        # If the spn is not published in the given archive/distroseries,
+        # no changes are made.
         spn = self.factory.makeSourcePackageName()
         distroseries = self.factory.makeDistroSeries()
         pocket = self.factory.getAnyPocket()
         policy = FromExistingOverridePolicy()
         overrides = policy.calculateSourceOverrides(
-            distroseries.main_archive, distroseries, pocket, (spn,))
+            distroseries.main_archive, distroseries, pocket,
+            [SourceOverride(spn)])
         self.assertEqual([], overrides)
 
     def test_source_overrides(self):
@@ -49,10 +51,10 @@
         policy = FromExistingOverridePolicy()
         overrides = policy.calculateSourceOverrides(
             spph.distroseries.main_archive, spph.distroseries, spph.pocket,
-            (spph.sourcepackagerelease.sourcepackagename,))
+            [SourceOverride(spph.sourcepackagerelease.sourcepackagename)])
         expected = [SourceOverride(
             spph.sourcepackagerelease.sourcepackagename,
-            spph.component, spph.section)]
+            component=spph.component, section=spph.section)]
         self.assertEqual(expected, overrides)
 
     def test_source_overrides_latest_only_is_returned(self):
@@ -72,9 +74,12 @@
             sourcepackagerelease=spr, distroseries=distroseries)
         policy = FromExistingOverridePolicy()
         overrides = policy.calculateSourceOverrides(
-            distroseries.main_archive, distroseries, spph.pocket, (spn,))
+            spph.distroseries.main_archive, spph.distroseries, spph.pocket,
+            [SourceOverride(spn)])
         self.assertEqual(
-            [SourceOverride(spn, spph.component, spph.section)], overrides)
+            [SourceOverride(
+                spn, component=spph.component, section=spph.section)],
+            overrides)
 
     def test_source_overrides_constant_query_count(self):
         # The query count is constant, no matter how many sources are
@@ -94,7 +99,7 @@
         with StormStatementRecorder() as recorder:
             policy.calculateSourceOverrides(
                 spph.distroseries.main_archive, spph.distroseries,
-                spph.pocket, spns)
+                spph.pocket, [SourceOverride(spn) for spn in spns])
         self.assertThat(recorder, HasQueryCount(Equals(4)))
 
     def test_no_binary_overrides(self):
@@ -107,25 +112,44 @@
         pocket = self.factory.getAnyPocket()
         policy = FromExistingOverridePolicy()
         overrides = policy.calculateBinaryOverrides(
-            distroseries.main_archive, distroseries, pocket, ((bpn, None),))
+            distroseries.main_archive, distroseries, pocket,
+            [BinaryOverride(bpn, None)])
         self.assertEqual([], overrides)
 
     def test_binary_overrides(self):
         # When a binary is published in the given distroarchseries, the
         # overrides are returned.
-        bpph = self.factory.makeBinaryPackagePublishingHistory()
-        distroseries = bpph.distroarchseries.distroseries
-        distroseries.nominatedarchindep = bpph.distroarchseries
+        distroseries = self.factory.makeDistroSeries()
+        bpph1 = self.factory.makeBinaryPackagePublishingHistory(
+            archive=distroseries.main_archive,
+            distroarchseries=self.factory.makeDistroArchSeries(distroseries))
+        bpph2 = self.factory.makeBinaryPackagePublishingHistory(
+            archive=distroseries.main_archive, pocket=bpph1.pocket,
+            distroarchseries=self.factory.makeDistroArchSeries(distroseries))
+        distroseries.nominatedarchindep = bpph1.distroarchseries
         policy = FromExistingOverridePolicy()
         overrides = policy.calculateBinaryOverrides(
-            distroseries.main_archive, distroseries, bpph.pocket,
-            ((bpph.binarypackagerelease.binarypackagename, None),))
+            distroseries.main_archive, distroseries, bpph1.pocket,
+            [BinaryOverride(
+                bpph1.binarypackagerelease.binarypackagename,
+                bpph1.distroarchseries.architecturetag),
+             BinaryOverride(
+                bpph2.binarypackagerelease.binarypackagename,
+                bpph2.distroarchseries.architecturetag),
+            ])
         expected = [
             BinaryOverride(
-                bpph.binarypackagerelease.binarypackagename,
-                bpph.distroarchseries, bpph.component, bpph.section,
-                bpph.priority, None)]
-        self.assertEqual(expected, overrides)
+                bpph1.binarypackagerelease.binarypackagename,
+                bpph1.distroarchseries.architecturetag,
+                component=bpph1.component, section=bpph1.section,
+                priority=bpph1.priority),
+            BinaryOverride(
+                bpph2.binarypackagerelease.binarypackagename,
+                bpph2.distroarchseries.architecturetag,
+                component=bpph2.component, section=bpph2.section,
+                priority=bpph2.priority),
+            ]
+        self.assertContentEqual(expected, overrides)
 
     def test_binary_overrides_constant_query_count(self):
         # The query count is constant, no matter how many bpn-das pairs are
@@ -146,9 +170,15 @@
         policy = FromExistingOverridePolicy()
         with StormStatementRecorder() as recorder:
             policy.calculateBinaryOverrides(
-                distroseries.main_archive, distroseries, pocket, bpns)
+                distroseries.main_archive, distroseries, pocket,
+                [BinaryOverride(bpn, das) for bpn, das in bpns])
         self.assertThat(recorder, HasQueryCount(Equals(4)))
 
+
+class TestUnknownOverridePolicy(TestCaseWithFactory):
+
+    layer = ZopelessDatabaseLayer
+
     def test_getComponentOverride_default_name(self):
         # getComponentOverride returns the default component name when an
         # unknown component name is passed.
@@ -175,18 +205,40 @@
         self.assertEqual(universe_component, component)
 
     def test_unknown_sources(self):
-        # If the unknown policy is used, it does no checks, just returns the
-        # defaults.
-        spph = self.factory.makeSourcePackagePublishingHistory()
-        policy = UnknownOverridePolicy()
-        overrides = policy.calculateSourceOverrides(
-            spph.distroseries.main_archive, spph.distroseries, spph.pocket,
-            (spph.sourcepackagerelease.sourcepackagename,))
-        universe = getUtility(IComponentSet)['universe']
-        expected = [
-            SourceOverride(
-                spph.sourcepackagerelease.sourcepackagename, universe,
-                None)]
+        # The unknown policy uses a default component based on the
+        # pre-override component.
+        for component in ('contrib', 'non-free'):
+            self.factory.makeComponent(component)
+        distroseries = self.factory.makeDistroSeries()
+        spns = [self.factory.makeSourcePackageName() for i in range(3)]
+        overrides = UnknownOverridePolicy().calculateSourceOverrides(
+            distroseries.main_archive, distroseries,
+            PackagePublishingPocket.RELEASE,
+            [SourceOverride(
+                spn, component=getUtility(IComponentSet)[component])
+             for spn, component in zip(spns, ('main', 'contrib', 'non-free'))])
+        expected = [
+            SourceOverride(spn, component=getUtility(IComponentSet)[component])
+            for spn, component in
+            zip(spns, ('universe', 'multiverse', 'multiverse'))]
+        self.assertEqual(expected, overrides)
+
+    def test_unknown_sources_ppa(self):
+        # The unknown policy overrides everything to the archive's
+        # default component, if it has one.
+        for component in ('contrib', 'non-free'):
+            self.factory.makeComponent(component)
+        distroseries = self.factory.makeDistroSeries()
+        spns = [self.factory.makeSourcePackageName() for i in range(3)]
+        overrides = UnknownOverridePolicy().calculateSourceOverrides(
+            self.factory.makeArchive(distribution=distroseries.distribution),
+            distroseries, PackagePublishingPocket.RELEASE,
+            [SourceOverride(
+                spn, component=getUtility(IComponentSet)[component])
+             for spn, component in zip(spns, ('main', 'contrib', 'non-free'))])
+        expected = [
+            SourceOverride(spn, component=getUtility(IComponentSet)[component])
+            for spn, component in zip(spns, ('main', 'main', 'main'))]
         self.assertEqual(expected, overrides)
 
     def test_unknown_binaries(self):
@@ -198,20 +250,26 @@
         policy = UnknownOverridePolicy()
         overrides = policy.calculateBinaryOverrides(
             distroseries.main_archive, distroseries, bpph.pocket,
-            ((bpph.binarypackagerelease.binarypackagename, None),))
+            [BinaryOverride(
+                bpph.binarypackagerelease.binarypackagename, None)])
         universe = getUtility(IComponentSet)['universe']
         expected = [
             BinaryOverride(
-                bpph.binarypackagerelease.binarypackagename,
-                bpph.distroarchseries, universe, None, None, None)]
+                bpph.binarypackagerelease.binarypackagename, None,
+                component=universe)]
         self.assertEqual(expected, overrides)
 
+
+class TestUbuntuOverridePolicy(TestCaseWithFactory):
+
+    layer = ZopelessDatabaseLayer
+
     def test_ubuntu_override_policy_sources(self):
         # The Ubuntu policy incorporates both the existing and the unknown
         # policy.
         universe = getUtility(IComponentSet)['universe']
         spns = [self.factory.makeSourcePackageName()]
-        expected = [SourceOverride(spns[0], universe, None)]
+        expected = [SourceOverride(spns[0], component=universe)]
         distroseries = self.factory.makeDistroSeries()
         pocket = self.factory.getAnyPocket()
         for i in xrange(8):
@@ -222,12 +280,14 @@
             expected.append(
                 SourceOverride(
                     spph.sourcepackagerelease.sourcepackagename,
-                    spph.component, spph.section))
+                    component=spph.component, section=spph.section))
         spns.append(self.factory.makeSourcePackageName())
-        expected.append(SourceOverride(spns[-1], universe, None))
+        expected.append(
+            SourceOverride(spns[-1], component=universe, section=None))
         policy = UbuntuOverridePolicy()
         overrides = policy.calculateSourceOverrides(
-            distroseries.main_archive, distroseries, pocket, spns)
+            distroseries.main_archive, distroseries, pocket,
+            [SourceOverride(spn) for spn in spns])
         self.assertEqual(10, len(overrides))
         sorted_expected = sorted(
             expected, key=attrgetter("source_package_name.name"))
@@ -258,23 +318,24 @@
             bpns.append((bpn, distroarchseries.architecturetag))
             expected.append(
                 BinaryOverride(
-                    bpn, distroarchseries, bpph.component, bpph.section,
-                    bpph.priority, None))
+                    bpn, distroarchseries.architecturetag,
+                    component=bpph.component, section=bpph.section,
+                    priority=bpph.priority))
         for i in xrange(2):
             distroarchseries = self.factory.makeDistroArchSeries(
                 distroseries=distroseries)
             bpns.append((bpn, distroarchseries.architecturetag))
             expected.append(
                 BinaryOverride(
-                    bpn, distroarchseries, universe, None, None, None))
+                    bpn, distroarchseries.architecturetag, component=universe))
         distroseries.nominatedarchindep = distroarchseries
         policy = UbuntuOverridePolicy()
         overrides = policy.calculateBinaryOverrides(
-            distroseries.main_archive, distroseries, pocket, bpns)
+            distroseries.main_archive, distroseries, pocket,
+            [BinaryOverride(bpn, das) for bpn, das in bpns])
         self.assertEqual(5, len(overrides))
-        key = attrgetter("binary_package_name.name",
-            "distro_arch_series.architecturetag",
-            "component.name")
+        key = attrgetter(
+            "binary_package_name.name", "architecture_tag", "component.name")
         sorted_expected = sorted(expected, key=key)
         sorted_overrides = sorted(overrides, key=key)
         self.assertEqual(sorted_expected, sorted_overrides)
@@ -292,7 +353,8 @@
         pocket = self.factory.getAnyPocket()
         policy = FromExistingOverridePolicy()
         overrides = policy.calculateBinaryOverrides(
-            distroseries.main_archive, distroseries, pocket, ((bpn, 'i386'),))
+            distroseries.main_archive, distroseries, pocket,
+            [BinaryOverride(bpn, 'i386')])
 
         self.assertEqual([], overrides)
 
@@ -317,21 +379,24 @@
         bpns.append((bpn, distroarchseries.architecturetag))
         expected.append(
             BinaryOverride(
-                bpn, distroarchseries, bpph.component, bpph.section,
-                bpph.priority, 50))
+                bpn, distroarchseries.architecturetag,
+                component=bpph.component, section=bpph.section,
+                priority=bpph.priority, phased_update_percentage=50))
         distroarchseries = self.factory.makeDistroArchSeries(
             distroseries=distroseries)
         bpns.append((bpn, distroarchseries.architecturetag))
         expected.append(
-            BinaryOverride(bpn, distroarchseries, universe, None, None, 50))
+            BinaryOverride(
+                bpn, distroarchseries.architecturetag, component=universe,
+                phased_update_percentage=50))
         distroseries.nominatedarchindep = distroarchseries
         policy = UbuntuOverridePolicy(phased_update_percentage=50)
         overrides = policy.calculateBinaryOverrides(
-            distroseries.main_archive, distroseries, pocket, bpns)
+            distroseries.main_archive, distroseries, pocket,
+            [BinaryOverride(bpn, das) for bpn, das in bpns])
         self.assertEqual(2, len(overrides))
-        key = attrgetter("binary_package_name.name",
-            "distro_arch_series.architecturetag",
-            "component.name")
+        key = attrgetter(
+            "binary_package_name.name", "architecture_tag", "component.name")
         sorted_expected = sorted(expected, key=key)
         sorted_overrides = sorted(overrides, key=key)
         self.assertEqual(sorted_expected, sorted_overrides)

=== modified file 'lib/lp/soyuz/model/packagecopyjob.py'
--- lib/lp/soyuz/model/packagecopyjob.py	2014-07-09 01:25:05 +0000
+++ lib/lp/soyuz/model/packagecopyjob.py	2014-07-17 13:39:24 +0000
@@ -501,7 +501,8 @@
         except NotFoundError:
             section = None
 
-        return SourceOverride(source_package_name, component, section)
+        return SourceOverride(
+            source_package_name, component=component, section=section)
 
     def findSourcePublication(self):
         """Find the appropriate origin `ISourcePackagePublishingHistory`."""
@@ -523,7 +524,7 @@
         override_policy = FromExistingOverridePolicy()
         ancestry = override_policy.calculateSourceOverrides(
             self.target_archive, self.target_distroseries,
-            self.target_pocket, [source_name])
+            self.target_pocket, [SourceOverride(source_name)])
 
         copy_policy = self.getPolicyImplementation()
 
@@ -532,7 +533,8 @@
             # metadata.
             defaults = UnknownOverridePolicy().calculateSourceOverrides(
                 self.target_archive, self.target_distroseries,
-                self.target_pocket, [source_name], source_component)
+                self.target_pocket,
+                [SourceOverride(source_name, component=source_component)])
             self.addSourceOverride(defaults[0])
             if auto_approve:
                 auto_approve = self.target_archive.canAdministerQueue(

=== modified file 'lib/lp/soyuz/model/publishing.py'
--- lib/lp/soyuz/model/publishing.py	2014-07-08 05:05:19 +0000
+++ lib/lp/soyuz/model/publishing.py	2014-07-17 13:39:24 +0000
@@ -1445,6 +1445,7 @@
 
     def copyBinaries(self, archive, distroseries, pocket, bpphs, policy=None):
         """See `IPublishingSet`."""
+        from lp.soyuz.adapters.overrides import BinaryOverride
         if distroseries.distribution != archive.distribution:
             raise AssertionError(
                 "Series distribution %s doesn't match archive distribution %s."
@@ -1477,13 +1478,12 @@
                     bpph.distroarchseries.architecturetag)] = bpph
             with_overrides = {}
             overrides = policy.calculateBinaryOverrides(
-                archive, distroseries, pocket, bpn_archtag.keys())
+                archive, distroseries, pocket,
+                [BinaryOverride(bpn, archtag)
+                 for bpn, archtag in bpn_archtag.keys()])
             for override in overrides:
-                if override.distro_arch_series is None:
-                    continue
                 bpph = bpn_archtag[
-                    (override.binary_package_name,
-                     override.distro_arch_series.architecturetag)]
+                    (override.binary_package_name, override.architecture_tag)]
                 new_component = override.component or bpph.component
                 new_section = override.section or bpph.section
                 new_priority = override.priority or bpph.priority

=== modified file 'lib/lp/soyuz/scripts/packagecopier.py'
--- lib/lp/soyuz/scripts/packagecopier.py	2013-07-16 08:10:32 +0000
+++ lib/lp/soyuz/scripts/packagecopier.py	2014-07-17 13:39:24 +0000
@@ -23,6 +23,7 @@
 
 from lp.services.database.bulk import load_related
 from lp.soyuz.adapters.notification import notify
+from lp.soyuz.adapters.overrides import SourceOverride
 from lp.soyuz.enums import (
     BinaryPackageFileType,
     SourcePackageFormat,
@@ -38,6 +39,7 @@
 from lp.soyuz.interfaces.queue import IPackageUploadCustom
 from lp.soyuz.scripts.custom_uploads_copier import CustomUploadsCopier
 
+
 # XXX cprov 2009-06-12: this function should be incorporated in
 # IPublishing.
 def update_files_privacy(pub_record):
@@ -720,7 +722,8 @@
             # Only one override can be returned so take the first
             # element of the returned list.
             overrides = policy.calculateSourceOverrides(
-                archive, series, pocket, package_names)
+                archive, series, pocket,
+                [SourceOverride(spn) for spn in package_names])
             # Only one override can be returned so take the first
             # element of the returned list.
             assert len(overrides) == 1, (

=== modified file 'lib/lp/soyuz/tests/test_packagecopyjob.py'
--- lib/lp/soyuz/tests/test_packagecopyjob.py	2014-07-09 02:42:47 +0000
+++ lib/lp/soyuz/tests/test_packagecopyjob.py	2014-07-17 13:39:24 +0000
@@ -832,7 +832,8 @@
         package = source_package.sourcepackagerelease.sourcepackagename
         restricted = getUtility(IComponentSet)['restricted']
         editors = getUtility(ISectionSet)['editors']
-        override = SourceOverride(package, restricted, editors)
+        override = SourceOverride(
+            package, component=restricted, section=editors)
         job.addSourceOverride(override)
 
         # Accept the upload to release the job then run it.
@@ -1525,12 +1526,10 @@
         old_component = self.factory.makeComponent()
         old_section = self.factory.makeSection()
         pcj.addSourceOverride(SourceOverride(
-            source_package_name=pcj.package_name,
-            component=old_component, section=old_section))
+            pcj.package_name, component=old_component, section=old_section))
         new_section = self.factory.makeSection()
         pcj.addSourceOverride(SourceOverride(
-            source_package_name=pcj.package_name,
-            component=None, section=new_section))
+            pcj.package_name, section=new_section))
         self.assertEqual(old_component.name, pcj.component_name)
         self.assertEqual(new_section.name, pcj.section_name)
 
@@ -1542,12 +1541,10 @@
         old_component = self.factory.makeComponent()
         old_section = self.factory.makeSection()
         pcj.addSourceOverride(SourceOverride(
-            source_package_name=pcj.package_name,
-            component=old_component, section=old_section))
+            pcj.package_name, component=old_component, section=old_section))
         new_component = self.factory.makeComponent()
         pcj.addSourceOverride(SourceOverride(
-            source_package_name=pcj.package_name,
-            component=new_component, section=None))
+            pcj.package_name, component=new_component))
         self.assertEqual(new_component.name, pcj.component_name)
         self.assertEqual(old_section.name, pcj.section_name)
 
@@ -1561,8 +1558,7 @@
             package_name=name.name, package_version="1.0")
         switch_dbuser('copy_packages')
 
-        override = SourceOverride(
-            source_package_name=name, component=component, section=section)
+        override = SourceOverride(name, component=component, section=section)
         pcj.addSourceOverride(override)
 
         self.assertEqual(override, pcj.getSourceOverride())


Follow ups