Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/werkzeug/datastructures/structures.py: 40%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

575 statements  

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)