Type-checking generic of enum.Meta with a custom metaclass fails with code that runs, and passes with code that doesn't run.
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- Python
- Sterne
- 20.6k
- Forks
- 3.3k
- PR-Merge-Kennzahlen
- PR-Kennzahlen ausstehend
Beschreibung
Bug Report
Trying to type-check generic types of a bound enum.Enum (with a custom metaclass) only catches type errors when the actual code fails to run; but doesn't detect the issues when the code runs.
To Reproduce
The code in this gist properly detects the type error while calling Carrier(Foo, Bar.item1):
import enum
from dataclasses import dataclass
from typing import TypeVar, Generic, Type
M = TypeVar('M', bound="MyEnum")
class Meta(enum.EnumMeta):
pass
class MyEnum(metaclass=Meta):
...
class Foo(enum.Enum, MyEnum):
item1 = "1"
item2 = "2"
class Bar(enum.Enum, MyEnum):
item1 = "1"
item2 = "2"
@dataclass
class Carrier(Generic[M]):
meta: Type[M]
instance: M
Carrier(Foo, Foo.item1)
Carrier(Foo, Bar.item1) # should fail
However that code fails to run with
Traceback (most recent call last):
File "/home/manu/src/tmp/enums.py", line 14, in <module>
class Foo(enum.Enum, MyEnum):
File "/usr/lib/python3.10/enum.py", line 173, in __prepare__
member_type, first_enum = metacls._get_mixins_(cls, bases)
File "/usr/lib/python3.10/enum.py", line 619, in _get_mixins_
raise TypeError("new enumerations should be created as "
TypeError: new enumerations should be created as `EnumName([mixin_type, ...] [data_type,] enum_type)`
In order for the code to run we have to swap the positions of enum.Enum and MyEnum in both Foo and Bar (see the second gist); but then mypy fails to catch the type-error.
Your Environment
- Mypy version used: master and 0.931
- Mypy command-line flags: none
- Mypy configuration options from
mypy.ini(and other config files): none - Python version used: 3.9
- Operating system and version:
Linux pavla 5.15.12-1-MANJARO #1 SMP PREEMPT Wed Dec 29 18:08:07 UTC 2021 x86_64 GNU/Linux
Previous discussion in gitter: https://gitter.im/python/typing?at=61dab43cf5a3947800f73b71
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 beiden verlinkten mypy-play-Reproduktionen mit Python 3.9 und mypy master auszuführen, und vergleiche die Version, die den ungültigen Carrier-Aufruf ablehnt, mit der Version, die zwar ausgeführt wird, ihn aber akzeptiert. Untersuche dann, wie mypy generische enum.Enum-Unterklassen und benutzerdefinierte EnumMeta-Klassen behandelt, und füge Regressionstestabdeckung für den erwarteten Typfehler hinzu.
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
- Größtenteils klar
- Anfängerfreundlichkeit
- 35/100