Spaces:
Running
Running
""" | |
Python HTTP library with thread-safe connection pooling, file post support, user friendly, and more | |
""" | |
from __future__ import annotations | |
# Set default logging handler to avoid "No handler found" warnings. | |
import logging | |
import sys | |
import typing | |
import warnings | |
from logging import NullHandler | |
from . import exceptions | |
from ._base_connection import _TYPE_BODY | |
from ._collections import HTTPHeaderDict | |
from ._version import __version__ | |
from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, connection_from_url | |
from .filepost import _TYPE_FIELDS, encode_multipart_formdata | |
from .poolmanager import PoolManager, ProxyManager, proxy_from_url | |
from .response import BaseHTTPResponse, HTTPResponse | |
from .util.request import make_headers | |
from .util.retry import Retry | |
from .util.timeout import Timeout | |
# Ensure that Python is compiled with OpenSSL 1.1.1+ | |
# If the 'ssl' module isn't available at all that's | |
# fine, we only care if the module is available. | |
try: | |
import ssl | |
except ImportError: | |
pass | |
else: | |
if not ssl.OPENSSL_VERSION.startswith("OpenSSL "): # Defensive: | |
warnings.warn( | |
"urllib3 v2 only supports OpenSSL 1.1.1+, currently " | |
f"the 'ssl' module is compiled with {ssl.OPENSSL_VERSION!r}. " | |
"See: https://github.com/urllib3/urllib3/issues/3020", | |
exceptions.NotOpenSSLWarning, | |
) | |
elif ssl.OPENSSL_VERSION_INFO < (1, 1, 1): # Defensive: | |
raise ImportError( | |
"urllib3 v2 only supports OpenSSL 1.1.1+, currently " | |
f"the 'ssl' module is compiled with {ssl.OPENSSL_VERSION!r}. " | |
"See: https://github.com/urllib3/urllib3/issues/2168" | |
) | |
__author__ = "Andrey Petrov (andrey.petrov@shazow.net)" | |
__license__ = "MIT" | |
__version__ = __version__ | |
__all__ = ( | |
"HTTPConnectionPool", | |
"HTTPHeaderDict", | |
"HTTPSConnectionPool", | |
"PoolManager", | |
"ProxyManager", | |
"HTTPResponse", | |
"Retry", | |
"Timeout", | |
"add_stderr_logger", | |
"connection_from_url", | |
"disable_warnings", | |
"encode_multipart_formdata", | |
"make_headers", | |
"proxy_from_url", | |
"request", | |
"BaseHTTPResponse", | |
) | |
logging.getLogger(__name__).addHandler(NullHandler()) | |
def add_stderr_logger( | |
level: int = logging.DEBUG, | |
) -> logging.StreamHandler[typing.TextIO]: | |
""" | |
Helper for quickly adding a StreamHandler to the logger. Useful for | |
debugging. | |
Returns the handler after adding it. | |
""" | |
# This method needs to be in this __init__.py to get the __name__ correct | |
# even if urllib3 is vendored within another package. | |
logger = logging.getLogger(__name__) | |
handler = logging.StreamHandler() | |
handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(message)s")) | |
logger.addHandler(handler) | |
logger.setLevel(level) | |
logger.debug("Added a stderr logging handler to logger: %s", __name__) | |
return handler | |
# ... Clean up. | |
del NullHandler | |
# All warning filters *must* be appended unless you're really certain that they | |
# shouldn't be: otherwise, it's very hard for users to use most Python | |
# mechanisms to silence them. | |
# SecurityWarning's always go off by default. | |
warnings.simplefilter("always", exceptions.SecurityWarning, append=True) | |
# InsecurePlatformWarning's don't vary between requests, so we keep it default. | |
warnings.simplefilter("default", exceptions.InsecurePlatformWarning, append=True) | |
def disable_warnings(category: type[Warning] = exceptions.HTTPWarning) -> None: | |
""" | |
Helper for quickly disabling all urllib3 warnings. | |
""" | |
warnings.simplefilter("ignore", category) | |
_DEFAULT_POOL = PoolManager() | |
def request( | |
method: str, | |
url: str, | |
*, | |
body: _TYPE_BODY | None = None, | |
fields: _TYPE_FIELDS | None = None, | |
headers: typing.Mapping[str, str] | None = None, | |
preload_content: bool | None = True, | |
decode_content: bool | None = True, | |
redirect: bool | None = True, | |
retries: Retry | bool | int | None = None, | |
timeout: Timeout | float | int | None = 3, | |
json: typing.Any | None = None, | |
) -> BaseHTTPResponse: | |
""" | |
A convenience, top-level request method. It uses a module-global ``PoolManager`` instance. | |
Therefore, its side effects could be shared across dependencies relying on it. | |
To avoid side effects create a new ``PoolManager`` instance and use it instead. | |
The method does not accept low-level ``**urlopen_kw`` keyword arguments. | |
:param method: | |
HTTP request method (such as GET, POST, PUT, etc.) | |
:param url: | |
The URL to perform the request on. | |
:param body: | |
Data to send in the request body, either :class:`str`, :class:`bytes`, | |
an iterable of :class:`str`/:class:`bytes`, or a file-like object. | |
:param fields: | |
Data to encode and send in the request body. | |
:param headers: | |
Dictionary of custom headers to send, such as User-Agent, | |
If-None-Match, etc. | |
:param bool preload_content: | |
If True, the response's body will be preloaded into memory. | |
:param bool decode_content: | |
If True, will attempt to decode the body based on the | |
'content-encoding' header. | |
:param redirect: | |
If True, automatically handle redirects (status codes 301, 302, | |
303, 307, 308). Each redirect counts as a retry. Disabling retries | |
will disable redirect, too. | |
:param retries: | |
Configure the number of retries to allow before raising a | |
:class:`~urllib3.exceptions.MaxRetryError` exception. | |
If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a | |
:class:`~urllib3.util.retry.Retry` object for fine-grained control | |
over different types of retries. | |
Pass an integer number to retry connection errors that many times, | |
but no other types of errors. Pass zero to never retry. | |
If ``False``, then retries are disabled and any exception is raised | |
immediately. Also, instead of raising a MaxRetryError on redirects, | |
the redirect response will be returned. | |
:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. | |
:param timeout: | |
If specified, overrides the default timeout for this one | |
request. It may be a float (in seconds) or an instance of | |
:class:`urllib3.util.Timeout`. | |
:param json: | |
Data to encode and send as JSON with UTF-encoded in the request body. | |
The ``"Content-Type"`` header will be set to ``"application/json"`` | |
unless specified otherwise. | |
""" | |
return _DEFAULT_POOL.request( | |
method, | |
url, | |
body=body, | |
fields=fields, | |
headers=headers, | |
preload_content=preload_content, | |
decode_content=decode_content, | |
redirect=redirect, | |
retries=retries, | |
timeout=timeout, | |
json=json, | |
) | |
if sys.platform == "emscripten": | |
from .contrib.emscripten import inject_into_urllib3 # noqa: 401 | |
inject_into_urllib3() | |