Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

signal/slot patternmaking function signatures generic #5115

Closed
chadrik opened this issue May 27, 2018 · 4 comments
Closed

signal/slot patternmaking function signatures generic #5115

chadrik opened this issue May 27, 2018 · 4 comments

Comments

@chadrik
Copy link
Contributor

chadrik commented May 27, 2018

I'm trying to design a simple signal/slot package that is pep484-compatible, but it's proving trickier than I thought. The problem is that the type-checked signatures of the generic class's methods should vary depending on its parameterization.

Here's a naive rough draft:

# file: signal.py
from typing import Any, Callable, TypeVar, List

T = TypeVar('T')

class Signal(Callable[T, Any]):
    def __init__(self):
        self.slots: List[Callable[T, Any]] = []

    def connect(self, func: Callable[T, Any]):
        self.slots.append(func)

    def __call__(self, *args, **kwargs):
        "emit the signal"
        for slot in self.slots:
            slot(*args, **kwargs)
# file: signal.pyi
from typing import Any, Callable, TypeVar

T = TypeVar('T')

class Signal(Callable[T, Any]):
    def connect(self, func: Callable[T, Any]) -> None: ...
# file: main.py
from signal import Signal

IntStrSignal = Signal[[int, str]]
sig = IntStrSignal()

def cb(a: int, b: str):
    pass

sig.connect(cb)

sig(1, 'foo')

Any advice on the best way to proceed is greatly appreciated, esp. any low-hanging issues that could unlock this functionality.

Related to #4031

edit: removed emit method in favor of the callable's __call__ method

@chadrik
Copy link
Contributor Author

chadrik commented May 27, 2018

It looks like I accidentally submitted this issue long before I was done editing, so if you got it by email you should click the link to the issue. Sorry!

@JelleZijlstra
Copy link
Member

I don't know if this fixes your problem, but don't you want Callable[[T], Any] instead of Callable[T, Any]? The latter is invalid.

@chadrik
Copy link
Contributor Author

chadrik commented May 27, 2018

I don't know if this fixes your problem, but don't you want Callable[[T], Any] instead of Callable[T, Any]? The latter is invalid.

Yes, it is invalid, but that's part of the problem in terms of expressive limitations. I don't want to limit Signal to callables with one argument. I want to capture the types of all of the args, and use that to restrict/overload the signatures of __call__ and connect. For example, in main.py I want T to hold [int, str], such that sig.connect fails for callables which don't match Callable[[int, str], Any]

@ilevkivskyi
Copy link
Member

This is a duplicate of python/typing#264 (you can cast your vote in favour of special OtherArgs variadic type variable there, it is exactly what you want).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants