Skip to content

Commit a5acb19

Browse files
committed
Update urllib3 to 2.6.2
1 parent 1c13558 commit a5acb19

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+6850
-6518
lines changed

newrelic/packages/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
# This file is used by dependabot to keep track of and recommend updates
44
# to the New Relic Python Agent's dependencies in newrelic/packages/.
55
opentelemetry_proto==1.32.1
6-
urllib3==1.26.19
6+
urllib3==2.6.2
77
wrapt==2.0.0
88
asgiref==3.6.0 # We only vendor asgiref.compatibility.py

newrelic/packages/urllib3/LICENSE.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2008-2020 Andrey Petrov and contributors (see CONTRIBUTORS.txt)
3+
Copyright (c) 2008-2020 Andrey Petrov and contributors.
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal
Lines changed: 132 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,57 @@
11
"""
22
Python HTTP library with thread-safe connection pooling, file post support, user friendly, and more
33
"""
4-
from __future__ import absolute_import
4+
5+
from __future__ import annotations
56

67
# Set default logging handler to avoid "No handler found" warnings.
78
import logging
9+
import sys
10+
import typing
811
import warnings
912
from logging import NullHandler
1013

1114
from . import exceptions
15+
from ._base_connection import _TYPE_BODY
16+
from ._collections import HTTPHeaderDict
1217
from ._version import __version__
1318
from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, connection_from_url
14-
from .filepost import encode_multipart_formdata
19+
from .filepost import _TYPE_FIELDS, encode_multipart_formdata
1520
from .poolmanager import PoolManager, ProxyManager, proxy_from_url
16-
from .response import HTTPResponse
21+
from .response import BaseHTTPResponse, HTTPResponse
1722
from .util.request import make_headers
1823
from .util.retry import Retry
1924
from .util.timeout import Timeout
20-
from .util.url import get_host
2125

22-
# === NOTE TO REPACKAGERS AND VENDORS ===
23-
# Please delete this block, this logic is only
24-
# for urllib3 being distributed via PyPI.
25-
# See: https://github.com/urllib3/urllib3/issues/2680
26+
# Ensure that Python is compiled with OpenSSL 1.1.1+
27+
# If the 'ssl' module isn't available at all that's
28+
# fine, we only care if the module is available.
2629
try:
27-
import urllib3_secure_extra # type: ignore # noqa: F401
30+
import ssl
2831
except ImportError:
2932
pass
3033
else:
31-
warnings.warn(
32-
"'urllib3[secure]' extra is deprecated and will be removed "
33-
"in a future release of urllib3 2.x. Read more in this issue: "
34-
"https://github.com/urllib3/urllib3/issues/2680",
35-
category=DeprecationWarning,
36-
stacklevel=2,
37-
)
34+
if not ssl.OPENSSL_VERSION.startswith("OpenSSL "): # Defensive:
35+
warnings.warn(
36+
"urllib3 v2 only supports OpenSSL 1.1.1+, currently "
37+
f"the 'ssl' module is compiled with {ssl.OPENSSL_VERSION!r}. "
38+
"See: https://github.com/urllib3/urllib3/issues/3020",
39+
exceptions.NotOpenSSLWarning,
40+
)
41+
elif ssl.OPENSSL_VERSION_INFO < (1, 1, 1): # Defensive:
42+
raise ImportError(
43+
"urllib3 v2 only supports OpenSSL 1.1.1+, currently "
44+
f"the 'ssl' module is compiled with {ssl.OPENSSL_VERSION!r}. "
45+
"See: https://github.com/urllib3/urllib3/issues/2168"
46+
)
3847

3948
__author__ = "Andrey Petrov (andrey.petrov@shazow.net)"
4049
__license__ = "MIT"
4150
__version__ = __version__
4251

4352
__all__ = (
4453
"HTTPConnectionPool",
54+
"HTTPHeaderDict",
4555
"HTTPSConnectionPool",
4656
"PoolManager",
4757
"ProxyManager",
@@ -52,15 +62,18 @@
5262
"connection_from_url",
5363
"disable_warnings",
5464
"encode_multipart_formdata",
55-
"get_host",
5665
"make_headers",
5766
"proxy_from_url",
67+
"request",
68+
"BaseHTTPResponse",
5869
)
5970

6071
logging.getLogger(__name__).addHandler(NullHandler())
6172

6273

