Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
converter.py 2.85 KiB
################################################################################
# Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# http://www.eclipse.org/legal/epl-2.0.
#
# SPDX-License-Identifier: EPL-2.0
################################################################################

from dataclasses import dataclass
from typing import Dict, List
import functools

def init_with_lowercase_keys(cls):
    wrapped_init = cls.__init__

    @functools.wraps(wrapped_init)
    def wrapper(self, *args, **kwargs):
        lowercase_kwargs = {key.lower(): value for key, value in kwargs.items()}
        wrapped_init(self, *args, **lowercase_kwargs)

    cls.__init__ = wrapper
    return cls

@init_with_lowercase_keys
@dataclass(frozen=True)
class Dependency:
    name: str
    type: str
    include: str


class DependencyException(Exception):
    def __init__(self, dependency_name):
        self.dependency_name = dependency_name
        message = f"The referenced dependency '{dependency_name}' does not exist."
        super().__init__(message)


class Converter:
    TYPE_MAPPING = {
        "runtime": True,
        "initialization": False}

    def __init__(self, dependencies: Dict[str, Dependency], name: str, values={}):
        self.name = name
        self.properties = sorted(values.get("Properties", [name]))
        self.keep = values.get("Keep", [])
        self.runtime = Converter.TYPE_MAPPING[values.get(
            "Type", "initialization").lower()]
        self.dependencies = Converter._parse_dependencies(dependencies, values)

    @staticmethod
    def _parse_dependencies(dependencies, values):
        collected_deps = set()
        for d in values.get("Dependencies", []):
            if d not in dependencies:
                raise DependencyException(d)
            collected_deps.add(dependencies[d])
        return sorted(list(collected_deps))


class ConverterRegistry:
    def __init__(self, dependencies: List[Dependency], converter):
        self.general = self._parse_definition(
            dependencies, converter.get("General", {}))
        self.node_specific = self._parse_definitions(
            dependencies, converter.get("NodeSpecific", {}))

    def _parse_definitions(self, dependencies, definitions):
        return {node_name: self._parse_definition(dependencies, definition)
                for node_name, definition in definitions.items()}

    def _parse_definition(self, dependencies, definition):
        return [Converter(dependencies, conv_name, conf_config)
                for conv_name, conf_config in definition.items()]

    def __getitem__(self, node_name):
        converters = list(self.general)
        converters.extend(self.node_specific.get(node_name, []))
        return converters