1"""
2    :codeauthor: Pedro Algarvio (pedro@algarvio.me)
3
4
5    salt.utils.immutabletypes
6    ~~~~~~~~~~~~~~~~~~~~~~~~~
7
8    Immutable types
9"""
10
11import copy
12from collections.abc import Mapping, Sequence, Set
13
14
15class ImmutableDict(Mapping):
16    """
17    An immutable dictionary implementation
18    """
19
20    def __init__(self, obj):
21        self.__obj = obj
22
23    def __len__(self):
24        return len(self.__obj)
25
26    def __iter__(self):
27        return iter(self.__obj)
28
29    def __getitem__(self, key):
30        return freeze(self.__obj[key])
31
32    def __repr__(self):
33        return "<{} {}>".format(self.__class__.__name__, repr(self.__obj))
34
35    def __deepcopy__(self, memo):
36        return copy.deepcopy(self.__obj)
37
38    def copy(self):
39        """
40        Return an un-frozen copy of self
41        """
42        return copy.deepcopy(self.__obj)
43
44
45class ImmutableList(Sequence):
46    """
47    An immutable list implementation
48    """
49
50    def __init__(self, obj):
51        self.__obj = obj
52
53    def __len__(self):
54        return len(self.__obj)
55
56    def __iter__(self):
57        return iter(self.__obj)
58
59    def __add__(self, other):
60        return self.__obj + other
61
62    def __radd__(self, other):
63        return other + self.__obj
64
65    def __getitem__(self, key):
66        return freeze(self.__obj[key])
67
68    def __repr__(self):
69        return "<{} {}>".format(self.__class__.__name__, repr(self.__obj))
70
71    def __deepcopy__(self, memo):
72        return copy.deepcopy(self.__obj)
73
74    def copy(self):
75        """
76        Return an un-frozen copy of self
77        """
78        return copy.deepcopy(self.__obj)
79
80
81class ImmutableSet(Set):
82    """
83    An immutable set implementation
84    """
85
86    def __init__(self, obj):
87        self.__obj = obj
88
89    def __len__(self):
90        return len(self.__obj)
91
92    def __iter__(self):
93        return iter(self.__obj)
94
95    def __contains__(self, key):
96        return key in self.__obj
97
98    def __repr__(self):
99        return "<{} {}>".format(self.__class__.__name__, repr(self.__obj))
100
101    def __deepcopy__(self, memo):
102        return copy.deepcopy(self.__obj)
103
104    def copy(self):
105        """
106        Return an un-frozen copy of self
107        """
108        return copy.deepcopy(self.__obj)
109
110
111def freeze(obj):
112    """
113    Freeze python types by turning them into immutable structures.
114    """
115    if isinstance(obj, dict):
116        return ImmutableDict(obj)
117    if isinstance(obj, list):
118        return ImmutableList(obj)
119    if isinstance(obj, set):
120        return ImmutableSet(obj)
121    return obj
122