Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions examples/template/build_template_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import yaml

from pyaml.configuration.factory import Factory

cc = yaml.safe_load(open("templated_config.yaml"))

obj = Factory.build(cc)
print(obj)
24 changes: 24 additions & 0 deletions examples/template/templated_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
- class: pyaml.configuration.template.Template
template: |
class: pyaml.magnet.hcorrector.HCorrector
name: %template_parameter%
model:
class: pyaml.magnet.linear_model.LinearMagnetModel
unit: rad
hardware_unit: str
calibration_factor: 1.0
powerconverter: MAGNET/%template_parameter%/B1L
string_to_replace: "%template_parameter%"
parameter_list:
- PKDK_WL_108
- PKDK_WL_93
- PKDK_WL_79
- PKDK_WL_64
- class: pyaml.magnet.hcorrector.HCorrector
name: ANOTHER
model:
class: pyaml.magnet.linear_model.LinearMagnetModel
unit: rad
hardware_unit: str
calibration_factor: 1.0
powerconverter: MAGNET/ANOTHER/B1L
12 changes: 11 additions & 1 deletion pyaml/configuration/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,17 @@ def _build_list(self, items: list[Any], ignore_external: bool = False):
ignore_external : bool
If ``True``, ignore unavailable external modules.
"""
return [self._build(item, ignore_external) for item in items]
list_out = []
for item in items:
obj = self._build(item, ignore_external)
from collections.abc import Iterator

if isinstance(obj, Iterator):
expanded_iterator = [*obj]
list_out.extend(expanded_iterator)
else:
list_out.append(obj)
return list_out

def _build_dict(self, data: dict, ignore_external: bool = False):
"""
Expand Down
40 changes: 40 additions & 0 deletions pyaml/configuration/template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import json

import yaml
from pydantic import BaseModel

from ..common.exception import PyAMLConfigException
from ..configuration.factory import Factory
from ..validation import StaticValidation, register_schema


def load_json_or_yaml(string_to_load: str) -> dict:
try:
loaded_dict = json.loads(string_to_load)
return "json"
except json.JSONDecodeError:
pass

try:
loaded_dict = yaml.safe_load(string_to_load)
except yaml.YAMLError as exc:
raise PyAMLConfigException("Template class is not a valid YAML or JSON string.") from exc

return loaded_dict


class TemplateValidationModel(BaseModel):
template: str
string_to_replace: str
parameter_list: list[str]


@register_schema
class Template(StaticValidation):
validation_model = TemplateValidationModel

def __new__(cls, template: str, string_to_replace: str, parameter_list: list[str]):
for par in parameter_list:
new_string = template.replace(string_to_replace, par)
new_dict = load_json_or_yaml(new_string)
yield Factory.build(new_dict)
7 changes: 6 additions & 1 deletion pyaml/validation/validation_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,12 @@ def __call__(cls, *args: Any, **kwargs: Any):
raise TypeError(f"{cls.__name__} must define validation_model.")

# Inspect the signature of the class
signature = inspect.signature(cls.__init__)
if "__init__" in cls.__dict__:
signature = inspect.signature(cls.__init__)
elif "__new__" in cls.__dict__:
signature = inspect.signature(cls.__new__)
else:
raise Exception

# Map arguments to parameters
bound = signature.bind(None, *args, **kwargs)
Expand Down
Loading