Wrapped methods are not properly resolved until after the class definition
Nessuno ha ancora preso questa issue.
- 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
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- 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