-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #216 from epics-containers/add-collection-tests2
Add collections of Entities inside of Definitions
- Loading branch information
Showing
46 changed files
with
14,726 additions
and
627 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
""" | ||
Classes to specify arguments to Definitions | ||
""" | ||
|
||
from __future__ import annotations | ||
|
||
from typing import Any, Dict, Optional | ||
|
||
from pydantic import Field | ||
from typing_extensions import Literal | ||
|
||
from .globals import BaseSettings | ||
|
||
|
||
class Value(BaseSettings): | ||
"""A calculated string value for a definition""" | ||
|
||
name: str = Field(description="Name of the value that the IOC instance will expose") | ||
description: str = Field( | ||
description="Description of what the value will be used for" | ||
) | ||
value: str = Field(description="The contents of the value") | ||
|
||
|
||
class Arg(BaseSettings): | ||
"""Base class for all Argument Types""" | ||
|
||
type: str | ||
name: str = Field( | ||
description="Name of the argument that the IOC instance should pass" | ||
) | ||
description: str = Field( | ||
description="Description of what the argument will be used for" | ||
) | ||
|
||
|
||
class FloatArg(Arg): | ||
"""An argument with a float value""" | ||
|
||
type: Literal["float"] = "float" | ||
default: Optional[float] = None | ||
|
||
|
||
class StrArg(Arg): | ||
"""An argument with a str value""" | ||
|
||
type: Literal["str"] = "str" | ||
default: Optional[str] = None | ||
|
||
|
||
class IntArg(Arg): | ||
"""An argument with an int value""" | ||
|
||
type: Literal["int"] = "int" | ||
default: Optional[int] = None | ||
|
||
|
||
class BoolArg(Arg): | ||
"""An argument with an bool value""" | ||
|
||
type: Literal["bool"] = "bool" | ||
default: Optional[bool] = None | ||
|
||
|
||
class ObjectArg(Arg): | ||
"""A reference to another entity defined in this IOC""" | ||
|
||
type: Literal["object"] = "object" | ||
default: Optional[str] = None | ||
|
||
|
||
class IdArg(Arg): | ||
"""Explicit ID argument that an object can refer to""" | ||
|
||
type: Literal["id"] = "id" | ||
default: Optional[str] = None | ||
|
||
|
||
class EnumArg(Arg): | ||
"""An argument with an enum value""" | ||
|
||
type: Literal["enum"] = "enum" | ||
default: Optional[Any] = None | ||
|
||
values: Dict[str, Any] = Field( | ||
description="provides a list of values to make this argument an Enum", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
""" | ||
The Definition class describes what a given support module can instantiate. | ||
""" | ||
|
||
from __future__ import annotations | ||
|
||
from enum import Enum | ||
from typing import Any, Mapping, Optional, Sequence, Union | ||
|
||
from pydantic import Field, PydanticUndefinedAnnotation | ||
from typing_extensions import Literal | ||
|
||
from .args import Arg, IdArg, Value | ||
from .globals import BaseSettings | ||
from .sub_entity import SubEntity | ||
|
||
|
||
def default(T: type): | ||
""" | ||
defines a default type which may be | ||
""" | ||
return Field( | ||
Union[Optional[T], PydanticUndefinedAnnotation], | ||
description="If given, instance doesn't supply argument, what value should be used", | ||
) | ||
|
||
|
||
class When(Enum): | ||
first = "first" | ||
every = "every" | ||
last = "last" | ||
|
||
|
||
class Database(BaseSettings): | ||
""" | ||
A database file that should be loaded by the startup script and its args | ||
""" | ||
|
||
file: str = Field( | ||
description="Filename of the database template in <module_root>/db" | ||
) | ||
|
||
enabled: str = Field( | ||
description="Set to False to disable loading this database", default="True" | ||
) | ||
|
||
args: Mapping[str, Optional[str]] = Field( | ||
description=( | ||
"Dictionary of args and values to pass through to database. " | ||
"A value of None is equivalent to ARG: '{{ ARG }}'. " | ||
"See `UTILS.render_map` for more details." | ||
) | ||
) | ||
|
||
|
||
class EnvironmentVariable(BaseSettings): | ||
""" | ||
An environment variable that should be set in the startup script | ||
""" | ||
|
||
name: str = Field(description="Name of environment variable") | ||
value: str = Field(description="Value to set") | ||
|
||
|
||
class Comment(BaseSettings): | ||
""" | ||
A script snippet that will have '# ' prepended to every line | ||
for insertion into the startup script | ||
""" | ||
|
||
type: Literal["comment"] = "comment" | ||
when: When = Field(description="One of first / every / last", default="every") | ||
value: str = Field( | ||
description="A comment to add into the startup script", default="" | ||
) | ||
|
||
|
||
class Text(BaseSettings): | ||
""" | ||
A script snippet to insert into the startup script | ||
""" | ||
|
||
type: Literal["text"] = "text" | ||
when: str = Field(description="One of first / every / last", default="every") | ||
value: str = Field(description="raw text to add to the startup script", default="") | ||
|
||
|
||
Script = Sequence[Union[Text, Comment]] | ||
|
||
|
||
class EntityPVI(BaseSettings): | ||
"""Entity PVI definition""" | ||
|
||
yaml_path: str = Field( | ||
description="Path to .pvi.device.yaml - absolute or relative to PVI_DEFS" | ||
) | ||
ui_index: bool = Field( | ||
True, | ||
description="Whether to add the UI to the IOC index.", | ||
) | ||
ui_macros: dict[str, str | None] = Field( | ||
None, | ||
description=( | ||
"Macros to launch the UI on the IOC index. " | ||
"These must be args of the Entity this is attached to." | ||
), | ||
) | ||
pv: bool = Field( | ||
False, | ||
description=( | ||
"Whether to generate a PVI PV. This adds a database template with info " | ||
"tags that create a PVAccess PV representing the device structure." | ||
), | ||
) | ||
pv_prefix: str = Field("", description='PV prefix for PVI PV - e.g. "$(P)"') | ||
|
||
|
||
class EntityDefinition(BaseSettings): | ||
""" | ||
A single definition of a class of Entity that an IOC instance may instantiate | ||
""" | ||
|
||
name: str = Field( | ||
description="Publish Definition as type <module>.<name> for IOC instances" | ||
) | ||
description: str = Field( | ||
description="A description of the Support module defined here" | ||
) | ||
# declare Arg as Union of its subclasses for Pydantic to be able to deserialize | ||
args: Sequence[Union[tuple(Arg.__subclasses__())]] = Field( # type: ignore | ||
description="The arguments IOC instance should supply", default=() | ||
) | ||
values: Sequence[Value] = Field( | ||
description="Calculated values to use as additional arguments", default=() | ||
) | ||
databases: Sequence[Database] = Field( | ||
description="Databases to instantiate", default=[] | ||
) | ||
pre_init: Script = Field( | ||
description="Startup script snippets to add before iocInit()", default=() | ||
) | ||
post_init: Script = Field( | ||
description="Startup script snippets to add post iocInit(), such as dbpf", | ||
default=(), | ||
) | ||
env_vars: Sequence[EnvironmentVariable] = Field( | ||
description="Environment variables to set in the boot script", default=() | ||
) | ||
pvi: Optional[EntityPVI] = Field( | ||
description="PVI definition for Entity", default=None | ||
) | ||
|
||
# list of additional entities to instantiate for each instance of this definition | ||
sub_entities: Sequence[SubEntity] = Field( | ||
description="The sub-entity instances that this collection is to instantiate", | ||
default=(), | ||
) | ||
|
||
shared: Sequence[Any] = Field( | ||
description="A place to create any anchors required for repeating YAML", | ||
default=(), | ||
) | ||
|
||
def _get_id_arg(self): | ||
"""Returns the name of the ID argument for this definition, if it exists""" | ||
for arg in self.args: | ||
if isinstance(arg, IdArg): | ||
return arg.name |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.