Source code for ibek.render
"""
Functions for rendering lines in the boot script using Jinja2
"""
from typing import Callable, List, Optional, Sequence, Union
from .definition import Comment, Script, Text, When
from .ioc import Entity
from .utils import UTILS
[docs]
class Render:
"""
A class for generating snippets of startup script / EPICS DB
by using Jinja to combine snippet templates from support module
definition yaml with substitution values supplied in ioc entity yaml
"""
def __init__(self: "Render"):
self.once_done: List[str] = []
[docs]
def render_text(
self, instance: Entity, text: str, when=When.every, suffix=""
) -> str:
"""
Add in the next line of text, honouring the once flag which will
only add the line once per IOC.
Jinja rendering of values/args has already been done in Entity.__post_init__
but we pass all strings though jinja again to render any other jinja
in the IOC (e.g. database and function entries)
once uses the name of the definition + suffix to track which lines
have been rendered already. The suffix can be used where a given
Entity has more than one element to render once (e.g. functions)
"""
if when == When.first.value:
name = instance.__definition__.name + suffix
if name not in self.once_done:
self.once_done.append(name)
else:
return ""
elif when == When.last.value:
raise NotImplementedError("When.last not yet implemented")
# Render Jinja entries in the text
result = UTILS.render(instance, text) # type: ignore
if result == "":
return ""
return result + "\n"
def render_script(self, instance: Entity, script_items: Script) -> Optional[str]:
script = ""
for item in script_items:
if isinstance(item, Comment):
comments = "\n".join(["# " + line for line in item.value.split("\n")])
script += self.render_text(
instance, comments, item.when, suffix="comment"
)
elif isinstance(item, Text):
script += self.render_text(
instance, item.value, item.when, suffix="text"
)
return script
[docs]
def render_pre_ioc_init(self, instance: Entity) -> Optional[str]:
"""
render the startup script by combining the jinja template from
an entity with the arguments from an Entity
"""
pre_init = instance.__definition__.pre_init
return self.render_script(instance, pre_init)
[docs]
def render_post_ioc_init(self, instance: Entity) -> Optional[str]:
"""
render the post-iocInit entries by combining the jinja template
from an entity with the arguments from an Entity
"""
post_init = instance.__definition__.post_init
return self.render_script(instance, post_init)
[docs]
def render_environment_variables(self, instance: Entity) -> Optional[str]:
"""
render the environment variable elements by combining the jinja template
from an entity with the arguments from an Entity
"""
variables = getattr(instance.__definition__, "env_vars")
if not variables:
return None
env_var_txt = ""
for variable in variables:
# Substitute the name and value of the environment variable from args
env_template = f"epicsEnvSet {variable.name} {variable.value}"
env_var_txt += UTILS.render(
instance,
env_template,
) # type: ignore
return env_var_txt + "\n"
[docs]
def render_elements(
self,
entities: Sequence[Entity],
render_element: Callable[[Entity], Union[str, None]],
) -> str:
"""
Render elements of a given IOC instance based on calling the correct method
"""
elements = ""
for entity in entities:
if entity.entity_enabled:
element = render_element(entity)
if element:
elements += element
return elements
[docs]
def render_pre_ioc_init_elements(self, entities: Sequence[Entity]) -> str:
"""
Render all of the startup script entries for a given IOC instance
"""
return self.render_elements(entities, self.render_pre_ioc_init)
[docs]
def render_post_ioc_init_elements(self, entities: Sequence[Entity]) -> str:
"""
Render all of the post-iocInit elements for a given IOC instance
"""
return self.render_elements(entities, self.render_post_ioc_init)
[docs]
def render_environment_variable_elements(self, entities: Sequence[Entity]) -> str:
"""
Render all of the environment variable entries for a given IOC instance
"""
return self.render_elements(entities, self.render_environment_variables)