Repository: urllib3/urllib3

Issue:
ResourceWarning due to _ssl_wrap_socket_and_match_hostname assert_fingerprint or assert_hostname failures not closing socket
### Subject

ResourceWarning due to _ssl_wrap_socket_and_match_hostname assert_fingerprint or assert_hostname failures not closing socket
discovered using https://github.com/urllib3/urllib3/pull/2842

### Environment

Describe your environment.
At least, paste here the output of:

### Steps to Reproduce
```python
import sys
import urllib3
import pytest
import gc


def main():
    with urllib3.HTTPSConnectionPool(
        "google.com",
        443,
        assert_fingerprint=(
            "AA:AA:AA:AA:AA:AAAA:AA:AAAA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA"
        ),
    ) as https_pool:
        with pytest.raises(urllib3.exceptions.MaxRetryError):
            https_pool.request("GET", "/", retries=0)


if __name__ == "__main__":
    sys.exit(main())
```

### Expected Behavior

prints nothing

### Actual Behavior
prints:

```
Exception ignored in: <ssl.SSLSocket fd=3, family=10, type=1, proto=6, laddr=('redacted', 51286, 0, 0), raddr=('2a00:1450:4009:820::200e', 443, 0, 0)>
ResourceWarning: unclosed <ssl.SSLSocket fd=3, family=10, type=1, proto=6, laddr=('redacted', 51286, 0, 0), raddr=('2a00:1450:4009:820::200e', 443, 0, 0)>
```


### Steps to Reproduce
```python
import sys
import urllib3
import pytest
import gc


def main():
    with urllib3.HTTPSConnectionPool(
        "google.com",
        443,
        assert_hostname="example.com",
    ) as https_pool:
        with pytest.raises(urllib3.exceptions.MaxRetryError):
            https_pool.request("GET", "/", retries=0)


if __name__ == "__main__":
    sys.exit(main())
```

### Expected Behavior

prints nothing

### Actual Behavior
prints:

```
Exception ignored in: <ssl.SSLSocket fd=3, family=10, type=1, proto=6, laddr=('redacted', 51286, 0, 0), raddr=('2a00:1450:4009:820::200e', 443, 0, 0)>
ResourceWarning: unclosed <ssl.SSLSocket fd=3, family=10, type=1, proto=6, laddr=('redacted', 51286, 0, 0), raddr=('2a00:1450:4009:820::200e', 443, 0, 0)>
```

Discussion:

Patch:
diff --git a/.github/PULL_REQUEST_TEMPLATE/release.md b/.github/PULL_REQUEST_TEMPLATE/release.md
index 7a99f524..5dc84b28 100644
--- a/.github/PULL_REQUEST_TEMPLATE/release.md
+++ b/.github/PULL_REQUEST_TEMPLATE/release.md
@@ -9,7 +9,7 @@
     ```
 * [ ]  Execute the `publish` GitHub workflow. This requires a review from a maintainer.
 * [ ]  Ensure that all expected artifacts are added to the new GitHub release. Should
-       be one `.whl`, one `.tar.gz`, and one `urllib3.intoto.jsonl`. Update the GitHub
+       be one `.whl`, one `.tar.gz`, and one `multiple.intoto.jsonl`. Update the GitHub
        release to have the content of the release's changelog.
 * [ ]  Announce on:
   * [ ]  Twitter
diff --git a/CHANGES.rst b/CHANGES.rst
index ea438480..1707eadd 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,37 +1,63 @@
-2.0.0a3 (2023-01-11)
-====================
+2.0.0 (2023-04-26)
+==================
 
-* Fix logging error when using ``add_stderr_logger``. (`#2839 <https://github.com/urllib3/urllib3/issues/2839>`__)
+Read the `v2.0 migration guide <https://urllib3.readthedocs.io/en/latest/v2-migration-guide.html>`__ for help upgrading to the latest version of urllib3.
 
-2.0.0a2 (2022-11-23)
-====================
+Removed
+-------
 
