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

TypeError: Parameter list cannot be empty for TypeVarTuple #322

Open
EmmanuelMess opened this issue Jan 18, 2024 · 2 comments
Open

TypeError: Parameter list cannot be empty for TypeVarTuple #322

EmmanuelMess opened this issue Jan 18, 2024 · 2 comments
Labels

Comments

@EmmanuelMess
Copy link

EmmanuelMess commented Jan 18, 2024

There is a problem with typing_extensions that doesn't happen with typing. Running the program with python3.11 works, but with python3.10 with typing_extensions throws:

Traceback (most recent call last):
  File ".../main.py", line 48, in <module>
    main()
  File ".../main.py", line 40, in main
    signal: Signal[()] = Signal[()]()
  File "/usr/lib/python3.10/typing.py", line 312, in inner
    return func(*args, **kwds)
  File "/usr/lib/python3.10/typing.py", line 1328, in __class_getitem__
    raise TypeError(
TypeError: Parameter list to Signal[...] cannot be empty

from __future__ import annotations

from typing_extensions import Callable, TypeVarTuple, Generic, Unpack, List, TypeVar

VarArgs = TypeVarTuple('VarArgs')


class Signal(Generic[Unpack[VarArgs]]):

    def __init__(self):
        self.functions: List[Callable[..., None]] = []
        """
        Simple mechanism that allows abstracted invocation of callbacks. Multiple callbacks can be attached to a signal
        so that they are all called when the signal is emitted.
        """

    def connect(self, function: Callable[..., None]):
        """
        Add a callback to this Signal
        :param function: callback to call when emited
        """
        self.functions.append(function)

    def emit(self, *args: Unpack[VarArgs]):
        """
        Call all callbacks with the arguments passed
        :param args: arguments for the signal, must be the same type as type parameter
        """
        for function in self.functions:
            if args:
                function(*args)
            else:
                function()


def main():
    def signalEmptyCall():
        print("Hello!")

    signal: Signal[()] = Signal[()]()

    signal.connect(signalEmptyCall)

    signal.emit()


if __name__ == '__main__':
    main()
@Daraan
Copy link
Contributor

Daraan commented Dec 15, 2024

I leave a quick comment here.

The problem is that in 3.10 typing.Generic(and earlier?) there is a check:

        if not params and cls is not Tuple:
             raise TypeError(f"Parameter list to {cls}[...] cannot be empty")

As params is an empty tuple the TypeError is raised. Without monkey patching typing itself the TypeError cannot be circumvented.

Afaik, the only workaround that can be used before 3.11 is to use the equivalent form of ()Unpack[Tuple[()]]:

signal: Signal[Unpack[Tuple[()]]]

@JelleZijlstra
Copy link
Member

We could make a typing_extensions.Generic that is different from typing.Generic and fixes this issue.

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

No branches or pull requests

4 participants