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
Swap the package's HTTP client: `requests.Session` → `httpx.Client`,
`requests.Response` → `httpx.Response`. Same call patterns, same
response shape; only the underlying transport changes. Headers,
timeout, and redirect defaults are centralized in
`dataretrieval.utils.HTTPX_DEFAULTS` (`httpx.Timeout(60.0,
connect=10.0)`, `follow_redirects=True`).
The chunker, paginated-loop helpers, and OGC waterdata fetchers
route through one `httpx.Client` that the chunker publishes on the
`_chunked_client` ContextVar so paginated sub-requests reuse the
connection pool across a single chunked call.
Three httpx behavior diffs handled defensively:
* `httpx.InvalidURL` is raised client-side when a URL component
exceeds httpx's 64 KB cap. Caught by `_safe_request_bytes` (treats
"too big to construct" as "doesn't fit", so the planner's halving
loop keeps shrinking) AND by `_issue` / `_classify_chunk_error`
(treats a runtime InvalidURL as `ServiceInterrupted` so partial
state remains recoverable via `.call.resume()`). Note that
`httpx.InvalidURL` does NOT inherit from `httpx.HTTPError` — it
needs an explicit catch.
* `httpx.Response.elapsed` is only populated once the response is
closed; `pytest-httpx` mock responses don't populate it. The new
`_safe_elapsed` helper falls back to `timedelta(0)`.
* `httpx.Response.url` is a read-only property. The new
`_set_response_url` helper rewrites it by reseating the bound
request, with a fallback path for `Mock`-shaped test responses.
Tests migrate from `requests_mock` to native `pytest-httpx`. The
new `tests/conftest.py` is ~30 lines configuring pytest-httpx
strict-mode relaxations.
Backwards-compat:
* `BaseMetadata.header` is now `httpx.Headers` instead of
`requests.structures.CaseInsensitiveDict`. Case-insensitive
`.get(...)` still works; literal dict equality
(`md.header == {"k": "v"}`) no longer holds because
`httpx.Headers` carries auto-added entries.
* `BaseMetadata.url` is coerced to `str`.
* `RequestExceedsQuota` and `API_USGS_LIMIT` are removed — the
chunker no longer pre-empts on `x-ratelimit-remaining`. A natural
429 still surfaces as `QuotaExhausted` via `_classify_chunk_error`,
carrying partial state for `.call.resume()`.
* The CI flaky-rerun regex now matches `httpx.ConnectError` as well
as the legacy `ConnectionError` string.
Test count: 404 mocked tests passing, 2 skipped, ruff clean.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
0 commit comments