NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

datastructures.py (44543B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\werkzeug\datastructures.py
      2 import re
      3 import codecs
      4 import mimetypes
      5 from werkzeug._internal import _proxy_repr, _missing, _empty_stream
      6 _locale_delim_re = re.compile('[_-]')
      7 
      8 def is_immutable(self):
      9     raise TypeError('%r objects are immutable' % self.__class__.__name__)
     10 
     11 
     12 def iter_multi_items(mapping):
     13     if isinstance(mapping, MultiDict):
     14         for item in mapping.iteritems(multi=True):
     15             yield item
     16 
     17     elif isinstance(mapping, dict):
     18         for key, value in mapping.iteritems():
     19             if isinstance(value, (tuple, list)):
     20                 for value in value:
     21                     yield (key, value)
     22 
     23             else:
     24                 yield (key, value)
     25 
     26     else:
     27         for item in mapping:
     28             yield item
     29 
     30 
     31 class ImmutableListMixin(object):
     32 
     33     def __reduce_ex__(self, protocol):
     34         return (type(self), (list(self),))
     35 
     36     def __delitem__(self, key):
     37         is_immutable(self)
     38 
     39     def __delslice__(self, i, j):
     40         is_immutable(self)
     41 
     42     def __iadd__(self, other):
     43         is_immutable(self)
     44 
     45     __imul__ = __iadd__
     46 
     47     def __setitem__(self, key, value):
     48         is_immutable(self)
     49 
     50     def __setslice__(self, i, j, value):
     51         is_immutable(self)
     52 
     53     def append(self, item):
     54         is_immutable(self)
     55 
     56     remove = append
     57 
     58     def extend(self, iterable):
     59         is_immutable(self)
     60 
     61     def insert(self, pos, value):
     62         is_immutable(self)
     63 
     64     def pop(self, index = -1):
     65         is_immutable(self)
     66 
     67     def reverse(self):
     68         is_immutable(self)
     69 
     70     def sort(self, cmp = None, key = None, reverse = None):
     71         is_immutable(self)
     72 
     73 
     74 class ImmutableList(ImmutableListMixin, list):
     75     __repr__ = _proxy_repr(list)
     76 
     77 
     78 class ImmutableDictMixin(object):
     79 
     80     def __reduce_ex__(self, protocol):
     81         return (type(self), (dict(self),))
     82 
     83     def setdefault(self, key, default = None):
     84         is_immutable(self)
     85 
     86     def update(self, *args, **kwargs):
     87         is_immutable(self)
     88 
     89     def pop(self, key, default = None):
     90         is_immutable(self)
     91 
     92     def popitem(self):
     93         is_immutable(self)
     94 
     95     def __setitem__(self, key, value):
     96         is_immutable(self)
     97 
     98     def __delitem__(self, key):
     99         is_immutable(self)
    100 
    101     def clear(self):
    102         is_immutable(self)
    103 
    104 
    105 class ImmutableMultiDictMixin(ImmutableDictMixin):
    106 
    107     def __reduce_ex__(self, protocol):
    108         return (type(self), (self.items(multi=True),))
    109 
    110     def add(self, key, value):
    111         is_immutable(self)
    112 
    113     def popitemlist(self):
    114         is_immutable(self)
    115 
    116     def poplist(self, key):
    117         is_immutable(self)
    118 
    119     def setlist(self, key, new_list):
    120         is_immutable(self)
    121 
    122     def setlistdefault(self, key, default_list = None):
    123         is_immutable(self)
    124 
    125 
    126 class UpdateDictMixin(object):
    127     on_update = None
    128 
    129     def calls_update(name):
    130 
    131         def oncall(self, *args, **kw):
    132             rv = getattr(super(UpdateDictMixin, self), name)(*args, **kw)
    133             if self.on_update is not None:
    134                 self.on_update(self)
    135             return rv
    136 
    137         oncall.__name__ = name
    138         return oncall
    139 
    140     __setitem__ = calls_update('__setitem__')
    141     __delitem__ = calls_update('__delitem__')
    142     clear = calls_update('clear')
    143     pop = calls_update('pop')
    144     popitem = calls_update('popitem')
    145     setdefault = calls_update('setdefault')
    146     update = calls_update('update')
    147     del calls_update
    148 
    149 
    150 class TypeConversionDict(dict):
    151 
    152     def get(self, key, default = None, type = None):
    153         try:
    154             rv = self[key]
    155             if type is not None:
    156                 rv = type(rv)
    157         except (KeyError, ValueError):
    158             rv = default
    159 
    160         return rv
    161 
    162 
    163 class ImmutableTypeConversionDict(ImmutableDictMixin, TypeConversionDict):
    164 
    165     def copy(self):
    166         return TypeConversionDict(self)
    167 
    168     def __copy__(self):
    169         return self
    170 
    171 
    172 class MultiDict(TypeConversionDict):
    173     KeyError = None
    174 
    175     def __init__(self, mapping = None):
    176         if isinstance(mapping, MultiDict):
    177             dict.__init__(self, ((k, l[:]) for k, l in mapping.iterlists()))
    178         elif isinstance(mapping, dict):
    179             tmp = {}
    180             for key, value in mapping.iteritems():
    181                 if isinstance(value, (tuple, list)):
    182                     value = list(value)
    183                 else:
    184                     value = [value]
    185                 tmp[key] = value
    186 
    187             dict.__init__(self, tmp)
    188         else:
    189             tmp = {}
    190             for key, value in mapping or ():
    191                 tmp.setdefault(key, []).append(value)
    192 
    193             dict.__init__(self, tmp)
    194 
    195     def __getstate__(self):
    196         return dict(self.lists())
    197 
    198     def __setstate__(self, value):
    199         dict.clear(self)
    200         dict.update(self, value)
    201 
    202     def __iter__(self):
    203         return self.iterkeys()
    204 
    205     def __getitem__(self, key):
    206         if key in self:
    207             return dict.__getitem__(self, key)[0]
    208         raise self.KeyError(key)
    209 
    210     def __setitem__(self, key, value):
    211         dict.__setitem__(self, key, [value])
    212 
    213     def add(self, key, value):
    214         dict.setdefault(self, key, []).append(value)
    215 
    216     def getlist(self, key, type = None):
    217         try:
    218             rv = dict.__getitem__(self, key)
    219         except KeyError:
    220             return []
    221 
    222         if type is None:
    223             return list(rv)
    224         result = []
    225         for item in rv:
    226             try:
    227                 result.append(type(item))
    228             except ValueError:
    229                 pass
    230 
    231         return result
    232 
    233     def setlist(self, key, new_list):
    234         dict.__setitem__(self, key, list(new_list))
    235 
    236     def setdefault(self, key, default = None):
    237         if key not in self:
    238             self[key] = default
    239         else:
    240             default = self[key]
    241         return default
    242 
    243     def setlistdefault(self, key, default_list = None):
    244         if key not in self:
    245             default_list = list(default_list or ())
    246             dict.__setitem__(self, key, default_list)
    247         else:
    248             default_list = dict.__getitem__(self, key)
    249         return default_list
    250 
    251     def items(self, multi = False):
    252         return list(self.iteritems(multi))
    253 
    254     def lists(self):
    255         return list(self.iterlists())
    256 
    257     def values(self):
    258         return [ self[key] for key in self.iterkeys() ]
    259 
    260     def listvalues(self):
    261         return list(self.iterlistvalues())
    262 
    263     def iteritems(self, multi = False):
    264         for key, values in dict.iteritems(self):
    265             if multi:
    266                 for value in values:
    267                     yield (key, value)
    268 
    269             else:
    270                 yield (key, values[0])
    271 
    272     def iterlists(self):
    273         for key, values in dict.iteritems(self):
    274             yield (key, list(values))
    275 
    276     def itervalues(self):
    277         for values in dict.itervalues(self):
    278             yield values[0]
    279 
    280     def iterlistvalues(self):
    281         for values in dict.itervalues(self):
    282             yield list(values)
    283 
    284     def copy(self):
    285         return self.__class__(self)
    286 
    287     def to_dict(self, flat = True):
    288         if flat:
    289             return dict(self.iteritems())
    290         return dict(self.lists())
    291 
    292     def update(self, other_dict):
    293         for key, value in iter_multi_items(other_dict):
    294             MultiDict.add(self, key, value)
    295 
    296     def pop(self, key, default = _missing):
    297         try:
    298             return dict.pop(self, key)[0]
    299         except KeyError as e:
    300             if default is not _missing:
    301                 return default
    302             raise self.KeyError(str(e))
    303 
    304     def popitem(self):
    305         try:
    306             item = dict.popitem(self)
    307             return (item[0], item[1][0])
    308         except KeyError as e:
    309             raise self.KeyError(str(e))
    310 
    311     def poplist(self, key):
    312         return dict.pop(self, key, [])
    313 
    314     def popitemlist(self):
    315         try:
    316             return dict.popitem(self)
    317         except KeyError as e:
    318             raise self.KeyError(str(e))
    319 
    320     def __repr__(self):
    321         return '%s(%r)' % (self.__class__.__name__, self.items(multi=True))
    322 
    323 
    324 class _omd_bucket(object):
    325     __slots__ = ('prev', 'key', 'value', 'next')
    326 
    327     def __init__(self, omd, key, value):
    328         self.prev = omd._last_bucket
    329         self.key = key
    330         self.value = value
    331         self.next = None
    332         if omd._first_bucket is None:
    333             omd._first_bucket = self
    334         if omd._last_bucket is not None:
    335             omd._last_bucket.next = self
    336         omd._last_bucket = self
    337 
    338     def unlink(self, omd):
    339         if self.prev:
    340             self.prev.next = self.next
    341         if self.next:
    342             self.next.prev = self.prev
    343         if omd._first_bucket is self:
    344             omd._first_bucket = self.next
    345         if omd._last_bucket is self:
    346             omd._last_bucket = self.prev
    347 
    348 
    349 class OrderedMultiDict(MultiDict):
    350     KeyError = None
    351 
    352     def __init__(self, mapping = None):
    353         dict.__init__(self)
    354         self._first_bucket = self._last_bucket = None
    355         if mapping is not None:
    356             OrderedMultiDict.update(self, mapping)
    357 
    358     def __eq__(self, other):
    359         if not isinstance(other, MultiDict):
    360             return NotImplemented
    361         if isinstance(other, OrderedMultiDict):
    362             iter1 = self.iteritems(multi=True)
    363             iter2 = other.iteritems(multi=True)
    364             try:
    365                 for k1, v1 in iter1:
    366                     k2, v2 = iter2.next()
    367                     if k1 != k2 or v1 != v2:
    368                         return False
    369 
    370             except StopIteration:
    371                 return False
    372 
    373             try:
    374                 iter2.next()
    375             except StopIteration:
    376                 return True
    377 
    378             return False
    379         if len(self) != len(other):
    380             return False
    381         for key, values in self.iterlists():
    382             if other.getlist(key) != values:
    383                 return False
    384 
    385         return True
    386 
    387     def __ne__(self, other):
    388         return not self.__eq__(other)
    389 
    390     def __reduce_ex__(self, protocol):
    391         return (type(self), (self.items(multi=True),))
    392 
    393     def __getstate__(self):
    394         return self.items(multi=True)
    395 
    396     def __setstate__(self, values):
    397         dict.clear(self)
    398         for key, value in values:
    399             self.add(key, value)
    400 
    401     def __getitem__(self, key):
    402         if key in self:
    403             return dict.__getitem__(self, key)[0].value
    404         raise self.KeyError(key)
    405 
    406     def __setitem__(self, key, value):
    407         self.poplist(key)
    408         self.add(key, value)
    409 
    410     def __delitem__(self, key):
    411         self.pop(key)
    412 
    413     def iterkeys(self):
    414         return (key for key, value in self.iteritems())
    415 
    416     def itervalues(self):
    417         return (value for key, value in self.iteritems())
    418 
    419     def iteritems(self, multi = False):
    420         ptr = self._first_bucket
    421         if multi:
    422             while ptr is not None:
    423                 yield (ptr.key, ptr.value)
    424                 ptr = ptr.next
    425 
    426         else:
    427             returned_keys = set()
    428             while ptr is not None:
    429                 if ptr.key not in returned_keys:
    430                     returned_keys.add(ptr.key)
    431                     yield (ptr.key, ptr.value)
    432                 ptr = ptr.next
    433 
    434     def iterlists(self):
    435         returned_keys = set()
    436         ptr = self._first_bucket
    437         while ptr is not None:
    438             if ptr.key not in returned_keys:
    439                 yield (ptr.key, self.getlist(ptr.key))
    440                 returned_keys.add(ptr.key)
    441             ptr = ptr.next
    442 
    443     def iterlistvalues(self):
    444         for key, values in self.iterlists():
    445             yield values
    446 
    447     def add(self, key, value):
    448         dict.setdefault(self, key, []).append(_omd_bucket(self, key, value))
    449 
    450     def getlist(self, key, type = None):
    451         try:
    452             rv = dict.__getitem__(self, key)
    453         except KeyError:
    454             return []
    455 
    456         if type is None:
    457             return [ x.value for x in rv ]
    458         result = []
    459         for item in rv:
    460             try:
    461                 result.append(type(item.value))
    462             except ValueError:
    463                 pass
    464 
    465         return result
    466 
    467     def setlist(self, key, new_list):
    468         self.poplist(key)
    469         for value in new_list:
    470             self.add(key, value)
    471 
    472     def setlistdefault(self, key, default_list = None):
    473         raise TypeError('setlistdefault is unsupported for ordered multi dicts')
    474 
    475     def update(self, mapping):
    476         for key, value in iter_multi_items(mapping):
    477             OrderedMultiDict.add(self, key, value)
    478 
    479     def poplist(self, key):
    480         buckets = dict.pop(self, key, ())
    481         for bucket in buckets:
    482             bucket.unlink(self)
    483 
    484         return [ x.value for x in buckets ]
    485 
    486     def pop(self, key, default = _missing):
    487         try:
    488             buckets = dict.pop(self, key)
    489         except KeyError as e:
    490             if default is not _missing:
    491                 return default
    492             raise self.KeyError(str(e))
    493 
    494         for bucket in buckets:
    495             bucket.unlink(self)
    496 
    497         return buckets[0].value
    498 
    499     def popitem(self):
    500         try:
    501             key, buckets = dict.popitem(self)
    502         except KeyError as e:
    503             raise self.KeyError(str(e))
    504 
    505         for bucket in buckets:
    506             bucket.unlink(self)
    507 
    508         return (key, buckets[0].value)
    509 
    510     def popitemlist(self):
    511         try:
    512             key, buckets = dict.popitem(self)
    513         except KeyError as e:
    514             raise self.KeyError(str(e))
    515 
    516         for bucket in buckets:
    517             bucket.unlink(self)
    518 
    519         return (key, [ x.value for x in buckets ])
    520 
    521 
    522 def _options_header_vkw(value, kw):
    523     if not kw:
    524         return value
    525     return dump_options_header(value, dict(((k.replace('_', '-'), v) for k, v in kw.items())))
    526 
    527 
    528 class Headers(object):
    529     KeyError = None
    530 
    531     def __init__(self, defaults = None, _list = None):
    532         if _list is None:
    533             _list = []
    534         self._list = _list
    535         if defaults is not None:
    536             if isinstance(defaults, (list, Headers)):
    537                 self._list.extend(defaults)
    538             else:
    539                 self.extend(defaults)
    540 
    541     @classmethod
    542     def linked(cls, headerlist):
    543         return cls(_list=headerlist)
    544 
    545     def __getitem__(self, key, _index_operation = True):
    546         if _index_operation:
    547             if isinstance(key, (int, long)):
    548                 return self._list[key]
    549             if isinstance(key, slice):
    550                 return self.__class__(self._list[key])
    551         ikey = key.lower()
    552         for k, v in self._list:
    553             if k.lower() == ikey:
    554                 return v
    555 
    556         raise self.KeyError(key)
    557 
    558     def __eq__(self, other):
    559         return other.__class__ is self.__class__ and set(other._list) == set(self._list)
    560 
    561     def __ne__(self, other):
    562         return not self.__eq__(other)
    563 
    564     def get(self, key, default = None, type = None):
    565         try:
    566             rv = self.__getitem__(key, _index_operation=False)
    567         except KeyError:
    568             return default
    569 
    570         if type is None:
    571             return rv
    572         try:
    573             return type(rv)
    574         except ValueError:
    575             return default
    576 
    577     def getlist(self, key, type = None):
    578         ikey = key.lower()
    579         result = []
    580         for k, v in self:
    581             if k.lower() == ikey:
    582                 if type is not None:
    583                     try:
    584                         v = type(v)
    585                     except ValueError:
    586                         continue
    587 
    588                 result.append(v)
    589 
    590         return result
    591 
    592     def get_all(self, name):
    593         return self.getlist(name)
    594 
    595     def iteritems(self, lower = False):
    596         for key, value in self:
    597             if lower:
    598                 key = key.lower()
    599             yield (key, value)
    600 
    601     def iterkeys(self, lower = False):
    602         for key, _ in self.iteritems(lower):
    603             yield key
    604 
    605     def itervalues(self):
    606         for _, value in self.iteritems():
    607             yield value
    608 
    609     def keys(self, lower = False):
    610         return list(self.iterkeys(lower))
    611 
    612     def values(self):
    613         return list(self.itervalues())
    614 
    615     def items(self, lower = False):
    616         return list(self.iteritems(lower))
    617 
    618     def extend(self, iterable):
    619         if isinstance(iterable, dict):
    620             for key, value in iterable.iteritems():
    621                 if isinstance(value, (tuple, list)):
    622                     for v in value:
    623                         self.add(key, v)
    624 
    625                 else:
    626                     self.add(key, value)
    627 
    628         else:
    629             for key, value in iterable:
    630                 self.add(key, value)
    631 
    632     def __delitem__(self, key, _index_operation = True):
    633         if _index_operation and isinstance(key, (int, long, slice)):
    634             del self._list[key]
    635             return
    636         key = key.lower()
    637         new = []
    638         for k, v in self._list:
    639             if k.lower() != key:
    640                 new.append((k, v))
    641 
    642         self._list[:] = new
    643 
    644     def remove(self, key):
    645         return self.__delitem__(key, _index_operation=False)
    646 
    647     def pop(self, key = None, default = _missing):
    648         if key is None:
    649             return self._list.pop()
    650         if isinstance(key, (int, long)):
    651             return self._list.pop(key)
    652         try:
    653             rv = self[key]
    654             self.remove(key)
    655         except KeyError:
    656             if default is not _missing:
    657                 return default
    658             raise
    659 
    660         return rv
    661 
    662     def popitem(self):
    663         return self.pop()
    664 
    665     def __contains__(self, key):
    666         try:
    667             self.__getitem__(key, _index_operation=False)
    668         except KeyError:
    669             return False
    670 
    671         return True
    672 
    673     has_key = __contains__
    674 
    675     def __iter__(self):
    676         return iter(self._list)
    677 
    678     def __len__(self):
    679         return len(self._list)
    680 
    681     def add(self, _key, _value, **kw):
    682         self._list.append((_key, _options_header_vkw(_value, kw)))
    683 
    684     def add_header(self, _key, _value, **_kw):
    685         self.add(_key, _value, **_kw)
    686 
    687     def clear(self):
    688         del self._list[:]
    689 
    690     def set(self, _key, _value, **kw):
    691         lc_key = _key.lower()
    692         _value = _options_header_vkw(_value, kw)
    693         for idx, (old_key, old_value) in enumerate(self._list):
    694             if old_key.lower() == lc_key:
    695                 self._list[idx] = (_key, _value)
    696                 break
    697         else:
    698             return self.add(_key, _value)
    699 
    700         self._list[idx + 1:] = [ (k, v) for k, v in self._list[idx + 1:] if k.lower() != lc_key ]
    701 
    702     def setdefault(self, key, value):
    703         if key in self:
    704             return self[key]
    705         self.set(key, value)
    706         return value
    707 
    708     def __setitem__(self, key, value):
    709         if isinstance(key, (slice, int, long)):
    710             self._list[key] = value
    711         else:
    712             self.set(key, value)
    713 
    714     def to_list(self, charset = 'utf-8'):
    715         result = []
    716         for k, v in self:
    717             if isinstance(v, unicode):
    718                 v = v.encode(charset)
    719             else:
    720                 v = str(v)
    721             result.append((k, v))
    722 
    723         return result
    724 
    725     def copy(self):
    726         return self.__class__(self._list)
    727 
    728     def __copy__(self):
    729         return self.copy()
    730 
    731     def __str__(self, charset = 'utf-8'):
    732         strs = []
    733         for key, value in self.to_list(charset):
    734             strs.append('%s: %s' % (key, value))
    735 
    736         strs.append('\r\n')
    737         return '\r\n'.join(strs)
    738 
    739     def __repr__(self):
    740         return '%s(%r)' % (self.__class__.__name__, list(self))
    741 
    742 
    743 class ImmutableHeadersMixin(object):
    744 
    745     def __delitem__(self, key):
    746         is_immutable(self)
    747 
    748     def __setitem__(self, key, value):
    749         is_immutable(self)
    750 
    751     set = __setitem__
    752 
    753     def add(self, item):
    754         is_immutable(self)
    755 
    756     remove = add_header = add
    757 
    758     def extend(self, iterable):
    759         is_immutable(self)
    760 
    761     def insert(self, pos, value):
    762         is_immutable(self)
    763 
    764     def pop(self, index = -1):
    765         is_immutable(self)
    766 
    767     def popitem(self):
    768         is_immutable(self)
    769 
    770     def setdefault(self, key, default):
    771         is_immutable(self)
    772 
    773 
    774 class EnvironHeaders(ImmutableHeadersMixin, Headers):
    775 
    776     def __init__(self, environ):
    777         self.environ = environ
    778 
    779     @classmethod
    780     def linked(cls, environ):
    781         raise TypeError('%r object is always linked to environment, no separate initializer' % cls.__name__)
    782 
    783     def __eq__(self, other):
    784         return self.environ is other.environ
    785 
    786     def __getitem__(self, key, _index_operation = False):
    787         key = key.upper().replace('-', '_')
    788         if key in ('CONTENT_TYPE', 'CONTENT_LENGTH'):
    789             return self.environ[key]
    790         return self.environ['HTTP_' + key]
    791 
    792     def __len__(self):
    793         return len(list(iter(self)))
    794 
    795     def __iter__(self):
    796         for key, value in self.environ.iteritems():
    797             if key.startswith('HTTP_') and key not in ('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'):
    798                 yield (key[5:].replace('_', '-').title(), value)
    799             elif key in ('CONTENT_TYPE', 'CONTENT_LENGTH'):
    800                 yield (key.replace('_', '-').title(), value)
    801 
    802     def copy(self):
    803         raise TypeError('cannot create %r copies' % self.__class__.__name__)
    804 
    805 
    806 class CombinedMultiDict(ImmutableMultiDictMixin, MultiDict):
    807 
    808     def __reduce_ex__(self, protocol):
    809         return (type(self), (self.dicts,))
    810 
    811     def __init__(self, dicts = None):
    812         self.dicts = dicts or []
    813 
    814     @classmethod
    815     def fromkeys(cls):
    816         raise TypeError('cannot create %r instances by fromkeys' % cls.__name__)
    817 
    818     def __getitem__(self, key):
    819         for d in self.dicts:
    820             if key in d:
    821                 return d[key]
    822 
    823         raise self.KeyError(key)
    824 
    825     def get(self, key, default = None, type = None):
    826         for d in self.dicts:
    827             if key in d:
    828                 if type is not None:
    829                     try:
    830                         return type(d[key])
    831                     except ValueError:
    832                         continue
    833 
    834                 return d[key]
    835 
    836         return default
    837 
    838     def getlist(self, key, type = None):
    839         rv = []
    840         for d in self.dicts:
    841             rv.extend(d.getlist(key, type))
    842 
    843         return rv
    844 
    845     def keys(self):
    846         rv = set()
    847         for d in self.dicts:
    848             rv.update(d.keys())
    849 
    850         return list(rv)
    851 
    852     def iteritems(self, multi = False):
    853         found = set()
    854         for d in self.dicts:
    855             for key, value in d.iteritems(multi):
    856                 if multi:
    857                     yield (key, value)
    858                 elif key not in found:
    859                     found.add(key)
    860                     yield (key, value)
    861 
    862     def itervalues(self):
    863         for key, value in self.iteritems():
    864             yield value
    865 
    866     def values(self):
    867         return list(self.itervalues())
    868 
    869     def items(self, multi = False):
    870         return list(self.iteritems(multi))
    871 
    872     def iterlists(self):
    873         rv = {}
    874         for d in self.dicts:
    875             for key, values in d.iterlists():
    876                 rv.setdefault(key, []).extend(values)
    877 
    878         return rv.iteritems()
    879 
    880     def lists(self):
    881         return list(self.iterlists())
    882 
    883     def iterlistvalues(self):
    884         return (x[0] for x in self.lists())
    885 
    886     def listvalues(self):
    887         return list(self.iterlistvalues())
    888 
    889     def iterkeys(self):
    890         return iter(self.keys())
    891 
    892     __iter__ = iterkeys
    893 
    894     def copy(self):
    895         return self.__class__(self.dicts[:])
    896 
    897     def to_dict(self, flat = True):
    898         rv = {}
    899         for d in reversed(self.dicts):
    900             rv.update(d.to_dict(flat))
    901 
    902         return rv
    903 
    904     def __len__(self):
    905         return len(self.keys())
    906 
    907     def __contains__(self, key):
    908         for d in self.dicts:
    909             if key in d:
    910                 return True
    911 
    912         return False
    913 
    914     has_key = __contains__
    915 
    916     def __repr__(self):
    917         return '%s(%r)' % (self.__class__.__name__, self.dicts)
    918 
    919 
    920 class FileMultiDict(MultiDict):
    921 
    922     def add_file(self, name, file, filename = None, content_type = None):
    923         if isinstance(file, FileStorage):
    924             self[name] = file
    925             return
    926         if isinstance(file, basestring):
    927             if filename is None:
    928                 filename = file
    929             file = open(file, 'rb')
    930         if filename and content_type is None:
    931             content_type = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
    932         self[name] = FileStorage(file, filename, name, content_type)
    933 
    934 
    935 class ImmutableDict(ImmutableDictMixin, dict):
    936     __repr__ = _proxy_repr(dict)
    937 
    938     def copy(self):
    939         return dict(self)
    940 
    941     def __copy__(self):
    942         return self
    943 
    944 
    945 class ImmutableMultiDict(ImmutableMultiDictMixin, MultiDict):
    946 
    947     def copy(self):
    948         return MultiDict(self)
    949 
    950     def __copy__(self):
    951         return self
    952 
    953 
    954 class ImmutableOrderedMultiDict(ImmutableMultiDictMixin, OrderedMultiDict):
    955 
    956     def copy(self):
    957         return OrderedMultiDict(self)
    958 
    959     def __copy__(self):
    960         return self
    961 
    962 
    963 class Accept(ImmutableList):
    964 
    965     def __init__(self, values = ()):
    966         if values is None:
    967             list.__init__(self)
    968             self.provided = False
    969         elif isinstance(values, Accept):
    970             self.provided = values.provided
    971             list.__init__(self, values)
    972         else:
    973             self.provided = True
    974             values = [ (a, b) for b, a in values ]
    975             values.sort()
    976             values.reverse()
    977             list.__init__(self, [ (a, b) for b, a in values ])
    978 
    979     def _value_matches(self, value, item):
    980         return item == '*' or item.lower() == value.lower()
    981 
    982     def __getitem__(self, key):
    983         if isinstance(key, basestring):
    984             return self.quality(key)
    985         return list.__getitem__(self, key)
    986 
    987     def quality(self, key):
    988         for item, quality in self:
    989             if self._value_matches(key, item):
    990                 return quality
    991 
    992         return 0
    993 
    994     def __contains__(self, value):
    995         for item, quality in self:
    996             if self._value_matches(value, item):
    997                 return True
    998 
    999         return False
   1000 
   1001     def __repr__(self):
   1002         return '%s([%s])' % (self.__class__.__name__, ', '.join(('(%r, %s)' % (x, y) for x, y in self)))
   1003 
   1004     def index(self, key):
   1005         if isinstance(key, basestring):
   1006             for idx, (item, quality) in enumerate(self):
   1007                 if self._value_matches(key, item):
   1008                     return idx
   1009 
   1010             raise ValueError(key)
   1011         return list.index(self, key)
   1012 
   1013     def find(self, key):
   1014         try:
   1015             return self.index(key)
   1016         except ValueError:
   1017             return -1
   1018 
   1019     def values(self):
   1020         return list(self.itervalues())
   1021 
   1022     def itervalues(self):
   1023         for item in self:
   1024             yield item[0]
   1025 
   1026     def to_header(self):
   1027         result = []
   1028         for value, quality in self:
   1029             if quality != 1:
   1030                 value = '%s;q=%s' % (value, quality)
   1031             result.append(value)
   1032 
   1033         return ','.join(result)
   1034 
   1035     def __str__(self):
   1036         return self.to_header()
   1037 
   1038     def best_match(self, matches, default = None):
   1039         best_quality = -1
   1040         result = default
   1041         for server_item in matches:
   1042             for client_item, quality in self:
   1043                 if quality <= best_quality:
   1044                     break
   1045                 if self._value_matches(client_item, server_item):
   1046                     best_quality = quality
   1047                     result = server_item
   1048 
   1049         return result
   1050 
   1051     @property
   1052     def best(self):
   1053         if self:
   1054             return self[0][0]
   1055 
   1056 
   1057 class MIMEAccept(Accept):
   1058 
   1059     def _value_matches(self, value, item):
   1060 
   1061         def _normalize(x):
   1062             x = x.lower()
   1063             return x == '*' and ('*', '*') or x.split('/', 1)
   1064 
   1065         if '/' not in value:
   1066             raise ValueError('invalid mimetype %r' % value)
   1067         value_type, value_subtype = _normalize(value)
   1068         if value_type == '*' and value_subtype != '*':
   1069             raise ValueError('invalid mimetype %r' % value)
   1070         if '/' not in item:
   1071             return False
   1072         item_type, item_subtype = _normalize(item)
   1073         if item_type == '*' and item_subtype != '*':
   1074             return False
   1075         return item_type == item_subtype == '*' or value_type == value_subtype == '*' or item_type == value_type and (item_subtype == '*' or value_subtype == '*' or item_subtype == value_subtype)
   1076 
   1077     @property
   1078     def accept_html(self):
   1079         return 'text/html' in self or 'application/xhtml+xml' in self or self.accept_xhtml
   1080 
   1081     @property
   1082     def accept_xhtml(self):
   1083         return 'application/xhtml+xml' in self or 'application/xml' in self
   1084 
   1085 
   1086 class LanguageAccept(Accept):
   1087 
   1088     def _value_matches(self, value, item):
   1089 
   1090         def _normalize(language):
   1091             return _locale_delim_re.split(language.lower())
   1092 
   1093         return item == '*' or _normalize(value) == _normalize(item)
   1094 
   1095 
   1096 class CharsetAccept(Accept):
   1097 
   1098     def _value_matches(self, value, item):
   1099 
   1100         def _normalize(name):
   1101             try:
   1102                 return codecs.lookup(name).name
   1103             except LookupError:
   1104                 return name.lower()
   1105 
   1106         return item == '*' or _normalize(value) == _normalize(item)
   1107 
   1108 
   1109 def cache_property(key, empty, type):
   1110     return property(lambda x: x._get_cache_value(key, empty, type), lambda x, v: x._set_cache_value(key, v, type), lambda x: x._del_cache_value(key), 'accessor for %r' % key)
   1111 
   1112 
   1113 class _CacheControl(UpdateDictMixin, dict):
   1114     no_cache = cache_property('no-cache', '*', None)
   1115     no_store = cache_property('no-store', None, bool)
   1116     max_age = cache_property('max-age', -1, int)
   1117     no_transform = cache_property('no-transform', None, None)
   1118 
   1119     def __init__(self, values = (), on_update = None):
   1120         dict.__init__(self, values or ())
   1121         self.on_update = on_update
   1122         self.provided = values is not None
   1123 
   1124     def _get_cache_value(self, key, empty, type):
   1125         if type is bool:
   1126             return key in self
   1127         if key in self:
   1128             value = self[key]
   1129             if value is None:
   1130                 return empty
   1131             if type is not None:
   1132                 try:
   1133                     value = type(value)
   1134                 except ValueError:
   1135                     pass
   1136 
   1137             return value
   1138 
   1139     def _set_cache_value(self, key, value, type):
   1140         if type is bool:
   1141             if value:
   1142                 self[key] = None
   1143             else:
   1144                 self.pop(key, None)
   1145         elif value is None:
   1146             self.pop(key)
   1147         elif value is True:
   1148             self[key] = None
   1149         else:
   1150             self[key] = value
   1151 
   1152     def _del_cache_value(self, key):
   1153         if key in self:
   1154             del self[key]
   1155 
   1156     def to_header(self):
   1157         return dump_header(self)
   1158 
   1159     def __str__(self):
   1160         return self.to_header()
   1161 
   1162     def __repr__(self):
   1163         return '<%s %r>' % (self.__class__.__name__, self.to_header())
   1164 
   1165 
   1166 class RequestCacheControl(ImmutableDictMixin, _CacheControl):
   1167     max_stale = cache_property('max-stale', '*', int)
   1168     min_fresh = cache_property('min-fresh', '*', int)
   1169     no_transform = cache_property('no-transform', None, None)
   1170     only_if_cached = cache_property('only-if-cached', None, bool)
   1171 
   1172 
   1173 class ResponseCacheControl(_CacheControl):
   1174     public = cache_property('public', None, bool)
   1175     private = cache_property('private', '*', None)
   1176     must_revalidate = cache_property('must-revalidate', None, bool)
   1177     proxy_revalidate = cache_property('proxy-revalidate', None, bool)
   1178     s_maxage = cache_property('s-maxage', None, None)
   1179 
   1180 
   1181 _CacheControl.cache_property = staticmethod(cache_property)
   1182 
   1183 class CallbackDict(UpdateDictMixin, dict):
   1184 
   1185     def __init__(self, initial = None, on_update = None):
   1186         dict.__init__(self, initial or ())
   1187         self.on_update = on_update
   1188 
   1189     def __repr__(self):
   1190         return '<%s %s>' % (self.__class__.__name__, dict.__repr__(self))
   1191 
   1192 
   1193 class HeaderSet(object):
   1194 
   1195     def __init__(self, headers = None, on_update = None):
   1196         self._headers = list(headers or ())
   1197         self._set = set([ x.lower() for x in self._headers ])
   1198         self.on_update = on_update
   1199 
   1200     def add(self, header):
   1201         self.update((header,))
   1202 
   1203     def remove(self, header):
   1204         key = header.lower()
   1205         if key not in self._set:
   1206             raise KeyError(header)
   1207         self._set.remove(key)
   1208         for idx, key in enumerate(self._headers):
   1209             if key.lower() == header:
   1210                 del self._headers[idx]
   1211                 break
   1212 
   1213         if self.on_update is not None:
   1214             self.on_update(self)
   1215 
   1216     def update(self, iterable):
   1217         inserted_any = False
   1218         for header in iterable:
   1219             key = header.lower()
   1220             if key not in self._set:
   1221                 self._headers.append(header)
   1222                 self._set.add(key)
   1223                 inserted_any = True
   1224 
   1225         if inserted_any and self.on_update is not None:
   1226             self.on_update(self)
   1227 
   1228     def discard(self, header):
   1229         try:
   1230             return self.remove(header)
   1231         except KeyError:
   1232             pass
   1233 
   1234     def find(self, header):
   1235         header = header.lower()
   1236         for idx, item in enumerate(self._headers):
   1237             if item.lower() == header:
   1238                 return idx
   1239 
   1240         return -1
   1241 
   1242     def index(self, header):
   1243         rv = self.find(header)
   1244         if rv < 0:
   1245             raise IndexError(header)
   1246         return rv
   1247 
   1248     def clear(self):
   1249         self._set.clear()
   1250         del self._headers[:]
   1251         if self.on_update is not None:
   1252             self.on_update(self)
   1253 
   1254     def as_set(self, preserve_casing = False):
   1255         if preserve_casing:
   1256             return set(self._headers)
   1257         return set(self._set)
   1258 
   1259     def to_header(self):
   1260         return ', '.join(map(quote_header_value, self._headers))
   1261 
   1262     def __getitem__(self, idx):
   1263         return self._headers[idx]
   1264 
   1265     def __delitem__(self, idx):
   1266         rv = self._headers.pop(idx)
   1267         self._set.remove(rv.lower())
   1268         if self.on_update is not None:
   1269             self.on_update(self)
   1270 
   1271     def __setitem__(self, idx, value):
   1272         old = self._headers[idx]
   1273         self._set.remove(old.lower())
   1274         self._headers[idx] = value
   1275         self._set.add(value.lower())
   1276         if self.on_update is not None:
   1277             self.on_update(self)
   1278 
   1279     def __contains__(self, header):
   1280         return header.lower() in self._set
   1281 
   1282     def __len__(self):
   1283         return len(self._set)
   1284 
   1285     def __iter__(self):
   1286         return iter(self._headers)
   1287 
   1288     def __nonzero__(self):
   1289         return bool(self._set)
   1290 
   1291     def __str__(self):
   1292         return self.to_header()
   1293 
   1294     def __repr__(self):
   1295         return '%s(%r)' % (self.__class__.__name__, self._headers)
   1296 
   1297 
   1298 class ETags(object):
   1299 
   1300     def __init__(self, strong_etags = None, weak_etags = None, star_tag = False):
   1301         self._strong = frozenset(not star_tag and strong_etags or ())
   1302         self._weak = frozenset(weak_etags or ())
   1303         self.star_tag = star_tag
   1304 
   1305     def as_set(self, include_weak = False):
   1306         rv = set(self._strong)
   1307         if include_weak:
   1308             rv.update(self._weak)
   1309         return rv
   1310 
   1311     def is_weak(self, etag):
   1312         return etag in self._weak
   1313 
   1314     def contains_weak(self, etag):
   1315         return self.is_weak(etag) or self.contains(etag)
   1316 
   1317     def contains(self, etag):
   1318         if self.star_tag:
   1319             return True
   1320         return etag in self._strong
   1321 
   1322     def contains_raw(self, etag):
   1323         etag, weak = unquote_etag(etag)
   1324         if weak:
   1325             return self.contains_weak(etag)
   1326         return self.contains(etag)
   1327 
   1328     def to_header(self):
   1329         if self.star_tag:
   1330             return '*'
   1331         return ', '.join([ '"%s"' % x for x in self._strong ] + [ 'w/"%s"' % x for x in self._weak ])
   1332 
   1333     def __call__(self, etag = None, data = None, include_weak = False):
   1334         if [etag, data].count(None) != 1:
   1335             raise TypeError('either tag or data required, but at least one')
   1336         if etag is None:
   1337             etag = generate_etag(data)
   1338         if include_weak:
   1339             if etag in self._weak:
   1340                 return True
   1341         return etag in self._strong
   1342 
   1343     def __nonzero__(self):
   1344         return bool(self.star_tag or self._strong)
   1345 
   1346     def __str__(self):
   1347         return self.to_header()
   1348 
   1349     def __iter__(self):
   1350         return iter(self._strong)
   1351 
   1352     def __contains__(self, etag):
   1353         return self.contains(etag)
   1354 
   1355     def __repr__(self):
   1356         return '<%s %r>' % (self.__class__.__name__, str(self))
   1357 
   1358 
   1359 class Authorization(ImmutableDictMixin, dict):
   1360 
   1361     def __init__(self, auth_type, data = None):
   1362         dict.__init__(self, data or {})
   1363         self.type = auth_type
   1364 
   1365     username = property(lambda x: x.get('username'), doc='\n        The username transmitted.  This is set for both basic and digest\n        auth all the time.')
   1366     password = property(lambda x: x.get('password'), doc='\n        When the authentication type is basic this is the password\n        transmitted by the client, else `None`.')
   1367     realm = property(lambda x: x.get('realm'), doc='\n        This is the server realm sent back for HTTP digest auth.')
   1368     nonce = property(lambda x: x.get('nonce'), doc='\n        The nonce the server sent for digest auth, sent back by the client.\n        A nonce should be unique for every 401 response for HTTP digest\n        auth.')
   1369     uri = property(lambda x: x.get('uri'), doc='\n        The URI from Request-URI of the Request-Line; duplicated because\n        proxies are allowed to change the Request-Line in transit.  HTTP\n        digest auth only.')
   1370     nc = property(lambda x: x.get('nc'), doc='\n        The nonce count value transmitted by clients if a qop-header is\n        also transmitted.  HTTP digest auth only.')
   1371     cnonce = property(lambda x: x.get('cnonce'), doc='\n        If the server sent a qop-header in the ``WWW-Authenticate``\n        header, the client has to provide this value for HTTP digest auth.\n        See the RFC for more details.')
   1372     response = property(lambda x: x.get('response'), doc='\n        A string of 32 hex digits computed as defined in RFC 2617, which\n        proves that the user knows a password.  Digest auth only.')
   1373     opaque = property(lambda x: x.get('opaque'), doc='\n        The opaque header from the server returned unchanged by the client.\n        It is recommended that this string be base64 or hexadecimal data.\n        Digest auth only.')
   1374 
   1375     @property
   1376     def qop(self):
   1377 
   1378         def on_update(header_set):
   1379             if not header_set and 'qop' in self:
   1380                 del self['qop']
   1381             elif header_set:
   1382                 self['qop'] = header_set.to_header()
   1383 
   1384         return parse_set_header(self.get('qop'), on_update)
   1385 
   1386 
   1387 class WWWAuthenticate(UpdateDictMixin, dict):
   1388     _require_quoting = frozenset(['domain',
   1389      'nonce',
   1390      'opaque',
   1391      'realm'])
   1392 
   1393     def __init__(self, auth_type = None, values = None, on_update = None):
   1394         dict.__init__(self, values or ())
   1395         if auth_type:
   1396             self['__auth_type__'] = auth_type
   1397         self.on_update = on_update
   1398 
   1399     def set_basic(self, realm = 'authentication required'):
   1400         dict.clear(self)
   1401         dict.update(self, {'__auth_type__': 'basic',
   1402          'realm': realm})
   1403         if self.on_update:
   1404             self.on_update(self)
   1405 
   1406     def set_digest(self, realm, nonce, qop = ('auth',), opaque = None, algorithm = None, stale = False):
   1407         d = {'__auth_type__': 'digest',
   1408          'realm': realm,
   1409          'nonce': nonce,
   1410          'qop': dump_header(qop)}
   1411         if stale:
   1412             d['stale'] = 'TRUE'
   1413         if opaque is not None:
   1414             d['opaque'] = opaque
   1415         if algorithm is not None:
   1416             d['algorithm'] = algorithm
   1417         dict.clear(self)
   1418         dict.update(self, d)
   1419         if self.on_update:
   1420             self.on_update(self)
   1421 
   1422     def to_header(self):
   1423         d = dict(self)
   1424         auth_type = d.pop('__auth_type__', None) or 'basic'
   1425         return '%s %s' % (auth_type.title(), ', '.join([ '%s=%s' % (key, quote_header_value(value, allow_token=key not in self._require_quoting)) for key, value in d.iteritems() ]))
   1426 
   1427     def __str__(self):
   1428         return self.to_header()
   1429 
   1430     def __repr__(self):
   1431         return '<%s %r>' % (self.__class__.__name__, self.to_header())
   1432 
   1433     def auth_property(name, doc = None):
   1434 
   1435         def _set_value(self, value):
   1436             if value is None:
   1437                 self.pop(name, None)
   1438             else:
   1439                 self[name] = str(value)
   1440 
   1441         return property(lambda x: x.get(name), _set_value, doc=doc)
   1442 
   1443     def _set_property(name, doc = None):
   1444 
   1445         def fget(self):
   1446 
   1447             def on_update(header_set):
   1448                 if not header_set and name in self:
   1449                     del self[name]
   1450                 elif header_set:
   1451                     self[name] = header_set.to_header()
   1452 
   1453             return parse_set_header(self.get(name), on_update)
   1454 
   1455         return property(fget, doc=doc)
   1456 
   1457     type = auth_property('__auth_type__', doc='\n        The type of the auth mechanism.  HTTP currently specifies\n        `Basic` and `Digest`.')
   1458     realm = auth_property('realm', doc='\n        A string to be displayed to users so they know which username and\n        password to use.  This string should contain at least the name of\n        the host performing the authentication and might additionally\n        indicate the collection of users who might have access.')
   1459     domain = _set_property('domain', doc='\n        A list of URIs that define the protection space.  If a URI is an\n        absolute path, it is relative to the canonical root URL of the\n        server being accessed.')
   1460     nonce = auth_property('nonce', doc='\n        A server-specified data string which should be uniquely generated\n        each time a 401 response is made.  It is recommended that this\n        string be base64 or hexadecimal data.')
   1461     opaque = auth_property('opaque', doc='\n        A string of data, specified by the server, which should be returned\n        by the client unchanged in the Authorization header of subsequent\n        requests with URIs in the same protection space.  It is recommended\n        that this string be base64 or hexadecimal data.')
   1462     algorithm = auth_property('algorithm', doc='\n        A string indicating a pair of algorithms used to produce the digest\n        and a checksum.  If this is not present it is assumed to be "MD5".\n        If the algorithm is not understood, the challenge should be ignored\n        (and a different one used, if there is more than one).')
   1463     qop = _set_property('qop', doc='\n        A set of quality-of-privacy directives such as auth and auth-int.')
   1464 
   1465     def _get_stale(self):
   1466         val = self.get('stale')
   1467         if val is not None:
   1468             return val.lower() == 'true'
   1469 
   1470     def _set_stale(self, value):
   1471         if value is None:
   1472             self.pop('stale', None)
   1473         else:
   1474             self['stale'] = value and 'TRUE' or 'FALSE'
   1475 
   1476     stale = property(_get_stale, _set_stale, doc='\n        A flag, indicating that the previous request from the client was\n        rejected because the nonce value was stale.')
   1477     del _get_stale
   1478     del _set_stale
   1479     auth_property = staticmethod(auth_property)
   1480     del _set_property
   1481 
   1482 
   1483 class FileStorage(object):
   1484 
   1485     def __init__(self, stream = None, filename = None, name = None, content_type = 'application/octet-stream', content_length = -1, headers = None):
   1486         self.name = name
   1487         self.stream = stream or _empty_stream
   1488         self.filename = filename or getattr(stream, 'name', None)
   1489         self.content_type = content_type
   1490         self.content_length = content_length
   1491         if headers is None:
   1492             headers = Headers()
   1493         self.headers = headers
   1494 
   1495     def save(self, dst, buffer_size = 16384):
   1496         from shutil import copyfileobj
   1497         close_dst = False
   1498         if isinstance(dst, basestring):
   1499             dst = file(dst, 'wb')
   1500             close_dst = True
   1501         try:
   1502             copyfileobj(self.stream, dst, buffer_size)
   1503         finally:
   1504             if close_dst:
   1505                 dst.close()
   1506 
   1507     def close(self):
   1508         try:
   1509             self.stream.close()
   1510         except:
   1511             pass
   1512 
   1513     def __nonzero__(self):
   1514         return bool(self.filename)
   1515 
   1516     def __getattr__(self, name):
   1517         return getattr(self.stream, name)
   1518 
   1519     def __iter__(self):
   1520         return iter(self.readline, '')
   1521 
   1522     def __repr__(self):
   1523         return '<%s: %r (%r)>' % (self.__class__.__name__, self.filename, self.content_type)
   1524 
   1525 
   1526 from werkzeug.http import dump_options_header, dump_header, generate_etag, quote_header_value, parse_set_header, unquote_etag
   1527 from werkzeug.exceptions import BadRequest
   1528 for _cls in (MultiDict,
   1529  OrderedMultiDict,
   1530  CombinedMultiDict,
   1531  Headers,
   1532  EnvironHeaders):
   1533     _cls.KeyError = BadRequest.wrap(KeyError, _cls.__name__ + '.KeyError')
   1534 
   1535 del _cls