feat: accept injected httpx2 clients#2747
Draft
dsfaccini wants to merge 2 commits into
Draft
Conversation
httpx2 (https://github.com/pydantic/httpx2) is a drop-in fork of httpx under a separate import namespace, so httpx2 classes fail isinstance(x, httpx.*) and are rejected by HttpOptions. Behind a guarded `import httpx2`: - errors.py / _api_client.py: consolidate the duplicated httpx response checks into widened tuples and swap the runtime isinstance sites for response, headers, and the transient-exception retry predicate. - types.py (generated): widen the HttpxClient / HttpxAsyncClient aliases so HttpOptions(httpx_async_client=...) accepts an httpx2 client instead of raising ValidationError. Add a test guarded by pytest.importorskip("httpx2") and declare httpx2 as a test dependency (py3.10+).
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
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.
Draft / RFC — not for direct merge. A minimal, duck-typed demonstration to help move #2680 forward. This repo mirrors an internal source of truth via Copybara and doesn't merge external PRs directly, so the value here is making the change concrete, not landing it.
httpx2is Pydantic's actively-maintained, API-compatible fork ofhttpx. Because it lives in a separate import namespace,httpx2.*classes failisinstance(x, httpx.*). Handing the SDK an httpx2 client viaHttpOptions(httpx_async_client=...)hits two walls today:HttpOptions.httpx_async_client/httpx_clientare typed via theHttpxClient/HttpxAsyncClientaliases in generatedgoogle/genai/types.py; witharbitrary_types_allowed=True, Pydantic emits anis_instance_of(httpx.AsyncClient)check, so an httpx2 client raisesValidationError.isinstance(x, httpx.Response/Headers)checks and the retry-exception tuple inerrors.py/_api_client.pydon't recognize httpx2 objects. The async success path is the worst case: itsstatus_code == 200early-return is nested insideisinstance(response, httpx.Response), so every async httpx2 response falls through to "Unsupported response type".Behind a guarded
import httpx2(a no-op when httpx2 isn't installed), this widens the runtime checks:errors.pyraise_for_response+raise_for_async_response;_api_client.pyHttpResponse.__init__headers check,_iter_response_stream+_aiter_response_stream(validity guard + iterator selection), and theretry_argsretry predicate — each via one widened tuple per concept.types.pywidens theHttpxClient/HttpxAsyncClientaliases toUnion[httpx.*, httpx2.*]. This file is generated ("DO NOT EDIT"), so the real Wall 1 fix must happen in the generator template; it's included here only so the demonstration runs end-to-end.Adds a test (guarded by
pytest.importorskip("httpx2")) covering both walls with realhttpx2objects, and declareshttpx2as a test dependency (py3.10+, which required bumping theanyio/idnapins it needs).Scope / known limitation: this covers the
models.generate_content(_stream)path (sync + async, streaming + non-streaming). The injected client is also forwarded into the experimentalclient.agents/interactions/webhooks/triggerssurfaces (the_gaossub-SDK), which still couple tohttpxand are not handled here — that's a separate, larger generated-code change. Deliberately does not touch the default-client base classes or the client-arg filter.