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, )