2019-08-31 15:17:10 +02:00
|
|
|
from collections import OrderedDict
|
|
|
|
|
2021-10-31 15:04:39 +01:00
|
|
|
from multidict import MultiDict, CIMultiDict
|
2019-08-31 15:17:10 +02:00
|
|
|
|
|
|
|
|
2021-10-31 15:04:39 +01:00
|
|
|
class BaseMultiDict(MultiDict):
|
2019-08-31 15:17:10 +02:00
|
|
|
"""
|
2021-10-31 15:04:39 +01:00
|
|
|
Base class for all MultiDicts.
|
|
|
|
"""
|
|
|
|
|
2019-08-31 15:17:10 +02:00
|
|
|
|
2021-11-25 00:41:37 +01:00
|
|
|
class HTTPHeadersDict(CIMultiDict, BaseMultiDict):
|
2019-08-31 15:17:10 +02:00
|
|
|
"""
|
2021-10-31 15:04:39 +01:00
|
|
|
Headers are case-insensitive and multiple values are supported
|
|
|
|
through the `add()` API.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def add(self, key, value):
|
|
|
|
"""
|
|
|
|
Add or update a new header.
|
|
|
|
|
|
|
|
If the given `value` is `None`, then all the previous
|
|
|
|
values will be overwritten and the value will be set
|
|
|
|
to `None`.
|
|
|
|
"""
|
|
|
|
if value is None:
|
|
|
|
self[key] = value
|
|
|
|
return None
|
|
|
|
|
|
|
|
# If the previous value for the given header is `None`
|
|
|
|
# then discard it since we are explicitly giving a new
|
|
|
|
# value for it.
|
|
|
|
if key in self and self.getone(key) is None:
|
|
|
|
self.popone(key)
|
|
|
|
|
|
|
|
super().add(key, value)
|
2019-08-31 15:17:10 +02:00
|
|
|
|
2022-04-03 15:48:31 +02:00
|
|
|
def remove_item(self, key, value):
|
|
|
|
"""
|
|
|
|
Remove a (key, value) pair from the dict.
|
|
|
|
"""
|
|
|
|
existing_values = self.popall(key)
|
|
|
|
existing_values.remove(value)
|
|
|
|
|
|
|
|
for value in existing_values:
|
|
|
|
self.add(key, value)
|
|
|
|
|
2019-08-31 15:17:10 +02:00
|
|
|
|
|
|
|
class RequestJSONDataDict(OrderedDict):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class MultiValueOrderedDict(OrderedDict):
|
|
|
|
"""Multi-value dict for URL parameters and form data."""
|
|
|
|
|
|
|
|
def __setitem__(self, key, value):
|
|
|
|
"""
|
|
|
|
If `key` is assigned more than once, `self[key]` holds a
|
|
|
|
`list` of all the values.
|
|
|
|
|
|
|
|
This allows having multiple fields with the same name in form
|
|
|
|
data and URL params.
|
|
|
|
|
|
|
|
"""
|
|
|
|
assert not isinstance(value, list)
|
|
|
|
if key not in self:
|
|
|
|
super().__setitem__(key, value)
|
|
|
|
else:
|
|
|
|
if not isinstance(self[key], list):
|
|
|
|
super().__setitem__(key, [self[key]])
|
|
|
|
self[key].append(value)
|
|
|
|
|
2020-09-28 12:16:57 +02:00
|
|
|
def items(self):
|
|
|
|
for key, values in super().items():
|
|
|
|
if not isinstance(values, list):
|
|
|
|
values = [values]
|
|
|
|
for value in values:
|
|
|
|
yield key, value
|
|
|
|
|
2019-08-31 15:17:10 +02:00
|
|
|
|
|
|
|
class RequestQueryParamsDict(MultiValueOrderedDict):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class RequestDataDict(MultiValueOrderedDict):
|
2020-09-28 12:16:57 +02:00
|
|
|
pass
|
2019-08-31 15:17:10 +02:00
|
|
|
|
2020-09-28 12:16:57 +02:00
|
|
|
|
|
|
|
class MultipartRequestDataDict(MultiValueOrderedDict):
|
|
|
|
pass
|
2019-08-31 15:17:10 +02:00
|
|
|
|
|
|
|
|
|
|
|
class RequestFilesDict(RequestDataDict):
|
|
|
|
pass
|
2022-02-09 00:18:40 +01:00
|
|
|
|
|
|
|
|
|
|
|
class NestedJSONArray(list):
|
|
|
|
"""Denotes a top-level JSON array."""
|