Skip to content

angee.compose.runtime

Build-time runtime source rendering and emission.

Runtime is the composer's emitter: it reads the discovered addons' abstract source models and renders the concrete Django apps under runtime/<label>/ that each source addon then adopts (see angee.compose.apps and docs/composer.md). render_sources is the seam — everything reaching it is generic plugin composition (discover, order, drift, clean); everything inside it is Angee's concrete emission.

ModelContributions

python
class ModelContributions(NamedTuple)

Abstract source models one addon contributes, split by composition role.

owned

Models emitted as concrete runtime classes under the addon's label.

extensions

Same-row extensions that merge fields into another addon's model.

Runtime

python
class Runtime()

Owner for Angee runtime rendering, emission, checks, and cleanup.

One object owns the whole build-time lifecycle so the plan and the emit travel together (docs/backend/guidelines.md → compose-onto-classes):

  • render_sources — the seam: returns {relative path: text} for the whole runtime. Every other entry point renders through it.
  • emit — write that map to runtime_dir during the explicit angee build pass (resets, prunes orphans).
  • is_current / check / _drift — disk vs the rendered map.
  • reset / clean — delete generated files behind the GENERATED_SENTINEL gate while preserving */migrations/.

Construction groups source models by emitted label, resolves extends extensions, and fails fast on field collisions, so an invalid composition never reaches emission.

__init__

python
def __init__(addons: Iterable[AppConfig],
             *,
             runtime_dir: Path,
             runtime_module: str = "runtime") -> None

Create a runtime renderer for addons and runtime_dir.

from_django

python
@classmethod
def from_django(cls) -> Runtime

Return a runtime using installed addons and Django settings.

ANGEE_RUNTIME_DIR is the single owner of where the runtime lives. angee.compose.settings always sets it. A host that installs the composer without it is misconfigured, so fail loudly here rather than let a caller silently skip emission and surface a cryptic missing-model error later in app population.

render_sources

python
def render_sources() -> dict[Path, str]

Return generated runtime source files keyed by relative path.

The composition seam. The returned map (path relative to runtime_dir → file text) is the single source of truth that emit writes and _drift compares against disk. It contains the generated package __init__ plus, per label, an empty app/migrations __init__ and a models.py. Migrations themselves are never rendered here — Django's makemigrations owns runtime/<label>/migrations/ (redirected via MIGRATION_MODULES), and cleanup preserves it.

emit

python
def emit() -> None

Reset the runtime and write all sources (destructive; explicit).

Used by the angee build command: it runs the _ensure_cleanable gate and prunes stale files (e.g. a removed addon's leftover label), then rewrites.

import_generated_models

python
def import_generated_models() -> None

Import generated concrete model modules for all emitted labels.

emit_if_stale

python
def emit_if_stale() -> bool

Write the runtime when it drifts from the sources, on every boot.

Called from the composer's import_models in app-populate phase 2. Write-only and idempotent: it never resets or cleans, so a present-but- stale runtime is healed file by file and a corrupted or non-Angee directory can never abort app population through the destructive _ensure_cleanable gate. Orphaned files from a removed addon are pruned by the explicit angee build (which calls emit). Returning early when current keeps boots fast and avoids churning files the running process (and Django's autoreloader) already imported.

configure_migration_modules

python
def configure_migration_modules() -> Runtime

Redirect migrations for emitted runtime app labels.

is_current

python
def is_current() -> bool

Return whether the on-disk runtime matches the rendered sources.

check

python
def check() -> None

Raise when generated runtime sources differ from disk.

reset

python
def reset() -> None

Clear generated runtime sources while preserving migrations.

clean

python
def clean() -> None

Delete generated runtime files while preserving migrations.

model_contributions

python
def model_contributions(app_config: AppConfig) -> ModelContributions

Return source models and extensions declared by one Django app config.

Runtime owns this scan because addons deliberately remain plain Django AppConfig classes with no shared Angee base method to delegate to.

Released under the AGPL-3.0 License.