File: _serizlizer.py

package info (click to toggle)
freeorion 0.5.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 194,940 kB
  • sloc: cpp: 186,508; python: 40,969; ansic: 1,164; xml: 719; makefile: 32; sh: 7
file content (81 lines) | stat: -rw-r--r-- 2,685 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
from abc import ABC
from typing import Callable, TypeVar

Serializable = TypeVar("Serializable")


class Serializer(ABC):
    def __init__(
        self,
        *,
        serializer: Callable[[Serializable], str],
        deserializer: Callable[[str], Serializable],
    ):
        self._deserializer = deserializer
        self._serializer = serializer

    def deserialize(self, value: str) -> Serializable:
        try:
            return self._deserializer(value)
        except Exception as e:
            raise ValueError(f"{self.__class__.__name__} fail to deserialize {value}: {e}") from e

    def serialize(self, value: Serializable) -> str:
        return self._serializer(value)


class _IntSerializer(Serializer):
    def __init__(self):
        super().__init__(serializer=str, deserializer=int)


class _FloatSerializer(Serializer):
    def __init__(self):
        super().__init__(serializer=str, deserializer=float)


class _StrSerializer(Serializer):
    def __init__(self):
        super().__init__(serializer=str, deserializer=str.strip)


class ListSerializer(Serializer):
    def __init__(self, item_serializer: Serializer):
        def serializer(value: list[Serializable]) -> str:
            return ", ".join(item_serializer.serialize(val) for val in value)

        def deserializer(serialized: str) -> Serializable:
            elements = serialized.split(",")
            return [item_serializer.deserialize(v) for v in elements]

        super().__init__(serializer=serializer, deserializer=deserializer)


class DictSerializer(Serializer):
    def __init__(self, items: dict[str, Serializer]):
        def serializer(value: dict[str, Serializable]) -> str:
            assert set(value) == set(items), f"Keys should match {sorted(value)} != {sorted(items)}"
            serialized_dict = {}
            for key, val in value.items():  # preserve order of values dict
                serializer_instance = items[key]
                serialized_dict[key] = serializer_instance.serialize(val)

            return ", ".join(f"{k}: {v}" for k, v in serialized_dict.items())

        def deserializer(serialized: str) -> Serializable:
            elements = serialized.split(",")
            assert len(elements) == len(items)

            def extract_pair(pair_string: str):
                key, val = pair_string.split(":")
                return key.strip(), val.strip()

            pairs = (extract_pair(x) for x in elements)
            return {k: items[k].deserialize(v) for (k, v) in pairs}

        super().__init__(serializer=serializer, deserializer=deserializer)


to_int = _IntSerializer()
to_str = _StrSerializer()
to_float = _FloatSerializer()