Skip to content

Commit 8c29bbd

Browse files
authored
Merge branch 'master' into query-logging
2 parents a9c6182 + b7ffab6 commit 8c29bbd

33 files changed

+862
-300
lines changed

.flake8

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[flake8]
22
ignore = E402,E731,W503,W504,E252
3-
exclude = .git,__pycache__,build,dist,.eggs,.github,.local,.venv
3+
exclude = .git,__pycache__,build,dist,.eggs,.github,.local,.venv,.tox

.github/workflows/release.yml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
PIP_DISABLE_PIP_VERSION_CHECK: 1
5151

5252
steps:
53-
- uses: actions/checkout@v3
53+
- uses: actions/checkout@v4
5454
with:
5555
fetch-depth: 50
5656
submodules: true
@@ -76,11 +76,11 @@ jobs:
7676
outputs:
7777
include: ${{ steps.set-matrix.outputs.include }}
7878
steps:
79-
- uses: actions/checkout@v3
79+
- uses: actions/checkout@v4
8080
- uses: actions/setup-python@v4
8181
with:
8282
python-version: "3.x"
83-
- run: pip install cibuildwheel==2.13.1
83+
- run: pip install cibuildwheel==2.16.2
8484
- id: set-matrix
8585
run: |
8686
MATRIX_INCLUDE=$(
@@ -109,7 +109,7 @@ jobs:
109109
PIP_DISABLE_PIP_VERSION_CHECK: 1
110110

111111
steps:
112-
- uses: actions/checkout@v3
112+
- uses: actions/checkout@v4
113113
with:
114114
fetch-depth: 50
115115
submodules: true
@@ -118,7 +118,7 @@ jobs:
118118
if: runner.os == 'Linux'
119119
uses: docker/setup-qemu-action@v2
120120

121-
- uses: pypa/cibuildwheel@v2.13.1
121+
- uses: pypa/cibuildwheel@fff9ec32ed25a9c576750c91e06b410ed0c15db7 # v2.16.2
122122
with:
123123
only: ${{ matrix.only }}
124124
env:
@@ -138,7 +138,7 @@ jobs:
138138

139139
steps:
140140
- name: Checkout source
141-
uses: actions/checkout@v3
141+
uses: actions/checkout@v4
142142
with:
143143
fetch-depth: 5
144144
submodules: true
@@ -154,7 +154,7 @@ jobs:
154154
make htmldocs
155155
156156
- name: Checkout gh-pages
157-
uses: actions/checkout@v3
157+
uses: actions/checkout@v4
158158
with:
159159
fetch-depth: 5
160160
ref: gh-pages
@@ -180,7 +180,7 @@ jobs:
180180
runs-on: ubuntu-latest
181181

182182
steps:
183-
- uses: actions/checkout@v3
183+
- uses: actions/checkout@v4
184184
with:
185185
fetch-depth: 5
186186
submodules: false

.github/workflows/tests.yml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@ jobs:
1717
# job.
1818
strategy:
1919
matrix:
20-
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
20+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
2121
os: [ubuntu-latest, macos-latest, windows-latest]
2222
loop: [asyncio, uvloop]
2323
exclude:
2424
# uvloop does not support windows
2525
- loop: uvloop
2626
os: windows-latest
27+
# No 3.12 release yet
28+
- loop: uvloop
29+
python-version: "3.12"
2730

2831
runs-on: ${{ matrix.os }}
2932

@@ -35,7 +38,7 @@ jobs:
3538
PIP_DISABLE_PIP_VERSION_CHECK: 1
3639

3740
steps:
38-
- uses: actions/checkout@v3
41+
- uses: actions/checkout@v4
3942
with:
4043
fetch-depth: 50
4144
submodules: true
@@ -76,15 +79,15 @@ jobs:
7679
test-postgres:
7780
strategy:
7881
matrix:
79-
postgres-version: ["9.5", "9.6", "10", "11", "12", "13", "14", "15"]
82+
postgres-version: ["9.5", "9.6", "10", "11", "12", "13", "14", "15", "16"]
8083

8184
runs-on: ubuntu-latest
8285

8386
env:
8487
PIP_DISABLE_PIP_VERSION_CHECK: 1
8588

8689
steps:
87-
- uses: actions/checkout@v3
90+
- uses: actions/checkout@v4
8891
with:
8992
fetch-depth: 50
9093
submodules: true

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ of PostgreSQL server binary protocol for use with Python's ``asyncio``
1313
framework. You can read more about asyncpg in an introductory
1414
`blog post <http://magic.io/blog/asyncpg-1m-rows-from-postgres-to-python/>`_.
1515

16-
asyncpg requires Python 3.7 or later and is supported for PostgreSQL
17-
versions 9.5 to 15. Older PostgreSQL versions or other databases implementing
16+
asyncpg requires Python 3.8 or later and is supported for PostgreSQL
17+
versions 9.5 to 16. Older PostgreSQL versions or other databases implementing
1818
the PostgreSQL protocol *may* work, but are not being actively tested.
1919

2020

asyncpg/_asyncio_compat.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Backports from Python/Lib/asyncio for older Pythons
2+
#
3+
# Copyright (c) 2001-2023 Python Software Foundation; All Rights Reserved
4+
#
5+
# SPDX-License-Identifier: PSF-2.0
6+
7+
8+
import asyncio
9+
import functools
10+
import sys
11+
12+
if sys.version_info < (3, 11):
13+
from async_timeout import timeout as timeout_ctx
14+
else:
15+
from asyncio import timeout as timeout_ctx
16+
17+
18+
async def wait_for(fut, timeout):
19+
"""Wait for the single Future or coroutine to complete, with timeout.
20+
21+
Coroutine will be wrapped in Task.
22+
23+
Returns result of the Future or coroutine. When a timeout occurs,
24+
it cancels the task and raises TimeoutError. To avoid the task
25+
cancellation, wrap it in shield().
26+
27+
If the wait is cancelled, the task is also cancelled.
28+
29+
If the task supresses the cancellation and returns a value instead,
30+
that value is returned.
31+
32+
This function is a coroutine.
33+
"""
34+
# The special case for timeout <= 0 is for the following case:
35+
#
36+
# async def test_waitfor():
37+
# func_started = False
38+
#
39+
# async def func():
40+
# nonlocal func_started
41+
# func_started = True
42+
#
43+
# try:
44+
# await asyncio.wait_for(func(), 0)
45+
# except asyncio.TimeoutError:
46+
# assert not func_started
47+
# else:
48+
# assert False
49+
#
50+
# asyncio.run(test_waitfor())
51+
52+
if timeout is not None and timeout <= 0:
53+
fut = asyncio.ensure_future(fut)
54+
55+
if fut.done():
56+
return fut.result()
57+
58+
await _cancel_and_wait(fut)
59+
try:
60+
return fut.result()
61+
except asyncio.CancelledError as exc:
62+
raise TimeoutError from exc
63+
64+
async with timeout_ctx(timeout):
65+
return await fut
66+
67+
68+
async def _cancel_and_wait(fut):
69+
"""Cancel the *fut* future or task and wait until it completes."""
70+
71+
loop = asyncio.get_running_loop()
72+
waiter = loop.create_future()
73+
cb = functools.partial(_release_waiter, waiter)
74+
fut.add_done_callback(cb)
75+
76+
try:
77+
fut.cancel()
78+
# We cannot wait on *fut* directly to make
79+
# sure _cancel_and_wait itself is reliably cancellable.
80+
await waiter
81+
finally:
82+
fut.remove_done_callback(cb)
83+
84+
85+
def _release_waiter(waiter, *args):
86+
if not waiter.done():
87+
waiter.set_result(None)

asyncpg/compat.py

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
# the Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0
66

77

8-
import asyncio
98
import pathlib
109
import platform
1110
import typing
11+
import sys
1212

1313

1414
SYSTEM = platform.uname().system
@@ -49,17 +49,13 @@ async def wait_closed(stream):
4949
pass
5050

5151

52-
# Workaround for https://bugs.python.org/issue37658
53-
async def wait_for(fut, timeout):
54-
if timeout is None:
55-
return await fut
52+
if sys.version_info < (3, 12):
53+
from ._asyncio_compat import wait_for as wait_for # noqa: F401
54+
else:
55+
from asyncio import wait_for as wait_for # noqa: F401
5656

57-
fut = asyncio.ensure_future(fut)
5857

59-
try:
60-
return await asyncio.wait_for(fut, timeout)
61-
except asyncio.CancelledError:
62-
if fut.done():
63-
return fut.result()
64-
else:
65-
raise
58+
if sys.version_info < (3, 11):
59+
from ._asyncio_compat import timeout_ctx as timeout # noqa: F401
60+
else:
61+
from asyncio import timeout as timeout # noqa: F401

0 commit comments

Comments
 (0)