anyio: Some TLS tests failed with Python 3.11.3

Things to check first

  • I have searched the existing issues and didn’t find my bug already reported there

  • I have checked that my bug is still present in the latest release

AnyIO version

git-master (b38e5995fbf8b38d3c19e3fa6d7aafcdd1c19e76)

Python version

3.11.3

What happened?

Some tests failed:

============================= test session starts ==============================
platform linux -- Python 3.11.3, pytest-7.3.0, pluggy-1.0.0
rootdir: /build/python-anyio/src/anyio
configfile: pyproject.toml
plugins: anyio-3.6.2, hypothesis-6.59.0, mock-3.10.0
collected 26 items

tests/streams/test_tls.py ..FF.....FF..FF.........FF                     [100%]

=================================== FAILURES ===================================
_________________ TestTLSStream.test_extra_attributes[asyncio] _________________
tests/streams/test_tls.py:105: in test_extra_attributes
    assert isinstance(wrapper.extra(TLSAttribute.shared_ciphers), list)
E   assert False
E    +  where False = isinstance(None, list)
E    +    where None = <bound method TypedAttributeProvider.extra of TLSStream(transport_stream=<anyio._backends._asyncio.SocketStream object...c987f8d10>, _read_bio=<_ssl.MemoryBIO object at 0x7f0c98f99e70>, _write_bio=<_ssl.MemoryBIO object at 0x7f0c98f99c00>)>(<object object at 0x7f0c9a984f30>)
E    +      where <bound method TypedAttributeProvider.extra of TLSStream(transport_stream=<anyio._backends._asyncio.SocketStream object...c987f8d10>, _read_bio=<_ssl.MemoryBIO object at 0x7f0c98f99e70>, _write_bio=<_ssl.MemoryBIO object at 0x7f0c98f99c00>)> = TLSStream(transport_stream=<anyio._backends._asyncio.SocketStream object at 0x7f0c987f9410>, standard_compatible=False...0c987f8d10>, _read_bio=<_ssl.MemoryBIO object at 0x7f0c98f99e70>, _write_bio=<_ssl.MemoryBIO object at 0x7f0c98f99c00>).extra
E    +      and   <object object at 0x7f0c9a984f30> = TLSAttribute.shared_ciphers
_____________ TestTLSStream.test_extra_attributes[asyncio+uvloop] ______________
tests/streams/test_tls.py:105: in test_extra_attributes
    assert isinstance(wrapper.extra(TLSAttribute.shared_ciphers), list)
E   assert False
E    +  where False = isinstance(None, list)
E    +    where None = <bound method TypedAttributeProvider.extra of TLSStream(transport_stream=<anyio._backends._asyncio.SocketStream object...c98893ed0>, _read_bio=<_ssl.MemoryBIO object at 0x7f0c98fa2da0>, _write_bio=<_ssl.MemoryBIO object at 0x7f0c98fa0520>)>(<object object at 0x7f0c9a984f30>)
E    +      where <bound method TypedAttributeProvider.extra of TLSStream(transport_stream=<anyio._backends._asyncio.SocketStream object...c98893ed0>, _read_bio=<_ssl.MemoryBIO object at 0x7f0c98fa2da0>, _write_bio=<_ssl.MemoryBIO object at 0x7f0c98fa0520>)> = TLSStream(transport_stream=<anyio._backends._asyncio.SocketStream object at 0x7f0c98893090>, standard_compatible=False...0c98893ed0>, _read_bio=<_ssl.MemoryBIO object at 0x7f0c98fa2da0>, _write_bio=<_ssl.MemoryBIO object at 0x7f0c98fa0520>).extra
E    +      and   <object object at 0x7f0c9a984f30> = TLSAttribute.shared_ciphers
___________ TestTLSStream.test_ragged_eofs[asyncio-server_standard] ____________
tests/streams/test_tls.py:244: in test_ragged_eofs
    assert isinstance(server_exc, OSError)
