python / python/mypy

Wrapped methods are not properly resolved until after the class definition

Aperta
#16,397 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

bug
Lingua principale
Python
Stelle
20.6k
Fork
3.3k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

Context & setup

Consider the following simple protocol:

class Proto(Protocol):
    @property
    def f(self) -> int:
        ...

One can implement this protocol wrongly as follows:

T = TypeVar("T")
P = ParamSpec("P")


def wrapper(f: Callable[P, T]) -> Callable[P, str]:
    def wrapped(*args: P.args, **kwargs: P.kwargs) -> str:
        return 0

    return wrapped

class Impl:
    @wrapper  # converts return type from `bool` to `str`, while the protocol expects `int`
    def f(self) -> bool:
        return False

# error: Incompatible return value type (got "Impl", expected "Proto")  [return-value]
# note: Following member(s) of "Impl" have conflicts:
# note:     Expected:
# note:         def f(self) -> int
# note:     Got:
# note:         def f(self) -> str
def b() -> Proto:
    return Impl()

The bug (false negative)

When this same function b is placed before class Impl, mypy does not report an error. Adding reveal_type(Impl.f) before and after the class definition hints at what is going on:

main.py:21: error: Expression has type "Any"  [misc]
main.py:21: error: Cannot determine type of "f"  [has-type]
main.py:21: note: Revealed type is "Any"
main.py:21: error: Name "Impl" is used before definition  [used-before-def]

main.py:28: note: Revealed type is "def (self: __main__.Impl) -> builtins.str"

If f is not decorated but explicitly returns str, one gets

main.py:21: note: Revealed type is "def (self: __main__.Impl) -> builtins.str"
main.py:21: error: Name "Impl" is used before definition  [used-before-def]

main.py:27: note: Revealed type is "def (self: __main__.Impl) -> builtins.str"

as expected. This indicates that the wrapped decorator is only properly resolved for code after the class definition.

False positive variant

If f is decorated with @property, this can also produce false positives. This is how I encountered the issue in the first place. Playground.

Additional info

Python: 3.11
Mypy: 371219347a6d17e16924bbabf3e693c6874e7138
Flags: --strict --disallow-any-*

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

Riproduci il falso negativo e il falso positivo in main.py usando gli esempi mypy-play collegati, confrontando il posizionamento della funzione, @wrapper e @property. Traccia come vengono risolti il decorator e il tipo del metodo wrapped prima e dopo class Impl; il lavoro è completato quando entrambe le varianti riportano in modo coerente le diagnosi previste di compatibilità con il protocollo.

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

Valutazione

Stack tecnologico
python
Ambito
tooling
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.