Source code for ibek.render

"""
Functions for rendering lines in the boot script using Jinja2
"""

from typing import Callable, List, Optional, Sequence, Union

from .entity_model 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 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 model + 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._model.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._model.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._model.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._model, "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)