Skip to content

Callable with variadic fixed arguments that doesn't mean *args  #1301

Open
@drecdroid

Description

@drecdroid

Suppose I have a type of function called CommandHandler, that is a function that receives a command as its first parameter but then could have other parameters.
Examples

class Command:
    pass

class RegisterUser(Command):
    pass

class DeleteUser(Command):
    pass

def register_user(command: RegisterUser, db : Db) -> None:
    ...

def delete_user(command: DeleteUser, dispatch: EventDispatcher, cache: Cache) -> None:
    ...

mappings : dict[Command, CommandHandler] = {
    RegisterUser: register_user,
    DeleteUser: delete_user
}

What would be the definition of CommandHandler?

Ideally it would be:

C= TypeVar("C", bound=Command)
CommandHandler = Callable[[C, ...], None] 

But this syntax is not possible.

I've found in the documentation that Concatenate could receive ... at the end,

Concatenate is currently only valid when used as the first argument to a Callable. The last parameter to Concatenate must be a ParamSpec or ellipsis (...).

so it could be:

C= TypeVar("C", bound=Command)
CommandHandler = Callable[Concatenate[C, ...], None] 

But this returns an error from Pylance:

image

One could say Callback Protocol could solve this like:

C= TypeVar("C", bound=Command)
class CommandHandler(Protocol):
    def __call__(self, __command: C, *__args: Any) -> None: ...

But it only receives functions that has an implicit variadic argument, it doesn't work with variadic forms of the function.

So far the only way I could solve this is through the Union of many Callables, but it doesn't look like the best solution.

At the end CommandHandler can only be defined as:

C= TypeVar("C", bound=Command)
CommandHandler = Union[
    Callable[[C, Any], None],
    Callable[[C, Any, Any], None],
    Callable[[C, Any, Any, Any], None],
    Callable[[C, Any, Any, Any, Any], None],
    Callable[[C, Any, Any, Any, Any, Any], None],
    Callable[[C, Any, Any, Any, Any, Any, Any], None],
    Callable[[C, Any, Any, Any, Any, Any, Any, Any], None],
    Callable[
        [C, Any, Any, Any, Any, Any, Any, Any, Any], None
    ],
]

Related:
python/cpython#88954
https://stackoverflow.com/questions/57658879/python-type-hint-for-callable-with-variable-number-of-str-same-type-arguments

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic: otherOther topics not covered

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions