1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
import cgi, sys
from cStringIO import StringIO
from webob import html_escape, Response
from webob.multidict import *
from nose.tools import eq_ as eq, assert_raises
def test_html_escape():
for v, s in [
# unsafe chars
('these chars: < > & "', 'these chars: < > & "'),
(' ', ' '),
('è', '&egrave;'),
# The apostrophe is *not* escaped, which some might consider to be
# a serious bug (see, e.g. http://www.cvedetails.com/cve/CVE-2010-2480/)
(u'the majestic m\xf8ose', 'the majestic møose'),
#("'", "'")
# 8-bit strings are passed through
(u'\xe9', 'é'),
(u'the majestic m\xf8ose'.encode('utf-8'), 'the majestic m\xc3\xb8ose'),
# ``None`` is treated specially, and returns the empty string.
(None, ''),
# Objects that define a ``__html__`` method handle their own escaping
(t_esc_HTML(), '<div>hello</div>'),
# Things that are not strings are converted to strings and then escaped
(42, '42'),
(Exception("expected a '<'."), "expected a '<'."),
# If an object implements both ``__str__`` and ``__unicode__``, the latter
# is preferred
(t_esc_SuperMoose(), 'møose'),
(t_esc_Unicode(), 'é'),
(t_esc_UnsafeAttrs(), '<UnsafeAttrs>'),
]:
eq(html_escape(v), s)
class t_esc_HTML(object):
def __html__(self):
return '<div>hello</div>'
class t_esc_Unicode(object):
def __unicode__(self):
return u'\xe9'
class t_esc_UnsafeAttrs(object):
attr = 'value'
def __getattr__(self):
return self.attr
def __repr__(self):
return '<UnsafeAttrs>'
class t_esc_SuperMoose(object):
def __str__(self):
return u'm\xf8ose'.encode('UTF-8')
def __unicode__(self):
return u'm\xf8ose'
def test_multidict():
d = MultiDict(a=1, b=2)
eq(d['a'], 1)
eq(d.getall('c'), [])
d.add('a', 2)
eq(d['a'], 2)
eq(d.getall('a'), [1, 2])
d['b'] = 4
eq(d.getall('b'), [4])
eq(d.keys(), ['a', 'a', 'b'])
eq(d.items(), [('a', 1), ('a', 2), ('b', 4)])
eq(d.mixed(), {'a': [1, 2], 'b': 4})
# test getone
# KeyError: "Multiple values match 'a': [1, 2]"
assert_raises(KeyError, d.getone, 'a')
eq(d.getone('b'), 4)
# KeyError: "Key not found: 'g'"
assert_raises(KeyError, d.getone, 'g')
eq(d.dict_of_lists(), {'a': [1, 2], 'b': [4]})
assert 'b' in d
assert 'e' not in d
d.clear()
assert 'b' not in d
d['a'] = 4
d.add('a', 5)
e = d.copy()
assert 'a' in e
e.clear()
e['f'] = 42
d.update(e)
eq(d, MultiDict([('a', 4), ('a', 5), ('f', 42)]))
f = d.pop('a')
eq(f, 4)
eq(d['a'], 5)
eq(d.pop('g', 42), 42)
assert_raises(KeyError, d.pop, 'n')
# TypeError: pop expected at most 2 arguments, got 3
assert_raises(TypeError, d.pop, 4, 2, 3)
d.setdefault('g', []).append(4)
eq(d, MultiDict([('a', 5), ('f', 42), ('g', [4])]))
def test_multidict_init():
d = MultiDict([('a', 'b')], c=2)
eq(repr(d), "MultiDict([('a', 'b'), ('c', 2)])")
eq(d, MultiDict([('a', 'b')], c=2))
# TypeError: MultiDict can only be called with one positional argument
assert_raises(TypeError, MultiDict, 1, 2, 3)
# TypeError: MultiDict.view_list(obj) takes only actual list objects, not None
assert_raises(TypeError, MultiDict.view_list, None)
def test_multidict_cgi():
env = {'QUERY_STRING': ''}
fs = cgi.FieldStorage(environ=env)
fs.filename = '\xc3\xb8'
plain = MultiDict(key='\xc3\xb8', fs=fs)
ua = UnicodeMultiDict(multi=plain, encoding='utf-8')
eq(ua.getall('key'), [u'\xf8'])
eq(repr(ua.getall('fs')), "[FieldStorage(None, u'\\xf8', [])]")
ub = UnicodeMultiDict(multi=ua, encoding='utf-8')
eq(ub.getall('key'), [u'\xf8'])
eq(repr(ub.getall('fs')), "[FieldStorage(None, u'\\xf8', [])]")
|