-Read the `v2.0 migration guide <https://urllib3.readthedocs.io/en/latest/v2-migration-guide.html>`__ for help upgrading to the latest version of urllib3.
+* Removed support for Python 2.7, 3.5, and 3.6 (`#883 <https://github.com/urllib3/urllib3/issues/883>`__, `#2336 <https://github.com/urllib3/urllib3/issues/2336>`__).
+* Removed fallback on certificate ``commonName`` in ``match_hostname()`` function.
+  This behavior was deprecated in May 2000 in RFC 2818. Instead only ``subjectAltName``
+  is used to verify the hostname by default. To enable verifying the hostname against
+  ``commonName`` use ``SSLContext.hostname_checks_common_name = True`` (`#2113 <https://github.com/urllib3/urllib3/issues/2113>`__).
+* Removed support for Python with an ``ssl`` module compiled with LibreSSL, CiscoSSL,
+  wolfSSL, and all other OpenSSL alternatives. Python is moving to require OpenSSL with PEP 644 (`#2168 <https://github.com/urllib3/urllib3/issues/2168>`__).
+* Removed support for OpenSSL versions earlier than 1.1.1 or that don't have SNI support.
+  When an incompatible OpenSSL version is detected an ``ImportError`` is raised (`#2168 <https://github.com/urllib3/urllib3/issues/2168>`__).
+* Removed the list of default ciphers for OpenSSL 1.1.1+ and SecureTransport as their own defaults are already secure (`#2082 <https://github.com/urllib3/urllib3/issues/2082>`__).
+* Removed ``urllib3.contrib.appengine.AppEngineManager`` and support for Google App Engine Standard Environment (`#2044 <https://github.com/urllib3/urllib3/issues/2044>`__).
+* Removed deprecated ``Retry`` options ``method_whitelist``, ``DEFAULT_REDIRECT_HEADERS_BLACKLIST`` (`#2086 <https://github.com/urllib3/urllib3/issues/2086>`__).
+* Removed ``urllib3.HTTPResponse.from_httplib`` (`#2648 <https://github.com/urllib3/urllib3/issues/2648>`__).
+* Removed default value of ``None`` for the ``request_context`` parameter of ``urllib3.PoolManager.connection_from_pool_key``. This change should have no effect on users as the default value of ``None`` was an invalid option and was never used (`#1897 <https://github.com/urllib3/urllib3/issues/1897>`__).
+* Removed the ``urllib3.request`` module. ``urllib3.request.RequestMethods`` has been made a private API.
+  This change was made to ensure that ``from urllib3 import request`` imported the top-level ``request()``
+  function instead of the ``urllib3.request`` module (`#2269 <https://github.com/urllib3/urllib3/issues/2269>`__).
+* Removed support for SSLv3.0 from the ``urllib3.contrib.pyopenssl`` even when support is available from the compiled OpenSSL library (`#2233 <https://github.com/urllib3/urllib3/issues/2233>`__).
+* Removed the deprecated ``urllib3.contrib.ntlmpool`` module (`#2339 <https://github.com/urllib3/urllib3/issues/2339>`__).
+* Removed ``DEFAULT_CIPHERS``, ``HAS_SNI``, ``USE_DEFAULT_SSLCONTEXT_CIPHERS``, from the private module ``urllib3.util.ssl_`` (`#2168 <https://github.com/urllib3/urllib3/issues/2168>`__).
+* Removed ``urllib3.exceptions.SNIMissingWarning`` (`#2168 <https://github.com/urllib3/urllib3/issues/2168>`__).
+* Removed the ``_prepare_conn`` method from ``HTTPConnectionPool``. Previously this was only used to call ``HTTPSConnection.set_cert()`` by ``HTTPSConnectionPool`` (`#1985 <https://github.com/urllib3/urllib3/issues/1985>`__).
+* Removed ``tls_in_tls_required`` property from ``HTTPSConnection``. This is now determined from the ``scheme`` parameter in ``HTTPConnection.set_tunnel()`` (`#1985 <https://github.com/urllib3/urllib3/issues/1985>`__).
 
-* Changed ``HTTPResponse.read()`` to raise an error when calling with ``decode_content=False`` after using ``decode_content=True`` to prevent data loss (`#2800 <https://github.com/urllib3/urllib3/issues/2800>`__).
-* Changed ``HTTPResponse.getheaders()`` and ``.getheader()`` to previous behavior in 1.26.x.
-  Instead we are deprecating these methods in favor of ``HTTPResponse.headers.items()`` and ``HTTPResponse.headers.get()``. Both deprecated
-  methods will be removed in v2.1.0 (`#2814 <https://github.com/urllib3/urllib3/issues/2814>`__)
-* Fixed an issue where parsing a URL with leading zeroes in the port would be rejected
-  even when the port number after removing the zeroes was valid. (`#2806 <https://github.com/urllib3/urllib3/pull/2806>`__)
-* Fixed deprecation warning when using cryptography v39.0.0. This fix requires using pyOpenSSL>=17.1.0 and cryptography>=1.9. (`#2829 <https://github.com/urllib3/urllib3/pull/2829>`__)
+Deprecated
+----------
 
-2.0.0a1 (2022-11-15)
-====================
+* Deprecated ``HTTPResponse.getheaders()`` and ``HTTPResponse.getheader()`` which will be removed in urllib3 v2.1.0. Instead use ``HTTPResponse.headers`` and ``HTTPResponse.headers.get(name, default)``. (`#1543 <https://github.com/urllib3/urllib3/issues/1543>`__, `#2814 <https://github.com/urllib3/urllib3/issues/2814>`__).
+* Deprecated ``urllib3.contrib.pyopenssl`` module which will be removed in urllib3 v2.1.0 (`#2691 <https://github.com/urllib3/urllib3/issues/2691>`__).
+* Deprecated ``urllib3.contrib.securetransport`` module which will be removed in urllib3 v2.1.0 (`#2692 <https://github.com/urllib3/urllib3/issues/2692>`__).
+* Deprecated ``ssl_version`` option in favor of ``ssl_minimum_version``. ``ssl_version`` will be removed in urllib3 v2.1.0 (`#2110 <https://github.com/urllib3/urllib3/issues/2110>`__).
+* Deprecated the ``strict`` parameter as it's not longer needed in Python 3.x. It will be removed in urllib3 v2.1.0 (`#2267 <https://github.com/urllib3/urllib3/issues/2267>`__)
+* Deprecated the ``NewConnectionError.pool`` attribute which will be removed in urllib3 v2.1.0 (`#2271 <https://github.com/urllib3/urllib3/issues/2271>`__).
+* Deprecated ``format_header_param_html5`` and ``format_header_param`` in favor of ``format_multipart_header_param`` (`#2257 <https://github.com/urllib3/urllib3/issues/2257>`__).
+* Deprecated ``RequestField.header_formatter`` parameter which will be removed in urllib3 v2.1.0 (`#2257 <https://github.com/urllib3/urllib3/issues/2257>`__).
+* Deprecated ``HTTPSConnection.set_cert()`` method. Instead pass parameters to the ``HTTPSConnection`` constructor (`#1985 <https://github.com/urllib3/urllib3/issues/1985>`__).
+* Deprecated ``HTTPConnection.request_chunked()`` method which will be removed in urllib3 v2.1.0. Instead pass ``chunked=True`` to ``HTTPConnection.request()`` (`#1985 <https://github.com/urllib3/urllib3/issues/1985>`__).
 
