typing icon indicating copy to clipboard operation
typing copied to clipboard

Literal of enum values

Open vnmabus opened this issue 4 years ago • 9 comments

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?

vnmabus avatar Jan 21 '21 16:01 vnmabus

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 avatar Feb 02 '21 08:02 PrettyWood

@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

ravwojdyla avatar Jun 09 '21 08:06 ravwojdyla

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:

  1. Invalid type alias: expression is not a valid type
  2. error: Variable "..." is not valid as a type

kunansy avatar Jan 27 '22 07:01 kunansy

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.

erictraut avatar Jan 27 '22 08:01 erictraut