Source code for codegen.outputs
"""Target-agnostic build-phase output types.
Only :class:`~codegen.outputs.StaticFile` is truly target-neutral
and lives here; Python / FastAPI / Pydantic output types live in
:mod:`be.outputs` since a non-Python target wouldn't use them.
"""
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Any, Literal
from codegen.render import FileFragment, registry
if TYPE_CHECKING:
from collections.abc import Iterator
from codegen.render import Fragment, RenderCtx
[docs]
@dataclass
class StaticFile:
"""A file rendered directly from a template.
Used for scaffold files (auth, db sessions), utils, and other
files that don't need the assembler's multi-contributor merging.
``if_exists`` defaults to ``"overwrite"`` (be's regenerated
scaffold behaviour); ``"skip"`` makes
:func:`codegen.output.write_files` leave existing files alone
-- right for one-shot bootstraps like be_root, where
``--force`` / ``--force-paths`` is the explicit opt-in to
clobber.
``executable`` sets the user/group/other ``+x`` bits on the
emitted file after write -- use for shell scripts the
surrounding ``justfile`` / ``package.json`` invokes via a bare
``./scripts/foo.sh`` rather than ``bash ./scripts/foo.sh``.
``banner`` defaults to ``True``; set ``False`` to suppress the
engine-emitted autogenerated header for files that must not
carry one.
"""
path: str
template: str
context: dict[str, Any] = field(default_factory=dict)
if_exists: Literal["overwrite", "skip"] = "overwrite"
executable: bool = False
banner: bool = True
@registry.renders(StaticFile)
def _static_fragment(sf: StaticFile, _ctx: RenderCtx) -> Iterator[Fragment]:
"""Render a :class:`StaticFile` into a single :class:`FileFragment`.
Lives in codegen (next to :class:`StaticFile`) rather than in
a target package so every target gets the renderer the moment
it imports :mod:`codegen.outputs` -- without this, a target
that doesn't transitively import be's renderer module would
fail with ``LookupError: No renderer for StaticFile`` the
first time an op yields one.
"""
yield FileFragment(
path=sf.path,
template=sf.template,
context=dict(sf.context),
if_exists=sf.if_exists,
executable=sf.executable,
banner=sf.banner,
)