Created
March 21, 2017 17:07
-
-
Save dillonhicks/7fdba3453969590028f3ca9f569bab03 to your computer and use it in GitHub Desktop.
Package safe serialization
This file contains hidden or 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
| import abc | |
| from modulefinder import Module | |
| import ruamel.yaml as _yaml | |
| import six | |
| from ruamel.yaml.nodes import Node, ScalarNode | |
| from typing import Generic, TypeVar | |
| from typing import Type | |
| T = TypeVar('T') | |
| N = TypeVar('N', covariant=Node) | |
| class _BlinkLoader(_yaml.Loader): | |
| pass | |
| class _BlinkDumper(_yaml.Dumper): | |
| pass | |
| class YAMLType(Generic[T]): | |
| @abc.abstractmethod | |
| def name(self): | |
| # type: () -> str | |
| pass | |
| @abc.abstractmethod | |
| def python_type(self): | |
| # type: () -> type | |
| pass | |
| @abc.abstractmethod | |
| def representer(self, tag, data): | |
| # type: (six.string_types, T) -> N | |
| pass | |
| @abc.abstractmethod | |
| def constructor(self, tag_suffix, node): | |
| # type: (six.string_types, N) -> six.string_types | |
| pass | |
| def tag(self): | |
| return '!custom/type/{}'.format(self.name()) | |
| # noinspection PyUnresolvedReferences | |
| def register(self, yaml_module=_yaml): | |
| # type: (Module) -> None | |
| yaml_module.add_constructor(self.tag(), self.constructor, Loader=_BlinkLoader) | |
| yaml_module.add_representer(self.python_type(), self.representer, Dumper=_BlinkDumper) | |
| # | |
| # Test | |
| # | |
| from decimal import Decimal | |
| class DecimalYAMLType(YAMLType[Decimal]): | |
| def name(self): | |
| # type: () -> str | |
| return Decimal.__name__ | |
| def python_type(self): | |
| # type: () -> Type[Decimal] | |
| return Decimal | |
| def representer(self, tag, data): | |
| # type: (Decimal) -> ScalarNode | |
| return ScalarNode(self.tag(), str(data)) | |
| def constructor(self, tag_suffix, node): | |
| # type: (six.string_types, ScalarNode) -> Decimal | |
| return Decimal(node.value) | |
| def load(string): | |
| return _yaml.load(string, Loader=_BlinkLoader) | |
| def dump(obj): | |
| return _yaml.dump(obj, default_flow_style=False, Dumper=_BlinkDumper) | |
| # In some common place you'd register your extensions | |
| DecimalYAMLType().register() | |
| from datetime import datetime | |
| data = dict(ts=datetime.now(), cost=Decimal('123.45')) | |
| string = dump(data) | |
| print(string) | |
| data2 = load(string) | |
| print(data2) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment