Dependencies#

dependency(
    annotation: type[T],
    *,
    name: str | None = None,
    provide: object | None = None,
    apply=(),
    cache=DependencyCachePolicy.CALL,
    secret: bool = False,
) -> DependencySpec[T]
Inject(
    placement: Path | Query | Header | Cookie | JsonField | Form | Part,
    source: object,
    cache=DependencyCachePolicy.ATTEMPT,
    secret: bool = False,
)

DependencySpec передаётся в requires=(...), а Inject в inject=(...) объявления операции.

Binding#

field("attribute").to_header("X-Name")
field("attribute").to_query("name")
field("attribute").to_cookie("name")
field("attribute").to_body("name")
value().to_header("X-Value")

Binding

Target

field(name).to_header(name)

Request header

field(name).to_query(name)

Query parameter

field(name).to_cookie(name)

Cookie

field(name).to_body(name)

Поле тела

value().to_*

Весь результат зависимости

apply= пишет в уже объявленный слот операции: отсутствие цели среди полей означает ошибку объявления (dependency target is not declared: header.X-Device-Id). Inject создаёт слот сам и потому не требует поля, но конфликтует с одноимённым полем операции.

Cache#

DependencyCachePolicy поддерживает NONE, CLIENT, CALL и ATTEMPT. dependency(...) по умолчанию CALL, а Inject(...) использует ATTEMPT.

Registry#

registry.register(spec.dependency, provider)
Identity(dependencies=registry)

Поставщик является объектом с синхронным или асинхронным методом resolve(context: DependencyContext); callable без resolve оборачивается автоматически, когда передан через provide= или как Inject.source. provide= задаёт reusable provider identity, но реализация всегда живёт в DependencyRegistry, а не в операции.

Адрес сервиса#

service_url(Router, path="") служит источником для Inject и для dependency(provide=...): это адрес, к которому роутер привязан в корне SDK.

Inject(markers.Header("Origin"), service_url(LoginPagesApi))
Inject(markers.Header("Referer"), service_url(LoginPagesApi, "/"))

Без роутера это адрес сервиса самой операции. Базовый класс называет все роутеры, которые его наследуют; у них должен быть один адрес. Роутер, которого нет в корне, даёт PlanError до отправки запроса. Те же значения доступны поставщику: context.base_url, context.services, context.service_url(...).

Проекция#

Проекция, объявленная с двумя параметрами, получает разрешённые значения requires= как Injected сопоставляет RequestDependency со значением:

def to_wire(source: CreateOrder, injected: Injected) -> OrderWire: ...

secret=True redacts значение из diagnostics. Missing provider, invalid result type или конфликт нескольких bindings завершается до network side effects. ATTEMPT dependency пересчитывается для retry/redirect; CALL reuse-ится в пределах logical call.