Skip to content

Commit 9785283

Browse files
Use Callable for typing, rather than ParamSpec (#710)
1 parent 09d6a0b commit 9785283

File tree

6 files changed

+26
-20
lines changed

6 files changed

+26
-20
lines changed

.coveragerc

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,6 @@ _site-packages-to-src-mapping =
99
*/lib/python*/site-packages
1010
*\Lib\site-packages
1111

12-
[report]
13-
fail_under = 98
14-
skip_covered = true
15-
skip_empty = true
16-
show_missing = true
17-
exclude_also =
18-
^\s*@pytest\.mark\.xfail
19-
2012
[run]
2113
branch = true
2214
cover_pylib = false

CHANGES/699.feature.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
1-
Improved type safety by allowing callback parameters to be type checked (``typing-extensions`` is now required for Python 3.9).
2-
31
Added decorator functionality to ``Signal`` as a convenient way to add a callback
42
-- by ``@Vizonex``.

CHANGES/710.feature.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Improved type safety by allowing callback parameters to be type checked (``typing-extensions`` is now required for Python <3.13).
2+
-- by ``@Vizonex`` and ``@Dreamsorcerer``.

aiosignal/__init__.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,27 @@
11
import sys
2-
from typing import Awaitable, Callable, TypeVar
2+
from typing import Any, Awaitable, Callable, TypeVar
33

44
from frozenlist import FrozenList
55

6-
if sys.version_info >= (3, 10):
7-
from typing import ParamSpec
6+
if sys.version_info >= (3, 11):
7+
from typing import Unpack
88
else:
9-
from typing_extensions import ParamSpec
9+
from typing_extensions import Unpack
10+
11+
if sys.version_info >= (3, 13):
12+
from typing import TypeVarTuple
13+
else:
14+
from typing_extensions import TypeVarTuple
1015

11-
_P = ParamSpec("_P")
1216
_T = TypeVar("_T")
13-
_AsyncFunc = Callable[_P, Awaitable[_T]]
17+
_Ts = TypeVarTuple("_Ts", default=Unpack[tuple[()]])
1418

1519
__version__ = "1.3.2"
1620

1721
__all__ = ("Signal",)
1822

1923

20-
class Signal(FrozenList[_AsyncFunc[_P, _T]]):
24+
class Signal(FrozenList[Callable[[Unpack[_Ts]], Awaitable[object]]]):
2125
"""Coroutine-based signal implementation.
2226
2327
To connect a callback to a signal, use any list method.
@@ -37,7 +41,7 @@ def __repr__(self) -> str:
3741
self._owner, self.frozen, list(self)
3842
)
3943

40-
async def send(self, *args: _P.args, **kwargs: _P.kwargs) -> None:
44+
async def send(self, *args: Unpack[_Ts], **kwargs: Any) -> None:
4145
"""
4246
Sends data to all registered receivers.
4347
"""
@@ -47,7 +51,9 @@ async def send(self, *args: _P.args, **kwargs: _P.kwargs) -> None:
4751
for receiver in self:
4852
await receiver(*args, **kwargs)
4953

50-
def __call__(self, func: _AsyncFunc[_P, _T]) -> _AsyncFunc[_P, _T]:
54+
def __call__(
55+
self, func: Callable[[Unpack[_Ts]], Awaitable[_T]]
56+
) -> Callable[[Unpack[_Ts]], Awaitable[_T]]:
5157
"""Decorator to add a function to this Signal."""
5258
self.append(func)
5359
return func

docs/index.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ and dropping callbacks is forbidden.
1515
The only available operation is calling the previously registered
1616
callbacks by using ``await sig.send(data)``.
1717

18+
The callback parameters, which should be passed in the ``.send()`` call, can be
19+
specified for a type checker:
20+
21+
```python
22+
signal = Signal[int, str](owner)
23+
signal.send(42, "foo")
24+
```
25+
1826
For concrete usage examples see the :ref:`aiohttp:aiohttp-web-signals` section of the :doc:`aiohttp:web_advanced` chapter of the :doc:`aiohttp documentation <aiohttp:index>`.
1927

2028
API

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ include_package_data = True
3838

3939
install_requires =
4040
frozenlist >= 1.1.0
41-
typing-extensions >= 3.10; python_version <= '3.9'
41+
typing-extensions >= 4.2; python_version < '3.13'
4242

4343

4444
[pep8]

0 commit comments

Comments
 (0)