Exhaustive Checks with Mypy
Marcel Jackwerth
1 min read
If you want to exhaustively check an enum (or a literal) and have Mypy tell you when you forgot a case, you can write yourself a tiny utility function:
from typing import NoReturn
def unreachable(v: NoReturn) -> NoReturn:
raise AssertionError()
You can then use it with match
(on Python 3.10) or is
:
import enum
from .utils import unreachable
class Fruit(enum.Enum):
APPLE = enum.auto()
BANANA = enum.auto()
def using_match(fruit: Fruit) -> int:
match fruit:
case Fruit.APPLE:
return 1
case Fruit.BANANA:
return 2
case _:
unreachable(fruit)
def using_is(fruit: Fruit) -> int:
if fruit is Fruit.APPLE:
return 1
elif fruit is Fruit.BANANA:
return 2
else:
unreachable(fruit)
But beware that this won't work for enums when using ==
as Mypy can't know whether the operator has been overridden:
def using_eq(fruit: Fruit) -> int:
if fruit == Fruit.APPLE:
return 1
elif fruit == Fruit.BANANA:
return 2
else:
# error: Argument 1 to "unreachable" has incompatible
# type "Fruit"; expected "NoReturn" [arg-type]
unreachable(fruit)
0
Subscribe to my newsletter
Read articles from Marcel Jackwerth directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Marcel Jackwerth
Marcel Jackwerth
Software Engineer @ Memfault, Ex-Fitbit, Ex-Pebble