Wrong type inference for class with metaclass that acts as descriptor
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- Python
- Sterne
- 20.6k
- Forks
- 3.3k
- PR-Merge-Kennzahlen
- PR-Kennzahlen ausstehend
Beschreibung
Bug Report
Descriptor protocol does not work on metaclasses - defining __get__ method in a metaclass does not make classes using that metaclass work as descriptors.
To Reproduce
- Put this code in a py file:
from typing import Any, TYPE_CHECKING, overload
class _IntDescriptorMeta(type):
def __get__(self, instance: Any, owner: Any) -> int:
return 123
class IntDescriptorClass(metaclass=_IntDescriptorMeta):
...
class IntDescriptor:
def __get__(self, instance: Any, owner: Any) -> int:
return 123
class X:
number_cls = IntDescriptorClass
number = IntDescriptor()
print(X.number_cls)
print(X().number_cls)
print(X.number)
print(X().number)
if TYPE_CHECKING:
reveal_type(X.number_cls)
reveal_type(X().number_cls)
reveal_type(X.number)
reveal_type(X().number)
- Run it, you should see:
123
123
123
123
- Type check it with mypy and see the incorrect output.
Expected Behavior
I expected mypy to infer type of X.number_cls/X().number_cls correctly:
main.py:24: note: Revealed type is "builtins.int"
main.py:25: note: Revealed type is "builtins.int"
main.py:26: note: Revealed type is "builtins.int"
main.py:27: note: Revealed type is "builtins.int"
Note:
To simplify this example, __get__ returns an int no matter if instance is None or not but I assume a fix would also make it work properly with overloads as it does for instances of classes.
Actual Behavior
Mypy does not infer type of X.number_cls/X().number_cls correctly:
main.py:24: note: Revealed type is "def () -> __main__.IntDescriptorClass"
main.py:25: note: Revealed type is "def () -> __main__.IntDescriptorClass"
main.py:26: note: Revealed type is "builtins.int"
main.py:27: note: Revealed type is "builtins.int"
Your Environment
- Mypy version used: 0.910 as well as the latest (master branch)
- mypy-play.net URL: https://mypy-play.net/?mypy=latest&python=3.8&gist=de23d753f19cf0149ed9cd6919e84791
Additional notes
This works properly on pyright 1.1.161+, see the issue: https://github.com/microsoft/pyright/issues/2164
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Beginne damit, die bereitgestellte Python-Reproduktion auszuführen und die aufgedeckten Typen mit mypy zu prüfen; verwende bei Bedarf die verknüpfte mypy-play-URL. Verfolge mypys Typinferenz für Deskriptoren, die auf Metaklassen definiert sind, und vergleiche sie mit gewöhnlichen Instanzdeskriptoren. Als abgeschlossen gilt die Aufgabe, wenn alle vier Reveals für den klassenbasierten Deskriptor builtins.int melden und das bestehende Verhalten von Deskriptoren weiterhin korrekt ist.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- python
- Bereich
- devtools
- Issue-Typ
- Bug
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Aktivitätsstatus
- Veraltet
- Klarheit
- Klar beschrieben
- Anfängerfreundlichkeit
- 42/100