Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/utils/datastructures.py: 60%
177 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1import copy
2from collections.abc import Mapping
5class OrderedSet:
6 """
7 A set which keeps the ordering of the inserted items.
8 """
10 def __init__(self, iterable=None):
11 self.dict = dict.fromkeys(iterable or ())
13 def add(self, item):
14 self.dict[item] = None
16 def remove(self, item):
17 del self.dict[item]
19 def discard(self, item):
20 try:
21 self.remove(item)
22 except KeyError:
23 pass
25 def __iter__(self):
26 return iter(self.dict)
28 def __reversed__(self):
29 return reversed(self.dict)
31 def __contains__(self, item):
32 return item in self.dict
34 def __bool__(self):
35 return bool(self.dict)
37 def __len__(self):
38 return len(self.dict)
40 def __repr__(self):
41 data = repr(list(self.dict)) if self.dict else ""
42 return f"{self.__class__.__qualname__}({data})"
45class MultiValueDictKeyError(KeyError):
46 pass
49class MultiValueDict(dict):
50 """
51 A subclass of dictionary customized to handle multiple values for the
52 same key.
54 >>> d = MultiValueDict({'name': ['Adrian', 'Simon'], 'position': ['Developer']})
55 >>> d['name']
56 'Simon'
57 >>> d.getlist('name')
58 ['Adrian', 'Simon']
59 >>> d.getlist('doesnotexist')
60 []
61 >>> d.getlist('doesnotexist', ['Adrian', 'Simon'])
62 ['Adrian', 'Simon']
63 >>> d.get('lastname', 'nonexistent')
64 'nonexistent'
65 >>> d.setlist('lastname', ['Holovaty', 'Willison'])
67 This class exists to solve the irritating problem raised by cgi.parse_qs,
68 which returns a list for every key, even though most web forms submit
69 single name-value pairs.
70 """
72 def __init__(self, key_to_list_mapping=()):
73 super().__init__(key_to_list_mapping)
75 def __repr__(self):
76 return "<%s: %s>" % (self.__class__.__name__, super().__repr__())
78 def __getitem__(self, key):
79 """
80 Return the last data value for this key, or [] if it's an empty list;
81 raise KeyError if not found.
82 """
83 try:
84 list_ = super().__getitem__(key)
85 except KeyError:
86 raise MultiValueDictKeyError(key)
87 try:
88 return list_[-1]
89 except IndexError:
90 return []
92 def __setitem__(self, key, value):
93 super().__setitem__(key, [value])
95 def __copy__(self):
96 return self.__class__([(k, v[:]) for k, v in self.lists()])
98 def __deepcopy__(self, memo):
99 result = self.__class__()
100 memo[id(self)] = result
101 for key, value in dict.items(self):
102 dict.__setitem__(
103 result, copy.deepcopy(key, memo), copy.deepcopy(value, memo)
104 )
105 return result
107 def __getstate__(self):
108 return {**self.__dict__, "_data": {k: self._getlist(k) for k in self}}
110 def __setstate__(self, obj_dict):
111 data = obj_dict.pop("_data", {})
112 for k, v in data.items():
113 self.setlist(k, v)
114 self.__dict__.update(obj_dict)
116 def get(self, key, default=None):
117 """
118 Return the last data value for the passed key. If key doesn't exist
119 or value is an empty list, return `default`.
120 """
121 try:
122 val = self[key]
123 except KeyError:
124 return default
125 if val == []: 125 ↛ 126line 125 didn't jump to line 126, because the condition on line 125 was never true
126 return default
127 return val
129 def _getlist(self, key, default=None, force_list=False):
130 """
131 Return a list of values for the key.
133 Used internally to manipulate values list. If force_list is True,
134 return a new copy of values.
135 """
136 try:
137 values = super().__getitem__(key)
138 except KeyError:
139 if default is None:
140 return []
141 return default
142 else:
143 if force_list:
144 values = list(values) if values is not None else None
145 return values
147 def getlist(self, key, default=None):
148 """
149 Return the list of values for the key. If key doesn't exist, return a
150 default value.
151 """
152 return self._getlist(key, default, force_list=True)
154 def setlist(self, key, list_):
155 super().__setitem__(key, list_)
157 def setdefault(self, key, default=None):
158 if key not in self:
159 self[key] = default
160 # Do not return default here because __setitem__() may store
161 # another value -- QueryDict.__setitem__() does. Look it up.
162 return self[key]
164 def setlistdefault(self, key, default_list=None):
165 if key not in self:
166 if default_list is None: 166 ↛ 168line 166 didn't jump to line 168, because the condition on line 166 was never false
167 default_list = []
168 self.setlist(key, default_list)
169 # Do not return default_list here because setlist() may store
170 # another value -- QueryDict.setlist() does. Look it up.
171 return self._getlist(key)
173 def appendlist(self, key, value):
174 """Append an item to the internal list associated with key."""
175 self.setlistdefault(key).append(value)
177 def items(self):
178 """
179 Yield (key, value) pairs, where value is the last item in the list
180 associated with the key.
181 """
182 for key in self:
183 yield key, self[key]
185 def lists(self):
186 """Yield (key, list) pairs."""
187 return iter(super().items())
189 def values(self):
190 """Yield the last value on every key list."""
191 for key in self:
192 yield self[key]
194 def copy(self):
195 """Return a shallow copy of this object."""
196 return copy.copy(self)
198 def update(self, *args, **kwargs):
199 """Extend rather than replace existing key lists."""
200 if len(args) > 1: 200 ↛ 201line 200 didn't jump to line 201, because the condition on line 200 was never true
201 raise TypeError("update expected at most 1 argument, got %d" % len(args))
202 if args: 202 ↛ 212line 202 didn't jump to line 212, because the condition on line 202 was never false
203 arg = args[0]
204 if isinstance(arg, MultiValueDict): 204 ↛ 208line 204 didn't jump to line 208, because the condition on line 204 was never false
205 for key, value_list in arg.lists():
206 self.setlistdefault(key).extend(value_list)
207 else:
208 if isinstance(arg, Mapping):
209 arg = arg.items()
210 for key, value in arg:
211 self.setlistdefault(key).append(value)
212 for key, value in kwargs.items(): 212 ↛ 213line 212 didn't jump to line 213, because the loop on line 212 never started
213 self.setlistdefault(key).append(value)
215 def dict(self):
216 """Return current object as a dict with singular values."""
217 return {key: self[key] for key in self}
220class ImmutableList(tuple):
221 """
222 A tuple-like object that raises useful errors when it is asked to mutate.
224 Example::
226 >>> a = ImmutableList(range(5), warning="You cannot mutate this.")
227 >>> a[3] = '4'
228 Traceback (most recent call last):
229 ...
230 AttributeError: You cannot mutate this.
231 """
233 def __new__(cls, *args, warning="ImmutableList object is immutable.", **kwargs):
234 self = tuple.__new__(cls, *args, **kwargs)
235 self.warning = warning
236 return self
238 def complain(self, *args, **kwargs):
239 raise AttributeError(self.warning)
241 # All list mutation functions complain.
242 __delitem__ = complain
243 __delslice__ = complain
244 __iadd__ = complain
245 __imul__ = complain
246 __setitem__ = complain
247 __setslice__ = complain
248 append = complain
249 extend = complain
250 insert = complain
251 pop = complain
252 remove = complain
253 sort = complain
254 reverse = complain
257class DictWrapper(dict):
258 """
259 Wrap accesses to a dictionary so that certain values (those starting with
260 the specified prefix) are passed through a function before being returned.
261 The prefix is removed before looking up the real value.
263 Used by the SQL construction code to ensure that values are correctly
264 quoted before being used.
265 """
267 def __init__(self, data, func, prefix):
268 super().__init__(data)
269 self.func = func
270 self.prefix = prefix
272 def __getitem__(self, key):
273 """
274 Retrieve the real value after stripping the prefix string (if
275 present). If the prefix is present, pass the value through self.func
276 before returning, otherwise return the raw value.
277 """
278 use_func = key.startswith(self.prefix)
279 if use_func: 279 ↛ 280line 279 didn't jump to line 280, because the condition on line 279 was never true
280 key = key[len(self.prefix) :]
281 value = super().__getitem__(key)
282 if use_func: 282 ↛ 283line 282 didn't jump to line 283, because the condition on line 282 was never true
283 return self.func(value)
284 return value
287def _destruct_iterable_mapping_values(data):
288 for i, elem in enumerate(data):
289 if len(elem) != 2:
290 raise ValueError(
291 "dictionary update sequence element #{} has "
292 "length {}; 2 is required.".format(i, len(elem))
293 )
294 if not isinstance(elem[0], str):
295 raise ValueError(
296 "Element key %r invalid, only strings are allowed" % elem[0]
297 )
298 yield tuple(elem)
301class CaseInsensitiveMapping(Mapping):
302 """
303 Mapping allowing case-insensitive key lookups. Original case of keys is
304 preserved for iteration and string representation.
306 Example::
308 >>> ci_map = CaseInsensitiveMapping({'name': 'Jane'})
309 >>> ci_map['Name']
310 Jane
311 >>> ci_map['NAME']
312 Jane
313 >>> ci_map['name']
314 Jane
315 >>> ci_map # original case preserved
316 {'name': 'Jane'}
317 """
319 def __init__(self, data):
320 if not isinstance(data, Mapping):
321 data = {k: v for k, v in _destruct_iterable_mapping_values(data)}
322 self._store = {k.lower(): (k, v) for k, v in data.items()}
324 def __getitem__(self, key):
325 return self._store[key.lower()][1]
327 def __len__(self):
328 return len(self._store)
330 def __eq__(self, other):
331 return isinstance(other, Mapping) and {
332 k.lower(): v for k, v in self.items()
333 } == {k.lower(): v for k, v in other.items()}
335 def __iter__(self):
336 return (original_key for original_key, value in self._store.values())
338 def __repr__(self):
339 return repr({key: value for key, value in self._store.values()})
341 def copy(self):
342 return self