Skip to content

Commit d48bfea

Browse files
Merge branch 'master' into patch-1
2 parents 71be6bf + 3cfabe2 commit d48bfea

File tree

8 files changed

+45
-19
lines changed

8 files changed

+45
-19
lines changed

.github/workflows/auto-merge.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
steps:
1313
- name: Dependabot metadata
1414
id: metadata
15-
uses: dependabot/fetch-metadata@v1.1.1
15+
uses: dependabot/fetch-metadata@v1.3.4
1616
with:
1717
github-token: "${{ secrets.GITHUB_TOKEN }}"
1818
- name: Enable auto-merge for Dependabot PRs

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ jobs:
4949
needs: lint
5050
strategy:
5151
matrix:
52-
pyver: ["3.7", "3.8", "3.9", "3.10", "3.11-dev"]
52+
pyver: ["3.7", "3.8", "3.9", "3.10", "3.11"]
5353
os: [ubuntu, macos, windows]
5454
include:
5555
- pyver: pypy-3.9
@@ -84,7 +84,7 @@ jobs:
8484
python -m pytest tests
8585
python -m coverage xml
8686
- name: Upload coverage
87-
uses: codecov/codecov-action@v1
87+
uses: codecov/codecov-action@v3
8888
with:
8989
file: ./coverage.xml
9090
flags: unit
@@ -110,7 +110,7 @@ jobs:
110110
run:
111111
python -m build
112112
- name: Make Release
113-
uses: aio-libs/create-release@v1.2.3
113+
uses: aio-libs/create-release@v1.6.6
114114
with:
115115
changes_file: CHANGES.rst
116116
name: async-timeout

.pre-commit-config.yaml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: 'v4.3.0'
3+
rev: 'v4.4.0'
44
hooks:
55
- id: check-merge-conflict
66
exclude: "rst$"
77
- repo: https://github.com/asottile/yesqa
8-
rev: v1.3.0
8+
rev: v1.5.0
99
hooks:
1010
- id: yesqa
1111
- repo: https://github.com/PyCQA/isort
12-
rev: '5.10.1'
12+
rev: '5.12.0'
1313
hooks:
1414
- id: isort
1515
- repo: https://github.com/psf/black
16-
rev: '22.3.0'
16+
rev: '23.7.0'
1717
hooks:
1818
- id: black
1919
language_version: python3 # Should be a command that runs python3.6+
2020
- repo: https://github.com/pre-commit/pre-commit-hooks
21-
rev: 'v4.3.0'
21+
rev: 'v4.4.0'
2222
hooks:
2323
- id: check-case-conflict
2424
- id: check-json
@@ -35,17 +35,17 @@ repos:
3535
- id: debug-statements
3636
# Another entry is required to apply file-contents-sorter to another file
3737
- repo: https://github.com/pre-commit/pre-commit-hooks
38-
rev: 'v4.3.0'
38+
rev: 'v4.4.0'
3939
hooks:
4040
- id: file-contents-sorter
4141
files: |
4242
.gitignore
4343
- repo: https://github.com/asottile/pyupgrade
44-
rev: 'v2.34.0'
44+
rev: 'v3.10.1'
4545
hooks:
4646
- id: pyupgrade
4747
args: ['--py36-plus']
4848
- repo: https://github.com/PyCQA/flake8
49-
rev: '4.0.1'
49+
rev: '6.1.0'
5050
hooks:
5151
- id: flake8

CHANGES/333.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add support for Python 3.11.

CHANGES/362.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix compatibility with asyncio.timeout() on python 3.11+.

async_timeout/__init__.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,17 @@
1212
from typing_extensions import final
1313

1414

15+
if sys.version_info >= (3, 11):
16+
17+
def _uncancel_task(task: "asyncio.Task[object]") -> None:
18+
task.uncancel()
19+
20+
else:
21+
22+
def _uncancel_task(task: "asyncio.Task[object]") -> None:
23+
pass
24+
25+
1526
__version__ = "4.0.2"
1627

1728

