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
|
import pytest
from webob.util import html_escape
from webob.multidict import MultiDict
from webob.compat import (
text_,
PY3
)
def test_html_escape():
if PY3:
EXPECTED_LT = 'expected a '<'.'
else:
EXPECTED_LT = "expected a '<'."
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/)
(text_('the majestic m\xf8ose'), 'the majestic møose'),
# ("'", "'")
# 8-bit strings are passed through
(text_('\xe9'), 'é'),
# (text_(b'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_LT),
# If an object implements both ``__str__`` and ``__unicode__``, the latter
# is preferred
(t_esc_SuperMoose(), 'møose'),
(t_esc_Unicode(), 'é'),
(t_esc_UnsafeAttrs(), '<UnsafeAttrs>'),
]:
assert 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 text_(b'\xe9')
class t_esc_UnsafeAttrs(object):
attr = 'value'
def __getattr__(self, k):
return self.attr
def __repr__(self):
return '<UnsafeAttrs>'
class t_esc_SuperMoose(object):
def __str__(self):
return text_(b'm\xf8ose').encode('utf-8')
def __unicode__(self):
return text_(b'm\xf8ose')
def test_multidict():
d = MultiDict(a=1, b=2)
assert d['a'] == 1
assert d.getall('c') == []
d.add('a', 2)
assert d['a'] == 2
assert d.getall('a') == [1, 2]
d['b'] = 4
assert d.getall('b') == [4]
assert list(d.keys()) == ['a', 'a', 'b']
assert list(d.items()) == [('a', 1), ('a', 2), ('b', 4)]
assert d.mixed() == {'a': [1, 2], 'b': 4}
# test getone
# KeyError: "Multiple values match 'a': [1, 2]"
with pytest.raises(KeyError):
d.getone('a')
assert d.getone('b') == 4
# KeyError: "Key not found: 'g'"
with pytest.raises(KeyError):
d.getone('g')
assert 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)
assert d == MultiDict([('a', 4), ('a', 5), ('f', 42)])
f = d.pop('a')
assert f == 4
assert d['a'] == 5
assert d.pop('g', 42) == 42
with pytest.raises(KeyError):
d.pop('n')
# TypeError: pop expected at most 2 arguments, got 3
with pytest.raises(TypeError):
d.pop(4, 2, 3)
d.setdefault('g', []).append(4)
assert d == MultiDict([('a', 5), ('f', 42), ('g', [4])])
def test_multidict_init():
d = MultiDict([('a', 'b')], c=2)
assert repr(d) == "MultiDict([('a', 'b'), ('c', 2)])"
assert d == MultiDict([('a', 'b')], c=2)
# TypeError: MultiDict can only be called with one positional argument
with pytest.raises(TypeError):
MultiDict(1, 2, 3)
# TypeError: MultiDict.view_list(obj) takes only actual list objects, not None
with pytest.raises(TypeError):
MultiDict.view_list(None)
|