Source code for camacq.helper.template

"""Handle templates."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

import jinja2
from jinja2.sandbox import ImmutableSandboxedEnvironment

from camacq.exceptions import TemplateError
from camacq.plugins.leica.sample import LeicaSample, next_well_xy
from camacq.plugins.sample import get_matched_samples

if TYPE_CHECKING:
    from camacq.control import Center
    from camacq.plugins.sample import Sample

TEMPLATE_ENV_DATA = "template_env"


[docs] def get_env(center: Center) -> ImmutableSandboxedEnvironment: """Get the template environment.""" if TEMPLATE_ENV_DATA not in center.data: env = ImmutableSandboxedEnvironment() env = _set_global(env, "next_well_xy", template_next_well_xy) env = _set_global(env, "next_well_x", template_next_well_x) env = _set_global(env, "next_well_y", template_next_well_y) env = _set_global(env, "matched_samples", get_matched_samples) center.data[TEMPLATE_ENV_DATA] = env return center.data[TEMPLATE_ENV_DATA]
def _set_global( env: ImmutableSandboxedEnvironment, func_name: str, func: Any ) -> ImmutableSandboxedEnvironment: """Set a template environment global function.""" env.globals[func_name] = func return env
[docs] def make_template(center: Center, data: Any) -> Any: """Make templated data.""" if isinstance(data, dict): return {key: make_template(center, val) for key, val in data.items()} if isinstance(data, list): return [make_template(center, val) for val in data] env = get_env(center) return env.from_string(str(data))
[docs] def render_template(data: Any, variables: dict[str, Any]) -> Any: """Render templated data.""" if isinstance(data, dict): return {key: render_template(val, variables) for key, val in data.items()} if isinstance(data, list): return [render_template(val, variables) for val in data] try: rendered = data.render(variables) except jinja2.TemplateError as exc: raise TemplateError(exc) from exc return rendered
[docs] def template_next_well_xy( sample: Sample, plate_name: str, x_wells: int = 12, y_wells: int = 8 ) -> tuple[int | None, int | None]: """Return the next not done well for the given plate x, y format.""" return next_well_xy(sample, plate_name, x_wells, y_wells) # type: ignore[arg-type]
[docs] def template_next_well_x( sample: LeicaSample, plate_name: str, x_wells: int = 12, y_wells: int = 8 ) -> int | None: """Return the next well x coordinate for the plate x, y format.""" x_well, _ = next_well_xy( sample, plate_name, x_wells=x_wells, y_wells=y_wells, ) return x_well
[docs] def template_next_well_y( sample: LeicaSample, plate_name: str, x_wells: int = 12, y_wells: int = 8 ) -> int | None: """Return the next well x coordinate for the plate x, y format.""" _, y_well = next_well_xy( sample, plate_name, x_wells=x_wells, y_wells=y_wells, ) return y_well