Internalize http client management, add context manager support #15

Merged
coding-agent-marvin8 merged 0 commits from refs/pull/15/head into main 2026-06-08 21:43:13 +00:00
coding-agent-marvin8 commented 2026-06-08 03:35:51 +00:00 (Migrated from codeberg.org)

Removes httpx.AsyncClient from the public API. APClient now creates and owns its own client internally.

Changes:

  • Remove client param from APClient.init and APClient.create()
  • Remove client param from create_app(), validate_authorization_code(), get_auth_token()
  • Add http2: bool = False param (opt-in, matching httpx default)
  • Add close(), aenter, aexit for optional context manager usage
  • Update all tests to remove inline AsyncClient construction
  • Update all docs with new patterns and v2.0.0 migration guide
  • Add v1.x maintenance branch

Closes #6
Closes #14

Removes httpx.AsyncClient from the public API. APClient now creates and owns its own client internally. Changes: - Remove client param from APClient.__init__ and APClient.create() - Remove client param from create_app(), validate_authorization_code(), get_auth_token() - Add http2: bool = False param (opt-in, matching httpx default) - Add close(), __aenter__, __aexit__ for optional context manager usage - Update all tests to remove inline AsyncClient construction - Update all docs with new patterns and v2.0.0 migration guide - Add v1.x maintenance branch Closes #6 Closes #14
coding-agent-marvin8 commented 2026-06-08 03:51:54 +00:00 (Migrated from codeberg.org)

Also replacing httpx with httpx2

As part of this branch we are also migrating from httpx to httpx2 (https://httpx2.pydantic.dev) — Pydantic's actively maintained fork of httpx. This resolves the zstd dependency that currently blocks Python 3.15 testing (see #6).

What httpx2 is

httpx2 is a drop-in replacement for httpx at the API level: same class names (AsyncClient, HTTPError, Response, etc.), same exceptions, same request/response interface. The migration is transparent to longwei consumers — nothing changes in the public API.

What the migration involved

Source files (8 files): Mechanical import swap — from httpx import Xfrom httpx2 import X. No logic changes.

Test infrastructure (all ~50 test files): This was the significant part. pytest-httpx patches httpcore at the transport level. httpx2 uses httpcore2 (a separate package), so pytest-httpx cannot intercept httpx2 requests. The replacement is pytest-httpx2, which provides a httpx2_mock fixture backed by respx. The respx API is completely different from the pytest-httpx HTTPXMock API:

pytest-httpx (old) pytest-httpx2 / respx (new)
httpx_mock.add_response(json=X, headers=Y) httpx2_mock.route().respond(json=X, headers=Y)
httpx_mock.add_response(status_code=N) httpx2_mock.route().respond(N)
httpx_mock.add_exception(HTTPError(...)) httpx2_mock.route().mock(side_effect=HTTPError(...))
httpx_mock.get_request() httpx2_mock.calls.last.request
httpx_mock.get_requests()[0] httpx2_mock.calls[0].request
@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) removed (respx default)
URL-filtered: add_response(url="...", ...) httpx2_mock.get("...").respond(...)

All test files were converted systematically using this mapping.

## Also replacing httpx with httpx2 As part of this branch we are also migrating from httpx to httpx2 (https://httpx2.pydantic.dev) — Pydantic's actively maintained fork of httpx. This resolves the zstd dependency that currently blocks Python 3.15 testing (see #6). ### What httpx2 is httpx2 is a drop-in replacement for httpx at the API level: same class names (`AsyncClient`, `HTTPError`, `Response`, etc.), same exceptions, same request/response interface. The migration is transparent to longwei consumers — nothing changes in the public API. ### What the migration involved **Source files (8 files):** Mechanical import swap — `from httpx import X` → `from httpx2 import X`. No logic changes. **Test infrastructure (all ~50 test files):** This was the significant part. `pytest-httpx` patches `httpcore` at the transport level. httpx2 uses `httpcore2` (a separate package), so `pytest-httpx` cannot intercept httpx2 requests. The replacement is `pytest-httpx2`, which provides a `httpx2_mock` fixture backed by `respx`. The respx API is completely different from the pytest-httpx `HTTPXMock` API: | pytest-httpx (old) | pytest-httpx2 / respx (new) | |---|---| | `httpx_mock.add_response(json=X, headers=Y)` | `httpx2_mock.route().respond(json=X, headers=Y)` | | `httpx_mock.add_response(status_code=N)` | `httpx2_mock.route().respond(N)` | | `httpx_mock.add_exception(HTTPError(...))` | `httpx2_mock.route().mock(side_effect=HTTPError(...))` | | `httpx_mock.get_request()` | `httpx2_mock.calls.last.request` | | `httpx_mock.get_requests()[0]` | `httpx2_mock.calls[0].request` | | `@pytest.mark.httpx_mock(assert_all_responses_were_requested=False)` | removed (respx default) | | URL-filtered: `add_response(url="...", ...)` | `httpx2_mock.get("...").respond(...)` | All test files were converted systematically using this mapping.
coding-agent-marvin8 commented 2026-06-08 04:19:56 +00:00 (Migrated from codeberg.org)

Python 3.15 beta testing

The pytest_betas nox session (which runs the test suite against Python 3.15 and 3.15t) currently fails because pydantic-core 2.41.5 depends on pyo3 0.26.0, which declares Python 3.14 as its maximum supported version.

The failure is not a Rust tooling problem — even with Rust installed, the build aborts with:

error: the configured Python interpreter version (3.15) is newer than PyO3's maximum supported version (3.14)

This is a pydantic-side issue. Once pydantic-core ships a release built against pyo3 ≥ 0.27 (which will add 3.15 support), pre-built wheels will appear on PyPI and the failure will resolve automatically — no changes needed on our end.

The CI pipeline has been updated in this branch to run nox -s pytest_betas as a separate step with failure: ignore, so it runs and reports results without blocking the build.

## Python 3.15 beta testing The `pytest_betas` nox session (which runs the test suite against Python 3.15 and 3.15t) currently fails because `pydantic-core 2.41.5` depends on `pyo3 0.26.0`, which declares Python 3.14 as its maximum supported version. The failure is not a Rust tooling problem — even with Rust installed, the build aborts with: ``` error: the configured Python interpreter version (3.15) is newer than PyO3's maximum supported version (3.14) ``` This is a pydantic-side issue. Once pydantic-core ships a release built against pyo3 ≥ 0.27 (which will add 3.15 support), pre-built wheels will appear on PyPI and the failure will resolve automatically — no changes needed on our end. The CI pipeline has been updated in this branch to run `nox -s pytest_betas` as a separate step with `failure: ignore`, so it runs and reports results without blocking the build.
Sign in to join this conversation.
No description provided.