HsingMD / src /casmd /bundle /renderer.py
zzhaobz's picture
Deploy sanitized fictional Variant A release
4c02fbe
Raw History Blame Contribute Delete
1.82 kB
"""Render Jinja2 templates with a BundleSpec.
Templates are shipped as package data under `casmd/bundle/templates/`.
"""
from __future__ import annotations
from dataclasses import asdict
from importlib import resources
from typing import Any
from jinja2 import Environment, BaseLoader, TemplateNotFound
from casmd.bundle.spec import BundleSpec
_TEMPLATE_NAMES = (
"step1_minimization.mdp",
"step2_nvt.mdp",
"step3_npt.mdp",
"step4_production.mdp",
"submit.sh",
"run_md.sh",
"analyze.py",
"README.md",
)
class _PackageLoader(BaseLoader):
"""Load Jinja2 templates from casmd.bundle.templates package data."""
def get_source(self, environment, template: str):
try:
res = resources.files("casmd.bundle.templates").joinpath(f"{template}.j2")
text = res.read_text(encoding="utf-8")
except (FileNotFoundError, ModuleNotFoundError):
raise TemplateNotFound(template)
return text, None, lambda: True
_ENV = Environment(loader=_PackageLoader(), keep_trailing_newline=True)
def list_template_names() -> list[str]:
return list(_TEMPLATE_NAMES)
def render(name: str, spec: BundleSpec, *, extra: dict[str, Any] | None = None) -> str:
"""Render template `name` using a BundleSpec (plus optional extra context)."""
if name not in _TEMPLATE_NAMES:
raise KeyError(f"unknown template {name!r}; known: {_TEMPLATE_NAMES}")
ctx: dict[str, Any] = asdict(spec)
# Add derived ints from spec properties
ctx["production_steps"] = spec.production_steps
ctx["nvt_steps"] = spec.nvt_steps
ctx["npt_steps"] = spec.npt_steps
ctx["output_every_steps"] = spec.output_every_steps
if extra:
ctx.update(extra)
template = _ENV.get_template(name)
return template.render(**ctx)