Skip to content

jmaple.capabilities

The plugin contract. Subclass CrudCapability for standard CRUD-shaped data types or BaseCapability for non-CRUD capabilities.

CrudCapability

Bases: BaseCapability

Declarative capability that provides the JMAP standard method set.

Subclasses define the data-type name, SQLAlchemy models, and Pydantic schemas as class attributes. The framework generates <Type>/get, <Type>/changes, <Type>/set, <Type>/query, <Type>/copy, and <Type>/queryChanges method handlers from those.

Hooks (override to customise): * :meth:filter_clauses — translate the JMAP filter object into SQLAlchemy expressions for <Type>/query. * :meth:to_schema — convert a model row to its Pydantic wire shape. * :meth:create_model — build a model instance from a create payload. * :meth:clone_model — build a copied row for <Type>/copy. * :meth:get_custom_methods — return extra non-standard handlers.

clone_model classmethod

clone_model(
    source: Any,
    payload: dict[str, Any],
    account_id: str,
    obj_id: str,
) -> Any

Build a copied model row for <Type>/copy (override patches applied).

create_model classmethod

create_model(
    payload: BaseModel, account_id: str, obj_id: str
) -> Any

Construct a model instance from a validated create payload.

filter_clauses classmethod

filter_clauses(filter_: Any, account_id: str) -> list[Any]

Build SQLAlchemy WHERE clauses for <Type>/query.

The default scopes to account_id; subclasses extend with predicates translated from the JMAP filter object.

get_custom_methods classmethod

get_custom_methods() -> list[MethodHandler]

Override to add non-CRUD method handlers under this capability.

to_schema classmethod

to_schema(instance: Any) -> BaseModel

Convert one model row to its Pydantic wire-shape schema.

BaseCapability

Bare-bones capability base class for non-CRUD plugins.

Subclass when your capability either has no data type at all (admin-style capabilities, websocket signalling), or when you want full manual control over the method handlers. Most plugins use :class:CrudCapability instead.

as_capability classmethod

as_capability() -> Capability

Materialise the declarative class into a :class:Capability instance.

Call this in your capability module so the entry-point target is the instance, not the class itself.

get_account_properties classmethod

get_account_properties(
    account: Account,
) -> dict[str, Any] | None

Return per-account properties (or None to hide this capability from the account).

get_methods classmethod

get_methods() -> list[MethodHandler]

Return the JMAP method handlers this capability registers.

get_session_properties classmethod

get_session_properties(
    settings: Settings,
) -> dict[str, Any]

Return the object advertised under this capability's URN on the JMAP session.

Capability dataclass

A single JMAP capability — the unit of pluggability.

MethodHandler dataclass

One callable JMAP method, namespaced under a capability.

DataType dataclass

A JMAP data type contributed by a capability — e.g. Note, Mailbox.

make_capability

make_capability(
    urn: str,
    *,
    session_properties: SessionPropertiesFn | None = None,
    account_properties: AccountPropertiesFn | None = None,
    data_types: tuple[DataType, ...] = (),
    methods: tuple[MethodHandler, ...] = (),
    settings_model: type[BaseModel] | None = None,
) -> Capability

Construct a :class:Capability with sane defaults.

Defaults: session_properties advertises an empty object; account_properties advertises the capability on every account with no properties.