Parent: #452
JS source
.changeset/adapter-translation-helpers.md (6.7).
What Python adopters write today
200+ lines of httpx.AsyncClient boilerplate per upstream — auth header injection, 404→None translation, retry/timeout policy, JSON decode. See examples/v3_reference_seller/src/upstream.py for the canonical hand-rolled version.
Plus per-adapter bidirectional code↔code translation maps (status enums, channel enums, etc.) hand-written as two parallel dicts that drift.
Proposed API
from adcp.decisioning import create_upstream_http_client, create_translation_map
client = create_upstream_http_client(
base_url="https://api.vendor.com",
auth={"type": "static_bearer", "token": "..."}, # or dynamic_bearer | api_key | none
network_code="abc123",
default_headers={...},
timeout_s=30.0,
)
# Typed get/post/put/delete returning parsed JSON or None on 404.
account = await client.get("/accounts/{id}", params={...})
status_map = create_translation_map[AdcpStatus, UpstreamStatus]({
"active": "ACTIVE",
"paused": "PAUSED",
...
})
status_map.to_upstream("active") # "ACTIVE"
status_map.to_adcp("ACTIVE") # "active"
status_map.has_adcp("active") # True
status_map.has_upstream("ACTIVE") # True
Auth modes: static_bearer / dynamic_bearer (callable returning fresh token, used by OAuth passthrough in #6) / api_key / none.
Acceptance criteria
- Both helpers exported from
adcp.decisioning.
- Tests cover: each auth mode, 404→None, retry on 5xx, JSON decode errors.
- Translation map: round-trip identity, missing-key raises, generic typing.
examples/v3_reference_seller/src/upstream.py could be refactored to use them (defer that to a follow-up v3-ref-seller-uses-helpers PR).
Parent: #452
JS source
.changeset/adapter-translation-helpers.md(6.7).What Python adopters write today
200+ lines of
httpx.AsyncClientboilerplate per upstream — auth header injection, 404→None translation, retry/timeout policy, JSON decode. Seeexamples/v3_reference_seller/src/upstream.pyfor the canonical hand-rolled version.Plus per-adapter bidirectional code↔code translation maps (status enums, channel enums, etc.) hand-written as two parallel dicts that drift.
Proposed API
Auth modes:
static_bearer/dynamic_bearer(callable returning fresh token, used by OAuth passthrough in #6) /api_key/none.Acceptance criteria
adcp.decisioning.examples/v3_reference_seller/src/upstream.pycould be refactored to use them (defer that to a follow-upv3-ref-seller-uses-helpersPR).