You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
polish(transport): make Sync/AsyncTransport.close() explicitly idempotent + test parity with KalshiAuth #301
SyncTransport.close() (kalshi/_base_client.py:362-363) and AsyncTransport.aclose() (:550-551) delegate straight to self._client.close() / aclose() with no _closed flag and no test asserting idempotence. The rest of the SDK's lifecycle layer (KalshiAuth, KalshiClient, AsyncKalshiClient) tracks _closed explicitly — #267 even added a re-check-under-lock guard on the sign executor. The transport is the odd one out.
Today this is benign because httpx.Client.close() is itself idempotent, but:
The contract is implicit — a future httpx change (or a custom httpx.BaseTransport injected via KalshiClient(transport=...)) could break it.
The SDK already tests triple-close on KalshiAuth (tests/test_auth.py:290-296) but only single-close on the transport (tests/test_client.py:451, tests/test_async_client.py:284-285). The asymmetry leaves a regression hole.
Suggested fix
Add a _closed: bool = False to both transport __init__, return early from close() / aclose() if already closed, and document the contract:
classSyncTransport:
def__init__(self, ...) ->None:
...
self._closed=Falsedefclose(self) ->None:
"""Idempotent. Safe to call multiple times — subsequent calls no-op."""ifself._closed:
returnself._closed=Trueself._client.close()
Mirror on AsyncTransport. Optionally raise RuntimeError from request() if _closed is True so a use-after-close fails loudly instead of dispatching against a closed httpx pool.
Post-v2.5 multi-reviewer audit (HTTP transport + Testing surfaces). Polish-grade; brings the transport's lifecycle contract in line with the rest of the SDK.
Activity
release: 2.6.0 — post-v2.5 independent reviewer SDK audit closure (#295-