Literal of enum values
I am trying to implement a function that, as the type of one argument, can accept either an Enum or a value of such an enum (because some Python programmers are more used to type strings instead of enum values). Currently I have managed to do the following:
class LinkageCriterion(enum.Enum):
WARD = "ward"
COMPLETE = "complete"
AVERAGE = "average"
SINGLE = "single"
LinkageCriterionLike = Union[
LinkageCriterion,
Literal["ward", "complete", "average", "single"]
]
My question is if there is a way to not repeat myself here, that is, if you can construct a Literal from the values of a given Enum, and if so, how?
Hi @vnmabus How about
lit = Literal["ward", "complete", "average", "single"]
lit2 = Literal[tuple(x.value for x in LinkageCriterion.__members__.values())]
assert lit == lit2
Hope it helps
@PrettyWood
lit2 = Literal[tuple(x.value for x in LinkageCriterion.__members__.values())]
is not going to type check, see https://mypy.readthedocs.io/en/stable/literal_types.html#parameterizing-literals
Type check fails, it's impossible to create literal from enum (really, why?..)
NAMES = Literal[
MyEnum.field.name,
MyEnum.another_field.name,
]
VALUES = Literal[
MyEnum.field.value,
MyEnum.another_field.value,
]
def f(v: NAMES) -> VALUES:
pass
produces:
- Invalid type alias: expression is not a valid type
- error: Variable "..." is not valid as a type
Literal accepts only literal value expressions (str, bytes, bool, None, or enum values). It doesn't accept arbitrary variables or other complex expressions. Refer to PEP 586 for details.
To make this work, you would need to duplicate the literal values in the type declaration, as in the original poster's example.