Advertisement
Guest User

Untitled

a guest
Sep 16th, 2019
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.57 KB | None | 0 0
  1. from enum import Enum
  2. from functools import lru_cache
  3. from typing import Dict, Sequence, Any, Callable, Iterable, Tuple, Type, Generic, TypeVar, Union
  4.  
  5. E = TypeVar("E", bound=Enum)
  6.  
  7. Transformer = Callable[[Any], Any]
  8.  
  9.  
  10. def name_of(enum_or_name: Union[E, str]) -> str:
  11. if isinstance(enum_or_name, str):
  12. return enum_or_name
  13. else:
  14. return enum_or_name.name
  15.  
  16.  
  17. class EnumCallable(Generic[E]):
  18. def __init__(
  19. self,
  20. enum_type: Type[E],
  21. enum_func_registry: Union[
  22. Iterable[Tuple[Union[E, str], Transformer]],
  23. Dict[Union[E, str], Transformer],
  24. ],
  25. validate: bool = True,
  26. ) -> None:
  27. self._enum_type = enum_type
  28. if validate and not issubclass(self._enum_type, Enum):
  29. raise TypeError(f"Expecting an enum type, not '{self._enum_type}'")
  30.  
  31. enum2func = (
  32. enum_func_registry.items()
  33. if isinstance(enum_func_registry, dict)
  34. else enum_func_registry
  35. )
  36.  
  37. self._enum2func = {name_of(enum_val): func for enum_val, func in enum2func}
  38. if validate:
  39. vals = set(map(lambda e: e.name, self.values))
  40. for enum_name in self._enum2func.keys():
  41. if enum_name not in vals:
  42. raise ValueError(f"No function for enum value named: '{enum_name}'")
  43.  
  44. @property
  45. @lru_cache(1)
  46. def values(self) -> tuple:
  47. """Obtain all distinct enum values.
  48. """
  49. return tuple(self._enum_type._member_map_.values())
  50.  
  51. def get_transformer(self, e: E) -> Callable[[Any], Any]:
  52. """Obtain the registered transformation function for the specific enum value.
  53. """
  54. return self._enum2func[e.name]
  55.  
  56. def transform(self, enum_val_or_name: Union[E, str], value: Any) -> Any:
  57. """Applies the function registered for the enum's specific value.
  58. """
  59. return self._enum2func[name_of(enum_val_or_name)](value)
  60.  
  61. def __call__(self, *args, **kwargs):
  62. """Alis for :func:`transform`.
  63. """
  64. return self.transform(*args, **kwargs)
  65.  
  66.  
  67. def test_enum_callable():
  68. ET = Enum("ET", ["a", "b", "c"])
  69. ec = EnumCallable(
  70. enum_type=ET,
  71. enum_func_registry={
  72. ET["a"]: lambda x: x + 1,
  73. "b": lambda x: x % 2 == 0,
  74. ET["c"]: lambda x: x * 10,
  75. },
  76. validate=True,
  77. )
  78. assert ec.transform(ET["a"], 0) == 1
  79. assert ec.transform(ET["b"], 6)
  80. assert ec.transform(ET["c"], -10) == -100
  81. assert ec.transform("a", -1) == 0
  82. assert ec.transform("b", 2)
  83. assert ec.transform("c", 99) == 990
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement