python (3.12.0)
1 import unittest
2 import sys
3 from collections import OrderedDict, UserDict
4 from types import MappingProxyType
5 from test import support
6 from test.support import import_helper
7 import _testcapi
8
9
10 NULL = None
11
12 class ESC[4;38;5;81mDictSubclass(ESC[4;38;5;149mdict):
13 def __getitem__(self, key):
14 raise RuntimeError('do not get evil')
15 def __setitem__(self, key, value):
16 raise RuntimeError('do not set evil')
17 def __delitem__(self, key):
18 raise RuntimeError('do not del evil')
19
20 def gen():
21 yield 'a'
22 yield 'b'
23 yield 'c'
24
25
26 class ESC[4;38;5;81mCAPITest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
27
28 def test_dict_check(self):
29 check = _testcapi.dict_check
30 self.assertTrue(check({1: 2}))
31 self.assertTrue(check(OrderedDict({1: 2})))
32 self.assertFalse(check(UserDict({1: 2})))
33 self.assertFalse(check([1, 2]))
34 self.assertFalse(check(object()))
35 #self.assertFalse(check(NULL))
36
37 def test_dict_checkexact(self):
38 check = _testcapi.dict_checkexact
39 self.assertTrue(check({1: 2}))
40 self.assertFalse(check(OrderedDict({1: 2})))
41 self.assertFalse(check(UserDict({1: 2})))
42 self.assertFalse(check([1, 2]))
43 self.assertFalse(check(object()))
44 #self.assertFalse(check(NULL))
45
46 def test_dict_new(self):
47 dict_new = _testcapi.dict_new
48 dct = dict_new()
49 self.assertEqual(dct, {})
50 self.assertIs(type(dct), dict)
51 dct2 = dict_new()
52 self.assertIsNot(dct2, dct)
53
54 def test_dictproxy_new(self):
55 dictproxy_new = _testcapi.dictproxy_new
56 for dct in {1: 2}, OrderedDict({1: 2}), UserDict({1: 2}):
57 proxy = dictproxy_new(dct)
58 self.assertIs(type(proxy), MappingProxyType)
59 self.assertEqual(proxy, dct)
60 with self.assertRaises(TypeError):
61 proxy[1] = 3
62 self.assertEqual(proxy[1], 2)
63 dct[1] = 4
64 self.assertEqual(proxy[1], 4)
65
66 self.assertRaises(TypeError, dictproxy_new, [])
67 self.assertRaises(TypeError, dictproxy_new, 42)
68 # CRASHES dictproxy_new(NULL)
69
70 def test_dict_copy(self):
71 copy = _testcapi.dict_copy
72 for dct in {1: 2}, OrderedDict({1: 2}):
73 dct_copy = copy(dct)
74 self.assertIs(type(dct_copy), dict)
75 self.assertEqual(dct_copy, dct)
76
77 self.assertRaises(SystemError, copy, UserDict())
78 self.assertRaises(SystemError, copy, [])
79 self.assertRaises(SystemError, copy, 42)
80 self.assertRaises(SystemError, copy, NULL)
81
82 def test_dict_clear(self):
83 clear = _testcapi.dict_clear
84 dct = {1: 2}
85 clear(dct)
86 self.assertEqual(dct, {})
87
88 # NOTE: It is not safe to call it with OrderedDict.
89
90 # Has no effect for non-dicts.
91 dct = UserDict({1: 2})
92 clear(dct)
93 self.assertEqual(dct, {1: 2})
94 lst = [1, 2]
95 clear(lst)
96 self.assertEqual(lst, [1, 2])
97 clear(object())
98
99 # CRASHES? clear(NULL)
100
101 def test_dict_size(self):
102 size = _testcapi.dict_size
103 self.assertEqual(size({1: 2}), 1)
104 self.assertEqual(size(OrderedDict({1: 2})), 1)
105
106 self.assertRaises(SystemError, size, UserDict())
107 self.assertRaises(SystemError, size, [])
108 self.assertRaises(SystemError, size, 42)
109 self.assertRaises(SystemError, size, object())
110 self.assertRaises(SystemError, size, NULL)
111
112 def test_dict_getitem(self):
113 getitem = _testcapi.dict_getitem
114 dct = {'a': 1, '\U0001f40d': 2}
115 self.assertEqual(getitem(dct, 'a'), 1)
116 self.assertIs(getitem(dct, 'b'), KeyError)
117 self.assertEqual(getitem(dct, '\U0001f40d'), 2)
118
119 dct2 = DictSubclass(dct)
120 self.assertEqual(getitem(dct2, 'a'), 1)
121 self.assertIs(getitem(dct2, 'b'), KeyError)
122
123 self.assertIs(getitem({}, []), KeyError) # unhashable
124 self.assertIs(getitem(42, 'a'), KeyError)
125 self.assertIs(getitem([1], 0), KeyError)
126 # CRASHES getitem({}, NULL)
127 # CRASHES getitem(NULL, 'a')
128
129 def test_dict_getitemstring(self):
130 getitemstring = _testcapi.dict_getitemstring
131 dct = {'a': 1, '\U0001f40d': 2}
132 self.assertEqual(getitemstring(dct, b'a'), 1)
133 self.assertIs(getitemstring(dct, b'b'), KeyError)
134 self.assertEqual(getitemstring(dct, '\U0001f40d'.encode()), 2)
135
136 dct2 = DictSubclass(dct)
137 self.assertEqual(getitemstring(dct2, b'a'), 1)
138 self.assertIs(getitemstring(dct2, b'b'), KeyError)
139
140 self.assertIs(getitemstring({}, b'\xff'), KeyError)
141 self.assertIs(getitemstring(42, b'a'), KeyError)
142 self.assertIs(getitemstring([], b'a'), KeyError)
143 # CRASHES getitemstring({}, NULL)
144 # CRASHES getitemstring(NULL, b'a')
145
146 def test_dict_getitemwitherror(self):
147 getitem = _testcapi.dict_getitemwitherror
148 dct = {'a': 1, '\U0001f40d': 2}
149 self.assertEqual(getitem(dct, 'a'), 1)
150 self.assertIs(getitem(dct, 'b'), KeyError)
151 self.assertEqual(getitem(dct, '\U0001f40d'), 2)
152
153 dct2 = DictSubclass(dct)
154 self.assertEqual(getitem(dct2, 'a'), 1)
155 self.assertIs(getitem(dct2, 'b'), KeyError)
156
157 self.assertRaises(SystemError, getitem, 42, 'a')
158 self.assertRaises(TypeError, getitem, {}, []) # unhashable
159 self.assertRaises(SystemError, getitem, [], 1)
160 self.assertRaises(SystemError, getitem, [], 'a')
161 # CRASHES getitem({}, NULL)
162 # CRASHES getitem(NULL, 'a')
163
164 def test_dict_contains(self):
165 contains = _testcapi.dict_contains
166 dct = {'a': 1, '\U0001f40d': 2}
167 self.assertTrue(contains(dct, 'a'))
168 self.assertFalse(contains(dct, 'b'))
169 self.assertTrue(contains(dct, '\U0001f40d'))
170
171 dct2 = DictSubclass(dct)
172 self.assertTrue(contains(dct2, 'a'))
173 self.assertFalse(contains(dct2, 'b'))
174
175 self.assertRaises(TypeError, contains, {}, []) # unhashable
176 # CRASHES contains({}, NULL)
177 # CRASHES contains(UserDict(), 'a')
178 # CRASHES contains(42, 'a')
179 # CRASHES contains(NULL, 'a')
180
181 def test_dict_setitem(self):
182 setitem = _testcapi.dict_setitem
183 dct = {}
184 setitem(dct, 'a', 5)
185 self.assertEqual(dct, {'a': 5})
186 setitem(dct, '\U0001f40d', 8)
187 self.assertEqual(dct, {'a': 5, '\U0001f40d': 8})
188
189 dct2 = DictSubclass()
190 setitem(dct2, 'a', 5)
191 self.assertEqual(dct2, {'a': 5})
192
193 self.assertRaises(TypeError, setitem, {}, [], 5) # unhashable
194 self.assertRaises(SystemError, setitem, UserDict(), 'a', 5)
195 self.assertRaises(SystemError, setitem, [1], 0, 5)
196 self.assertRaises(SystemError, setitem, 42, 'a', 5)
197 # CRASHES setitem({}, NULL, 5)
198 # CRASHES setitem({}, 'a', NULL)
199 # CRASHES setitem(NULL, 'a', 5)
200
201 def test_dict_setitemstring(self):
202 setitemstring = _testcapi.dict_setitemstring
203 dct = {}
204 setitemstring(dct, b'a', 5)
205 self.assertEqual(dct, {'a': 5})
206 setitemstring(dct, '\U0001f40d'.encode(), 8)
207 self.assertEqual(dct, {'a': 5, '\U0001f40d': 8})
208
209 dct2 = DictSubclass()
210 setitemstring(dct2, b'a', 5)
211 self.assertEqual(dct2, {'a': 5})
212
213 self.assertRaises(UnicodeDecodeError, setitemstring, {}, b'\xff', 5)
214 self.assertRaises(SystemError, setitemstring, UserDict(), b'a', 5)
215 self.assertRaises(SystemError, setitemstring, 42, b'a', 5)
216 # CRASHES setitemstring({}, NULL, 5)
217 # CRASHES setitemstring({}, b'a', NULL)
218 # CRASHES setitemstring(NULL, b'a', 5)
219
220 def test_dict_delitem(self):
221 delitem = _testcapi.dict_delitem
222 dct = {'a': 1, 'c': 2, '\U0001f40d': 3}
223 delitem(dct, 'a')
224 self.assertEqual(dct, {'c': 2, '\U0001f40d': 3})
225 self.assertRaises(KeyError, delitem, dct, 'b')
226 delitem(dct, '\U0001f40d')
227 self.assertEqual(dct, {'c': 2})
228
229 dct2 = DictSubclass({'a': 1, 'c': 2})
230 delitem(dct2, 'a')
231 self.assertEqual(dct2, {'c': 2})
232 self.assertRaises(KeyError, delitem, dct2, 'b')
233
234 self.assertRaises(TypeError, delitem, {}, []) # unhashable
235 self.assertRaises(SystemError, delitem, UserDict({'a': 1}), 'a')
236 self.assertRaises(SystemError, delitem, [1], 0)
237 self.assertRaises(SystemError, delitem, 42, 'a')
238 # CRASHES delitem({}, NULL)
239 # CRASHES delitem(NULL, 'a')
240
241 def test_dict_delitemstring(self):
242 delitemstring = _testcapi.dict_delitemstring
243 dct = {'a': 1, 'c': 2, '\U0001f40d': 3}
244 delitemstring(dct, b'a')
245 self.assertEqual(dct, {'c': 2, '\U0001f40d': 3})
246 self.assertRaises(KeyError, delitemstring, dct, b'b')
247 delitemstring(dct, '\U0001f40d'.encode())
248 self.assertEqual(dct, {'c': 2})
249
250 dct2 = DictSubclass({'a': 1, 'c': 2})
251 delitemstring(dct2, b'a')
252 self.assertEqual(dct2, {'c': 2})
253 self.assertRaises(KeyError, delitemstring, dct2, b'b')
254
255 self.assertRaises(UnicodeDecodeError, delitemstring, {}, b'\xff')
256 self.assertRaises(SystemError, delitemstring, UserDict({'a': 1}), b'a')
257 self.assertRaises(SystemError, delitemstring, 42, b'a')
258 # CRASHES delitemstring({}, NULL)
259 # CRASHES delitemstring(NULL, b'a')
260
261 def test_dict_setdefault(self):
262 setdefault = _testcapi.dict_setdefault
263 dct = {}
264 self.assertEqual(setdefault(dct, 'a', 5), 5)
265 self.assertEqual(dct, {'a': 5})
266 self.assertEqual(setdefault(dct, 'a', 8), 5)
267 self.assertEqual(dct, {'a': 5})
268
269 dct2 = DictSubclass()
270 self.assertEqual(setdefault(dct2, 'a', 5), 5)
271 self.assertEqual(dct2, {'a': 5})
272 self.assertEqual(setdefault(dct2, 'a', 8), 5)
273 self.assertEqual(dct2, {'a': 5})
274
275 self.assertRaises(TypeError, setdefault, {}, [], 5) # unhashable
276 self.assertRaises(SystemError, setdefault, UserDict(), 'a', 5)
277 self.assertRaises(SystemError, setdefault, [1], 0, 5)
278 self.assertRaises(SystemError, setdefault, 42, 'a', 5)
279 # CRASHES setdefault({}, NULL, 5)
280 # CRASHES setdefault({}, 'a', NULL)
281 # CRASHES setdefault(NULL, 'a', 5)
282
283 def test_mapping_keys_valuesitems(self):
284 class ESC[4;38;5;81mBadMapping(ESC[4;38;5;149mdict):
285 def keys(self):
286 return None
287 def values(self):
288 return None
289 def items(self):
290 return None
291 dict_obj = {'foo': 1, 'bar': 2, 'spam': 3}
292 for mapping in [dict_obj, DictSubclass(dict_obj), BadMapping(dict_obj)]:
293 self.assertListEqual(_testcapi.dict_keys(mapping),
294 list(dict_obj.keys()))
295 self.assertListEqual(_testcapi.dict_values(mapping),
296 list(dict_obj.values()))
297 self.assertListEqual(_testcapi.dict_items(mapping),
298 list(dict_obj.items()))
299
300 def test_dict_keys_valuesitems_bad_arg(self):
301 for mapping in UserDict(), [], object():
302 self.assertRaises(SystemError, _testcapi.dict_keys, mapping)
303 self.assertRaises(SystemError, _testcapi.dict_values, mapping)
304 self.assertRaises(SystemError, _testcapi.dict_items, mapping)
305
306 def test_dict_next(self):
307 dict_next = _testcapi.dict_next
308 self.assertIsNone(dict_next({}, 0))
309 dct = {'a': 1, 'b': 2, 'c': 3}
310 pos = 0
311 pairs = []
312 while True:
313 res = dict_next(dct, pos)
314 if res is None:
315 break
316 rc, pos, key, value = res
317 self.assertEqual(rc, 1)
318 pairs.append((key, value))
319 self.assertEqual(pairs, list(dct.items()))
320
321 # CRASHES dict_next(NULL, 0)
322
323 def test_dict_update(self):
324 update = _testcapi.dict_update
325 for cls1 in dict, DictSubclass:
326 for cls2 in dict, DictSubclass, UserDict:
327 dct = cls1({'a': 1, 'b': 2})
328 update(dct, cls2({'b': 3, 'c': 4}))
329 self.assertEqual(dct, {'a': 1, 'b': 3, 'c': 4})
330
331 self.assertRaises(AttributeError, update, {}, [])
332 self.assertRaises(AttributeError, update, {}, 42)
333 self.assertRaises(SystemError, update, UserDict(), {})
334 self.assertRaises(SystemError, update, 42, {})
335 self.assertRaises(SystemError, update, {}, NULL)
336 self.assertRaises(SystemError, update, NULL, {})
337
338 def test_dict_merge(self):
339 merge = _testcapi.dict_merge
340 for cls1 in dict, DictSubclass:
341 for cls2 in dict, DictSubclass, UserDict:
342 dct = cls1({'a': 1, 'b': 2})
343 merge(dct, cls2({'b': 3, 'c': 4}), 0)
344 self.assertEqual(dct, {'a': 1, 'b': 2, 'c': 4})
345 dct = cls1({'a': 1, 'b': 2})
346 merge(dct, cls2({'b': 3, 'c': 4}), 1)
347 self.assertEqual(dct, {'a': 1, 'b': 3, 'c': 4})
348
349 self.assertRaises(AttributeError, merge, {}, [], 0)
350 self.assertRaises(AttributeError, merge, {}, 42, 0)
351 self.assertRaises(SystemError, merge, UserDict(), {}, 0)
352 self.assertRaises(SystemError, merge, 42, {}, 0)
353 self.assertRaises(SystemError, merge, {}, NULL, 0)
354 self.assertRaises(SystemError, merge, NULL, {}, 0)
355
356 def test_dict_mergefromseq2(self):
357 mergefromseq2 = _testcapi.dict_mergefromseq2
358 for cls1 in dict, DictSubclass:
359 for cls2 in list, iter:
360 dct = cls1({'a': 1, 'b': 2})
361 mergefromseq2(dct, cls2([('b', 3), ('c', 4)]), 0)
362 self.assertEqual(dct, {'a': 1, 'b': 2, 'c': 4})
363 dct = cls1({'a': 1, 'b': 2})
364 mergefromseq2(dct, cls2([('b', 3), ('c', 4)]), 1)
365 self.assertEqual(dct, {'a': 1, 'b': 3, 'c': 4})
366
367 self.assertRaises(ValueError, mergefromseq2, {}, [(1,)], 0)
368 self.assertRaises(ValueError, mergefromseq2, {}, [(1, 2, 3)], 0)
369 self.assertRaises(TypeError, mergefromseq2, {}, [1], 0)
370 self.assertRaises(TypeError, mergefromseq2, {}, 42, 0)
371 # CRASHES mergefromseq2(UserDict(), [], 0)
372 # CRASHES mergefromseq2(42, [], 0)
373 # CRASHES mergefromseq2({}, NULL, 0)
374 # CRASHES mergefromseq2(NULL, {}, 0)
375
376
377 if __name__ == "__main__":
378 unittest.main()