4
class Unhashable(object):
6
raise TypeError('I am not hashable')
11
def __eq__(self, other):
12
return isinstance(other, Hashable)
14
class CountedHashable(object):
21
def __eq__(self, other):
23
return id(self) == id(other)
25
@cython.test_fail_if_path_exists('//AttributeNode')
26
@cython.test_assert_path_exists('//PythonCapiCallNode')
28
def setdefault1(d, key):
38
>>> setdefault1(d, Unhashable())
39
Traceback (most recent call last):
40
TypeError: I am not hashable
43
>>> h1 = setdefault1(d, Hashable())
46
>>> h2 = setdefault1(d, Hashable())
51
# CPython's behaviour depends on version and py_debug setting, so just compare to it
52
>>> py_hashed1 = CountedHashable()
53
>>> y = {py_hashed1: 5}
54
>>> py_hashed2 = CountedHashable()
55
>>> y.setdefault(py_hashed2)
57
>>> cy_hashed1 = CountedHashable()
58
>>> y = {cy_hashed1: 5}
59
>>> cy_hashed2 = CountedHashable()
60
>>> setdefault1(y, cy_hashed2)
61
>>> py_hashed1.hash_count - cy_hashed1.hash_count
63
>>> py_hashed2.hash_count - cy_hashed2.hash_count
65
>>> (py_hashed1.eq_count + py_hashed2.eq_count) - (cy_hashed1.eq_count + cy_hashed2.eq_count)
68
return d.setdefault(key)
70
@cython.test_fail_if_path_exists('//AttributeNode')
71
@cython.test_assert_path_exists('//PythonCapiCallNode')
73
def setdefault2(d, key, value):
76
>>> setdefault2(d, 1, 2)
80
>>> setdefault2(d, 1, 2)
84
>>> l = setdefault2(d, 2, [])
88
>>> setdefault2(d, 2, [])
92
>>> setdefault2(d, Unhashable(), 1)
93
Traceback (most recent call last):
94
TypeError: I am not hashable
95
>>> h1 = setdefault2(d, Hashable(), 55)
98
>>> h2 = setdefault2(d, Hashable(), 66)
104
# CPython's behaviour depends on version and py_debug setting, so just compare to it
105
>>> py_hashed1 = CountedHashable()
106
>>> y = {py_hashed1: 5}
107
>>> py_hashed2 = CountedHashable()
108
>>> y.setdefault(py_hashed2, [])
111
>>> cy_hashed1 = CountedHashable()
112
>>> y = {cy_hashed1: 5}
113
>>> cy_hashed2 = CountedHashable()
114
>>> setdefault2(y, cy_hashed2, [])
116
>>> py_hashed1.hash_count - cy_hashed1.hash_count
118
>>> py_hashed2.hash_count - cy_hashed2.hash_count
120
>>> (py_hashed1.eq_count + py_hashed2.eq_count) - (cy_hashed1.eq_count + cy_hashed2.eq_count)
123
return d.setdefault(key, value)