Skip to content

Commit 8321172

Browse files
committed
Python 3.13 + pyright typing
1 parent dac42f0 commit 8321172

File tree

6 files changed

+74
-78
lines changed

6 files changed

+74
-78
lines changed

.github/workflows/ci.yml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,26 @@ jobs:
1212
- uses: actions/setup-python@v5
1313
- run: pip install uv
1414
- run: uv venv
15-
- run: uv pip install --requirement pyproject.toml --all-extras
16-
- run: .venv/bin/ruff format --check .
17-
- run: .venv/bin/ruff check .
18-
- run: .venv/bin/mypy asyncio_connection_pool
15+
- run: uv sync --all-extras
16+
- run: uv run ruff format --check .
17+
- run: uv run ruff check .
18+
- run: uv run pyright asyncio_connection_pool
1919

2020
test:
2121
runs-on: ubuntu-latest
2222
strategy:
2323
matrix:
24-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
24+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
2525
steps:
2626
- uses: actions/checkout@v4
2727
- uses: actions/setup-python@v5
2828
with:
2929
python-version: ${{ matrix.python-version }}
3030
- run: pip install uv
3131
- run: uv venv
32-
- run: uv pip install --editable ".[dev,datadog,aioredis]"
33-
- run: .venv/bin/pytest --cov=asyncio_connection_pool --cov-branch --cov-config=.coveragerc
34-
- run: .venv/bin/codecov
35-
if: matrix.python-version == '3.11'
32+
- run: uv sync --all-extras
33+
- run: uv run pytest --cov=asyncio_connection_pool --cov-branch --cov-config=.coveragerc
34+
- run: uv run codecov
35+
if: matrix.python-version == '3.13'
3636
env:
3737
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

.github/workflows/release.yml

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,7 @@ jobs:
1515
- uses: actions/checkout@v4
1616
- uses: actions/setup-python@v5
1717
with:
18-
python-version: "3.12"
18+
python-version: "3.13"
1919
- run: pip install uv
20-
- run: uv venv
21-
- run: uv pip install --requirement pyproject.toml
22-
- run: uv pip install setuptools setuptools-scm wheel build
23-
- run: .venv/bin/python -m build --no-isolation
24-
- name: Publish package distributions to PyPI
25-
uses: pypa/gh-action-pypi-publish@release/v1
20+
- run: uv build
21+
- run: uv publish

asyncio_connection_pool/__init__.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import asyncio
2+
import collections
23
import inspect
34
from abc import ABC, abstractmethod
45
from contextlib import asynccontextmanager
5-
from typing import AsyncIterator, Awaitable, Generic, Optional, TypeVar
6+
from typing import AsyncIterator, Awaitable, Generic, Optional, TypeVar, cast
67

78
__all__ = "ConnectionPool", "ConnectionStrategy"
89
Conn = TypeVar("Conn")
@@ -77,7 +78,10 @@ def _total(self) -> int:
7778

7879
@property
7980
def _waiters(self) -> int:
80-
waiters = self.available._getters # type: ignore
81+
waiters: collections.deque[asyncio.Future[None]] = cast(
82+
collections.deque[asyncio.Future[None]],
83+
self.available._getters, # type: ignore
84+
)
8185
return sum(not (w.done() or w.cancelled()) for w in waiters)
8286

8387
async def _connection_maker(self) -> Conn:

asyncio_connection_pool/contrib/datadog.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,31 @@
11
from contextlib import AsyncExitStack, asynccontextmanager
2-
from typing import Any, AsyncIterator, Awaitable, Coroutine, TypeVar
2+
from typing import Any, AsyncIterator, Awaitable, Coroutine, Optional, TypeVar
33

44
from datadog.dogstatsd.base import statsd
5-
from ddtrace import tracer
5+
from ddtrace.trace import tracer
66

7-
from asyncio_connection_pool import ConnectionPool as _ConnectionPool
7+
from asyncio_connection_pool import (
8+
ConnectionPool as _ConnectionPool,
9+
)
10+
from asyncio_connection_pool import (
11+
ConnectionStrategy,
12+
)
813

914
__all__ = ("ConnectionPool",)
1015
Conn = TypeVar("Conn")
1116

1217

1318
class ConnectionPool(_ConnectionPool[Conn]):
14-
def __init__(self, service_name, *args, extra_tags=None, **kwargs):
15-
super().__init__(*args, **kwargs)
19+
def __init__(
20+
self,
21+
service_name: str,
22+
*,
23+
extra_tags: list[str] | None = None,
24+
strategy: ConnectionStrategy[Conn],
25+
max_size: int,
26+
burst_limit: Optional[int] = None,
27+
):
28+
super().__init__(strategy=strategy, max_size=max_size, burst_limit=burst_limit)
1629
self._connections_acquiring = 0
1730
self._service_name = service_name
1831
self._is_bursting = False

pyproject.toml

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
[build-system]
2-
requires = ["setuptools", "setuptools-scm"]
3-
build-backend = "setuptools.build_meta"
2+
requires = ["hatchling", "hatch-vcs"]
3+
build-backend = "hatchling.build"
4+
5+
[tool.hatch.version]
6+
source = "vcs"
47

58
[project]
69
name = "asyncio-connection-pool"
@@ -14,17 +17,17 @@ dependencies = []
1417

1518
[project.optional-dependencies]
1619
datadog = ["ddtrace", "datadog"]
20+
21+
[dependency-groups]
1722
dev = [
1823
"codecov~=2.1",
19-
"mypy~=1.9",
24+
"pyright>=1.1.396",
2025
"pytest~=8.1",
2126
"pytest-asyncio~=0.23",
2227
"pytest-cov~=5.0",
2328
"ruff~=0.4",
2429
]
2530

