from __future__ import annotations import sys import typing # asyncio.iscoroutinefunction is deprecated in Python 3.14 and will be removed in 3.16. # Use inspect.iscoroutinefunction for Python 3.14+ and asyncio.iscoroutinefunction for earlier. # Note: There are subtle behavioral differences between the two functions, but for # the use cases in niquests (checking if callbacks/hooks are async), both should work. if sys.version_info >= (3, 14): import inspect iscoroutinefunction = inspect.iscoroutinefunction else: import asyncio iscoroutinefunction = asyncio.iscoroutinefunction try: from urllib3 import __version__ HAS_LEGACY_URLLIB3: bool = int(__version__.split(".")[-1]) < 900 except (ValueError, ImportError): # Defensive: tested in separate CI # Means one of the two cases: # 1) urllib3 does not exist -> fallback to urllib3_future # 2) urllib3 exist but not fork -> fallback to urllib3_future HAS_LEGACY_URLLIB3 = True if HAS_LEGACY_URLLIB3: # Defensive: tested in separate CI import urllib3_future else: urllib3_future = None # type: ignore[assignment] try: import urllib3 # force detect broken or dummy urllib3 package urllib3.Timeout # noqa urllib3.Retry # noqa urllib3.__version__ # noqa except (ImportError, AttributeError): # Defensive: tested in separate CI urllib3 = None # type: ignore[assignment] if (urllib3 is None and urllib3_future is None) or (HAS_LEGACY_URLLIB3 and urllib3_future is None): raise RuntimeError( # Defensive: tested in separate CI "This is awkward but your environment is missing urllib3-future. " "Your environment seems broken. " "You may fix this issue by running `python -m pip install niquests -U` " "to force reinstall its dependencies." ) if urllib3 is not None: T = typing.TypeVar("T", urllib3.Timeout, urllib3.Retry) else: # Defensive: tested in separate CI T = typing.TypeVar("T", urllib3_future.Timeout, urllib3_future.Retry) # type: ignore def urllib3_ensure_type(o: T) -> T: """Retry, Timeout must be the one in urllib3_future.""" if urllib3 is None: return o if HAS_LEGACY_URLLIB3: # Defensive: tested in separate CI if "urllib3_future" not in str(type(o)): assert urllib3_future is not None if isinstance(o, urllib3.Timeout): return urllib3_future.Timeout( # type: ignore[return-value] o.total, # type: ignore[arg-type] o.connect_timeout, # type: ignore[arg-type] o.read_timeout, # type: ignore[arg-type] ) if isinstance(o, urllib3.Retry): return urllib3_future.Retry( # type: ignore[return-value] o.total, o.connect, o.read, redirect=o.redirect, status=o.status, other=o.other, allowed_methods=o.allowed_methods, status_forcelist=o.status_forcelist, backoff_factor=o.backoff_factor, backoff_max=o.backoff_max, raise_on_redirect=o.raise_on_redirect, raise_on_status=o.raise_on_status, history=o.history, # type: ignore[arg-type] respect_retry_after_header=o.respect_retry_after_header, remove_headers_on_redirect=o.remove_headers_on_redirect, backoff_jitter=o.backoff_jitter, ) return o