summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpjenvey <devnull@localhost>2007-01-22 03:50:53 +0000
committerpjenvey <devnull@localhost>2007-01-22 03:50:53 +0000
commit09df81aa57e768c5d0f6b26b23e9f9f02096ec6b (patch)
treee2fcd98ca3e00dda71dece3ac2489f579ad70040
parent4a2ca4cc0bdaa79a00f6a4979d43be59b03063bf (diff)
downloadpaste-09df81aa57e768c5d0f6b26b23e9f9f02096ec6b.tar.gz
by default don't have WSGIRequest decode parameter keys when unicode params are expected.
allow this behavior when WSGIRequest.decode_param_names is enabled
-rw-r--r--paste/util/multidict.py45
-rw-r--r--paste/wsgiwrappers.py25
-rw-r--r--tests/test_multidict.py30
3 files changed, 65 insertions, 35 deletions
diff --git a/paste/util/multidict.py b/paste/util/multidict.py
index 2a9a4d8..40d021a 100644
--- a/paste/util/multidict.py
+++ b/paste/util/multidict.py
@@ -203,23 +203,34 @@ class MultiDict(DictMixin):
class UnicodeMultiDict(DictMixin):
"""
- A MultiDict wrapper that decodes returned key/values to unicode on the
- fly. Decoding is not applied to assigned key/values.
+ A MultiDict wrapper that decodes returned values to unicode on the
+ fly. Decoding is not applied to assigned values.
The key/value contents are assumed to be ``str``/``strs`` or
``str``/``FieldStorages`` (as is returned by the paste.request.parse_
functions).
- ``FieldStorage`` instances are cloned, and the clone's ``name`` and
- ``filename`` variables are decoded.
+ Can optionally also decode keys when the ``decode_keys`` argument is
+ True.
+
+ ``FieldStorage`` instances are cloned, and the clone's ``filename``
+ variable is decoded. Its ``name`` variable is decoded when ``decode_keys``
+ is enabled.
"""
- def __init__(self, multi=None, encoding=None, errors='strict'):
+ def __init__(self, multi=None, encoding=None, errors='strict',
+ decode_keys=False):
self.multi = multi
if encoding is None:
encoding = sys.getdefaultencoding()
self.encoding = encoding
self.errors = errors
+ self.decode_keys = decode_keys
+
+ def _decode_key(self, key):
+ if self.decode_keys:
+ key = key.decode(self.encoding, self.errors)
+ return key
def _decode_value(self, value):
"""
@@ -231,7 +242,8 @@ class UnicodeMultiDict(DictMixin):
if isinstance(value, cgi.FieldStorage):
# decode FieldStorage's field name and filename
value = copy.copy(value)
- value.name = value.name.decode(self.encoding, self.errors)
+ if self.decode_keys:
+ value.name = value.name.decode(self.encoding, self.errors)
value.filename = value.filename.decode(self.encoding, self.errors)
else:
try:
@@ -279,8 +291,7 @@ class UnicodeMultiDict(DictMixin):
value = [self._decode_value(value) for value in value]
else:
value = self._decode_value(value)
- unicode_mixed[key.decode(self.encoding, self.errors)] = \
- value
+ unicode_mixed[self._decode_key(key)] = value
return unicode_mixed
def dict_of_lists(self):
@@ -291,8 +302,7 @@ class UnicodeMultiDict(DictMixin):
unicode_dict = {}
for key, value in self.multi.dict_of_lists().iteritems():
value = [self._decode_value(value) for value in value]
- unicode_dict[key.decode(self.encoding, self.errors)] = \
- value
+ unicode_dict[self._decode_key(key)] = value
return unicode_dict
def __delitem__(self, key):
@@ -317,8 +327,7 @@ class UnicodeMultiDict(DictMixin):
def popitem(self):
k, v = self.multi.popitem()
- return (k.decode(self.encoding, self.errors),
- self._decode_value(v))
+ return (self._decode_key(k), self._decode_value(v))
def __repr__(self):
items = ', '.join(['(%r, %r)' % v for v in self.items()])
@@ -332,23 +341,21 @@ class UnicodeMultiDict(DictMixin):
##
def keys(self):
- return [k.decode(self.encoding, self.errors) for \
- k in self.multi.iterkeys()]
+ return [self._decode_key(k) for k in self.multi.iterkeys()]
def iterkeys(self):
for k in self.multi.iterkeys():
- yield k.decode(self.encoding, self.errors)
+ yield self._decode_key(k)
__iter__ = iterkeys
def items(self):
- return [(k.decode(self.encoding, self.errors), self._decode_value(v)) \
- for k, v in self.multi.iteritems()]
+ return [(self._decode_key(k), self._decode_value(v)) for \
+ k, v in self.multi.iteritems()]
def iteritems(self):
for k, v in self.multi.iteritems():
- yield (k.decode(self.encoding, self.errors),
- self._decode_value(v))
+ yield (self._decode_key(k), self._decode_value(v))
def values(self):
return [self._decode_value(v) for v in self.multi.itervalues()]
diff --git a/paste/wsgiwrappers.py b/paste/wsgiwrappers.py
index 2e7a667..15ad1c1 100644
--- a/paste/wsgiwrappers.py
+++ b/paste/wsgiwrappers.py
@@ -57,10 +57,14 @@ class WSGIRequest(object):
to express nothing beyond what is available in the environment
dictionary.
- The only state maintained in this object is the desired ``charset``
- and its associated ``errors`` handler. The incoming parameters will
- be automatically coerced to unicode objects of the ``charset``
- encoding when ``charset`` is set.
+ The only state maintained in this object is the desired ``charset``,
+ its associated ``errors`` handler, and the ``decode_param_names``
+ option.
+
+ The incoming parameter values will be automatically coerced to unicode
+ objects of the ``charset`` encoding when ``charset`` is set. The
+ incoming parameter names are not decoded to unicode unless the
+ ``decode_param_names`` option is enabled.
When unicode is expected, ``charset`` will overridden by the the
value of the ``Content-Type`` header's charset parameter if one was
@@ -76,7 +80,8 @@ class WSGIRequest(object):
You are free to subclass this object.
"""
- defaults = StackedObjectProxy(default=dict(charset=None, errors='strict'))
+ defaults = StackedObjectProxy(default=dict(charset=None, errors='strict',
+ decode_param_names=False))
def __init__(self, environ):
self.environ = environ
# This isn't "state" really, since the object is derivative:
@@ -91,6 +96,7 @@ class WSGIRequest(object):
if browser_charset:
self.charset = browser_charset
self.errors = defaults.get('errors', 'strict')
+ self.decode_param_names = defaults.get('decode_param_names', False)
body = environ_getter('wsgi.input')
scheme = environ_getter('wsgi.url_scheme')
@@ -127,7 +133,8 @@ class WSGIRequest(object):
params = self._GET()
if self.charset:
params = UnicodeMultiDict(params, encoding=self.charset,
- errors=self.errors)
+ errors=self.errors,
+ decode_keys=self.decode_param_names)
return params
GET = property(GET, doc=GET.__doc__)
@@ -153,7 +160,8 @@ class WSGIRequest(object):
params = self._POST()
if self.charset:
params = UnicodeMultiDict(params, encoding=self.charset,
- errors=self.errors)
+ errors=self.errors,
+ decode_keys=self.decode_param_names)
return params
POST = property(POST, doc=POST.__doc__)
@@ -177,7 +185,8 @@ class WSGIRequest(object):
params.update(self._GET())
if self.charset:
params = UnicodeMultiDict(params, encoding=self.charset,
- errors=self.errors)
+ errors=self.errors,
+ decode_keys=self.decode_param_names)
return params
params = property(params, doc=params.__doc__)
diff --git a/tests/test_multidict.py b/tests/test_multidict.py
index a6787e8..76ffe0e 100644
--- a/tests/test_multidict.py
+++ b/tests/test_multidict.py
@@ -48,19 +48,33 @@ def test_dict():
assert dcopy != d
def test_unicode_dict():
+ _test_unicode_dict()
+ _test_unicode_dict(decode_param_names=True)
+
+def _test_unicode_dict(decode_param_names=False):
+ d = UnicodeMultiDict(MultiDict({'a': 'a test'}))
+ d.encoding = 'utf-8'
+ d.errors = 'ignore'
+
+ if decode_param_names:
+ key_str = unicode
+ d.decode_keys = True
+ else:
+ key_str = str
+
def assert_unicode(obj):
assert isinstance(obj, unicode)
+ def assert_key_str(obj):
+ assert isinstance(obj, key_str)
+
def assert_unicode_items(obj):
key, value = obj
- assert isinstance(key, unicode)
+ assert isinstance(key, key_str)
assert isinstance(value, unicode)
- d = UnicodeMultiDict(MultiDict({'a': 'a test'}))
- d.encoding = 'utf-8'
- d.errors = 'ignore'
assert d.items() == [('a', u'a test')]
- map(assert_unicode, d.keys())
+ map(assert_key_str, d.keys())
map(assert_unicode, d.values())
d['b'] = '2 test'
@@ -89,7 +103,7 @@ def test_unicode_dict():
assert isinstance(d.getone('a'), unicode)
assert d.popitem() == ('c', u'3 test')
d['c'] = '3 test'
- map(assert_unicode, d.popitem())
+ assert_unicode_items(d.popitem())
assert d.items() == [('a', u'a test')]
map(assert_unicode_items, d.items())
@@ -97,7 +111,7 @@ def test_unicode_dict():
assert d.setdefault('z', item) is item
items = d.items()
assert items == [('a', u'a test'), ('z', item)]
- assert isinstance(items[1][0], unicode)
+ assert isinstance(items[1][0], key_str)
assert isinstance(items[1][1], list)
assert isinstance(d.setdefault('y', 'y test'), unicode)
@@ -127,7 +141,7 @@ def test_unicode_dict():
assert isinstance(ufs, cgi.FieldStorage)
assert ufs is not fs
assert ufs.name == fs.name
- assert isinstance(ufs.name, unicode)
+ assert isinstance(ufs.name, key_str)
assert ufs.filename == fs.filename
assert isinstance(ufs.filename, unicode)
assert isinstance(ufs.value, str)