Skip to content

Commit c5c3dce

Browse files
committed
feat: ✨ Drop Python 3.9 support, add 3.13 support and update things
1 parent 6368f81 commit c5c3dce

File tree

6 files changed

+34
-37
lines changed

6 files changed

+34
-37
lines changed

.pre-commit-config.yaml

+4-8
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,26 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: v4.5.0
3+
rev: v5.0.0
44
hooks:
55
- id: end-of-file-fixer
66
- id: check-added-large-files
77
- id: check-merge-conflict
88
- id: check-docstring-first
99
- id: debug-statements
1010
- repo: https://github.com/astral-sh/ruff-pre-commit
11-
rev: v0.2.1
11+
rev: v0.7.2
1212
hooks:
1313
- id: ruff
1414
args: [--fix, --exit-non-zero-on-fix]
15-
- repo: https://github.com/Lucas-C/pre-commit-hooks-safety
16-
rev: v1.3.3
17-
hooks:
18-
- id: python-safety-dependencies-check
1915
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
20-
rev: v9.11.0
16+
rev: v9.18.0
2117
hooks:
2218
- id: commitlint
2319
stages: [commit-msg]
2420
additional_dependencies:
2521
- "@commitlint/config-conventional"
2622
default_stages:
27-
- commit
23+
- pre-commit
2824
default_install_hook_types:
2925
- pre-commit
3026
- commit-msg

async_signals/dispatcher.py

+10-9
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
import logging
33
import threading
44
import weakref
5-
from typing import Any, Callable, Dict, Hashable, List, Optional, Tuple, Type, Union
5+
from collections.abc import Hashable
6+
from typing import Any, Callable, Optional, Union
67

78
from .utils import func_accepts_kwargs
89

@@ -11,7 +12,7 @@
1112

1213
def _make_id(
1314
target: Union[Hashable, Callable, None],
14-
) -> Union[Hashable, Tuple[Hashable, ...]]:
15+
) -> Union[Hashable, tuple[Hashable, ...]]:
1516
if hasattr(target, "__self__") and hasattr(target, "__func__"):
1617
return id(target.__self__), id(target.__func__) # type: ignore
1718
return id(target)
@@ -33,7 +34,7 @@ class Signal:
3334
{ receiverkey (id) : weakref(receiver) }
3435
"""
3536

36-
receivers: List[Tuple[Tuple[Hashable, Hashable], Callable]]
37+
receivers: list[tuple[tuple[Hashable, Hashable], Callable]]
3738
use_caching: bool
3839
debug: bool
3940

@@ -55,7 +56,7 @@ def __init__(
5556
# distinct sender we cache the receivers that sender has in
5657
# 'sender_receivers_cache'. The cache is cleaned when .connect() or
5758
# .disconnect() is called and populated on send().
58-
self.sender_receivers_cache: Union[weakref.WeakKeyDictionary, Dict] \
59+
self.sender_receivers_cache: Union[weakref.WeakKeyDictionary, dict] \
5960
= weakref.WeakKeyDictionary() if use_caching else {}
6061
self._dead_receivers = False
6162

@@ -115,7 +116,7 @@ def connect(
115116
lookup_key = (_make_id(receiver), _make_id(sender))
116117

117118
if weak:
118-
ref: Union[Type[weakref.WeakMethod[Any]], Type[weakref.ReferenceType[Any]]] \
119+
ref: Union[type[weakref.WeakMethod[Any]], type[weakref.ReferenceType[Any]]] \
119120
= weakref.ref
120121
receiver_object = receiver
121122
# Check for bound methods
@@ -201,7 +202,7 @@ async def send(
201202
self,
202203
sender: Hashable,
203204
**named: Any,
204-
) -> List[Tuple[Callable, Any]]:
205+
) -> list[tuple[Callable, Any]]:
205206
"""
206207
Send signal from sender to all connected receivers.
207208
@@ -243,7 +244,7 @@ async def send_robust(
243244
self,
244245
sender: Hashable,
245246
**named: Any,
246-
) -> List[Tuple[Callable, Any]]:
247+
) -> list[tuple[Callable, Any]]:
247248
"""
248249
Send signal from sender to all connected receivers catching errors.
249250
@@ -302,7 +303,7 @@ def _clear_dead_receivers(self) -> None:
302303
if not (isinstance(r[1], weakref.ReferenceType) and r[1]() is None)
303304
]
304305

305-
def _live_receivers(self, sender: Union[Hashable, None]) -> List[Callable]:
306+
def _live_receivers(self, sender: Union[Hashable, None]) -> list[Callable]:
306307
"""
307308
Filter sequence of receivers to get resolved, live receivers.
308309
@@ -353,7 +354,7 @@ def _remove_receiver(self, receiver: Optional[Callable] = None) -> None: # noqa
353354

354355

355356
def receiver(
356-
signal: Union[Signal, List[Signal], Tuple[Signal, ...]],
357+
signal: Union[Signal, list[Signal], tuple[Signal, ...]],
357358
*,
358359
sender: Optional[Hashable] = None,
359360
weak: bool = True,

async_signals/utils.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import functools
22
import inspect
3-
from typing import Callable, Tuple
3+
from typing import Callable
44

55
# Those functions are copied from
66
# https://github.com/django/django/blob/main/django/utils/inspect.py
@@ -10,7 +10,7 @@
1010
def _get_func_parameters(
1111
func: Callable,
1212
remove_first: bool,
13-
) -> Tuple[inspect.Parameter, ...]:
13+
) -> tuple[inspect.Parameter, ...]:
1414
parameters = tuple(inspect.signature(func).parameters.values())
1515
if remove_first:
1616
parameters = parameters[1:]
@@ -19,7 +19,7 @@ def _get_func_parameters(
1919

2020
def _get_callable_parameters(
2121
meth_or_func: Callable,
22-
) -> Tuple[inspect.Parameter, ...]:
22+
) -> tuple[inspect.Parameter, ...]:
2323
is_method = inspect.ismethod(meth_or_func)
2424
func = meth_or_func.__func__ if is_method else meth_or_func # type: ignore
2525
return _get_func_parameters(func, remove_first=is_method)

