Skip to content

Instantly share code, notes, and snippets.

@malcolmgreaves
Last active May 3, 2023 22:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save malcolmgreaves/a59462e15e6ed9b4270c8ecd69db4125 to your computer and use it in GitHub Desktop.
Save malcolmgreaves/a59462e15e6ed9b4270c8ecd69db4125 to your computer and use it in GitHub Desktop.
Function to create a function that can parse `str -> Enum instance` and one from `Enum instance -> str`.
from enum import Enum
from typing import Callable, Optional, Type, TypeVar
class EnumStr(str, Enum):
pass
E = TypeVar('E', bound=EnumStr)
EnumParser = Callable[[Optional[str]], Optional[E]]
EnumWriter = Callable[[Optional[E]], Optional[str]]
def create_enum_parser(enum_cls: Type[E]) -> EnumParser[E]:
if not issubclass(enum_cls, EnumStr):
raise TypeError(f"Expecting {enum_cls} to be an Enum type!")
def parse(maybe_value: Optional[str]) -> Optional[E]:
if maybe_value is None:
return None
try:
return enum_cls(maybe_value)
except ValueError as e:
raise ValueError(f"{str(e)}: use one of {list(enum_cls.__members__.values())}")
return parse
def create_enum_writer(enum_cls: Type[E]) -> EnumWriter[E]:
if not issubclass(enum_cls, EnumStr):
raise TypeError(f"Expecting {enum_cls} to be an Enum type!")
def write(maybe_enum: Optional[E]) -> Optional[str]:
if maybe_enum is None:
return None
return maybe_enum.value
return write
#
# use
#
class Example(EnumStr):
name1 = "value1"
name2 = "value2"
example_parser: EnumParser[Example] = create_enum_parser(Example)
example_writer: EnumWriter[Example] = create_enum_writer(Example)
print(f'{example_parser("value1")=}')
print(f'{example_writer(Example.name2)=}')
# produces:
# example_parser("value1")=<Example.name1: 'value1'>
# example_writer(Example.name2)='value2'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment