Colin Watson has proposed merging
lp:~cjwatson/launchpad/snap-parse-architectures into lp:launchpad with
lp:~cjwatson/launchpad/snap-initial-name-bzr as a prerequisite.
Commit message:
Implement determine_architectures_to_build for snaps.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #1770400 in Launchpad itself: "Support snapcraft architectures keyword"
https://bugs.launchpad.net/launchpad/+bug/1770400
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/snap-parse-architectures/+merge/347998
This is based on https://github.com/kyrofa/snapcraft-architectures-parser, and
is the first step towards full build-on architectures support. I'm still
working on the code to actually use this, but it's far enough along for me to
be confident that the interface is the right shape.
The code is quite significantly refactored from Kyle's version, to make it
easier to fit into Launchpad.
--
Your team Launchpad code reviewers is requested to review the proposed merge of
lp:~cjwatson/launchpad/snap-parse-architectures into lp:launchpad.
=== added directory 'lib/lp/snappy/adapters'
=== added file 'lib/lp/snappy/adapters/__init__.py'
=== added file 'lib/lp/snappy/adapters/buildarch.py'
--- lib/lp/snappy/adapters/buildarch.py 1970-01-01 00:00:00 +
+++ lib/lp/snappy/adapters/buildarch.py 2018-06-14 17:14:47 +
@@ -0,0 +1,176 @@
+# Copyright 2018 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+'determine_architectures_to_build',
+]
+
+from collections import Counter
+
+import six
+
+from lp.services.helpers import english_list
+
+
+class SnapArchitecturesParserError(Exception):
+"""Base class for all exceptions in this module."""
+
+
+class MissingPropertyError(SnapArchitecturesParserError):
+"""Error for when an expected property is not present in the YAML."""
+
+def __init__(self, prop):
+super(MissingPropertyError, self).__init__(
+"Architecture specification is missing the {!r} property".format(
+prop))
+self.property = prop
+
+
+class IncompatibleArchitecturesStyleError(SnapArchitecturesParserError):
+"""Error for when architectures mix incompatible styles."""
+
+def __init__(self):
+super(IncompatibleArchitecturesStyleError, self).__init__(
+"'architectures' must either be a list of strings or dicts, not "
+"both")
+
+
+class DuplicateBuildOnError(SnapArchitecturesParserError):
+"""Error for when multiple `build-on`s include the same architecture."""
+
+def __init__(self, duplicates):
+super(DuplicateBuildOnError, self).__init__(
+"{} {} present in the 'build-on' of multiple items".format(
+english_list(duplicates),
+"is" if len(duplicates) == 1 else "are"))
+
+
+class UnsupportedBuildOnError(SnapArchitecturesParserError):
+"""Error for when a requested architecture is not supported."""
+
+def __init__(self, build_on):
+super(UnsupportedBuildOnError, self).__init__(
+"build-on specifies no supported architectures: {!r}".format(
+build_on))
+self.build_on = build_on
+
+
+class SnapArchitecture:
+"""A single entry in the snapcraft.yaml 'architectures' list."""
+
+def __init__(self, build_on, run_on=None, build_error=None):
+"""Create a new architecture entry.
+
+:param build_on: string or list; build-on property from
+snapcraft.yaml.
+:param run_on: string or list; run-on property from snapcraft.yaml
+(defaults to build_on).
+:param build_error: string; build-error property from
+snapcraft.yaml.
+"""
+self.build_on = (
+[build_on] if isinstance(build_on, six.string_types) else build_on)
+if run_on:
+self.run_on = (
+[run_on] if isinstance(run_on, six.string_types) else run_on)
+else:
+self.run_on = self.build_on
+self.build_error = build_error
+
+@classmethod
+def from_dict(cls, properties):
+"""Create a new architecture entry from a dict."""
+try:
+build_on = properties["build-on"]
+except KeyError:
+raise MissingPropertyError("build-on")
+
+return cls(
+build_on=build_on, run_on=properties.get("run-on"),
+build_error=properties.get("build-error"))
+
+
+class SnapBuildInstance:
+"""A single instance of a snap that should be built.
+
+It has two useful attributes:
+
+ - architecture: The architecture tag that should be used to build the
+snap.
+ - required: Whether or not failure to build should cause the entire
+set to fail.
+"""
+
+def