def _iter(self, version: int) -> Iterator[tuple[str, _V]]: for e in self._md._keys.iter_entries(): if version != self._md._version: raise RuntimeError("Dictionary changed during iteration") yield self._md._key(e.key), e.value
@reprlib.recursive_repr() def __repr__(self) -> str:
lst = [] for e in self._md._keys.iter_entries():
lst.append(f"'{e.key}': {e.value!r}")
body = ", ".join(lst) return f"<{self.__class__.__name__}({body})>"
def _tmp_set(self, it: Iterable[_T]) -> set[tuple[str, _V]]:
tmp = set() for arg in it:
item = self._parse_item(arg) if item isNone: continue else:
tmp.add((item[1], item[3])) return tmp
def __and__(self, other: Iterable[Any]) -> set[tuple[str, _V]]:
ret = set() try:
it = iter(other) except TypeError: return NotImplemented for arg in it:
item = self._parse_item(arg) if item isNone: continue
hash_, identity, key, value = item for slot, idx, e in self._md._keys.iter_hash(hash_):
e.hash = -1 if e.identity == identity and e.value == value:
ret.add((e.key, e.value))
self._md._keys.restore_hash(hash_) return ret
def __rand__(self, other: Iterable[_T]) -> set[_T]:
ret = set() try:
it = iter(other) except TypeError: return NotImplemented for arg in it:
item = self._parse_item(arg) if item isNone: continue
hash_, identity, key, value = item for slot, idx, e in self._md._keys.iter_hash(hash_): if e.identity == identity and e.value == value:
ret.add(arg) break return ret
def __or__(self, other: Iterable[_T]) -> set[Union[tuple[str, _V], _T]]:
ret: set[Union[tuple[str, _V], _T]] = set(self) try:
it = iter(other) except TypeError: return NotImplemented for arg in it:
item: Optional[tuple[int, str, str, _V]] = self._parse_item(arg) if item isNone:
ret.add(arg) continue
hash_, identity, key, value = item for slot, idx, e in self._md._keys.iter_hash(hash_): if e.identity == identity and e.value == value: # pragma: no branch break else:
ret.add(arg) return ret
for e in self._md._keys.iter_entries(): if (e.identity, e.value) notin tmp:
ret.add((e.key, e.value))
return ret
def __rsub__(self, other: Iterable[_T]) -> set[_T]:
ret: set[_T] = set() try:
it = iter(other) except TypeError: return NotImplemented for arg in it:
item = self._parse_item(arg) if item isNone:
ret.add(arg) continue
hash_, identity, key, value = item for slot, idx, e in self._md._keys.iter_hash(hash_): if e.identity == identity and e.value == value: # pragma: no branch break else:
ret.add(arg) return ret
def isdisjoint(self, other: Iterable[tuple[str, _V]]) -> bool: for arg in other:
item = self._parse_item(arg) if item isNone: continue
hash_, identity, key, value = item for slot, idx, e in self._md._keys.iter_hash(hash_): if e.identity == identity and e.value == value: # pragma: no branch returnFalse returnTrue
class _ValuesView(_ViewBase[_V], ValuesView[_V]): def __contains__(self, value: object) -> bool: for e in self._md._keys.iter_entries(): if e.value == value: returnTrue returnFalse
def _iter(self, version: int) -> Iterator[_V]: for e in self._md._keys.iter_entries(): if version != self._md._version: raise RuntimeError("Dictionary changed during iteration") yield e.value
@reprlib.recursive_repr() def __repr__(self) -> str:
lst = [] for e in self._md._keys.iter_entries():
lst.append(repr(e.value))
body = ", ".join(lst) return f"<{self.__class__.__name__}({body})>"
class _KeysView(_ViewBase[_V], KeysView[str]): def __contains__(self, key: object) -> bool: ifnot isinstance(key, str): returnFalse
identity = self._md._identity(key)
hash_ = hash(identity) for slot, idx, e in self._md._keys.iter_hash(hash_): if e.identity == identity: # pragma: no branch returnTrue returnFalse
def _iter(self, version: int) -> Iterator[str]: for e in self._md._keys.iter_entries(): if version != self._md._version: raise RuntimeError("Dictionary changed during iteration") yield self._md._key(e.key)
def __repr__(self) -> str:
lst = [] for e in self._md._keys.iter_entries():
lst.append(f"'{e.key}'")
body = ", ".join(lst) return f"<{self.__class__.__name__}({body})>"
def __and__(self, other: Iterable[object]) -> set[str]:
ret = set() try:
it = iter(other) except TypeError: return NotImplemented for key in it: ifnot isinstance(key, str): continue
identity = self._md._identity(key)
hash_ = hash(identity) for slot, idx, e in self._md._keys.iter_hash(hash_): if e.identity == identity: # pragma: no branch
ret.add(e.key) break return ret
def __rand__(self, other: Iterable[_T]) -> set[_T]:
ret = set() try:
it = iter(other) except TypeError: return NotImplemented for key in it: ifnot isinstance(key, str): continue if key in self._md:
ret.add(key) return cast(set[_T], ret)
def __or__(self, other: Iterable[_T]) -> set[Union[str, _T]]:
ret: set[Union[str, _T]] = set(self) try:
it = iter(other) except TypeError: return NotImplemented for key in it: ifnot isinstance(key, str):
ret.add(key) continue if key notin self._md:
ret.add(key) return ret
tmp = set() for key in ret: ifnot isinstance(key, str): continue
identity = self._md._identity(key)
tmp.add(identity)
for e in self._md._keys.iter_entries(): if e.identity notin tmp:
ret.add(e.key) return ret
def __sub__(self, other: Iterable[object]) -> set[str]:
ret = set(self) try:
it = iter(other) except TypeError: return NotImplemented for key in it: ifnot isinstance(key, str): continue
identity = self._md._identity(key)
hash_ = hash(identity) for slot, idx, e in self._md._keys.iter_hash(hash_): if e.identity == identity: # pragma: no branch
ret.discard(e.key) break return ret
def __rsub__(self, other: Iterable[_T]) -> set[_T]: try:
ret: set[_T] = set(other) except TypeError: return NotImplemented for key in other: ifnot isinstance(key, str): continue if key in self._md:
ret.discard(key) # type: ignore[arg-type] return ret
def isdisjoint(self, other: Iterable[object]) -> bool: for key in other: ifnot isinstance(key, str): continue if key in self._md: returnFalse returnTrue
class _CSMixin:
_ci: ClassVar[bool] = False
def _key(self, key: str) -> str: return key
def _identity(self, key: str) -> str: if isinstance(key, str): return key else: raise TypeError("MultiDict keys should be either str or subclasses of str")
class _CIMixin:
_ci: ClassVar[bool] = True
def _key(self, key: str) -> str: if type(key) is istr: return key else: return istr(key)
def _identity(self, key: str) -> str: if isinstance(key, istr):
ret = key.__istr_identity__ if ret isNone:
ret = key.lower()
key.__istr_identity__ = ret return ret if isinstance(key, str): return key.lower() else: raise TypeError("MultiDict keys should be either str or subclasses of str")
def build_indices(self, update: bool) -> None:
mask = self.mask
indices = self.indices for idx, e in enumerate(self.entries): assert e isnotNone
hash_ = e.hash if update: if hash_ == -1:
hash_ = hash(e.identity) else: assert hash_ != -1
i = hash_ & mask
perturb = hash_ & sys.maxsize while indices[i] != -1:
perturb >>= 5
i = mask & (i * 5 + perturb + 1)
indices[i] = idx
def find_empty_slot(self, hash_: int) -> int:
mask = self.mask
indices = self.indices
i = hash_ & mask
perturb = hash_ & sys.maxsize
ix = indices[i] while ix != -1:
perturb >>= 5
i = (i * 5 + perturb + 1) & mask
ix = indices[i] return i
def iter_hash(self, hash_: int) -> Iterator[tuple[int, int, _Entry[_V]]]:
mask = self.mask
indices = self.indices
entries = self.entries
i = hash_ & mask
perturb = hash_ & sys.maxsize
ix = indices[i] while ix != -1: if ix != -2:
e = entries[ix] if e.hash == hash_: yield i, ix, e
perturb >>= 5
i = (i * 5 + perturb + 1) & mask
ix = indices[i]
def del_idx(self, hash_: int, idx: int) -> None:
mask = self.mask
indices = self.indices
i = hash_ & mask
perturb = hash_ & sys.maxsize
ix = indices[i] while ix != idx:
perturb >>= 5
i = (i * 5 + perturb + 1) & mask
ix = indices[i]
indices[i] = -2
it = self._parse_args(arg, kwargs)
log2_size = estimate_log2_keysize(cast(int, next(it))) if log2_size > 17: # pragma: no cover # Don't overallocate really huge keys space in init
log2_size = 17
self._keys: _HtKeys[_V] = _HtKeys.new(log2_size, [])
self._extend_items(cast(Iterator[_Entry[_V]], it))
def _from_md(self, md: "MultiDict[_V]") -> None: # Copy everything as-is without compacting the new multidict, # otherwise it requires reindexing
self._keys = md._keys.clone()
self._used = md._used
@overload def getall(self, key: str) -> list[_V]: ...
@overload def getall(self, key: str, default: _T) -> Union[list[_V], _T]: ... def getall(
self, key: str, default: Union[_T, _SENTINEL] = sentinel
) -> Union[list[_V], _T]: """Return a list of all values matching the key."""
identity = self._identity(key)
hash_ = hash(identity)
res = []
restore = [] for slot, idx, e in self._keys.iter_hash(hash_): if e.identity == identity: # pragma: no branch
res.append(e.value)
e.hash = -1
restore.append(idx)
if res:
entries = self._keys.entries for idx in restore:
entries[idx].hash = hash_ # type: ignore[union-attr] return res ifnot res and default isnot sentinel: return default raise KeyError("Key not found: %r" % key)
Raises KeyError if the key isnot found and no default is provided. """
identity = self._identity(key)
hash_ = hash(identity) for slot, idx, e in self._keys.iter_hash(hash_): if e.identity == identity: # pragma: no branch return e.value if default isnot sentinel: return default raise KeyError("Key not found: %r" % key)
def keys(self) -> KeysView[str]: """Return a new view of the dictionary's keys.""" return _KeysView(self)
def items(self) -> ItemsView[str, _V]: """Return a new view of the dictionary's items *(key, value) pairs).""" return _ItemsView(self)
def values(self) -> _ValuesView[_V]: """Return a new view of the dictionary's values.""" return _ValuesView(self)
def __eq__(self, other: object) -> bool: ifnot isinstance(other, Mapping): return NotImplemented if isinstance(other, MultiDictProxy): return self == other._md if isinstance(other, MultiDict):
lft = self._keys
rht = other._keys if self._used != other._used: returnFalse for e1, e2 in zip(lft.iter_entries(), rht.iter_entries()): if e1.identity != e2.identity or e1.value != e2.value: returnFalse returnTrue if self._used != len(other): returnFalse for k, v in self.items():
nv = other.get(k, sentinel) if v != nv: returnFalse returnTrue
def __contains__(self, key: object) -> bool: ifnot isinstance(key, str): returnFalse
identity = self._identity(key)
hash_ = hash(identity) for slot, idx, e in self._keys.iter_hash(hash_): if e.identity == identity: # pragma: no branch returnTrue returnFalse
@reprlib.recursive_repr() def __repr__(self) -> str:
body = ", ".join(f"'{e.key}': {e.value!r}"for e in self._keys.iter_entries()) return f"<{self.__class__.__name__}({body})>"
def copy(self) -> Self: """Return a copy of itself."""
cls = self.__class__ return cls(self)
__copy__ = copy
def extend(self, arg: MDArg[_V] = None, /, **kwargs: _V) -> None: """Extend current MultiDict with more values.
This method must be used instead of update. """
it = self._parse_args(arg, kwargs)
newsize = self._used + cast(int, next(it))
self._resize(estimate_log2_keysize(newsize), False)
self._extend_items(cast(Iterator[_Entry[_V]], it))
def _parse_args(
self,
arg: MDArg[_V],
kwargs: Mapping[str, _V],
) -> Iterator[Union[int, _Entry[_V]]]:
identity_func = self._identity if arg: if isinstance(arg, MultiDictProxy):
arg = arg._md if isinstance(arg, MultiDict): yield len(arg) + len(kwargs) if self._ci isnot arg._ci: for e in arg._keys.iter_entries():
identity = identity_func(e.key) yield _Entry(hash(identity), identity, e.key, e.value) else: for e in arg._keys.iter_entries(): yield _Entry(e.hash, e.identity, e.key, e.value) if kwargs: for key, value in kwargs.items():
identity = identity_func(key) yield _Entry(hash(identity), identity, key, value) else: if hasattr(arg, "keys"):
arg = cast(SupportsKeys[_V], arg)
arg = [(k, arg[k]) for k in arg.keys()] if kwargs:
arg = list(arg)
arg.extend(list(kwargs.items())) try: yield len(arg) + len(kwargs) # type: ignore[arg-type] except TypeError: yield0 for pos, item in enumerate(arg): ifnot len(item) == 2: raise ValueError(
f"multidict update sequence element #{pos}"
f"has length {len(item)}; 2 is required"
)
identity = identity_func(item[0]) yield _Entry(hash(identity), identity, item[0], item[1]) else: yield len(kwargs) for key, value in kwargs.items():
identity = identity_func(key) yield _Entry(hash(identity), identity, key, value)
def _extend_items(self, items: Iterable[_Entry[_V]]) -> None: for e in items:
self._add_with_hash(e)
self._incr_version()
def clear(self) -> None: """Remove all items from MultiDict."""
self._used = 0
self._keys = _HtKeys.new(_HtKeys.LOG_MINSIZE, [])
self._incr_version()
for slot, idx, e in self._keys.iter_hash(hash_): if e.identity == identity: # pragma: no branch ifnot found:
e.key = key
e.value = value
e.hash = -1
found = True
self._incr_version() elif e.hash != -1: # pragma: no branch
self._del_at(slot, idx)
If key isnot found, d is returned if given, otherwise
KeyError is raised.
"""
identity = self._identity(key)
hash_ = hash(identity) for slot, idx, e in self._keys.iter_hash(hash_): if e.identity == identity: # pragma: no branch
value = e.value
self._del_at(slot, idx)
self._incr_version() return value if default is sentinel: raise KeyError(key) else: return default
# Type checking will inherit signature for pop() if we don't confuse it here. ifnot TYPE_CHECKING:
pop = popone
@overload def popall(self, key: str) -> list[_V]: ...
@overload def popall(self, key: str, default: _T) -> Union[list[_V], _T]: ... def popall(
self, key: str, default: Union[_T, _SENTINEL] = sentinel
) -> Union[list[_V], _T]: """Remove all occurrences of key and return the list of corresponding
values.
If key isnot found, default is returned if given, otherwise
KeyError is raised.
"""
found = False
identity = self._identity(key)
hash_ = hash(identity)
ret = [] for slot, idx, e in self._keys.iter_hash(hash_): if e.identity == identity: # pragma: no branch
found = True
ret.append(e.value)
self._del_at(slot, idx)
self._incr_version()
ifnot found: if default is sentinel: raise KeyError(key) else: return default else: return ret
def popitem(self) -> tuple[str, _V]: """Remove and return an arbitrary (key, value) pair.""" if self._used <= 0: raise KeyError("empty multidict")
while entry isNone:
pos -= 1
entry = self._keys.entries.pop()
ret = self._key(entry.key), entry.value
self._keys.del_idx(entry.hash, pos)
self._used -= 1
self._incr_version() return ret
def update(self, arg: MDArg[_V] = None, /, **kwargs: _V) -> None: """Update the dictionary, overwriting existing keys."""
it = self._parse_args(arg, kwargs)
newsize = self._used + cast(int, next(it))
log2_size = estimate_log2_keysize(newsize) if log2_size > 17: # pragma: no cover # Don't overallocate really huge keys space in update, # duplicate keys could reduce the resulting anount of entries
log2_size = 17 if log2_size > self._keys.log2_size:
self._resize(log2_size, False) try:
self._update_items(cast(Iterator[_Entry[_V]], it)) finally:
self._post_update()
def _update_items(self, items: Iterator[_Entry[_V]]) -> None: for entry in items:
found = False
hash_ = entry.hash
identity = entry.identity for slot, idx, e in self._keys.iter_hash(hash_): if e.identity == identity: # pragma: no branch ifnot found:
found = True
e.key = entry.key
e.value = entry.value
e.hash = -1 else:
self._del_at_for_upd(e) ifnot found:
self._add_with_hash_for_upd(entry)
def _post_update(self) -> None:
keys = self._keys
indices = keys.indices
entries = keys.entries for slot in range(keys.nslots):
idx = indices[slot] if idx >= 0:
e2 = entries[idx] assert e2 isnotNone if e2.key isNone:
entries[idx] = None
indices[slot] = -2
self._used -= 1 if e2.hash == -1:
e2.hash = hash(e2.identity)
self._incr_version()
def merge(self, arg: MDArg[_V] = None, /, **kwargs: _V) -> None: """Merge into the dictionary, adding non-existing keys."""
it = self._parse_args(arg, kwargs)
newsize = self._used + cast(int, next(it))
log2_size = estimate_log2_keysize(newsize) if log2_size > 17: # pragma: no cover # Don't overallocate really huge keys space in update, # duplicate keys could reduce the resulting anount of entries
log2_size = 17 if log2_size > self._keys.log2_size:
self._resize(log2_size, False) try:
self._merge_items(cast(Iterator[_Entry[_V]], it)) finally:
self._post_update()
def _merge_items(self, items: Iterator[_Entry[_V]]) -> None: for entry in items:
hash_ = entry.hash
identity = entry.identity for slot, idx, e in self._keys.iter_hash(hash_): if e.identity == identity: # pragma: no branch break else:
self._add_with_hash_for_upd(entry)
if len(oldkeys.entries) == newentries:
entries = oldkeys.entries else:
entries = [e for e in oldkeys.entries if e isnotNone]
newkeys: _HtKeys[_V] = _HtKeys.new(log2_newsize, entries)
newkeys.usable -= newentries
newkeys.build_indices(update)
self._keys = newkeys
Raises KeyError if the key isnot found and no default is provided. """ if default isnot sentinel: return self._md.getone(key, default) else: return self._md.getone(key)
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.