python / python/mypy

Type-checking generic of enum.Meta with a custom metaclass fails with code that runs, and passes with code that doesn't run.

Aperta
#11,970 4 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

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

Descrizione

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

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

Inizia eseguendo le due riproduzioni collegate di mypy-play con Python 3.9 e mypy master, confrontando la versione che rifiuta la chiamata non valida a Carrier con la versione che viene eseguita ma la accetta. Poi analizza come mypy gestisce le sottoclassi generiche di enum.Enum e le classi EnumMeta personalizzate, e aggiungi una copertura di regressione per l’errore di tipo previsto.

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

Valutazione

Stack tecnologico
python
Ambito
devtools
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.