From f8a11f5b1b2d1351c4e2f509e22c4e43a96e7b52 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Sat, 16 Oct 2021 14:10:34 +0200 Subject: [PATCH] Add support for Python 3.10 (#5927) (#6081) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sviatoslav Sydorenko (cherry picked from commit 84babebc96e08f1ea2b7c31406eb5a1ed20cd5c4) Co-authored-by: 秋葉 --- .github/workflows/ci.yml | 2 +- CHANGES/5927.feature | 1 + aiohttp/connector.py | 4 +++- aiohttp/helpers.py | 1 + aiohttp/test_utils.py | 6 ++++-- requirements/dev.txt | 4 ++-- requirements/lint.txt | 2 +- tests/conftest.py | 2 +- tests/test_client_functional.py | 2 +- tests/test_connector.py | 14 +++++++++----- tests/test_loop.py | 4 ++-- tests/test_proxy_functional.py | 18 ++++++++++++++++-- tests/test_worker.py | 6 +++--- 13 files changed, 45 insertions(+), 21 deletions(-) create mode 100644 CHANGES/5927.feature diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ce180874f01..fa5ad37e7de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -76,7 +76,7 @@ jobs: needs: lint strategy: matrix: - pyver: [3.6, 3.7, 3.8, 3.9] + pyver: [3.6, 3.7, 3.8, 3.9, '3.10'] no-extensions: ['', 'Y'] os: [ubuntu, macos, windows] exclude: diff --git a/CHANGES/5927.feature b/CHANGES/5927.feature new file mode 100644 index 00000000000..dac4f3e5eb9 --- /dev/null +++ b/CHANGES/5927.feature @@ -0,0 +1 @@ +Added support for Python 3.10 to Github Actions CI/CD workflows and fix the related deprecation warnings -- :user:`Hanaasagi`. diff --git a/aiohttp/connector.py b/aiohttp/connector.py index 153fbdc5a52..c30cce0d63d 100644 --- a/aiohttp/connector.py +++ b/aiohttp/connector.py @@ -913,9 +913,11 @@ def _make_ssl_context(verified: bool) -> SSLContext: if verified: return ssl.create_default_context() else: - sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) sslcontext.options |= ssl.OP_NO_SSLv2 sslcontext.options |= ssl.OP_NO_SSLv3 + sslcontext.check_hostname = False + sslcontext.verify_mode = ssl.CERT_NONE try: sslcontext.options |= ssl.OP_NO_COMPRESSION except AttributeError as attr_err: diff --git a/aiohttp/helpers.py b/aiohttp/helpers.py index ea973611bf8..94e9b0224fd 100644 --- a/aiohttp/helpers.py +++ b/aiohttp/helpers.py @@ -60,6 +60,7 @@ PY_36 = sys.version_info >= (3, 6) PY_37 = sys.version_info >= (3, 7) PY_38 = sys.version_info >= (3, 8) +PY_310 = sys.version_info >= (3, 10) if not PY_37: import idna_ssl # type: ignore[import] diff --git a/aiohttp/test_utils.py b/aiohttp/test_utils.py index d4a2f3f6127..495dcc8f403 100644 --- a/aiohttp/test_utils.py +++ b/aiohttp/test_utils.py @@ -443,8 +443,10 @@ def get_app(self) -> Application: raise RuntimeError("Did you forget to define get_application()?") def setUp(self) -> None: - if PY_38: - self.loop = asyncio.get_event_loop() + try: + self.loop = asyncio.get_running_loop() + except RuntimeError: + self.loop = asyncio.get_event_loop_policy().get_event_loop() self.loop.run_until_complete(self.setUpAsync()) diff --git a/requirements/dev.txt b/requirements/dev.txt index fed2837085d..6591d6dbcb6 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -224,7 +224,7 @@ requests==2.25.1 # sphinx setuptools-git==1.2 # via -r requirements/test.txt -six==1.15.0 +six==1.16.0 # via # -r requirements/lint.txt # cryptography @@ -300,7 +300,7 @@ yarl==1.7.0 # via -r requirements/base.txt # The following packages are considered to be unsafe in a requirements file: -setuptools==51.3.1 +setuptools==57.4.0 # via # blockdiag # gunicorn diff --git a/requirements/lint.txt b/requirements/lint.txt index 89b4568af32..be57cf3ab21 100644 --- a/requirements/lint.txt +++ b/requirements/lint.txt @@ -68,7 +68,7 @@ pyyaml==5.4.1 # via pre-commit regex==2020.11.13 # via black -six==1.15.0 +six==1.16.0 # via virtualenv toml==0.10.2 # via diff --git a/tests/conftest.py b/tests/conftest.py index 85f482b56d6..e27817b640a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -51,7 +51,7 @@ def tls_certificate(tls_certificate_authority): @pytest.fixture def ssl_ctx(tls_certificate): - ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) tls_certificate.configure_cert(ssl_ctx) return ssl_ctx diff --git a/tests/test_client_functional.py b/tests/test_client_functional.py index bbe680ef733..b0750fa561e 100644 --- a/tests/test_client_functional.py +++ b/tests/test_client_functional.py @@ -2340,7 +2340,7 @@ def create(url, srv): cert = tls_certificate_authority.issue_cert( url.host, "localhost", "127.0.0.1" ) - ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) cert.configure_cert(ssl_ctx) kwargs["ssl"] = ssl_ctx return aiohttp_server(app, **kwargs) diff --git a/tests/test_connector.py b/tests/test_connector.py index 09841923e16..52dd83bbd68 100644 --- a/tests/test_connector.py +++ b/tests/test_connector.py @@ -84,7 +84,11 @@ async def go(app): def create_mocked_conn(conn_closing_result=None, **kwargs): - loop = asyncio.get_event_loop() + try: + loop = asyncio.get_running_loop() + except RuntimeError: + loop = asyncio.get_event_loop_policy().get_event_loop() + proto = mock.Mock(**kwargs) proto.closed = loop.create_future() proto.closed.set_result(conn_closing_result) @@ -1262,7 +1266,7 @@ async def test___get_ssl_context1(loop) -> None: async def test___get_ssl_context2(loop) -> None: - ctx = ssl.SSLContext() + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) conn = aiohttp.TCPConnector(loop=loop) req = mock.Mock() req.is_ssl.return_value = True @@ -1271,7 +1275,7 @@ async def test___get_ssl_context2(loop) -> None: async def test___get_ssl_context3(loop) -> None: - ctx = ssl.SSLContext() + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) conn = aiohttp.TCPConnector(loop=loop, ssl=ctx) req = mock.Mock() req.is_ssl.return_value = True @@ -1280,7 +1284,7 @@ async def test___get_ssl_context3(loop) -> None: async def test___get_ssl_context4(loop) -> None: - ctx = ssl.SSLContext() + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) conn = aiohttp.TCPConnector(loop=loop, ssl=ctx) req = mock.Mock() req.is_ssl.return_value = True @@ -1289,7 +1293,7 @@ async def test___get_ssl_context4(loop) -> None: async def test___get_ssl_context5(loop) -> None: - ctx = ssl.SSLContext() + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) conn = aiohttp.TCPConnector(loop=loop, ssl=ctx) req = mock.Mock() req.is_ssl.return_value = True diff --git a/tests/test_loop.py b/tests/test_loop.py index 914b8f1fc4d..8880dd35802 100644 --- a/tests/test_loop.py +++ b/tests/test_loop.py @@ -35,8 +35,8 @@ async def test_on_startup_hook(self) -> None: self.assertTrue(self.on_startup_called) def test_default_loop(self) -> None: - self.assertIs(self.loop, asyncio.get_event_loop()) + self.assertIs(self.loop, asyncio.get_event_loop_policy().get_event_loop()) def test_default_loop(loop) -> None: - assert asyncio.get_event_loop() is loop + assert asyncio.get_event_loop_policy().get_event_loop() is loop diff --git a/tests/test_proxy_functional.py b/tests/test_proxy_functional.py index 7d323784ce7..2f4ee56f0a7 100644 --- a/tests/test_proxy_functional.py +++ b/tests/test_proxy_functional.py @@ -1,6 +1,8 @@ import asyncio +import functools import os import pathlib +import platform from re import match as match_regex from unittest import mock from uuid import uuid4 @@ -11,8 +13,18 @@ import aiohttp from aiohttp import web -from aiohttp.client_exceptions import ClientConnectionError -from aiohttp.helpers import IS_MACOS, IS_WINDOWS, PY_37 +from aiohttp.client_exceptions import ClientConnectionError, ClientProxyConnectionError +from aiohttp.helpers import IS_MACOS, IS_WINDOWS, PY_37, PY_310 + +secure_proxy_xfail_under_py310_except_macos = functools.partial( + pytest.mark.xfail, + PY_310 and platform.system() != "Darwin", + reason=( + "The secure proxy fixture does not seem to work " + "under Python 3.10 on Linux or Windows. " + "See https://github.com/abhinavsingh/proxy.py/issues/622." + ), +) ASYNCIO_SUPPORTS_TLS_IN_TLS = hasattr( asyncio.sslproto._SSLProtocolTransport, @@ -113,6 +125,7 @@ def _pretend_asyncio_supports_tls_in_tls( ) +@secure_proxy_xfail_under_py310_except_macos(raises=ClientProxyConnectionError) @pytest.mark.parametrize( "web_server_endpoint_type", ( @@ -152,6 +165,7 @@ async def test_secure_https_proxy_absolute_path( await conn.close() +@secure_proxy_xfail_under_py310_except_macos(raises=AssertionError) @pytest.mark.xfail( not PY_37, raises=RuntimeError, diff --git a/tests/test_worker.py b/tests/test_worker.py index 64cff82e643..2e8b2c45d7e 100644 --- a/tests/test_worker.py +++ b/tests/test_worker.py @@ -252,7 +252,7 @@ def test__create_ssl_context_without_certs_and_ciphers( worker, tls_certificate_pem_path, ) -> None: - worker.cfg.ssl_version = ssl.PROTOCOL_SSLv23 + worker.cfg.ssl_version = ssl.PROTOCOL_TLS_CLIENT worker.cfg.cert_reqs = ssl.CERT_OPTIONAL worker.cfg.certfile = tls_certificate_pem_path worker.cfg.keyfile = tls_certificate_pem_path @@ -266,7 +266,7 @@ def test__create_ssl_context_with_ciphers( worker, tls_certificate_pem_path, ) -> None: - worker.cfg.ssl_version = ssl.PROTOCOL_SSLv23 + worker.cfg.ssl_version = ssl.PROTOCOL_TLS_CLIENT worker.cfg.cert_reqs = ssl.CERT_OPTIONAL worker.cfg.certfile = tls_certificate_pem_path worker.cfg.keyfile = tls_certificate_pem_path @@ -281,7 +281,7 @@ def test__create_ssl_context_with_ca_certs( tls_ca_certificate_pem_path, tls_certificate_pem_path, ) -> None: - worker.cfg.ssl_version = ssl.PROTOCOL_SSLv23 + worker.cfg.ssl_version = ssl.PROTOCOL_TLS_CLIENT worker.cfg.cert_reqs = ssl.CERT_OPTIONAL worker.cfg.certfile = tls_certificate_pem_path worker.cfg.keyfile = tls_certificate_pem_path