26-
[tool.setuptools_scm]
27-
2831
[tool.ruff.lint]
2932
select = [
3033
"B",
@@ -33,7 +36,6 @@ select = [
3336
"EM",
3437
"F",
3538
"I",
36-
"I",
3739
"N",
3840
"PT",
3941
"RSE",
@@ -47,22 +49,3 @@ preview = true
4749

4850
[tool.ruff.format]
4951
preview = true
50-
51-
[tool.mypy]
52-
ignore_missing_imports = true
53-
check_untyped_defs = true
54-
disallow_any_unimported = true
55-
disallow_any_decorated = true
56-
disallow_any_generics = true
57-
disallow_subclassing_any = true
58-
disallow_incomplete_defs = false
59-
disallow_untyped_decorators = true
60-
no_implicit_optional = true
61-
strict_optional = true
62-
warn_redundant_casts = true
63-
warn_unused_ignores = true
64-
warn_return_any = true
65-
warn_unreachable = true
66-
implicit_reexport = false
67-
strict_equality = true
68-
pretty = true

test/test_pool.py

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def close_connection(self, conn):
2929
pass
3030

3131

32-
@pytest.mark.asyncio()
32+
@pytest.mark.asyncio
3333
async def test_valid_burst_limit(pool_cls): # noqa: RUF029
3434
"""Test that invalid burst_limit values cause errors (only at construction time)"""
3535
strategy = RandomIntStrategy()
@@ -64,7 +64,7 @@ async def inc(self):
6464
self.n -= 1
6565

6666

67-
@pytest.mark.asyncio()
67+
@pytest.mark.asyncio
6868
async def test_concurrent_get_connection(pool_cls):
6969
"""Test handling several connection requests in a short time."""
7070

@@ -87,12 +87,12 @@ async def connection_holder():
8787
await asyncio.gather(*coros)
8888

8989
assert pool.in_use == 0
90-
assert (
91-
pool.available.qsize() == nworkers
92-
), f"{nworkers} connections should be allocated"
90+
assert pool.available.qsize() == nworkers, (
91+
f"{nworkers} connections should be allocated"
92+
)
9393

9494

95-
@pytest.mark.asyncio()
95+
@pytest.mark.asyncio
9696
async def test_currently_allocating(pool_cls):
9797
"""Test that currently_allocating is accurate."""
9898

@@ -122,22 +122,22 @@ async def worker():
122122
await counter.wait()
123123
await asyncio.sleep(0)
124124

125-
assert (
126-
pool.currently_allocating == nworkers
127-
), f"{nworkers} workers are waiting for a connection"
125+
assert pool.currently_allocating == nworkers, (
126+
f"{nworkers} workers are waiting for a connection"
127+
)
128128
ev.set() # allow the workers to get their connections
129129
await counter2.wait()
130130
assert pool.currently_allocating == 0
131131
assert pool.in_use == nworkers, "all workers should have their connections now"
132132
ev2.set()
133133
await asyncio.gather(*coros)
134134
assert pool.in_use == 0
135-
assert (
136-
pool.available.qsize() == nworkers
137-
), "all workers should have returned their connections"
135+
assert pool.available.qsize() == nworkers, (
136+
"all workers should have returned their connections"
137+
)
138138

139139

140-
@pytest.mark.asyncio()
140+
@pytest.mark.asyncio
141141
async def test_burst(pool_cls):
142142
"""Test that bursting works when enabled and doesn't when not."""
143143

@@ -189,24 +189,24 @@ async def waiting_worker():
189189
assert pool._waiters == 1, "Worker should be waiting, we're at burst_limit already"
190190
burst_event.set() # Allow worker holding burst connection to finish
191191
await burst_worker # Wait for it to release the connection
192-
assert (
193-
not did_call_close_connection.is_set()
194-
), "Did not churn the burst connection while there was a waiter"
192+
assert not did_call_close_connection.is_set(), (
193+
"Did not churn the burst connection while there was a waiter"
194+
)
195195
await coro # Should be able to take that burst connection we created
196-
assert (
197-
did_call_close_connection.is_set()
198-
), "No more waiters, burst connection should be closed"
199-
assert (
200-
pool._total == pool.max_size
201-
), "Pool should return to max size after burst capacity is not needed"
196+
assert did_call_close_connection.is_set(), (
197+
"No more waiters, burst connection should be closed"
198+
)
199+
assert pool._total == pool.max_size, (
200+
"Pool should return to max size after burst capacity is not needed"
201+
)
202202
main_event.set() # Allow the initial workers to exit
203203
await asyncio.gather(*coros) # Wait for initial workers to exit
204-
assert (
205-
pool.available.qsize() == pool.max_size
206-
), "Workers should return their connections to the pool"
204+
assert pool.available.qsize() == pool.max_size, (
205+
"Workers should return their connections to the pool"
206+
)
207207

208208

209-
@pytest.mark.asyncio()
209+
@pytest.mark.asyncio
210210
async def test_stale_connections(pool_cls):
211211
"""Test that the pool doesn't hand out closed connections."""
212212

@@ -243,12 +243,12 @@ async def worker():
243243
stale_connections.add(conn)
244244

245245
async with pool.get_connection() as conn:
246-
assert (
247-
conn != now_stale
248-
), "Make sure connections closed by consumers are not given back out"
246+
assert conn != now_stale, (
247+
"Make sure connections closed by consumers are not given back out"
248+
)
249249

250250

251-
@pytest.mark.asyncio()
251+
@pytest.mark.asyncio
252252
async def test_handling_cancellederror():
253253
making_connection = asyncio.Event()
254254

0 commit comments

Comments
 (0)