python / python/typing

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

Ouverte
#1,301 4 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

topic: other
Langage dominant
Python
Étoiles
1.8k
Forks
302
Merge moyen
23 h
PR mergées (30 j)
8

Description

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:
https://github.com/python/cpython/issues/88954
https://stackoverflow.com/questions/57658879/python-type-hint-for-callable-with-variable-number-of-str-same-type-arguments

Guide de contribution

Aucun guide de contribution indexé pour ce dépôt

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par la documentation de Callable et Concatenate décrite dans l’issue, puis examinez l’issue associée 88954 et la discussion Stack Overflow liée. Comparez les formes de CommandHandler demandées avec les règles actuelles de typing et déterminez si une conception prise en charge permet de les exprimer ; le résultat doit inclure une spécification approuvée ainsi qu’un plan correspondant de documentation ou d’implémentation.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
tooling
Type d'issue
Fonctionnalité
Difficulté
5/5
Temps estimé
Plus d'une semaine
Activité
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
30/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.