--- title: Dependencies description: Публичный API вычисляемых значений запроса. sources: - eazy_sdk.dependencies api_fingerprint: "sha256:d16f02296e2945f13e1a01992fb71aab78a13b112aa90eb978b39ddfa83cd3b2" --- ```python dependency( annotation: type[T], *, name: str | None = None, provide: object | None = None, apply=(), cache=DependencyCachePolicy.CALL, secret: bool = False, ) -> DependencySpec[T] ``` ```python Inject( placement: Path | Query | Header | Cookie | JsonField | Form | Part, source: object, cache=DependencyCachePolicy.ATTEMPT, secret: bool = False, ) ``` `DependencySpec` передаётся в `requires=(...)`, а `Inject` в `inject=(...)` объявления операции. ## Binding ```python 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 ```python 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. ```python 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` со значением: ```python 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.