-Read the `v2.0 migration guide <https://urllib3.readthedocs.io/en/latest/v2-migration-guide.html>`__ for help upgrading to the latest version of urllib3.
+Added
+-----
 
+* Added top-level ``urllib3.request`` function which uses a preconfigured module-global ``PoolManager`` instance (`#2150 <https://github.com/urllib3/urllib3/issues/2150>`__).
+* Added the ``json`` parameter to ``urllib3.request()``, ``PoolManager.request()``, and ``ConnectionPool.request()`` methods to send JSON bodies in requests. Using this parameter will set the header ``Content-Type: application/json`` if ``Content-Type`` isn't already defined.
+  Added support for parsing JSON response bodies with ``HTTPResponse.json()`` method (`#2243 <https://github.com/urllib3/urllib3/issues/2243>`__).
 * Added type hints to the ``urllib3`` module (`#1897 <https://github.com/urllib3/urllib3/issues/1897>`__).
 * Added ``ssl_minimum_version`` and ``ssl_maximum_version`` options which set
   ``SSLContext.minimum_version`` and ``SSLContext.maximum_version`` (`#2110 <https://github.com/urllib3/urllib3/issues/2110>`__).
 * Added support for Zstandard (RFC 8878) when ``zstandard`` 1.18.0 or later is installed.
   Added the ``zstd`` extra which installs the ``zstandard`` package (`#1992 <https://github.com/urllib3/urllib3/issues/1992>`__).
 * Added ``urllib3.response.BaseHTTPResponse`` class. All future response classes will be subclasses of ``BaseHTTPResponse`` (`#2083 <https://github.com/urllib3/urllib3/issues/2083>`__).
-* Added top-level ``urllib3.request`` function which uses a preconfigured module-global ``PoolManager`` instance (`#2150 <https://github.com/urllib3/urllib3/issues/2150>`__).
 * Added ``FullPoolError`` which is raised when ``PoolManager(block=True)`` and a connection is returned to a full pool (`#2197 <https://github.com/urllib3/urllib3/issues/2197>`__).
 * Added ``HTTPHeaderDict`` to the top-level ``urllib3`` namespace (`#2216 <https://github.com/urllib3/urllib3/issues/2216>`__).
-* Added the ``json`` parameter to ``urllib3.request()``, ``PoolManager.request()``, and ``ConnectionPool.request()`` methods to send JSON bodies in requests. Using this parameter will set the header ``Content-Type: application/json`` if ``Content-Type`` isn't already defined.
-  Added support for parsing JSON response bodies with ``HTTPResponse.json()`` method (`#2243 <https://github.com/urllib3/urllib3/issues/2243>`__).
 * Added support for configuring header merging behavior with HTTPHeaderDict
   When using a ``HTTPHeaderDict`` to provide headers for a request, by default duplicate
   header values will be repeated. But if ``combine=True`` is passed into a call to
@@ -45,30 +71,10 @@ Read the `v2.0 migration guide <https://urllib3.readthedocs.io/en/latest/v2-migr
 * Added the ``authority`` property to the Url class as per RFC 3986 3.2. This property should be used in place of ``netloc`` for users who want to include the userinfo (auth) component of the URI (`#2520 <https://github.com/urllib3/urllib3/issues/2520>`__).
 * Added the ``scheme`` parameter to ``HTTPConnection.set_tunnel`` to configure the scheme of the origin being tunnelled to (`#1985 <https://github.com/urllib3/urllib3/issues/1985>`__).
 * Added the ``is_closed``, ``is_connected`` and ``has_connected_to_proxy`` properties to ``HTTPConnection`` (`#1985 <https://github.com/urllib3/urllib3/issues/1985>`__).
+* Added optional ``backoff_jitter`` parameter to ``Retry``. (`#2952 <https://github.com/urllib3/urllib3/issues/2952>`__)
 
