API reference¶
Most of the public API is covered in Reference. The symbols below round out the surface for tool authors and contributors.
foundry CLI¶
Foundry CLI entry point.
The CLI is target-agnostic: every piece of framework-specific
behavior comes from a Target discovered
via the foundry.targets entry-point group. The foundry CLI
loads the config, runs the generic pipeline against the target’s
registry/assembler/env, and writes files to disk.
- clean_cmd(config, out=PosixPath('.'), target_name=None)[source]¶
Delete the output directory.
Removes out and its contents. The current working directory is never deleted.
--configis parsed so the CLI surfaces config errors consistently, but its contents do not influence what is removed.- Return type:
- cli_main()[source]¶
Run the CLI, converting
CLIErrorto a clean exit.Any
CLIErrorraised inside a command is rendered as{prefix}: {message}on stderr and exits with code 1. Other exceptions propagate with a traceback, because they indicate a bug rather than bad user input.- Return type:
- generate_cmd(config, out=PosixPath('.'), target_name=None, clean=False, dry_run=False)[source]¶
Generate files from a config via the selected target.
- Return type:
- targets_list_cmd()[source]¶
List every target registered under
foundry.targets.Each line is formatted as
<name> (<language>)so users can see at a glance which target to pass to--target.- Return type:
- validate_cmd(config, target_name=None)[source]¶
Validate a config file without generating anything.
Parses and schema-checks
--configusing the selected target, then exits. Useful as a pre-commit check or for editor integrations that want fast feedback without running the full pipeline.- Return type:
kiln target¶
Registration of kiln as a foundry target.
Exposes target, the Target
instance the foundry CLI picks up via the foundry.targets
entry-point group declared in kiln’s pyproject.toml.
Importing this module transitively imports kiln’s renderer and
operation modules (via foundry’s entry-point discovery), which
populate foundry.render.registry as a side effect.
foundry.config¶
Load and validate target config files.
Supports .json files directly and .jsonnet files via
foundry.jsonnet, which adds prefix-based stdlib imports so
targets can ship their own libsonnet helpers under a registered
prefix (e.g. import 'kiln/auth/jwt.libsonnet').
- class FoundryConfig(**data)[source]¶
Base class for target-level config schemas.
Targets registering with foundry should subclass this so their config model carries the foundry-recognized meta fields. Today that is just
package_prefix; more may be added as foundry grows. Target-specific fields (auth, databases, apps, routes, whatever) are declared by the subclass.- package_prefix¶
Dotted prefix prepended to the dotted import path of every
GeneratedFile(and used as the on-disk directory prefix). Empty string disables the prefix. Targets that generate Python (or another language with package semantics) should override the default to something sensible (kiln uses"_generated").
- load_config(path, schema, stdlibs=None)[source]¶
Load and validate a config file against schema.
- Parameters:
path (
Path) – Path to a.jsonor.jsonnetfile.schema (
type[FoundryConfig]) – Pydantic model used to validate the parsed data.stdlibs (
Mapping[str,Path] |None) – Optional mapping of jsonnet import prefix to stdlib directory. Seefoundry.jsonnet.evaluate().
- Return type:
- Returns:
Validated model instance of schema.
- Raises:
ConfigError – If the file is missing, has an unsupported extension, fails to parse, or fails schema validation.
foundry.jsonnet¶
Thin wrapper around _jsonnet with prefix-based stdlib imports.
Jsonnet delegates import resolution to a host-supplied callback.
This module provides a callback that interprets the first path
segment of an import as a registered stdlib prefix: given
{"kiln": Path(".../jsonnet")}, an import like
'kiln/auth/jwt.libsonnet' resolves under that directory.
Imports without a matching prefix fall through to the normal
relative-to-importer resolution, so user configs can still
import './shared.libsonnet' freely.
The only public entry points are evaluate() (file in, JSON
string out) and make_import_callback() (the bare callback,
exposed for callers that want to build their own evaluator).
- evaluate(path, stdlibs=None)[source]¶
Evaluate a Jsonnet file to a JSON string.
- Parameters:
- Return type:
- Returns:
JSON string produced by the Jsonnet evaluator.
- Raises:
RuntimeError – If Jsonnet evaluation fails.
OSError – If the file cannot be read.
foundry.pipeline¶
Generic build pipeline: config in, files out.
Runs the Engine over the full config
tree in a single pass, then assembles the build store into files
using foundry’s shared registry and generic assembler. Reads
package_prefix directly from
the config and does not inspect any target-specific field.
- generate(config, target)[source]¶
Generate all files for a validated config.
Engineauto-discovers operations from thefoundry.operationsentry-point group, runs the hierarchical engine once over the full config tree, and hands the resulting build store to foundry’s generic assembler.- Parameters:
config (
FoundryConfig) – Validated config model.target (
Target) – The selected target; itstemplate_diris used to build the Jinja environment passed to renderers.
- Return type:
- Returns:
Flat list of generated files.
- Raises:
GenerationError – If config semantics are invalid (e.g. a resource references an unknown operation, or an operation’s options fail introspection).
foundry.assembler¶
Assembler: combine fragments into output files.
Each dispatched render gets a RenderCtx with store
and instance_id set to the current entry. Renderers yield a
FileFragment (declaring the output file and its
wrapper template) plus one or more SnippetFragment
contributions into the file’s slot lists. This module folds
them: files with the same path merge via |, snippets render
(either from value or their template), and each file’s
wrapper is rendered once with every slot’s items in order.
- assemble(store, registry, ctx)[source]¶
Turn a build store into rendered output files.
Walks every item in the store, dispatches to the registry to collect file/snippet fragments, then renders one file per declared shell with its snippets folded in.
- Parameters:
store (
BuildStore) – The build store from the engine’s build phase.registry (
RenderRegistry) – Render registry with all renderers registered.ctx (
RenderCtx) – Render context – env, config, package prefix.
- Return type:
- Returns:
Flat list of
GeneratedFileobjects ready for output.
foundry.render¶
Render registry for output types.
The @renders decorator registers a function that knows how
to turn a build output into a Fragment – a path,
import set, and shell-template spec. The engine/assembler
calls renderers after the build phase and then groups fragments
by output path to produce final files.
- class FileFragment(path, template, context=<factory>, imports=<factory>)[source]¶
Declares an output file’s wrapper template and scalar context.
One
FileFragmentper output path describes the template the assembler wraps the file in and the non-slot context passed to it. EverySnippetFragmentsharing that path contributes a slot-list item that the assembler folds intocontextbefore the wrapper is rendered.Multiple renderers may emit a
FileFragmentfor the same path (e.g. every route handler at the resource declares the route file) — the assembler requires them to agree ontemplateand unifies theircontextdicts, raising if two disagree on a shared key.A blank
templateis a convention for an empty-content file (e.g.__init__.py).- path¶
Output path relative to the output directory.
- template¶
Jinja2 template name that wraps the file.
- context¶
Non-slot template variables. Merged across all FileFragments at this path (shared keys must agree).
- imports¶
Imports the wrapper itself needs, on top of any contributed by snippets.
- Fragment = foundry.render.FileFragment | foundry.render.SnippetFragment¶
Union of fragment types a renderer may yield.
- class RenderCtx(env, config, package_prefix='', language='', store=<factory>, instance_id='')[source]¶
Context passed to every renderer function.
- env¶
Jinja2 environment for template lookups.
- config¶
The full project config dict (or model).
- package_prefix¶
Dotted prefix for generated imports, e.g.
"_generated".
- language¶
Target language identifier used to render import blocks (e.g.
"python"). Must match a formatter declared in thefoundry.import_formattersentry-point group.
- store¶
The build store. Renderers reach ancestor scope instances through it (e.g. a handler rendered at operation scope looks up its resource via
store.ancestor_of(instance_id, "resource")).
- class RenderRegistry(_entries=<factory>)[source]¶
Maps output types to renderer functions.
Example:
registry = RenderRegistry() @registry.renders(RouteHandler) def render_route(handler, ctx): return Fragment(...)
- render(obj, ctx)[source]¶
Produce fragments for a build output.
Every registered renderer returns an iterable of fragments (typically as a generator via
yield). Renderers usually yield aFileFragmentdeclaring the output file plus one or moreSnippetFragmentcontributions into its slots.- Parameters:
- Return type:
- Returns:
A list of fragments. May be empty if the renderer decides not to contribute.
- Raises:
LookupError – No renderer registered for the type.
- renders(output_type)[source]¶
Register a renderer for output_type.
- Parameters:
output_type (
type) – The output class this renderer handles.- Return type:
Callable[[Callable[[Any,RenderCtx],Iterable[FileFragment|SnippetFragment]]],Callable[[Any,RenderCtx],Iterable[FileFragment|SnippetFragment]]]- Returns:
The original function, unmodified.
- class SnippetFragment(path, slot, template=None, context=<factory>, value=None, imports=<factory>)[source]¶
A contribution slotted into a file’s context list.
Each snippet becomes one entry in
file.context[slot]— a list the wrapper template iterates over. Snippets at the same path may target different slots.Supply exactly one of
template(rendered by the assembler into a string) orvalue(used as-is, may be any type — useful for dict slots the wrapper iterates over itself).- path¶
Output path; must match a
FileFragment.
- slot¶
Key in the file’s context this snippet appends to.
- template¶
Jinja2 template the assembler renders against
contextto produce a string slot item. Mutually exclusive withvalue.
- imports¶
Imports this contribution needs in the output file’s import block.
- render_slot_item(env)[source]¶
Return the slot-list item this snippet contributes.
When
templateis set the assembler renders it againstcontextand strips surrounding whitespace, so the surrounding file template can join items with its own separators without fighting jinja’s trailing newline. Otherwisevalueis passed through unchanged.- Return type:
- registry = RenderRegistry(_entries={<class 'kiln.operations.types.SchemaClass'>: <function _schema_fragment>, <class 'kiln.operations.types.EnumClass'>: <function _enum_fragment>, <class 'kiln.operations.types.RouteHandler'>: <function _handler_fragment>, <class 'kiln.operations.types.SerializerFn'>: <function _serializer_fragment>, <class 'kiln.operations.types.TestCase'>: <function _testcase_fragment>, <class 'foundry.outputs.StaticFile'>: <function _static_fragment>})¶
Process-wide render registry.
Targets’ renderer modules register into this singleton at import time. Because foundry discovers operations via the
foundry.operationsentry-point group and loading an operation transitively imports its renderer module, no separate renderer-discovery step is needed — by the time the pipeline’s assembler runs, every renderer is registered.
kiln.operations¶
FastAPI renderers for build output types.
Each renderer is an @registry.renders(SomeOutput) generator
that yields fragments: a FileFragment
declaring the output file’s wrapper template and scalar
context, plus one or more SnippetFragment
contributions into its slot lists. The assembler groups
fragments by path, folds snippets into the file’s context, and
renders each wrapper template once.
Per-op RouteHandler rendering is owned by each op module (e.g.
kiln.operations.list). Those modules call
build_handler_fragment() with their op-specific body
template, context, and import tuple. This module keeps only
the cross-cutting renderers (schema / enum / serializer /
testcase / static) plus a generic RouteHandler
fallback for hand-written handlers that aren’t one of the
registered subclasses.
- render_enum_class(enum)[source]¶
Render an Enum class definition string.
Kept as a Python string builder because repr-formatted member values aren’t something jinja filters express cleanly. Called from
_enum_fragment()to pre-render the slot value.- Return type:
- utils_imports()[source]¶
Return import pairs for the
ingotruntime helpers.The three CRUD ops that load-or-404 a row (get, update, delete) all need
get_object_from_query_or_404andassert_rowcount; this centralizes the pair.
Get operation: GET /{pk} – retrieve a single resource.
- class Get[source]¶
GET /{pk} – retrieve a single resource.
- Options¶
alias of
FieldsOptions
- build(ctx, options)[source]¶
Produce output for GET /{pk}.
- Parameters:
ctx (
BuildContext[OperationConfig]) – Build context for the"get"operation entry.options (
FieldsOptions) – ParsedFieldsOptions.
- Yields:
The
{Model}Resourceschema, its serializer, the route handler, and a test case.- Return type:
List operation: POST /search – list/filter/sort/paginate resources.
- class List[source]¶
POST /search – list/filter/sort/paginate resources.
Always emits a single
POST /searchroute; never a GET. Whenfilters,ordering, orpaginationis configured, aSearchRequestbody carries the query, the handler calls the matching ingot helpers, and (for pagination) aPageschema wraps the response. With no extensions configured, the handler takes no body and returnslist[{Model}ListItem].- build(ctx, options)[source]¶
Produce output for POST /search.
- Parameters:
ctx (BuildContext[OperationConfig]) – Build context for the
"list"operation entry.options (Options) – Parsed
Options.
- Yields:
The
{Model}ListItemschema, its serializer, and the POST/searchhandler + test case. Additionally yields extension schemas (filter / sort / search-request / page) when the corresponding options are configured.- Return type:
Iterable[object]
Create operation: POST / – create a new resource.
- class Create[source]¶
POST / – create a new resource.
- Options¶
alias of
FieldsOptions
- build(ctx, options)[source]¶
Produce output for POST /.
- Parameters:
ctx (
BuildContext[OperationConfig]) – Build context for the"create"operation entry.options (
FieldsOptions) – ParsedFieldsOptions.
- Yields:
The
{Model}CreateRequestschema, the route handler, and a test case.- Return type:
Update operation: PATCH /{pk} – partially update a resource.
- class Update[source]¶
PATCH /{pk} – partially update a resource.
- Options¶
alias of
FieldsOptions
- build(ctx, options)[source]¶
Produce output for PATCH /{pk}.
- Parameters:
ctx (
BuildContext[OperationConfig]) – Build context for the"update"operation entry.options (
FieldsOptions) – ParsedFieldsOptions.
- Yields:
The
{Model}UpdateRequestschema (all fields optional), the route handler, and a test case.- Return type:
Delete operation: DELETE /{pk} – delete a resource.
- class Delete[source]¶
DELETE /{pk} – delete a resource.
- Options¶
alias of
EmptyOptions
- build(ctx, _options)[source]¶
Produce output for DELETE /{pk}.
- Parameters:
ctx (
BuildContext[OperationConfig]) – Build context for the"delete"operation entry._options (
EmptyOptions) – Unused.
- Yields:
The route handler and a test case.
- Return type:
Action operation: custom endpoint via function introspection.
- class Action[source]¶
Custom action endpoint via function introspection.
Dispatches on the presence of a
fnattribute rather than a literal name match: anyOperationConfigwhoseoptionsincludefnbecomes an action.- build(ctx, options)[source]¶
Produce output for a custom action endpoint.
- Parameters:
ctx (BuildContext[OperationConfig]) – Build context for the action’s operation entry.
options (Options) – Parsed Action.Options with
fnpath.
- Yields:
The route handler and a test case.
- Return type:
Iterable[object]
Auth operation: augments CRUD handlers with auth dependencies.
Auth is a resource-scoped operation that runs after the CRUD and action operations have produced their route handlers and test cases. When the project has auth configured and the current resource opts in, it:
Appends
current_user: Annotated[dict, Depends(...)]to eachRouteHandler’sextra_depsso the template renders the auth dependency.Appends the
get_current_userimport to the handler’sextra_importsso the assembler includes it.Flips
TestCase.requires_authso the generated tests expect a 401 without credentials.
This is the first example of an operation in the augment role: it produces no new outputs, only mutates earlier ones.
- class Auth[source]¶
Augment CRUD/action handlers and tests with auth.
Runs at resource scope with
after_children=Trueso all operation-scope ops under this resource have already produced their handlers and test cases by the time auth sweeps through.- Options¶
alias of
EmptyOptions
- build(ctx, _options)[source]¶
Mutate earlier handlers/tests to require auth.
- Parameters:
ctx (
BuildContext[ResourceConfig]) – Build context with store of earlier outputs._options (
BaseModel) – Unused.
- Return type:
- Returns:
Empty iterable – this operation only mutates earlier output and emits no new objects.
- when(ctx)[source]¶
Apply only when auth is configured and the resource opts in.
- Parameters:
ctx (
BuildContext[ResourceConfig]) – Build context for the current resource.- Return type:
- Returns:
Truewhen the project config hasauthset and the resource hasrequire_auth(defaultTrue).
Scaffold operations: db sessions and auth dependencies.
Produces StaticFile objects for
infrastructure files. Split into two operations:
Scaffold– always runs; emits thedb/tree.AuthScaffold– runs only when the project config hasauthset, viaAuthScaffold.when().
- class AuthScaffold[source]¶
Generate
auth/infrastructure files.- Options¶
alias of
EmptyOptions
- build(ctx, _options)[source]¶
Produce static files for auth dependencies and router.
- Parameters:
ctx (
BuildContext[ProjectConfig]) – Build context with project config.whenhas already confirmedctx.instance.auth is not None._options (
BaseModel) – Unused (no options).
- Yields:
StaticFilefor theauth/package, the dependencies module, and the JWT router (only when using the default flow).- Return type:
- when(ctx)[source]¶
Apply only when the project config has
authset.- Parameters:
ctx (
BuildContext[ProjectConfig]) – Build context with project config.- Return type:
- Returns:
Truewhenctx.instance.authis notNone.
- class Scaffold[source]¶
Generate
db/infrastructure files.- Options¶
alias of
EmptyOptions
- build(ctx, _options)[source]¶
Produce static files for db sessions.
- Parameters:
ctx (
BuildContext[ProjectConfig]) – Build context with project config._options (
BaseModel) – Unused (no options).
- Yields:
StaticFileobjects for thedb/package and one session module per configured database.- Return type:
Router operations: per-app router and project router.
- class ProjectRouter[source]¶
Generate
routes/__init__.pymounting all apps.- Options¶
alias of
EmptyOptions
- build(ctx, _options)[source]¶
Produce the project-level router file.
Only produces output for configs that have an
appslist.ProjectConfigwraps a single-app shorthand into an implicit app withprefix=""at validation time, so every project config routed throughgenerate()has at least one app and this op runs unconditionally in the normal pipeline.- Parameters:
ctx (
BuildContext[ProjectConfig]) – Build context; instance is the project config._options (
BaseModel) – Unused.
- Yields:
Single
StaticFilefor the project router, or nothing for configs that have no apps at all.- Return type:
- class Router[source]¶
Generate one app’s
{module}/routes/__init__.py.Runs in the post-children phase of the app scope so the build store is fully populated with resource-scope output beneath this app. Emits one
RouterMountper resource that produced at least oneRouteHandlerplus a singleStaticFilethat aggregates them into the app’s router module.- Options¶
alias of
EmptyOptions
- build(ctx, _options)[source]¶
Produce this app’s router-aggregation file.
- Parameters:
ctx (
BuildContext[App]) – Build context for oneApp;storeis fully populated with resource-scope output becauseafter_children=True._options (
BaseModel) – Unused.
- Yields:
A single
StaticFilefor the app’s routes package, carrying oneroutesentry per resource that produced aRouteHandler. Nothing is yielded when no resource in the app produced a handler.- Return type:
Runtime helpers for kiln-generated FastAPI projects.
These are the shared route utilities that generated code imports
directly (from ingot import apply_offset_pagination, ...) rather
than having its own copy emitted into the target project.
Everything here is pure Python — the kiln CLI knows to emit imports
pointing at this module instead of scaffolding a utils.py into
the generated app.
- apply_filters(stmt, node, model)[source]¶
Build WHERE clauses from a typed filter expression.
Accepts a typed Pydantic filter model — either a single condition (with
field,op,value) or a combiner (withand_/or_lists of nested conditions). Models that match none of these shapes are treated as a no-op and the statement is returned unchanged.- Parameters:
stmt (
Select) – The SQLAlchemy SELECT statement to filter.node (
BaseModel) – A Pydantic model representing the filter tree.model (
type) – The SQLAlchemy model class providing columns.
- Return type:
Select- Returns:
The statement with WHERE clauses applied.
- apply_keyset_pagination(stmt, model, cursor, cursor_field, page_size, max_page_size)[source]¶
Apply keyset (cursor-based) pagination to a SELECT.
Adds a
WHERE cursor_field > cursorclause when a cursor is provided, clamps page_size, and addsLIMIT page_size + 1(the extra row detects whether more results exist).- Parameters:
stmt (
Select) – The SQLAlchemy SELECT statement.model (
type) – The SQLAlchemy model class providing columns.cursor (
Any) – The cursor value (already cast to the correct type), orNone.cursor_field (
str) – Name of the cursor column.page_size (
int) – Requested page size.max_page_size (
int) – Maximum allowed page size.
- Return type:
- Returns:
(paginated_stmt, effective_page_size)tuple. The caller is responsible for executing paginated_stmt.
- apply_offset_pagination(stmt, offset, limit, max_page_size)[source]¶
Apply offset pagination to a SELECT.
Clamps limit to max_page_size, applies
OFFSET/LIMIT, and builds a companionCOUNT(*)statement so the caller can fetch the total alongside the page.- Parameters:
- Return type:
- Returns:
(paginated_stmt, count_stmt, effective_limit)tuple. The caller is responsible for executing both statements.
- apply_ordering(stmt, sort_clauses, model, default_field, default_dir='asc')[source]¶
Apply one or more sort clauses to a SELECT statement.
Each clause is a Pydantic model with
field(an enum whose.valueis the column name) anddir(SortDirection).When sort_clauses is
Noneor empty, the default field and direction are used.- Parameters:
stmt (
Select) – The SQLAlchemy SELECT statement to sort.sort_clauses (
Sequence[BaseModel] |None) – List of sort clause models, orNone.model (
type) – The SQLAlchemy model class providing columns.default_field (
str) – Column name to sort by when no clauses are provided.default_dir (
Literal['asc','desc']) – Direction for the default sort.
- Return type:
Select- Returns:
The statement with ORDER BY applied.
- assert_rowcount(result, *, expected=1, status_code=404, detail='Not found')[source]¶
Raise HTTPException when result did not affect expected rows.
- Parameters:
- Raises:
HTTPException – When
result.rowcountdoes not equal expected.- Return type: