Description
Opened in python/mypy#4040, but moved here after @JukkaL 's advice.
Some debate took place in there, but I'll copy the original post here for context:
It's a common practice to pass literal strings as arguments. In Python, it's even more important, as strings are often used instead of byte flags, constants or enums.
You often end up checking if those literals are passed correctly so you can give some debug information:
-
sorry, the parameter mode except a string among "started, paused, cancelled";
-
you can only used an integer between 0 and 16.
etc.
The problem with that is it's done at runtime despite the fact those argument are completely static ones. So the IDE can't use this information to help you write code. Typically, I would have code completion and linting helping me with "started/pause/cancelled" if it was an enum, but not if it's a string.
With this concept I could do:
MODES = ('started', 'paused', 'cancelled')
LEVELS = (
range(0, 5),
range(40, float('+inf')),
)
def foo(mode: typing.Among(MODES), levels: typing.Among(LEVELS)):
pass
So that mypy could alert my users if they do:
def foo("Start", 6):
Of course, it's only for strings/ints/floats literals, maybe bytes and tuple, as we need the information to be immutable and simple to be usable.