@@ -84,14 +95,15 @@ class Timeout:
8495
# The purpose is to time out as soon as possible
8596
# without waiting for the next await expression.
8697

87-
__slots__ = ("_deadline", "_loop", "_state", "_timeout_handler")
98+
__slots__ = ("_deadline", "_loop", "_state", "_timeout_handler", "_task")
8899

89100
def __init__(
90101
self, deadline: Optional[float], loop: asyncio.AbstractEventLoop
91102
) -> None:
92103
self._loop = loop
93104
self._state = _State.INIT
94105

106+
self._task: Optional["asyncio.Task[object]"] = None
95107
self._timeout_handler = None # type: Optional[asyncio.Handle]
96108
if deadline is None:
97109
self._deadline = None # type: Optional[float]
@@ -147,6 +159,7 @@ def reject(self) -> None:
147159
self._reject()
148160

149161
def _reject(self) -> None:
162+
self._task = None
150163
if self._timeout_handler is not None:
151164
self._timeout_handler.cancel()
152165
self._timeout_handler = None
@@ -194,11 +207,11 @@ def _reschedule(self) -> None:
194207
if self._timeout_handler is not None:
195208
self._timeout_handler.cancel()
196209

197-
task = asyncio.current_task()
210+
self._task = asyncio.current_task()
198211
if deadline <= now:
199-
self._timeout_handler = self._loop.call_soon(self._on_timeout, task)
212+
self._timeout_handler = self._loop.call_soon(self._on_timeout)
200213
else:
201-
self._timeout_handler = self._loop.call_at(deadline, self._on_timeout, task)
214+
self._timeout_handler = self._loop.call_at(deadline, self._on_timeout)
202215

203216
def _do_enter(self) -> None:
204217
if self._state != _State.INIT:
@@ -208,15 +221,19 @@ def _do_enter(self) -> None:
208221

209222
def _do_exit(self, exc_type: Optional[Type[BaseException]]) -> None:
210223
if exc_type is asyncio.CancelledError and self._state == _State.TIMEOUT:
224+
assert self._task is not None
225+
_uncancel_task(self._task)
211226
self._timeout_handler = None
227+
self._task = None
212228
raise asyncio.TimeoutError
213229
# timeout has not expired
214230
self._state = _State.EXIT
215231
self._reject()
216232
return None
217233

218-
def _on_timeout(self, task: "asyncio.Task[None]") -> None:
219-
task.cancel()
234+
def _on_timeout(self) -> None:
235+
assert self._task is not None
236+
self._task.cancel()
220237
self._state = _State.TIMEOUT
221238
# drop the reference early
222239
self._timeout_handler = None

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ classifiers =
3232
Programming Language :: Python :: 3.8
3333
Programming Language :: Python :: 3.9
3434
Programming Language :: Python :: 3.10
35+
Programming Language :: Python :: 3.11
3536

3637
[options]
3738
python_requires = >=3.7

tests/test_timeout.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import asyncio
2+
import sys
23
import time
34
from functools import wraps
45
from typing import Any, Callable, List, TypeVar
@@ -39,6 +40,10 @@ async def long_running_task() -> None:
3940
await long_running_task()
4041
assert t._loop is asyncio.get_event_loop()
4142
assert canceled_raised, "CancelledError was not raised"
43+
if sys.version_info >= (3, 11):
44+
task = asyncio.current_task()
45+
assert task is not None
46+
assert not task.cancelling()
4247

4348

4449
@pytest.mark.asyncio
@@ -144,7 +149,6 @@ async def test_timeout_time() -> None:
144149

145150
@pytest.mark.asyncio
146151
async def test_outer_coro_is_not_cancelled() -> None:
147-
148152
has_timeout = False
149153

150154
async def outer() -> None:
@@ -159,6 +163,8 @@ async def outer() -> None:
159163
await task
160164
assert has_timeout
161165
assert not task.cancelled()
166+
if sys.version_info >= (3, 11):
167+
assert not task.cancelling()
162168
assert task.done()
163169

164170

0 commit comments

Comments
 (0)