-* Removed support for Python 2.7, 3.5, and 3.6 (`#883 <https://github.com/urllib3/urllib3/issues/883>`__, `#2336 <https://github.com/urllib3/urllib3/issues/2336>`__).
-* Removed fallback on certificate ``commonName`` in ``match_hostname()`` function.
-  This behavior was deprecated in May 2000 in RFC 2818. Instead only ``subjectAltName``
-  is used to verify the hostname by default. To enable verifying the hostname against
-  ``commonName`` use ``SSLContext.hostname_checks_common_name = True`` (`#2113 <https://github.com/urllib3/urllib3/issues/2113>`__).
-* Removed support for Python with an ``ssl`` module compiled with LibreSSL, CiscoSSL,
-  wolfSSL, and all other OpenSSL alternatives. Python is moving to require OpenSSL with PEP 644 (`#2168 <https://github.com/urllib3/urllib3/issues/2168>`__).
-* Removed support for OpenSSL versions earlier than 1.1.1 or that don't have SNI support.
-  When an incompatible OpenSSL version is detected an ``ImportError`` is raised (`#2168 <https://github.com/urllib3/urllib3/issues/2168>`__).
-* Removed the list of default ciphers for OpenSSL 1.1.1+ and SecureTransport as their own defaults are already secure (`#2082 <https://github.com/urllib3/urllib3/issues/2082>`__).
-* Removed ``urllib3.contrib.appengine.AppEngineManager`` and support for Google App Engine Standard Environment (`#2044 <https://github.com/urllib3/urllib3/issues/2044>`__).
-* Removed deprecated ``Retry`` options ``method_whitelist``, ``DEFAULT_REDIRECT_HEADERS_BLACKLIST`` (`#2086 <https://github.com/urllib3/urllib3/issues/2086>`__).
-* Removed ``urllib3.HTTPResponse.from_httplib`` (`#2648 <https://github.com/urllib3/urllib3/issues/2648>`__).
-* Removed default value of ``None`` for the ``request_context`` parameter of ``urllib3.PoolManager.connection_from_pool_key``. This change should have no effect on users as the default value of ``None`` was an invalid option and was never used (`#1897 <https://github.com/urllib3/urllib3/issues/1897>`__).
-* Removed the ``urllib3.request`` module. ``urllib3.request.RequestMethods`` has been made a private API.
-  This change was made to ensure that ``from urllib3 import request`` imported the top-level ``request()``
-  function instead of the ``urllib3.request`` module (`#2269 <https://github.com/urllib3/urllib3/issues/2269>`__).
-* Removed support for SSLv3.0 from the ``urllib3.contrib.pyopenssl`` even when support is available from the compiled OpenSSL library (`#2233 <https://github.com/urllib3/urllib3/issues/2233>`__).
-* Removed the deprecated ``urllib3.contrib.ntlmpool`` module (`#2339 <https://github.com/urllib3/urllib3/issues/2339>`__).
-* Removed ``DEFAULT_CIPHERS``, ``HAS_SNI``, ``USE_DEFAULT_SSLCONTEXT_CIPHERS``, from the private module ``urllib3.util.ssl_`` (`#2168 <https://github.com/urllib3/urllib3/issues/2168>`__).
-* Removed ``urllib3.exceptions.SNIMissingWarning`` (`#2168 <https://github.com/urllib3/urllib3/issues/2168>`__).
-* Removed the ``_prepare_conn`` method from ``HTTPConnectionPool``. Previously this was only used to call ``HTTPSConnection.set_cert()`` by ``HTTPSConnectionPool`` (`#1985 <https://github.com/urllib3/urllib3/issues/1985>`__).
-* Removed ``tls_in_tls_required`` property from ``HTTPSConnection``. This is now determined from the ``scheme`` parameter in ``HTTPConnection.set_tunnel()`` (`#1985 <https://github.com/urllib3/urllib3/issues/1985>`__).
+Changed
+-------
 
 * Changed ``urllib3.response.HTTPResponse.read`` to respect the semantics of ``io.BufferedIOBase`` regardless of compression. Specifically, this method:
 
@@ -77,6 +83,7 @@ Read the `v2.0 migration guide <https://urllib3.readthedocs.io/en/latest/v2-migr
   * Can issue any number of system calls: zero, one or multiple.
 
   If you want each ``urllib3.response.HTTPResponse.read`` call to issue a single system call, you need to disable decompression by setting ``decode_content=False`` (`#2128 <https://github.com/urllib3/urllib3/issues/2128>`__).
+* Changed ``urllib3.HTTPConnection.getresponse`` to return an instance of ``urllib3.HTTPResponse`` instead of ``http.client.HTTPResponse`` (`#2648 <https://github.com/urllib3/urllib3/issues/2648>`__).
 * Changed ``ssl_version`` to instead set the corresponding ``SSLContext.minimum_version``
   and ``SSLContext.maximum_version`` values.  Regardless of ``ssl_version`` passed
   ``SSLContext`` objects are now constructed using ``ssl.PROTOCOL_TLS_CLIENT`` (`#2110 <https://github.com/urllib3/urllib3/issues/2110>`__).
@@ -85,15 +92,13 @@ Read the `v2.0 migration guide <https://urllib3.readthedocs.io/en/latest/v2-migr
 * Changed ``urllib3.util.create_urllib3_context`` to not override the system cipher suites with
   a default value. The new default will be cipher suites configured by the operating system (`#2168 <https://github.com/urllib3/urllib3/issues/2168>`__).
 * Changed ``multipart/form-data`` header parameter formatting matches the WHATWG HTML Standard as of 2021-06-10. Control characters in filenames are no longer percent encoded (`#2257 <https://github.com/urllib3/urllib3/issues/2257>`__).
-* Changed ``urllib3.HTTPConnection.getresponse`` to return an instance of ``urllib3.HTTPResponse`` instead of ``http.client.HTTPResponse`` (`#2648 <https://github.com/urllib3/urllib3/issues/2648>`__).
 * Changed the error raised when connecting via HTTPS when the ``ssl`` module isn't available from ``SSLError`` to ``ImportError`` (`#2589 <https://github.com/urllib3/urllib3/issues/2589>`__).
 * Changed ``HTTPConnection.request()`` to always use lowercase chunk boundaries when sending requests with ``Transfer-Encoding: chunked`` (`#2515 <https://github.com/urllib3/urllib3/issues/2515>`__).
