feat(core): typed serde, pagination, webhooks, tracing, and fixes#3
Merged
Conversation
Tristate carries three states (value / explicit null / absent) so PATCH-style payloads can round-trip an explicit null without conflating it with an omitted field. The codec is a small encode/decode layer over the existing Serde protocol for converting between typed models and wire bytes, standard-library only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Verifies inbound webhook payloads (id/timestamp/signature headers, HMAC-SHA256, constant-time comparison, replay-window check) and unwraps the verified JSON body. Pure standard library. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A sync and async paginator that iterate items or pages over a configured pipeline, with cursor/token, page-number, and RFC 5988 Link-header strategies. Fetching each page runs the full pipeline, so retry, auth, and tracing apply per page. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
An adapter-style HttpTracer whose per-event methods default to no-ops, carried on the instrumentation context. Trace and span ids are published to contextvars so the client logger can stamp them onto every record. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The idempotency policy stamps a key generated once per request and reused across retries onto write methods, so safe automatic retries don't double-apply a side effect. The client-identity policy sets a consistent User-Agent. Both are wired into the default pipeline. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…c retry Retry now honours X-RateLimit-Reset, defaults to full jitter, and caps a server Retry-After. The tracing and redirect policies emit tracer lifecycle events. The async retry policy never catches or retries CancelledError. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
On a mid-drain error the response body now retains the bytes read so far and re-raises, instead of silently caching an empty body; the one-time drain is guarded by a lock; and both loggable bodies gain a bounded snapshot that previews at most N bytes without copying more. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The SSE parser strips a leading byte-order mark. Async response and SSE cleanup runs to completion even when the awaiting task is cancelled, then re-raises CancelledError. A circular import between the errors package and the streaming module is broken by importing the error type directly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Digest credentials are encoded as UTF-8 only when the challenge advertises charset=UTF-8, and ISO-8859-1 otherwise, per RFC 7616. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Parameters split on the first '=' only, quoted values are unquoted and unescaped, parameter keys are lowercased while values keep their case, and an unknown charset degrades to None. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
HTTP errors carry a retryable flag the retry policy can read directly and a non-consuming body snapshot for previewing the error body without consuming it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Behavioural fixtures assert observable contracts (single-use bodies, replayability, header case-insensitivity, context eviction, pagination, webhook verification); snapshot tests pin serialized output; and an ast-based public-surface baseline fails on unintended API changes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The lockfile pinned a requests specifier that no longer matched the transport package's pyproject; re-sync corrects the drift. No dependency change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The retry policy minted its own HttpTracer from the factory instead of reusing the per-operation instance cached on the pipeline context, so attempt events landed on a different tracer than the operation-level events emitted by the tracing and redirect policies. It now resolves the shared tracer. An X-RateLimit-Reset wait was also jittered downward, which could wake the client before the window actually reset and earn another rate-limit response. The jitter is now upward-only, so a reconnect never fires before the reset instant. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
RFC 5988 permits a relative next/prev target. LinkHeaderStrategy parsed the target directly and raised on the missing scheme; it now resolves the target against the originating request URL before reissuing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The codec's bytes-encoding branch let a UnicodeDecodeError escape. It now wraps it in SerializationError to match the documented Raises contract. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
If a shielded cleanup coroutine raised an ordinary exception while an outer cancellation was pending, the cancellation was dropped in favour of the cleanup error. The cleanup helpers now re-raise the pending CancelledError once the cleanup completes, surfacing a cleanup failure only when no cancellation is pending. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a batch of optional building blocks to
dexpace-sdk-coreand fixes several correctness issues. Everything lands incore; the transport packages are unchanged. No public symbol was removed, so existing code keeps working unmodified.New capabilities
serde.tristate) — a three-way type distinguishing "a value", "explicit null", and "absent", so PATCH-style payloads can round-trip an explicitnullwithout conflating it with an omitted field.serde.codec) — a small encode/decode layer over the existingSerdeprotocol for moving between typed models and wire bytes, standard-library only.http.webhooks) — verifies inbound webhook payloads (HMAC-SHA256, constant-time comparison, replay-window check) and unwraps the verified body.pagination) — sync and async paginators that iterate items or pages over a configured pipeline, with cursor/token, page-number, and RFC 5988 Link-header strategies. Each page fetch runs the full pipeline, so retry, auth, and tracing apply per page.User-Agent. Both are wired into the default pipeline.Correctness fixes
CancelledError; a circular import between the errors package and the streaming module is broken.=splits, quoted/escaped values, key-only lowercasing, and unknown charsets.retryableflag and a non-consuming body snapshot.HttpTracer: attempt-level events (attempt_started/attempt_failed/attempt_retries_exhausted) and the operation/request/response lifecycle events land on the same tracer instance instead of separate ones.X-RateLimit-Resetwait is now jittered upward only, so a reconnect never wakes before the window resets — a downward jitter risked an immediate repeat 429.Retry-Afteris still respected and capped.SerializationErrorwhen asked to encode non-UTF-8bytes, rather than letting aUnicodeDecodeErrorescape.Tests and tooling
Adds behavioural conformance fixtures, serialization snapshot tests, and an ast-based public-API surface baseline that fails on unintended API changes.
Verification
ruff check,ruff format --check,mypy --strict(212 source files), and the fullpytestsuite (999 passing) are all green.