python / mypy

Optional static typing for Python
https://www.mypy-lang.org/
Other
18.46k stars 2.83k forks source link

Enum elements accessed via 'self' have 'auto' type #12107

Open finite-state-machine opened 2 years ago

finite-state-machine commented 2 years ago

Bug Report

Within an Enum class e.g., SomeEnum, elements initialized with auto() and accessed as self.SOME_ELEMENT have type enum.auto* instead of SomeEnum, resulting in false positives for comparison operations.

To Reproduce

Run mypy on the following code:

from enum import (
        auto,
        Enum,
        )

class Game(Enum):

    TENNIS = auto()
    PING_PONG = auto()
    SOCCER = auto()

    def is_racquet_sport(self) -> bool:
        return self in {self.TENNIS, self.PING_PONG}
                # error: Non-overlapping container check (
                #           element type: "Game",
                #           container item type: "auto"
                #           )
                #           [comparison-overlap]

Expected Behavior

No errors should be issued.

Actual Behavior

A comparison-overlap error is issued on the return statement:

the_code_above.py:13: error: Non-overlapping container check (element type: "Game", container item type: "auto")
Found 1 error in 1 file (checked 1 source file)

Additional notes

Changing the element references from e.g. self.TENNIS to Game.TENNIS results in the expected behaviour.

Your Environment

AlexWaygood commented 2 years ago

Note that the docs for the enum module explicitly recommend that you do not access other members via self in this way.

MestreLion commented 1 year ago

Note that the docs for the enum module explicitly recommend that you do not access other members via self in this way.

It seems that while this was the case in Python 3.10, since Python 3.11 there is no such recommendation anymore, and accessing members via other instances (including self) is not only no longer deprecated but officially supported. The only recommendation is to avoid naming clashes between members and methods.

MestreLion commented 1 year ago

This bug also happens with literal values instead of auto():

import enum

class Planet(enum.Enum):
    EARTH   = 1
    MARS    = 2
    JUPITER = 3
    SATURN  = 4

    @property
    def is_solid(self) -> bool:
        return self in (self.EARTH, self.MARS)

    @property
    def is_home(self) -> bool:
        return self is self.EARTH

home = Planet.EARTH
print(home)
print(home.MARS)
print(home.is_home)
print(home.is_solid)
$ python3.8 teste.py 
Planet.EARTH
Planet.MARS
True
True
$ mypy teste.py 
teste.py:12: error: Non-overlapping container check (element type: "Planet", container item type: "int")  [comparison-overlap]
teste.py:16: error: Non-overlapping identity check (left operand type: "Planet", right operand type: "Literal[1]")  [comparison-overlap]
Found 2 errors in 1 file (checked 1 source file)
$ mypy --version 
mypy 1.4.1 (compiled: yes)

Btw, same errors if running as mypy --python-version 3.11 teste.py

MestreLion commented 1 year ago

I believe this is a duplicate of #10910