launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #21519
[Merge] lp:~cjwatson/launchpad/archive-dependencies-unittest into lp:launchpad
Colin Watson has proposed merging lp:~cjwatson/launchpad/archive-dependencies-unittest into lp:launchpad.
Commit message:
Convert archive-dependencies.txt to unit tests. Make InvalidExternalDependencies have a slightly more sensible message in the process.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/archive-dependencies-unittest/+merge/323129
I needed to do this to make it less painful to change get_sources_list_for_building to talk to the keyserver, which I need in order to fix bug 1626739.
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/archive-dependencies-unittest into lp:launchpad.
=== added file 'lib/lp/soyuz/adapters/tests/test_archivedependencies.py'
--- lib/lp/soyuz/adapters/tests/test_archivedependencies.py 1970-01-01 00:00:00 +0000
+++ lib/lp/soyuz/adapters/tests/test_archivedependencies.py 2017-04-25 11:44:32 +0000
@@ -0,0 +1,517 @@
+# Copyright 2017 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Test archive dependencies."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+
+from testtools.matchers import StartsWith
+import transaction
+from zope.component import getUtility
+
+from lp.registry.interfaces.distribution import IDistributionSet
+from lp.registry.interfaces.pocket import PackagePublishingPocket
+from lp.services.log.logger import BufferLogger
+from lp.soyuz.adapters.archivedependencies import (
+ default_component_dependency_name,
+ default_pocket_dependency,
+ get_components_for_context,
+ get_primary_current_component,
+ get_sources_list_for_building,
+ pocket_dependencies,
+ )
+from lp.soyuz.enums import PackagePublishingStatus
+from lp.soyuz.interfaces.archive import IArchive
+from lp.soyuz.interfaces.component import IComponentSet
+from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
+from lp.testing import TestCaseWithFactory
+from lp.testing.layers import (
+ LaunchpadZopelessLayer,
+ ZopelessDatabaseLayer,
+ )
+
+
+class TestOgreModel(TestCaseWithFactory):
+ """Test ogre-model component handling.
+
+ The Ubuntu "ogre model" (cf. Shrek) ensures that build-dependencies are
+ consistent with the component in which the source is published.
+ """
+
+ layer = ZopelessDatabaseLayer
+
+ def setUpComponents(self, distroseries, component_names):
+ for component_name in component_names:
+ component = getUtility(IComponentSet)[component_name]
+ self.factory.makeComponentSelection(distroseries, component)
+
+ def assertComponentMap(self, expected, distroseries, pocket):
+ for component_name, expected_components in expected.items():
+ component = getUtility(IComponentSet)[component_name]
+ self.assertEqual(
+ expected_components,
+ get_components_for_context(component, distroseries, pocket))
+
+ def test_strict_supported_component_dependencies(self):
+ # In strict-supported-component-dependencies mode, a source
+ # published in main is only allowed to build-depend on binaries also
+ # published in main, while a source published in universe is allowed
+ # to build-depend on main and universe.
+ distroseries = self.factory.makeDistroSeries()
+ expected = {
+ "main": ["main"],
+ "restricted": ["main", "restricted"],
+ "universe": ["main", "universe"],
+ "multiverse": ["main", "restricted", "universe", "multiverse"],
+ "partner": ["partner"],
+ }
+ self.setUpComponents(distroseries, expected.keys())
+ self.assertComponentMap(
+ expected, distroseries, PackagePublishingPocket.RELEASE)
+
+ def test_lax_supported_component_dependencies(self):
+ # In lax-supported-component-dependencies mode, source packages in
+ # "supported" components (main and restricted) may additionally
+ # build-depend on binary packages in "unsupported" components
+ # (universe and multiverse).
+ distroseries = self.factory.makeDistroSeries()
+ distroseries.strict_supported_component_dependencies = False
+ expected = {
+ "main": ["main", "universe"],
+ "restricted": ["main", "restricted", "universe", "multiverse"],
+ "universe": ["main", "universe"],
+ "multiverse": ["main", "restricted", "universe", "multiverse"],
+ "partner": ["partner"],
+ }
+ self.setUpComponents(distroseries, expected.keys())
+ self.assertComponentMap(
+ expected, distroseries, PackagePublishingPocket.RELEASE)
+
+ def test_backports(self):
+ # Source packages in the BACKPORTS pocket are allowed to
+ # build-depend on binary packages in any component. This avoids
+ # having to make potentially-invasive changes to accommodate
+ # backporting to stable series.
+ distroseries = self.factory.makeDistroSeries()
+ expected = {
+ "main": ["main", "restricted", "universe", "multiverse"],
+ "restricted": ["main", "restricted", "universe", "multiverse"],
+ "universe": ["main", "restricted", "universe", "multiverse"],
+ "multiverse": ["main", "restricted", "universe", "multiverse"],
+ "partner": ["main", "restricted", "universe", "multiverse"],
+ }
+ self.setUpComponents(distroseries, expected.keys())
+ self.assertComponentMap(
+ expected, distroseries, PackagePublishingPocket.BACKPORTS)
+
+
+class TestSourcesList(TestCaseWithFactory):
+ """Test sources.list contents for building, and related mechanisms."""
+
+ layer = LaunchpadZopelessLayer
+
+ ubuntu_components = [
+ "main", "restricted", "universe", "multiverse", "partner"]
+
+ def setUp(self):
+ super(TestSourcesList, self).setUp()
+ self.publisher = SoyuzTestPublisher()
+ self.ubuntu = getUtility(IDistributionSet).getByName("ubuntu")
+ self.hoary = self.ubuntu.getSeries("hoary")
+ self.publisher.addFakeChroots(self.hoary)
+ self.publisher.setUpDefaultDistroSeries(self.hoary)
+ for component_name in self.ubuntu_components:
+ component = getUtility(IComponentSet)[component_name]
+ if component not in self.hoary.components:
+ self.factory.makeComponentSelection(self.hoary, component)
+
+ def test_defaults(self):
+ # Non-primary archives by default use the Release, Security and
+ # Updates pockets from the primary archive, and all its available
+ # components.
+ self.assertEqual(
+ PackagePublishingPocket.UPDATES, default_pocket_dependency)
+ self.assertEqual("multiverse", default_component_dependency_name)
+ self.assertEqual(
+ (PackagePublishingPocket.RELEASE,
+ PackagePublishingPocket.SECURITY,
+ PackagePublishingPocket.UPDATES),
+ pocket_dependencies[default_pocket_dependency])
+
+ def makeArchive(self, publish_binary=False, **kwargs):
+ archive = self.factory.makeArchive(distribution=self.ubuntu, **kwargs)
+ if publish_binary:
+ self.publisher.getPubBinaries(
+ archive=archive, status=PackagePublishingStatus.PUBLISHED)
+ return archive
+
+ def makeBuild(self, **kwargs):
+ pub_source = self.publisher.getPubSource(**kwargs)
+ [build] = pub_source.createMissingBuilds()
+ return build
+
+ def assertPrimaryCurrentComponent(self, expected, build):
+ self.assertEqual(
+ expected,
+ get_primary_current_component(
+ build.archive, build.distro_series,
+ build.source_package_release.name).name)
+
+ def assertSourcesList(self, expected, build, **kwargs):
+ expected_lines = []
+ for archive_or_prefix, suffixes in expected:
+ if IArchive.providedBy(archive_or_prefix):
+ prefix = "deb %s " % archive_or_prefix.archive_url
+ else:
+ prefix = archive_or_prefix + " "
+ expected_lines.extend([prefix + suffix for suffix in suffixes])
+ sources_list = get_sources_list_for_building(
+ build, build.distro_arch_series, build.source_package_release.name,
+ **kwargs)
+ self.assertEqual(expected_lines, sources_list)
+
+ def test_ppa_with_no_binaries(self):
+ # If there are no published binaries in a PPA, only its primary
+ # archive dependencies need to be considered.
+ ppa = self.makeArchive()
+ build = self.makeBuild(archive=ppa)
+ self.assertEqual(
+ 0, ppa.getAllPublishedBinaries(
+ distroarchseries=build.distro_arch_series,
+ status=PackagePublishingStatus.PUBLISHED).count())
+ self.assertSourcesList(
+ [(self.ubuntu.main_archive, [
+ "hoary main restricted universe multiverse",
+ "hoary-security main restricted universe multiverse",
+ "hoary-updates main restricted universe multiverse",
+ ]),
+ ], build)
+
+ def test_ppa_with_binaries(self):
+ # If there are binaries published in a PPA, then the PPA is
+ # considered as well as its primary dependencies.
+ ppa = self.makeArchive(publish_binary=True)
+ build = self.makeBuild(archive=ppa)
+ self.assertSourcesList(
+ [(ppa, ["hoary main"]),
+ (self.ubuntu.main_archive, [
+ "hoary main restricted universe multiverse",
+ "hoary-security main restricted universe multiverse",
+ "hoary-updates main restricted universe multiverse",
+ ]),
+ ], build)
+
+ def test_dependent_ppa_with_no_binaries(self):
+ # A depended-upon PPA is not considered if it has no published
+ # binaries.
+ lower_ppa = self.makeArchive()
+ upper_ppa = self.makeArchive(publish_binary=True)
+ upper_ppa.addArchiveDependency(
+ lower_ppa, PackagePublishingPocket.RELEASE,
+ getUtility(IComponentSet)["main"])
+ build = self.makeBuild(archive=upper_ppa)
+ self.assertSourcesList(
+ [(upper_ppa, ["hoary main"]),
+ (self.ubuntu.main_archive, [
+ "hoary main restricted universe multiverse",
+ "hoary-security main restricted universe multiverse",
+ "hoary-updates main restricted universe multiverse",
+ ]),
+ ], build)
+
+ def test_dependent_ppa_with_binaries(self):
+ # A depended-upon PPA is considered if it has published binaries.
+ lower_ppa = self.makeArchive(publish_binary=True)
+ upper_ppa = self.makeArchive(publish_binary=True)
+ upper_ppa.addArchiveDependency(
+ lower_ppa, PackagePublishingPocket.RELEASE,
+ getUtility(IComponentSet)["main"])
+ build = self.makeBuild(archive=upper_ppa)
+ self.assertSourcesList(
+ [(upper_ppa, ["hoary main"]),
+ (lower_ppa, ["hoary main"]),
+ (self.ubuntu.main_archive, [
+ "hoary main restricted universe multiverse",
+ "hoary-security main restricted universe multiverse",
+ "hoary-updates main restricted universe multiverse",
+ ]),
+ ], build)
+
+ def test_lax_supported_component_dependencies(self):
+ # Dependencies for series with
+ # strict_supported_component_dependencies=False are reasonable.
+ # PPAs only have the "main" component.
+ lower_ppa = self.makeArchive(publish_binary=True)
+ upper_ppa = self.makeArchive(publish_binary=True)
+ upper_ppa.addArchiveDependency(
+ lower_ppa, PackagePublishingPocket.RELEASE,
+ getUtility(IComponentSet)["main"])
+ upper_ppa.addArchiveDependency(
+ self.ubuntu.main_archive, PackagePublishingPocket.UPDATES,
+ getUtility(IComponentSet)["restricted"])
+ build = self.makeBuild(archive=upper_ppa)
+ self.assertSourcesList(
+ [(upper_ppa, ["hoary main"]),
+ (lower_ppa, ["hoary main"]),
+ (self.ubuntu.main_archive, [
+ "hoary main restricted",
+ "hoary-security main restricted",
+ "hoary-updates main restricted",
+ ]),
+ ], build)
+ self.hoary.strict_supported_component_dependencies = False
+ transaction.commit()
+ self.assertSourcesList(
+ [(upper_ppa, ["hoary main"]),
+ (lower_ppa, ["hoary main"]),
+ (self.ubuntu.main_archive, [
+ "hoary main restricted universe multiverse",
+ "hoary-security main restricted universe multiverse",
+ "hoary-updates main restricted universe multiverse",
+ ]),
+ ], build)
+
+ def test_no_op_primary_archive_dependency(self):
+ # Overriding the default primary archive dependencies with exactly
+ # the same values has no effect.
+ ppa = self.makeArchive()
+ ppa.addArchiveDependency(
+ self.ubuntu.main_archive, PackagePublishingPocket.UPDATES,
+ getUtility(IComponentSet)["multiverse"])
+ build = self.makeBuild(archive=ppa)
+ self.assertSourcesList(
+ [(self.ubuntu.main_archive, [
+ "hoary main restricted universe multiverse",
+ "hoary-security main restricted universe multiverse",
+ "hoary-updates main restricted universe multiverse",
+ ]),
+ ], build)
+
+ def test_primary_archive_dependency_security(self):
+ # The primary archive dependency can be modified to behave as an
+ # embargoed archive that builds security updates. This is done by
+ # setting the SECURITY pocket dependencies (RELEASE and SECURITY)
+ # and following the component dependencies of the component where
+ # the source was last published in the primary archive.
+ ppa = self.makeArchive()
+ ppa.addArchiveDependency(
+ self.ubuntu.main_archive, PackagePublishingPocket.SECURITY)
+ build = self.makeBuild(archive=ppa)
+ self.assertPrimaryCurrentComponent("universe", build)
+ self.assertSourcesList(
+ [(self.ubuntu.main_archive, [
+ "hoary main universe",
+ "hoary-security main universe",
+ ]),
+ ], build)
+ self.publisher.getPubSource(
+ sourcename="with-ancestry", version="1.0",
+ archive=self.ubuntu.main_archive)
+ [build_with_ancestry] = self.publisher.getPubSource(
+ sourcename="with-ancestry", version="1.1",
+ archive=ppa).createMissingBuilds()
+ self.assertPrimaryCurrentComponent("main", build_with_ancestry)
+ self.assertSourcesList(
+ [(self.ubuntu.main_archive, [
+ "hoary main",
+ "hoary-security main",
+ ]),
+ ], build_with_ancestry)
+
+ def test_primary_archive_dependency_release(self):
+ # The primary archive dependency can be modified to behave as a
+ # pristine build environment based only on what was included in the
+ # original release of the corresponding series.
+ ppa = self.makeArchive()
+ ppa.addArchiveDependency(
+ self.ubuntu.main_archive, PackagePublishingPocket.RELEASE,
+ getUtility(IComponentSet)["restricted"])
+ build = self.makeBuild(archive=ppa)
+ self.assertSourcesList(
+ [(self.ubuntu.main_archive, ["hoary main restricted"])], build)
+
+ def test_primary_archive_dependency_proposed(self):
+ # The primary archive dependency can be modified to extend the build
+ # environment for PROPOSED.
+ ppa = self.makeArchive()
+ ppa.addArchiveDependency(
+ self.ubuntu.main_archive, PackagePublishingPocket.PROPOSED,
+ getUtility(IComponentSet)["multiverse"])
+ build = self.makeBuild(archive=ppa)
+ self.assertSourcesList(
+ [(self.ubuntu.main_archive, [
+ "hoary main restricted universe multiverse",
+ "hoary-security main restricted universe multiverse",
+ "hoary-updates main restricted universe multiverse",
+ "hoary-proposed main restricted universe multiverse",
+ ]),
+ ], build)
+
+ def test_primary_archive_dependency_backports(self):
+ # The primary archive dependency can be modified to extend the build
+ # environment for PROPOSED.
+ ppa = self.makeArchive()
+ ppa.addArchiveDependency(
+ self.ubuntu.main_archive, PackagePublishingPocket.BACKPORTS,
+ getUtility(IComponentSet)["multiverse"])
+ build = self.makeBuild(archive=ppa)
+ self.assertSourcesList(
+ [(self.ubuntu.main_archive, [
+ "hoary main restricted universe multiverse",
+ "hoary-security main restricted universe multiverse",
+ "hoary-updates main restricted universe multiverse",
+ "hoary-backports main restricted universe multiverse",
+ ]),
+ ], build)
+
+ def test_partner(self):
+ # Similarly to what happens with PPA builds, partner builds may
+ # depend on any component in the primary archive. This behaviour
+ # allows scenarios where partner packages may use other
+ # restricted/non-free applications from multiverse, and also other
+ # partner applications.
+ primary, partner = self.ubuntu.all_distro_archives
+ self.publisher.getPubBinaries(
+ archive=partner, component="partner",
+ status=PackagePublishingStatus.PUBLISHED)
+ build = self.makeBuild(archive=partner, component="partner")
+ self.assertSourcesList(
+ [(partner, ["hoary partner"]),
+ (primary, [
+ "hoary main restricted universe multiverse",
+ "hoary-security main restricted universe multiverse",
+ "hoary-updates main restricted universe multiverse",
+ ]),
+ ], build)
+
+ def test_partner_proposed(self):
+ # The partner archive's PROPOSED pocket builds against itself, but
+ # still uses the default UPDATES dependency for the primary archive
+ # unless overridden by ArchiveDependency.
+ primary, partner = self.ubuntu.all_distro_archives
+ self.publisher.getPubBinaries(
+ archive=partner, component="partner",
+ status=PackagePublishingStatus.PUBLISHED)
+ self.publisher.getPubBinaries(
+ archive=partner, component="partner",
+ status=PackagePublishingStatus.PUBLISHED,
+ pocket=PackagePublishingPocket.PROPOSED)
+ build = self.makeBuild(
+ archive=partner, component="partner",
+ pocket=PackagePublishingPocket.PROPOSED)
+ self.assertSourcesList(
+ [(partner, [
+ "hoary partner",
+ "hoary-proposed partner",
+ ]),
+ (primary, [
+ "hoary main restricted universe multiverse",
+ "hoary-security main restricted universe multiverse",
+ "hoary-updates main restricted universe multiverse",
+ ]),
+ ], build)
+
+ def test_archive_external_dependencies(self):
+ # An archive can be manually given additional external dependencies.
+ # If present, "%(series)s" is replaced with the series name for the
+ # build being dispatched.
+ ppa = self.makeArchive(publish_binary=True)
+ ppa.external_dependencies = (
+ "deb http://user:pass@repository zoing everything\n"
+ "deb http://user:pass@repository %(series)s public private\n"
+ "deb http://user:pass@repository %(series)s-extra public")
+ build = self.makeBuild(archive=ppa)
+ self.assertSourcesList(
+ [(ppa, ["hoary main"]),
+ ("deb http://user:pass@repository", [
+ "zoing everything",
+ "hoary public private",
+ "hoary-extra public",
+ ]),
+ (self.ubuntu.main_archive, [
+ "hoary main restricted universe multiverse",
+ "hoary-security main restricted universe multiverse",
+ "hoary-updates main restricted universe multiverse",
+ ]),
+ ], build)
+
+ def test_build_external_dependencies(self):
+ # A single build can be manually given additional external
+ # dependencies.
+ ppa = self.makeArchive(publish_binary=True)
+ build = self.makeBuild(archive=ppa)
+ build.api_external_dependencies = (
+ "deb http://user:pass@repository foo bar")
+ self.assertSourcesList(
+ [(ppa, ["hoary main"]),
+ ("deb http://user:pass@repository", ["foo bar"]),
+ (self.ubuntu.main_archive, [
+ "hoary main restricted universe multiverse",
+ "hoary-security main restricted universe multiverse",
+ "hoary-updates main restricted universe multiverse",
+ ]),
+ ], build)
+
+ def test_build_tools(self):
+ # We can force an extra build tools line to be added to
+ # sources.list, which is useful for specialised build types.
+ ppa = self.makeArchive(publish_binary=True)
+ build = self.makeBuild(archive=ppa)
+ self.assertSourcesList(
+ [(ppa, ["hoary main"]),
+ ("deb http://example.org", ["hoary main"]),
+ (self.ubuntu.main_archive, [
+ "hoary main restricted universe multiverse",
+ "hoary-security main restricted universe multiverse",
+ "hoary-updates main restricted universe multiverse",
+ ]),
+ ], build, tools_source="deb http://example.org %(series)s main")
+
+ def test_build_tools_bad_formatting(self):
+ # If tools_source is badly formatted, we log the error but don't
+ # blow up. (Note the missing "s" at the end of "%(series)".)
+ ppa = self.makeArchive(publish_binary=True)
+ build = self.makeBuild(archive=ppa)
+ logger = BufferLogger()
+ self.assertSourcesList(
+ [(ppa, ["hoary main"]),
+ (self.ubuntu.main_archive, [
+ "hoary main restricted universe multiverse",
+ "hoary-security main restricted universe multiverse",
+ "hoary-updates main restricted universe multiverse",
+ ]),
+ ],
+ build, tools_source="deb http://example.org %(series) main",
+ logger=logger)
+ self.assertThat(logger.getLogBuffer(), StartsWith(
+ "ERROR Exception processing build tools sources.list entry:\n"))
+
+ def test_overlay(self):
+ # An overlay distroseries is a derived distribution which works like
+ # a PPA. This means that the parent's details gets added to the
+ # sources.list passed to the builders.
+ depdistro = self.factory.makeDistribution(
+ "depdistro", publish_base_url="http://archive.launchpad.dev/")
+ depseries = self.factory.makeDistroSeries(
+ distribution=depdistro, name="depseries")
+ self.factory.makeDistroArchSeries(
+ distroseries=depseries, architecturetag="i386")
+ self.publisher.addFakeChroots(depseries)
+ for component_name in self.ubuntu_components:
+ component = getUtility(IComponentSet)[component_name]
+ self.factory.makeComponentSelection(depseries, component)
+ self.factory.makeDistroSeriesParent(
+ derived_series=self.hoary, parent_series=depseries,
+ initialized=True, is_overlay=True,
+ pocket=PackagePublishingPocket.SECURITY,
+ component=getUtility(IComponentSet)["universe"])
+ build = self.makeBuild()
+ self.assertSourcesList(
+ [(self.ubuntu.main_archive, ["hoary main"]),
+ (depdistro.main_archive, [
+ "depseries main universe",
+ "depseries-security main universe",
+ ]),
+ ], build)
=== removed file 'lib/lp/soyuz/doc/archive-dependencies.txt'
--- lib/lp/soyuz/doc/archive-dependencies.txt 2016-04-07 00:04:42 +0000
+++ lib/lp/soyuz/doc/archive-dependencies.txt 1970-01-01 00:00:00 +0000
@@ -1,637 +0,0 @@
-= Archive dependencies =
-
-`ArchiveDependencies` class models archive dependencies mechanics and
-is used to provided the contents of 'sources_list' file used to build
-sources in the given IBuildQueue context.
-
-
-== Testing scenario setup ==
-
-We use `SoyuzTestPublisher` to generate a source publications and
-build candidates for ubuntu/hoary.
-
- >>> from lp.registry.interfaces.distribution import IDistributionSet
- >>> from lp.soyuz.interfaces.component import IComponentSet
- >>> from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
- >>> from lp.testing import login
-
- >>> login('foo.bar@xxxxxxxxxxxxx')
-
- >>> test_publisher = SoyuzTestPublisher()
-
- >>> ubuntu = getUtility(IDistributionSet).getByName('ubuntu')
- >>> hoary = ubuntu.getSeries('hoary')
-
- >>> test_publisher.addFakeChroots(hoary)
- >>> _ = test_publisher.setUpDefaultDistroSeries(hoary)
-
- >>> ubuntu_components = [
- ... 'main', 'restricted', 'universe', 'multiverse', 'partner']
- >>> for component_name in ubuntu_components:
- ... component = getUtility(IComponentSet)[component_name]
- ... if component not in hoary.components:
- ... _ = factory.makeComponentSelection(hoary, component)
-
-
-== Static dependency maps ==
-
-`pocket_dependencies` contains a static map of the default ubuntu
-pocket dependencies.
-
- >>> from lp.soyuz.adapters.archivedependencies import pocket_dependencies
-
- >>> def show_pocket_deps():
- ... print "Pocket | Dependencies"
- ... print "----------+---------------"
- ... for (key, value) in sorted(pocket_dependencies.items()):
- ... print "%7s |" % (key.name,),
- ... for pocket in value:
- ... print pocket.name,
- ... print
-
- >>> show_pocket_deps()
- Pocket | Dependencies
- ----------+---------------
- RELEASE | RELEASE
- SECURITY | RELEASE SECURITY
- UPDATES | RELEASE SECURITY UPDATES
- PROPOSED | RELEASE SECURITY UPDATES PROPOSED
- BACKPORTS | RELEASE SECURITY UPDATES BACKPORTS
-
-
-== 'Ogre' components ==
-
-The ubuntu 'ogre-model' ensures that build dependencies are
-consistently spread according to the source target component, i.e. a
-source published in 'main' component is only allowed to depend on
-binaries also published in 'main', on the other hand a source
-published in 'universe' is allowed to depend on binaries published in
-'main' and 'universe' components.
-
-A proper name for this "model" would be 'cross-component-dependency'.
-
- >>> from lp.services.database.sqlbase import flush_database_caches
-
- >>> from zope.security.proxy import removeSecurityProxy
- >>> from lp.registry.interfaces.pocket import (
- ... PackagePublishingPocket)
- >>> from lp.soyuz.adapters.archivedependencies import (
- ... get_components_for_context)
- >>> from lp.soyuz.enums import ArchivePurpose
-
- >>> def testOgreComponents(build):
- ... print " Component | Ogre-Model"
- ... print "-----------+---------------"
- ... for component in ubuntu_components:
- ... component = getUtility(IComponentSet)[component]
- ... npub = removeSecurityProxy(build.current_source_publication)
- ... npub.component = component
- ... flush_database_caches()
- ... components_term = " ".join(get_components_for_context(
- ... build.current_component, build.distro_series,
- ... build.pocket))
- ... print '%10s | %s' % (build.current_component.name,
- ... components_term)
-
- >>> archive = factory.makeArchive(
- ... distribution=ubuntu, purpose=ArchivePurpose.PRIMARY)
- >>> ogre_build = factory.makeBinaryPackageBuild(
- ... distroarchseries=hoary.architectures[0], archive=archive,
- ... pocket=PackagePublishingPocket.RELEASE)
- >>> testOgreComponents(ogre_build)
- Component | Ogre-Model
- -----------+---------------
- main | main
- restricted | main restricted
- universe | main universe
- multiverse | main restricted universe multiverse
- partner | partner
-
-Series with strict_supported_component_dependencies=False additionally allow
-source packages in 'supported' components (main and restricted) to
-build-depend on binary packages in 'unsupported' components (universe and
-multiverse).
-
- >>> from lp.buildmaster.interfaces.processor import IProcessorSet
-
- >>> lax_distroseries = factory.makeDistroSeries(
- ... distribution=archive.distribution, name='lax')
- >>> lax_distroseries.strict_supported_component_dependencies = False
- >>> lax_distroarchseries = factory.makeDistroArchSeries(
- ... distroseries=lax_distroseries, architecturetag='i386',
- ... processor=getUtility(IProcessorSet).getByName('386'))
- >>> test_publisher.addFakeChroots(lax_distroseries)
- >>> for component_name in ubuntu_components:
- ... component = getUtility(IComponentSet)[component_name]
- ... _ = factory.makeComponentSelection(lax_distroseries, component)
- >>> lax_ogre_build = factory.makeBinaryPackageBuild(
- ... distroarchseries=lax_distroarchseries, archive=archive,
- ... pocket=PackagePublishingPocket.RELEASE)
- >>> testOgreComponents(lax_ogre_build)
- Component | Ogre-Model
- -----------+---------------
- main | main universe
- restricted | main restricted universe multiverse
- universe | main universe
- multiverse | main restricted universe multiverse
- partner | partner
-
-As fixed for bug #198936, builds for the BACKPORTS pocket are allowed
-to use any component available, independently of the component they
-are currently published. This special-case is important because it
-avoids changes to accommodate the backported source in the already
-released series.
-
-Ultimately, it means that a build targeted to the BACKPORTS pocket
-will behave as if it were published in the multiverse component,
-despite the component it is actually published in.
-
- >>> back_build = factory.makeBinaryPackageBuild(
- ... distroarchseries=hoary.architectures[0],
- ... archive=archive, pocket=PackagePublishingPocket.BACKPORTS)
- >>> testOgreComponents(back_build)
- Component | Ogre-Model
- -----------+---------------
- main | main restricted universe multiverse
- restricted | main restricted universe multiverse
- universe | main restricted universe multiverse
- multiverse | main restricted universe multiverse
- partner | main restricted universe multiverse
-
-
-== Sources.list contents for building ==
-
-We will use Celso's PPA for testing these mechanisms.
-
- >>> from lp.registry.interfaces.person import IPersonSet
- >>> cprov = getUtility(IPersonSet).getByName('cprov')
- >>> print cprov.archive.displayname
- PPA for Celso Providelo
-
-Non-primary archives by default use primary Release, Security and Updates
-pockets and all its available components.
-
- >>> from lp.soyuz.adapters.archivedependencies import (
- ... default_component_dependency_name, default_pocket_dependency)
-
- >>> print default_pocket_dependency
- Updates
-
- >>> print default_component_dependency_name
- multiverse
-
-The default values get applied to their corresponding dependency maps
-and then will expand to distinct values that will be used to produce
-the building 'sources_list' contents.
-
- >>> for pocket in pocket_dependencies[default_pocket_dependency]:
- ... print pocket
- Release
- Security
- Updates
-
- >>> for component_name in get_components_for_context(
- ... getUtility(IComponentSet)[default_component_dependency_name],
- ... hoary, pocket):
- ... print component_name
- main
- restricted
- universe
- multiverse
-
-We will create a testing source publication and probe its build
-environment.
-
- >>> pub_source = test_publisher.getPubSource(
- ... version='1.1', archive=cprov.archive)
- >>> [a_build] = pub_source.createMissingBuilds()
-
-Now we can verify if get_sources_list_for_building() method returns the
-expected content for building the just-created source.
-
- >>> from lp.soyuz.adapters.archivedependencies import (
- ... get_sources_list_for_building)
-
- >>> def print_building_sources_list(candidate):
- ... sources_list = get_sources_list_for_building(
- ... candidate, candidate.distro_arch_series,
- ... candidate.source_package_release.name)
- ... for line in sources_list:
- ... print line
-
-Note that only the default ubuntu dependencies for a public PPA will be
-considered when building the source candidate. That's because there is
-no binary published in Celso's PPA hoary/i386, so there is
-no need to request the builder to load its archive indexes.
-
- >>> from lp.soyuz.enums import PackagePublishingStatus
-
- >>> cprov.archive.getAllPublishedBinaries(
- ... distroarchseries=a_build.distro_arch_series,
- ... status=PackagePublishingStatus.PUBLISHED).count()
- 0
-
- >>> print_building_sources_list(a_build)
- deb http://archive.launchpad.dev/ubuntu hoary
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-security
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-updates
- main restricted universe multiverse
-
-Once we publish a test binary in Celso's PPA hoary/i386,
-this archive becomes relevant for building, and thus listed in the
-returned 'sources_list' content.
-
- >>> pub_binaries = test_publisher.getPubBinaries(
- ... binaryname='dep-bin', archive=cprov.archive,
- ... status=PackagePublishingStatus.PUBLISHED)
-
- >>> print_building_sources_list(a_build)
- deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
- deb http://archive.launchpad.dev/ubuntu hoary
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-security
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-updates
- main restricted universe multiverse
-
-Similarly, unpopulated PPA dependencies are *not* listed in the building
-'sources_list'.
-
- >>> mark = getUtility(IPersonSet).getByName('mark')
- >>> archive_dependency = cprov.archive.addArchiveDependency(
- ... mark.archive, PackagePublishingPocket.RELEASE,
- ... getUtility(IComponentSet)['main'])
- >>> print_building_sources_list(a_build)
- deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
- deb http://archive.launchpad.dev/ubuntu hoary
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-security
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-updates
- main restricted universe multiverse
-
-But *populated* PPA dependencies *are* listed in the building 'sources_list'.
-
- >>> pub_binaries = test_publisher.getPubBinaries(
- ... binaryname='dep-bin', archive=mark.archive,
- ... status=PackagePublishingStatus.PUBLISHED)
- >>> print_building_sources_list(a_build)
- deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
- deb http://ppa.launchpad.dev/mark/ppa/ubuntu hoary main
- deb http://archive.launchpad.dev/ubuntu hoary
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-security
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-updates
- main restricted universe multiverse
-
-Dependencies for series with strict_supported_component_dependencies=False
-are reasonable too. PPAs only have the 'main' component.
-
- >>> lax_pub_source = test_publisher.getPubSource(
- ... version='1.2', distroseries=lax_distroseries,
- ... archive=cprov.archive)
- >>> [lax_build] = lax_pub_source.createMissingBuilds()
- >>> _ = test_publisher.getPubBinaries(
- ... binaryname='dep-bin', distroseries=lax_distroseries,
- ... archive=cprov.archive, status=PackagePublishingStatus.PUBLISHED)
- >>> _ = test_publisher.getPubBinaries(
- ... binaryname='dep-bin', distroseries=lax_distroseries,
- ... archive=mark.archive, status=PackagePublishingStatus.PUBLISHED)
- >>> print_building_sources_list(lax_build)
- deb http://ppa.launchpad.dev/cprov/ppa/ubuntu lax main
- deb http://ppa.launchpad.dev/mark/ppa/ubuntu lax main
- deb http://archive.launchpad.dev/ubuntu lax
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu lax-security
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu lax-updates
- main restricted universe multiverse
-
- >>> cprov.archive.removeArchiveDependency(mark.archive)
-
-What when we supply invalid dependencies, an exception is raised.
-
- >>> cprov.archive.external_dependencies = (
- ... "Malformed format string here --> %(series)")
- Traceback (most recent call last):
- InvalidExternalDependencies: (InvalidExternalDependencies(...),
- "Invalid external dependencies:\nMalformed format string here
- --> %(series): Must start with 'deb'\nMalformed format string here
- --> %(series): Invalid URL\n")
-
-
-== Overriding default primary archive dependencies ==
-
-Despite being private or public, default primary archive dependencies
-can be overridden by simply creating a `ArchiveDependency`record
-targeted to the primary archive.
-
-The 'pocket' and 'component' dependency attributes can be adjusted to
-produce the desired build behaviour.
-
-By default, public PPAs depend on all of the pocket dependencies of
-UPDATES, and all of the primary archive's 'multiverse' component
-dependencies.
-
- >>> print_building_sources_list(a_build)
- deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
- deb http://archive.launchpad.dev/ubuntu hoary
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-security
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-updates
- main restricted universe multiverse
-
-The default build behaviour will remain unchanged when we override the
-default primary archive dependencies with exactly the same values.
-
- >>> default_dependency = cprov.archive.addArchiveDependency(
- ... ubuntu.main_archive, PackagePublishingPocket.UPDATES,
- ... getUtility(IComponentSet)['multiverse'])
-
- >>> print_building_sources_list(a_build)
- deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
- deb http://archive.launchpad.dev/ubuntu hoary
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-security
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-updates
- main restricted universe multiverse
-
- >>> cprov.archive.removeArchiveDependency(ubuntu.main_archive)
-
-The dependency can be modified to behave as an embargoed archive that
-builds security updates. This is done by setting the SECURITY pocket
-dependencies (RELEASE and SECURITY) and following the component
-dependencies of the component where the source was last published in
-the primary archive.
-
- >>> security_dependency = cprov.archive.addArchiveDependency(
- ... ubuntu.main_archive, PackagePublishingPocket.SECURITY)
-
- >>> from lp.soyuz.adapters.archivedependencies import (
- ... get_primary_current_component)
-
- >>> print get_primary_current_component(a_build.archive,
- ... a_build.distro_series, a_build.source_package_release.name).name
- universe
-
- >>> print_building_sources_list(a_build)
- deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
- deb http://archive.launchpad.dev/ubuntu hoary
- main universe
- deb http://archive.launchpad.dev/ubuntu hoary-security
- main universe
-
- >>> _ = test_publisher.getPubSource(
- ... sourcename='with-ancestry', version='1.0',
- ... archive=ubuntu.main_archive)
- >>> [build_with_ancestry] = test_publisher.getPubSource(
- ... sourcename='with-ancestry', version='1.1',
- ... archive=cprov.archive).createMissingBuilds()
- >>> print get_primary_current_component(
- ... build_with_ancestry.archive, build_with_ancestry.distro_series,
- ... build_with_ancestry.source_package_release.name).name
- main
- >>> print_building_sources_list(build_with_ancestry)
- deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
- deb http://archive.launchpad.dev/ubuntu hoary main
- deb http://archive.launchpad.dev/ubuntu hoary-security main
-
- >>> cprov.archive.removeArchiveDependency(ubuntu.main_archive)
-
-It's also possible to modify the PPA to act as a super-free and
-pristine build environment based only on what was included in the
-original ubuntu release.
-
- >>> release_dependency = cprov.archive.addArchiveDependency(
- ... ubuntu.main_archive, PackagePublishingPocket.RELEASE,
- ... getUtility(IComponentSet)['restricted'])
-
- >>> print_building_sources_list(a_build)
- deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
- deb http://archive.launchpad.dev/ubuntu hoary main restricted
-
- >>> cprov.archive.removeArchiveDependency(ubuntu.main_archive)
-
-The PPA can also be configured to extend the ubuntu PROPOSED build
-environment.
-
- >>> proposed_dependency = cprov.archive.addArchiveDependency(
- ... ubuntu.main_archive, PackagePublishingPocket.PROPOSED,
- ... getUtility(IComponentSet)['multiverse'])
-
- >>> print_building_sources_list(a_build)
- deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
- deb http://archive.launchpad.dev/ubuntu hoary
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-security
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-updates
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-proposed
- main restricted universe multiverse
-
- >>> cprov.archive.removeArchiveDependency(ubuntu.main_archive)
-
-Similarly an extension of the BACKPORTS environment can be set.
-
- >>> backports_dependency = cprov.archive.addArchiveDependency(
- ... ubuntu.main_archive, PackagePublishingPocket.BACKPORTS,
- ... getUtility(IComponentSet)['multiverse'])
-
- >>> print_building_sources_list(a_build)
- deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
- deb http://archive.launchpad.dev/ubuntu hoary
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-security
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-updates
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-backports
- main restricted universe multiverse
-
- >>> cprov.archive.removeArchiveDependency(ubuntu.main_archive)
-
-
-== Partner archive builds ==
-
-Similarly to what happens with PPA builds, PARTNER builds may depend
-on any Ubuntu component in the PRIMARY archive. This behaviour allows
-scenarios where partner packages may use other restricted/non-free
-applications from 'multiverse', for instance 'sun-java', and also
-other partner applications by default.
-
- # Populate the ubuntutest PARTNER archive with one built and one
- # pending build source.
- >>> primary, partner = ubuntu.all_distro_archives
- >>> unused_source = test_publisher.getPubSource(
- ... archive=partner, component='partner')
- >>> unused = test_publisher.getPubBinaries(
- ... pub_source=unused_source,
- ... status=PackagePublishingStatus.PUBLISHED)
- >>> pub_source = test_publisher.getPubSource(
- ... version='1.2', archive=partner, component='partner')
- >>> [partner_build] = pub_source.createMissingBuilds()
-
- >>> print_building_sources_list(partner_build)
- deb http://archive.launchpad.dev/ubuntu-partner hoary partner
- deb http://archive.launchpad.dev/ubuntu hoary
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-security
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-updates
- main restricted universe multiverse
-
-PARTNER's PROPOSED pocket builds against itself, but still uses the
-default UPDATES dependency for PRIMARY unless overridden by
-ArchiveDependency.
-
- >>> proposed_source = test_publisher.getPubSource(
- ... version='1.2', archive=partner, component='partner',
- ... pocket=PackagePublishingPocket.PROPOSED)
- >>> unused = test_publisher.getPubBinaries(
- ... archive=partner, distroseries=proposed_source.distroseries,
- ... pocket=PackagePublishingPocket.PROPOSED,
- ... status=PackagePublishingStatus.PUBLISHED)
- >>> [partner_proposed_build] = proposed_source.createMissingBuilds()
-
- >>> print_building_sources_list(partner_proposed_build)
- deb http://archive.launchpad.dev/ubuntu-partner hoary partner
- deb http://archive.launchpad.dev/ubuntu-partner hoary-proposed partner
- deb http://archive.launchpad.dev/ubuntu hoary
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-security
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-updates
- main restricted universe multiverse
-
-== External build dependencies ==
-
-Via an administrator change, any PPA hosted in launchpad can be
-assigned to one or more 'external' build dependencies additionally to
-the internal ones.
-
-There is a column on IArchive called 'external_dependencies' which can be set
-for any hosted PPA. It is a string listing the comma-separated external
-dependencies in the debian sources_list format.
-
- deb http[s]://[user:pass@]<host>[/path] %(series)s[-pocket] [components]
-
-The '%(series)s' part is optional and will be replaced on-the-fly with
-the series name for the build record being dispatched.
-
-We will create some dependencies for Celso's PPA.
-
- >>> cprov.archive.external_dependencies = (
- ... "deb http://user:pass@repository zoing everything\n"
- ... "deb http://user:pass@repository %(series)s public private\n"
- ... "deb http://user:pass@repository %(series)s-extra public")
-
-Now builds in Celso's PPA will use the external dependencies.
-
- >>> print_building_sources_list(a_build)
- deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
- deb http://user:pass@repository zoing everything
- deb http://user:pass@repository hoary public private
- deb http://user:pass@repository hoary-extra public
- deb http://archive.launchpad.dev/ubuntu hoary
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-security
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-updates
- main restricted universe multiverse
-
- >>> cprov.archive.external_dependencies = None
-
-We can also set external dependencies for a single build.
-
- >>> a_build.api_external_dependencies = (
- ... u"deb http://user:pass@repository foo bar")
- >>> print_building_sources_list(a_build)
- deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
- deb http://user:pass@repository foo bar
- deb http://archive.launchpad.dev/ubuntu hoary
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-security
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-updates
- main restricted universe multiverse
- >>> a_build.api_external_dependencies = None
-
-
-== Build tools sources.list entries ==
-
-We can force an extra build tools line to be added to the sources.list,
-which is useful for specialised build types.
-
- >>> for line in get_sources_list_for_building(
- ... a_build, a_build.distro_arch_series,
- ... a_build.source_package_release.name,
- ... tools_source="deb http://example.org %(series)s main"):
- ... print line
- deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
- deb http://example.org hoary main
- deb http://archive.launchpad.dev/ubuntu hoary
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-security
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-updates
- main restricted universe multiverse
-
-If tools_source is badly formatted, we log the error but don't blow up.
-(Note the missing "s" at the end of "%(series)".)
-
- >>> from lp.services.log.logger import BufferLogger
- >>> logger = BufferLogger()
- >>> for line in get_sources_list_for_building(
- ... a_build, a_build.distro_arch_series,
- ... a_build.source_package_release.name,
- ... tools_source="deb http://example.org %(series) main",
- ... logger=logger):
- ... print line
- deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
- deb http://archive.launchpad.dev/ubuntu hoary
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-security
- main restricted universe multiverse
- deb http://archive.launchpad.dev/ubuntu hoary-updates
- main restricted universe multiverse
- >>> print logger.getLogBuffer()
- ERROR Exception processing build tools sources.list entry:
- ...
-
-
-== Overlays ==
-
-An overlay distroseries is a derived distribution which works like a PPA.
-This means that the parent's details gets added to the sources.list passed to
-the builders.
-
- >>> depdistro = factory.makeDistribution('depdistro',
- ... publish_base_url=u'http://archive.launchpad.dev/')
- >>> depseries = factory.makeDistroSeries(
- ... name='depseries', distribution=depdistro)
- >>> deparchseries = factory.makeDistroArchSeries(
- ... distroseries = depseries, architecturetag = 'i386')
- >>> test_publisher.addFakeChroots(depseries)
- >>> for component_name in ubuntu_components:
- ... component = getUtility(IComponentSet)[component_name]
- ... _ = factory.makeComponentSelection(depseries, component)
- >>> universe_component = getUtility(IComponentSet)['universe']
- >>> dsp = factory.makeDistroSeriesParent(
- ... derived_series=hoary, parent_series=depseries,
- ... initialized=True, is_overlay=True,
- ... pocket=PackagePublishingPocket.SECURITY,
- ... component=universe_component)
- >>> pub_source = test_publisher.getPubSource(
- ... version='1.1', archive=hoary.main_archive)
- >>> [hoary_build] = pub_source.createMissingBuilds()
- >>> print_building_sources_list(hoary_build)
- deb http://archive.launchpad.dev/ubuntu hoary main
- deb http://archive.launchpad.dev/depdistro depseries main universe
- deb http://archive.launchpad.dev/depdistro depseries-security
- main universe
=== modified file 'lib/lp/soyuz/interfaces/archive.py'
--- lib/lp/soyuz/interfaces/archive.py 2016-11-14 19:55:07 +0000
+++ lib/lp/soyuz/interfaces/archive.py 2017-04-25 11:44:32 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2016 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Archive interfaces."""
@@ -306,7 +306,7 @@
def __init__(self, errors):
error_msg = 'Invalid external dependencies:\n%s\n' % '\n'.join(errors)
- super(Exception, self).__init__(self, error_msg)
+ super(Exception, self).__init__(error_msg)
self.errors = errors
=== modified file 'lib/lp/soyuz/tests/test_archive.py'
--- lib/lp/soyuz/tests/test_archive.py 2016-11-07 16:42:23 +0000
+++ lib/lp/soyuz/tests/test_archive.py 2017-04-25 11:44:32 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2016 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Test Archive features."""
@@ -78,6 +78,7 @@
DuplicateTokenName,
IArchiveSet,
InsufficientUploadRights,
+ InvalidExternalDependencies,
InvalidPocketForPartnerArchive,
InvalidPocketForPPA,
NAMED_AUTH_TOKEN_FEATURE_FLAG,
@@ -1767,6 +1768,18 @@
"person-name-.*/dependency/ubuntu distroseries-.* main")
self.assertThat(sources_list[0], matches)
+ def test_invalid_external_dependencies(self):
+ """Trying to set invalid external dependencies raises an exception."""
+ ppa = self.factory.makeArchive()
+ self.assertRaisesWithContent(
+ InvalidExternalDependencies,
+ "Invalid external dependencies:\n"
+ "Malformed format string here --> %(series): "
+ "Must start with 'deb'\n"
+ "Malformed format string here --> %(series): Invalid URL\n",
+ setattr, ppa, "external_dependencies",
+ "Malformed format string here --> %(series)")
+
class TestFindDepCandidates(TestCaseWithFactory):
"""Tests for Archive.findDepCandidates."""
=== modified file 'lib/lp/testing/factory.py'
--- lib/lp/testing/factory.py 2016-12-02 12:04:11 +0000
+++ lib/lp/testing/factory.py 2017-04-25 11:44:32 +0000
@@ -2,7 +2,7 @@
# NOTE: The first line above must stay first; do not move the copyright
# notice to the top. See http://www.python.org/dev/peps/pep-0263/.
#
-# Copyright 2009-2016 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Testing infrastructure for the Launchpad application.
@@ -268,7 +268,10 @@
)
from lp.services.oauth.interfaces import IOAuthConsumerSet
from lp.services.openid.model.openididentifier import OpenIdIdentifier
-from lp.services.propertycache import clear_property_cache
+from lp.services.propertycache import (
+ clear_property_cache,
+ get_property_cache,
+ )
from lp.services.temporaryblobstorage.interfaces import (
ITemporaryStorageManager,
)
@@ -2832,8 +2835,10 @@
if not IComponent.providedBy(component):
component = self.makeComponent(component)
- return ComponentSelection(
+ selection = ComponentSelection(
distroseries=distroseries, component=component)
+ del get_property_cache(distroseries).components
+ return selection
def makeArchive(self, distribution=None, owner=None, name=None,
purpose=None, enabled=True, private=False,
Follow ups