From c4f616a4e1a9ea9b5db06f8acdf4cd08e3f4b966 Mon Sep 17 00:00:00 2001 From: Sergio Costas Rodriguez Date: Mon, 17 Jul 2023 21:29:48 +0200 Subject: [PATCH] Add support for custom data This patch implements proposal ST090. It allows to add custom metadata into the snapcraft.yaml files without interferring with snapcraft. This is useful for adding extra data for tools that manage snap files, like updatesnap.py, which searches for new versions of the parts in a snapcraft.yaml file. Proposal: https://docs.google.com/document/d/1QX0moP6V709D7L267pIT5AREQetbPb7KsFrpgvCLKVM --- snapcraft/projects.py | 2 ++ snapcraft/utils.py | 21 +++++++++++++++++++++ snapcraft_legacy/project/_project_info.py | 7 +++++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/snapcraft/projects.py b/snapcraft/projects.py index c9a441efbf2..e25f3f229e7 100644 --- a/snapcraft/projects.py +++ b/snapcraft/projects.py @@ -32,6 +32,7 @@ convert_architecture_deb_to_platform, get_effective_base, get_host_architecture, + remove_custom_data, ) @@ -639,6 +640,7 @@ def unmarshal(cls, data: Dict[str, Any]) -> "Project": if not isinstance(data, dict): raise TypeError("Project data is not a dictionary") + data = remove_custom_data(data) try: project = Project(**data) except pydantic.ValidationError as err: diff --git a/snapcraft/utils.py b/snapcraft/utils.py index 060f0089163..505d2899124 100644 --- a/snapcraft/utils.py +++ b/snapcraft/utils.py @@ -457,3 +457,24 @@ def process_version(version: Optional[str]) -> str: def is_snapcraft_running_from_snap() -> bool: """Check if snapcraft is running from the snap.""" return os.getenv("SNAP_NAME") == "snapcraft" and os.getenv("SNAP") is not None + +def _remove_custom_data_from_dict(data): + prog = re.compile("^custom-data-[a-zA-Z0-9][a-zA-Z0-9_-]*$") + for element in list(data.keys()): + if prog.match(element) is not None: + data.pop(element) + return data + + +def remove_custom_data(data): + # remove custom data from the root + data = _remove_custom_data_from_dict(data) + + # remove custom data from apps, plugs, slots and parts + for entry_name in ["apps", "plugs", "slots", "parts"]: + if entry_name in data: + for app in list(data[entry_name].keys()): + data[entry_name][app] = _remove_custom_data_from_dict( + data[entry_name][app] + ) + return data diff --git a/snapcraft_legacy/project/_project_info.py b/snapcraft_legacy/project/_project_info.py index e509ccd4ee8..041e3368355 100644 --- a/snapcraft_legacy/project/_project_info.py +++ b/snapcraft_legacy/project/_project_info.py @@ -20,14 +20,17 @@ from snapcraft_legacy import yaml_utils from . import _schema - +from snapcraft.utils import ( + remove_custom_data, +) class ProjectInfo: """Information gained from the snap's snapcraft.yaml file.""" def __init__(self, *, snapcraft_yaml_file_path) -> None: self.snapcraft_yaml_file_path = snapcraft_yaml_file_path - self.__raw_snapcraft = yaml_utils.load_yaml_file(snapcraft_yaml_file_path) + self.__raw_snapcraft = remove_custom_data( + yaml_utils.load_yaml_file(snapcraft_yaml_file_path)) try: self.name = self.__raw_snapcraft["name"]