-* Changed `enforce_content_length` default to True, preventing silent data loss when reading streamed responses (`#2514 <https://github.com/urllib3/urllib3/issues/2514>`__).
+* Changed ``enforce_content_length`` default to True, preventing silent data loss when reading streamed responses (`#2514 <https://github.com/urllib3/urllib3/issues/2514>`__).
 * Changed internal implementation of ``HTTPHeaderDict`` to use ``dict`` instead of ``collections.OrderedDict`` for better performance (`#2080 <https://github.com/urllib3/urllib3/issues/2080>`__).
 * Changed the ``urllib3.contrib.pyopenssl`` module to wrap ``OpenSSL.SSL.Error`` with ``ssl.SSLError`` in ``PyOpenSSLContext.load_cert_chain`` (`#2628 <https://github.com/urllib3/urllib3/issues/2628>`__).
 * Changed usage of the deprecated ``socket.error`` to ``OSError`` (`#2120 <https://github.com/urllib3/urllib3/issues/2120>`__).
 * Changed all parameters in the ``HTTPConnection`` and ``HTTPSConnection`` constructors to be keyword-only except ``host`` and ``port`` (`#1985 <https://github.com/urllib3/urllib3/issues/1985>`__).
-* Changed ``urllib3.util.is_connection_dropped()`` to use ``HTTPConnection.is_connected`` (`#1985 <https://github.com/urllib3/urllib3/issues/1985>`__).
 * Changed ``HTTPConnection.getresponse()`` to set the socket timeout from ``HTTPConnection.timeout`` value before reading
   data from the socket. This previously was done manually by the ``HTTPConnectionPool`` calling ``HTTPConnection.sock.settimeout(...)`` (`#1985 <https://github.com/urllib3/urllib3/issues/1985>`__).
 * Changed the ``_proxy_host`` property to ``_tunnel_host`` in ``HTTPConnectionPool`` to more closely match how the property is used (value in ``HTTPConnection.set_tunnel()``) (`#1985 <https://github.com/urllib3/urllib3/issues/1985>`__).
@@ -101,19 +106,12 @@ Read the `v2.0 migration guide <https://urllib3.readthedocs.io/en/latest/v2-migr
 * Changed TLS handshakes to use ``SSLContext.check_hostname`` when possible (`#2452 <https://github.com/urllib3/urllib3/pull/2452>`__).
 * Changed ``server_hostname`` to behave like other parameters only used by ``HTTPSConnectionPool`` (`#2537 <https://github.com/urllib3/urllib3/pull/2537>`__).
 * Changed the default ``blocksize`` to 16KB to match OpenSSL's default read amounts (`#2348 <https://github.com/urllib3/urllib3/pull/2348>`__).
+* Changed ``HTTPResponse.read()`` to raise an error when calling with ``decode_content=False`` after using ``decode_content=True`` to prevent data loss (`#2800 <https://github.com/urllib3/urllib3/issues/2800>`__).
 
-* Deprecated ``HTTPResponse.getheaders()`` and ``HTTPResponse.getheader()`` which will be removed in urllib3 v2.1.0. Instead use ``HTTPResponse.headers`` and ``HTTPResponse.headers.get(name, default)``. (`#1543 <https://github.com/urllib3/urllib3/issues/1543>`__, `#2814 <https://github.com/urllib3/urllib3/issues/2814>`__).
-* Deprecated ``urllib3.contrib.pyopenssl`` module which will be removed in urllib3 v2.1.0 (`#2691 <https://github.com/urllib3/urllib3/issues/2691>`__).
-* Deprecated ``urllib3.contrib.securetransport`` module which will be removed in urllib3 v2.1.0 (`#2692 <https://github.com/urllib3/urllib3/issues/2692>`__).
-* Deprecated ``ssl_version`` option in favor of ``ssl_minimum_version``. ``ssl_version`` will be removed in urllib3 v2.1.0 (`#2110 <https://github.com/urllib3/urllib3/issues/2110>`__).
-* Deprecated the ``strict`` parameter as it's not longer needed in Python 3.x. It will be removed in urllib3 v2.1.0 (`#2267 <https://github.com/urllib3/urllib3/issues/2267>`__)
-* Deprecated the ``NewConnectionError.pool`` attribute which will be removed in urllib3 v2.1.0 (`#2271 <https://github.com/urllib3/urllib3/issues/2271>`__).
-* Deprecated ``format_header_param_html5`` and ``format_header_param`` in favor of ``format_multipart_header_param`` (`#2257 <https://github.com/urllib3/urllib3/issues/2257>`__).
-* Deprecated ``RequestField.header_formatter`` parameter which will be removed in urllib3 v2.1.0 (`#2257 <https://github.com/urllib3/urllib3/issues/2257>`__).
-* Deprecated ``HTTPSConnection.set_cert()`` method. Instead pass parameters to the ``HTTPSConnection`` constructor (`#1985 <https://github.com/urllib3/urllib3/issues/1985>`__).
-* Deprecated ``HTTPConnection.request_chunked()`` method which will be removed in urllib3 v2.1.0. Instead pass ``chunked=True`` to ``HTTPConnection.request()`` (`#1985 <https://github.com/urllib3/urllib3/issues/1985>`__).
+Fixed
+-----
 