pyproject.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ readme = "README.md"
99
packages = [{include = "async_signals"}]
1010

1111
[tool.poetry.dependencies]
12-
python = "^3.8"
12+
python = "^3.9"
1313

1414
[tool.poetry.group.dev.dependencies]
1515
pytest = ">=7.1.3,<9.0.0"
@@ -22,7 +22,7 @@ pyright = ">=1.1.350,<1.2"
2222

2323
[tool.ruff]
2424
line-length = 115
25-
target-version = "py38"
25+
target-version = "py39"
2626
output-format = "grouped"
2727

2828
[tool.ruff.lint]

tests/test_dispatcher.py

+13-13
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,22 @@
66
from async_signals import Signal, receiver
77

88

9-
@pytest.fixture()
9+
@pytest.fixture
1010
def signal() -> Signal:
1111
return Signal()
1212

1313

14-
@pytest.fixture()
14+
@pytest.fixture
1515
def signal2() -> Signal:
1616
return Signal()
1717

1818

19-
@pytest.fixture()
19+
@pytest.fixture
2020
def debug_signal() -> Signal:
2121
return Signal(debug=True)
2222

2323

24-
@pytest.fixture()
24+
@pytest.fixture
2525
def cached_signal() -> Signal:
2626
return Signal(use_caching=True)
2727

@@ -153,14 +153,14 @@ def invalid_receiver_function():
153153
debug_signal.connect(invalid_receiver_function)
154154

155155

156-
@pytest.mark.anyio()
156+
@pytest.mark.anyio
157157
async def test_signal_send_without_receivers(signal: Signal, mocker):
158158
result = await signal.send(sender=test_signal_send_without_receivers, x="a", y="b")
159159

160160
assert len(result) == 0
161161

162162

163-
@pytest.mark.anyio()
163+
@pytest.mark.anyio
164164
async def test_signal_send_without_receivers_and_caching(signal: Signal, mocker):
165165
signal.use_caching = True
166166

@@ -169,7 +169,7 @@ async def test_signal_send_without_receivers_and_caching(signal: Signal, mocker)
169169
assert len(result) == 0
170170

171171

172-
@pytest.mark.anyio()
172+
@pytest.mark.anyio
173173
async def test_signal_send_sync(signal: Signal, mocker):
174174
receiver_function = mocker.Mock()
175175

@@ -186,7 +186,7 @@ async def test_signal_send_sync(signal: Signal, mocker):
186186
)
187187

188188

189-
@pytest.mark.anyio()
189+
@pytest.mark.anyio
190190
async def test_signal_send_async(signal: Signal, mocker):
191191
receiver_function = mocker.AsyncMock()
192192

@@ -203,7 +203,7 @@ async def test_signal_send_async(signal: Signal, mocker):
203203
)
204204

205205

206-
@pytest.mark.anyio()
206+
@pytest.mark.anyio
207207
async def test_signal_send_will_raise_exception(signal: Signal, mocker):
208208
receiver_function = mocker.AsyncMock(
209209
side_effect=RuntimeError("Boom!"),
@@ -215,14 +215,14 @@ async def test_signal_send_will_raise_exception(signal: Signal, mocker):
215215
await signal.send(sender=test_signal_send_will_raise_exception, x="a", y="b")
216216

217217

218-
@pytest.mark.anyio()
218+
@pytest.mark.anyio
219219
async def test_signal_send_robust_without_receivers(signal: Signal, mocker):
220220
result = await signal.send_robust(sender=test_signal_send_without_receivers, x="a", y="b")
221221

222222
assert len(result) == 0
223223

224224

225-
@pytest.mark.anyio()
225+
@pytest.mark.anyio
226226
async def test_signal_send_robust_works_normally(signal: Signal, mocker):
227227
receiver_function = mocker.AsyncMock()
228228

@@ -239,7 +239,7 @@ async def test_signal_send_robust_works_normally(signal: Signal, mocker):
239239
)
240240

241241

242-
@pytest.mark.anyio()
242+
@pytest.mark.anyio
243243
async def test_signal_send_robust_will_catch_exception(signal: Signal, mocker):
244244
receiver_function = mocker.AsyncMock(
245245
side_effect=Exception("Boom!"),
@@ -268,7 +268,7 @@ def receiver_function(**kwargs):
268268
assert len(signal2.receivers) == 1
269269

270270

271-
@pytest.mark.anyio()
271+
@pytest.mark.anyio
272272
async def test_receivers_only_called_when_sender_matches(signal: Signal, mocker):
273273
receiver_function1 = mocker.AsyncMock()
274274
receiver_function2 = mocker.AsyncMock()

tox.ini

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
[tox]
22
isolated_build = True
33
envlist =
4-
py38,
54
py39,
65
py310,
76
py311,
8-
py312
7+
py312,
8+
py313
99

1010
[testenv]
1111
deps =

0 commit comments

Comments
 (0)