Skip to content

Commit

Permalink
magic probe module adaptions
Browse files Browse the repository at this point in the history
Signed-off-by: Fabian Klemm <[email protected]>
  • Loading branch information
klemmpnx committed Dec 19, 2023
1 parent f4a9df7 commit 8b6343f
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@

from everest.testing.core_utils.common import Requirement
from everest.testing.core_utils.probe_module import ProbeModule
from pydantic import BaseModel

from .types.everest_command import EverestCommand
from .types.everest_config_schema import EverestConfigSchema
from .types.everest_interface import EverestInterface
from .types.everest_type import EverestType
from .value_generator import ValueGenerator
Expand All @@ -15,13 +13,11 @@
class MagicProbeModule(ProbeModule):

def __init__(self,
interfaces: dict[str, EverestInterface],
interface_implementations: dict[str, EverestInterface],
types: list[EverestType],
connections: dict[str, list[tuple[Requirement, EverestInterface]]],
config: EverestConfigSchema | dict,
session, module_id="probe"):
self._config = config if isinstance(config, EverestConfigSchema) else EverestConfigSchema(**config)
self._interfaces = interfaces
self._interface_implementations = interface_implementations
self._connections = connections
super().__init__(session, module_id)
self._value_generator = ValueGenerator(types)
Expand Down Expand Up @@ -53,8 +49,7 @@ def implementation_mocks(self) -> dict[str, Mock]:
return self._implementation_mocks

def _init_commands(self):

for implementation_id, interface in self._interfaces.items():
for implementation_id, interface in self._interface_implementations.items():
for command in interface.commands.values():
self._init_command(implementation_id, command)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,31 @@ class MagicProbeModuleConfigurationStrategy(EverestConfigAdjustmentStrategy):

def __init__(self,
module_connections: dict[str, dict[str, list[str]]],
probe_module_connections: dict[str, list[Requirement]],
# probe_module_connections: dict[str, list[Requirement]],
module_id: str = "probe"
):
self._module_id = module_id
self._connections = probe_module_connections
# self._connections = probe_module_connections
self._module_connections = module_connections

def adjust_everest_configuration(self, everest_config: dict) -> dict:
adjusted_config = deepcopy(everest_config)
self._add_probe_module(adjusted_config)
# self._add_probe_module(adjusted_config)
self._add_required_probe_module(adjusted_config)

return adjusted_config

def _add_probe_module(self, adjusted_config: dict):
probe_connections = {
requirement_id: [{"module_id": requirement.module_id, "implementation_id": requirement.implementation_id}
for requirement in requirements_list]
for requirement_id, requirements_list in self._connections.items()}

active_modules = adjusted_config.setdefault("active_modules", {})
active_modules[self._module_id] = {
'connections': probe_connections,
'module': 'ProbeModule'
}
# def _add_probe_module(self, adjusted_config: dict):
# probe_connections = {
# requirement_id: [{"module_id": requirement.module_id, "implementation_id": requirement.implementation_id}
# for requirement in requirements_list]
# for requirement_id, requirements_list in self._connections.items()}
#
# active_modules = adjusted_config.setdefault("active_modules", {})
# active_modules[self._module_id] = {
# 'connections': probe_connections,
# 'module': 'ProbeModule'
# }

