Back to index

moin  1.9.0~rc2
datastructures.py
Go to the documentation of this file.
00001 # -*- coding: utf-8 -*-
00002 """
00003     werkzeug.datastructures
00004     ~~~~~~~~~~~~~~~~~~~~~~~
00005 
00006     This module provides mixins and classes with an immutable interface.
00007 
00008     :copyright: (c) 2009 by the Werkzeug Team, see AUTHORS for more details.
00009     :license: BSD, see LICENSE for more details.
00010 """
00011 import re
00012 import codecs
00013 import mimetypes
00014 from werkzeug._internal import _proxy_repr, _missing
00015 
00016 
00017 _locale_delim_re = re.compile(r'[_-]')
00018 
00019 
00020 def is_immutable(self):
00021     raise TypeError('%r objects are immutable' % self.__class__.__name__)
00022 
00023 
00024 class ImmutableListMixin(object):
00025     """Makes a :class:`list` immutable.
00026 
00027     .. versionadded:: 0.5
00028 
00029     :private:
00030     """
00031 
00032     def __delitem__(self, key):
00033         is_immutable(self)
00034 
00035     def __delslice__(self, i, j):
00036         is_immutable(self)
00037 
00038     def __iadd__(self, other):
00039         is_immutable(self)
00040     __imul__ = __iadd__
00041 
00042     def __setitem__(self, key, value):
00043         is_immutable(self)
00044 
00045     def __setslice__(self, i, j, value):
00046         is_immutable(self)
00047 
00048     def append(self, item):
00049         is_immutable(self)
00050     remove = append
00051 
00052     def extend(self, iterable):
00053         is_immutable(self)
00054 
00055     def insert(self, pos, value):
00056         is_immutable(self)
00057 
00058     def pop(self, index=-1):
00059         is_immutable(self)
00060 
00061     def reverse(self):
00062         is_immutable(self)
00063 
00064     def sort(self, cmp=None, key=None, reverse=None):
00065         is_immutable(self)
00066 
00067 
00068 class ImmutableList(ImmutableListMixin, list):
00069     """An immutable :class:`list`.
00070 
00071     .. versionadded:: 0.5
00072 
00073     :private:
00074     """
00075 
00076     __repr__ = _proxy_repr(list)
00077 
00078 
00079 class ImmutableDictMixin(object):
00080     """Makes a :class:`dict` immutable.
00081 
00082     .. versionadded:: 0.5
00083 
00084     :private:
00085     """
00086 
00087     def setdefault(self, key, default=None):
00088         is_immutable(self)
00089 
00090     def update(self, *args, **kwargs):
00091         is_immutable(self)
00092 
00093     def pop(self, key, default=None):
00094         is_immutable(self)
00095 
00096     def popitem(self):
00097         is_immutable(self)
00098 
00099     def __setitem__(self, key, value):
00100         is_immutable(self)
00101 
00102     def __delitem__(self, key):
00103         is_immutable(self)
00104 
00105     def clear(self):
00106         is_immutable(self)
00107 
00108 
00109 class ImmutableMultiDictMixin(ImmutableDictMixin):
00110     """Makes a :class:`MultiDict` immutable.
00111 
00112     .. versionadded:: 0.5
00113 
00114     :private:
00115     """
00116 
00117     def popitemlist(self):
00118         is_immutable(self)
00119 
00120     def poplist(self, key):
00121         is_immutable(self)
00122 
00123     def setlist(self, key, new_list):
00124         is_immutable(self)
00125 
00126     def setlistdefault(self, key, default_list=None):
00127         is_immutable(self)
00128 
00129 
00130 class UpdateDictMixin(object):
00131     """Makes dicts call `self.on_update` on modifications."""
00132 
00133     on_update = None
00134 
00135     def calls_update(name):
00136         def oncall(self, *args, **kw):
00137             rv = getattr(super(UpdateDictMixin, self), name)(*args, **kw)
00138             if self.on_update is not None:
00139                 self.on_update(self)
00140             return rv
00141         oncall.__name__ = name
00142         return oncall
00143 
00144     __setitem__ = calls_update('__setitem__')
00145     __delitem__ = calls_update('__delitem__')
00146     clear = calls_update('clear')
00147     pop = calls_update('pop')
00148     popitem = calls_update('popitem')
00149     setdefault = calls_update('setdefault')
00150     update = calls_update('update')
00151     del calls_update
00152 
00153 
00154 class TypeConversionDict(dict):
00155     """Works like a regular dict but the :meth:`get` method can perform
00156     type conversions.  :class:`MultiDict` and :class:`CombinedMultiDict`
00157     are subclasses of this class and provide the same feature.
00158 
00159     .. versionadded:: 0.5
00160     """
00161 
00162     def get(self, key, default=None, type=None):
00163         """Return the default value if the requested data doesn't exist.
00164         If `type` is provided and is a callable it should convert the value,
00165         return it or raise a :exc:`ValueError` if that is not possible.  In
00166         this case the function will return the default as if the value was not
00167         found:
00168 
00169         >>> d = TypeConversionDict(foo='42', bar='blub')
00170         >>> d.get('foo', type=int)
00171         42
00172         >>> d.get('bar', -1, type=int)
00173         -1
00174 
00175         :param key: The key to be looked up.
00176         :param default: The default value to be returned if the key can't
00177                         be looked up.  If not further specified `None` is
00178                         returned.
00179         :param type: A callable that is used to cast the value in the
00180                      :class:`MultiDict`.  If a :exc:`ValueError` is raised
00181                      by this callable the default value is returned.
00182         """
00183         try:
00184             rv = self[key]
00185             if type is not None:
00186                 rv = type(rv)
00187         except (KeyError, ValueError):
00188             rv = default
00189         return rv
00190 
00191 
00192 class ImmutableTypeConversionDict(ImmutableDictMixin, TypeConversionDict):
00193     """Works like a :class:`TypeConversionDict` but does not support
00194     modifications.
00195 
00196     .. versionadded:: 0.5
00197     """
00198 
00199     def copy(self):
00200         """Return a shallow mutable copy of this object.  Keep in mind that
00201         the standard library's :func:`copy` funciton is a no-op for this class
00202         like for any other python immutable type (eg: :class:`tuple`).
00203         """
00204         return TypeConversionDict(self)
00205 
00206     def __copy__(self):
00207         return self
00208 
00209 
00210 class MultiDict(TypeConversionDict):
00211     """A :class:`MultiDict` is a dictionary subclass customized to deal with
00212     multiple values for the same key which is for example used by the parsing
00213     functions in the wrappers.  This is necessary because some HTML form
00214     elements pass multiple values for the same key.
00215 
00216     :class:`MultiDict` implements all standard dictionary methods.
00217     Internally, it saves all values for a key as a list, but the standard dict
00218     access methods will only return the first value for a key. If you want to
00219     gain access to the other values, too, you have to use the `list` methods as
00220     explained below.
00221 
00222     Basic Usage:
00223 
00224     >>> d = MultiDict([('a', 'b'), ('a', 'c')])
00225     >>> d
00226     MultiDict([('a', 'b'), ('a', 'c')])
00227     >>> d['a']
00228     'b'
00229     >>> d.getlist('a')
00230     ['b', 'c']
00231     >>> 'a' in d
00232     True
00233 
00234     It behaves like a normal dict thus all dict functions will only return the
00235     first value when multiple values for one key are found.
00236 
00237     From Werkzeug 0.3 onwards, the `KeyError` raised by this class is also a
00238     subclass of the :exc:`~exceptions.BadRequest` HTTP exception and will
00239     render a page for a ``400 BAD REQUEST`` if catched in a catch-all for HTTP
00240     exceptions.
00241 
00242     A :class:`MultiDict` can be constructed from an iterable of
00243     ``(key, value)`` tuples, a dict, a :class:`MultiDict` or from Werkzeug 0.2
00244     onwards some keyword parameters.
00245 
00246     :param mapping: the initial value for the :class:`MultiDict`.  Either a
00247                     regular dict, an iterable of ``(key, value)`` tuples
00248                     or `None`.
00249     """
00250 
00251     # the key error this class raises.  Because of circular dependencies
00252     # with the http exception module this class is created at the end of
00253     # this module.
00254     KeyError = None
00255 
00256     def __init__(self, mapping=None):
00257         if isinstance(mapping, MultiDict):
00258             dict.__init__(self, ((k, l[:]) for k, l in mapping.iterlists()))
00259         elif isinstance(mapping, dict):
00260             tmp = {}
00261             for key, value in mapping.iteritems():
00262                 if isinstance(value, (tuple, list)):
00263                     value = list(value)
00264                 else:
00265                     value = [value]
00266                 tmp[key] = value
00267             dict.__init__(self, tmp)
00268         else:
00269             tmp = {}
00270             for key, value in mapping or ():
00271                 tmp.setdefault(key, []).append(value)
00272             dict.__init__(self, tmp)
00273 
00274     def __getitem__(self, key):
00275         """Return the first data value for this key;
00276         raises KeyError if not found.
00277 
00278         :param key: The key to be looked up.
00279         :raise KeyError: if the key does not exist.
00280         """
00281         if key in self:
00282             return dict.__getitem__(self, key)[0]
00283         raise self.KeyError(key)
00284 
00285     def __setitem__(self, key, value):
00286         """Set an item as list."""
00287         dict.__setitem__(self, key, [value])
00288 
00289     def getlist(self, key, type=None):
00290         """Return the list of items for a given key. If that key is not in the
00291         `MultiDict`, the return value will be an empty list.  Just as `get`
00292         `getlist` accepts a `type` parameter.  All items will be converted
00293         with the callable defined there.
00294 
00295         :param key: The key to be looked up.
00296         :param type: A callable that is used to cast the value in the
00297                      :class:`MultiDict`.  If a :exc:`ValueError` is raised
00298                      by this callable the value will be removed from the list.
00299         :return: a :class:`list` of all the values for the key.
00300         """
00301         try:
00302             rv = dict.__getitem__(self, key)
00303         except KeyError:
00304             return []
00305         if type is None:
00306             return list(rv)
00307         result = []
00308         for item in rv:
00309             try:
00310                 result.append(type(item))
00311             except ValueError:
00312                 pass
00313         return result
00314 
00315     def setlist(self, key, new_list):
00316         """Remove the old values for a key and add new ones.  Note that the list
00317         you pass the values in will be shallow-copied before it is inserted in
00318         the dictionary.
00319 
00320         >>> d = MultiDict()
00321         >>> d.setlist('foo', ['1', '2'])
00322         >>> d['foo']
00323         '1'
00324         >>> d.getlist('foo')
00325         ['1', '2']
00326 
00327         :param key: The key for which the values are set.
00328         :param new_list: An iterable with the new values for the key.  Old values
00329                          are removed first.
00330         """
00331         dict.__setitem__(self, key, list(new_list))
00332 
00333     def setdefault(self, key, default=None):
00334         """Returns the value for the key if it is in the dict, otherwise it
00335         returns `default` and sets that value for `key`.
00336 
00337         :param key: The key to be looked up.
00338         :param default: The default value to be returned if the key is not
00339                         in the dict.  If not further specified it's `None`.
00340         """
00341         if key not in self:
00342             self[key] = default
00343         else:
00344             default = self[key]
00345         return default
00346 
00347     def setlistdefault(self, key, default_list=None):
00348         """Like `setdefault` but sets multiple values.  The list returned
00349         is not a copy, but the list that is actually used internally.  This
00350         means that you can put new values into the dict by appending items
00351         to the list:
00352 
00353         >>> d = MultiDict({"foo": 1})
00354         >>> d.setlistdefault("foo").extend([2, 3])
00355         >>> d.getlist("foo")
00356         [1, 2, 3]
00357 
00358         :param key: The key to be looked up.
00359         :param default: An iterable of default values.  It is either copied
00360                         (in case it was a list) or converted into a list
00361                         before returned.
00362         :return: a :class:`list`
00363         """
00364         if key not in self:
00365             default_list = list(default_list or ())
00366             dict.__setitem__(self, key, default_list)
00367         else:
00368             default_list = dict.__getitem__(self, key)
00369         return default_list
00370 
00371     def items(self, multi=False):
00372         """Return a list of ``(key, value)`` pairs.
00373 
00374         :param multi: If set to `True` the list returned will have a
00375                       pair for each value of each key.  Ohterwise it
00376                       will only contain pairs for the first value of
00377                       each key.
00378 
00379         :return: a :class:`list`
00380         """
00381         return list(self.iteritems(multi))
00382 
00383     #: Return a list of ``(key, value)`` pairs, where values is the list of
00384     #: all values associated with the key.
00385     #:
00386     #: :return: a :class:`list`
00387     lists = dict.items
00388 
00389     def values(self):
00390         """Returns a list of the first value on every key's value list.
00391 
00392         :return: a :class:`list`.
00393         """
00394         return [self[key] for key in self.iterkeys()]
00395 
00396     def listvalues(self):
00397         """Return a list of all values associated with a key.  Zipping
00398         :meth:`keys` and this is the same as calling :meth:`lists`:
00399 
00400         >>> d = MultiDict({"foo": [1, 2, 3]})
00401         >>> zip(d.keys(), d.listvalues()) == d.lists()
00402         True
00403 
00404         :return: a :class:`list`
00405         """
00406         return list(self.iterlistvalues())
00407 
00408     def iteritems(self, multi=False):
00409         """Like :meth:`items` but returns an iterator."""
00410         for key, values in dict.iteritems(self):
00411             if multi:
00412                 for value in values:
00413                     yield key, value
00414             else:
00415                 yield key, values[0]
00416 
00417     def iterlists(self):
00418         """Return a list of all values associated with a key.
00419 
00420         :return: a class:`list`
00421         """
00422         for key, values in dict.iteritems(self):
00423             yield key, list(values)
00424 
00425     def itervalues(self):
00426         """Like :meth:`values` but returns an iterator."""
00427         for values in dict.itervalues(self):
00428             yield values[0]
00429 
00430     def iterlistvalues(self):
00431         """like :meth:`listvalues` but returns an iterator."""
00432         for values in dict.itervalues(self):
00433             yield list(values)
00434 
00435     def copy(self):
00436         """Return a shallow copy of this object."""
00437         return self.__class__(self)
00438 
00439     def to_dict(self, flat=True):
00440         """Return the contents as regular dict.  If `flat` is `True` the
00441         returned dict will only have the first item present, if `flat` is
00442         `False` all values will be returned as lists.
00443 
00444         :param flat: If set to `False` the dict returned will have lists
00445                      with all the values in it.  Otherwise it will only
00446                      contain the first value for each key.
00447         :return: a :class:`dict`
00448         """
00449         if flat:
00450             return dict(self.iteritems())
00451         return dict(self)
00452 
00453     def update(self, other_dict):
00454         """update() extends rather than replaces existing key lists."""
00455         if isinstance(other_dict, MultiDict):
00456             for key, value_list in other_dict.iterlists():
00457                 self.setlistdefault(key, []).extend(value_list)
00458         elif isinstance(other_dict, dict):
00459             for key, value in other_dict.items():
00460                 self.setlistdefault(key, []).append(value)
00461         else:
00462             for key, value in other_dict:
00463                 self.setlistdefault(key, []).append(value)
00464 
00465     def pop(self, key, default=_missing):
00466         """Pop the first item for a list on the dict.  Afterwards the
00467         key is removed from the dict, so additional values are discarded:
00468 
00469         >>> d = MultiDict({"foo": [1, 2, 3]})
00470         >>> d.pop("foo")
00471         1
00472         >>> "foo" in d
00473         False
00474 
00475         :param key: the key to pop.
00476         :param default: if provided the value to return if the key was
00477                         not in the dictionary.
00478         """
00479         if default is not _missing:
00480             return dict.pop(self, key, default)
00481         try:
00482             return dict.pop(self, key)[0]
00483         except KeyError, e:
00484             raise self.KeyError(str(e))
00485 
00486     def popitem(self):
00487         """Pop an item from the dict."""
00488         try:
00489             item = dict.popitem(self)
00490             return (item[0], item[1][0])
00491         except KeyError, e:
00492             raise self.KeyError(str(e))
00493 
00494     def poplist(self, key):
00495         """Pop the list for a key from the dict.  If the key is not in the dict
00496         an empty list is returned.
00497 
00498         .. versionchanged:: 0.5
00499            If the key does no longer exist a list is returned instead of
00500            raising an error.
00501         """
00502         return dict.pop(self, key, [])
00503 
00504     def popitemlist(self):
00505         """Pop a ``(key, list)`` tuple from the dict."""
00506         try:
00507             return dict.popitem(self)
00508         except KeyError, e:
00509             raise self.KeyError(str(e))
00510 
00511     def __repr__(self):
00512         return '%s(%r)' % (self.__class__.__name__, self.items(multi=True))
00513 
00514 
00515 class Headers(object):
00516     """An object that stores some headers.  It has a dict-like interface
00517     but is ordered and can store the same keys multiple times.
00518 
00519     This data structure is useful if you want a nicer way to handle WSGI
00520     headers which are stored as tuples in a list.
00521 
00522     From Werkzeug 0.3 onwards, the :exc:`KeyError` raised by this class is
00523     also a subclass of the :class:`~exceptions.BadRequest` HTTP exception
00524     and will render a page for a ``400 BAD REQUEST`` if catched in a
00525     catch-all for HTTP exceptions.
00526 
00527     Headers is mostly compatible with the Python :class:`wsgiref.headers.Headers`
00528     class, with the exception of `__getitem__`.  :mod:`wsgiref` will return
00529     `None` for ``headers['missing']``, whereas :class:`Headers` will raise
00530     a :class:`KeyError`.
00531 
00532     To create a new :class:`Headers` object pass it a list or dict of headers
00533     which are used as default values.  This does not reuse the list passed
00534     to the constructor for internal usage.  To create a :class:`Headers`
00535     object that uses as internal storage the list or list-like object you
00536     can use the :meth:`linked` class method.
00537 
00538     :param defaults: The list of default values for the :class:`Headers`.
00539     """
00540 
00541     # the key error this class raises.  Because of circular dependencies
00542     # with the http exception module this class is created at the end of
00543     # this module.
00544     KeyError = None
00545 
00546     def __init__(self, defaults=None, _list=None):
00547         if _list is None:
00548             _list = []
00549         self._list = _list
00550         if defaults is not None:
00551             self.extend(defaults)
00552 
00553     @classmethod
00554     def linked(cls, headerlist):
00555         """Create a new :class:`Headers` object that uses the list of headers
00556         passed as internal storage:
00557 
00558         >>> headerlist = [('Content-Length', '40')]
00559         >>> headers = Headers.linked(headerlist)
00560         >>> headers.add('Content-Type', 'text/html')
00561         >>> headerlist
00562         [('Content-Length', '40'), ('Content-Type', 'text/html')]
00563 
00564         :param headerlist: The list of headers the class is linked to.
00565         :return: new linked :class:`Headers` object.
00566         """
00567         return cls(_list=headerlist)
00568 
00569     def __getitem__(self, key, _index_operation=True):
00570         if _index_operation:
00571             if isinstance(key, (int, long)):
00572                 return self._list[key]
00573             elif isinstance(key, slice):
00574                 return self.__class__(self._list[key])
00575         ikey = key.lower()
00576         for k, v in self._list:
00577             if k.lower() == ikey:
00578                 return v
00579         raise self.KeyError(key)
00580 
00581     def __eq__(self, other):
00582         return other.__class__ is self.__class__ and \
00583                set(other._list) == set(self._list)
00584 
00585     def __ne__(self, other):
00586         return not self.__eq__(other)
00587 
00588     def get(self, key, default=None, type=None):
00589         """Return the default value if the requested data doesn't exist.
00590         If `type` is provided and is a callable it should convert the value,
00591         return it or raise a :exc:`ValueError` if that is not possible.  In
00592         this case the function will return the default as if the value was not
00593         found:
00594 
00595         >>> d = Headers([('Content-Length', '42')])
00596         >>> d.get('Content-Length', type=int)
00597         42
00598 
00599         If a headers object is bound you must not add unicode strings
00600         because no encoding takes place.
00601 
00602         :param key: The key to be looked up.
00603         :param default: The default value to be returned if the key can't
00604                         be looked up.  If not further specified `None` is
00605                         returned.
00606         :param type: A callable that is used to cast the value in the
00607                      :class:`Headers`.  If a :exc:`ValueError` is raised
00608                      by this callable the default value is returned.
00609         """
00610         try:
00611             rv = self.__getitem__(key, _index_operation=False)
00612         except KeyError:
00613             return default
00614         if type is None:
00615             return rv
00616         try:
00617             return type(rv)
00618         except ValueError:
00619             return default
00620 
00621     def getlist(self, key, type=None):
00622         """Return the list of items for a given key. If that key is not in the
00623         :class:`Headers`, the return value will be an empty list.  Just as
00624         :meth:`get` :meth:`getlist` accepts a `type` parameter.  All items will
00625         be converted with the callable defined there.
00626 
00627         :param key: The key to be looked up.
00628         :param type: A callable that is used to cast the value in the
00629                      :class:`Headers`.  If a :exc:`ValueError` is raised
00630                      by this callable the value will be removed from the list.
00631         :return: a :class:`list` of all the values for the key.
00632         """
00633         ikey = key.lower()
00634         result = []
00635         for k, v in self:
00636             if k.lower() == ikey:
00637                 if type is not None:
00638                     try:
00639                         v = type(v)
00640                     except ValueError:
00641                         continue
00642                 result.append(v)
00643         return result
00644 
00645     def get_all(self, name):
00646         """Return a list of all the values for the named field.
00647 
00648         This method is compatible with the :mod:`wsgiref`
00649         :meth:`~wsgiref.headers.Headers.get_all` method.
00650         """
00651         return self.getlist(name)
00652 
00653     def iteritems(self, lower=False):
00654         for key, value in self:
00655             if lower:
00656                 key = key.lower()
00657             yield key, value
00658 
00659     def iterkeys(self, lower=False):
00660         for key, _ in self.iteritems(lower):
00661             yield key
00662 
00663     def itervalues(self):
00664         for _, value in self.iteritems():
00665             yield value
00666 
00667     def keys(self, lower=False):
00668         return list(self.iterkeys(lower))
00669 
00670     def values(self):
00671         return list(self.itervalues())
00672 
00673     def items(self, lower=False):
00674         return list(self.iteritems(lower))
00675 
00676     def extend(self, iterable):
00677         """Extend the headers with a dict or an iterable yielding keys and
00678         values.
00679         """
00680         if isinstance(iterable, dict):
00681             for key, value in iterable.iteritems():
00682                 if isinstance(value, (tuple, list)):
00683                     for v in value:
00684                         self.add(key, v)
00685                 else:
00686                     self.add(key, value)
00687         else:
00688             for key, value in iterable:
00689                 self.add(key, value)
00690 
00691     def __delitem__(self, key, _index_operation=True):
00692         if _index_operation and isinstance(key, (int, long, slice)):
00693             del self._list[key]
00694             return
00695         key = key.lower()
00696         new = []
00697         for k, v in self._list:
00698             if k.lower() != key:
00699                 new.append((k, v))
00700         self._list[:] = new
00701 
00702     def remove(self, key):
00703         """Remove a key.
00704 
00705         :param key: The key to be removed.
00706         """
00707         return self.__delitem__(key, _index_operation=False)
00708 
00709     def pop(self, key=None, default=_missing):
00710         """Removes and returns a key or index.
00711 
00712         :param key: The key to be popped.  If this is an integer the item at
00713                     that position is removed, if it's a string the value for
00714                     that key is.  If the key is omitted or `None` the last
00715                     item is removed.
00716         :return: an item.
00717         """
00718         if key is None:
00719             return self._list.pop()
00720         if isinstance(key, (int, long)):
00721             return self._list.pop(key)
00722         try:
00723             rv = self[key]
00724             self.remove(key)
00725         except KeyError:
00726             if default is not _missing:
00727                 return default
00728             raise
00729         return rv
00730 
00731     def popitem(self):
00732         """Removes a key or index and returns a (key, value) item."""
00733         return self.pop()
00734 
00735     def __contains__(self, key):
00736         """Check if a key is present."""
00737         try:
00738             self.__getitem__(key, _index_operation=False)
00739         except KeyError:
00740             return False
00741         return True
00742 
00743     has_key = __contains__
00744 
00745     def __iter__(self):
00746         """Yield ``(key, value)`` tuples."""
00747         return iter(self._list)
00748 
00749     def __len__(self):
00750         return len(self._list)
00751 
00752     def add(self, _key, _value, **kw):
00753         """Add a new header tuple to the list.
00754 
00755         Keyword arguments can specify additional parameters for the header
00756         value, with underscores converted to dashes::
00757 
00758         >>> d = Headers()
00759         >>> d.add('Content-Type', 'text/plain')
00760         >>> d.add('Content-Disposition', 'attachment', filename='foo.png')
00761 
00762         The keyword argument dumping uses :func:`dump_options_header`
00763         behind the scenes.
00764 
00765         .. versionadded:: 0.4.1
00766             keyword arguments were added for :mod:`wsgiref` compatibility.
00767         """
00768         if kw:
00769             _value = dump_options_header(_value, dict((k.replace('_', '-'), v)
00770                                                       for k, v in kw.items()))
00771         self._list.append((_key, _value))
00772 
00773     def add_header(self, _key, _value, **_kw):
00774         """Add a new header tuple to the list.
00775 
00776         An alias for :meth:`add` for compatibility with the :mod:`wsgiref`
00777         :meth:`~wsgiref.headers.Headers.add_header` method.
00778         """
00779         self.add(_key, _value, **_kw)
00780 
00781     def clear(self):
00782         """Clears all headers."""
00783         del self._list[:]
00784 
00785     def set(self, key, value):
00786         """Remove all header tuples for `key` and add a new one.  The newly
00787         added key either appears at the end of the list if there was no
00788         entry or replaces the first one.
00789 
00790         :param key: The key to be inserted.
00791         :param value: The value to be inserted.
00792         """
00793         lc_key = key.lower()
00794         for idx, (old_key, old_value) in enumerate(self._list):
00795             if old_key.lower() == lc_key:
00796                 # replace first ocurrence
00797                 self._list[idx] = (key, value)
00798                 break
00799         else:
00800             return self.add(key, value)
00801         self._list[idx + 1:] = [(k, v) for k, v in self._list[idx + 1:]
00802                                 if k.lower() != lc_key]
00803 
00804     def setdefault(self, key, value):
00805         """Returns the value for the key if it is in the dict, otherwise it
00806         returns `default` and sets that value for `key`.
00807 
00808         :param key: The key to be looked up.
00809         :param default: The default value to be returned if the key is not
00810                         in the dict.  If not further specified it's `None`.
00811         """
00812         if key in self:
00813             return self[key]
00814         self.set(key, value)
00815         return value
00816 
00817     def __setitem__(self, key, value):
00818         """Like :meth:`set` but also supports index/slice based setting."""
00819         if isinstance(key, (slice, int, long)):
00820             self._list[key] = value
00821         else:
00822             self.set(key, value)
00823 
00824     def to_list(self, charset='utf-8'):
00825         """Convert the headers into a list and converts the unicode header
00826         items to the specified charset.
00827 
00828         :return: list
00829         """
00830         result = []
00831         for k, v in self:
00832             if isinstance(v, unicode):
00833                 v = v.encode(charset)
00834             else:
00835                 v = str(v)
00836             result.append((k, v))
00837         return result
00838 
00839     def copy(self):
00840         return self.__class__(self._list)
00841 
00842     def __copy__(self):
00843         return self.copy()
00844 
00845     def __str__(self, charset='utf-8'):
00846         """Returns formatted headers suitable for HTTP transmission."""
00847         strs = []
00848         for key, value in self.to_list(charset):
00849             strs.append('%s: %s' % (key, value))
00850         strs.append('\r\n')
00851         return '\r\n'.join(strs)
00852 
00853     def __repr__(self):
00854         return '%s(%r)' % (
00855             self.__class__.__name__,
00856             list(self)
00857         )
00858 
00859 
00860 class ImmutableHeadersMixin(object):
00861     """Makes a :class:`Headers` immutable.
00862 
00863     .. versionadded:: 0.5
00864     """
00865 
00866     def __delitem__(self, key):
00867         is_immutable(self)
00868 
00869     def __setitem__(self, key, value):
00870         is_immutable(self)
00871     set = __setitem__
00872 
00873     def add(self, item):
00874         is_immutable(self)
00875     remove = add_header = add
00876 
00877     def extend(self, iterable):
00878         is_immutable(self)
00879 
00880     def insert(self, pos, value):
00881         is_immutable(self)
00882 
00883     def pop(self, index=-1):
00884         is_immutable(self)
00885 
00886     def popitem(self):
00887         is_immutable(self)
00888 
00889     def setdefault(self, key, default):
00890         is_immutable(self)
00891 
00892 
00893 class EnvironHeaders(ImmutableHeadersMixin, Headers):
00894     """Read only version of the headers from a WSGI environment.  This
00895     provides the same interface as `Headers` and is constructed from
00896     a WSGI environment.
00897 
00898     From Werkzeug 0.3 onwards, the `KeyError` raised by this class is also a
00899     subclass of the :exc:`~exceptions.BadRequest` HTTP exception and will
00900     render a page for a ``400 BAD REQUEST`` if catched in a catch-all for
00901     HTTP exceptions.
00902     """
00903 
00904     def __init__(self, environ):
00905         self.environ = environ
00906 
00907     @classmethod
00908     def linked(cls, environ):
00909         raise TypeError('%r object is always linked to environment, '
00910                         'no separate initializer' % cls.__name__)
00911 
00912     def __eq__(self, other):
00913         return self is other
00914 
00915     def __getitem__(self, key, _index_operation=False):
00916         # _index_operation is a no-op for this class as there is no index but
00917         # used because get() calls it.
00918         key = key.upper().replace('-', '_')
00919         if key in ('CONTENT_TYPE', 'CONTENT_LENGTH'):
00920             return self.environ[key]
00921         return self.environ['HTTP_' + key]
00922 
00923     def __iter__(self):
00924         for key, value in self.environ.iteritems():
00925             if key.startswith('HTTP_'):
00926                 yield key[5:].replace('_', '-').title(), value
00927             elif key in ('CONTENT_TYPE', 'CONTENT_LENGTH'):
00928                 yield key.replace('_', '-').title(), value
00929 
00930     def copy(self):
00931         raise TypeError('cannot create %r copies' % self.__class__.__name__)
00932 
00933 
00934 class CombinedMultiDict(ImmutableMultiDictMixin, MultiDict):
00935     """A read only :class:`MultiDict` that you can pass multiple :class:`MultiDict`
00936     instances as sequence and it will combine the return values of all wrapped
00937     dicts:
00938 
00939     >>> from werkzeug import MultiDict, CombinedMultiDict
00940     >>> post = MultiDict([('foo', 'bar')])
00941     >>> get = MultiDict([('blub', 'blah')])
00942     >>> combined = CombinedMultiDict([get, post])
00943     >>> combined['foo']
00944     'bar'
00945     >>> combined['blub']
00946     'blah'
00947 
00948     This works for all read operations and will raise a `TypeError` for
00949     methods that usually change data which isn't possible.
00950 
00951     From Werkzeug 0.3 onwards, the `KeyError` raised by this class is also a
00952     subclass of the :exc:`~exceptions.BadRequest` HTTP exception and will
00953     render a page for a ``400 BAD REQUEST`` if catched in a catch-all for HTTP
00954     exceptions.
00955     """
00956 
00957     def __init__(self, dicts=None):
00958         self.dicts = dicts or []
00959 
00960     @classmethod
00961     def fromkeys(cls):
00962         raise TypeError('cannot create %r instances by fromkeys' %
00963                         cls.__name__)
00964 
00965     def __getitem__(self, key):
00966         for d in self.dicts:
00967             if key in d:
00968                 return d[key]
00969         raise self.KeyError(key)
00970 
00971     def get(self, key, default=None, type=None):
00972         for d in self.dicts:
00973             if key in d:
00974                 if type is not None:
00975                     try:
00976                         return type(d[key])
00977                     except ValueError:
00978                         continue
00979                 return d[key]
00980         return default
00981 
00982     def getlist(self, key, type=None):
00983         rv = []
00984         for d in self.dicts:
00985             rv.extend(d.getlist(key, type))
00986         return rv
00987 
00988     def keys(self):
00989         rv = set()
00990         for d in self.dicts:
00991             rv.update(d.keys())
00992         return list(rv)
00993 
00994     def iteritems(self, multi=False):
00995         found = set()
00996         for d in self.dicts:
00997             for key, value in d.iteritems(multi):
00998                 if multi:
00999                     yield key, value
01000                 elif key not in found:
01001                     found.add(key)
01002                     yield key, value
01003 
01004     def itervalues(self):
01005         for key, value in self.iteritems():
01006             yield value
01007 
01008     def values(self):
01009         return list(self.itervalues())
01010 
01011     def items(self, multi=False):
01012         return list(self.iteritems(multi))
01013 
01014     def iterlists(self):
01015         rv = {}
01016         for d in self.dicts:
01017             for key, values in d.iterlists():
01018                 rv.setdefault(key, []).extend(values)
01019         return rv.iteritems()
01020 
01021     def lists(self):
01022         return list(self.iterlists())
01023 
01024     def iterlistvalues(self):
01025         return (x[0] for x in self.lists())
01026 
01027     def listvalues(self):
01028         return list(self.iterlistvalues())
01029 
01030     def iterkeys(self):
01031         return iter(self.keys())
01032 
01033     __iter__ = iterkeys
01034 
01035     def copy(self):
01036         """Return a shallow copy of this object."""
01037         return self.__class__(self.dicts[:])
01038 
01039     def to_dict(self, flat=True):
01040         """Return the contents as regular dict.  If `flat` is `True` the
01041         returned dict will only have the first item present, if `flat` is
01042         `False` all values will be returned as lists.
01043 
01044         :param flat: If set to `False` the dict returned will have lists
01045                      with all the values in it.  Otherwise it will only
01046                      contain the first item for each key.
01047         :return: a :class:`dict`
01048         """
01049         rv = {}
01050         for d in reversed(self.dicts):
01051             rv.update(d.to_dict(flat))
01052         return rv
01053 
01054     def __len__(self):
01055         return len(self.keys())
01056 
01057     def __contains__(self, key):
01058         for d in self.dicts:
01059             if key in d:
01060                 return True
01061         return False
01062 
01063     has_key = __contains__
01064 
01065     def __repr__(self):
01066         return '%s(%r)' % (self.__class__.__name__, self.dicts)
01067 
01068 
01069 class FileMultiDict(MultiDict):
01070     """A special :class:`MultiDict` that has convenience methods to add
01071     files to it.  This is used for :class:`EnvironBuilder` and generally
01072     useful for unittesting.
01073 
01074     .. versionadded:: 0.5
01075     """
01076 
01077     def add_file(self, name, file, filename=None, content_type=None):
01078         """Adds a new file to the dict.  `file` can be a file name or
01079         a :class:`file`-like or a :class:`FileStorage` object.
01080 
01081         :param name: the name of the field.
01082         :param file: a filename or :class:`file`-like object
01083         :param filename: an optional filename
01084         :param content_type: an optional content type
01085         """
01086         from werkzeug.utils import FileStorage
01087         if isinstance(file, FileStorage):
01088             self[name] = file
01089             return
01090         if isinstance(file, basestring):
01091             if filename is None:
01092                 filename = file
01093             file = open(file, 'rb')
01094         if filename and content_type is None:
01095             content_type = mimetypes.guess_type(filename)[0] or \
01096                            'application/octet-stream'
01097         self[name] = FileStorage(file, filename, name, content_type)
01098 
01099 
01100 class ImmutableDict(ImmutableDictMixin, dict):
01101     """An immutable :class:`dict`.
01102 
01103     .. versionadded:: 0.5
01104     """
01105 
01106     __repr__ = _proxy_repr(dict)
01107 
01108     def copy(self):
01109         """Return a shallow mutable copy of this object.  Keep in mind that
01110         the standard library's :func:`copy` funciton is a no-op for this class
01111         like for any other python immutable type (eg: :class:`tuple`).
01112         """
01113         return dict(self)
01114 
01115     def __copy__(self):
01116         return self
01117 
01118 
01119 class ImmutableMultiDict(ImmutableMultiDictMixin, MultiDict):
01120     """An immutable :class:`MultiDict`.
01121 
01122     .. versionadded:: 0.5
01123     """
01124 
01125     def copy(self):
01126         """Return a shallow mutable copy of this object.  Keep in mind that
01127         the standard library's :func:`copy` funciton is a no-op for this class
01128         like for any other python immutable type (eg: :class:`tuple`).
01129         """
01130         return MultiDict(self)
01131 
01132     def __copy__(self):
01133         return self
01134 
01135 
01136 class Accept(ImmutableList):
01137     """An :class:`Accept` object is just a list subclass for lists of
01138     ``(value, quality)`` tuples.  It is automatically sorted by quality.
01139 
01140     All :class:`Accept` objects work similar to a list but provide extra
01141     functionality for working with the data.  Containment checks are
01142     normalized to the rules of that header:
01143 
01144     >>> a = CharsetAccept([('ISO-8859-1', 1), ('utf-8', 0.7)])
01145     >>> a.best
01146     'ISO-8859-1'
01147     >>> 'iso-8859-1' in a
01148     True
01149     >>> 'UTF8' in a
01150     True
01151     >>> 'utf7' in a
01152     False
01153 
01154     To get the quality for an item you can use normal item lookup:
01155 
01156     >>> print a['utf-8']
01157     0.7
01158     >>> a['utf7']
01159     0
01160 
01161     .. versionchanged:: 0.5
01162        :class:`Accept` objects are forzed immutable now.
01163     """
01164 
01165     def __init__(self, values=()):
01166         if values is None:
01167             list.__init__(self)
01168             self.provided = False
01169         elif isinstance(values, Accept):
01170             self.provided = values.provided
01171             list.__init__(self, values)
01172         else:
01173             self.provided = True
01174             values = [(a, b) for b, a in values]
01175             values.sort()
01176             values.reverse()
01177             list.__init__(self, [(a, b) for b, a in values])
01178 
01179     def _value_matches(self, value, item):
01180         """Check if a value matches a given accept item."""
01181         return item == '*' or item.lower() == value.lower()
01182 
01183     def __getitem__(self, key):
01184         """Besides index lookup (getting item n) you can also pass it a string
01185         to get the quality for the item.  If the item is not in the list, the
01186         returned quality is ``0``.
01187         """
01188         if isinstance(key, basestring):
01189             for item, quality in self:
01190                 if self._value_matches(key, item):
01191                     return quality
01192             return 0
01193         return list.__getitem__(self, key)
01194 
01195     def __contains__(self, value):
01196         for item, quality in self:
01197             if self._value_matches(value, item):
01198                 return True
01199         return False
01200 
01201     def __repr__(self):
01202         return '%s([%s])' % (
01203             self.__class__.__name__,
01204             ', '.join('(%r, %s)' % (x, y) for x, y in self)
01205         )
01206 
01207     def index(self, key):
01208         """Get the position of an entry or raise :exc:`ValueError`.
01209 
01210         :param key: The key to be looked up.
01211 
01212         .. versionchanged:: 0.5
01213            This used to raise :exc:`IndexError`, which was inconsistent
01214            with the list API.
01215         """
01216         if isinstance(key, basestring):
01217             for idx, (item, quality) in enumerate(self):
01218                 if self._value_matches(key, item):
01219                     return idx
01220             raise ValueError(key)
01221         return list.index(self, key)
01222 
01223     def find(self, key):
01224         """Get the position of an entry or return -1.
01225 
01226         :param key: The key to be looked up.
01227         """
01228         try:
01229             return self.index(key)
01230         except ValueError:
01231             return -1
01232 
01233     def values(self):
01234         """Return a list of the values, not the qualities."""
01235         return list(self.itervalues())
01236 
01237     def itervalues(self):
01238         """Iterate over all values."""
01239         for item in self:
01240             yield item[0]
01241 
01242     def to_header(self):
01243         """Convert the header set into an HTTP header string."""
01244         result = []
01245         for value, quality in self:
01246             if quality != 1:
01247                 value = '%s;q=%s' % (value, quality)
01248             result.append(value)
01249         return ','.join(result)
01250 
01251     def __str__(self):
01252         return self.to_header()
01253 
01254     @property
01255     def best(self):
01256         """The best match as value."""
01257         if self:
01258             return self[0][0]
01259 
01260 
01261 class MIMEAccept(Accept):
01262     """Like :class:`Accept` but with special methods and behavior for
01263     mimetypes.
01264     """
01265 
01266     def _value_matches(self, value, item):
01267         def _normalize(x):
01268             x = x.lower()
01269             return x == '*' and ('*', '*') or x.split('/', 1)
01270 
01271         # this is from the application which is trusted.  to avoid developer
01272         # frustration we actually check these for valid values
01273         if '/' not in value:
01274             raise ValueError('invalid mimetype %r' % value)
01275         value_type, value_subtype = _normalize(value)
01276         if value_type == '*' and value_subtype != '*':
01277             raise ValueError('invalid mimetype %r' % value)
01278 
01279         if '/' not in item:
01280             return False
01281         item_type, item_subtype = _normalize(item)
01282         if item_type == '*' and item_subtype != '*':
01283             return False
01284         return (
01285             (item_type == item_subtype == '*' or
01286              value_type == value_subtype == '*') or
01287             (item_type == value_type and (item_subtype == '*' or
01288                                           value_subtype == '*' or
01289                                           item_subtype == value_subtype))
01290         )
01291 
01292     @property
01293     def accept_html(self):
01294         """True if this object accepts HTML."""
01295         return (
01296             'text/html' in self or
01297             'application/xhtml+xml' in self or
01298             self.accept_xhtml
01299         )
01300 
01301     @property
01302     def accept_xhtml(self):
01303         """True if this object accepts XHTML."""
01304         return (
01305             'application/xhtml+xml' in self or
01306             'application/xml' in self
01307         )
01308 
01309 
01310 class LanguageAccept(Accept):
01311     """Like :class:`Accept` but with normalization for languages."""
01312 
01313     def _value_matches(self, value, item):
01314         def _normalize(language):
01315             return _locale_delim_re.split(language.lower())
01316         return item == '*' or _normalize(value) == _normalize(item)
01317 
01318 
01319 class CharsetAccept(Accept):
01320     """Like :class:`Accept` but with normalization for charsets."""
01321 
01322     def _value_matches(self, value, item):
01323         def _normalize(name):
01324             try:
01325                 return codecs.lookup(name).name
01326             except LookupError:
01327                 return name.lower()
01328         return item == '*' or _normalize(value) == _normalize(item)
01329 
01330 
01331 def cache_property(key, empty, type):
01332     """Return a new property object for a cache header.  Useful if you
01333     want to add support for a cache extension in a subclass."""
01334     return property(lambda x: x._get_cache_value(key, empty, type),
01335                     lambda x, v: x._set_cache_value(key, v, type),
01336                     lambda x: x._del_cache_value(key),
01337                     'accessor for %r' % key)
01338 
01339 
01340 class _CacheControl(UpdateDictMixin, dict):
01341     """Subclass of a dict that stores values for a Cache-Control header.  It
01342     has accessors for all the cache-control directives specified in RFC 2616.
01343     The class does not differentiate between request and response directives.
01344 
01345     Because the cache-control directives in the HTTP header use dashes the
01346     python descriptors use underscores for that.
01347 
01348     To get a header of the :class:`CacheControl` object again you can convert
01349     the object into a string or call the :meth:`to_header` method.  If you plan
01350     to subclass it and add your own items have a look at the sourcecode for
01351     that class.
01352 
01353     The following attributes are exposed:
01354 
01355     `no_cache`, `no_store`, `max_age`, `max_stale`, `min_fresh`,
01356     `no_transform`, `only_if_cached`, `public`, `private`, `must_revalidate`,
01357     `proxy_revalidate`, and `s_maxage`
01358 
01359     .. versionchanged:: 0.4
01360 
01361        setting `no_cache` or `private` to boolean `True` will set the implicit
01362        none-value which is ``*``:
01363 
01364        >>> cc = ResponseCacheControl()
01365        >>> cc.no_cache = True
01366        >>> cc
01367        <ResponseCacheControl 'no-cache'>
01368        >>> cc.no_cache
01369        '*'
01370        >>> cc.no_cache = None
01371        >>> cc
01372        <ResponseCacheControl ''>
01373     """
01374 
01375     no_cache = cache_property('no-cache', '*', None)
01376     no_store = cache_property('no-store', None, bool)
01377     max_age = cache_property('max-age', -1, int)
01378     no_transform = cache_property('no-transform', None, None)
01379 
01380     def __init__(self, values=(), on_update=None):
01381         dict.__init__(self, values or ())
01382         self.on_update = on_update
01383         self.provided = values is not None
01384 
01385     def _get_cache_value(self, key, empty, type):
01386         """Used internally by the accessor properties."""
01387         if type is bool:
01388             return key in self
01389         if key in self:
01390             value = self[key]
01391             if value is None:
01392                 return empty
01393             elif type is not None:
01394                 try:
01395                     value = type(value)
01396                 except ValueError:
01397                     pass
01398             return value
01399 
01400     def _set_cache_value(self, key, value, type):
01401         """Used internally by the accessor properties."""
01402         if type is bool:
01403             if value:
01404                 self[key] = None
01405             else:
01406                 self.pop(key, None)
01407         else:
01408             if value is None:
01409                 self.pop(key)
01410             elif value is True:
01411                 self[key] = None
01412             else:
01413                 self[key] = value
01414 
01415     def _del_cache_value(self, key):
01416         """Used internally by the accessor properties."""
01417         if key in self:
01418             del self[key]
01419 
01420     def to_header(self):
01421         """Convert the stored values into a cache control header."""
01422         return dump_header(self)
01423 
01424     def __str__(self):
01425         return self.to_header()
01426 
01427     def __repr__(self):
01428         return '<%s %r>' % (
01429             self.__class__.__name__,
01430             self.to_header()
01431         )
01432 
01433 
01434 class RequestCacheControl(ImmutableDictMixin, _CacheControl):
01435     """A cache control for requests.  This is immutable and gives access
01436     to all the request-relevant cache control headers.
01437 
01438     .. versionadded:: 0.5
01439        In previous versions a `CacheControl` class existed that was used
01440        both for request and response.
01441     """
01442 
01443     max_stale = cache_property('max-stale', '*', int)
01444     min_fresh = cache_property('min-fresh', '*', int)
01445     no_transform = cache_property('no-transform', None, None)
01446     only_if_cached = cache_property('only-if-cached', None, bool)
01447 
01448 
01449 class ResponseCacheControl(_CacheControl):
01450     """A cache control for responses.  Unlike :class:`RequestCacheControl`
01451     this is mutable and gives access to response-relevant cache control
01452     headers.
01453 
01454     .. versionadded:: 0.5
01455        In previous versions a `CacheControl` class existed that was used
01456        both for request and response.
01457     """
01458 
01459     public = cache_property('public', None, bool)
01460     private = cache_property('private', '*', None)
01461     must_revalidate = cache_property('must-revalidate', None, bool)
01462     proxy_revalidate = cache_property('proxy-revalidate', None, bool)
01463     s_maxage = cache_property('s-maxage', None, None)
01464 
01465 
01466 class CacheControl(ResponseCacheControl):
01467     """Deprecated."""
01468     max_stale = cache_property('max-stale', '*', int)
01469     min_fresh = cache_property('min-fresh', '*', int)
01470     no_transform = cache_property('no-transform', None, None)
01471     only_if_cached = cache_property('only-if-cached', None, bool)
01472 
01473     def __init__(self, values=(), on_update=None):
01474         from warnings import warn
01475         warn(DeprecationWarning('CacheControl is deprecated in favor of '
01476                                 'RequestCacheControl and ResponseCacheControl.'))
01477         ResponseCacheControl.__init__(self, values, on_update)
01478 
01479 
01480 # attach cache_property to the _CacheControl as staticmethod
01481 # so that others can reuse it.
01482 _CacheControl.cache_property = staticmethod(cache_property)
01483 
01484 
01485 class CallbackDict(UpdateDictMixin, dict):
01486     """A dict that calls a function passed every time something is changed.
01487     The function is passed the dict instance.
01488     """
01489 
01490     def __init__(self, initial=None, on_update=None):
01491         dict.__init__(self, initial or ())
01492         self.on_update = on_update
01493 
01494     def __repr__(self):
01495         return '<%s %s>' % (
01496             self.__class__.__name__,
01497             dict.__repr__(self)
01498         )
01499 
01500 
01501 class HeaderSet(object):
01502     """Similar to the :class:`ETags` class this implements a set-like structure.
01503     Unlike :class:`ETags` this is case insensitive and used for vary, allow, and
01504     content-language headers.
01505 
01506     If not constructed using the :func:`parse_set_header` function the
01507     instantiation works like this:
01508 
01509     >>> hs = HeaderSet(['foo', 'bar', 'baz'])
01510     >>> hs
01511     HeaderSet(['foo', 'bar', 'baz'])
01512     """
01513 
01514     def __init__(self, headers=None, on_update=None):
01515         self._headers = list(headers or ())
01516         self._set = set([x.lower() for x in self._headers])
01517         self.on_update = on_update
01518 
01519     def add(self, header):
01520         """Add a new header to the set."""
01521         self.update((header,))
01522 
01523     def remove(self, header):
01524         """Remove a layer from the set.  This raises an :exc:`KeyError` if the
01525         header is not in the set.
01526 
01527         .. versionchanged:: 0.5
01528             In older versions a :exc:`IndexError` was raised instead of a
01529             :exc:`KeyError` if the object was missing.
01530 
01531         :param header: the header to be removed.
01532         """
01533         key = header.lower()
01534         if key not in self._set:
01535             raise KeyError(header)
01536         self._set.remove(key)
01537         for idx, key in enumerate(self._headers):
01538             if key.lower() == header:
01539                 del self._headers[idx]
01540                 break
01541         if self.on_update is not None:
01542             self.on_update(self)
01543 
01544     def update(self, iterable):
01545         """Add all the headers from the iterable to the set.
01546 
01547         :param iterable: updates the set with the items from the iterable.
01548         """
01549         inserted_any = False
01550         for header in iterable:
01551             key = header.lower()
01552             if key not in self._set:
01553                 self._headers.append(header)
01554                 self._set.add(key)
01555                 inserted_any = True
01556         if inserted_any and self.on_update is not None:
01557             self.on_update(self)
01558 
01559     def discard(self, header):
01560         """Like :meth:`remove` but ignores errors.
01561 
01562         :param header: the header to be discarded.
01563         """
01564         try:
01565             return self.remove(header)
01566         except KeyError:
01567             pass
01568 
01569     def find(self, header):
01570         """Return the index of the header in the set or return -1 if not found.
01571 
01572         :param header: the header to be looked up.
01573         """
01574         header = header.lower()
01575         for idx, item in enumerate(self._headers):
01576             if item.lower() == header:
01577                 return idx
01578         return -1
01579 
01580     def index(self, header):
01581         """Return the index of the header in the set or raise an
01582         :exc:`IndexError`.
01583 
01584         :param header: the header to be looked up.
01585         """
01586         rv = self.find(header)
01587         if rv < 0:
01588             raise IndexError(header)
01589         return rv
01590 
01591     def clear(self):
01592         """Clear the set."""
01593         self._set.clear()
01594         del self._headers[:]
01595         if self.on_update is not None:
01596             self.on_update(self)
01597 
01598     def as_set(self, preserve_casing=False):
01599         """Return the set as real python set type.  When calling this, all
01600         the items are converted to lowercase and the ordering is lost.
01601 
01602         :param preserve_casing: if set to `True` the items in the set returned
01603                                 will have the original case like in the
01604                                 :class:`HeaderSet`, otherwise they will
01605                                 be lowercase.
01606         """
01607         if preserve_casing:
01608             return set(self._headers)
01609         return set(self._set)
01610 
01611     def to_header(self):
01612         """Convert the header set into an HTTP header string."""
01613         return ', '.join(map(quote_header_value, self._headers))
01614 
01615     def __getitem__(self, idx):
01616         return self._headers[idx]
01617 
01618     def __delitem__(self, idx):
01619         rv = self._headers.pop(idx)
01620         self._set.remove(rv.lower())
01621         if self.on_update is not None:
01622             self.on_update(self)
01623 
01624     def __setitem__(self, idx, value):
01625         old = self._headers[idx]
01626         self._set.remove(old.lower())
01627         self._headers[idx] = value
01628         self._set.add(value.lower())
01629         if self.on_update is not None:
01630             self.on_update(self)
01631 
01632     def __contains__(self, header):
01633         return header.lower() in self._set
01634 
01635     def __len__(self):
01636         return len(self._set)
01637 
01638     def __iter__(self):
01639         return iter(self._headers)
01640 
01641     def __nonzero__(self):
01642         return bool(self._set)
01643 
01644     def __str__(self):
01645         return self.to_header()
01646 
01647     def __repr__(self):
01648         return '%s(%r)' % (
01649             self.__class__.__name__,
01650             self._headers
01651         )
01652 
01653 
01654 class ETags(object):
01655     """A set that can be used to check if one etag is present in a collection
01656     of etags.
01657     """
01658 
01659     def __init__(self, strong_etags=None, weak_etags=None, star_tag=False):
01660         self._strong = frozenset(not star_tag and strong_etags or ())
01661         self._weak = frozenset(weak_etags or ())
01662         self.star_tag = star_tag
01663 
01664     def as_set(self, include_weak=False):
01665         """Convert the `ETags` object into a python set.  Per default all the
01666         weak etags are not part of this set."""
01667         rv = set(self._strong)
01668         if include_weak:
01669             rv.update(self._weak)
01670         return rv
01671 
01672     def is_weak(self, etag):
01673         """Check if an etag is weak."""
01674         return etag in self._weak
01675 
01676     def contains_weak(self, etag):
01677         """Check if an etag is part of the set including weak and strong tags."""
01678         return self.is_weak(etag) or self.contains(etag)
01679 
01680     def contains(self, etag):
01681         """Check if an etag is part of the set ignoring weak tags."""
01682         if self.star_tag:
01683             return True
01684         return etag in self._strong
01685 
01686     def contains_raw(self, etag):
01687         """When passed a quoted tag it will check if this tag is part of the
01688         set.  If the tag is weak it is checked against weak and strong tags,
01689         otherwise weak only."""
01690         etag, weak = unquote_etag(etag)
01691         if weak:
01692             return self.contains_weak(etag)
01693         return self.contains(etag)
01694 
01695     def to_header(self):
01696         """Convert the etags set into a HTTP header string."""
01697         if self.star_tag:
01698             return '*'
01699         return ', '.join(
01700             ['"%s"' % x for x in self._strong] +
01701             ['w/"%s"' % x for x in self._weak]
01702         )
01703 
01704     def __call__(self, etag=None, data=None, include_weak=False):
01705         if [etag, data].count(None) != 1:
01706             raise TypeError('either tag or data required, but at least one')
01707         if etag is None:
01708             etag = generate_etag(data)
01709         if include_weak:
01710             if etag in self._weak:
01711                 return True
01712         return etag in self._strong
01713 
01714     def __nonzero__(self):
01715         return bool(self.star_tag or self._strong)
01716 
01717     def __str__(self):
01718         return self.to_header()
01719 
01720     def __iter__(self):
01721         return iter(self._strong)
01722 
01723     def __contains__(self, etag):
01724         return self.contains(etag)
01725 
01726     def __repr__(self):
01727         return '<%s %r>' % (self.__class__.__name__, str(self))
01728 
01729 
01730 class Authorization(ImmutableDictMixin, dict):
01731     """Represents an `Authorization` header sent by the client.  You should
01732     not create this kind of object yourself but use it when it's returned by
01733     the `parse_authorization_header` function.
01734 
01735     This object is a dict subclass and can be altered by setting dict items
01736     but it should be considered immutable as it's returned by the client and
01737     not meant for modifications.
01738 
01739     .. versionchanged:: 0.5
01740        This object became immutable.
01741     """
01742 
01743     def __init__(self, auth_type, data=None):
01744         dict.__init__(self, data or {})
01745         self.type = auth_type
01746 
01747     username = property(lambda x: x.get('username'), doc='''
01748         The username transmitted.  This is set for both basic and digest
01749         auth all the time.''')
01750     password = property(lambda x: x.get('password'), doc='''
01751         When the authentication type is basic this is the password
01752         transmitted by the client, else `None`.''')
01753     realm = property(lambda x: x.get('realm'), doc='''
01754         This is the server realm sent back for HTTP digest auth.''')
01755     nonce = property(lambda x: x.get('nonce'), doc='''
01756         The nonce the server sent for digest auth, sent back by the client.
01757         A nonce should be unique for every 401 response for HTTP digest
01758         auth.''')
01759     uri = property(lambda x: x.get('uri'), doc='''
01760         The URI from Request-URI of the Request-Line; duplicated because
01761         proxies are allowed to change the Request-Line in transit.  HTTP
01762         digest auth only.''')
01763     nc = property(lambda x: x.get('nc'), doc='''
01764         The nonce count value transmitted by clients if a qop-header is
01765         also transmitted.  HTTP digest auth only.''')
01766     cnonce = property(lambda x: x.get('cnonce'), doc='''
01767         If the server sent a qop-header in the ``WWW-Authenticate``
01768         header, the client has to provide this value for HTTP digest auth.
01769         See the RFC for more details.''')
01770     response = property(lambda x: x.get('response'), doc='''
01771         A string of 32 hex digits computed as defined in RFC 2617, which
01772         proves that the user knows a password.  Digest auth only.''')
01773     opaque = property(lambda x: x.get('opaque'), doc='''
01774         The opaque header from the server returned unchanged by the client.
01775         It is recommended that this string be base64 or hexadecimal data.
01776         Digest auth only.''')
01777 
01778     @property
01779     def qop(self):
01780         """Indicates what "quality of protection" the client has applied to
01781         the message for HTTP digest auth."""
01782         def on_update(header_set):
01783             if not header_set and 'qop' in self:
01784                 del self['qop']
01785             elif header_set:
01786                 self['qop'] = header_set.to_header()
01787         return parse_set_header(self.get('qop'), on_update)
01788 
01789 
01790 class WWWAuthenticate(UpdateDictMixin, dict):
01791     """Provides simple access to `WWW-Authenticate` headers."""
01792 
01793     #: list of keys that require quoting in the generated header
01794     _require_quoting = frozenset(['domain', 'nonce', 'opaque', 'realm'])
01795 
01796     def __init__(self, auth_type=None, values=None, on_update=None):
01797         dict.__init__(self, values or ())
01798         if auth_type:
01799             self['__auth_type__'] = auth_type
01800         self.on_update = on_update
01801 
01802     def set_basic(self, realm='authentication required'):
01803         """Clear the auth info and enable basic auth."""
01804         dict.clear(self)
01805         dict.update(self, {'__auth_type__': 'basic', 'realm': realm})
01806         if self.on_update:
01807             self.on_update(self)
01808 
01809     def set_digest(self, realm, nonce, qop=('auth',), opaque=None,
01810                    algorithm=None, stale=False):
01811         """Clear the auth info and enable digest auth."""
01812         d = {
01813             '__auth_type__':    'digest',
01814             'realm':            realm,
01815             'nonce':            nonce,
01816             'qop':              dump_header(qop)
01817         }
01818         if stale:
01819             d['stale'] = 'TRUE'
01820         if opaque is not None:
01821             d['opaque'] = opaque
01822         if algorithm is not None:
01823             d['algorithm'] = algorithm
01824         dict.clear(self)
01825         dict.update(self, d)
01826         if self.on_update:
01827             self.on_update(self)
01828 
01829     def to_header(self):
01830         """Convert the stored values into a WWW-Authenticate header."""
01831         d = dict(self)
01832         auth_type = d.pop('__auth_type__', None) or 'basic'
01833         return '%s %s' % (auth_type.title(), ', '.join([
01834             '%s=%s' % (key, quote_header_value(value,
01835                        allow_token=key not in self._require_quoting))
01836             for key, value in d.iteritems()
01837         ]))
01838 
01839     def __str__(self):
01840         return self.to_header()
01841 
01842     def __repr__(self):
01843         return '<%s %r>' % (
01844             self.__class__.__name__,
01845             self.to_header()
01846         )
01847 
01848     def auth_property(name, doc=None):
01849         """A static helper function for subclasses to add extra authentication
01850         system properites onto a class::
01851 
01852             class FooAuthenticate(WWWAuthenticate):
01853                 special_realm = auth_property('special_realm')
01854 
01855         For more information have a look at the sourcecode to see how the
01856         regular properties (:attr:`realm` etc. are implemented).
01857         """
01858         def _set_value(self, value):
01859             if value is None:
01860                 self.pop(name, None)
01861             else:
01862                 self[name] = str(value)
01863         return property(lambda x: x.get(name), _set_value, doc=doc)
01864 
01865     def _set_property(name, doc=None):
01866         def fget(self):
01867             def on_update(header_set):
01868                 if not header_set and name in self:
01869                     del self[name]
01870                 elif header_set:
01871                     self[name] = header_set.to_header()
01872             return parse_set_header(self.get(name), on_update)
01873         return property(fget, doc=doc)
01874 
01875     type = auth_property('__auth_type__', doc='''
01876         The type of the auth mechanism.  HTTP currently specifies
01877         `Basic` and `Digest`.''')
01878     realm = auth_property('realm', doc='''
01879         A string to be displayed to users so they know which username and
01880         password to use.  This string should contain at least the name of
01881         the host performing the authentication and might additionally
01882         indicate the collection of users who might have access.''')
01883     domain = _set_property('domain', doc='''
01884         A list of URIs that define the protection space.  If a URI is an
01885         absolute path, it is relative to the canonical root URL of the
01886         server being accessed.''')
01887     nonce = auth_property('nonce', doc='''
01888         A server-specified data string which should be uniquely generated
01889         each time a 401 response is made.  It is recommended that this
01890         string be base64 or hexadecimal data.''')
01891     opaque = auth_property('opaque', doc='''
01892         A string of data, specified by the server, which should be returned
01893         by the client unchanged in the Authorization header of subsequent
01894         requests with URIs in the same protection space.  It is recommended
01895         that this string be base64 or hexadecimal data.''')
01896     algorithm = auth_property('algorithm', doc='''
01897         A string indicating a pair of algorithms used to produce the digest
01898         and a checksum.  If this is not present it is assumed to be "MD5".
01899         If the algorithm is not understood, the challenge should be ignored
01900         (and a different one used, if there is more than one).''')
01901     qop = _set_property('qop', doc='''
01902         A set of quality-of-privacy modifies such as auth and auth-int.''')
01903 
01904     def _get_stale(self):
01905         val = self.get('stale')
01906         if val is not None:
01907             return val.lower() == 'true'
01908     def _set_stale(self, value):
01909         if value is None:
01910             self.pop('stale', None)
01911         else:
01912             self['stale'] = value and 'TRUE' or 'FALSE'
01913     stale = property(_get_stale, _set_stale, doc='''
01914         A flag, indicating that the previous request from the client was
01915         rejected because the nonce value was stale.''')
01916     del _get_stale, _set_stale
01917 
01918     # make auth_property a staticmethod so that subclasses of
01919     # `WWWAuthenticate` can use it for new properties.
01920     auth_property = staticmethod(auth_property)
01921     del _set_property
01922 
01923 
01924 # circular dependencies
01925 from werkzeug.http import dump_options_header, dump_header, generate_etag, \
01926      quote_header_value, parse_set_header, unquote_etag
01927 
01928 
01929 # create all the special key errors now that the classes are defined.
01930 from werkzeug.exceptions import BadRequest
01931 for _cls in MultiDict, CombinedMultiDict, Headers, EnvironHeaders:
01932     _cls.KeyError = BadRequest.wrap(KeyError, _cls.__name__ + '.KeyError')
01933 del _cls