Description
- Are you reporting a bug, or opening a feature request?
Asking a question. I'd like to know if there is a standard idiom for enforcing exhaustive matching of an Enum / Literal type.
- Please insert below the code you are checking with mypy
Suppose there are three types of pets: cats, dogs and iguanas. I want to write a function that makes the appropriate pet sound, depending on the type of pet. I'd also like to make sure that I've caught every possible type of pet. Here was my first attempt, using the NoReturn
trick mentioned by @bluetech here. It looks like this works for Unions, but not for Enums / Literals? Apologies if this has been covered before.
def assert_never(x: Any) -> NoReturn:
assert False, "Unhandled type: {}".format(type(x).__name__)
PetLiteral = Literal['dog', 'cat', 'iguana']
def make_sound_literal(pet: PetLiteral) -> str:
if pet == 'dog':
return 'woof'
elif pet == 'cat':
return 'meow'
# elif pet == 'iguana':
# return 'confused silence'
else:
assert_never(pet)
If I comment out the iguana branch and check this file with:
$ mypy --strict pet_sounds.py
mypy has no complaints. If I try the same deal with an enum:
class PetEnum(Enum):
dog: str = 'dog'
cat: str = 'cat'
iguana: str = 'iguana'
def make_sound_enum(pet: PetEnum) -> str:
if pet == PetEnum.dog:
return 'woof'
elif pet == PetEnum.cat:
return 'meow'
# elif pet == PetEnum.iguana:
# return 'confused silence'
else:
assert_never(pet)
and check again with --strict
, I still get no complaints.
-
What are the versions of mypy and Python you are using?
mypy 0.660
Python 3.6.5 -
Do you see the same issue after installing mypy from Git master?
Yes, got the same behavior with mypy 0.680+dev.21c8a812c697baf7394eafe360188ededcec6d9c
- What are the mypy flags you are using? (For example --strict-optional)
--strict