# Copyright (c) 2022 Nordic Semiconductor ASA # # SPDX-License-Identifier: Apache-2.0 '''Domain handling for west extension commands. This provides parsing of domains yaml file and creation of objects of the Domain class. ''' from dataclasses import dataclass import yaml import pykwalify.core import logging DOMAINS_SCHEMA = ''' ## A pykwalify schema for basic validation of the structure of a ## domains YAML file. ## # The domains.yaml file is a simple list of domains from a multi image build # along with the default domain to use. type: map mapping: default: required: true type: str build_dir: required: true type: str domains: required: true type: seq sequence: - type: map mapping: name: required: true type: str build_dir: required: true type: str flash_order: required: false type: seq sequence: - type: str ''' schema = yaml.safe_load(DOMAINS_SCHEMA) logger = logging.getLogger('build_helpers') # Configure simple logging backend. formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s') handler = logging.StreamHandler() handler.setFormatter(formatter) logger.addHandler(handler) class Domains: def __init__(self, domains_yaml): try: data = yaml.safe_load(domains_yaml) pykwalify.core.Core(source_data=data, schema_data=schema).validate() except (yaml.YAMLError, pykwalify.errors.SchemaError): logger.critical(f'malformed domains.yaml') exit(1) self._build_dir = data['build_dir'] self._domains = { d['name']: Domain(d['name'], d['build_dir']) for d in data['domains'] } # In the YAML data, the values for "default" and "flash_order" # must not name any domains that aren't listed under "domains". # Now that self._domains has been initialized, we can leverage # the common checks in self.get_domain to verify this. self._default_domain = self.get_domain(data['default']) self._flash_order = self.get_domains(data.get('flash_order', [])) @staticmethod def from_file(domains_file): '''Load domains from a domains.yaml file. ''' try: with open(domains_file, 'r') as f: domains_yaml = f.read() except FileNotFoundError: logger.critical(f'domains.yaml file not found: {domains_file}') exit(1) return Domains(domains_yaml) @staticmethod def from_yaml(domains_yaml): '''Load domains from a string with YAML contents. ''' return Domains(domains_yaml) def get_domains(self, names=None, default_flash_order=False): if names is None: if default_flash_order: return self._flash_order return list(self._domains.values()) return list(map(self.get_domain, names)) def get_domain(self, name): found = self._domains.get(name) if not found: logger.critical(f'domain "{name}" not found, ' f'valid domains are: {", ".join(self._domains)}') exit(1) return found def get_default_domain(self): return self._default_domain def get_top_build_dir(self): return self._build_dir @dataclass class Domain: name: str build_dir: str