Source code for ibek.render

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

from typing import Callable, List, Optional, Union

from .globals import render_with_utils
from .ioc import IOC, Entity
from .support import Comment, Script, Text, When


[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 = render_with_utils(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 += render_with_utils(instance, env_template) # type: ignore return env_var_txt + "\n"
[docs] def render_elements( self, ioc: IOC, method: Callable[[Entity], Union[str, None]] ) -> str: """ Render elements of a given IOC instance based on calling the correct method """ elements = "" for entity in ioc.entities: # TODO can we eliminate the need for intermediate root # see definition of EntityModel in ioc.py instance = getattr(entity, "root") if instance.entity_enabled: element = method(instance) if element: elements += element return elements
[docs] def render_pre_ioc_init_elements(self, ioc: IOC) -> str: """ Render all of the startup script entries for a given IOC instance """ return self.render_elements(ioc, self.render_pre_ioc_init)
[docs] def render_post_ioc_init_elements(self, ioc: IOC) -> str: """ Render all of the post-iocInit elements for a given IOC instance """ return self.render_elements(ioc, self.render_post_ioc_init)
[docs] def render_environment_variable_elements(self, ioc: IOC) -> str: """ Render all of the environment variable entries for a given IOC instance """ return self.render_elements(ioc, self.render_environment_variables)