I want to use a collection that has both Enum
s and Enum
members. But I can't find a way to write it that doesn't cause mypy errors when I try to access the Special Attribute __name__
. (See a list of when __name__
can be expected types and members.)
For context a brief explanation about what happens is given by the BDFL in mypy issue #3728. Basically when you iterate over a collection that has items of different types they are joined. So in the next example what mypy is saying is that the Enum and the Enum member are joined to object
...
Example 1:
from enum import Enum
from typing import Type
class Color(Enum):
RED = 1
my_collection: tuple[Type[Color], Color] = (Color, Color.RED)
for item in my_collection:
if item is Color:
print(item.__name__)
mypy gives the error:
error: "object" has no attribute "__name__"; maybe "__ne__" or "__new__"?
Example 2:
Next I tried to annotate the variable in the for loop to see if the mypy error gained some more color...
from enum import Enum
from typing import Type, Union
class Color(Enum):
RED = 1
my_collection: tuple[Type[Color], Color] = (Color, Color.RED)
item: Union[Type[Color], Color]
for item in my_collection:
if item is Color:
print(item.__name__)
This time mypy gave 2 errors, the first caused by the incompatible types in the for loop (makes sense), and the second expectable error saying the Enum member doesn't have the __name__
special attribute.
error: Incompatible types in assignment (expression has type "object", variable has type "Union[Type[Color], Color]")
error: Item "Color" of "Union[Type[Color], Color]" has no attribute "__name__"
Example 3:
My next step was trying typing.cast before using __name__
which usually is enough for mypy to restrict the type...
from enum import Enum
from typing import Type, cast
class Color(Enum):
RED = 1
my_collection: tuple[Type[Color], Color] = (Color, Color.RED)
for item in my_collection:
if item is Color:
item = cast(Type[Color], item)
print(item.__name__)
This time the error was:
error: has no attribute "__name__"
The 3 examples work at run-time, but what's the Pythonic way of iterating over a collection having items of different types that doesn't cause mypy errors? (Using Python 3.9 and mypy 0.812 with default configurations.)