>>> py3-truststore: Building community/py3-truststore 0.10.4-r2 (using abuild 3.18.0_rc7-r1) started Thu, 05 Nov 2026 13:01:19 +0000 >>> py3-truststore: Validating /home/buildozer/aports/community/py3-truststore/APKBUILD... >>> py3-truststore: Analyzing dependencies... >>> py3-truststore: Installing for build: build-base py3-gpep517 py3-installer py3-flit-core py3-aiohttp py3-flaky py3-httpx py3-openssl py3-pytest py3-pytest-asyncio py3-pytest-httpserver py3-requests py3-trustme py3-urllib3 ( 1/106) Installing libbz2 (1.0.8-r6) ( 2/106) Installing libffi (3.8.0-r0) ( 3/106) Installing xz-libs (5.8.4-r0) ( 4/106) Installing mpdecimal (4.0.1-r0) ( 5/106) Installing libpanelw (6.6_p20261017-r0) ( 6/106) Installing readline (8.3.3-r1) ( 7/106) Installing sqlite-libs (3.54.1-r0) ( 8/106) Installing python3 (3.14.10-r1) ( 9/106) Installing python3-pycache-pyc0 (3.14.10-r1) ( 10/106) Installing pyc (3.14.10-r1) ( 11/106) Installing py3-installer-pyc (1.0.1-r0) ( 12/106) Installing py3-gpep517-pyc (20-r0) ( 13/106) Installing python3-pyc (3.14.10-r1) ( 14/106) Installing py3-installer (1.0.1-r0) ( 15/106) Installing py3-gpep517 (20-r0) ( 16/106) Installing py3-flit-core (4.1.0-r0) ( 17/106) Installing py3-flit-core-pyc (4.1.0-r0) ( 18/106) Installing py3-aiohappyeyeballs (2.6.1-r1) ( 19/106) Installing py3-aiohappyeyeballs-pyc (2.6.1-r1) ( 20/106) Installing py3-frozenlist (1.8.0-r2) ( 21/106) Installing py3-frozenlist-pyc (1.8.0-r2) ( 22/106) Installing py3-aiosignal (1.4.0-r1) ( 23/106) Installing py3-aiosignal-pyc (1.4.0-r1) ( 24/106) Installing py3-typing-extensions (4.16.0-r0) ( 25/106) Installing py3-typing-extensions-pyc (4.16.0-r0) ( 26/106) Installing py3-async-timeout (4.0.3-r3) ( 27/106) Installing py3-async-timeout-pyc (4.0.3-r3) ( 28/106) Installing py3-attrs (26.1.0-r0) ( 29/106) Installing py3-attrs-pyc (26.1.0-r0) ( 30/106) Installing py3-brotli (1.2.1-r0) ( 31/106) Installing py3-brotli-pyc (1.2.1-r0) ( 32/106) Installing py3-charset-normalizer (3.5.1-r0) ( 33/106) Installing py3-charset-normalizer-pyc (3.5.1-r0) ( 34/106) Installing py3-idna (3.20-r0) ( 35/106) Installing py3-idna-pyc (3.20-r0) ( 36/106) Installing py3-idna-ssl (1.1.0-r10) ( 37/106) Installing py3-idna-ssl-pyc (1.1.0-r10) ( 38/106) Installing py3-multidict (7.2.1-r0) ( 39/106) Installing py3-multidict-pyc (7.2.1-r0) ( 40/106) Installing py3-expandvars (1.1.2-r3) ( 41/106) Installing py3-expandvars-pyc (1.1.2-r3) ( 42/106) Installing py3-propcache (0.5.4-r0) ( 43/106) Installing py3-propcache-pyc (0.5.4-r0) ( 44/106) Installing py3-yarl (1.25.1-r0) ( 45/106) Installing py3-yarl-pyc (1.25.1-r0) ( 46/106) Installing py3-aiohttp (3.14.3-r0) ( 47/106) Installing py3-aiohttp-pyc (3.14.3-r0) ( 48/106) Installing py3-flaky (3.8.1-r3) ( 49/106) Installing py3-flaky-pyc (3.8.1-r3) ( 50/106) Installing py3-certifi (2026.10.23-r0) ( 51/106) Installing py3-certifi-pyc (2026.10.23-r0) ( 52/106) Installing py3-curio (1.6-r4) ( 53/106) Installing py3-curio-pyc (1.6-r4) ( 54/106) Installing py3-sniffio (1.3.1-r2) ( 55/106) Installing py3-sniffio-pyc (1.3.1-r2) ( 56/106) Installing py3-anyio (4.16.0-r0) ( 57/106) Installing py3-anyio-pyc (4.16.0-r0) ( 58/106) Installing py3-h11 (0.16.0-r1) ( 59/106) Installing py3-h11-pyc (0.16.0-r1) ( 60/106) Installing py3-httpcore (1.0.9-r1) ( 61/106) Installing py3-httpcore-pyc (1.0.9-r1) ( 62/106) Installing py3-httpx (0.28.1-r1) ( 63/106) Installing py3-httpx-pyc (0.28.1-r1) ( 64/106) Installing py3-cparser (3.0-r1) ( 65/106) Installing py3-cparser-pyc (3.0-r1) ( 66/106) Installing py3-cffi (2.1.1-r0) ( 67/106) Installing py3-cffi-pyc (2.1.1-r0) ( 68/106) Installing py3-cryptography (50.0.0-r0) ( 69/106) Installing py3-cryptography-pyc (50.0.0-r0) ( 70/106) Installing py3-openssl (26.4.0-r0) ( 71/106) Installing py3-openssl-pyc (26.4.0-r0) ( 72/106) Installing py3-iniconfig (2.3.0-r1) ( 73/106) Installing py3-iniconfig-pyc (2.3.0-r1) ( 74/106) Installing py3-parsing (3.3.3-r0) ( 75/106) Installing py3-parsing-pyc (3.3.3-r0) ( 76/106) Installing py3-packaging (26.3-r0) ( 77/106) Installing py3-packaging-pyc (26.3-r0) ( 78/106) Installing py3-pluggy (1.6.0-r1) ( 79/106) Installing py3-pluggy-pyc (1.6.0-r1) ( 80/106) Installing py3-py (1.11.0-r5) ( 81/106) Installing py3-py-pyc (1.11.0-r5) ( 82/106) Installing py3-pygments (2.21.0-r0) ( 83/106) Installing py3-pygments-pyc (2.21.0-r0) ( 84/106) Installing py3-pytest (9.1.1-r1) ( 85/106) Installing py3-pytest-pyc (9.1.1-r1) ( 86/106) Installing py3-pytest-asyncio (1.4.0-r0) ( 87/106) Installing py3-pytest-asyncio-pyc (1.4.0-r0) ( 88/106) Installing py3-markupsafe (3.0.3-r1) ( 89/106) Installing py3-markupsafe-pyc (3.0.3-r1) ( 90/106) Installing py3-werkzeug (3.1.8-r0) ( 91/106) Installing py3-werkzeug-pyc (3.1.8-r0) ( 92/106) Installing py3-pytest-httpserver (1.2.0-r0) ( 93/106) Installing py3-pytest-httpserver-pyc (1.2.0-r0) ( 94/106) Installing py3-urllib3 (2.8.0-r0) ( 95/106) Installing py3-urllib3-pyc (2.8.0-r0) ( 96/106) Installing py3-requests (2.34.2-r0) ( 97/106) Installing py3-requests-pyc (2.34.2-r0) ( 98/106) Installing py3-asn1 (0.6.5-r0) ( 99/106) Installing py3-asn1-pyc (0.6.5-r0) (100/106) Installing py3-asn1-modules (0.4.2-r1) (101/106) Installing py3-asn1-modules-pyc (0.4.2-r1) (102/106) Installing py3-service_identity (26.1.0-r0) (103/106) Installing py3-service_identity-pyc (26.1.0-r0) (104/106) Installing py3-trustme (1.2.1-r1) (105/106) Installing py3-trustme-pyc (1.2.1-r1) (106/106) Installing .makedepends-py3-truststore (20261105.130133) Executing busybox-1.38.0-r8.trigger OK: 517.1 MiB in 211 packages >>> py3-truststore: Cleaning up srcdir >>> py3-truststore: Cleaning up pkgdir >>> py3-truststore: Cleaning up tmpdir >>> py3-truststore: Fetching https://distfiles.alpinelinux.org/distfiles/v3.25/py3-truststore-0.10.4.tar.gz Connecting to distfiles.alpinelinux.org (172.105.82.32:443) saving to '/var/cache/distfiles/v3.25/py3-truststore-0.10.4.tar.gz.part' py3-truststore-0.10. 100% |********************************| 30349 0:00:00 ETA '/var/cache/distfiles/v3.25/py3-truststore-0.10.4.tar.gz.part' saved /var/cache/distfiles/v3.25/py3-truststore-0.10.4.tar.gz: OK >>> py3-truststore: Fetching https://distfiles.alpinelinux.org/distfiles/v3.25/py3-truststore-0.10.4.tar.gz /var/cache/distfiles/v3.25/py3-truststore-0.10.4.tar.gz: OK >>> py3-truststore: Unpacking /var/cache/distfiles/v3.25/py3-truststore-0.10.4.tar.gz... 2026-11-05 13:01:34,182 gpep517 INFO Building wheel via backend flit_core.buildapi 2026-11-05 13:01:34,184 flit_core.wheel INFO Zip timestamps will be from SOURCE_DATE_EPOCH: 2026-03-30 07:40:59+00:00 2026-11-05 13:01:34,184 flit_core.wheel INFO Copying package file(s) from src/truststore 2026-11-05 13:01:34,186 flit_core.wheel INFO Writing metadata files 2026-11-05 13:01:34,187 flit_core.wheel INFO Writing the record of files 2026-11-05 13:01:34,187 flit_core.wheel INFO Built wheel: .dist/truststore-0.10.4-py3-none-any.whl 2026-11-05 13:01:34,187 gpep517 INFO The backend produced .dist/truststore-0.10.4-py3-none-any.whl truststore-0.10.4-py3-none-any.whl ============================= test session starts ============================== platform linux -- Python 3.14.10, pytest-9.1.1, pluggy-1.6.0 -- /home/buildozer/aports/community/py3-truststore/src/truststore-0.10.4/.testenv/bin/python3 cachedir: .pytest_cache rootdir: /home/buildozer/aports/community/py3-truststore/src/truststore-0.10.4 configfile: pyproject.toml plugins: pytest_httpserver-1.2.0, asyncio-1.4.0, flaky-3.8.1, anyio-0.0.0 asyncio: mode=Mode.STRICT, debug=False, asyncio_default_fixture_loop_scope=function, asyncio_default_test_loop_scope=function collecting ... collected 61 items / 8 deselected / 53 selected tests/test_api.py::test_success[1.1.1.1] PASSED [ 1%] tests/test_api.py::test_failures[wrong.host.badssl.com] PASSED [ 3%] tests/test_api.py::test_failures[expired.badssl.com] PASSED [ 5%] tests/test_api.py::test_failures[self-signed.badssl.com] PASSED [ 7%] tests/test_api.py::test_failures[untrusted-root.badssl.com] PASSED [ 9%] tests/test_api.py::test_failures[superfish.badssl.com] PASSED [ 11%] tests/test_api.py::test_success_after_loading_additional_anchors[1.1.1.1] PASSED [ 13%] tests/test_api.py::test_failure_after_loading_additional_anchors[wrong.host.badssl.com] PASSED [ 15%] tests/test_api.py::test_failure_after_loading_additional_anchors[expired.badssl.com] PASSED [ 16%] tests/test_api.py::test_failure_after_loading_additional_anchors[self-signed.badssl.com] PASSED [ 18%] tests/test_api.py::test_failure_after_loading_additional_anchors[untrusted-root.badssl.com] PASSED [ 20%] tests/test_api.py::test_failure_after_loading_additional_anchors[superfish.badssl.com] PASSED [ 22%] tests/test_api.py::test_failures_without_revocation_checks[wrong.host.badssl.com] PASSED [ 24%] tests/test_api.py::test_failures_without_revocation_checks[expired.badssl.com] PASSED [ 26%] tests/test_api.py::test_failures_without_revocation_checks[self-signed.badssl.com] PASSED [ 28%] tests/test_api.py::test_failures_without_revocation_checks[untrusted-root.badssl.com] PASSED [ 30%] tests/test_api.py::test_failures_without_revocation_checks[superfish.badssl.com] PASSED [ 32%] tests/test_api.py::test_sslcontext_api_success[1.1.1.1] SKIPPED (url...) [ 33%] tests/test_api.py::test_sslcontext_api_success_async[1.1.1.1] PASSED [ 35%] tests/test_api.py::test_sslcontext_api_failures[wrong.host.badssl.com] PASSED [ 37%] tests/test_api.py::test_sslcontext_api_failures[expired.badssl.com] PASSED [ 39%] tests/test_api.py::test_sslcontext_api_failures[self-signed.badssl.com] PASSED [ 41%] tests/test_api.py::test_sslcontext_api_failures[untrusted-root.badssl.com] PASSED [ 43%] tests/test_api.py::test_sslcontext_api_failures[superfish.badssl.com] PASSED [ 45%] tests/test_api.py::test_sslcontext_api_failures_async[wrong.host.badssl.com] PASSED [ 47%] tests/test_api.py::test_sslcontext_api_failures_async[expired.badssl.com] FAILED [ 49%] tests/test_api.py::test_sslcontext_api_failures_async[self-signed.badssl.com] PASSED [ 50%] tests/test_api.py::test_sslcontext_api_failures_async[untrusted-root.badssl.com] PASSED [ 52%] tests/test_api.py::test_sslcontext_api_failures_async[superfish.badssl.com] PASSED [ 54%] tests/test_api.py::test_requests_sslcontext_api_success[1.1.1.1] SKIPPED [ 56%] tests/test_api.py::test_requests_sslcontext_api_failures[wrong.host.badssl.com] PASSED [ 58%] tests/test_api.py::test_requests_sslcontext_api_failures[expired.badssl.com] PASSED [ 60%] tests/test_api.py::test_requests_sslcontext_api_failures[self-signed.badssl.com] FAILED [ 62%] tests/test_api.py::test_requests_sslcontext_api_failures[untrusted-root.badssl.com] PASSED [ 64%] tests/test_api.py::test_requests_sslcontext_api_failures[superfish.badssl.com] FAILED [ 66%] tests/test_api.py::test_wrong_host_succeeds_with_hostname_verification_disabled PASSED [ 67%] tests/test_api.py::test_trustme_cert PASSED [ 69%] tests/test_api.py::test_trustme_cert_loaded_via_capath PASSED [ 71%] tests/test_api.py::test_macos_10_7_import_error PASSED [ 73%] tests/test_custom_ca.py::test_urllib3_custom_ca SKIPPED (Install mkc...) [ 75%] tests/test_custom_ca.py::test_aiohttp_custom_ca SKIPPED (Install mkc...) [ 77%] tests/test_custom_ca.py::test_requests_custom_ca SKIPPED (Install mk...) [ 79%] tests/test_inject.py::test_inject_and_extract PASSED [ 81%] tests/test_inject.py::test_inject_set_values PASSED [ 83%] tests/test_inject.py::test_urllib3_works_with_inject SKIPPED (Instal...) [ 84%] tests/test_inject.py::test_aiohttp_works_with_inject SKIPPED (Instal...) [ 86%] tests/test_inject.py::test_requests_works_with_inject SKIPPED (Insta...) [ 88%] tests/test_inject.py::test_sync_httpx_works_with_inject SKIPPED (Ins...) [ 90%] tests/test_inject.py::test_async_httpx_works_with_inject SKIPPED (In...) [ 92%] tests/test_sslcontext.py::test_minimum_maximum_version PASSED [ 94%] tests/test_sslcontext.py::test_check_hostname_false PASSED [ 96%] tests/test_sslcontext.py::test_verify_mode_cert_none PASSED [ 98%] tests/test_threading.py::test_threading SKIPPED (Install mkcert to r...) [100%] =================================== FAILURES =================================== ____________ test_sslcontext_api_failures_async[expired.badssl.com] ____________ self = addr_infos = [] req = timeout = ClientTimeout(total=300, connect=None, sock_read=None, sock_connect=30, ceil_threshold=5) client_error = args = (functools.partial(, loop=<_UnixSelectorEventLoop running=False closed=False debug=False>),) kwargs = {'ssl': , 'server_hostname': 'expired.badssl.com'} async def _wrap_create_connection( self, *args: Any, addr_infos: list[AddrInfoType], req: ClientRequest, timeout: "ClientTimeout", client_error: type[Exception] = ClientConnectorError, **kwargs: Any, ) -> tuple[asyncio.Transport, ResponseHandler]: try: async with ceil_timeout( timeout.sock_connect, ceil_threshold=timeout.ceil_threshold ): sock = await aiohappyeyeballs.start_connection( addr_infos=addr_infos, local_addr_infos=self._local_addr_infos, happy_eyeballs_delay=self._happy_eyeballs_delay, interleave=self._interleave, loop=self._loop, socket_factory=self._socket_factory, ) # Add ssl_shutdown_timeout for Python 3.11+ when SSL is used if ( kwargs.get("ssl") and self._ssl_shutdown_timeout and sys.version_info >= (3, 11) ): kwargs["ssl_shutdown_timeout"] = self._ssl_shutdown_timeout > return await self._loop.create_connection(*args, **kwargs, sock=sock) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/aiohttp/connector.py:1316: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/asyncio/base_events.py:1199: in create_connection transport, protocol = await self._create_connection_transport( /usr/lib/python3.14/asyncio/base_events.py:1237: in _create_connection_transport await waiter _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_SelectorSocketTransport closed fd=17> def _read_ready__get_buffer(self): if self._conn_lost: return try: buf = self._protocol.get_buffer(-1) if not len(buf): raise RuntimeError('get_buffer() returned an empty buffer') except (SystemExit, KeyboardInterrupt): raise except BaseException as exc: self._fatal_error( exc, 'Fatal error: protocol.get_buffer() call failed.') return try: > nbytes = self._sock.recv_into(buf) ^^^^^^^^^^^^^^^^^^^^^^^^^ E ConnectionResetError: [Errno 104] Connection reset by peer /usr/lib/python3.14/asyncio/selector_events.py:986: ConnectionResetError The above exception was the direct cause of the following exception: failure = FailureHost(host='expired.badssl.com', error_messages=['certificate has expired', '“*.badssl.com” certificate is expir... not within its validity period when verifying against the current system clock or the timestamp in the signed file.']) @failure_hosts @pytest.mark.filterwarnings("ignore:enable_cleanup_closed ignored.*:DeprecationWarning") @pytest.mark.asyncio async def test_sslcontext_api_failures_async(failure): ctx = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT) if platform.system() != "Linux": ctx.verify_flags |= ssl.VERIFY_CRL_CHECK_CHAIN # connector avoids https://github.com/aio-libs/aiohttp/issues/5426 async with aiohttp.ClientSession( connector=aiohttp.TCPConnector(force_close=True, enable_cleanup_closed=True) ) as http: with pytest.raises( aiohttp.client_exceptions.ClientConnectorCertificateError ) as e: > await http.request("GET", f"https://{failure.host}", ssl=ctx) tests/test_api.py:346: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/aiohttp/client.py:858: in _request resp = await handler(req) ^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/aiohttp/client.py:812: in _connect_and_send_request conn = await self._connector.connect( /usr/lib/python3.14/site-packages/aiohttp/connector.py:657: in connect proto = await self._create_connection(req, traces, timeout) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/aiohttp/connector.py:1242: in _create_connection _, proto = await self._create_direct_connection(req, traces, timeout) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/aiohttp/connector.py:1620: in _create_direct_connection raise last_exc /usr/lib/python3.14/site-packages/aiohttp/connector.py:1589: in _create_direct_connection transp, proto = await self._wrap_create_connection( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = addr_infos = [] req = timeout = ClientTimeout(total=300, connect=None, sock_read=None, sock_connect=30, ceil_threshold=5) client_error = args = (functools.partial(, loop=<_UnixSelectorEventLoop running=False closed=False debug=False>),) kwargs = {'ssl': , 'server_hostname': 'expired.badssl.com'} async def _wrap_create_connection( self, *args: Any, addr_infos: list[AddrInfoType], req: ClientRequest, timeout: "ClientTimeout", client_error: type[Exception] = ClientConnectorError, **kwargs: Any, ) -> tuple[asyncio.Transport, ResponseHandler]: try: async with ceil_timeout( timeout.sock_connect, ceil_threshold=timeout.ceil_threshold ): sock = await aiohappyeyeballs.start_connection( addr_infos=addr_infos, local_addr_infos=self._local_addr_infos, happy_eyeballs_delay=self._happy_eyeballs_delay, interleave=self._interleave, loop=self._loop, socket_factory=self._socket_factory, ) # Add ssl_shutdown_timeout for Python 3.11+ when SSL is used if ( kwargs.get("ssl") and self._ssl_shutdown_timeout and sys.version_info >= (3, 11) ): kwargs["ssl_shutdown_timeout"] = self._ssl_shutdown_timeout return await self._loop.create_connection(*args, **kwargs, sock=sock) except cert_errors as exc: raise ClientConnectorCertificateError(req.connection_key, exc) from exc except ssl_errors as exc: raise ClientConnectorSSLError(req.connection_key, exc) from exc except OSError as exc: if exc.errno is None and isinstance(exc, asyncio.TimeoutError): raise > raise client_error(req.connection_key, exc) from exc E aiohttp.client_exceptions.ClientConnectorError: Cannot connect to host expired.badssl.com:443 ssl: [Connection reset by peer] /usr/lib/python3.14/site-packages/aiohttp/connector.py:1324: ClientConnectorError ________ test_requests_sslcontext_api_failures[self-signed.badssl.com] _________ self = method = 'GET', url = '/', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=False, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :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 headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :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 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 assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :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 pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :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 release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/site-packages/urllib3/connection.py:878: in connect wrapped_socket, is_verified = _ssl_wrap_socket_and_match_hostname( /usr/lib/python3.14/site-packages/urllib3/connection.py:1080: in _ssl_wrap_socket_and_match_hostname ssl_sock = ssl_wrap_socket( /usr/lib/python3.14/site-packages/urllib3/util/ssl_.py:437: in ssl_wrap_socket ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls, server_hostname) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/urllib3/util/ssl_.py:481: in _ssl_wrap_socket_impl return ssl_context.wrap_socket(sock, server_hostname=server_hostname) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .testenv/lib/python3.14/site-packages/truststore/_api.py:121: in wrap_socket ssl_sock = self._ctx.wrap_socket( /usr/lib/python3.14/ssl.py:469: in wrap_socket return self.sslsocket_class._create( /usr/lib/python3.14/ssl.py:1087: in _create self.do_handshake() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = , block = False @_sslcopydoc def do_handshake(self, block=False): self._check_connected() timeout = self.gettimeout() try: if timeout == 0.0 and block: self.settimeout(None) > self._sslobj.do_handshake() E ConnectionResetError: [Errno 104] Connection reset by peer /usr/lib/python3.14/ssl.py:1383: ConnectionResetError During handling of the above exception, another exception occurred: self = request = , stream = False, timeout = None, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( /usr/lib/python3.14/site-packages/urllib3/util/retry.py:510: in increment raise reraise(type(error), error, _stacktrace) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/urllib3/util/util.py:38: in reraise raise value.with_traceback(tb) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:793: in urlopen response = self._make_request( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/site-packages/urllib3/connection.py:878: in connect wrapped_socket, is_verified = _ssl_wrap_socket_and_match_hostname( /usr/lib/python3.14/site-packages/urllib3/connection.py:1080: in _ssl_wrap_socket_and_match_hostname ssl_sock = ssl_wrap_socket( /usr/lib/python3.14/site-packages/urllib3/util/ssl_.py:437: in ssl_wrap_socket ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls, server_hostname) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/urllib3/util/ssl_.py:481: in _ssl_wrap_socket_impl return ssl_context.wrap_socket(sock, server_hostname=server_hostname) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .testenv/lib/python3.14/site-packages/truststore/_api.py:121: in wrap_socket ssl_sock = self._ctx.wrap_socket( /usr/lib/python3.14/ssl.py:469: in wrap_socket return self.sslsocket_class._create( /usr/lib/python3.14/ssl.py:1087: in _create self.do_handshake() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = , block = False @_sslcopydoc def do_handshake(self, block=False): self._check_connected() timeout = self.gettimeout() try: if timeout == 0.0 and block: self.settimeout(None) > self._sslobj.do_handshake() E urllib3.exceptions.ProtocolError: ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer')) /usr/lib/python3.14/ssl.py:1383: ProtocolError During handling of the above exception, another exception occurred: failure = FailureHost(host='self-signed.badssl.com', error_messages=['self-signed certificate', 'self signed certificate', '“*.b...d', 'A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.']) @failure_hosts def test_requests_sslcontext_api_failures(failure): host = failure.host ctx = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT) if platform.system() != "Linux": ctx.verify_flags |= ssl.VERIFY_CRL_CHECK_CHAIN with requests.Session() as http: http.mount("https://", SSLContextAdapter(ssl_context=ctx)) with pytest.raises(requests.exceptions.SSLError) as e: > http.request("GET", f"https://{host}") tests/test_api.py:378: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = None, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: > raise ConnectionError(err, request=request) E requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer')) /usr/lib/python3.14/site-packages/requests/adapters.py:711: ConnectionError _________ test_requests_sslcontext_api_failures[superfish.badssl.com] __________ self = method = 'GET', url = '/', body = None headers = {'User-Agent': 'python-requests/2.34.2', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=False, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None, preload_content = False decode_content = False, response_kw = {} def urlopen( # type: ignore[override] self, method: str, url: str, body: _TYPE_BODY | None = None, headers: typing.Mapping[str, str] | None = None, retries: Retry | bool | int | None = None, redirect: bool = True, assert_same_host: bool = True, timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, pool_timeout: int | None = None, release_conn: bool | None = None, chunked: bool = False, body_pos: _TYPE_BODY_POSITION | None = None, preload_content: bool = True, decode_content: bool = True, **response_kw: typing.Any, ) -> BaseHTTPResponse: """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :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 headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :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 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 assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :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 pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :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 release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``preload_content`` which defaults to ``True``. :param bool chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. """ # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): # URLs starting with / are inherently schemeless. url = to_str(_encode_target(url)) destination_scheme = None else: parsed_url = parse_url(url) destination_scheme = parsed_url.scheme url = to_str(parsed_url._replace(fragment=None).url) if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = preload_content # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() # type: ignore[attr-defined] headers.update(self.proxy_headers) # type: ignore[union-attr] # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) timeout_obj = self._get_timeout(timeout) try: # Request a connection from the queue. conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout # type: ignore[assignment] # Is this a closed/new connection that requires CONNECT tunnelling? if self.proxy is not None and http_tunnel_required and conn.is_closed: try: self._prepare_proxy(conn) except (BaseSSLError, OSError, SocketTimeout) as e: self._raise_timeout( err=e, url=self.proxy.url, timeout_value=conn.timeout ) raise # If we're going to release the connection in ``finally:``, then # the response doesn't need to know about the connection. Otherwise # it will also try to release it and we'll have a double-release # mess. response_conn = conn if not release_conn else None # Make the request on the HTTPConnection object > response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, retries=retries, response_conn=response_conn, preload_content=preload_content, decode_content=decode_content, **response_kw, ) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:793: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/site-packages/urllib3/connection.py:878: in connect wrapped_socket, is_verified = _ssl_wrap_socket_and_match_hostname( /usr/lib/python3.14/site-packages/urllib3/connection.py:1080: in _ssl_wrap_socket_and_match_hostname ssl_sock = ssl_wrap_socket( /usr/lib/python3.14/site-packages/urllib3/util/ssl_.py:437: in ssl_wrap_socket ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls, server_hostname) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/urllib3/util/ssl_.py:481: in _ssl_wrap_socket_impl return ssl_context.wrap_socket(sock, server_hostname=server_hostname) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .testenv/lib/python3.14/site-packages/truststore/_api.py:121: in wrap_socket ssl_sock = self._ctx.wrap_socket( /usr/lib/python3.14/ssl.py:469: in wrap_socket return self.sslsocket_class._create( /usr/lib/python3.14/ssl.py:1087: in _create self.do_handshake() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = , block = False @_sslcopydoc def do_handshake(self, block=False): self._check_connected() timeout = self.gettimeout() try: if timeout == 0.0 and block: self.settimeout(None) > self._sslobj.do_handshake() E ConnectionResetError: [Errno 104] Connection reset by peer /usr/lib/python3.14/ssl.py:1383: ConnectionResetError During handling of the above exception, another exception occurred: self = request = , stream = False, timeout = None, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) /usr/lib/python3.14/site-packages/requests/adapters.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:847: in urlopen retries = retries.increment( /usr/lib/python3.14/site-packages/urllib3/util/retry.py:510: in increment raise reraise(type(error), error, _stacktrace) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/urllib3/util/util.py:38: in reraise raise value.with_traceback(tb) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:793: in urlopen response = self._make_request( /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:494: in _make_request raise new_e /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:470: in _make_request self._validate_conn(conn) /usr/lib/python3.14/site-packages/urllib3/connectionpool.py:1125: in _validate_conn conn.connect() /usr/lib/python3.14/site-packages/urllib3/connection.py:878: in connect wrapped_socket, is_verified = _ssl_wrap_socket_and_match_hostname( /usr/lib/python3.14/site-packages/urllib3/connection.py:1080: in _ssl_wrap_socket_and_match_hostname ssl_sock = ssl_wrap_socket( /usr/lib/python3.14/site-packages/urllib3/util/ssl_.py:437: in ssl_wrap_socket ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls, server_hostname) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/urllib3/util/ssl_.py:481: in _ssl_wrap_socket_impl return ssl_context.wrap_socket(sock, server_hostname=server_hostname) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .testenv/lib/python3.14/site-packages/truststore/_api.py:121: in wrap_socket ssl_sock = self._ctx.wrap_socket( /usr/lib/python3.14/ssl.py:469: in wrap_socket return self.sslsocket_class._create( /usr/lib/python3.14/ssl.py:1087: in _create self.do_handshake() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = , block = False @_sslcopydoc def do_handshake(self, block=False): self._check_connected() timeout = self.gettimeout() try: if timeout == 0.0 and block: self.settimeout(None) > self._sslobj.do_handshake() E urllib3.exceptions.ProtocolError: ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer')) /usr/lib/python3.14/ssl.py:1383: ProtocolError During handling of the above exception, another exception occurred: failure = FailureHost(host='superfish.badssl.com', error_messages=['unable to get local issuer certificate', '“superfish.badssl....d', 'A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.']) @failure_hosts def test_requests_sslcontext_api_failures(failure): host = failure.host ctx = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT) if platform.system() != "Linux": ctx.verify_flags |= ssl.VERIFY_CRL_CHECK_CHAIN with requests.Session() as http: http.mount("https://", SSLContextAdapter(ssl_context=ctx)) with pytest.raises(requests.exceptions.SSLError) as e: > http.request("GET", f"https://{host}") tests/test_api.py:378: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/requests/sessions.py:651: in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/requests/sessions.py:784: in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False, timeout = None, verify = True cert = None, proxies = OrderedDict() def send( self, request: PreparedRequest, stream: bool = False, timeout: _t.TimeoutType = None, verify: _t.VerifyType = True, cert: _t.CertType = None, proxies: dict[str, str] | None = None, ) -> Response: """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ assert _is_prepared(request) try: conn = self.get_connection_with_tls_context( request, verify, proxies=proxies, cert=cert ) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout resolved_timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): resolved_timeout = timeout else: resolved_timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, # type: ignore[arg-type] # urllib3 stubs don't accept Iterable[bytes | str] headers=request.headers, # type: ignore[arg-type] # urllib3#3072 redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=resolved_timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: > raise ConnectionError(err, request=request) E requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer')) /usr/lib/python3.14/site-packages/requests/adapters.py:711: ConnectionError ===Flaky Test Report=== test_success[1.1.1.1] passed 1 out of the required 1 times. Success! test_failures[wrong.host.badssl.com] failed (1 runs remaining out of 2). [Errno 104] Connection reset by peer [, , , , , , , , , , , , , , , , , , , , , , , , , , , , ] test_failures[wrong.host.badssl.com] passed 1 out of the required 1 times. Success! test_failures[expired.badssl.com] passed 1 out of the required 1 times. Success! test_failures[self-signed.badssl.com] passed 1 out of the required 1 times. Success! test_failures[untrusted-root.badssl.com] passed 1 out of the required 1 times. Success! test_failures[superfish.badssl.com] passed 1 out of the required 1 times. Success! test_success_after_loading_additional_anchors[1.1.1.1] passed 1 out of the required 1 times. Success! test_failure_after_loading_additional_anchors[wrong.host.badssl.com] passed 1 out of the required 1 times. Success! test_failure_after_loading_additional_anchors[expired.badssl.com] passed 1 out of the required 1 times. Success! test_failure_after_loading_additional_anchors[self-signed.badssl.com] passed 1 out of the required 1 times. Success! test_failure_after_loading_additional_anchors[untrusted-root.badssl.com] passed 1 out of the required 1 times. Success! test_failure_after_loading_additional_anchors[superfish.badssl.com] passed 1 out of the required 1 times. Success! test_failures_without_revocation_checks[wrong.host.badssl.com] failed (1 runs remaining out of 2). [Errno 104] Connection reset by peer [, , , , , , , , , , , , , , , , , , , , , , , , , , , , ] test_failures_without_revocation_checks[wrong.host.badssl.com] passed 1 out of the required 1 times. Success! test_failures_without_revocation_checks[expired.badssl.com] passed 1 out of the required 1 times. Success! test_failures_without_revocation_checks[self-signed.badssl.com] passed 1 out of the required 1 times. Success! test_failures_without_revocation_checks[untrusted-root.badssl.com] passed 1 out of the required 1 times. Success! test_failures_without_revocation_checks[superfish.badssl.com] passed 1 out of the required 1 times. Success! test_sslcontext_api_success_async[1.1.1.1] passed 1 out of the required 1 times. Success! test_sslcontext_api_failures[wrong.host.badssl.com] passed 1 out of the required 1 times. Success! test_sslcontext_api_failures[expired.badssl.com] passed 1 out of the required 1 times. Success! test_sslcontext_api_failures[self-signed.badssl.com] passed 1 out of the required 1 times. Success! test_sslcontext_api_failures[untrusted-root.badssl.com] passed 1 out of the required 1 times. Success! test_sslcontext_api_failures[superfish.badssl.com] passed 1 out of the required 1 times. Success! test_sslcontext_api_failures_async[wrong.host.badssl.com] passed 1 out of the required 1 times. Success! test_sslcontext_api_failures_async[expired.badssl.com] failed (1 runs remaining out of 2). Cannot connect to host expired.badssl.com:443 ssl: [Connection reset by peer] [, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ] test_sslcontext_api_failures_async[expired.badssl.com] failed; it passed 0 out of the required 1 times. Cannot connect to host expired.badssl.com:443 ssl: [Connection reset by peer] [, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ] test_sslcontext_api_failures_async[self-signed.badssl.com] passed 1 out of the required 1 times. Success! test_sslcontext_api_failures_async[untrusted-root.badssl.com] passed 1 out of the required 1 times. Success! test_sslcontext_api_failures_async[superfish.badssl.com] failed (1 runs remaining out of 2). Cannot connect to host superfish.badssl.com:443 ssl: [Connection reset by peer] [, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ] test_sslcontext_api_failures_async[superfish.badssl.com] passed 1 out of the required 1 times. Success! test_requests_sslcontext_api_failures[wrong.host.badssl.com] passed 1 out of the required 1 times. Success! test_requests_sslcontext_api_failures[expired.badssl.com] failed (1 runs remaining out of 2). ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer')) [, , , , , , , , , , , , , , , , , , , , , , , , , , ] test_requests_sslcontext_api_failures[expired.badssl.com] passed 1 out of the required 1 times. Success! test_requests_sslcontext_api_failures[self-signed.badssl.com] failed (1 runs remaining out of 2). ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer')) [, , , , , , , , , , , , , , , , , , , , , , , , , , ] test_requests_sslcontext_api_failures[self-signed.badssl.com] failed; it passed 0 out of the required 1 times. ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer')) [, , , , , , , , , , , , , , , , , , , , , , , , , , ] test_requests_sslcontext_api_failures[untrusted-root.badssl.com] passed 1 out of the required 1 times. Success! test_requests_sslcontext_api_failures[superfish.badssl.com] failed (1 runs remaining out of 2). ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer')) [, , , , , , , , , , , , , , , , , , , , , , , , , , ] test_requests_sslcontext_api_failures[superfish.badssl.com] failed; it passed 0 out of the required 1 times. ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer')) [, , , , , , , , , , , , , , , , , , , , , , , , , , ] test_wrong_host_succeeds_with_hostname_verification_disabled passed 1 out of the required 1 times. Success! test_trustme_cert passed 1 out of the required 1 times. Success! test_trustme_cert_loaded_via_capath passed 1 out of the required 1 times. Success! test_macos_10_7_import_error passed 1 out of the required 1 times. Success! ===End Flaky Test Report=== =========================== short test summary info ============================ FAILED tests/test_api.py::test_sslcontext_api_failures_async[expired.badssl.com] FAILED tests/test_api.py::test_requests_sslcontext_api_failures[self-signed.badssl.com] FAILED tests/test_api.py::test_requests_sslcontext_api_failures[superfish.badssl.com] ====== 3 failed, 39 passed, 11 skipped, 8 deselected in 78.25s (0:01:18) ======= >>> ERROR: py3-truststore: check failed >>> py3-truststore: Uninstalling dependencies... ( 1/106) Purging .makedepends-py3-truststore (20261105.130133) ( 2/106) Purging py3-gpep517-pyc (20-r0) ( 3/106) Purging py3-gpep517 (20-r0) ( 4/106) Purging py3-installer-pyc (1.0.1-r0) ( 5/106) Purging py3-installer (1.0.1-r0) ( 6/106) Purging py3-flit-core-pyc (4.1.0-r0) ( 7/106) Purging py3-flit-core (4.1.0-r0) ( 8/106) Purging py3-aiohttp-pyc (3.14.3-r0) ( 9/106) Purging py3-aiohttp (3.14.3-r0) ( 10/106) Purging py3-aiohappyeyeballs-pyc (2.6.1-r1) ( 11/106) Purging py3-aiohappyeyeballs (2.6.1-r1) ( 12/106) Purging py3-aiosignal-pyc (1.4.0-r1) ( 13/106) Purging py3-aiosignal (1.4.0-r1) ( 14/106) Purging py3-frozenlist-pyc (1.8.0-r2) ( 15/106) Purging py3-frozenlist (1.8.0-r2) ( 16/106) Purging py3-async-timeout-pyc (4.0.3-r3) ( 17/106) Purging py3-async-timeout (4.0.3-r3) ( 18/106) Purging py3-brotli-pyc (1.2.1-r0) ( 19/106) Purging py3-brotli (1.2.1-r0) ( 20/106) Purging py3-idna-ssl-pyc (1.1.0-r10) ( 21/106) Purging py3-idna-ssl (1.1.0-r10) ( 22/106) Purging py3-yarl-pyc (1.25.1-r0) ( 23/106) Purging py3-yarl (1.25.1-r0) ( 24/106) Purging py3-multidict-pyc (7.2.1-r0) ( 25/106) Purging py3-multidict (7.2.1-r0) ( 26/106) Purging py3-propcache-pyc (0.5.4-r0) ( 27/106) Purging py3-propcache (0.5.4-r0) ( 28/106) Purging py3-expandvars-pyc (1.1.2-r3) ( 29/106) Purging py3-expandvars (1.1.2-r3) ( 30/106) Purging py3-flaky-pyc (3.8.1-r3) ( 31/106) Purging py3-flaky (3.8.1-r3) ( 32/106) Purging py3-httpx-pyc (0.28.1-r1) ( 33/106) Purging py3-httpx (0.28.1-r1) ( 34/106) Purging py3-httpcore-pyc (1.0.9-r1) ( 35/106) Purging py3-httpcore (1.0.9-r1) ( 36/106) Purging py3-anyio-pyc (4.16.0-r0) ( 37/106) Purging py3-anyio (4.16.0-r0) ( 38/106) Purging py3-h11-pyc (0.16.0-r1) ( 39/106) Purging py3-h11 (0.16.0-r1) ( 40/106) Purging py3-sniffio-pyc (1.3.1-r2) ( 41/106) Purging py3-sniffio (1.3.1-r2) ( 42/106) Purging py3-curio-pyc (1.6-r4) ( 43/106) Purging py3-curio (1.6-r4) ( 44/106) Purging py3-pytest-asyncio-pyc (1.4.0-r0) ( 45/106) Purging py3-pytest-asyncio (1.4.0-r0) ( 46/106) Purging py3-pytest-pyc (9.1.1-r1) ( 47/106) Purging py3-pytest (9.1.1-r1) ( 48/106) Purging py3-iniconfig-pyc (2.3.0-r1) ( 49/106) Purging py3-iniconfig (2.3.0-r1) ( 50/106) Purging py3-packaging-pyc (26.3-r0) ( 51/106) Purging py3-packaging (26.3-r0) ( 52/106) Purging py3-parsing-pyc (3.3.3-r0) ( 53/106) Purging py3-parsing (3.3.3-r0) ( 54/106) Purging py3-pluggy-pyc (1.6.0-r1) ( 55/106) Purging py3-pluggy (1.6.0-r1) ( 56/106) Purging py3-py-pyc (1.11.0-r5) ( 57/106) Purging py3-py (1.11.0-r5) ( 58/106) Purging py3-pygments-pyc (2.21.0-r0) ( 59/106) Purging py3-pygments (2.21.0-r0) ( 60/106) Purging py3-pytest-httpserver-pyc (1.2.0-r0) ( 61/106) Purging py3-pytest-httpserver (1.2.0-r0) ( 62/106) Purging py3-werkzeug-pyc (3.1.8-r0) ( 63/106) Purging py3-werkzeug (3.1.8-r0) ( 64/106) Purging py3-markupsafe-pyc (3.0.3-r1) ( 65/106) Purging py3-markupsafe (3.0.3-r1) ( 66/106) Purging py3-requests-pyc (2.34.2-r0) ( 67/106) Purging py3-requests (2.34.2-r0) ( 68/106) Purging py3-certifi-pyc (2026.10.23-r0) ( 69/106) Purging py3-certifi (2026.10.23-r0) ( 70/106) Purging py3-charset-normalizer-pyc (3.5.1-r0) ( 71/106) Purging py3-charset-normalizer (3.5.1-r0) ( 72/106) Purging py3-trustme-pyc (1.2.1-r1) ( 73/106) Purging py3-trustme (1.2.1-r1) ( 74/106) Purging py3-idna-pyc (3.20-r0) ( 75/106) Purging py3-idna (3.20-r0) ( 76/106) Purging py3-openssl-pyc (26.4.0-r0) ( 77/106) Purging py3-openssl (26.4.0-r0) ( 78/106) Purging py3-typing-extensions-pyc (4.16.0-r0) ( 79/106) Purging py3-typing-extensions (4.16.0-r0) ( 80/106) Purging py3-service_identity-pyc (26.1.0-r0) ( 81/106) Purging py3-service_identity (26.1.0-r0) ( 82/106) Purging py3-asn1-modules-pyc (0.4.2-r1) ( 83/106) Purging py3-asn1-modules (0.4.2-r1) ( 84/106) Purging py3-asn1-pyc (0.6.5-r0) ( 85/106) Purging py3-asn1 (0.6.5-r0) ( 86/106) Purging py3-attrs-pyc (26.1.0-r0) ( 87/106) Purging py3-attrs (26.1.0-r0) ( 88/106) Purging py3-cryptography-pyc (50.0.0-r0) ( 89/106) Purging py3-cryptography (50.0.0-r0) ( 90/106) Purging py3-cffi-pyc (2.1.1-r0) ( 91/106) Purging py3-cffi (2.1.1-r0) ( 92/106) Purging py3-cparser-pyc (3.0-r1) ( 93/106) Purging py3-cparser (3.0-r1) ( 94/106) Purging py3-urllib3-pyc (2.8.0-r0) ( 95/106) Purging py3-urllib3 (2.8.0-r0) ( 96/106) Purging python3-pyc (3.14.10-r1) ( 97/106) Purging python3-pycache-pyc0 (3.14.10-r1) ( 98/106) Purging pyc (3.14.10-r1) ( 99/106) Purging python3 (3.14.10-r1) (100/106) Purging libbz2 (1.0.8-r6) (101/106) Purging libffi (3.8.0-r0) (102/106) Purging libpanelw (6.6_p20261017-r0) (103/106) Purging mpdecimal (4.0.1-r0) (104/106) Purging readline (8.3.3-r1) (105/106) Purging sqlite-libs (3.54.1-r0) (106/106) Purging xz-libs (5.8.4-r0) Executing busybox-1.38.0-r8.trigger OK: 441.7 MiB in 105 packages