Created
February 8, 2024 22:00
-
-
Save nerodono/15ed162280174f8f790481dbc26bae5e to your computer and use it in GitHub Desktop.
Stupidly simple mapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from typing import ( | |
Generic, | |
TypeVar, | |
Protocol, | |
Any, | |
Type, | |
NewType, | |
) | |
T = TypeVar("T") | |
R = TypeVar("R") | |
Src = TypeVar("Src", contravariant=True) | |
Dst = TypeVar("Dst", covariant=True) | |
class ConvertRule(Protocol[Src, Dst]): | |
def __call__(self, src: Src, /) -> Dst: | |
... | |
class RulesStore(Generic[T]): | |
__slots__ = ('rules', ) | |
def __init__(self, rules: dict[Any, ConvertRule[T, Any]]) -> None: | |
self.rules = rules | |
def add_rule( | |
self, | |
# Это можно и убрать вообще, но для lambda полезно | |
to_tp: Type[Dst], | |
rule: ConvertRule[T, Dst] | |
) -> None: | |
self.rules[to_tp] = rule | |
def convert(self, value: T, tp: Type[Dst]) -> Dst: | |
return self.rules[tp](value) | |
class ObjectMapper: | |
__slots__ = ('_types', ) | |
def __init__(self) -> None: | |
self._types: dict[Any, RulesStore[Any]] = {} | |
def convert( | |
self, | |
src_tp: Type[Src], | |
dst_tp: Type[Dst], | |
src: Src, | |
) -> Dst: | |
return self._types[src_tp].convert(src, dst_tp) | |
def add_rule( | |
self, | |
src_tp: Type[Src], | |
dst_tp: Type[Dst], | |
rule: ConvertRule[Src, Dst], | |
) -> None: | |
store = self._types.get(src_tp) | |
if store is None: | |
store = RulesStore[Src]({}) | |
self._types[src_tp] = store | |
store.add_rule(dst_tp, rule) | |
Age = NewType("Age", int) | |
mapper = ObjectMapper() | |
mapper.add_rule(int, str, str) | |
mapper.add_rule(int, Age, Age) | |
mapper.add_rule(int, int, lambda x: x + 10) | |
print(repr(mapper.convert(int, str, 10))) | |
print(repr(mapper.convert(int, Age, 13))) # Уже нормальная такая женщина | |
print(mapper.convert(int, int, 1478)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment