Skip to content

Services

Protocols (lenient)

CreateService

Bases: Protocol[InputT, ResultT]

Structural shape for a create-action service callable.

Lenient by design: **kwargs: Any is the escape hatch that lets the framework pass any extras (URL kwargs, ServiceSpec.kwargs / get_service_kwargs returns) without requiring the service to declare them. Services may freely omit parameters they do not need; the framework inspects the signature and only passes what is declared.

Annotate against this Protocol for IDE / type-checker help on the known pool keys. For full enforcement (no **kwargs escape hatch), use :class:StrictCreateService.

UpdateService

Bases: Protocol[InputT, InstanceT, ResultT]

Structural shape for an update-action service callable.

Receives the resolved instance plus the validated data. Returning None instructs the framework to render the in-memory instance (mirroring DRF's UpdateAPIView shape).

Lenient by design — see :class:CreateService for rationale.

DeleteService

Bases: Protocol[InstanceT, ResultT]

Structural shape for a delete-action service callable.

Receives the resolved instance. Most delete services return None; if you need a response body, return a value and configure ServiceSpec.output_serializer (or output_selector).

Lenient by design — see :class:CreateService for rationale.

Protocols (strict)

StrictCreateService

Bases: Protocol[InputT, ResultT, ExtraT]

Strict shape for a create-action service.

Identical to :class:CreateService except the **kwargs: Any escape hatch is replaced with **extras: Unpack[ExtraT] (:pep:692). When ExtraT is a TypedDict, type checkers enforce that the service declares exactly the extra keys delivered by ServiceSpec.kwargs — nothing more, nothing less.

Use it for services where you want drift-free signatures::

class CreateAuthorKwargs(TypedDict):
    tenant_id: int

def create_author(
    *,
    data: AuthorIn,
    request: HttpRequest,
    user: UserT,
    tenant_id: int,
) -> Author: ...

# Static check that the function matches the strict Protocol:
_: StrictCreateService[AuthorIn, Author, CreateAuthorKwargs] = create_author

StrictUpdateService

Bases: Protocol[InputT, InstanceT, ResultT, ExtraT]

Strict shape for an update-action service.

See :class:StrictCreateService for rationale. Pin the extras delivered by ServiceSpec.kwargs via a TypedDict::

class UpdateAuthorKwargs(TypedDict):
    tenant_id: int

def update_author(
    *,
    instance: Author,
    data: AuthorIn,
    request: HttpRequest,
    user: UserT,
    tenant_id: int,
) -> Author: ...

_: StrictUpdateService[AuthorIn, Author, Author, UpdateAuthorKwargs] = update_author

StrictDeleteService

Bases: Protocol[InstanceT, ResultT, ExtraT]

Strict shape for a delete-action service.

See :class:StrictCreateService for rationale. Most delete services return None; that's fine — annotate ResultT as None.