Skip to content

[python] isolate implicit API clients#24129

Open
tamird wants to merge 2 commits into
OpenAPITools:masterfrom
tamird:upstream/python-independent-implicit-clients
Open

[python] isolate implicit API clients#24129
tamird wants to merge 2 commits into
OpenAPITools:masterfrom
tamird:upstream/python-independent-implicit-clients

Conversation

@tamird

@tamird tamird commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Generated API instances currently share the cached default ApiClient
and its Configuration. Mutating credentials, headers, cookies, or
transport settings through one implicit API can therefore affect
another.

Add the default-off useIndependentImplicitClients option. Treat
isolation as one ownership contract rather than separate configuration
copy and client-cache switches: an API constructed without an explicit
or registered default client owns a private client and copied
configuration. Retain that owned client separately from the public
api_client attribute, so later reassignment neither transfers
ownership nor changes what close() releases. Explicit and registered
clients remain shared and caller-owned.

Make Configuration.set_default() copy configuration-owned containers
and make get_default_copy() return another copy. Keep process-global
logging resources and stateful transport extension objects shared, but
copy the containers around those objects. Copy proxy-header mappings
through their mapping protocol so mutable dictionaries and immutable
multidict proxies both produce independent defaults.

For aiohttp, preserve connector=None as an explicit request for
ClientSession's default connector. Non-None caller-supplied
connectors remain caller-owned.

Keep the option disabled by default because existing clients may rely on
mutating the shared defaults. Resolve operation IDs that conflict with
the generated lifecycle after operations are grouped, so HTTP-info,
streaming, serializer, and HTTPX-sync variants remain unique.

Closes #24124.

@tamird tamird force-pushed the upstream/python-independent-implicit-clients branch 7 times, most recently from 46d3f88 to 96d76aa Compare June 26, 2026 00:52
@tamird tamird marked this pull request as ready for review June 26, 2026 01:17
@tamird

tamird commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

The only red check is
CircleCI node2.
It failed before project tests while the C++ toolchain setup hit Chrome
apt key FD533C07C264648F and a Launchpad network error. All 40 GitHub
Actions checks passed.

@tomplus, could you review the configuration-copy, client-ownership, and
aiohttp lifetime contract?

@wing328, could you review the option and Python generator scope?

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 42 files

Note: This PR contains a large number of files. cubic only reviews up to 40 files per PR, so some files may not have been reviewed. cubic prioritizes the most important files to review.
On a pro plan you can use ultrareview for larger PRs.

Re-trigger cubic

@tamird tamird force-pushed the upstream/python-independent-implicit-clients branch from 96d76aa to 6a61da5 Compare June 26, 2026 11:52
@tamird

tamird commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

The proxy_headers finding was valid. The old exception preserved
the identity of mutable dictionaries while avoiding
CIMultiDictProxy's unsupported generic deepcopy. The branch now uses
the mapping copy() protocol instead. Regression coverage mutates the
original multidict backing store and the stored default independently,
then proves the later copy sees neither mutation.

The connector=None finding does not describe a regression.
client_session_kwargs is an explicit ClientSession override, and
master already applies it after constructing the generated connector.
An explicit None therefore selects aiohttp's default connector and
intentionally bypasses generated SSL and pool settings. aiohttp creates
that connector, so the session must own it. The key-presence check
preserves that contract without constructing a connector only to discard
it:
https://github.com/aio-libs/aiohttp/blob/v3.8.4/aiohttp/client.py#L238-L257

I added an inline explanation of that distinction.

tamird added 2 commits June 26, 2026 07:56
Generated API instances currently share the cached default ApiClient and
its Configuration. Mutating credentials, headers, cookies, or transport
settings through one implicit API can therefore affect another.

Add the default-off useIndependentImplicitClients option. Treat
isolation as one ownership contract rather than separate configuration
copy and client-cache switches: an API constructed without an explicit
or registered default client owns a private client and copied
configuration. Its close method and context manager release that client.
Explicit and registered clients remain shared and caller-owned.

Make Configuration.set_default() copy configuration-owned containers
and make get_default_copy() return another copy. Keep process-global
logging resources and event-loop-bound transport objects shared, but
copy the containers around those objects. Copy proxy-header mappings
through their mapping protocol so mutable dictionaries and immutable
multidict proxies both produce independent defaults.

For aiohttp, preserve connector=None as an explicit request for
ClientSession's default connector. Non-None caller-supplied connectors
remain caller-owned.

Keep the option disabled by default because existing clients may rely on
mutating the shared defaults. Rename normalized operation IDs that would
overwrite lifecycle methods only when the corresponding lifecycle is
generated.

Closes OpenAPITools#24124
Regenerate the aiohttp and lazy-import Python clients with copied
defaults and independent implicit clients.
@tamird tamird force-pushed the upstream/python-independent-implicit-clients branch from 6a61da5 to c059690 Compare June 26, 2026 11:58
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.

[REQ][python] isolate implicit API clients

1 participant