File: dict_setdefault.py

package info (click to toggle)
cython 3.0.11%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 19,092 kB
  • sloc: python: 83,539; ansic: 18,831; cpp: 1,402; xml: 1,031; javascript: 511; makefile: 403; sh: 204; sed: 11
file content (123 lines) | stat: -rw-r--r-- 3,081 bytes parent folder | download | duplicates (10)
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

import cython

class Unhashable(object):
    def __hash__(self):
        raise TypeError('I am not hashable')

class Hashable(object):
    def __hash__(self):
        return 1
    def __eq__(self, other):
        return isinstance(other, Hashable)

class CountedHashable(object):
    def __init__(self):
        self.hash_count = 0
        self.eq_count = 0
    def __hash__(self):
        self.hash_count += 1
        return 42
    def __eq__(self, other):
        self.eq_count += 1
        return id(self) == id(other)

@cython.test_fail_if_path_exists('//AttributeNode')
@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.locals(d=dict)
def setdefault1(d, key):
    """
    >>> d = {}
    >>> setdefault1(d, 1)
    >>> len(d)
    1
    >>> setdefault1(d, 1)
    >>> len(d)
    1
    >>> d[1]
    >>> setdefault1(d, Unhashable())
    Traceback (most recent call last):
    TypeError: I am not hashable
    >>> len(d)
    1
    >>> h1 = setdefault1(d, Hashable())
    >>> len(d)
    2
    >>> h2 = setdefault1(d, Hashable())
    >>> len(d)
    2
    >>> d[Hashable()]

    # CPython's behaviour depends on version and py_debug setting, so just compare to it
    >>> py_hashed1 = CountedHashable()
    >>> y = {py_hashed1: 5}
    >>> py_hashed2 = CountedHashable()
    >>> y.setdefault(py_hashed2)

    >>> cy_hashed1 = CountedHashable()
    >>> y = {cy_hashed1: 5}
    >>> cy_hashed2 = CountedHashable()
    >>> setdefault1(y, cy_hashed2)
    >>> py_hashed1.hash_count - cy_hashed1.hash_count
    0
    >>> py_hashed2.hash_count - cy_hashed2.hash_count
    0
    >>> (py_hashed1.eq_count + py_hashed2.eq_count) - (cy_hashed1.eq_count + cy_hashed2.eq_count)
    0
    """
    return d.setdefault(key)

@cython.test_fail_if_path_exists('//AttributeNode')
@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.locals(d=dict)
def setdefault2(d, key, value):
    """
    >>> d = {}
    >>> setdefault2(d, 1, 2)
    2
    >>> len(d)
    1
    >>> setdefault2(d, 1, 2)
    2
    >>> len(d)
    1
    >>> l = setdefault2(d, 2, [])
    >>> len(d)
    2
    >>> l.append(1)
    >>> setdefault2(d, 2, [])
    [1]
    >>> len(d)
    2
    >>> setdefault2(d, Unhashable(), 1)
    Traceback (most recent call last):
    TypeError: I am not hashable
    >>> h1 = setdefault2(d, Hashable(), 55)
    >>> len(d)
    3
    >>> h2 = setdefault2(d, Hashable(), 66)
    >>> len(d)
    3
    >>> d[Hashable()]
    55

    # CPython's behaviour depends on version and py_debug setting, so just compare to it
    >>> py_hashed1 = CountedHashable()
    >>> y = {py_hashed1: 5}
    >>> py_hashed2 = CountedHashable()
    >>> y.setdefault(py_hashed2, [])
    []

    >>> cy_hashed1 = CountedHashable()
    >>> y = {cy_hashed1: 5}
    >>> cy_hashed2 = CountedHashable()
    >>> setdefault2(y, cy_hashed2, [])
    []
    >>> py_hashed1.hash_count - cy_hashed1.hash_count
    0
    >>> py_hashed2.hash_count - cy_hashed2.hash_count
    0
    >>> (py_hashed1.eq_count + py_hashed2.eq_count) - (cy_hashed1.eq_count + cy_hashed2.eq_count)
    0
    """
    return d.setdefault(key, value)