Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/itypes.py: 21%

145 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1# coding: utf-8 

2try: 

3 from collections.abc import Mapping, Sequence 

4except ImportError: # support for python 2.x 

5 from collections import Mapping, Sequence 

6 

7 

8__version__ = '1.2.0' 

9 

10 

11def to_mutable(instance): 

12 if isinstance(instance, Dict): 

13 return { 

14 key: to_mutable(value) 

15 for key, value in instance.items() 

16 } 

17 elif isinstance(instance, List): 

18 return [ 

19 to_mutable(value) 

20 for value in instance 

21 ] 

22 return instance 

23 

24 

25def to_immutable(value): 

26 if isinstance(value, dict): 

27 return Dict(value) 

28 elif isinstance(value, list): 

29 return List(value) 

30 return value 

31 

32 

33def _to_hashable(instance): 

34 if isinstance(instance, Dict): 

35 items = sorted(instance.items(), key=lambda item: item[0]) 

36 return ( 

37 (key, _to_hashable(value)) 

38 for key, value in items 

39 ) 

40 elif isinstance(instance, List): 

41 return [ 

42 _to_hashable(value) 

43 for value in instance 

44 ] 

45 return instance 

46 

47 

48def _set_in(node, keys, value): 

49 if not keys: 

50 return value 

51 elif len(keys) == 1: 

52 return node.set(keys[0], value) 

53 

54 key = keys[0] 

55 child = node[key] 

56 if not isinstance(child, (Dict, List)): 

57 msg = "Expected a container type at key '%s', but got '%s'" 

58 raise KeyError(msg % type(child)) 

59 child = child.set_in(keys[1:], value) 

60 return node.set(key, child) 

61 

62 

63def _delete_in(node, keys): 

64 if not keys: 

65 return 

66 elif len(keys) == 1: 

67 return node.delete(keys[0]) 

68 

69 key = keys[0] 

70 child = node[key] 

71 if not isinstance(child, (Dict, List)): 

72 msg = "Expected a container type at key '%s', but got '%s'" 

73 raise KeyError(msg % type(child)) 

74 child = child.delete_in(keys[1:]) 

75 return node.set(key, child) 

76 

77 

78def _get_in(node, keys, default=None): 

79 if not keys: 

80 return default 

81 

82 key = keys[0] 

83 try: 

84 child = node[key] 

85 except (KeyError, IndexError): 

86 return default 

87 

88 if len(keys) == 1: 

89 return child 

90 return child.get_in(keys[1:], default=default) 

91 

92 

93class Object(object): 

94 def __setattr__(self, key, value): 

95 if key.startswith('_'): 

96 return object.__setattr__(self, key, value) 

97 msg = "'%s' object doesn't support property assignment." 

98 raise TypeError(msg % self.__class__.__name__) 

99 

100 

101class Dict(Mapping): 

102 def __init__(self, *args, **kwargs): 

103 self._data = { 

104 key: to_immutable(value) 

105 for key, value in dict(*args, **kwargs).items() 

106 } 

107 

108 def __setattr__(self, key, value): 

109 if key.startswith('_'): 

110 return object.__setattr__(self, key, value) 

111 msg = "'%s' object doesn't support property assignment." 

112 raise TypeError(msg % self.__class__.__name__) 

113 

114 def __getitem__(self, key): 

115 return self._data[key] 

116 

117 def __iter__(self): 

118 return iter(self._data) 

119 

120 def __len__(self): 

121 return len(self._data) 

122 

123 def __eq__(self, other): 

124 if isinstance(other, self.__class__): 

125 return self._data == other._data 

126 return self._data == other 

127 

128 def __hash__(self): 

129 return hash(_to_hashable(self)) 

130 

131 def __repr__(self): 

132 return "%s(%s)" % ( 

133 self.__class__.__name__, 

134 to_mutable(self) 

135 ) 

136 

137 def __str__(self): 

138 return str(self._data) 

139 

140 def set(self, key, value): 

141 data = dict(self._data) 

142 data[key] = value 

143 if hasattr(self, 'clone'): 

144 return self.clone(data) 

145 return type(self)(data) 

146 

147 def delete(self, key): 

148 data = dict(self._data) 

149 data.pop(key) 

150 if hasattr(self, 'clone'): 

151 return self.clone(data) 

152 return type(self)(data) 

153 

154 def get_in(self, keys, default=None): 

155 return _get_in(self, keys, default=default) 

156 

157 def set_in(self, keys, value): 

158 return _set_in(self, keys, value) 

159 

160 def delete_in(self, keys): 

161 return _delete_in(self, keys) 

162 

163 

164class List(Sequence): 

165 def __init__(self, *args): 

166 self._data = [ 

167 to_immutable(value) 

168 for value in list(*args) 

169 ] 

170 

171 def __setattr__(self, key, value): 

172 if key == '_data': 

173 return object.__setattr__(self, key, value) 

174 msg = "'%s' object doesn't support property assignment." 

175 raise TypeError(msg % self.__class__.__name__) 

176 

177 def __getitem__(self, key): 

178 return self._data[key] 

179 

180 def __iter__(self): 

181 return iter(self._data) 

182 

183 def __len__(self): 

184 return len(self._data) 

185 

186 def __eq__(self, other): 

187 if isinstance(other, self.__class__): 

188 return self._data == other._data 

189 return self._data == other 

190 

191 def __hash__(self): 

192 return hash(_to_hashable(self)) 

193 

194 def __repr__(self): 

195 return "%s(%s)" % ( 

196 self.__class__.__name__, 

197 to_mutable(self) 

198 ) 

199 

200 def __str__(self): 

201 return str(self._data) 

202 

203 def set(self, key, value): 

204 data = list(self._data) 

205 data[key] = value 

206 if hasattr(self, 'clone'): 

207 return self.clone(data) 

208 return type(self)(data) 

209 

210 def delete(self, key): 

211 data = list(self._data) 

212 data.pop(key) 

213 if hasattr(self, 'clone'): 

214 return self.clone(data) 

215 return type(self)(data) 

216 

217 def get_in(self, keys, default=None): 

218 return _get_in(self, keys, default=default) 

219 

220 def set_in(self, keys, value): 

221 return _set_in(self, keys, value) 

222 

223 def delete_in(self, keys): 

224 return _delete_in(self, keys)