11import os
2+ import weakref
23from collections .abc import Callable
34from typing import ClassVar
45from urllib .request import getproxies
@@ -69,7 +70,9 @@ class Client:
6970
7071 _api_client_cached : ClassVar [_AuthenticatedApi | None ] = None
7172 _api_client_uncached : ClassVar [_AuthenticatedApi | None ] = None
72- _api_client_external : ClassVar [dict [int , _AuthenticatedApi ]] = {}
73+ _api_client_external : ClassVar [weakref .WeakKeyDictionary [Callable [[], str ], _AuthenticatedApi ]] = (
74+ weakref .WeakKeyDictionary ()
75+ )
7376
7477 _api : _AuthenticatedApi
7578 applications : Applications
@@ -81,24 +84,14 @@ def __init__(self, cache_token: bool = True, token_provider: Callable[[], str] |
8184
8285 Args:
8386 cache_token: If True, caches the authentication token. Defaults to True.
87+ Ignored when ``token_provider`` is supplied.
8488 token_provider: Optional external token provider callable. When provided,
8589 bypasses internal OAuth authentication entirely. The callable must
86- return a valid bearer token string.
87-
88- Raises:
89- ValueError: If both ``token_provider`` and ``cache_token=False`` are specified,
90- since token caching is irrelevant when using an external provider.
90+ return a valid bearer token string. When set, ``cache_token`` has no
91+ effect because the external provider manages its own token lifecycle.
9192
9293 Sets up resource accessors for applications, versions, and runs.
9394 """
94- if token_provider is not None and not cache_token :
95- msg = (
96- "Cannot set cache_token=False with an external token_provider. "
97- "Token caching is managed internally when using the default OAuth flow. "
98- "When providing an external token_provider, omit cache_token or use the default."
99- )
100- raise ValueError (msg )
101-
10295 try :
10396 logger .trace ("Initializing client with cache_token={}, token_provider={}" , cache_token , token_provider )
10497 self ._api = Client .get_api_client (cache_token = cache_token , token_provider = token_provider )
@@ -260,7 +253,7 @@ def get_api_client(cache_token: bool = True, token_provider: Callable[[], str] |
260253
261254 API client instances are shared across all Client instances for efficient connection reuse.
262255 Three pools are maintained: cached-token, uncached-token, and external-provider (keyed by
263- provider identity).
256+ provider identity via a WeakKeyDictionary — entries are evicted when the provider is GC'd ).
264257
265258 Args:
266259 cache_token: If True, caches the authentication token. Defaults to True.
@@ -275,9 +268,8 @@ def get_api_client(cache_token: bool = True, token_provider: Callable[[], str] |
275268 """
276269 # Check singleton caches first
277270 if token_provider is not None :
278- provider_key = id (token_provider )
279- if provider_key in Client ._api_client_external :
280- return Client ._api_client_external [provider_key ]
271+ if token_provider in Client ._api_client_external :
272+ return Client ._api_client_external [token_provider ]
281273 elif cache_token and Client ._api_client_cached is not None :
282274 return Client ._api_client_cached
283275 elif not cache_token and Client ._api_client_uncached is not None :
@@ -300,7 +292,7 @@ def get_api_client(cache_token: bool = True, token_provider: Callable[[], str] |
300292
301293 # Store in the appropriate singleton cache
302294 if token_provider is not None :
303- Client ._api_client_external [provider_key ] = api_client
295+ Client ._api_client_external [token_provider ] = api_client
304296 elif cache_token :
305297 Client ._api_client_cached = api_client
306298 else :
0 commit comments