Skip to content

feat: async client pilot (httpx) for cex.candle + cex.ticker (#142)#149

Merged
martinkersner merged 1 commit into
mainfrom
feat/async-client-pilot
Jul 3, 2026
Merged

feat: async client pilot (httpx) for cex.candle + cex.ticker (#142)#149
martinkersner merged 1 commit into
mainfrom
feat/async-client-pilot

Conversation

@martinkersner

Copy link
Copy Markdown
Member

Closes #142

Async client pilot — the scoped approach we agreed on (candle + ticker first, httpx as an optional extra), not the full mirror.

What's added

datamaxi.aio.AsyncDatamaxi (httpx-based):

from datamaxi.aio import AsyncDatamaxi

async with AsyncDatamaxi(api_key="...") as client:
    df = await client.cex.candle(exchange="binance", market="spot", symbol="BTC-USDT")
    t  = await client.cex.ticker.get(exchange="binance", market="spot", symbol="BTC-USDT")
  • AsyncAPI transport: async context manager (aclose), bounded retry of transient 5xx, ClientError/ServerError parity, last_response metadata — mirrors the sync client.
  • Pilot surface: cex.candle + cex.ticker.get (same validation + DataFrame/pandas=False behavior as sync).

No sync/async drift

Extracted the shared request core into datamaxi/_dispatch.pyresolve_endpoint (op_id → method/url/query), raise_for_error, extract_limit_usage — and made the sync API delegate to them. Behavior-preserving: the full sync suite stays green. Both clients now build requests and raise errors through the exact same code.

httpx = optional extra

  • pip install "datamaxi[async]" (added to [project.optional-dependencies]).
  • Importing the sync client never loads httpx (verified); using the async client without it raises a clear pip install 'datamaxi[async]' hint.
  • Query params are str()-encoded so bools serialize as "True" (matching the sync urlencode output), not httpx's "true".

Tests

  • New tests/test_async.py (7) via httpx.MockTransport (no network/extra deps, importorskip guard): candle→DataFrame, pandas=False→envelope, bool-param encoding, last_response, ClientError on 4xx, retry 503,503,200, and validation-before-request. httpx added to requirements-test.txt so CI runs them.
  • pytest -m "not integration": 162 passed, 11 skipped (155 + 7).
  • black + flake8 clean; sync import datamaxi doesn't pull httpx.

Scope / next steps

Deliberately small. Expanding to the full resource tree (~17 classes / ~50 methods) is the follow-on if the pattern lands well — each endpoint's async method is a thin duplicate of its sync validation/shaping over the shared transport. Same hand-maintenance/drift caveat as the typed models applies.

Known failures

None.

Closes #142

Add datamaxi.aio.AsyncDatamaxi (optional 'async' extra, httpx). Pilot scope:
cex.candle + cex.ticker, async context manager, bounded retry of transient
5xx, ClientError/ServerError parity, and last_response.

To avoid sync/async drift, extract endpoint resolution + error handling into
datamaxi._dispatch (resolve_endpoint, raise_for_error, extract_limit_usage)
and have the sync API delegate to them (behavior-preserving; full sync suite
still green).

httpx is an optional dependency (datamaxi[async]); importing the sync client
never loads it, and using the async client without it raises a clear install
hint. Query params are str()-encoded so bools match the sync urlencode output
('True', not httpx's 'true').
@martinkersner martinkersner merged commit 1313f4f into main Jul 3, 2026
5 checks passed
@martinkersner martinkersner deleted the feat/async-client-pilot branch July 3, 2026 08:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Async client variant (httpx) for concurrent market-data fetches

1 participant