1from __future__ import annotations
2
3import collections.abc as cabc
4import typing as t
5from copy import deepcopy
6
7from .. import exceptions
8from .._internal import _missing
9from .mixins import ImmutableDictMixin
10from .mixins import ImmutableListMixin
11from .mixins import ImmutableMultiDictMixin
12from .mixins import UpdateDictMixin
13
14if t.TYPE_CHECKING:
15 import typing_extensions as te
16
17K = t.TypeVar("K")
18V = t.TypeVar("V")
19T = t.TypeVar("T")
20
21
22def iter_multi_items(
23 mapping: (
24 MultiDict[K, V]
25 | cabc.Mapping[K, V | list[V] | tuple[V, ...] | set[V]]
26 | cabc.Iterable[tuple[K, V]]
27 ),
28) -> cabc.Iterator[tuple[K, V]]:
29 """Iterates over the items of a mapping yielding keys and values
30 without dropping any from more complex structures.
31 """
32 if isinstance(mapping, MultiDict):
33 yield from mapping.items(multi=True)
34 elif isinstance(mapping, cabc.Mapping):
35 for key, value in mapping.items():
36 if isinstance(value, (list, tuple, set)):
37 for v in value:
38 yield key, v
39 else:
40 yield key, value
41 else:
42 yield from mapping
43
44
45class ImmutableList(ImmutableListMixin, list[V]): # type: ignore[misc]
46 """An immutable :class:`list`.
47
48 .. versionadded:: 0.5
49
50 :private:
51 """
52
53 def __repr__(self) -> str:
54 return f"{type(self).__name__}({list.__repr__(self)})"
55
56
57class TypeConversionDict(dict[K, V]):
58 """Works like a regular dict but the :meth:`get` method can perform
59 type conversions. :class:`MultiDict` and :class:`CombinedMultiDict`
60 are subclasses of this class and provide the same feature.
61
62 .. versionadded:: 0.5
63 """
64
65 @t.overload # type: ignore[override]
66 def get(self, key: K) -> V | None: ...
67 @t.overload
68 def get(self, key: K, default: V) -> V: ...
69 @t.overload
70 def get(self, key: K, default: T) -> V | T: ...
71 @t.overload
72 def get(self, key: str, type: cabc.Callable[[V], T]) -> T | None: ...
73 @t.overload
74 def get(self, key: str, default: T, type: cabc.Callable[[V], T]) -> T: ...
75 def get( # type: ignore[misc]
76 self,
77 key: K,
78 default: V | T | None = None,
79 type: cabc.Callable[[V], T] | None = None,
80 ) -> V | T | None:
81 """Return the default value if the requested data doesn't exist.
82 If `type` is provided and is a callable it should convert the value,
83 return it or raise a :exc:`ValueError` if that is not possible. In
84 this case the function will return the default as if the value was not
85 found:
86
87 >>> d = TypeConversionDict(foo='42', bar='blub')
88 >>> d.get('foo', type=int)
89 42
90 >>> d.get('bar', -1, type=int)
91 -1
92
93 :param key: The key to be looked up.
94 :param default: The default value to be returned if the key can't
95 be looked up. If not further specified `None` is
96 returned.
97 :param type: A callable that is used to cast the value in the
98 :class:`MultiDict`. If a :exc:`ValueError` or a
99 :exc:`TypeError` is raised by this callable the default
100 value is returned.
101
102 .. versionchanged:: 3.0.2
103 Returns the default value on :exc:`TypeError`, too.
104 """
105 try:
106 rv = self[key]
107 except KeyError:
108 return default
109
110 if type is None:
111 return rv
112
113 try:
114 return type(rv)
115 except (ValueError, TypeError):
116 return default
117
118
119class ImmutableTypeConversionDict(ImmutableDictMixin[K, V], TypeConversionDict[K, V]): # type: ignore[misc]
120 """Works like a :class:`TypeConversionDict` but does not support
121 modifications.
122
123 .. versionadded:: 0.5
124 """
125
126 def copy(self) -> TypeConversionDict[K, V]:
127 """Return a shallow mutable copy of this object. Keep in mind that
128 the standard library's :func:`copy` function is a no-op for this class
129 like for any other python immutable type (eg: :class:`tuple`).
130 """
131 return TypeConversionDict(self)
132
133 def __copy__(self) -> te.Self:
134 return self
135
136
137class MultiDict(TypeConversionDict[K, V]):
138 """A :class:`MultiDict` is a dictionary subclass customized to deal with
139 multiple values for the same key which is for example used by the parsing
140 functions in the wrappers. This is necessary because some HTML form
141 elements pass multiple values for the same key.
142
143 :class:`MultiDict` implements all standard dictionary methods.
144 Internally, it saves all values for a key as a list, but the standard dict
145 access methods will only return the first value for a key. If you want to
146 gain access to the other values, too, you have to use the `list` methods as
147 explained below.
148
149 Basic Usage:
150
151 >>> d = MultiDict([('a', 'b'), ('a', 'c')])
152 >>> d
153 MultiDict([('a', 'b'), ('a', 'c')])
154 >>> d['a']
155 'b'
156 >>> d.getlist('a')
157 ['b', 'c']
158 >>> 'a' in d
159 True
160
161 It behaves like a normal dict thus all dict functions will only return the
162 first value when multiple values for one key are found.
163
164 From Werkzeug 0.3 onwards, the `KeyError` raised by this class is also a
165 subclass of the :exc:`~exceptions.BadRequest` HTTP exception and will
166 render a page for a ``400 BAD REQUEST`` if caught in a catch-all for HTTP
167 exceptions.
168
169 A :class:`MultiDict` can be constructed from an iterable of
170 ``(key, value)`` tuples, a dict, a :class:`MultiDict` or from Werkzeug 0.2
171 onwards some keyword parameters.
172
173 :param mapping: the initial value for the :class:`MultiDict`. Either a
174 regular dict, an iterable of ``(key, value)`` tuples
175 or `None`.
176
177 .. versionchanged:: 3.1
178 Implement ``|`` and ``|=`` operators.
179 """
180
181 def __init__(
182 self,
183 mapping: (
184 MultiDict[K, V]
185 | cabc.Mapping[K, V | list[V] | tuple[V, ...] | set[V]]
186 | cabc.Iterable[tuple[K, V]]
187 | None
188 ) = None,
189 ) -> None:
190 if mapping is None:
191 super().__init__()
192 elif isinstance(mapping, MultiDict):
193 super().__init__((k, vs[:]) for k, vs in mapping.lists())
194 elif isinstance(mapping, cabc.Mapping):
195 tmp = {}
196 for key, value in mapping.items():
197 if isinstance(value, (list, tuple, set)):
198 value = list(value)
199
200 if not value:
201 continue
202 else:
203 value = [value]
204 tmp[key] = value
205 super().__init__(tmp) # type: ignore[arg-type]
206 else:
207 tmp = {}
208 for key, value in mapping:
209 tmp.setdefault(key, []).append(value)
210 super().__init__(tmp) # type: ignore[arg-type]
211
212 def __getstate__(self) -> t.Any:
213 return dict(self.lists())
214
215 def __setstate__(self, value: t.Any) -> None:
216 super().clear()
217 super().update(value)
218
219 def __iter__(self) -> cabc.Iterator[K]:
220 # https://github.com/python/cpython/issues/87412
221 # If __iter__ is not overridden, Python uses a fast path for dict(md),
222 # taking the data directly and getting lists of values, rather than
223 # calling __getitem__ and getting only the first value.
224 return super().__iter__()
225
226 def __getitem__(self, key: K) -> V:
227 """Return the first data value for this key;
228 raises KeyError if not found.
229
230 :param key: The key to be looked up.
231 :raise KeyError: if the key does not exist.
232 """
233
234 if key in self:
235 lst = super().__getitem__(key)
236 if len(lst) > 0: # type: ignore[arg-type]
237 return lst[0] # type: ignore[index,no-any-return]
238 raise exceptions.BadRequestKeyError(key)
239
240 def __setitem__(self, key: K, value: V) -> None:
241 """Like :meth:`add` but removes an existing key first.
242
243 :param key: the key for the value.
244 :param value: the value to set.
245 """
246 super().__setitem__(key, [value]) # type: ignore[assignment]
247
248 def add(self, key: K, value: V) -> None:
249 """Adds a new value for the key.
250
251 .. versionadded:: 0.6
252
253 :param key: the key for the value.
254 :param value: the value to add.
255 """
256 super().setdefault(key, []).append(value) # type: ignore[arg-type,attr-defined]
257
258 @t.overload
259 def getlist(self, key: K) -> list[V]: ...
260 @t.overload
261 def getlist(self, key: K, type: cabc.Callable[[V], T]) -> list[T]: ...
262 def getlist(
263 self, key: K, type: cabc.Callable[[V], T] | None = None
264 ) -> list[V] | list[T]:
265 """Return the list of items for a given key. If that key is not in the
266 `MultiDict`, the return value will be an empty list. Just like `get`,
267 `getlist` accepts a `type` parameter. All items will be converted
268 with the callable defined there.
269
270 :param key: The key to be looked up.
271 :param type: Callable to convert each value. If a ``ValueError`` or
272 ``TypeError`` is raised, the value is omitted.
273 :return: a :class:`list` of all the values for the key.
274
275 .. versionchanged:: 3.1
276 Catches ``TypeError`` in addition to ``ValueError``.
277 """
278 try:
279 rv: list[V] = super().__getitem__(key) # type: ignore[assignment]
280 except KeyError:
281 return []
282 if type is None:
283 return list(rv)
284 result = []
285 for item in rv:
286 try:
287 result.append(type(item))
288 except (ValueError, TypeError):
289 pass
290 return result
291
292 def setlist(self, key: K, new_list: cabc.Iterable[V]) -> None:
293 """Remove the old values for a key and add new ones. Note that the list
294 you pass the values in will be shallow-copied before it is inserted in
295 the dictionary.
296
297 >>> d = MultiDict()
298 >>> d.setlist('foo', ['1', '2'])
299 >>> d['foo']
300 '1'
301 >>> d.getlist('foo')
302 ['1', '2']
303
304 :param key: The key for which the values are set.
305 :param new_list: An iterable with the new values for the key. Old values
306 are removed first.
307 """
308 super().__setitem__(key, list(new_list)) # type: ignore[assignment]
309
310 @t.overload
311 def setdefault(self, key: K) -> None: ...
312 @t.overload
313 def setdefault(self, key: K, default: V) -> V: ...
314 def setdefault(self, key: K, default: V | None = None) -> V | None:
315 """Returns the value for the key if it is in the dict, otherwise it
316 returns `default` and sets that value for `key`.
317
318 :param key: The key to be looked up.
319 :param default: The default value to be returned if the key is not
320 in the dict. If not further specified it's `None`.
321 """
322 if key not in self:
323 self[key] = default # type: ignore[assignment]
324
325 return self[key]
326
327 def setlistdefault(
328 self, key: K, default_list: cabc.Iterable[V] | None = None
329 ) -> list[V]:
330 """Like `setdefault` but sets multiple values. The list returned
331 is not a copy, but the list that is actually used internally. This
332 means that you can put new values into the dict by appending items
333 to the list:
334
335 >>> d = MultiDict({"foo": 1})
336 >>> d.setlistdefault("foo").extend([2, 3])
337 >>> d.getlist("foo")
338 [1, 2, 3]
339
340 :param key: The key to be looked up.
341 :param default_list: An iterable of default values. It is either copied
342 (in case it was a list) or converted into a list
343 before returned.
344 :return: a :class:`list`
345 """
346 if key not in self:
347 super().__setitem__(key, list(default_list or ())) # type: ignore[assignment]
348
349 return super().__getitem__(key) # type: ignore[return-value]
350
351 def items(self, multi: bool = False) -> cabc.Iterable[tuple[K, V]]: # type: ignore[override]
352 """Return an iterator of ``(key, value)`` pairs.
353
354 :param multi: If set to `True` the iterator returned will have a pair
355 for each value of each key. Otherwise it will only
356 contain pairs for the first value of each key.
357 """
358 values: list[V]
359
360 for key, values in super().items(): # type: ignore[assignment]
361 if multi:
362 for value in values:
363 yield key, value
364 else:
365 yield key, values[0]
366
367 def lists(self) -> cabc.Iterable[tuple[K, list[V]]]:
368 """Return a iterator of ``(key, values)`` pairs, where values is the list
369 of all values associated with the key."""
370 values: list[V]
371
372 for key, values in super().items(): # type: ignore[assignment]
373 yield key, list(values)
374
375 def values(self) -> cabc.Iterable[V]: # type: ignore[override]
376 """Returns an iterator of the first value on every key's value list."""
377 values: list[V]
378
379 for values in super().values(): # type: ignore[assignment]
380 yield values[0]
381
382 def listvalues(self) -> cabc.Iterable[list[V]]:
383 """Return an iterator of all values associated with a key. Zipping
384 :meth:`keys` and this is the same as calling :meth:`lists`:
385
386 >>> d = MultiDict({"foo": [1, 2, 3]})
387 >>> zip(d.keys(), d.listvalues()) == d.lists()
388 True
389 """
390 return super().values() # type: ignore[return-value]
391
392 def copy(self) -> te.Self:
393 """Return a shallow copy of this object."""
394 return self.__class__(self)
395
396 def deepcopy(self, memo: t.Any = None) -> te.Self:
397 """Return a deep copy of this object."""
398 return self.__class__(deepcopy(self.to_dict(flat=False), memo))
399
400 @t.overload
401 def to_dict(self) -> dict[K, V]: ...
402 @t.overload
403 def to_dict(self, flat: t.Literal[False]) -> dict[K, list[V]]: ...
404 def to_dict(self, flat: bool = True) -> dict[K, V] | dict[K, list[V]]:
405 """Return the contents as regular dict. If `flat` is `True` the
406 returned dict will only have the first item present, if `flat` is
407 `False` all values will be returned as lists.
408
409 :param flat: If set to `False` the dict returned will have lists
410 with all the values in it. Otherwise it will only
411 contain the first value for each key.
412 :return: a :class:`dict`
413 """
414 if flat:
415 return dict(self.items())
416 return dict(self.lists())
417
418 def update( # type: ignore[override]
419 self,
420 mapping: (
421 MultiDict[K, V]
422 | cabc.Mapping[K, V | list[V] | tuple[V, ...] | set[V]]
423 | cabc.Iterable[tuple[K, V]]
424 ),
425 ) -> None:
426 """update() extends rather than replaces existing key lists:
427
428 >>> a = MultiDict({'x': 1})
429 >>> b = MultiDict({'x': 2, 'y': 3})
430 >>> a.update(b)
431 >>> a
432 MultiDict([('y', 3), ('x', 1), ('x', 2)])
433
434 If the value list for a key in ``other_dict`` is empty, no new values
435 will be added to the dict and the key will not be created:
436
437 >>> x = {'empty_list': []}
438 >>> y = MultiDict()
439 >>> y.update(x)
440 >>> y
441 MultiDict([])
442 """
443 for key, value in iter_multi_items(mapping):
444 self.add(key, value)
445
446 def __or__( # type: ignore[override]
447 self, other: cabc.Mapping[K, V | list[V] | tuple[V, ...] | set[V]]
448 ) -> MultiDict[K, V]:
449 if not isinstance(other, cabc.Mapping):
450 return NotImplemented
451
452 rv = self.copy()
453 rv.update(other)
454 return rv
455
456 def __ior__( # type: ignore[override]
457 self,
458 other: (
459 cabc.Mapping[K, V | list[V] | tuple[V, ...] | set[V]]
460 | cabc.Iterable[tuple[K, V]]
461 ),
462 ) -> te.Self:
463 if not isinstance(other, (cabc.Mapping, cabc.Iterable)):
464 return NotImplemented
465
466 self.update(other)
467 return self
468
469 @t.overload
470 def pop(self, key: K) -> V: ...
471 @t.overload
472 def pop(self, key: K, default: V) -> V: ...
473 @t.overload
474 def pop(self, key: K, default: T) -> V | T: ...
475 def pop(
476 self,
477 key: K,
478 default: V | T = _missing, # type: ignore[assignment]
479 ) -> V | T:
480 """Pop the first item for a list on the dict. Afterwards the
481 key is removed from the dict, so additional values are discarded:
482
483 >>> d = MultiDict({"foo": [1, 2, 3]})
484 >>> d.pop("foo")
485 1
486 >>> "foo" in d
487 False
488
489 :param key: the key to pop.
490 :param default: if provided the value to return if the key was
491 not in the dictionary.
492 """
493 lst: list[V]
494
495 try:
496 lst = super().pop(key) # type: ignore[assignment]
497
498 if len(lst) == 0:
499 raise exceptions.BadRequestKeyError(key)
500
501 return lst[0]
502 except KeyError:
503 if default is not _missing:
504 return default
505
506 raise exceptions.BadRequestKeyError(key) from None
507
508 def popitem(self) -> tuple[K, V]:
509 """Pop an item from the dict."""
510 item: tuple[K, list[V]]
511
512 try:
513 item = super().popitem() # type: ignore[assignment]
514
515 if len(item[1]) == 0:
516 raise exceptions.BadRequestKeyError(item[0])
517
518 return item[0], item[1][0]
519 except KeyError as e:
520 raise exceptions.BadRequestKeyError(e.args[0]) from None
521
522 def poplist(self, key: K) -> list[V]:
523 """Pop the list for a key from the dict. If the key is not in the dict
524 an empty list is returned.
525
526 .. versionchanged:: 0.5
527 If the key does no longer exist a list is returned instead of
528 raising an error.
529 """
530 return super().pop(key, []) # type: ignore[return-value]
531
532 def popitemlist(self) -> tuple[K, list[V]]:
533 """Pop a ``(key, list)`` tuple from the dict."""
534 try:
535 return super().popitem() # type: ignore[return-value]
536 except KeyError as e:
537 raise exceptions.BadRequestKeyError(e.args[0]) from None
538
539 def __copy__(self) -> te.Self:
540 return self.copy()
541
542 def __deepcopy__(self, memo: t.Any) -> te.Self:
543 return self.deepcopy(memo=memo)
544
545 def __repr__(self) -> str:
546 return f"{type(self).__name__}({list(self.items(multi=True))!r})"
547
548
549class _omd_bucket(t.Generic[K, V]):
550 """Wraps values in the :class:`OrderedMultiDict`. This makes it
551 possible to keep an order over multiple different keys. It requires
552 a lot of extra memory and slows down access a lot, but makes it
553 possible to access elements in O(1) and iterate in O(n).
554 """
555
556 __slots__ = ("prev", "key", "value", "next")
557
558 def __init__(self, omd: _OrderedMultiDict[K, V], key: K, value: V) -> None:
559 self.prev: _omd_bucket[K, V] | None = omd._last_bucket
560 self.key: K = key
561 self.value: V = value
562 self.next: _omd_bucket[K, V] | None = None
563
564 if omd._first_bucket is None:
565 omd._first_bucket = self
566 if omd._last_bucket is not None:
567 omd._last_bucket.next = self
568 omd._last_bucket = self
569
570 def unlink(self, omd: _OrderedMultiDict[K, V]) -> None:
571 if self.prev:
572 self.prev.next = self.next
573 if self.next:
574 self.next.prev = self.prev
575 if omd._first_bucket is self:
576 omd._first_bucket = self.next
577 if omd._last_bucket is self:
578 omd._last_bucket = self.prev
579
580
581class _OrderedMultiDict(MultiDict[K, V]):
582 """Works like a regular :class:`MultiDict` but preserves the
583 order of the fields. To convert the ordered multi dict into a
584 list you can use the :meth:`items` method and pass it ``multi=True``.
585
586 In general an :class:`OrderedMultiDict` is an order of magnitude
587 slower than a :class:`MultiDict`.
588
589 .. admonition:: note
590
591 Due to a limitation in Python you cannot convert an ordered
592 multi dict into a regular dict by using ``dict(multidict)``.
593 Instead you have to use the :meth:`to_dict` method, otherwise
594 the internal bucket objects are exposed.
595
596 .. deprecated:: 3.1
597 Will be removed in Werkzeug 3.2. Use ``MultiDict`` instead.
598 """
599
600 def __init__(
601 self,
602 mapping: (
603 MultiDict[K, V]
604 | cabc.Mapping[K, V | list[V] | tuple[V, ...] | set[V]]
605 | cabc.Iterable[tuple[K, V]]
606 | None
607 ) = None,
608 ) -> None:
609 import warnings
610
611 warnings.warn(
612 "'OrderedMultiDict' is deprecated and will be removed in Werkzeug"
613 " 3.2. Use 'MultiDict' instead.",
614 DeprecationWarning,
615 stacklevel=2,
616 )
617 super().__init__()
618 self._first_bucket: _omd_bucket[K, V] | None = None
619 self._last_bucket: _omd_bucket[K, V] | None = None
620 if mapping is not None:
621 self.update(mapping)
622
623 def __eq__(self, other: object) -> bool:
624 if not isinstance(other, MultiDict):
625 return NotImplemented
626 if isinstance(other, _OrderedMultiDict):
627 iter1 = iter(self.items(multi=True))
628 iter2 = iter(other.items(multi=True))
629 try:
630 for k1, v1 in iter1:
631 k2, v2 = next(iter2)
632 if k1 != k2 or v1 != v2:
633 return False
634 except StopIteration:
635 return False
636 try:
637 next(iter2)
638 except StopIteration:
639 return True
640 return False
641 if len(self) != len(other):
642 return False
643 for key, values in self.lists():
644 if other.getlist(key) != values:
645 return False
646 return True
647
648 __hash__ = None # type: ignore[assignment]
649
650 def __reduce_ex__(self, protocol: t.SupportsIndex) -> t.Any:
651 return type(self), (list(self.items(multi=True)),)
652
653 def __getstate__(self) -> t.Any:
654 return list(self.items(multi=True))
655
656 def __setstate__(self, values: t.Any) -> None:
657 self.clear()
658
659 for key, value in values:
660 self.add(key, value)
661
662 def __getitem__(self, key: K) -> V:
663 if key in self:
664 return dict.__getitem__(self, key)[0].value # type: ignore[index,no-any-return]
665 raise exceptions.BadRequestKeyError(key)
666
667 def __setitem__(self, key: K, value: V) -> None:
668 self.poplist(key)
669 self.add(key, value)
670
671 def __delitem__(self, key: K) -> None:
672 self.pop(key)
673
674 def keys(self) -> cabc.Iterable[K]: # type: ignore[override]
675 return (key for key, _ in self.items())
676
677 def __iter__(self) -> cabc.Iterator[K]:
678 return iter(self.keys())
679
680 def values(self) -> cabc.Iterable[V]: # type: ignore[override]
681 return (value for key, value in self.items())
682
683 def items(self, multi: bool = False) -> cabc.Iterable[tuple[K, V]]: # type: ignore[override]
684 ptr = self._first_bucket
685 if multi:
686 while ptr is not None:
687 yield ptr.key, ptr.value
688 ptr = ptr.next
689 else:
690 returned_keys = set()
691 while ptr is not None:
692 if ptr.key not in returned_keys:
693 returned_keys.add(ptr.key)
694 yield ptr.key, ptr.value
695 ptr = ptr.next
696
697 def lists(self) -> cabc.Iterable[tuple[K, list[V]]]:
698 returned_keys = set()
699 ptr = self._first_bucket
700 while ptr is not None:
701 if ptr.key not in returned_keys:
702 yield ptr.key, self.getlist(ptr.key)
703 returned_keys.add(ptr.key)
704 ptr = ptr.next
705
706 def listvalues(self) -> cabc.Iterable[list[V]]:
707 for _key, values in self.lists():
708 yield values
709
710 def add(self, key: K, value: V) -> None:
711 dict.setdefault(self, key, []).append(_omd_bucket(self, key, value)) # type: ignore[arg-type,attr-defined]
712
713 @t.overload
714 def getlist(self, key: K) -> list[V]: ...
715 @t.overload
716 def getlist(self, key: K, type: cabc.Callable[[V], T]) -> list[T]: ...
717 def getlist(
718 self, key: K, type: cabc.Callable[[V], T] | None = None
719 ) -> list[V] | list[T]:
720 rv: list[_omd_bucket[K, V]]
721
722 try:
723 rv = dict.__getitem__(self, key) # type: ignore[index]
724 except KeyError:
725 return []
726 if type is None:
727 return [x.value for x in rv]
728 result = []
729 for item in rv:
730 try:
731 result.append(type(item.value))
732 except (ValueError, TypeError):
733 pass
734 return result
735
736 def setlist(self, key: K, new_list: cabc.Iterable[V]) -> None:
737 self.poplist(key)
738 for value in new_list:
739 self.add(key, value)
740
741 def setlistdefault(self, key: t.Any, default_list: t.Any = None) -> t.NoReturn:
742 raise TypeError("setlistdefault is unsupported for ordered multi dicts")
743
744 def update( # type: ignore[override]
745 self,
746 mapping: (
747 MultiDict[K, V]
748 | cabc.Mapping[K, V | list[V] | tuple[V, ...] | set[V]]
749 | cabc.Iterable[tuple[K, V]]
750 ),
751 ) -> None:
752 for key, value in iter_multi_items(mapping):
753 self.add(key, value)
754
755 def poplist(self, key: K) -> list[V]:
756 buckets: cabc.Iterable[_omd_bucket[K, V]] = dict.pop(self, key, ()) # type: ignore[arg-type]
757 for bucket in buckets:
758 bucket.unlink(self)
759 return [x.value for x in buckets]
760
761 @t.overload
762 def pop(self, key: K) -> V: ...
763 @t.overload
764 def pop(self, key: K, default: V) -> V: ...
765 @t.overload
766 def pop(self, key: K, default: T) -> V | T: ...
767 def pop(
768 self,
769 key: K,
770 default: V | T = _missing, # type: ignore[assignment]
771 ) -> V | T:
772 buckets: list[_omd_bucket[K, V]]
773
774 try:
775 buckets = dict.pop(self, key) # type: ignore[arg-type]
776 except KeyError:
777 if default is not _missing:
778 return default
779
780 raise exceptions.BadRequestKeyError(key) from None
781
782 for bucket in buckets:
783 bucket.unlink(self)
784
785 return buckets[0].value
786
787 def popitem(self) -> tuple[K, V]:
788 key: K
789 buckets: list[_omd_bucket[K, V]]
790
791 try:
792 key, buckets = dict.popitem(self) # type: ignore[arg-type,assignment]
793 except KeyError as e:
794 raise exceptions.BadRequestKeyError(e.args[0]) from None
795
796 for bucket in buckets:
797 bucket.unlink(self)
798
799 return key, buckets[0].value
800
801 def popitemlist(self) -> tuple[K, list[V]]:
802 key: K
803 buckets: list[_omd_bucket[K, V]]
804
805 try:
806 key, buckets = dict.popitem(self) # type: ignore[arg-type,assignment]
807 except KeyError as e:
808 raise exceptions.BadRequestKeyError(e.args[0]) from None
809
810 for bucket in buckets:
811 bucket.unlink(self)
812
813 return key, [x.value for x in buckets]
814
815
816class CombinedMultiDict(ImmutableMultiDictMixin[K, V], MultiDict[K, V]): # type: ignore[misc]
817 """A read only :class:`MultiDict` that you can pass multiple :class:`MultiDict`
818 instances as sequence and it will combine the return values of all wrapped
819 dicts:
820
821 >>> from werkzeug.datastructures import CombinedMultiDict, MultiDict
822 >>> post = MultiDict([('foo', 'bar')])
823 >>> get = MultiDict([('blub', 'blah')])
824 >>> combined = CombinedMultiDict([get, post])
825 >>> combined['foo']
826 'bar'
827 >>> combined['blub']
828 'blah'
829
830 This works for all read operations and will raise a `TypeError` for
831 methods that usually change data which isn't possible.
832
833 From Werkzeug 0.3 onwards, the `KeyError` raised by this class is also a
834 subclass of the :exc:`~exceptions.BadRequest` HTTP exception and will
835 render a page for a ``400 BAD REQUEST`` if caught in a catch-all for HTTP
836 exceptions.
837 """
838
839 def __reduce_ex__(self, protocol: t.SupportsIndex) -> t.Any:
840 return type(self), (self.dicts,)
841
842 def __init__(self, dicts: cabc.Iterable[MultiDict[K, V]] | None = None) -> None:
843 super().__init__()
844 self.dicts: list[MultiDict[K, V]] = list(dicts or ())
845
846 @classmethod
847 def fromkeys(cls, keys: t.Any, value: t.Any = None) -> t.NoReturn:
848 raise TypeError(f"cannot create {cls.__name__!r} instances by fromkeys")
849
850 def __getitem__(self, key: K) -> V:
851 for d in self.dicts:
852 if key in d:
853 return d[key]
854 raise exceptions.BadRequestKeyError(key)
855
856 @t.overload # type: ignore[override]
857 def get(self, key: K) -> V | None: ...
858 @t.overload
859 def get(self, key: K, default: V) -> V: ...
860 @t.overload
861 def get(self, key: K, default: T) -> V | T: ...
862 @t.overload
863 def get(self, key: str, type: cabc.Callable[[V], T]) -> T | None: ...
864 @t.overload
865 def get(self, key: str, default: T, type: cabc.Callable[[V], T]) -> T: ...
866 def get( # type: ignore[misc]
867 self,
868 key: K,
869 default: V | T | None = None,
870 type: cabc.Callable[[V], T] | None = None,
871 ) -> V | T | None:
872 for d in self.dicts:
873 if key in d:
874 if type is not None:
875 try:
876 return type(d[key])
877 except (ValueError, TypeError):
878 continue
879 return d[key]
880 return default
881
882 @t.overload
883 def getlist(self, key: K) -> list[V]: ...
884 @t.overload
885 def getlist(self, key: K, type: cabc.Callable[[V], T]) -> list[T]: ...
886 def getlist(
887 self, key: K, type: cabc.Callable[[V], T] | None = None
888 ) -> list[V] | list[T]:
889 rv = []
890 for d in self.dicts:
891 rv.extend(d.getlist(key, type)) # type: ignore[arg-type]
892 return rv
893
894 def _keys_impl(self) -> set[K]:
895 """This function exists so __len__ can be implemented more efficiently,
896 saving one list creation from an iterator.
897 """
898 return set(k for d in self.dicts for k in d)
899
900 def keys(self) -> cabc.Iterable[K]: # type: ignore[override]
901 return self._keys_impl()
902
903 def __iter__(self) -> cabc.Iterator[K]:
904 return iter(self._keys_impl())
905
906 @t.overload # type: ignore[override]
907 def items(self) -> cabc.Iterable[tuple[K, V]]: ...
908 @t.overload
909 def items(self, multi: t.Literal[True]) -> cabc.Iterable[tuple[K, list[V]]]: ...
910 def items(
911 self, multi: bool = False
912 ) -> cabc.Iterable[tuple[K, V]] | cabc.Iterable[tuple[K, list[V]]]:
913 found = set()
914 for d in self.dicts:
915 for key, value in d.items(multi):
916 if multi:
917 yield key, value
918 elif key not in found:
919 found.add(key)
920 yield key, value
921
922 def values(self) -> cabc.Iterable[V]: # type: ignore[override]
923 for _, value in self.items():
924 yield value
925
926 def lists(self) -> cabc.Iterable[tuple[K, list[V]]]:
927 rv: dict[K, list[V]] = {}
928 for d in self.dicts:
929 for key, values in d.lists():
930 rv.setdefault(key, []).extend(values)
931 return rv.items()
932
933 def listvalues(self) -> cabc.Iterable[list[V]]:
934 return (x[1] for x in self.lists())
935
936 def copy(self) -> MultiDict[K, V]: # type: ignore[override]
937 """Return a shallow mutable copy of this object.
938
939 This returns a :class:`MultiDict` representing the data at the
940 time of copying. The copy will no longer reflect changes to the
941 wrapped dicts.
942
943 .. versionchanged:: 0.15
944 Return a mutable :class:`MultiDict`.
945 """
946 return MultiDict(self)
947
948 def __len__(self) -> int:
949 return len(self._keys_impl())
950
951 def __contains__(self, key: K) -> bool: # type: ignore[override]
952 for d in self.dicts:
953 if key in d:
954 return True
955 return False
956
957 def __repr__(self) -> str:
958 return f"{type(self).__name__}({self.dicts!r})"
959
960
961class ImmutableDict(ImmutableDictMixin[K, V], dict[K, V]): # type: ignore[misc]
962 """An immutable :class:`dict`.
963
964 .. versionadded:: 0.5
965 """
966
967 def __repr__(self) -> str:
968 return f"{type(self).__name__}({dict.__repr__(self)})"
969
970 def copy(self) -> dict[K, V]:
971 """Return a shallow mutable copy of this object. Keep in mind that
972 the standard library's :func:`copy` function is a no-op for this class
973 like for any other python immutable type (eg: :class:`tuple`).
974 """
975 return dict(self)
976
977 def __copy__(self) -> te.Self:
978 return self
979
980
981class ImmutableMultiDict(ImmutableMultiDictMixin[K, V], MultiDict[K, V]): # type: ignore[misc]
982 """An immutable :class:`MultiDict`.
983
984 .. versionadded:: 0.5
985 """
986
987 def copy(self) -> MultiDict[K, V]: # type: ignore[override]
988 """Return a shallow mutable copy of this object. Keep in mind that
989 the standard library's :func:`copy` function is a no-op for this class
990 like for any other python immutable type (eg: :class:`tuple`).
991 """
992 return MultiDict(self)
993
994 def __copy__(self) -> te.Self:
995 return self
996
997
998class _ImmutableOrderedMultiDict( # type: ignore[misc]
999 ImmutableMultiDictMixin[K, V], _OrderedMultiDict[K, V]
1000):
1001 """An immutable :class:`OrderedMultiDict`.
1002
1003 .. deprecated:: 3.1
1004 Will be removed in Werkzeug 3.2. Use ``ImmutableMultiDict`` instead.
1005
1006 .. versionadded:: 0.6
1007 """
1008
1009 def __init__(
1010 self,
1011 mapping: (
1012 MultiDict[K, V]
1013 | cabc.Mapping[K, V | list[V] | tuple[V, ...] | set[V]]
1014 | cabc.Iterable[tuple[K, V]]
1015 | None
1016 ) = None,
1017 ) -> None:
1018 super().__init__()
1019
1020 if mapping is not None:
1021 for k, v in iter_multi_items(mapping):
1022 _OrderedMultiDict.add(self, k, v)
1023
1024 def _iter_hashitems(self) -> cabc.Iterable[t.Any]:
1025 return enumerate(self.items(multi=True))
1026
1027 def copy(self) -> _OrderedMultiDict[K, V]: # type: ignore[override]
1028 """Return a shallow mutable copy of this object. Keep in mind that
1029 the standard library's :func:`copy` function is a no-op for this class
1030 like for any other python immutable type (eg: :class:`tuple`).
1031 """
1032 return _OrderedMultiDict(self)
1033
1034 def __copy__(self) -> te.Self:
1035 return self
1036
1037
1038class CallbackDict(UpdateDictMixin[K, V], dict[K, V]):
1039 """A dict that calls a function passed every time something is changed.
1040 The function is passed the dict instance.
1041 """
1042
1043 def __init__(
1044 self,
1045 initial: cabc.Mapping[K, V] | cabc.Iterable[tuple[K, V]] | None = None,
1046 on_update: cabc.Callable[[te.Self], None] | None = None,
1047 ) -> None:
1048 if initial is None:
1049 super().__init__()
1050 else:
1051 super().__init__(initial)
1052
1053 self.on_update = on_update
1054
1055 def __repr__(self) -> str:
1056 return f"<{type(self).__name__} {super().__repr__()}>"
1057
1058
1059class HeaderSet(cabc.MutableSet[str]):
1060 """Similar to the :class:`ETags` class this implements a set-like structure.
1061 Unlike :class:`ETags` this is case insensitive and used for vary, allow, and
1062 content-language headers.
1063
1064 If not constructed using the :func:`parse_set_header` function the
1065 instantiation works like this:
1066
1067 >>> hs = HeaderSet(['foo', 'bar', 'baz'])
1068 >>> hs
1069 HeaderSet(['foo', 'bar', 'baz'])
1070 """
1071
1072 def __init__(
1073 self,
1074 headers: cabc.Iterable[str] | None = None,
1075 on_update: cabc.Callable[[te.Self], None] | None = None,
1076 ) -> None:
1077 self._headers = list(headers or ())
1078 self._set = {x.lower() for x in self._headers}
1079 self.on_update = on_update
1080
1081 def add(self, header: str) -> None:
1082 """Add a new header to the set."""
1083 self.update((header,))
1084
1085 def remove(self: te.Self, header: str) -> None:
1086 """Remove a header from the set. This raises an :exc:`KeyError` if the
1087 header is not in the set.
1088
1089 .. versionchanged:: 0.5
1090 In older versions a :exc:`IndexError` was raised instead of a
1091 :exc:`KeyError` if the object was missing.
1092
1093 :param header: the header to be removed.
1094 """
1095 key = header.lower()
1096 if key not in self._set:
1097 raise KeyError(header)
1098 self._set.remove(key)
1099 for idx, key in enumerate(self._headers):
1100 if key.lower() == header:
1101 del self._headers[idx]
1102 break
1103 if self.on_update is not None:
1104 self.on_update(self)
1105
1106 def update(self: te.Self, iterable: cabc.Iterable[str]) -> None:
1107 """Add all the headers from the iterable to the set.
1108
1109 :param iterable: updates the set with the items from the iterable.
1110 """
1111 inserted_any = False
1112 for header in iterable:
1113 key = header.lower()
1114 if key not in self._set:
1115 self._headers.append(header)
1116 self._set.add(key)
1117 inserted_any = True
1118 if inserted_any and self.on_update is not None:
1119 self.on_update(self)
1120
1121 def discard(self, header: str) -> None:
1122 """Like :meth:`remove` but ignores errors.
1123
1124 :param header: the header to be discarded.
1125 """
1126 try:
1127 self.remove(header)
1128 except KeyError:
1129 pass
1130
1131 def find(self, header: str) -> int:
1132 """Return the index of the header in the set or return -1 if not found.
1133
1134 :param header: the header to be looked up.
1135 """
1136 header = header.lower()
1137 for idx, item in enumerate(self._headers):
1138 if item.lower() == header:
1139 return idx
1140 return -1
1141
1142 def index(self, header: str) -> int:
1143 """Return the index of the header in the set or raise an
1144 :exc:`IndexError`.
1145
1146 :param header: the header to be looked up.
1147 """
1148 rv = self.find(header)
1149 if rv < 0:
1150 raise IndexError(header)
1151 return rv
1152
1153 def clear(self: te.Self) -> None:
1154 """Clear the set."""
1155 self._set.clear()
1156 self._headers.clear()
1157
1158 if self.on_update is not None:
1159 self.on_update(self)
1160
1161 def as_set(self, preserve_casing: bool = False) -> set[str]:
1162 """Return the set as real python set type. When calling this, all
1163 the items are converted to lowercase and the ordering is lost.
1164
1165 :param preserve_casing: if set to `True` the items in the set returned
1166 will have the original case like in the
1167 :class:`HeaderSet`, otherwise they will
1168 be lowercase.
1169 """
1170 if preserve_casing:
1171 return set(self._headers)
1172 return set(self._set)
1173
1174 def to_header(self) -> str:
1175 """Convert the header set into an HTTP header string."""
1176 return ", ".join(map(http.quote_header_value, self._headers))
1177
1178 def __getitem__(self, idx: t.SupportsIndex) -> str:
1179 return self._headers[idx]
1180
1181 def __delitem__(self: te.Self, idx: t.SupportsIndex) -> None:
1182 rv = self._headers.pop(idx)
1183 self._set.remove(rv.lower())
1184 if self.on_update is not None:
1185 self.on_update(self)
1186
1187 def __setitem__(self: te.Self, idx: t.SupportsIndex, value: str) -> None:
1188 old = self._headers[idx]
1189 self._set.remove(old.lower())
1190 self._headers[idx] = value
1191 self._set.add(value.lower())
1192 if self.on_update is not None:
1193 self.on_update(self)
1194
1195 def __contains__(self, header: str) -> bool: # type: ignore[override]
1196 return header.lower() in self._set
1197
1198 def __len__(self) -> int:
1199 return len(self._set)
1200
1201 def __iter__(self) -> cabc.Iterator[str]:
1202 return iter(self._headers)
1203
1204 def __bool__(self) -> bool:
1205 return bool(self._set)
1206
1207 def __str__(self) -> str:
1208 return self.to_header()
1209
1210 def __repr__(self) -> str:
1211 return f"{type(self).__name__}({self._headers!r})"
1212
1213
1214# circular dependencies
1215from .. import http
1216
1217
1218def __getattr__(name: str) -> t.Any:
1219 import warnings
1220
1221 if name == "OrderedMultiDict":
1222 warnings.warn(
1223 "'OrderedMultiDict' is deprecated and will be removed in Werkzeug"
1224 " 3.2. Use 'MultiDict' instead.",
1225 DeprecationWarning,
1226 stacklevel=2,
1227 )
1228 return _OrderedMultiDict
1229
1230 if name == "ImmutableOrderedMultiDict":
1231 warnings.warn(
1232 "'ImmutableOrderedMultiDict' is deprecated and will be removed in"
1233 " Werkzeug 3.2. Use 'ImmutableMultiDict' instead.",
1234 DeprecationWarning,
1235 stacklevel=2,
1236 )
1237 return _ImmutableOrderedMultiDict
1238
1239 raise AttributeError(name)