E   assert False
E    +  where False = isinstance(None, OSError)
___________ TestTLSStream.test_ragged_eofs[asyncio-client_standard] ____________
tests/streams/test_tls.py:237: in test_ragged_eofs
    with client_cm:
E   Failed: DID NOT RAISE <class 'anyio.BrokenResourceError'>
________ TestTLSStream.test_ragged_eofs[asyncio+uvloop-server_standard] ________
tests/streams/test_tls.py:244: in test_ragged_eofs
    assert isinstance(server_exc, OSError)
E   assert False
E    +  where False = isinstance(None, OSError)
________ TestTLSStream.test_ragged_eofs[asyncio+uvloop-client_standard] ________
tests/streams/test_tls.py:237: in test_ragged_eofs
    with client_cm:
E   Failed: DID NOT RAISE <class 'anyio.BrokenResourceError'>
_________________ TestTLSListener.test_handshake_fail[asyncio] _________________
tests/streams/test_tls.py:411: in test_handshake_fail
    assert isinstance(exception, BrokenResourceError)
E   AssertionError: assert False
E    +  where False = isinstance(SSLZeroReturnError(6, 'TLS/SSL connection has been closed (EOF) (_ssl.c:1002)'), BrokenResourceError)
------------------------------ Captured log call -------------------------------
ERROR    anyio.streams.tls:tls.py:286 Error during TLS handshake
NoneType: None
_____________ TestTLSListener.test_handshake_fail[asyncio+uvloop] ______________
tests/streams/test_tls.py:411: in test_handshake_fail
    assert isinstance(exception, BrokenResourceError)
E   AssertionError: assert False
E    +  where False = isinstance(SSLZeroReturnError(6, 'TLS/SSL connection has been closed (EOF) (_ssl.c:1002)'), BrokenResourceError)
------------------------------ Captured log call -------------------------------
ERROR    anyio.streams.tls:tls.py:286 Error during TLS handshake
NoneType: None
========================= 8 failed, 18 passed in 1.61s =========================

How can we reproduce the bug?

  1. Upgrade to Python 3.11.3
  2. Fix incorrectly skipped tests caused by https://github.com/agronholm/anyio/commit/891c0d6fff5b3a77aba682c1479b3f8ccfbc69d6:
diff --git a/tests/streams/test_tls.py b/tests/streams/test_tls.py
index fed2b1d..f062763 100644
--- a/tests/streams/test_tls.py
+++ b/tests/streams/test_tls.py
@@ -2,6 +2,7 @@ from __future__ import annotations
 
 import socket
 import ssl
+import sys
 from contextlib import ExitStack
 from threading import Thread
 from typing import ContextManager, NoReturn
@@ -22,7 +23,7 @@ from anyio.streams.tls import TLSAttribute, TLSListener, TLSStream
 
 pytestmark = pytest.mark.anyio
 skip_on_broken_openssl = pytest.mark.skipif(
-    ssl.OPENSSL_VERSION_INFO[0] > 1,
+    (ssl.OPENSSL_VERSION_INFO[0] > 1 and sys.version_info == (3, 7)),
     reason="Python 3.7 does not work with OpenSSL versions higher than 1.X",
 )
 
  1. Run pytest tests/streams/test_tls.py

Those tests do not fail with Python 3.11.2. Probably TLS/SSL changes in 3.11.3 [1][2][3] are relevant.

[1] https://docs.python.org/release/3.11.3/whatsnew/changelog.html#python-3-11-3 [2] https://github.com/python/cpython/pull/95495 [3] https://github.com/python/cpython/pull/96932

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 1
  • Comments: 17 (11 by maintainers)

Commits related to this issue

Most upvoted comments

I was planning on it. I just need to decide what other fixes I can backport.

Yep, I got those too on 3.11.3. I’ll try to investigate today.

I’ve corrected the skip condition on master, and it’s failing for Python >= 3.10 now. Locally it’s passing for all supported Python versions, sans 3.11.3 which I compiled manually. I hate OpenSSL.