# HG changeset patch # User Thomas Waldmann # Date 1240094775 -7200 # Node ID bd3f5ccf6fb64f06e982a8baf2e8eb5362cf1751 # Parent 3e4e67bcbeddeb4ba5ea3cac17777ba48b9e7089 updated werkzeug diff -r 3e4e67bcbedd -r bd3f5ccf6fb6 MoinMoin/support/werkzeug/datastructures.py --- a/MoinMoin/support/werkzeug/datastructures.py Sun Apr 19 00:38:06 2009 +0200 +++ b/MoinMoin/support/werkzeug/datastructures.py Sun Apr 19 00:46:15 2009 +0200 @@ -238,11 +238,6 @@ or `None`. """ - # internal list type. This is an internal interface! do not use. - # it's only used in methods that do not modify the multi dict so that - # ImmutableMultiDict can use it without much hassle. - _list_type = list - # the key error this class raises. Because of circular dependencies # with the http exception module this class is created at the end of # this module. @@ -250,23 +245,21 @@ def __init__(self, mapping=None): if isinstance(mapping, MultiDict): - dict.__init__(self, ((k, self._list_type(v)) - for k, v in mapping.lists())) + dict.__init__(self, ((k, l[:]) for k, l in mapping.lists())) elif isinstance(mapping, dict): tmp = {} for key, value in mapping.iteritems(): if isinstance(value, (tuple, list)): - value = self._list_type(value) + value = list(value) else: - value = self._list_type([value]) + value = [value] tmp[key] = value dict.__init__(self, tmp) else: tmp = {} for key, value in mapping or (): tmp.setdefault(key, []).append(value) - dict.__init__(self, (dict((k, self._list_type(v)) - for k, v in tmp.iteritems()))) + dict.__init__(self, tmp) def __getitem__(self, key): """Return the first data value for this key; @@ -298,16 +291,16 @@ try: rv = dict.__getitem__(self, key) except KeyError: - return self._list_type() + return [] if type is None: - return rv + return list(rv) result = [] for item in rv: try: result.append(type(item)) except ValueError: pass - return self._list_type(result) + return result def setlist(self, key, new_list): """Remove the old values for a key and add new ones. Note that the list @@ -341,8 +334,16 @@ default = self[key] return default - def setlistdefault(self, key, default_list=()): - """Like `setdefault` but sets multiple values. + def setlistdefault(self, key, default_list=None): + """Like `setdefault` but sets multiple values. The list returned + is not a copy, but the list that is actually used internally. This + means that you can put new values into the dict by appending items + to the list: + + >>> d = MultiDict({"foo": 1}) + >>> d.setlistdefault("foo").extend([2, 3]) + >>> d.getlist("foo") + [1, 2, 3] :param key: The key to be looked up. :param default: An iterable of default values. It is either copied @@ -351,10 +352,10 @@ :return: a :class:`list` """ if key not in self: - default_list = list(default_list) + default_list = list(default_list or ()) dict.__setitem__(self, key, default_list) else: - default_list = self.getlist(key) + default_list = dict.__getitem__(self, key) return default_list def items(self): @@ -378,33 +379,40 @@ """ return [self[key] for key in self.iterkeys()] - #: Return a list of all values associated with a key. Zipping - #: :meth:`keys` and this is the same as calling :meth:`lists`: - #: - #: >>> d = MultiDict({"foo": [1, 2, 3]}) - #: >>> zip(d.keys(), d.listvalues()) == d.lists() - #: True - #: - #: :return: a :class:`list` - listvalues = dict.values + def listvalues(self): + """Return a list of all values associated with a key. Zipping + :meth:`keys` and this is the same as calling :meth:`lists`: + + >>> d = MultiDict({"foo": [1, 2, 3]}) + >>> zip(d.keys(), d.listvalues()) == d.lists() + True + + :return: a :class:`list` + """ + return list(self.iterlistvalues()) def iteritems(self): """Like :meth:`items` but returns an iterator.""" for key, values in dict.iteritems(self): yield key, values[0] - #: Return a list of all values associated with a key. - #: - #: :return: a :class:`list` - iterlists = dict.iteritems + def iterlists(self): + """Return a list of all values associated with a key. + + :return: a class:`list` + """ + for key, values in dict.iteritems(self): + yield key, list(values) def itervalues(self): """Like :meth:`values` but returns an iterator.""" for values in dict.itervalues(self): yield values[0] - #: like :meth:`listvalues` but returns an iterator. - iterlistvalues = dict.itervalues + def iterlistvalues(self): + """like :meth:`listvalues` but returns an iterator.""" + for values in dict.itervalues(self): + yield list(values) def copy(self): """Return a shallow copy of this object.""" @@ -932,8 +940,6 @@ exceptions. """ - _list_type = ImmutableList - def __init__(self, dicts=None): self.dicts = dicts or [] @@ -963,7 +969,7 @@ rv = [] for d in self.dicts: rv.extend(d.getlist(key, type)) - return self._list_type(rv) + return rv def keys(self): rv = set() @@ -994,8 +1000,7 @@ for d in self.dicts: for key, values in d.iterlists(): rv.setdefault(key, []).extend(values) - for key, values in rv.iteritems(): - yield key, ImmutableList(values) + return rv.iteritems() def lists(self): return list(self.iterlists()) @@ -1086,14 +1091,11 @@ class ImmutableMultiDict(ImmutableMultiDictMixin, MultiDict): - """An immutable :class:`MultiDict`. The methods that return the internal - lists return :class:`ImmutableList` objects. + """An immutable :class:`MultiDict`. .. versionadded:: 0.5 """ - _list_type = ImmutableList - class Accept(ImmutableList): """An :class:`Accept` object is just a list subclass for lists of diff -r 3e4e67bcbedd -r bd3f5ccf6fb6 MoinMoin/support/werkzeug/test.py --- a/MoinMoin/support/werkzeug/test.py Sun Apr 19 00:38:06 2009 +0200 +++ b/MoinMoin/support/werkzeug/test.py Sun Apr 19 00:46:15 2009 +0200 @@ -22,7 +22,7 @@ from werkzeug._internal import _empty_stream from werkzeug.wrappers import BaseRequest from werkzeug.utils import create_environ, run_wsgi_app, get_current_url, \ - url_encode, url_decode, FileStorage + url_encode, url_decode, FileStorage, get_host from werkzeug.datastructures import FileMultiDict, MultiDict, \ CombinedMultiDict, Headers @@ -628,16 +628,33 @@ if self.cookie_jar is not None: self.cookie_jar.extract_wsgi(environ, rv[2]) - if rv[0].status_code in (301, 302, 303, 305, 307) and follow_redirects: - redirect = urlparse.urlunsplit(urlparse.urlsplit( - dict(rv[2])['Location'])[:-2] + ('', '')) + # handle redirects + redirect_chain = [] + status_code = int(rv[1].split(None, 1)[0]) + while status_code in (301, 302, 303, 305, 307) and follow_redirects: + redirect = dict(rv[2])['Location'] + host = get_host(create_environ('/', redirect)) + if get_host(environ).split(':', 1)[0] != host: + raise RuntimeError('%r does not support redirect to ' + 'external targets' % self.__class__) + + scheme, netloc, script_root, qs, anchor = urlparse.urlsplit(redirect) + redirect_chain.append((redirect, status_code)) + kwargs.update({ - 'base_url': redirect, + 'base_url': urlparse.urlunsplit((scheme, host, + script_root, '', '')).rstrip('/') + '/', + 'query_string': qs, 'as_tuple': as_tuple, 'buffered': buffered, - 'follow_redirects': True + 'follow_redirects': False }) - return self.open(*args, **kwargs) + rv = self.open(*args, **kwargs) + status_code = int(rv[1].split(None, 1)[0]) + + # Prevent loops + if redirect_chain[-1] in redirect_chain[0:-1]: + break response = self.response_wrapper(*rv) if as_tuple: diff -r 3e4e67bcbedd -r bd3f5ccf6fb6 MoinMoin/support/werkzeug/useragents.py --- a/MoinMoin/support/werkzeug/useragents.py Sun Apr 19 00:38:06 2009 +0200 +++ b/MoinMoin/support/werkzeug/useragents.py Sun Apr 19 00:46:15 2009 +0200 @@ -98,11 +98,49 @@ .. attribute:: platform - the browser platform + the browser platform. The following platforms are currently + recognized: + + - `aix` + - `amiga` + - `android` + - `bsd` + - `hpux` + - `iphone` + - `irix` + - `linux` + - `macos` + - `sco` + - `solaris` + - `wii` + - `windows` .. attribute:: browser - the name of the browser + the name of the browser. The following browsers are currently + recognized: + + - `aol` * + - `ask` * + - `camino` + - `chrome` + - `firefox` + - `galeon` + - `google` * + - `kmeleon` + - `konqueror` + - `links` + - `lynx` + - `msie` + - `msn` + - `netscape` + - `opera` + - `safari` + - `seamonkey` + - `webkit` + - `yahoo` * + + (Browsers maked with a star (``*``) are crawlers.) .. attribute:: version diff -r 3e4e67bcbedd -r bd3f5ccf6fb6 MoinMoin/support/werkzeug/utils.py --- a/MoinMoin/support/werkzeug/utils.py Sun Apr 19 00:38:06 2009 +0200 +++ b/MoinMoin/support/werkzeug/utils.py Sun Apr 19 00:46:15 2009 +0200 @@ -1109,7 +1109,7 @@ def secure_filename(filename): - """Pass it a filename and it will return a secure version of it. This + r"""Pass it a filename and it will return a secure version of it. This filename can then savely be stored on a regular file system and passed to :func:`os.path.join`. The filename returned is an ASCII only string for maximum portability. @@ -1510,9 +1510,7 @@ if ':' in import_name: module, obj = import_name.split(':', 1) elif '.' in import_name: - items = import_name.split('.') - module = '.'.join(items[:-1]) - obj = items[-1] + module, obj = import_name.rsplit('.', 1) else: return __import__(import_name) return getattr(__import__(module, None, None, [obj]), obj)