-* Fixed thread-safety issue where accessing a `PoolManager` with many distinct origins would cause connection pools to be closed while requests are in progress (`#1252 <https://github.com/urllib3/urllib3/issues/1252>`__).
+* Fixed thread-safety issue where accessing a ``PoolManager`` with many distinct origins would cause connection pools to be closed while requests are in progress (`#1252 <https://github.com/urllib3/urllib3/issues/1252>`__).
 * Fixed an issue where an ``HTTPConnection`` instance would erroneously reuse the socket read timeout value from reading the previous response instead of a newly configured connect timeout.
   Instead now if ``HTTPConnection.timeout`` is updated before sending the next request the new timeout value will be used (`#2645 <https://github.com/urllib3/urllib3/issues/2645>`__).
 * Fixed ``socket.error.errno`` when raised from pyOpenSSL's ``OpenSSL.SSL.SysCallError`` (`#2118 <https://github.com/urllib3/urllib3/issues/2118>`__).
@@ -121,9 +119,10 @@ Read the `v2.0 migration guide <https://urllib3.readthedocs.io/en/latest/v2-migr
 * Fixed a bug where ``headers`` would be modified by the ``remove_headers_on_redirect`` feature (`#2272 <https://github.com/urllib3/urllib3/issues/2272>`__).
 * Fixed a reference cycle bug in ``urllib3.util.connection.create_connection()`` (`#2277 <https://github.com/urllib3/urllib3/issues/2277>`__).
 * Fixed a socket leak if ``HTTPConnection.connect()`` fails (`#2571 <https://github.com/urllib3/urllib3/pull/2571>`__).
+* Fixed ``urllib3.contrib.pyopenssl.WrappedSocket`` and ``urllib3.contrib.securetransport.WrappedSocket`` close methods (`#2970 <https://github.com/urllib3/urllib3/issues/2970>`__)
 
 1.26.15 (2023-03-10)
---------------------
+====================
 
 * Fix socket timeout value when ``HTTPConnection`` is reused (`#2645 <https://github.com/urllib3/urllib3/issues/2645>`__)
 * Remove "!" character from the unreserved characters in IPv6 Zone ID parsing
@@ -131,13 +130,13 @@ Read the `v2.0 migration guide <https://urllib3.readthedocs.io/en/latest/v2-migr
 * Fix IDNA handling of '\x80' byte (`#2901 <https://github.com/urllib3/urllib3/issues/2901>`__)
 
 1.26.14 (2023-01-11)
---------------------
+====================
 
 * Fixed parsing of port 0 (zero) returning None, instead of 0. (`#2850 <https://github.com/urllib3/urllib3/issues/2850>`__)
 * Removed deprecated getheaders() calls in contrib module. Fixed the type hint of ``PoolKey.key_retries`` by adding ``bool`` to the union. (`#2865 <https://github.com/urllib3/urllib3/issues/2865>`__)
 
 1.26.13 (2022-11-23)
---------------------
+====================
 
 * Deprecated the ``HTTPResponse.getheaders()`` and ``HTTPResponse.getheader()`` methods.
 * Fixed an issue where parsing a URL with leading zeroes in the port would be rejected
