1818
1919import functools
2020import http .client as http_client
21+ import importlib .util
2122import logging
2223import numbers
2324import time
24- from typing import Optional
25-
26- try :
27- import requests
28- except ImportError as caught_exc : # pragma: NO COVER
25+ from typing import Optional , Set , TYPE_CHECKING
26+
27+ # PEP 0810: Explicit Lazy Imports
28+ # Python 3.15+ natively intercepts and defers these imports.
29+ # Developers can disable this behavior and force eager imports.
30+ # For more information, see:
31+ # https://docs.python.org/3.15/library/sys.html#sys.set_lazy_imports_filter
32+ # Older Python versions safely ignore this variable.
33+ __lazy_modules__ : Set [str ] = {
34+ "requests" ,
35+ "requests.adapters" ,
36+ "requests.exceptions" ,
37+ "requests.packages" ,
38+ "requests.packages.urllib3" ,
39+ "requests.packages.urllib3.util" ,
40+ "requests.packages.urllib3.util.ssl_" ,
41+ }
42+
43+
44+ if importlib .util .find_spec ("requests" ) is None :
2945 raise ImportError (
30- "The requests library is not installed from please install the requests package to use the requests transport."
31- ) from caught_exc
46+ "The requests library is not installed, please install the requests package to use the requests transport."
47+ )
48+
49+ import requests
3250import requests .adapters # pylint: disable=ungrouped-imports
3351import requests .exceptions # pylint: disable=ungrouped-imports
34- from requests .packages .urllib3 .util .ssl_ import ( # type: ignore
35- create_urllib3_context ,
36- ) # pylint: disable=ungrouped-imports
3752
38- from google .auth import _helpers
39- from google .auth import exceptions
40- from google .auth import transport
53+
54+ from google .auth import _helpers , exceptions , transport
4155from google .auth .transport import _mtls_helper
4256import google .auth .transport ._mtls_helper
4357from google .oauth2 import service_account
4458
59+ if TYPE_CHECKING :
60+ _HTTPAdapterBase = requests .adapters .HTTPAdapter
61+ _SessionBase = requests .Session
62+ else :
63+ _HTTPAdapterBase = _helpers .HeapDummy
64+ _SessionBase = _helpers .HeapDummy
65+
66+
67+ class _LazyBasesMeta (_helpers .LazyBasesMeta ):
68+ def _perform_resolve_bases (cls ):
69+ current_bases = type .__getattribute__ (cls , "__bases__" )
70+ if current_bases == (_helpers .HeapDummy ,):
71+ cls_name = type .__getattribute__ (cls , "__name__" )
72+ if cls_name in ("_MutualTlsAdapter" , "_MutualTlsOffloadAdapter" ):
73+ cls .__bases__ = (requests .adapters .HTTPAdapter ,)
74+ elif cls_name == "AuthorizedSession" :
75+ cls .__bases__ = (requests .Session ,)
76+
77+
4578_LOGGER = logging .getLogger (__name__ )
4679
4780_DEFAULT_TIMEOUT = 120 # in seconds
@@ -84,9 +117,11 @@ class TimeoutGuard(object):
84117 :class:`requests.exceptions.Timeout`.
85118 """
86119
87- def __init__ (self , timeout , timeout_error_type = requests . exceptions . Timeout ):
120+ def __init__ (self , timeout , timeout_error_type = None ):
88121 self ._timeout = timeout
89122 self .remaining_timeout = timeout
123+ if timeout_error_type is None :
124+ timeout_error_type = requests .exceptions .Timeout
90125 self ._timeout_error_type = timeout_error_type
91126
92127 def __enter__ (self ):
@@ -161,7 +196,7 @@ def __call__(
161196 body = None ,
162197 headers = None ,
163198 timeout = _DEFAULT_TIMEOUT ,
164- ** kwargs
199+ ** kwargs ,
165200 ):
166201 """Make an HTTP request using requests.
167202
@@ -195,7 +230,7 @@ def __call__(
195230 raise new_exc from caught_exc
196231
197232
198- class _MutualTlsAdapter (requests . adapters . HTTPAdapter ):
233+ class _MutualTlsAdapter (_HTTPAdapterBase , metaclass = _LazyBasesMeta ):
199234 """
200235 A TransportAdapter that enables mutual TLS.
201236
@@ -209,9 +244,13 @@ class _MutualTlsAdapter(requests.adapters.HTTPAdapter):
209244 """
210245
211246 def __init__ (self , cert , key ):
212- import certifi
213247 import ssl
214248
249+ from google .auth .transport .requests import (
250+ create_urllib3_context ,
251+ )
252+ import certifi
253+
215254 ctx_poolmanager = create_urllib3_context ()
216255 ctx_poolmanager .load_verify_locations (cafile = certifi .where ())
217256
@@ -261,7 +300,7 @@ def proxy_manager_for(self, *args, **kwargs):
261300 return super (_MutualTlsAdapter , self ).proxy_manager_for (* args , ** kwargs )
262301
263302
264- class _MutualTlsOffloadAdapter (requests . adapters . HTTPAdapter ):
303+ class _MutualTlsOffloadAdapter (_HTTPAdapterBase , metaclass = _LazyBasesMeta ):
265304 """
266305 A TransportAdapter that enables mutual TLS and offloads the client side
267306 signing operation to the signing library.
@@ -284,7 +323,11 @@ class _MutualTlsOffloadAdapter(requests.adapters.HTTPAdapter):
284323 """
285324
286325 def __init__ (self , enterprise_cert_file_path ):
326+ from google .auth .transport .requests import (
327+ create_urllib3_context ,
328+ )
287329 import certifi
330+
288331 from google .auth .transport import _custom_tls_signer
289332
290333 self .signer = _custom_tls_signer .CustomTlsSigner (enterprise_cert_file_path )
@@ -311,7 +354,7 @@ def proxy_manager_for(self, *args, **kwargs):
311354 return super (_MutualTlsOffloadAdapter , self ).proxy_manager_for (* args , ** kwargs )
312355
313356
314- class AuthorizedSession (requests . Session ):
357+ class AuthorizedSession (_SessionBase , metaclass = _LazyBasesMeta ):
315358 """A Requests Session class with credentials.
316359
317360 This class is used to perform requests to API endpoints that require
@@ -504,7 +547,7 @@ def request(
504547 headers = None ,
505548 max_allowed_time = None ,
506549 timeout = _DEFAULT_TIMEOUT ,
507- ** kwargs
550+ ** kwargs ,
508551 ):
509552 """Implementation of Requests' request.
510553
@@ -566,7 +609,7 @@ def request(
566609 data = data ,
567610 headers = request_headers ,
568611 timeout = timeout ,
569- ** kwargs
612+ ** kwargs ,
570613 )
571614 remaining_time = guard .remaining_timeout
572615
@@ -638,7 +681,7 @@ def request(
638681 max_allowed_time = remaining_time ,
639682 timeout = timeout ,
640683 _credential_refresh_attempt = _credential_refresh_attempt + 1 ,
641- ** kwargs
684+ ** kwargs ,
642685 )
643686
644687 return response
@@ -652,3 +695,13 @@ def close(self):
652695 if self ._auth_request_session is not None :
653696 self ._auth_request_session .close ()
654697 super (AuthorizedSession , self ).close ()
698+
699+
700+ def __getattr__ (name ):
701+ if name == "create_urllib3_context" :
702+ from requests .packages .urllib3 .util .ssl_ import ( # type: ignore
703+ create_urllib3_context ,
704+ )
705+
706+ return create_urllib3_context
707+ raise AttributeError (f"module { __name__ } has no attribute { name } " )
0 commit comments