python / python/mypy

Type checking for *args and **kwargs when passing them to another function

Aperta
#19,302 14 commenti 9 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

feature topic-calls
Lingua principale
Python
Stelle
20.6k
Fork
3.3k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

Feature

Add type checking for passing *args and **kwargs to another function.

It may be enabled by default when mypy detects *args and **kwargs are passed to the same function or it may be enabled only by decorator (for example, @mypy_extensions.pass_args. This will overwrite *args and **kwargs in the function signature with signature of the function to which they are passed. Also it should be possible to explicitly mark the function to which arguments are passed and specify whether to pass *args, **kwargs or both.

Pitch

I'll give an example with usual functions but it will be useful for decorators too.

For example, function wrapper passes its arguments to function inner and adds its own arguments:

def inner(a: int, b: int) -> None:
    ...


def wrapper(arg1: str, *args, **kwargs) -> None:
    inner(*args, **kwargs)  # It will automatically detect passing arguments to another function

This will automatically detect passing *args and **kwargs to another function and change the function signature to:

def wrapper(arg1: str, a: int, b: int):
    ...

It should successfully process and type-check the following calls:

wrapper("foo", 1, 2)  # All positional arguments
wrapper(arg1="foo", b=1, a=2)  # All keyword arguments
wrapper("foo", 1, a=2)  # Mix positional and keyword

wrapper([], 1, 2)
#       ^^ Type error in wrapper's argument (list passed instead of str)

wrapper("foo", [], 2)
#              ^^ Type error in inner's argument (list passed instead of int)

Also multiple passes to the same function should be successfully processed:

def wrapper(arg1: str, *args, **kwargs) -> None:
    if some_condition:
        inner(1, *args, **kwargs)  # Multiple same function calls with passed arguments
    elif condition2:
        inner(2, *args, **kwargs)
    else:
        inner(*args, **kwargs)

Also these cases should be processed:

def wrapper(arg1: str, *args, **kwargs) -> None:
    inner(*args)  # Only args are passed
def wrapper(arg1: str, *args, **kwargs) -> None:
    inner(**kwargs)  # Only kwargs are passed

There should be an option to overwrite this behavior using decorator (or this feature may be disabled by default and be enabled by the decorator). The decorator factory signature concept:

def pass_args(func: collections.abc.Callable | None, pass_args: bool = False, pass_kwargs: bool = False):
    ...

func – The function to copy arguments from. Use None value to force disable this feature.
pass_args – whether to copy arguments that may be passed as positional (passing *args)
pass_kwargs – whether to copy arguments that may be passed as keyword (passing **kwargs)

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

La issue non indica file, test o punti di ingresso. Inizia individuando come mypy gestisce le firme e le chiamate di funzione, quindi determina come il comportamento proposto si inserisce nel controllo degli argomenti esistente. Il lavoro è completo quando sono presenti un design deciso, un’implementazione e test che coprano gli argomenti posizionali, gli argomenti con parole chiave, le chiamate miste, l’inoltro parziale e gli override.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
python
Ambito
devtools
Tipo di issue
Funzionalità
Difficoltà
5/5
Tempo stimato
Più di una settimana
Stato di attività
Tranquilla
Chiarezza
Da chiarire
Idoneità per principianti
28/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.