From c1bafea3e81c737ee69c33cda428af9537d2dfde Mon Sep 17 00:00:00 2001 From: Nachtalb <9467802+Nachtalb@users.noreply.github.com> Date: Sat, 18 Nov 2023 20:24:19 +0100 Subject: [PATCH] Upgrade to py12 (#1354) * Upgrade to py12 compatible aiohttp beta version * Fix uvloop deprecation warning causing pytest not to run * Fix test due to asyncio task scheduling race condition * Fix test_state_in_unknown_class for Python 3.12+ due to PEP 678 changes * Add Python 3.12 support in GitHub Actions and project configurations * Add changelog entry --------- Co-authored-by: Alex Root Junior --- .github/workflows/tests.yml | 1 + CHANGES/1354.misc.rst | 1 + aiogram/__init__.py | 4 +++- pyproject.toml | 7 ++++--- tests/test_fsm/test_state.py | 19 ++++++++++++++++--- tests/test_webhook/test_aiohtt_server.py | 10 ++++++++++ 6 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 CHANGES/1354.misc.rst diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d238a558..3097b6bd 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -33,6 +33,7 @@ jobs: - '3.9' - '3.10' - '3.11' + - '3.12' - 'pypy3.8' - 'pypy3.9' diff --git a/CHANGES/1354.misc.rst b/CHANGES/1354.misc.rst new file mode 100644 index 00000000..42b4cfa5 --- /dev/null +++ b/CHANGES/1354.misc.rst @@ -0,0 +1 @@ +Introduce Python 3.12 support diff --git a/aiogram/__init__.py b/aiogram/__init__.py index 31d1b16b..b945226f 100644 --- a/aiogram/__init__.py +++ b/aiogram/__init__.py @@ -15,8 +15,10 @@ from .utils.text_decorations import markdown_decoration as md with suppress(ImportError): import uvloop as _uvloop + import asyncio + + asyncio.set_event_loop_policy(_uvloop.EventLoopPolicy()) - _uvloop.install() # type: ignore[attr-defined,unused-ignore] F = MagicFilter() flags = FlagGenerator() diff --git a/pyproject.toml b/pyproject.toml index 0557223b..2d17be3b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,6 +34,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 :: Implementation :: PyPy", "Topic :: Software Development :: Libraries :: Application Frameworks", "Topic :: Software Development :: Libraries :: Python Modules", @@ -41,7 +42,7 @@ classifiers = [ ] dependencies = [ "magic-filter>=1.0.12,<1.1", - "aiohttp~=3.8.5", + "aiohttp~=3.9.0", "pydantic>=2.4.1,<2.6", "aiofiles~=23.2.1", "certifi>=2023.7.22", @@ -144,7 +145,7 @@ features = [ serve = "sphinx-autobuild --watch aiogram/ --watch CHANGELOG.rst --watch README.rst docs/ docs/_build/ {args}" [tool.hatch.envs.dev] -python = "3.11" +python = "3.12" features = [ "dev", "fast", @@ -185,7 +186,7 @@ view-cov = "google-chrome-stable reports/py{matrix:python}/coverage/index.html" [[tool.hatch.envs.test.matrix]] -python = ["38", "39", "310", "311"] +python = ["38", "39", "310", "311", "312"] [tool.ruff] line-length = 99 diff --git a/tests/test_fsm/test_state.py b/tests/test_fsm/test_state.py index 159b20ca..dd240946 100644 --- a/tests/test_fsm/test_state.py +++ b/tests/test_fsm/test_state.py @@ -1,7 +1,10 @@ import pytest +import sys from aiogram.fsm.state import State, StatesGroup, any_state +PY312_OR_GREATER = sys.version_info >= (3, 12) + class TestState: def test_empty(self): @@ -72,10 +75,20 @@ class TestState: assert state(None, check) is result def test_state_in_unknown_class(self): - with pytest.raises(RuntimeError): + if PY312_OR_GREATER: + # Python 3.12+ does not wrap __set_name__ exceptions with RuntimeError anymore as part + # of PEP 678. See "Other Language Changes" in the changelogs: + # https://docs.python.org/3/whatsnew/3.12.html + with pytest.raises(ValueError): - class MyClass: - state1 = State() + class MyClass: + state1 = State() + + else: + with pytest.raises(RuntimeError): + + class MyClass: + state1 = State() class TestStatesGroup: diff --git a/tests/test_webhook/test_aiohtt_server.py b/tests/test_webhook/test_aiohtt_server.py index 4e3f6658..f29895ba 100644 --- a/tests/test_webhook/test_aiohtt_server.py +++ b/tests/test_webhook/test_aiohtt_server.py @@ -181,10 +181,20 @@ class TestSimpleRequestHandler: "aiogram.dispatcher.dispatcher.Dispatcher.silent_call_request", new_callable=AsyncMock, ) as mocked_silent_call_request: + method_called_event = asyncio.Event() + mocked_silent_call_request.side_effect = ( + lambda *args, **kwargs: method_called_event.set() + ) + handler_event.clear() resp = await self.make_reqest(client=client) assert resp.status == 200 await asyncio.wait_for(handler_event.wait(), timeout=1) + await asyncio.wait_for(method_called_event.wait(), timeout=1) + # Python 3.12 had some changes to asyncio which make it quite a bit faster. But + # probably because of that the assert_awaited call is consistently scheduled before the + # silent_call_request call - failing the test. So we wait for the method to be called + # before asserting if it has been awaited. mocked_silent_call_request.assert_awaited() result = await resp.json() assert not result