%PDF- %PDF-
Direktori : /data/old/usr/lib64/python3.4/site-packages/multidict/ |
Current File : //data/old/usr/lib64/python3.4/site-packages/multidict/_multidict.pyx |
from __future__ import absolute_import import sys from collections import abc from collections.abc import Iterable, Set from cpython.object cimport PyObject_Str from ._abc import MultiMapping, MutableMultiMapping from ._istr import istr cdef object _marker = object() upstr = istr # for relaxing backward compatibility problems cdef object _istr = istr def getversion(_Base md): return md._impl._version cdef _eq(self, other): cdef int is_left_base, is_right_base cdef Py_ssize_t i, l cdef list lft_items, rgt_items cdef _Pair lft, rgt is_left_base = isinstance(self, _Base) is_right_base = isinstance(other, _Base) if is_left_base and is_right_base: lft_items = (<_Base>self)._impl._items rgt_items = (<_Base>other)._impl._items l = len(lft_items) if l != len(rgt_items): return False for i in range(l): lft = <_Pair>(lft_items[i]) rgt = <_Pair>(rgt_items[i]) if lft._hash != rgt._hash: return False if lft._identity != rgt._identity: return False if lft._value != rgt._value: return False return True elif is_left_base and isinstance(other, abc.Mapping): return (<_Base>self)._eq_to_mapping(other) elif is_right_base and isinstance(self, abc.Mapping): return (<_Base>other)._eq_to_mapping(self) else: return NotImplemented cdef class _Pair: cdef str _identity cdef Py_hash_t _hash cdef str _key cdef object _value def __cinit__(self, identity, key, value): self._hash = hash(identity) self._identity = <str>identity self._key = <str>key self._value = value cdef unsigned long long _version cdef class _Impl: cdef list _items cdef unsigned long long _version def __cinit__(self): self._items = [] self.incr_version() cdef void incr_version(self): global _version _version += 1 self._version = _version cdef class _Base: cdef _Impl _impl cdef str _title(self, s): typ = type(s) if typ is str: return <str>s elif typ is _istr: return PyObject_Str(s) else: return str(s) def getall(self, key, default=_marker): """Return a list of all values matching the key.""" return self._getall(self._title(key), key, default) cdef _getall(self, str identity, key, default): cdef list res cdef _Pair item cdef Py_hash_t h = hash(identity) res = [] for i in self._impl._items: item = <_Pair>i if item._hash != h: continue if item._identity == identity: res.append(item._value) if res: return res elif default is not _marker: return default else: raise KeyError('Key not found: %r' % key) def getone(self, key, default=_marker): """Get first value matching the key.""" return self._getone(self._title(key), key, default) cdef _getone(self, str identity, key, default): cdef _Pair item cdef Py_hash_t h = hash(identity) for i in self._impl._items: item = <_Pair>i if item._hash != h: continue if item._identity == identity: return item._value if default is not _marker: return default raise KeyError('Key not found: %r' % key) # Mapping interface # def __getitem__(self, key): return self._getone(self._title(key), key, _marker) def get(self, key, default=None): """Get first value matching the key. The method is alias for .getone(). """ return self._getone(self._title(key), key, default) def __contains__(self, key): return self._contains(self._title(key)) cdef _contains(self, str identity): cdef _Pair item cdef Py_hash_t h = hash(identity) for i in self._impl._items: item = <_Pair>i if item._hash != h: continue if item._identity == identity: return True return False def __iter__(self): return iter(self.keys()) def __len__(self): return len(self._impl._items) cpdef keys(self): """Return a new view of the dictionary's keys.""" return _KeysView.__new__(_KeysView, self._impl) def items(self): """Return a new view of the dictionary's items *(key, value) pairs).""" return _ItemsView.__new__(_ItemsView, self._impl) def values(self): """Return a new view of the dictionary's values.""" return _ValuesView.__new__(_ValuesView, self._impl) def __repr__(self): cdef _Pair item lst = [] for i in self._impl._items: item = <_Pair>i lst.append("'{}': {!r}".format(item._key, item._value)) body = ', '.join(lst) return '<{}({})>'.format(self.__class__.__name__, body) cdef _eq_to_mapping(self, other): cdef _Pair item if len(self._impl._items) != len(other): return False for i in self._impl._items: item = <_Pair>i for k, v in other.items(): if self._title(k) != item._identity: continue if v == item._value: break else: return False return True def __richcmp__(self, other, op): if op == 2: # == return _eq(self, other) elif op == 3: # != ret = _eq(self, other) if ret is NotImplemented: return ret else: return not ret else: return NotImplemented cdef class MultiDictProxy(_Base): _proxy_classes = (MultiDict, MultiDictProxy) _base_class = MultiDict def __init__(self, arg): cdef _Base base if not isinstance(arg, self._proxy_classes): raise TypeError( 'ctor requires {} instance' ', not {}'.format( ' or '.join(self._proxy_classes), type(arg))) base = arg self._impl = base._impl def __reduce__(self): raise TypeError("can't pickle {} objects" .format(self.__class__.__name__)) def copy(self): """Return a copy of itself.""" return self._base_class(self) MultiMapping.register(MultiDictProxy) cdef class CIMultiDictProxy(MultiDictProxy): _proxy_classes = (CIMultiDict, CIMultiDictProxy) _base_class = CIMultiDict cdef str _title(self, s): typ = type(s) if typ is str: return <str>(s.title()) elif type(s) is _istr: return PyObject_Str(s) return s.title() MultiMapping.register(CIMultiDictProxy) cdef str _str(key): typ = type(key) if typ is str: return <str>key if typ is _istr: return PyObject_Str(key) elif issubclass(typ, str): return str(key) else: raise TypeError("MultiDict keys should be either str " "or subclasses of str") cdef class MultiDict(_Base): """An ordered dictionary that can have multiple values for each key.""" def __init__(self, *args, **kwargs): self._impl = _Impl() self._extend(args, kwargs, 'MultiDict', True) def __reduce__(self): return ( self.__class__, (list(self.items()),) ) cdef _extend(self, tuple args, dict kwargs, name, bint do_add): cdef _Pair item cdef object key cdef object value cdef object arg cdef object i if len(args) > 1: raise TypeError("{} takes at most 1 positional argument" " ({} given)".format(name, len(args))) if args: arg = args[0] if isinstance(arg, _Base): if do_add: self._append_items((<_Base>arg)._impl) else: self._update_items((<_Base>arg)._impl) else: if hasattr(arg, 'items'): arg = arg.items() if do_add: self._append_items_seq(arg, name) else: self._update_items_seq(arg, name) for key, value in kwargs.items(): if do_add: self._add(key, value) else: self._replace(key, value) cdef object _update_items(self, _Impl impl): cdef _Pair item, item2 cdef object i cdef dict used_keys = {} cdef Py_ssize_t start cdef Py_ssize_t post cdef Py_ssize_t size = len(self._impl._items) cdef Py_hash_t h for i in impl._items: item = <_Pair>i start = used_keys.get(item._identity, 0) for pos in range(start, size): item2 = <_Pair>(self._impl._items[pos]) if item2._hash != item._hash: continue if item2._identity == item._identity: used_keys[item._identity] = pos + 1 item2._key = item._key item2._value = item._value break else: self._impl._items.append(_Pair.__new__( _Pair, item._identity, item._key, item._value)) size += 1 used_keys[item._identity] = size self._post_update(used_keys) cdef object _update_items_seq(self, object arg, object name): cdef _Pair item cdef object i cdef object identity cdef object key cdef object value cdef dict used_keys = {} cdef Py_ssize_t start cdef Py_ssize_t post cdef Py_ssize_t size = len(self._impl._items) cdef Py_hash_t h for i in arg: if not len(i) == 2: raise TypeError( "{} takes either dict or list of (key, value) " "tuples".format(name)) key = _str(i[0]) value = i[1] identity = self._title(key) h = hash(identity) start = used_keys.get(identity, 0) for pos in range(start, size): item = <_Pair>(self._impl._items[pos]) if item._hash != h: continue if item._identity == identity: used_keys[identity] = pos + 1 item._key = key item._value = value break else: self._impl._items.append(_Pair.__new__( _Pair, identity, key, value)) size += 1 used_keys[identity] = size self._post_update(used_keys) cdef object _post_update(self, dict used_keys): cdef Py_ssize_t i = 0 cdef _Pair item while i < len(self._impl._items): item = <_Pair>self._impl._items[i] pos = used_keys.get(item._identity) if pos is None: i += 1 continue if i >= pos: del self._impl._items[i] else: i += 1 self._impl.incr_version() cdef object _append_items(self, _Impl impl): cdef _Pair item cdef object i cdef str key cdef object value for i in impl._items: item = <_Pair>i key = item._key value = item._value self._impl._items.append(_Pair.__new__( _Pair, self._title(key), key, value)) self._impl.incr_version() cdef object _append_items_seq(self, object arg, object name): cdef object i cdef object key cdef object value for i in arg: if not len(i) == 2: raise TypeError( "{} takes either dict or list of (key, value) " "tuples".format(name)) key = i[0] value = i[1] self._impl._items.append(_Pair.__new__( _Pair, self._title(key), _str(key), value)) self._impl.incr_version() cdef _add(self, key, value): self._impl._items.append(_Pair.__new__( _Pair, self._title(key), _str(key), value)) self._impl.incr_version() cdef _replace(self, key, value): cdef str identity = self._title(key) cdef str k = _str(key) cdef Py_hash_t h = hash(identity) cdef Py_ssize_t i, rgt cdef _Pair item cdef list items = self._impl._items for i in range(len(items)-1, -1, -1): item = <_Pair>items[i] if h != item._hash: continue if item._identity == identity: item._key = k item._value = value # i points to last found item rgt = i self._impl.incr_version() break else: self._impl._items.append(_Pair.__new__(_Pair, identity, k, value)) self._impl.incr_version() return # remove all precending items i = 0 while i < rgt: item = <_Pair>items[i] if h == item._hash and item._identity == identity: del items[i] rgt -= 1 else: i += 1 def add(self, key, value): """Add the key and value, not overwriting any previous value.""" self._add(key, value) def copy(self): """Return a copy of itself.""" ret = MultiDict() ret._extend((list(self.items()),), {}, 'copy', True) return ret def extend(self, *args, **kwargs): """Extend current MultiDict with more values. This method must be used instead of update. """ self._extend(args, kwargs, "extend", True) def clear(self): """Remove all items from MultiDict""" self._impl._items.clear() self._impl.incr_version() # MutableMapping interface # def __setitem__(self, key, value): self._replace(key, value) def __delitem__(self, key): self._remove(key) cdef _remove(self, key): cdef _Pair item cdef bint found = False cdef str identity = self._title(key) cdef Py_hash_t h = hash(identity) cdef list items = self._impl._items for i in range(len(items) - 1, -1, -1): item = <_Pair>items[i] if item._hash != h: continue if item._identity == identity: del items[i] found = True if not found: raise KeyError(key) else: self._impl.incr_version() def setdefault(self, key, default=None): """Return value for key, set value to default if key is not present.""" cdef _Pair item cdef str identity = self._title(key) cdef Py_hash_t h = hash(identity) cdef list items = self._impl._items for i in items: item = <_Pair>i if item._hash != h: continue if item._identity == identity: return item._value self._add(key, default) return default def popone(self, key, default=_marker): """Remove the last occurrence of key and return the corresponding value. If key is not found, default is returned if given, otherwise KeyError is raised. """ cdef object value = None cdef str identity = self._title(key) cdef Py_hash_t h = hash(identity) cdef _Pair item cdef list items = self._impl._items for i in range(len(items)): item = <_Pair>items[i] if item._hash != h: continue if item._identity == identity: value = item._value del items[i] self._impl.incr_version() return value if default is _marker: raise KeyError(key) else: return default pop = popone def popall(self, key, default=_marker): """Remove all occurrences of key and return the list of corresponding values. If key is not found, default is returned if given, otherwise KeyError is raised. """ cdef bint found = False cdef str identity = self._title(key) cdef Py_hash_t h = hash(identity) cdef _Pair item cdef list items = self._impl._items cdef list ret = [] for i in range(len(items)-1, -1, -1): item = <_Pair>items[i] if item._hash != h: continue if item._identity == identity: ret.append(item._value) del items[i] self._impl.incr_version() found = True if not found: if default is _marker: raise KeyError(key) else: return default else: ret.reverse() return ret def popitem(self): """Remove and return an arbitrary (key, value) pair.""" cdef _Pair item cdef list items = self._impl._items if items: item = <_Pair>items.pop(0) self._impl.incr_version() return (item._key, item._value) else: raise KeyError("empty multidict") def update(self, *args, **kwargs): """Update the dictionary from *other*, overwriting existing keys.""" self._extend(args, kwargs, "update", False) MutableMultiMapping.register(MultiDict) cdef class CIMultiDict(MultiDict): """An ordered dictionary that can have multiple values for each key.""" def __init__(self, *args, **kwargs): self._impl = _Impl() self._extend(args, kwargs, 'CIMultiDict', True) def __reduce__(self): return ( self.__class__, (list(self.items()),), ) cdef str _title(self, s): typ = type(s) if typ is str: return <str>(s.title()) elif type(s) is _istr: return PyObject_Str(s) return s.title() def copy(self): """Return a copy of itself.""" ret = CIMultiDict() ret._extend((list(self.items()),), {}, 'copy', True) return ret MutableMultiMapping.register(CIMultiDict) cdef class _ViewBase: cdef _Impl _impl def __cinit__(self, _Impl impl): self._impl = impl def __len__(self): return len(self._impl._items) cdef class _ViewBaseSet(_ViewBase): def __richcmp__(self, other, op): if op == 0: # < if not isinstance(other, Set): return NotImplemented return len(self) < len(other) and self <= other elif op == 1: # <= if not isinstance(other, Set): return NotImplemented if len(self) > len(other): return False for elem in self: if elem not in other: return False return True elif op == 2: # == if not isinstance(other, Set): return NotImplemented return len(self) == len(other) and self <= other elif op == 3: # != return not self == other elif op == 4: # > if not isinstance(other, Set): return NotImplemented return len(self) > len(other) and self >= other elif op == 5: # >= if not isinstance(other, Set): return NotImplemented if len(self) < len(other): return False for elem in other: if elem not in self: return False return True def __and__(self, other): if not isinstance(other, Iterable): return NotImplemented if isinstance(self, _ViewBaseSet): self = set(iter(self)) if isinstance(other, _ViewBaseSet): other = set(iter(other)) if not isinstance(other, Set): other = set(iter(other)) return self & other def __or__(self, other): if not isinstance(other, Iterable): return NotImplemented if isinstance(self, _ViewBaseSet): self = set(iter(self)) if isinstance(other, _ViewBaseSet): other = set(iter(other)) if not isinstance(other, Set): other = set(iter(other)) return self | other def __sub__(self, other): if not isinstance(other, Iterable): return NotImplemented if isinstance(self, _ViewBaseSet): self = set(iter(self)) if isinstance(other, _ViewBaseSet): other = set(iter(other)) if not isinstance(other, Set): other = set(iter(other)) return self - other def __xor__(self, other): if not isinstance(other, Iterable): return NotImplemented if isinstance(self, _ViewBaseSet): self = set(iter(self)) if isinstance(other, _ViewBaseSet): other = set(iter(other)) if not isinstance(other, Set): other = set(iter(other)) return self ^ other cdef class _ItemsIter: cdef _Impl _impl cdef int _current cdef int _len cdef unsigned long long _version def __cinit__(self, _Impl impl): self._impl = impl self._current = 0 self._version = impl._version self._len = len(impl._items) def __iter__(self): return self def __next__(self): if self._version != self._impl._version: raise RuntimeError("Dictionary changed during iteration") if self._current == self._len: raise StopIteration item = <_Pair>self._impl._items[self._current] self._current += 1 return (item._key, item._value) cdef class _ItemsView(_ViewBaseSet): def isdisjoint(self, other): 'Return True if two sets have a null intersection.' cdef _Pair item for i in self._impl._items: item = <_Pair>i t = (item._key, item._value) if t in other: return False return True def __contains__(self, i): cdef _Pair item cdef str key cdef object value assert isinstance(i, tuple) or isinstance(i, list) assert len(i) == 2 key = i[0] value = i[1] for item in self._impl._items: if key == item._key and value == item._value: return True return False def __iter__(self): return _ItemsIter.__new__(_ItemsIter, self._impl) def __repr__(self): cdef _Pair item lst = [] for i in self._impl._items: item = <_Pair>i lst.append("{!r}: {!r}".format(item._key, item._value)) body = ', '.join(lst) return '{}({})'.format(self.__class__.__name__, body) abc.ItemsView.register(_ItemsView) cdef class _ValuesIter: cdef _Impl _impl cdef int _current cdef int _len cdef unsigned long long _version def __cinit__(self, _Impl impl): self._impl = impl self._current = 0 self._len = len(impl._items) self._version = impl._version def __iter__(self): return self def __next__(self): if self._version != self._impl._version: raise RuntimeError("Dictionary changed during iteration") if self._current == self._len: raise StopIteration item = <_Pair>self._impl._items[self._current] self._current += 1 return item._value cdef class _ValuesView(_ViewBase): def __contains__(self, value): cdef _Pair item for i in self._impl._items: item = <_Pair>i if item._value == value: return True return False def __iter__(self): return _ValuesIter.__new__(_ValuesIter, self._impl) def __repr__(self): cdef _Pair item lst = [] for i in self._impl._items: item = <_Pair>i lst.append("{!r}".format(item._value)) body = ', '.join(lst) return '{}({})'.format(self.__class__.__name__, body) abc.ValuesView.register(_ValuesView) cdef class _KeysIter: cdef _Impl _impl cdef int _current cdef int _len cdef unsigned long long _version def __cinit__(self, _Impl impl): self._impl = impl self._current = 0 self._len = len(self._impl._items) self._version = impl._version def __iter__(self): return self def __next__(self): if self._version != self._impl._version: raise RuntimeError("Dictionary changed during iteration") if self._current == self._len: raise StopIteration item = <_Pair>self._impl._items[self._current] self._current += 1 return item._key cdef class _KeysView(_ViewBaseSet): def isdisjoint(self, other): 'Return True if two sets have a null intersection.' cdef _Pair item for i in self._impl._items: item = <_Pair>i if item._key in other: return False return True def __contains__(self, value): cdef _Pair item for i in self._impl._items: item = <_Pair>i if item._key == value: return True return False def __iter__(self): return _KeysIter.__new__(_KeysIter, self._impl) def __repr__(self): cdef _Pair item lst = [] for i in self._impl._items: item = <_Pair>i lst.append("{!r}".format(item._key)) body = ', '.join(lst) return '{}({})'.format(self.__class__.__name__, body) abc.KeysView.register(_KeysView)