From b45e3da1b76a67a45f897d22c33af82ff3d2a424 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 9 Aug 2023 13:22:58 +0100 Subject: [PATCH 1/3] [pre-commit.ci] pre-commit autoupdate (#319) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/pre-commit/pre-commit-hooks: v4.3.0 → v4.4.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.3.0...v4.4.0) - [github.com/asottile/yesqa: v1.3.0 → v1.5.0](https://github.com/asottile/yesqa/compare/v1.3.0...v1.5.0) - [github.com/PyCQA/isort: 5.10.1 → 5.12.0](https://github.com/PyCQA/isort/compare/5.10.1...5.12.0) - [github.com/psf/black: 22.3.0 → 23.7.0](https://github.com/psf/black/compare/22.3.0...23.7.0) - [github.com/pre-commit/pre-commit-hooks: v4.3.0 → v4.4.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.3.0...v4.4.0) - [github.com/pre-commit/pre-commit-hooks: v4.3.0 → v4.4.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.3.0...v4.4.0) - [github.com/asottile/pyupgrade: v2.34.0 → v3.10.1](https://github.com/asottile/pyupgrade/compare/v2.34.0...v3.10.1) - [github.com/PyCQA/flake8: 4.0.1 → 6.1.0](https://github.com/PyCQA/flake8/compare/4.0.1...6.1.0) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 16 ++++++++-------- tests/test_timeout.py | 1 - 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 56315f9..2065cab 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,24 +1,24 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: 'v4.3.0' + rev: 'v4.4.0' hooks: - id: check-merge-conflict exclude: "rst$" - repo: https://github.com/asottile/yesqa - rev: v1.3.0 + rev: v1.5.0 hooks: - id: yesqa - repo: https://github.com/PyCQA/isort - rev: '5.10.1' + rev: '5.12.0' hooks: - id: isort - repo: https://github.com/psf/black - rev: '22.3.0' + rev: '23.7.0' hooks: - id: black language_version: python3 # Should be a command that runs python3.6+ - repo: https://github.com/pre-commit/pre-commit-hooks - rev: 'v4.3.0' + rev: 'v4.4.0' hooks: - id: check-case-conflict - id: check-json @@ -35,17 +35,17 @@ repos: - id: debug-statements # Another entry is required to apply file-contents-sorter to another file - repo: https://github.com/pre-commit/pre-commit-hooks - rev: 'v4.3.0' + rev: 'v4.4.0' hooks: - id: file-contents-sorter files: | .gitignore - repo: https://github.com/asottile/pyupgrade - rev: 'v2.34.0' + rev: 'v3.10.1' hooks: - id: pyupgrade args: ['--py36-plus'] - repo: https://github.com/PyCQA/flake8 - rev: '4.0.1' + rev: '6.1.0' hooks: - id: flake8 diff --git a/tests/test_timeout.py b/tests/test_timeout.py index d32c5fd..1bf267b 100644 --- a/tests/test_timeout.py +++ b/tests/test_timeout.py @@ -144,7 +144,6 @@ async def test_timeout_time() -> None: @pytest.mark.asyncio async def test_outer_coro_is_not_cancelled() -> None: - has_timeout = False async def outer() -> None: From adf9e28f6a91117ff02b2635c6de8ed2cec993c0 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Wed, 9 Aug 2023 14:23:35 +0200 Subject: [PATCH 2/3] Add support for Python 3.11 (#333) --- .github/workflows/auto-merge.yml | 2 +- .github/workflows/ci.yml | 6 +++--- CHANGES/333.feature | 1 + setup.cfg | 1 + 4 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 CHANGES/333.feature diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index 5a9408a..8b436cf 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Dependabot metadata id: metadata - uses: dependabot/fetch-metadata@v1.1.1 + uses: dependabot/fetch-metadata@v1.3.4 with: github-token: "${{ secrets.GITHUB_TOKEN }}" - name: Enable auto-merge for Dependabot PRs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6cbe882..7beefab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,7 +49,7 @@ jobs: needs: lint strategy: matrix: - pyver: ["3.7", "3.8", "3.9", "3.10", "3.11-dev"] + pyver: ["3.7", "3.8", "3.9", "3.10", "3.11"] os: [ubuntu, macos, windows] include: - pyver: pypy-3.9 @@ -84,7 +84,7 @@ jobs: python -m pytest tests python -m coverage xml - name: Upload coverage - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v3 with: file: ./coverage.xml flags: unit @@ -110,7 +110,7 @@ jobs: run: python -m build - name: Make Release - uses: aio-libs/create-release@v1.2.3 + uses: aio-libs/create-release@v1.6.6 with: changes_file: CHANGES.rst name: async-timeout diff --git a/CHANGES/333.feature b/CHANGES/333.feature new file mode 100644 index 0000000..5d1d984 --- /dev/null +++ b/CHANGES/333.feature @@ -0,0 +1 @@ +Add support for Python 3.11. diff --git a/setup.cfg b/setup.cfg index 6b7a970..a363ce7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -32,6 +32,7 @@ classifiers = Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 [options] python_requires = >=3.7 From 3cfabe24a10a0bd5cea13a682881503255911ab9 Mon Sep 17 00:00:00 2001 From: Tristan King Date: Wed, 9 Aug 2023 19:08:23 +0200 Subject: [PATCH 3/3] Uncancel tasks after timeout in python 3.11 (#363) --- CHANGES/362.feature | 1 + async_timeout/__init__.py | 29 +++++++++++++++++++++++------ tests/test_timeout.py | 7 +++++++ 3 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 CHANGES/362.feature diff --git a/CHANGES/362.feature b/CHANGES/362.feature new file mode 100644 index 0000000..f547d13 --- /dev/null +++ b/CHANGES/362.feature @@ -0,0 +1 @@ +Fix compatibility with asyncio.timeout() on python 3.11+. diff --git a/async_timeout/__init__.py b/async_timeout/__init__.py index 4188a98..c39a170 100644 --- a/async_timeout/__init__.py +++ b/async_timeout/__init__.py @@ -12,6 +12,17 @@ from typing_extensions import final +if sys.version_info >= (3, 11): + + def _uncancel_task(task: "asyncio.Task[object]") -> None: + task.uncancel() + +else: + + def _uncancel_task(task: "asyncio.Task[object]") -> None: + pass + + __version__ = "4.0.2" @@ -84,7 +95,7 @@ class Timeout: # The purpose is to time out as soon as possible # without waiting for the next await expression. - __slots__ = ("_deadline", "_loop", "_state", "_timeout_handler") + __slots__ = ("_deadline", "_loop", "_state", "_timeout_handler", "_task") def __init__( self, deadline: Optional[float], loop: asyncio.AbstractEventLoop @@ -92,6 +103,7 @@ def __init__( self._loop = loop self._state = _State.INIT + self._task: Optional["asyncio.Task[object]"] = None self._timeout_handler = None # type: Optional[asyncio.Handle] if deadline is None: self._deadline = None # type: Optional[float] @@ -147,6 +159,7 @@ def reject(self) -> None: self._reject() def _reject(self) -> None: + self._task = None if self._timeout_handler is not None: self._timeout_handler.cancel() self._timeout_handler = None @@ -194,11 +207,11 @@ def _reschedule(self) -> None: if self._timeout_handler is not None: self._timeout_handler.cancel() - task = asyncio.current_task() + self._task = asyncio.current_task() if deadline <= now: - self._timeout_handler = self._loop.call_soon(self._on_timeout, task) + self._timeout_handler = self._loop.call_soon(self._on_timeout) else: - self._timeout_handler = self._loop.call_at(deadline, self._on_timeout, task) + self._timeout_handler = self._loop.call_at(deadline, self._on_timeout) def _do_enter(self) -> None: if self._state != _State.INIT: @@ -208,15 +221,19 @@ def _do_enter(self) -> None: def _do_exit(self, exc_type: Optional[Type[BaseException]]) -> None: if exc_type is asyncio.CancelledError and self._state == _State.TIMEOUT: + assert self._task is not None + _uncancel_task(self._task) self._timeout_handler = None + self._task = None raise asyncio.TimeoutError # timeout has not expired self._state = _State.EXIT self._reject() return None - def _on_timeout(self, task: "asyncio.Task[None]") -> None: - task.cancel() + def _on_timeout(self) -> None: + assert self._task is not None + self._task.cancel() self._state = _State.TIMEOUT # drop the reference early self._timeout_handler = None diff --git a/tests/test_timeout.py b/tests/test_timeout.py index 1bf267b..7c687ac 100644 --- a/tests/test_timeout.py +++ b/tests/test_timeout.py @@ -1,4 +1,5 @@ import asyncio +import sys import time from functools import wraps from typing import Any, Callable, List, TypeVar @@ -39,6 +40,10 @@ async def long_running_task() -> None: await long_running_task() assert t._loop is asyncio.get_event_loop() assert canceled_raised, "CancelledError was not raised" + if sys.version_info >= (3, 11): + task = asyncio.current_task() + assert task is not None + assert not task.cancelling() @pytest.mark.asyncio @@ -158,6 +163,8 @@ async def outer() -> None: await task assert has_timeout assert not task.cancelled() + if sys.version_info >= (3, 11): + assert not task.cancelling() assert task.done()