Skip to content

Commit 6644cbd

Browse files
committed
feat: add schema registry helpers to Python SDK
Expose schema upsert/get client methods with tests and quickstart coverage so Track C parity includes the schemas family in GA clients. Made-with: Cursor
1 parent b68f483 commit 6644cbd

3 files changed

Lines changed: 95 additions & 0 deletions

File tree

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,17 @@ with AxmeClient(config) as client:
8181
idempotency_key="media-finalize-001",
8282
)
8383
print(finalized["status"])
84+
schema = client.upsert_schema(
85+
{
86+
"semantic_type": "axme.calendar.schedule.v1",
87+
"schema_json": {"type": "object", "required": ["date"], "properties": {"date": {"type": "string"}}},
88+
"compatibility_mode": "strict",
89+
},
90+
idempotency_key="schema-upsert-001",
91+
)
92+
print(schema["schema"]["schema_hash"])
93+
schema_get = client.get_schema("axme.calendar.schedule.v1")
94+
print(schema_get["schema"]["semantic_type"])
8495
subscription = client.upsert_webhook_subscription(
8596
{
8697
"callback_url": "https://integrator.example/webhooks/axme",

axme_sdk/client.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,25 @@ def finalize_media_upload(
233233
retryable=idempotency_key is not None,
234234
)
235235

236+
def upsert_schema(
237+
self,
238+
payload: dict[str, Any],
239+
*,
240+
idempotency_key: str | None = None,
241+
trace_id: str | None = None,
242+
) -> dict[str, Any]:
243+
return self._request_json(
244+
"POST",
245+
"/v1/schemas",
246+
json_body=payload,
247+
idempotency_key=idempotency_key,
248+
trace_id=trace_id,
249+
retryable=idempotency_key is not None,
250+
)
251+
252+
def get_schema(self, semantic_type: str, *, trace_id: str | None = None) -> dict[str, Any]:
253+
return self._request_json("GET", f"/v1/schemas/{semantic_type}", trace_id=trace_id, retryable=True)
254+
236255
def upsert_webhook_subscription(
237256
self,
238257
payload: dict[str, Any],

tests/test_client.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,71 @@ def handler(request: httpx.Request) -> httpx.Response:
461461
assert client.finalize_media_upload(payload, idempotency_key="media-finalize-1")["status"] == "ready"
462462

463463

464+
def test_upsert_schema_success() -> None:
465+
semantic_type = "axme.calendar.schedule.v1"
466+
payload = {
467+
"semantic_type": semantic_type,
468+
"schema_json": {"type": "object", "required": ["date"], "properties": {"date": {"type": "string"}}},
469+
"compatibility_mode": "strict",
470+
}
471+
472+
def handler(request: httpx.Request) -> httpx.Response:
473+
assert request.method == "POST"
474+
assert request.url.path == "/v1/schemas"
475+
assert request.headers["idempotency-key"] == "schema-upsert-1"
476+
body = json.loads(request.read().decode("utf-8"))
477+
assert body == payload
478+
return httpx.Response(
479+
200,
480+
json={
481+
"ok": True,
482+
"schema": {
483+
"semantic_type": semantic_type,
484+
"schema_ref": f"schema://{semantic_type}",
485+
"schema_hash": "a" * 64,
486+
"compatibility_mode": "strict",
487+
"scope": "tenant",
488+
"owner_agent": "agent://owner",
489+
"active": True,
490+
"created_at": "2026-02-28T00:00:00Z",
491+
"updated_at": "2026-02-28T00:00:01Z",
492+
},
493+
},
494+
)
495+
496+
client = _client(handler)
497+
assert client.upsert_schema(payload, idempotency_key="schema-upsert-1")["schema"]["semantic_type"] == semantic_type
498+
499+
500+
def test_get_schema_success() -> None:
501+
semantic_type = "axme.calendar.schedule.v1"
502+
503+
def handler(request: httpx.Request) -> httpx.Response:
504+
assert request.method == "GET"
505+
assert request.url.path == f"/v1/schemas/{semantic_type}"
506+
return httpx.Response(
507+
200,
508+
json={
509+
"ok": True,
510+
"schema": {
511+
"semantic_type": semantic_type,
512+
"schema_ref": f"schema://{semantic_type}",
513+
"schema_hash": "b" * 64,
514+
"compatibility_mode": "strict",
515+
"scope": "tenant",
516+
"owner_agent": "agent://owner",
517+
"active": True,
518+
"schema_json": {"type": "object", "properties": {"date": {"type": "string"}}},
519+
"created_at": "2026-02-28T00:00:00Z",
520+
"updated_at": "2026-02-28T00:00:01Z",
521+
},
522+
},
523+
)
524+
525+
client = _client(handler)
526+
assert client.get_schema(semantic_type)["schema"]["semantic_type"] == semantic_type
527+
528+
464529
@pytest.mark.parametrize(
465530
("status_code", "expected_exception"),
466531
[

0 commit comments

Comments
 (0)