Skip to content

angee.addons

Plain AppConfig helpers for Angee addon declarations.

AddonContract

python
@dataclass(frozen=True, slots=True)
class AddonContract()

An addon's declarative contract, read from its co-located addon.toml.

The manifest reuses pyproject's metadata vocabulary verbatim (description/keywords/license/readme/version/authors/ urls) so hatch-angee can compile it straight into the package's [project]. The Angee-owned fields are only what pyproject lacks: the addon name (import id), the inter-addon depends_on graph, the freeform category, and the contribution seams — schemas/permissions (simple strings) in [addon]; web/mcp/resources as their own sections. The presence of the manifest is the addon marker, so an addon needs an apps.py only when it has a python seam to run (ready()). The contribution seams default to what the directory reveals (schema.py, permissions.zed, web/package.json, mcp_tools.py); a manifest entry only overrides that default. permissions records the .zed contribution for the catalog — a remote catalog reads the manifest, never the addon's files — while the runtime still discovers the .zed by convention (adjacent to the addon).

addon_contract

python
def addon_contract(app_config: AppConfig) -> AddonContract | None

Return the addon's declared contract.

An explicit _addon_contract attribute wins — a code-defined addon (or a test) that carries its contract in memory rather than a file on disk. Otherwise the contract is parsed from the co-located addon.toml. None for any app with neither (plain Django apps, non-addons).

AvailableAddon

python
@dataclass(frozen=True, slots=True)
class AvailableAddon()

An addon present in the environment, whether or not it is enabled.

source is "installed" for an addon advertised by an installed bundle's angee.addons entry point, or "local" for one discovered as an addon.toml under a configured addon dir. anchor is the entry point's import target (installed) or the addon directory (local).

available_addons

python
def available_addons(addon_dirs: Iterable[Path | str] = (
)) -> dict[str, AvailableAddon]

Return every available addon, keyed by name.

The available set is the union of (1) the angee.addons entry points across all installed distributions — the SSOT being uv.lock's bundles, the same way pip-installed packages are "available" before being added to INSTALLED_APPS — and (2) any addon.toml under the configured addon dirs (local/uninstalled consumer addons). The enabled set (INSTALLED_APPS) is expected to be a subset of this. Pure importlib.metadata + filesystem; no Django app loading required, so a catalog/marketplace can read it cheaply.

is_angee_addon

python
def is_angee_addon(app_config: AppConfig) -> bool

Return whether app_config is an Angee addon.

An app is an addon exactly when it carries a contract — a co-located addon.toml manifest (the on-disk case) or an in-memory _addon_contract (a code-defined addon or a test). The manifest is the marker; no apps.py opt-in flag is needed.

resolve_addon_reference

python
def resolve_addon_reference(app_config: AppConfig, dotted: str, *,
                            attr: str) -> Any

Import the object a <attr> dotted reference on an addon names.

A bare "module.name" is taken relative to the addon's import package (app_config.name); an already-qualified path is used as-is. Raises ImproperlyConfigured naming <addon>.<attr> on failure. The one owner of the manifest dotted-reference contract shared by the schemas (GraphQL) and mcp_tools (MCP) discovery seams — including the fail-fast that the reference is a dotted string in the first place.

addon_contribution

python
def addon_contribution(app_config: AppConfig,
                       module_name: str,
                       attr: str,
                       *,
                       allow_callable: bool = False) -> list[Any]

Return an installed addon's conventional iterable contribution.

Addon subsystems expose small conventional modules such as urls.py or asgi.py. This helper owns the repeated Angee-addon gate, submodule check, import error shape, optional callable execution, and iterable validation.

Released under the AGPL-3.0 License.