63-
def add_stderr_logger(level=logging.DEBUG):
74+
def add_stderr_logger(
75+
level: int = logging.DEBUG,
76+
) -> logging.StreamHandler[typing.TextIO]:
6477
"""
6578
Helper for quickly adding a StreamHandler to the logger. Useful for
6679
debugging.
@@ -87,16 +100,112 @@ def add_stderr_logger(level=logging.DEBUG):
87100
# mechanisms to silence them.
88101
# SecurityWarning's always go off by default.
89102
warnings.simplefilter("always", exceptions.SecurityWarning, append=True)
90-
# SubjectAltNameWarning's should go off once per host
91-
warnings.simplefilter("default", exceptions.SubjectAltNameWarning, append=True)
92103
# InsecurePlatformWarning's don't vary between requests, so we keep it default.
93104
warnings.simplefilter("default", exceptions.InsecurePlatformWarning, append=True)
94-
# SNIMissingWarnings should go off only once.
95-
warnings.simplefilter("default", exceptions.SNIMissingWarning, append=True)
96105

97106

98-
def disable_warnings(category=exceptions.HTTPWarning):
107+
def disable_warnings(category: type[Warning] = exceptions.HTTPWarning) -> None:
99108
"""
100109
Helper for quickly disabling all urllib3 warnings.
101110
"""
102111
warnings.simplefilter("ignore", category)
112+
113+
114+
_DEFAULT_POOL = PoolManager()
115+
116+
117+
def request(
118+
method: str,
119+
url: str,
120+
*,
121+
body: _TYPE_BODY | None = None,
122+
fields: _TYPE_FIELDS | None = None,
123+
headers: typing.Mapping[str, str] | None = None,
124+
preload_content: bool | None = True,
125+
decode_content: bool | None = True,
126+
redirect: bool | None = True,
127+
retries: Retry | bool | int | None = None,
128+
timeout: Timeout | float | int | None = 3,
129+
json: typing.Any | None = None,
130+
) -> BaseHTTPResponse:
131+
"""
132+
A convenience, top-level request method. It uses a module-global ``PoolManager`` instance.
133+
Therefore, its side effects could be shared across dependencies relying on it.
134+
To avoid side effects create a new ``PoolManager`` instance and use it instead.
135+
The method does not accept low-level ``**urlopen_kw`` keyword arguments.
136+
137+
:param method:
138+
HTTP request method (such as GET, POST, PUT, etc.)
139+
140+
:param url:
141+
The URL to perform the request on.
142+
143+
:param body:
144+
Data to send in the request body, either :class:`str`, :class:`bytes`,
145+
an iterable of :class:`str`/:class:`bytes`, or a file-like object.
146+
147+
:param fields:
148+
Data to encode and send in the request body.
149+
150+
:param headers:
151+
Dictionary of custom headers to send, such as User-Agent,
152+
If-None-Match, etc.
153+
154+
:param bool preload_content:
155+
If True, the response's body will be preloaded into memory.
156+
157+
:param bool decode_content:
158+
If True, will attempt to decode the body based on the
159+
'content-encoding' header.
160+
161+
:param redirect:
162+
If True, automatically handle redirects (status codes 301, 302,
163+
303, 307, 308). Each redirect counts as a retry. Disabling retries
164+
will disable redirect, too.
165+
166+
:param retries:
167+
Configure the number of retries to allow before raising a
168+
:class:`~urllib3.exceptions.MaxRetryError` exception.
169+
170+
If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
171+
:class:`~urllib3.util.retry.Retry` object for fine-grained control
172+
over different types of retries.
173+
Pass an integer number to retry connection errors that many times,
174+
but no other types of errors. Pass zero to never retry.
175+
176+
If ``False``, then retries are disabled and any exception is raised
177+
immediately. Also, instead of raising a MaxRetryError on redirects,
178+
the redirect response will be returned.
179+
180+
:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.
181+
182+
:param timeout:
183+
If specified, overrides the default timeout for this one
184+
request. It may be a float (in seconds) or an instance of
185+
:class:`urllib3.util.Timeout`.
186+
187+
:param json:
188+
Data to encode and send as JSON with UTF-encoded in the request body.
189+
The ``"Content-Type"`` header will be set to ``"application/json"``
190+
unless specified otherwise.
191+
"""
192+
193+
return _DEFAULT_POOL.request(
194+
method,
195+
url,
196+
body=body,
197+
fields=fields,
198+
headers=headers,
199+
preload_content=preload_content,
200+
decode_content=decode_content,
201+
redirect=redirect,
202+
retries=retries,
203+
timeout=timeout,
204+
json=json,
205+
)
206+
207+
208+
if sys.platform == "emscripten":
209+
from .contrib.emscripten import inject_into_urllib3 # noqa: 401
210+
211+
inject_into_urllib3()
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
from __future__ import annotations
2+
3+
import typing
4+
5+
from .util.connection import _TYPE_SOCKET_OPTIONS
6+
from .util.timeout import _DEFAULT_TIMEOUT, _TYPE_TIMEOUT
7+
from .util.url import Url
8+
9+
_TYPE_BODY = typing.Union[bytes, typing.IO[typing.Any], typing.Iterable[bytes], str]
10+
11+
12+
class ProxyConfig(typing.NamedTuple):
13+
ssl_context: ssl.SSLContext | None
14+
use_forwarding_for_https: bool
15+
assert_hostname: None | str | typing.Literal[False]
16+
assert_fingerprint: str | None
17+
18+
19+
class _ResponseOptions(typing.NamedTuple):
20+
# TODO: Remove this in favor of a better
21+
# HTTP request/response lifecycle tracking.
22+
request_method: str
23+
request_url: str
24+
preload_content: bool
25+
decode_content: bool
26+
enforce_content_length: bool
27+
28+
29+
if typing.TYPE_CHECKING:
30+
import ssl
31+
from typing import Protocol
32+
33+
from .response import BaseHTTPResponse
34+
35+
class BaseHTTPConnection(Protocol):
36+
default_port: typing.ClassVar[int]
37+
default_socket_options: typing.ClassVar[_TYPE_SOCKET_OPTIONS]
38+
39+
host: str
40+
port: int
41+
timeout: None | (
42+
float
43+
) # Instance doesn't store _DEFAULT_TIMEOUT, must be resolved.
44+
blocksize: int
45+
source_address: tuple[str, int] | None
46+
socket_options: _TYPE_SOCKET_OPTIONS | None
47+
48+
proxy: Url | None
49+
proxy_config: ProxyConfig | None
50+
51+
is_verified: bool
52+
proxy_is_verified: bool | None
53+
54+
def __init__(
55+
self,
56+
host: str,
57+
port: int | None = None,
58+
*,
59+
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
60+
source_address: tuple[str, int] | None = None,
61+
blocksize: int = 8192,
62+
socket_options: _TYPE_SOCKET_OPTIONS | None = ...,
63+
proxy: Url | None = None,
64+
proxy_config: ProxyConfig | None = None,
65+
) -> None: ...
66+
67+
def set_tunnel(
68+
self,
69+
host: str,
70+
port: int | None = None,
71+
headers: typing.Mapping[str, str] | None = None,
72+
scheme: str = "http",
73+
) -> None: ...
74+
75+
def connect(self) -> None: ...
76+
77+
def request(
78+
self,
79+
method: str,
80+
url: str,
81+
body: _TYPE_BODY | None = None,
82+
headers: typing.Mapping[str, str] | None = None,
83+
# We know *at least* botocore is depending on the order of the
84+
# first 3 parameters so to be safe we only mark the later ones
85+
# as keyword-only to ensure we have space to extend.
86+
*,
87+
chunked: bool = False,
88+
preload_content: bool = True,
89+
decode_content: bool = True,
90+
enforce_content_length: bool = True,
91+
) -> None: ...
92+
93+
def getresponse(self) -> BaseHTTPResponse: ...
94+
95+
def close(self) -> None: ...
96+
97+
@property
98+
def is_closed(self) -> bool:
99+
"""Whether the connection either is brand new or has been previously closed.
100+
If this property is True then both ``is_connected`` and ``has_connected_to_proxy``
101+
properties must be False.
102+
"""
103+
104+
@property
105+
def is_connected(self) -> bool:
106+
"""Whether the connection is actively connected to any origin (proxy or target)"""
107+
108+
@property
109+
def has_connected_to_proxy(self) -> bool:
110+
"""Whether the connection has successfully connected to its proxy.
111+
This returns False if no proxy is in use. Used to determine whether
112+
errors are coming from the proxy layer or from tunnelling to the target origin.
113+
"""
114+
115+
class BaseHTTPSConnection(BaseHTTPConnection, Protocol):
116+
default_port: typing.ClassVar[int]
117+
default_socket_options: typing.ClassVar[_TYPE_SOCKET_OPTIONS]
118+
119+
# Certificate verification methods
120+
cert_reqs: int | str | None
121+
assert_hostname: None | str | typing.Literal[False]
122+
assert_fingerprint: str | None
123+
ssl_context: ssl.SSLContext | None
124+
125+
# Trusted CAs
126+
ca_certs: str | None
127+
ca_cert_dir: str | None
128+
ca_cert_data: None | str | bytes
129+
130+
# TLS version
131+
ssl_minimum_version: int | None
132+
ssl_maximum_version: int | None
133+
ssl_version: int | str | None # Deprecated
134+
135+
# Client certificates
136+
cert_file: str | None
137+
key_file: str | None
138+
key_password: str | None
139+
140+
def __init__(
141+
self,
142+
host: str,
143+
port: int | None = None,
144+
*,
145+
timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
146+
source_address: tuple[str, int] | None = None,
147+
blocksize: int = 16384,
148+
socket_options: _TYPE_SOCKET_OPTIONS | None = ...,
149+
proxy: Url | None = None,
150+
proxy_config: ProxyConfig | None = None,
151+
cert_reqs: int | str | None = None,
152+
assert_hostname: None | str | typing.Literal[False] = None,
153+
assert_fingerprint: str | None = None,
154+
server_hostname: str | None = None,
155+
ssl_context: ssl.SSLContext | None = None,
156+
ca_certs: str | None = None,
157+
ca_cert_dir: str | None = None,
158+
ca_cert_data: None | str | bytes = None,
159+
ssl_minimum_version: int | None = None,
160+
ssl_maximum_version: int | None = None,
161+
ssl_version: int | str | None = None, # Deprecated
162+
cert_file: str | None = None,
163+
key_file: str | None = None,
164+
key_password: str | None = None,
165+
) -> None: ...

0 commit comments

Comments
 (0)