python / python/typeshed

Implications of Union in argparse.Action.__call__ parameter types

Aperta
#7,559 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Lingua principale
Python
Stelle
5.1k
Fork
2.1k
Merge medio
1g 19h
PR unite (30g)
82

Descrizione

https://github.com/python/typeshed/blob/c41034c3540c5abda10008dd6c17d8e6ff6cc634/stdlib/argparse.pyi#L364-L366
I'm wondering if the reasoning behind this choice has been discussed before. Return types of library functions generally avoid Union (python/mypy#1693). To me, the parameters of a user-provided callback are similar to the return type of a library function—the annotations reflect objects passed to user code, and the user may have runtime control of their types. It is, however, more removed from the runtime context because the class must be first defined and then referenced.

If I override __call__ with an implementation that will only ever see str:

import argparse

class CSVCallback(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        setattr(namespace, self.dest, list(values.split(',')))

parser = argparse.ArgumentParser()
parser.add_argument('-o', action=CSVCallback, default=[])

args = parser.parse_args()

pyright complains, based on what appears to be a correct interpretation of the stub:

  repr.py:5:51 - error: Cannot access member "split" for type "Sequence[Any]"
    Member "split" is unknown (reportGeneralTypeIssues)
  repr.py:5:51 - error: "split" is not a known member of "None" (reportOptionalMemberAccess)

Would the appropriate solution be to add assert isinstance(values, str) at the beginning of every callback? Or is this actually abuse of action=..., which should be replaced with type=..., like this?

def csv_callback(value: str) -> list[str]:
    return list(value.split(','))

parser.add_argument('-o', type=csv_callback, default=[])

Since these examples are based on 10-year-old optparse code that was ported 1:1 to argparse 2 years ago, I'm not considering reimplementing them like that—they aren't broken, and the less trivial examples reference parser.error and the previous value of self.dest. But I'd rather avoid the asserts, so for new code I would probably prefer that pattern.

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

Esamina prima stdlib/argparse.pyi alle righe 364-366 e la discussione collegata su Union nelle interfacce delle librerie. Confronta l’esempio di callback Action con l’esempio di type= e determina se lo stub debba essere modificato o se l’annotazione esistente debba essere documentata; il lavoro richiede una risoluzione approvata da un maintainer.

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

Valutazione

Stack tecnologico
python
Ambito
tooling
Tipo di issue
Bug
Difficoltà
5/5
Tempo stimato
Più di una settimana
Stato di attività
Ferma
Chiarezza
Da chiarire
Idoneità per principianti
25/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.