Source code for ibek.render

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

from typing import Callable, List, Optional, Union

from .ioc import IOC, Entity
from .support import Comment, Script, Text, When
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, 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: if entity.entity_enabled: element = method(entity) 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)