def _add_required_probe_module(self, adjusted_config: dict):
for module_id, module_requirements in self._module_connections.items():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ def __init__(self,
self._probe_module_requirements: dict[
str, dict[str, list[tuple[Requirement, EverestInterface]]]] = self._determine_probe_module_requirements()

def get_interfaces(self) -> dict[str, EverestInterface]:
@property
def probe_module_id(self):
return self._probe_module_id

def get_interface_implementations(self) -> dict[str, EverestInterface]:
""" Returns the mapping of implementation id to EverestInterface for every interface implementation
the probe module shall provide. """
return {k: self._interfaces_by_name[v] for k, v in self._probe_module_implementations.items()}
Expand All @@ -46,8 +50,8 @@ def get_requirements(self):
def get_configuration_adjustment_strategy(self) -> EverestConfigAdjustmentStrategy:
return MagicProbeModuleConfigurationStrategy(
module_connections=self._module_connections,
probe_module_connections={k: [t[0] for t in requirements] for k, requirements in
self._probe_module_requirements.items()},
# probe_module_connections={k: [t[0] for t in requirements] for k, requirements in
# self._probe_module_requirements.items()},
module_id=self._probe_module_id
)

Expand Down Expand Up @@ -101,9 +105,9 @@ def _determine_probe_module_requirements(self) -> dict[str, dict[str, list[tuple
for module_id, mod in self._everest_config.active_modules.items():
manifest = self._manifests[mod.module]
if manifest.provides:
probe_module_requirements.setdefault(module_id, []).extend((
(Requirement(module_id=module_id, implementation_id=implementation_id),
self._interfaces_by_name[provides.interface])
for implementation_id, provides in manifest.provides.items()
))
for implementation_id, provides in manifest.provides.items():
probe_module_requirements.setdefault(provides.interface, []).append(
(Requirement(module_id=module_id, implementation_id=implementation_id),
self._interfaces_by_name[provides.interface])
)
return probe_module_requirements

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ def _parse_type_file(self, type_file: Path):
raise e
return parsed_types

def parse(self, type_files: list[Path]) -> dict[str, EverestType]:
def parse(self, type_directories: list[Path]) -> dict[str, EverestType]:
parsed_types = {}

for file in type_files:
parsed_types.update(self._parse_type_file(file))
for dir in type_directories:
for file in dir.glob("*.yaml"):
parsed_types.update(self._parse_type_file(file))

return parsed_types
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ class Config:
list[str],
Field(
description="Author(s) of this module (an array of strings)",
min_items=1,
min_length=2,
min_items=0,
min_length=0,
),
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
from pydantic import parse_obj_as


# oriented at
# https://stackoverflow.com/questions/73419115/pydantic-model-for-json-meta-schema

class JsonSchemaType(str, Enum):
OBJECT = "object"
ARRAY = "array"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class ValueGenerator:
@dataclass
class _GeneratorContext:
history: list[JsonSchema] = field(default_factory=list)
key_history: list[str] = field(default_factory=list)

@property
def depth(self) -> int:
Expand Down Expand Up @@ -115,6 +116,9 @@ def _generate_float(self, what: NumberJsonSchema, context: _GeneratorContext):

@_generation_step
def _generate_int(self, what: IntegerJsonSchema, context: _GeneratorContext):
if context.key_history and context.key_history[-1] == "id":
return 1

number = next(self._int_generator)
min = what.minimum if what.minimum else 0
if number < min:
Expand All @@ -135,6 +139,7 @@ def _generate_object(self, what: ObjectJsonSchema, context: _GeneratorContext):
value = {}
for key, p in what.properties.items():
if context.depth < self._MAX_DEPTH or key in what.required:
context.key_history.append(key)
value[key] = self._generate_json_schema(p, context)
return value

Expand All @@ -144,7 +149,7 @@ def _generate_array(self, what: ArrayJsonSchema, context: _GeneratorContext):
return []

target_schema = what.items if not isinstance(what.items, list) else what.items[0]

context.key_history.append(0)
return [self._generate_json_schema(target_schema, context)]

@_generation_step
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,65 @@
from pathlib import Path

from ._magic_probe_module.magic_probe_module import MagicProbeModule
import pytest

from ._magic_probe_module.parser.everest_interface_parser import EverestInterfaceParser as _EverestInterfaceParser
from ._magic_probe_module.parser.everest_type_parser import EverestTypeParser as _EverestTypeParser
from ._magic_probe_module.types.everest_config_schema import EverestConfigSchema as _EverestConfigSchema
from ._configuration.everest_environment_setup import EverestEnvironmentCoreConfiguration, \
EverestEnvironmentProbeModuleConfiguration
from ._magic_probe_module.magic_probe_module import MagicProbeModule
from ._magic_probe_module.magic_probe_module_configurator import MagicProbeModuleConfigurator
from ._magic_probe_module.types.everest_module_manifest_schema import \
EverestModuleManifestSchema as _EverestModuleManifestSchema
from ._magic_probe_module.value_generator import ValueGenerator
import yaml

from .everest_core import EverestCore


@pytest.fixture()
def magic_probe_module_configurator(core_config: EverestEnvironmentCoreConfiguration) -> MagicProbeModuleConfigurator:
everest_config = _EverestConfigSchema(**yaml.safe_load(core_config.template_everest_config_path.read_text()))

interfaces_directory = core_config.everest_core_path / "share" / "everest" / "interfaces"
modules_dir = core_config.everest_core_path / "libexec" / "everest" / "modules"

everest_interfaces = _EverestInterfaceParser().parse([interfaces_directory])

everest_manifests = {}
for f in modules_dir.glob("*"):
if (f / "manifest.yaml").exists():
everest_manifests[f.name] = _EverestModuleManifestSchema(
**yaml.safe_load((f / "manifest.yaml").read_text()))

configurator = MagicProbeModuleConfigurator(
everest_config=everest_config,
interfaces=everest_interfaces,
manifests=everest_manifests
)

return configurator


@pytest.fixture
def magic_probe_module(core_config: EverestEnvironmentCoreConfiguration, magic_probe_module_configurator: MagicProbeModuleConfigurator, everest_core: EverestCore) -> MagicProbeModule:

types_directory = core_config.everest_core_path / "share" / "everest" / "types"
everest_types = _EverestTypeParser().parse([types_directory])

return MagicProbeModule(
interface_implementations=magic_probe_module_configurator.get_interface_implementations(),
connections=magic_probe_module_configurator.get_requirements(),
module_id=magic_probe_module_configurator.probe_module_id,
session=everest_core.get_runtime_session(),
types=list(everest_types.values())
)


@pytest.fixture
def probe_module_config(request, magic_probe_module_configurator) -> EverestEnvironmentProbeModuleConfiguration | None:
return EverestEnvironmentProbeModuleConfiguration(
module_id=magic_probe_module_configurator.probe_module_id,
connections={k: [t[0] for t in requirements] for k, requirements in
magic_probe_module_configurator.get_requirements().items()}
)

0 comments on commit 8b6343f

Please sign in to comment.