diff --git a/changelog/2899.bugfix.rst b/changelog/2899.bugfix.rst
deleted file mode 100644
index f91bccd1..00000000
--- a/changelog/2899.bugfix.rst
+++ /dev/null
@@ -1,1 +0,0 @@
-Removed '!' from _UNRESERVED_PAT as specified in the RFC.
diff --git a/changelog/2901.bugfix.rst b/changelog/2901.bugfix.rst
deleted file mode 100644
index 8849a1c3..00000000
--- a/changelog/2901.bugfix.rst
+++ /dev/null
@@ -1,1 +0,0 @@
-Corrected a sign error in a check for whether a character is in the ASCII range.
diff --git a/changelog/2952.feature.rst b/changelog/2952.feature.rst
deleted file mode 100644
index c750ccde..00000000
--- a/changelog/2952.feature.rst
+++ /dev/null
@@ -1,1 +0,0 @@
-Added optional `backoff_jitter` parameter to ``Retry``.
diff --git a/changelog/2970.bugfix.rst b/changelog/2970.bugfix.rst
deleted file mode 100644
index cc20d222..00000000
--- a/changelog/2970.bugfix.rst
+++ /dev/null
@@ -1,1 +0,0 @@
-fix ``urllib3.contrib.pyopenssl.WrappedSocket`` and ``urllib3.contrib.securetransport.WrappedSocket`` close
diff --git a/changelog/2975.removal.rst b/changelog/2975.removal.rst
deleted file mode 100644
index f538ed1a..00000000
--- a/changelog/2975.removal.rst
+++ /dev/null
@@ -1,1 +0,0 @@
-Remove the ``setup.py`` shim, ``python setup.py install`` will print ``[Errno 2] No such file or directory`` instead of a warning to use pip
diff --git a/changelog/2991.bugfix.rst b/changelog/2991.bugfix.rst
new file mode 100644
index 00000000..19e360ba
--- /dev/null
+++ b/changelog/2991.bugfix.rst
@@ -0,0 +1,1 @@
+avoid a ``ResourceWarning`` if ``assert_fingerprint`` or ``match_hostname`` fail
diff --git a/ci/0002-Stop-relying-on-removed-DEFAULT_CIPHERS.patch b/ci/0002-Stop-relying-on-removed-DEFAULT_CIPHERS.patch
deleted file mode 100644
index e533a8c1..00000000
--- a/ci/0002-Stop-relying-on-removed-DEFAULT_CIPHERS.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From dcc55a54fe2ba3b403923e95ab329009a9f430e2 Mon Sep 17 00:00:00 2001
-From: Quentin Pradet <quentin.pradet@gmail.com>
-Date: Fri, 19 Aug 2022 11:02:11 +0400
-Subject: [PATCH] Stop relying on removed DEFAULT_CIPHERS
-
----
- botocore/httpsession.py | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/botocore/httpsession.py b/botocore/httpsession.py
-index 29b210377..aaecb454b 100644
---- a/botocore/httpsession.py
-+++ b/botocore/httpsession.py
-@@ -19,7 +19,6 @@ from urllib3.exceptions import ReadTimeoutError as URLLib3ReadTimeoutError
- from urllib3.exceptions import SSLError as URLLib3SSLError
- from urllib3.util.retry import Retry
- from urllib3.util.ssl_ import (
--    DEFAULT_CIPHERS,
-     OP_NO_COMPRESSION,
-     PROTOCOL_TLS,
-     OP_NO_SSLv2,
-@@ -99,7 +98,8 @@ def create_urllib3_context(
- 
-     context = SSLContext(ssl_version)
- 
--    context.set_ciphers(ciphers or DEFAULT_CIPHERS)
-+    if ciphers:
-+        context.set_ciphers(ciphers)
- 
-     # Setting the default here, as we may have no ssl module on import
-     cert_reqs = ssl.CERT_REQUIRED if cert_reqs is None else cert_reqs
--- 
-2.37.2
-
diff --git a/docs/sponsors.rst b/docs/sponsors.rst
index a08b536a..33e9ce7f 100644
--- a/docs/sponsors.rst
+++ b/docs/sponsors.rst
@@ -7,45 +7,6 @@ benefits from this library.
 Your contribution will go towards adding new features to urllib3 and making
 sure all functionality continues to meet our high quality standards.
 
-
-v2.0 Sponsor Perks
-------------------
-
-.. important::
-
-   `Get in contact <mailto:sethmichaellarson@gmail.com>`_ for additional
-   details on sponsorship and perks before making a contribution
-   through `GitHub Sponsors <https://github.com/sponsors/urllib3>`_ if you have questions.
-
-
-Silver v2.0 Sponsor Perks
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-- Your organization name and URL permanently added
-  to the **Sponsors and Grants** section below
-- Thank you within the v2.0 release announcement
-  and on Twitter from urllib3 maintainers
-
-➤ `Contribute to the "Silver v2.0 Sponsor" tier <https://opencollective.com/urllib3/contribute/silver-v2-sponsor-20442/checkout>`_
-on Open Collective.
-
-
-Gold v2.0 Sponsor Perks
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-- Organization logo and URL listed on top of the v2.0 Roadmap
-- Call with one or more urllib3 maintainer(s) to discuss
-  the v2.0 release and how it impacts your organization
-- Your organization will be thanked within the v2.0 release
-  announcement, within all blog posts and public updates related to v2.0
-  development, and multiple thank-you's on Twitter from
-  urllib3 maintainers throughout v2.0 development
-- All perks from the **Silver v2.0 Sponsors Perks** above
-
-➤ `Contribute to the "Gold v2.0 Sponsor" tier <https://opencollective.com/urllib3/contribute/gold-v2-sponsor-20443/checkout>`_
-on Open Collective.
-
-
 Sponsors and Grants
 -------------------
 
@@ -61,6 +22,8 @@ We also welcome sponsorship in the form of time. We greatly appreciate companies
 who encourage employees to contribute on an ongoing basis during their work hours.
 Let us know and we'll be glad to add you to our sponsors list.
 
+* `Spotify <https://engineering.atspotify.com/opensource/>`_ (June 2nd, 2022)
+
 * `GitCoin Grants <https://gitcoin.co/grants>`_ (2019-2020), sponsored `@sethmlarson <https://github.com/sethmlarson>`_
   and `@pquentin <https://github.com/pquentin>`_
 
diff --git a/noxfile.py b/noxfile.py
index 4b08f7ed..91b958e0 100644
--- a/noxfile.py
+++ b/noxfile.py
@@ -100,7 +100,6 @@ def downstream_botocore(session: nox.Session) -> None:
     session.chdir("botocore")
     for patch in [
         "0001-Mark-100-Continue-tests-as-failing.patch",
-        "0002-Stop-relying-on-removed-DEFAULT_CIPHERS.patch",
     ]:
         session.run("git", "apply", f"{root}/ci/{patch}", external=True)
     session.run("git", "rev-parse", "HEAD", external=True)
diff --git a/pyproject.toml b/pyproject.toml
index 2afda13f..7046f772 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -28,6 +28,7 @@ classifiers = [
   "Programming Language :: Python :: 3.9",
   "Programming Language :: Python :: 3.10",
   "Programming Language :: Python :: 3.11",
+  "Programming Language :: Python :: 3.12",
   "Programming Language :: Python :: 3 :: Only",
   "Programming Language :: Python :: Implementation :: CPython",
   "Programming Language :: Python :: Implementation :: PyPy",
diff --git a/src/urllib3/_version.py b/src/urllib3/_version.py
index d84ed56d..6c6d26d4 100644
--- a/src/urllib3/_version.py
+++ b/src/urllib3/_version.py
@@ -1,4 +1,4 @@
 # This file is protected via CODEOWNERS
 from __future__ import annotations
 
-__version__ = "2.0.0a3"
+__version__ = "2.0.0"
diff --git a/src/urllib3/connection.py b/src/urllib3/connection.py
index 1f13af0b..9dc04fe0 100644
--- a/src/urllib3/connection.py
+++ b/src/urllib3/connection.py
@@ -784,36 +784,42 @@ def _ssl_wrap_socket_and_match_hostname(
         tls_in_tls=tls_in_tls,
     )
 
-    if assert_fingerprint:
-        _assert_fingerprint(ssl_sock.getpeercert(binary_form=True), assert_fingerprint)
-    elif (
-        context.verify_mode != ssl.CERT_NONE
-        and not context.check_hostname
-        and assert_hostname is not False
-    ):
-        cert: _TYPE_PEER_CERT_RET_DICT = ssl_sock.getpeercert()  # type: ignore[assignment]
-
-        # Need to signal to our match_hostname whether to use 'commonName' or not.
-        # If we're using our own constructed SSLContext we explicitly set 'False'
-        # because PyPy hard-codes 'True' from SSLContext.hostname_checks_common_name.
-        if default_ssl_context:
-            hostname_checks_common_name = False
-        else:
-            hostname_checks_common_name = (
-                getattr(context, "hostname_checks_common_name", False) or False
+    try:
+        if assert_fingerprint:
+            _assert_fingerprint(
+                ssl_sock.getpeercert(binary_form=True), assert_fingerprint
+            )
+        elif (
+            context.verify_mode != ssl.CERT_NONE
+            and not context.check_hostname
+            and assert_hostname is not False
+        ):
+            cert: _TYPE_PEER_CERT_RET_DICT = ssl_sock.getpeercert()  # type: ignore[assignment]
+
+            # Need to signal to our match_hostname whether to use 'commonName' or not.
+            # If we're using our own constructed SSLContext we explicitly set 'False'
+            # because PyPy hard-codes 'True' from SSLContext.hostname_checks_common_name.
+            if default_ssl_context:
+                hostname_checks_common_name = False
+            else:
+                hostname_checks_common_name = (
+                    getattr(context, "hostname_checks_common_name", False) or False
+                )
+
+            _match_hostname(
+                cert,
+                assert_hostname or server_hostname,  # type: ignore[arg-type]
+                hostname_checks_common_name,
             )
 
-        _match_hostname(
-            cert,
-            assert_hostname or server_hostname,  # type: ignore[arg-type]
-            hostname_checks_common_name,
+        return _WrappedAndVerifiedSocket(
+            socket=ssl_sock,
+            is_verified=context.verify_mode == ssl.CERT_REQUIRED
+            or bool(assert_fingerprint),
         )
-
-    return _WrappedAndVerifiedSocket(
-        socket=ssl_sock,
-        is_verified=context.verify_mode == ssl.CERT_REQUIRED
-        or bool(assert_fingerprint),
-    )
+    except BaseException:
+        ssl_sock.close()
+        raise
 
 
 def _match_hostname(


Test patch:
diff --git a/test/test_connection.py b/test/test_connection.py
index 8237311f..9f33a7b3 100644
--- a/test/test_connection.py
+++ b/test/test_connection.py
@@ -17,7 +17,8 @@ from urllib3.connection import (  # type: ignore[attr-defined]
     _url_from_connection,
     _wrap_proxy_error,
 )
-from urllib3.exceptions import HTTPError, ProxyError
+from urllib3.exceptions import HTTPError, ProxyError, SSLError
+from urllib3.util import ssl_
 from urllib3.util.ssl_match_hostname import (
     CertificateError as ImplementationCertificateError,
 )
@@ -235,3 +236,32 @@ class TestConnection:
         # Should error if a request has not been sent
         with pytest.raises(ResponseNotReady):
             conn.getresponse()
+
+    def test_assert_fingerprint_closes_socket(self) -> None:
+        context = mock.create_autospec(ssl_.SSLContext)
+        context.wrap_socket.return_value.getpeercert.return_value = b"fake cert"
+        conn = HTTPSConnection(
+            "google.com",
+            port=443,
+            assert_fingerprint="AA:AA:AA:AA:AA:AAAA:AA:AAAA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA",
+            ssl_context=context,
+        )
+        with mock.patch.object(conn, "_new_conn"):
+            with pytest.raises(SSLError):
+                conn.connect()
+
+        context.wrap_socket.return_value.close.assert_called_once_with()
+
+    def test_assert_hostname_closes_socket(self) -> None:
+        context = mock.create_autospec(ssl_.SSLContext)
+        context.wrap_socket.return_value.getpeercert.return_value = {
+            "subjectAltName": (("DNS", "google.com"),)
+        }
+        conn = HTTPSConnection(
+            "google.com", port=443, assert_hostname="example.com", ssl_context=context
+        )
+        with mock.patch.object(conn, "_new_conn"):
+            with pytest.raises(ImplementationCertificateError):
+                conn.connect()
+
+        context.wrap_socket.return_value.close.assert_called_once_with()