1
# -*- coding: utf-8 -*-
3
werkzeug.datastructures
4
~~~~~~~~~~~~~~~~~~~~~~~
6
This module provides mixins and classes with an immutable interface.
8
:copyright: (c) 2009 by the Werkzeug Team, see AUTHORS for more details.
9
:license: BSD, see LICENSE for more details.
14
from werkzeug._internal import _proxy_repr, _missing
17
_locale_delim_re = re.compile(r'[_-]')
20
def is_immutable(self):
21
raise TypeError('%r objects are immutable' % self.__class__.__name__)
24
class ImmutableListMixin(object):
25
"""Makes a :class:`list` immutable.
32
def __delitem__(self, key):
35
def __delslice__(self, i, j):
38
def __iadd__(self, other):
42
def __setitem__(self, key, value):
45
def __setslice__(self, i, j, value):
48
def append(self, item):
52
def extend(self, iterable):
55
def insert(self, pos, value):
58
def pop(self, index=-1):
64
def sort(self, cmp=None, key=None, reverse=None):
68
class ImmutableList(ImmutableListMixin, list):
69
"""An immutable :class:`list`.
76
__repr__ = _proxy_repr(list)
79
class ImmutableDictMixin(object):
80
"""Makes a :class:`dict` immutable.
87
def setdefault(self, key, default=None):
90
def update(self, *args, **kwargs):
93
def pop(self, key, default=None):
99
def __setitem__(self, key, value):
102
def __delitem__(self, key):
109
class ImmutableMultiDictMixin(ImmutableDictMixin):
110
"""Makes a :class:`MultiDict` immutable.
112
.. versionadded:: 0.5
117
def popitemlist(self):
120
def poplist(self, key):
123
def setlist(self, key, new_list):
126
def setlistdefault(self, key, default_list=None):
130
class UpdateDictMixin(object):
131
"""Makes dicts call `self.on_update` on modifications."""
135
def calls_update(name):
136
def oncall(self, *args, **kw):
137
rv = getattr(super(UpdateDictMixin, self), name)(*args, **kw)
138
if self.on_update is not None:
141
oncall.__name__ = name
144
__setitem__ = calls_update('__setitem__')
145
__delitem__ = calls_update('__delitem__')
146
clear = calls_update('clear')
147
pop = calls_update('pop')
148
popitem = calls_update('popitem')
149
setdefault = calls_update('setdefault')
150
update = calls_update('update')
154
class TypeConversionDict(dict):
155
"""Works like a regular dict but the :meth:`get` method can perform
156
type conversions. :class:`MultiDict` and :class:`CombinedMultiDict`
157
are subclasses of this class and provide the same feature.
159
.. versionadded:: 0.5
162
def get(self, key, default=None, type=None):
163
"""Return the default value if the requested data doesn't exist.
164
If `type` is provided and is a callable it should convert the value,
165
return it or raise a :exc:`ValueError` if that is not possible. In
166
this case the function will return the default as if the value was not
169
>>> d = TypeConversionDict(foo='42', bar='blub')
170
>>> d.get('foo', type=int)
172
>>> d.get('bar', -1, type=int)
175
:param key: The key to be looked up.
176
:param default: The default value to be returned if the key can't
177
be looked up. If not further specified `None` is
179
:param type: A callable that is used to cast the value in the
180
:class:`MultiDict`. If a :exc:`ValueError` is raised
181
by this callable the default value is returned.
187
except (KeyError, ValueError):
192
class ImmutableTypeConversionDict(ImmutableDictMixin, TypeConversionDict):
193
"""Works like a :class:`TypeConversionDict` but does not support
196
.. versionadded:: 0.5
200
"""Return a shallow mutable copy of this object. Keep in mind that
201
the standard library's :func:`copy` funciton is a no-op for this class
202
like for any other python immutable type (eg: :class:`tuple`).
204
return TypeConversionDict(self)
210
class MultiDict(TypeConversionDict):
211
"""A :class:`MultiDict` is a dictionary subclass customized to deal with
212
multiple values for the same key which is for example used by the parsing
213
functions in the wrappers. This is necessary because some HTML form
214
elements pass multiple values for the same key.
216
:class:`MultiDict` implements all standard dictionary methods.
217
Internally, it saves all values for a key as a list, but the standard dict
218
access methods will only return the first value for a key. If you want to
219
gain access to the other values, too, you have to use the `list` methods as
224
>>> d = MultiDict([('a', 'b'), ('a', 'c')])
226
MultiDict([('a', 'b'), ('a', 'c')])
234
It behaves like a normal dict thus all dict functions will only return the
235
first value when multiple values for one key are found.
237
From Werkzeug 0.3 onwards, the `KeyError` raised by this class is also a
238
subclass of the :exc:`~exceptions.BadRequest` HTTP exception and will
239
render a page for a ``400 BAD REQUEST`` if catched in a catch-all for HTTP
242
A :class:`MultiDict` can be constructed from an iterable of
243
``(key, value)`` tuples, a dict, a :class:`MultiDict` or from Werkzeug 0.2
244
onwards some keyword parameters.
246
:param mapping: the initial value for the :class:`MultiDict`. Either a
247
regular dict, an iterable of ``(key, value)`` tuples
251
# the key error this class raises. Because of circular dependencies
252
# with the http exception module this class is created at the end of
256
def __init__(self, mapping=None):
257
if isinstance(mapping, MultiDict):
258
dict.__init__(self, ((k, l[:]) for k, l in mapping.iterlists()))
259
elif isinstance(mapping, dict):
261
for key, value in mapping.iteritems():
262
if isinstance(value, (tuple, list)):
267
dict.__init__(self, tmp)
270
for key, value in mapping or ():
271
tmp.setdefault(key, []).append(value)
272
dict.__init__(self, tmp)
274
def __getitem__(self, key):
275
"""Return the first data value for this key;
276
raises KeyError if not found.
278
:param key: The key to be looked up.
279
:raise KeyError: if the key does not exist.
282
return dict.__getitem__(self, key)[0]
283
raise self.KeyError(key)
285
def __setitem__(self, key, value):
286
"""Set an item as list."""
287
dict.__setitem__(self, key, [value])
289
def getlist(self, key, type=None):
290
"""Return the list of items for a given key. If that key is not in the
291
`MultiDict`, the return value will be an empty list. Just as `get`
292
`getlist` accepts a `type` parameter. All items will be converted
293
with the callable defined there.
295
:param key: The key to be looked up.
296
:param type: A callable that is used to cast the value in the
297
:class:`MultiDict`. If a :exc:`ValueError` is raised
298
by this callable the value will be removed from the list.
299
:return: a :class:`list` of all the values for the key.
302
rv = dict.__getitem__(self, key)
310
result.append(type(item))
315
def setlist(self, key, new_list):
316
"""Remove the old values for a key and add new ones. Note that the list
317
you pass the values in will be shallow-copied before it is inserted in
321
>>> d.setlist('foo', ['1', '2'])
327
:param key: The key for which the values are set.
328
:param new_list: An iterable with the new values for the key. Old values
331
dict.__setitem__(self, key, list(new_list))
333
def setdefault(self, key, default=None):
334
"""Returns the value for the key if it is in the dict, otherwise it
335
returns `default` and sets that value for `key`.
337
:param key: The key to be looked up.
338
:param default: The default value to be returned if the key is not
339
in the dict. If not further specified it's `None`.
347
def setlistdefault(self, key, default_list=None):
348
"""Like `setdefault` but sets multiple values. The list returned
349
is not a copy, but the list that is actually used internally. This
350
means that you can put new values into the dict by appending items
353
>>> d = MultiDict({"foo": 1})
354
>>> d.setlistdefault("foo").extend([2, 3])
358
:param key: The key to be looked up.
359
:param default: An iterable of default values. It is either copied
360
(in case it was a list) or converted into a list
362
:return: a :class:`list`
365
default_list = list(default_list or ())
366
dict.__setitem__(self, key, default_list)
368
default_list = dict.__getitem__(self, key)
371
def items(self, multi=False):
372
"""Return a list of ``(key, value)`` pairs.
374
:param multi: If set to `True` the list returned will have a
375
pair for each value of each key. Ohterwise it
376
will only contain pairs for the first value of
379
:return: a :class:`list`
381
return list(self.iteritems(multi))
383
#: Return a list of ``(key, value)`` pairs, where values is the list of
384
#: all values associated with the key.
386
#: :return: a :class:`list`
390
"""Returns a list of the first value on every key's value list.
392
:return: a :class:`list`.
394
return [self[key] for key in self.iterkeys()]
396
def listvalues(self):
397
"""Return a list of all values associated with a key. Zipping
398
:meth:`keys` and this is the same as calling :meth:`lists`:
400
>>> d = MultiDict({"foo": [1, 2, 3]})
401
>>> zip(d.keys(), d.listvalues()) == d.lists()
404
:return: a :class:`list`
406
return list(self.iterlistvalues())
408
def iteritems(self, multi=False):
409
"""Like :meth:`items` but returns an iterator."""
410
for key, values in dict.iteritems(self):
418
"""Return a list of all values associated with a key.
420
:return: a class:`list`
422
for key, values in dict.iteritems(self):
423
yield key, list(values)
425
def itervalues(self):
426
"""Like :meth:`values` but returns an iterator."""
427
for values in dict.itervalues(self):
430
def iterlistvalues(self):
431
"""like :meth:`listvalues` but returns an iterator."""
432
for values in dict.itervalues(self):
436
"""Return a shallow copy of this object."""
437
return self.__class__(self)
439
def to_dict(self, flat=True):
440
"""Return the contents as regular dict. If `flat` is `True` the
441
returned dict will only have the first item present, if `flat` is
442
`False` all values will be returned as lists.
444
:param flat: If set to `False` the dict returned will have lists
445
with all the values in it. Otherwise it will only
446
contain the first value for each key.
447
:return: a :class:`dict`
450
return dict(self.iteritems())
453
def update(self, other_dict):
454
"""update() extends rather than replaces existing key lists."""
455
if isinstance(other_dict, MultiDict):
456
for key, value_list in other_dict.iterlists():
457
self.setlistdefault(key, []).extend(value_list)
458
elif isinstance(other_dict, dict):
459
for key, value in other_dict.items():
460
self.setlistdefault(key, []).append(value)
462
for key, value in other_dict:
463
self.setlistdefault(key, []).append(value)
465
def pop(self, key, default=_missing):
466
"""Pop the first item for a list on the dict. Afterwards the
467
key is removed from the dict, so additional values are discarded:
469
>>> d = MultiDict({"foo": [1, 2, 3]})
475
:param key: the key to pop.
476
:param default: if provided the value to return if the key was
477
not in the dictionary.
479
if default is not _missing:
480
return dict.pop(self, key, default)
482
return dict.pop(self, key)[0]
484
raise self.KeyError(str(e))
487
"""Pop an item from the dict."""
489
item = dict.popitem(self)
490
return (item[0], item[1][0])
492
raise self.KeyError(str(e))
494
def poplist(self, key):
495
"""Pop the list for a key from the dict. If the key is not in the dict
496
an empty list is returned.
498
.. versionchanged:: 0.5
499
If the key does no longer exist a list is returned instead of
502
return dict.pop(self, key, [])
504
def popitemlist(self):
505
"""Pop a ``(key, list)`` tuple from the dict."""
507
return dict.popitem(self)
509
raise self.KeyError(str(e))
512
return '%s(%r)' % (self.__class__.__name__, self.items(multi=True))
515
class Headers(object):
516
"""An object that stores some headers. It has a dict-like interface
517
but is ordered and can store the same keys multiple times.
519
This data structure is useful if you want a nicer way to handle WSGI
520
headers which are stored as tuples in a list.
522
From Werkzeug 0.3 onwards, the :exc:`KeyError` raised by this class is
523
also a subclass of the :class:`~exceptions.BadRequest` HTTP exception
524
and will render a page for a ``400 BAD REQUEST`` if catched in a
525
catch-all for HTTP exceptions.
527
Headers is mostly compatible with the Python :class:`wsgiref.headers.Headers`
528
class, with the exception of `__getitem__`. :mod:`wsgiref` will return
529
`None` for ``headers['missing']``, whereas :class:`Headers` will raise
532
To create a new :class:`Headers` object pass it a list or dict of headers
533
which are used as default values. This does not reuse the list passed
534
to the constructor for internal usage. To create a :class:`Headers`
535
object that uses as internal storage the list or list-like object you
536
can use the :meth:`linked` class method.
538
:param defaults: The list of default values for the :class:`Headers`.
541
# the key error this class raises. Because of circular dependencies
542
# with the http exception module this class is created at the end of
546
def __init__(self, defaults=None, _list=None):
550
if defaults is not None:
551
self.extend(defaults)
554
def linked(cls, headerlist):
555
"""Create a new :class:`Headers` object that uses the list of headers
556
passed as internal storage:
558
>>> headerlist = [('Content-Length', '40')]
559
>>> headers = Headers.linked(headerlist)
560
>>> headers.add('Content-Type', 'text/html')
562
[('Content-Length', '40'), ('Content-Type', 'text/html')]
564
:param headerlist: The list of headers the class is linked to.
565
:return: new linked :class:`Headers` object.
567
return cls(_list=headerlist)
569
def __getitem__(self, key, _index_operation=True):
571
if isinstance(key, (int, long)):
572
return self._list[key]
573
elif isinstance(key, slice):
574
return self.__class__(self._list[key])
576
for k, v in self._list:
577
if k.lower() == ikey:
579
raise self.KeyError(key)
581
def __eq__(self, other):
582
return other.__class__ is self.__class__ and \
583
set(other._list) == set(self._list)
585
def __ne__(self, other):
586
return not self.__eq__(other)
588
def get(self, key, default=None, type=None):
589
"""Return the default value if the requested data doesn't exist.
590
If `type` is provided and is a callable it should convert the value,
591
return it or raise a :exc:`ValueError` if that is not possible. In
592
this case the function will return the default as if the value was not
595
>>> d = Headers([('Content-Length', '42')])
596
>>> d.get('Content-Length', type=int)
599
If a headers object is bound you must not add unicode strings
600
because no encoding takes place.
602
:param key: The key to be looked up.
603
:param default: The default value to be returned if the key can't
604
be looked up. If not further specified `None` is
606
:param type: A callable that is used to cast the value in the
607
:class:`Headers`. If a :exc:`ValueError` is raised
608
by this callable the default value is returned.
611
rv = self.__getitem__(key, _index_operation=False)
621
def getlist(self, key, type=None):
622
"""Return the list of items for a given key. If that key is not in the
623
:class:`Headers`, the return value will be an empty list. Just as
624
:meth:`get` :meth:`getlist` accepts a `type` parameter. All items will
625
be converted with the callable defined there.
627
:param key: The key to be looked up.
628
:param type: A callable that is used to cast the value in the
629
:class:`Headers`. If a :exc:`ValueError` is raised
630
by this callable the value will be removed from the list.
631
:return: a :class:`list` of all the values for the key.
636
if k.lower() == ikey:
645
def get_all(self, name):
646
"""Return a list of all the values for the named field.
648
This method is compatible with the :mod:`wsgiref`
649
:meth:`~wsgiref.headers.Headers.get_all` method.
651
return self.getlist(name)
653
def iteritems(self, lower=False):
654
for key, value in self:
659
def iterkeys(self, lower=False):
660
for key, _ in self.iteritems(lower):
663
def itervalues(self):
664
for _, value in self.iteritems():
667
def keys(self, lower=False):
668
return list(self.iterkeys(lower))
671
return list(self.itervalues())
673
def items(self, lower=False):
674
return list(self.iteritems(lower))
676
def extend(self, iterable):
677
"""Extend the headers with a dict or an iterable yielding keys and
680
if isinstance(iterable, dict):
681
for key, value in iterable.iteritems():
682
if isinstance(value, (tuple, list)):
688
for key, value in iterable:
691
def __delitem__(self, key, _index_operation=True):
692
if _index_operation and isinstance(key, (int, long, slice)):
697
for k, v in self._list:
702
def remove(self, key):
705
:param key: The key to be removed.
707
return self.__delitem__(key, _index_operation=False)
709
def pop(self, key=None, default=_missing):
710
"""Removes and returns a key or index.
712
:param key: The key to be popped. If this is an integer the item at
713
that position is removed, if it's a string the value for
714
that key is. If the key is omitted or `None` the last
719
return self._list.pop()
720
if isinstance(key, (int, long)):
721
return self._list.pop(key)
726
if default is not _missing:
732
"""Removes a key or index and returns a (key, value) item."""
735
def __contains__(self, key):
736
"""Check if a key is present."""
738
self.__getitem__(key, _index_operation=False)
743
has_key = __contains__
746
"""Yield ``(key, value)`` tuples."""
747
return iter(self._list)
750
return len(self._list)
752
def add(self, _key, _value, **kw):
753
"""Add a new header tuple to the list.
755
Keyword arguments can specify additional parameters for the header
756
value, with underscores converted to dashes::
759
>>> d.add('Content-Type', 'text/plain')
760
>>> d.add('Content-Disposition', 'attachment', filename='foo.png')
762
The keyword argument dumping uses :func:`dump_options_header`
765
.. versionadded:: 0.4.1
766
keyword arguments were added for :mod:`wsgiref` compatibility.
769
_value = dump_options_header(_value, dict((k.replace('_', '-'), v)
770
for k, v in kw.items()))
771
self._list.append((_key, _value))
773
def add_header(self, _key, _value, **_kw):
774
"""Add a new header tuple to the list.
776
An alias for :meth:`add` for compatibility with the :mod:`wsgiref`
777
:meth:`~wsgiref.headers.Headers.add_header` method.
779
self.add(_key, _value, **_kw)
782
"""Clears all headers."""
785
def set(self, key, value):
786
"""Remove all header tuples for `key` and add a new one. The newly
787
added key either appears at the end of the list if there was no
788
entry or replaces the first one.
790
:param key: The key to be inserted.
791
:param value: The value to be inserted.
794
for idx, (old_key, old_value) in enumerate(self._list):
795
if old_key.lower() == lc_key:
796
# replace first ocurrence
797
self._list[idx] = (key, value)
800
return self.add(key, value)
801
self._list[idx + 1:] = [(k, v) for k, v in self._list[idx + 1:]
802
if k.lower() != lc_key]
804
def setdefault(self, key, value):
805
"""Returns the value for the key if it is in the dict, otherwise it
806
returns `default` and sets that value for `key`.
808
:param key: The key to be looked up.
809
:param default: The default value to be returned if the key is not
810
in the dict. If not further specified it's `None`.
817
def __setitem__(self, key, value):
818
"""Like :meth:`set` but also supports index/slice based setting."""
819
if isinstance(key, (slice, int, long)):
820
self._list[key] = value
824
def to_list(self, charset='utf-8'):
825
"""Convert the headers into a list and converts the unicode header
826
items to the specified charset.
832
if isinstance(v, unicode):
833
v = v.encode(charset)
836
result.append((k, v))
840
return self.__class__(self._list)
845
def __str__(self, charset='utf-8'):
846
"""Returns formatted headers suitable for HTTP transmission."""
848
for key, value in self.to_list(charset):
849
strs.append('%s: %s' % (key, value))
851
return '\r\n'.join(strs)
855
self.__class__.__name__,
860
class ImmutableHeadersMixin(object):
861
"""Makes a :class:`Headers` immutable.
863
.. versionadded:: 0.5
866
def __delitem__(self, key):
869
def __setitem__(self, key, value):
875
remove = add_header = add
877
def extend(self, iterable):
880
def insert(self, pos, value):
883
def pop(self, index=-1):
889
def setdefault(self, key, default):
893
class EnvironHeaders(ImmutableHeadersMixin, Headers):
894
"""Read only version of the headers from a WSGI environment. This
895
provides the same interface as `Headers` and is constructed from
898
From Werkzeug 0.3 onwards, the `KeyError` raised by this class is also a
899
subclass of the :exc:`~exceptions.BadRequest` HTTP exception and will
900
render a page for a ``400 BAD REQUEST`` if catched in a catch-all for
904
def __init__(self, environ):
905
self.environ = environ
908
def linked(cls, environ):
909
raise TypeError('%r object is always linked to environment, '
910
'no separate initializer' % cls.__name__)
912
def __eq__(self, other):
915
def __getitem__(self, key, _index_operation=False):
916
# _index_operation is a no-op for this class as there is no index but
917
# used because get() calls it.
918
key = key.upper().replace('-', '_')
919
if key in ('CONTENT_TYPE', 'CONTENT_LENGTH'):
920
return self.environ[key]
921
return self.environ['HTTP_' + key]
924
for key, value in self.environ.iteritems():
925
if key.startswith('HTTP_'):
926
yield key[5:].replace('_', '-').title(), value
927
elif key in ('CONTENT_TYPE', 'CONTENT_LENGTH'):
928
yield key.replace('_', '-').title(), value
931
raise TypeError('cannot create %r copies' % self.__class__.__name__)
934
class CombinedMultiDict(ImmutableMultiDictMixin, MultiDict):
935
"""A read only :class:`MultiDict` that you can pass multiple :class:`MultiDict`
936
instances as sequence and it will combine the return values of all wrapped
939
>>> from werkzeug import MultiDict, CombinedMultiDict
940
>>> post = MultiDict([('foo', 'bar')])
941
>>> get = MultiDict([('blub', 'blah')])
942
>>> combined = CombinedMultiDict([get, post])
948
This works for all read operations and will raise a `TypeError` for
949
methods that usually change data which isn't possible.
951
From Werkzeug 0.3 onwards, the `KeyError` raised by this class is also a
952
subclass of the :exc:`~exceptions.BadRequest` HTTP exception and will
953
render a page for a ``400 BAD REQUEST`` if catched in a catch-all for HTTP
957
def __init__(self, dicts=None):
958
self.dicts = dicts or []
962
raise TypeError('cannot create %r instances by fromkeys' %
965
def __getitem__(self, key):
969
raise self.KeyError(key)
971
def get(self, key, default=None, type=None):
982
def getlist(self, key, type=None):
985
rv.extend(d.getlist(key, type))
994
def iteritems(self, multi=False):
997
for key, value in d.iteritems(multi):
1000
elif key not in found:
1004
def itervalues(self):
1005
for key, value in self.iteritems():
1009
return list(self.itervalues())
1011
def items(self, multi=False):
1012
return list(self.iteritems(multi))
1014
def iterlists(self):
1016
for d in self.dicts:
1017
for key, values in d.iterlists():
1018
rv.setdefault(key, []).extend(values)
1019
return rv.iteritems()
1022
return list(self.iterlists())
1024
def iterlistvalues(self):
1025
return (x[0] for x in self.lists())
1027
def listvalues(self):
1028
return list(self.iterlistvalues())
1031
return iter(self.keys())
1036
"""Return a shallow copy of this object."""
1037
return self.__class__(self.dicts[:])
1039
def to_dict(self, flat=True):
1040
"""Return the contents as regular dict. If `flat` is `True` the
1041
returned dict will only have the first item present, if `flat` is
1042
`False` all values will be returned as lists.
1044
:param flat: If set to `False` the dict returned will have lists
1045
with all the values in it. Otherwise it will only
1046
contain the first item for each key.
1047
:return: a :class:`dict`
1050
for d in reversed(self.dicts):
1051
rv.update(d.to_dict(flat))
1055
return len(self.keys())
1057
def __contains__(self, key):
1058
for d in self.dicts:
1063
has_key = __contains__
1066
return '%s(%r)' % (self.__class__.__name__, self.dicts)
1069
class FileMultiDict(MultiDict):
1070
"""A special :class:`MultiDict` that has convenience methods to add
1071
files to it. This is used for :class:`EnvironBuilder` and generally
1072
useful for unittesting.
1074
.. versionadded:: 0.5
1077
def add_file(self, name, file, filename=None, content_type=None):
1078
"""Adds a new file to the dict. `file` can be a file name or
1079
a :class:`file`-like or a :class:`FileStorage` object.
1081
:param name: the name of the field.
1082
:param file: a filename or :class:`file`-like object
1083
:param filename: an optional filename
1084
:param content_type: an optional content type
1086
from werkzeug.utils import FileStorage
1087
if isinstance(file, FileStorage):
1090
if isinstance(file, basestring):
1091
if filename is None:
1093
file = open(file, 'rb')
1094
if filename and content_type is None:
1095
content_type = mimetypes.guess_type(filename)[0] or \
1096
'application/octet-stream'
1097
self[name] = FileStorage(file, filename, name, content_type)
1100
class ImmutableDict(ImmutableDictMixin, dict):
1101
"""An immutable :class:`dict`.
1103
.. versionadded:: 0.5
1106
__repr__ = _proxy_repr(dict)
1109
"""Return a shallow mutable copy of this object. Keep in mind that
1110
the standard library's :func:`copy` funciton is a no-op for this class
1111
like for any other python immutable type (eg: :class:`tuple`).
1119
class ImmutableMultiDict(ImmutableMultiDictMixin, MultiDict):
1120
"""An immutable :class:`MultiDict`.
1122
.. versionadded:: 0.5
1126
"""Return a shallow mutable copy of this object. Keep in mind that
1127
the standard library's :func:`copy` funciton is a no-op for this class
1128
like for any other python immutable type (eg: :class:`tuple`).
1130
return MultiDict(self)
1136
class Accept(ImmutableList):
1137
"""An :class:`Accept` object is just a list subclass for lists of
1138
``(value, quality)`` tuples. It is automatically sorted by quality.
1140
All :class:`Accept` objects work similar to a list but provide extra
1141
functionality for working with the data. Containment checks are
1142
normalized to the rules of that header:
1144
>>> a = CharsetAccept([('ISO-8859-1', 1), ('utf-8', 0.7)])
1147
>>> 'iso-8859-1' in a
1154
To get the quality for an item you can use normal item lookup:
1156
>>> print a['utf-8']
1161
.. versionchanged:: 0.5
1162
:class:`Accept` objects are forzed immutable now.
1165
def __init__(self, values=()):
1168
self.provided = False
1169
elif isinstance(values, Accept):
1170
self.provided = values.provided
1171
list.__init__(self, values)
1173
self.provided = True
1174
values = [(a, b) for b, a in values]
1177
list.__init__(self, [(a, b) for b, a in values])
1179
def _value_matches(self, value, item):
1180
"""Check if a value matches a given accept item."""
1181
return item == '*' or item.lower() == value.lower()
1183
def __getitem__(self, key):
1184
"""Besides index lookup (getting item n) you can also pass it a string
1185
to get the quality for the item. If the item is not in the list, the
1186
returned quality is ``0``.
1188
if isinstance(key, basestring):
1189
for item, quality in self:
1190
if self._value_matches(key, item):
1193
return list.__getitem__(self, key)
1195
def __contains__(self, value):
1196
for item, quality in self:
1197
if self._value_matches(value, item):
1202
return '%s([%s])' % (
1203
self.__class__.__name__,
1204
', '.join('(%r, %s)' % (x, y) for x, y in self)
1207
def index(self, key):
1208
"""Get the position of an entry or raise :exc:`ValueError`.
1210
:param key: The key to be looked up.
1212
.. versionchanged:: 0.5
1213
This used to raise :exc:`IndexError`, which was inconsistent
1216
if isinstance(key, basestring):
1217
for idx, (item, quality) in enumerate(self):
1218
if self._value_matches(key, item):
1220
raise ValueError(key)
1221
return list.index(self, key)
1223
def find(self, key):
1224
"""Get the position of an entry or return -1.
1226
:param key: The key to be looked up.
1229
return self.index(key)
1234
"""Return a list of the values, not the qualities."""
1235
return list(self.itervalues())
1237
def itervalues(self):
1238
"""Iterate over all values."""
1242
def to_header(self):
1243
"""Convert the header set into an HTTP header string."""
1245
for value, quality in self:
1247
value = '%s;q=%s' % (value, quality)
1248
result.append(value)
1249
return ','.join(result)
1252
return self.to_header()
1256
"""The best match as value."""
1261
class MIMEAccept(Accept):
1262
"""Like :class:`Accept` but with special methods and behavior for
1266
def _value_matches(self, value, item):
1269
return x == '*' and ('*', '*') or x.split('/', 1)
1271
# this is from the application which is trusted. to avoid developer
1272
# frustration we actually check these for valid values
1273
if '/' not in value:
1274
raise ValueError('invalid mimetype %r' % value)
1275
value_type, value_subtype = _normalize(value)
1276
if value_type == '*' and value_subtype != '*':
1277
raise ValueError('invalid mimetype %r' % value)
1281
item_type, item_subtype = _normalize(item)
1282
if item_type == '*' and item_subtype != '*':
1285
(item_type == item_subtype == '*' or
1286
value_type == value_subtype == '*') or
1287
(item_type == value_type and (item_subtype == '*' or
1288
value_subtype == '*' or
1289
item_subtype == value_subtype))
1293
def accept_html(self):
1294
"""True if this object accepts HTML."""
1296
'text/html' in self or
1297
'application/xhtml+xml' in self or
1302
def accept_xhtml(self):
1303
"""True if this object accepts XHTML."""
1305
'application/xhtml+xml' in self or
1306
'application/xml' in self
1310
class LanguageAccept(Accept):
1311
"""Like :class:`Accept` but with normalization for languages."""
1313
def _value_matches(self, value, item):
1314
def _normalize(language):
1315
return _locale_delim_re.split(language.lower())
1316
return item == '*' or _normalize(value) == _normalize(item)
1319
class CharsetAccept(Accept):
1320
"""Like :class:`Accept` but with normalization for charsets."""
1322
def _value_matches(self, value, item):
1323
def _normalize(name):
1325
return codecs.lookup(name).name
1328
return item == '*' or _normalize(value) == _normalize(item)
1331
def cache_property(key, empty, type):
1332
"""Return a new property object for a cache header. Useful if you
1333
want to add support for a cache extension in a subclass."""
1334
return property(lambda x: x._get_cache_value(key, empty, type),
1335
lambda x, v: x._set_cache_value(key, v, type),
1336
lambda x: x._del_cache_value(key),
1337
'accessor for %r' % key)
1340
class _CacheControl(UpdateDictMixin, dict):
1341
"""Subclass of a dict that stores values for a Cache-Control header. It
1342
has accessors for all the cache-control directives specified in RFC 2616.
1343
The class does not differentiate between request and response directives.
1345
Because the cache-control directives in the HTTP header use dashes the
1346
python descriptors use underscores for that.
1348
To get a header of the :class:`CacheControl` object again you can convert
1349
the object into a string or call the :meth:`to_header` method. If you plan
1350
to subclass it and add your own items have a look at the sourcecode for
1353
The following attributes are exposed:
1355
`no_cache`, `no_store`, `max_age`, `max_stale`, `min_fresh`,
1356
`no_transform`, `only_if_cached`, `public`, `private`, `must_revalidate`,
1357
`proxy_revalidate`, and `s_maxage`
1359
.. versionchanged:: 0.4
1361
setting `no_cache` or `private` to boolean `True` will set the implicit
1362
none-value which is ``*``:
1364
>>> cc = ResponseCacheControl()
1365
>>> cc.no_cache = True
1367
<ResponseCacheControl 'no-cache'>
1370
>>> cc.no_cache = None
1372
<ResponseCacheControl ''>
1375
no_cache = cache_property('no-cache', '*', None)
1376
no_store = cache_property('no-store', None, bool)
1377
max_age = cache_property('max-age', -1, int)
1378
no_transform = cache_property('no-transform', None, None)
1380
def __init__(self, values=(), on_update=None):
1381
dict.__init__(self, values or ())
1382
self.on_update = on_update
1383
self.provided = values is not None
1385
def _get_cache_value(self, key, empty, type):
1386
"""Used internally by the accessor properties."""
1393
elif type is not None:
1400
def _set_cache_value(self, key, value, type):
1401
"""Used internally by the accessor properties."""
1415
def _del_cache_value(self, key):
1416
"""Used internally by the accessor properties."""
1420
def to_header(self):
1421
"""Convert the stored values into a cache control header."""
1422
return dump_header(self)
1425
return self.to_header()
1428
return '<%s %r>' % (
1429
self.__class__.__name__,
1434
class RequestCacheControl(ImmutableDictMixin, _CacheControl):
1435
"""A cache control for requests. This is immutable and gives access
1436
to all the request-relevant cache control headers.
1438
.. versionadded:: 0.5
1439
In previous versions a `CacheControl` class existed that was used
1440
both for request and response.
1443
max_stale = cache_property('max-stale', '*', int)
1444
min_fresh = cache_property('min-fresh', '*', int)
1445
no_transform = cache_property('no-transform', None, None)
1446
only_if_cached = cache_property('only-if-cached', None, bool)
1449
class ResponseCacheControl(_CacheControl):
1450
"""A cache control for responses. Unlike :class:`RequestCacheControl`
1451
this is mutable and gives access to response-relevant cache control
1454
.. versionadded:: 0.5
1455
In previous versions a `CacheControl` class existed that was used
1456
both for request and response.
1459
public = cache_property('public', None, bool)
1460
private = cache_property('private', '*', None)
1461
must_revalidate = cache_property('must-revalidate', None, bool)
1462
proxy_revalidate = cache_property('proxy-revalidate', None, bool)
1463
s_maxage = cache_property('s-maxage', None, None)
1466
class CacheControl(ResponseCacheControl):
1468
max_stale = cache_property('max-stale', '*', int)
1469
min_fresh = cache_property('min-fresh', '*', int)
1470
no_transform = cache_property('no-transform', None, None)
1471
only_if_cached = cache_property('only-if-cached', None, bool)
1473
def __init__(self, values=(), on_update=None):
1474
from warnings import warn
1475
warn(DeprecationWarning('CacheControl is deprecated in favor of '
1476
'RequestCacheControl and ResponseCacheControl.'))
1477
ResponseCacheControl.__init__(self, values, on_update)
1480
# attach cache_property to the _CacheControl as staticmethod
1481
# so that others can reuse it.
1482
_CacheControl.cache_property = staticmethod(cache_property)
1485
class CallbackDict(UpdateDictMixin, dict):
1486
"""A dict that calls a function passed every time something is changed.
1487
The function is passed the dict instance.
1490
def __init__(self, initial=None, on_update=None):
1491
dict.__init__(self, initial or ())
1492
self.on_update = on_update
1495
return '<%s %s>' % (
1496
self.__class__.__name__,
1501
class HeaderSet(object):
1502
"""Similar to the :class:`ETags` class this implements a set-like structure.
1503
Unlike :class:`ETags` this is case insensitive and used for vary, allow, and
1504
content-language headers.
1506
If not constructed using the :func:`parse_set_header` function the
1507
instantiation works like this:
1509
>>> hs = HeaderSet(['foo', 'bar', 'baz'])
1511
HeaderSet(['foo', 'bar', 'baz'])
1514
def __init__(self, headers=None, on_update=None):
1515
self._headers = list(headers or ())
1516
self._set = set([x.lower() for x in self._headers])
1517
self.on_update = on_update
1519
def add(self, header):
1520
"""Add a new header to the set."""
1521
self.update((header,))
1523
def remove(self, header):
1524
"""Remove a layer from the set. This raises an :exc:`KeyError` if the
1525
header is not in the set.
1527
.. versionchanged:: 0.5
1528
In older versions a :exc:`IndexError` was raised instead of a
1529
:exc:`KeyError` if the object was missing.
1531
:param header: the header to be removed.
1533
key = header.lower()
1534
if key not in self._set:
1535
raise KeyError(header)
1536
self._set.remove(key)
1537
for idx, key in enumerate(self._headers):
1538
if key.lower() == header:
1539
del self._headers[idx]
1541
if self.on_update is not None:
1542
self.on_update(self)
1544
def update(self, iterable):
1545
"""Add all the headers from the iterable to the set.
1547
:param iterable: updates the set with the items from the iterable.
1549
inserted_any = False
1550
for header in iterable:
1551
key = header.lower()
1552
if key not in self._set:
1553
self._headers.append(header)
1556
if inserted_any and self.on_update is not None:
1557
self.on_update(self)
1559
def discard(self, header):
1560
"""Like :meth:`remove` but ignores errors.
1562
:param header: the header to be discarded.
1565
return self.remove(header)
1569
def find(self, header):
1570
"""Return the index of the header in the set or return -1 if not found.
1572
:param header: the header to be looked up.
1574
header = header.lower()
1575
for idx, item in enumerate(self._headers):
1576
if item.lower() == header:
1580
def index(self, header):
1581
"""Return the index of the header in the set or raise an
1584
:param header: the header to be looked up.
1586
rv = self.find(header)
1588
raise IndexError(header)
1592
"""Clear the set."""
1594
del self._headers[:]
1595
if self.on_update is not None:
1596
self.on_update(self)
1598
def as_set(self, preserve_casing=False):
1599
"""Return the set as real python set type. When calling this, all
1600
the items are converted to lowercase and the ordering is lost.
1602
:param preserve_casing: if set to `True` the items in the set returned
1603
will have the original case like in the
1604
:class:`HeaderSet`, otherwise they will
1608
return set(self._headers)
1609
return set(self._set)
1611
def to_header(self):
1612
"""Convert the header set into an HTTP header string."""
1613
return ', '.join(map(quote_header_value, self._headers))
1615
def __getitem__(self, idx):
1616
return self._headers[idx]
1618
def __delitem__(self, idx):
1619
rv = self._headers.pop(idx)
1620
self._set.remove(rv.lower())
1621
if self.on_update is not None:
1622
self.on_update(self)
1624
def __setitem__(self, idx, value):
1625
old = self._headers[idx]
1626
self._set.remove(old.lower())
1627
self._headers[idx] = value
1628
self._set.add(value.lower())
1629
if self.on_update is not None:
1630
self.on_update(self)
1632
def __contains__(self, header):
1633
return header.lower() in self._set
1636
return len(self._set)
1639
return iter(self._headers)
1641
def __nonzero__(self):
1642
return bool(self._set)
1645
return self.to_header()
1649
self.__class__.__name__,
1654
class ETags(object):
1655
"""A set that can be used to check if one etag is present in a collection
1659
def __init__(self, strong_etags=None, weak_etags=None, star_tag=False):
1660
self._strong = frozenset(not star_tag and strong_etags or ())
1661
self._weak = frozenset(weak_etags or ())
1662
self.star_tag = star_tag
1664
def as_set(self, include_weak=False):
1665
"""Convert the `ETags` object into a python set. Per default all the
1666
weak etags are not part of this set."""
1667
rv = set(self._strong)
1669
rv.update(self._weak)
1672
def is_weak(self, etag):
1673
"""Check if an etag is weak."""
1674
return etag in self._weak
1676
def contains_weak(self, etag):
1677
"""Check if an etag is part of the set including weak and strong tags."""
1678
return self.is_weak(etag) or self.contains(etag)
1680
def contains(self, etag):
1681
"""Check if an etag is part of the set ignoring weak tags."""
1684
return etag in self._strong
1686
def contains_raw(self, etag):
1687
"""When passed a quoted tag it will check if this tag is part of the
1688
set. If the tag is weak it is checked against weak and strong tags,
1689
otherwise weak only."""
1690
etag, weak = unquote_etag(etag)
1692
return self.contains_weak(etag)
1693
return self.contains(etag)
1695
def to_header(self):
1696
"""Convert the etags set into a HTTP header string."""
1700
['"%s"' % x for x in self._strong] +
1701
['w/"%s"' % x for x in self._weak]
1704
def __call__(self, etag=None, data=None, include_weak=False):
1705
if [etag, data].count(None) != 1:
1706
raise TypeError('either tag or data required, but at least one')
1708
etag = generate_etag(data)
1710
if etag in self._weak:
1712
return etag in self._strong
1714
def __nonzero__(self):
1715
return bool(self.star_tag or self._strong)
1718
return self.to_header()
1721
return iter(self._strong)
1723
def __contains__(self, etag):
1724
return self.contains(etag)
1727
return '<%s %r>' % (self.__class__.__name__, str(self))
1730
class Authorization(ImmutableDictMixin, dict):
1731
"""Represents an `Authorization` header sent by the client. You should
1732
not create this kind of object yourself but use it when it's returned by
1733
the `parse_authorization_header` function.
1735
This object is a dict subclass and can be altered by setting dict items
1736
but it should be considered immutable as it's returned by the client and
1737
not meant for modifications.
1739
.. versionchanged:: 0.5
1740
This object became immutable.
1743
def __init__(self, auth_type, data=None):
1744
dict.__init__(self, data or {})
1745
self.type = auth_type
1747
username = property(lambda x: x.get('username'), doc='''
1748
The username transmitted. This is set for both basic and digest
1749
auth all the time.''')
1750
password = property(lambda x: x.get('password'), doc='''
1751
When the authentication type is basic this is the password
1752
transmitted by the client, else `None`.''')
1753
realm = property(lambda x: x.get('realm'), doc='''
1754
This is the server realm sent back for HTTP digest auth.''')
1755
nonce = property(lambda x: x.get('nonce'), doc='''
1756
The nonce the server sent for digest auth, sent back by the client.
1757
A nonce should be unique for every 401 response for HTTP digest
1759
uri = property(lambda x: x.get('uri'), doc='''
1760
The URI from Request-URI of the Request-Line; duplicated because
1761
proxies are allowed to change the Request-Line in transit. HTTP
1762
digest auth only.''')
1763
nc = property(lambda x: x.get('nc'), doc='''
1764
The nonce count value transmitted by clients if a qop-header is
1765
also transmitted. HTTP digest auth only.''')
1766
cnonce = property(lambda x: x.get('cnonce'), doc='''
1767
If the server sent a qop-header in the ``WWW-Authenticate``
1768
header, the client has to provide this value for HTTP digest auth.
1769
See the RFC for more details.''')
1770
response = property(lambda x: x.get('response'), doc='''
1771
A string of 32 hex digits computed as defined in RFC 2617, which
1772
proves that the user knows a password. Digest auth only.''')
1773
opaque = property(lambda x: x.get('opaque'), doc='''
1774
The opaque header from the server returned unchanged by the client.
1775
It is recommended that this string be base64 or hexadecimal data.
1776
Digest auth only.''')
1780
"""Indicates what "quality of protection" the client has applied to
1781
the message for HTTP digest auth."""
1782
def on_update(header_set):
1783
if not header_set and 'qop' in self:
1786
self['qop'] = header_set.to_header()
1787
return parse_set_header(self.get('qop'), on_update)
1790
class WWWAuthenticate(UpdateDictMixin, dict):
1791
"""Provides simple access to `WWW-Authenticate` headers."""
1793
#: list of keys that require quoting in the generated header
1794
_require_quoting = frozenset(['domain', 'nonce', 'opaque', 'realm'])
1796
def __init__(self, auth_type=None, values=None, on_update=None):
1797
dict.__init__(self, values or ())
1799
self['__auth_type__'] = auth_type
1800
self.on_update = on_update
1802
def set_basic(self, realm='authentication required'):
1803
"""Clear the auth info and enable basic auth."""
1805
dict.update(self, {'__auth_type__': 'basic', 'realm': realm})
1807
self.on_update(self)
1809
def set_digest(self, realm, nonce, qop=('auth',), opaque=None,
1810
algorithm=None, stale=False):
1811
"""Clear the auth info and enable digest auth."""
1813
'__auth_type__': 'digest',
1816
'qop': dump_header(qop)
1820
if opaque is not None:
1821
d['opaque'] = opaque
1822
if algorithm is not None:
1823
d['algorithm'] = algorithm
1825
dict.update(self, d)
1827
self.on_update(self)
1829
def to_header(self):
1830
"""Convert the stored values into a WWW-Authenticate header."""
1832
auth_type = d.pop('__auth_type__', None) or 'basic'
1833
return '%s %s' % (auth_type.title(), ', '.join([
1834
'%s=%s' % (key, quote_header_value(value,
1835
allow_token=key not in self._require_quoting))
1836
for key, value in d.iteritems()
1840
return self.to_header()
1843
return '<%s %r>' % (
1844
self.__class__.__name__,
1848
def auth_property(name, doc=None):
1849
"""A static helper function for subclasses to add extra authentication
1850
system properites onto a class::
1852
class FooAuthenticate(WWWAuthenticate):
1853
special_realm = auth_property('special_realm')
1855
For more information have a look at the sourcecode to see how the
1856
regular properties (:attr:`realm` etc. are implemented).
1858
def _set_value(self, value):
1860
self.pop(name, None)
1862
self[name] = str(value)
1863
return property(lambda x: x.get(name), _set_value, doc=doc)
1865
def _set_property(name, doc=None):
1867
def on_update(header_set):
1868
if not header_set and name in self:
1871
self[name] = header_set.to_header()
1872
return parse_set_header(self.get(name), on_update)
1873
return property(fget, doc=doc)
1875
type = auth_property('__auth_type__', doc='''
1876
The type of the auth mechanism. HTTP currently specifies
1877
`Basic` and `Digest`.''')
1878
realm = auth_property('realm', doc='''
1879
A string to be displayed to users so they know which username and
1880
password to use. This string should contain at least the name of
1881
the host performing the authentication and might additionally
1882
indicate the collection of users who might have access.''')
1883
domain = _set_property('domain', doc='''
1884
A list of URIs that define the protection space. If a URI is an
1885
absolute path, it is relative to the canonical root URL of the
1886
server being accessed.''')
1887
nonce = auth_property('nonce', doc='''
1888
A server-specified data string which should be uniquely generated
1889
each time a 401 response is made. It is recommended that this
1890
string be base64 or hexadecimal data.''')
1891
opaque = auth_property('opaque', doc='''
1892
A string of data, specified by the server, which should be returned
1893
by the client unchanged in the Authorization header of subsequent
1894
requests with URIs in the same protection space. It is recommended
1895
that this string be base64 or hexadecimal data.''')
1896
algorithm = auth_property('algorithm', doc='''
1897
A string indicating a pair of algorithms used to produce the digest
1898
and a checksum. If this is not present it is assumed to be "MD5".
1899
If the algorithm is not understood, the challenge should be ignored
1900
(and a different one used, if there is more than one).''')
1901
qop = _set_property('qop', doc='''
1902
A set of quality-of-privacy modifies such as auth and auth-int.''')
1904
def _get_stale(self):
1905
val = self.get('stale')
1907
return val.lower() == 'true'
1908
def _set_stale(self, value):
1910
self.pop('stale', None)
1912
self['stale'] = value and 'TRUE' or 'FALSE'
1913
stale = property(_get_stale, _set_stale, doc='''
1914
A flag, indicating that the previous request from the client was
1915
rejected because the nonce value was stale.''')
1916
del _get_stale, _set_stale
1918
# make auth_property a staticmethod so that subclasses of
1919
# `WWWAuthenticate` can use it for new properties.
1920
auth_property = staticmethod(auth_property)
1924
# circular dependencies
1925
from werkzeug.http import dump_options_header, dump_header, generate_etag, \
1926
quote_header_value, parse_set_header, unquote_etag
1929
# create all the special key errors now that the classes are defined.
1930
from werkzeug.exceptions import BadRequest
1931
for _cls in MultiDict, CombinedMultiDict, Headers, EnvironHeaders:
1932
_cls.KeyError = BadRequest.wrap(KeyError, _cls.__name__ + '.KeyError')