python / python/mypy

Narrowing enums causes `.value` to be typed as `Any`

Offen
#14,092 5 Kommentare 2 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

bug topic-enum
Vorherrschende Sprache
Python
Sterne
20.6k
Forks
3.3k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

Bug Report

Apologies if this has already been reported, but I couldn't find an existing issue for it.

The issue I'm seeing is related to accessing the .value of an Enum after "narrowing" it with the is operator. It seems like the narrowing (to Union[Literal[...]]) works as expected, but then it fails to realize that the .value of all the variants have the same type (and so falls back to Any).

This only affects runs with --warn-return-any enabled:

$ mypy --config-file /dev/null --warn-return-any enum_narrowing.py

To Reproduce

It's probably easiest to see in this example:

import enum
from typing import Tuple

RGB = Tuple[int, int, int]

class Color(enum.Enum):
    WHITE = (255, 255, 255)
    BLACK = (0, 0, 0)

    def red(self) -> int:
        if self is Color.WHITE:
            return 255
        return self.value[0]  # error: Returning Any from function declared to return "int"

(playground URL: https://mypy-play.net/?mypy=latest&python=3.8&flags=warn-return-any&gist=b2a6df92fb37717e5c9d7542b6e88fec)

Expected Behavior

This should deduce that self.value has type RGB and succeed.

Actual Behavior

If I add some reveal_type(self) and reveal_type(self.value)s before/after the narrowing, I get this output:

enum_narrowing.py:11: note: Revealed type is "enum_narrowing.Color"
enum_narrowing.py:12: note: Revealed type is "Tuple[Literal[255]?, Literal[255]?, Literal[255]?]"
enum_narrowing.py:15: note: Revealed type is "Literal[enum_narrowing.Color.BLACK]"
enum_narrowing.py:16: note: Revealed type is "Any"

Your Environment

$ python --version
Python 3.8.0
$ mypy --version
mypy 0.991 (compiled: yes)

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne damit, den bereitgestellten mypy-Befehl gegen enum_narrowing.py auszuführen, und vergleiche die angezeigten Typen vor und nach der is-Eingrenzung. Verfolge die Eingrenzung von Enum-Mitgliedern und die Behandlung des .value-Typs; die Korrektur ist vollständig, wenn self.value[0] als int inferiert wird und das Beispiel mit --warn-return-any erfolgreich durchläuft.

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
48/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.