1
2cimport cython
3
4dict_size = 4
5d = dict(zip(range(10,dict_size+10), range(dict_size)))
6
7
8def dict_iteritems(dict d):
9    """
10    >>> it = dict_iteritems(d)
11    >>> type(it) is list
12    False
13    >>> sorted(it)
14    [(10, 0), (11, 1), (12, 2), (13, 3)]
15    """
16    return d.iteritems()
17
18
19def dict_iterkeys(dict d):
20    """
21    >>> it = dict_iterkeys(d)
22    >>> type(it) is list
23    False
24    >>> sorted(it)
25    [10, 11, 12, 13]
26    """
27    return d.iterkeys()
28
29
30def dict_itervalues(dict d):
31    """
32    >>> it = dict_itervalues(d)
33    >>> type(it) is list
34    False
35    >>> sorted(it)
36    [0, 1, 2, 3]
37    """
38    return d.itervalues()
39
40
41@cython.test_fail_if_path_exists(
42    "//WhileStatNode")
43def items(dict d):
44    """
45    >>> items(d)
46    [(10, 0), (11, 1), (12, 2), (13, 3)]
47    """
48    l = []
49    for k,v in d.items():
50        l.append((k,v))
51    l.sort()
52    return l
53
54@cython.test_assert_path_exists(
55    "//WhileStatNode",
56    "//WhileStatNode//DictIterationNextNode")
57def iteritems(dict d):
58    """
59    >>> iteritems(d)
60    [(10, 0), (11, 1), (12, 2), (13, 3)]
61    >>> iteritems({})
62    []
63    """
64    l = []
65    for k,v in d.iteritems():
66        l.append((k,v))
67    l.sort()
68    return l
69
70@cython.test_assert_path_exists(
71    "//WhileStatNode",
72    "//WhileStatNode//DictIterationNextNode")
73def optimistic_iteritems(d):
74    """
75    >>> optimistic_iteritems(d)
76    [(10, 0), (11, 1), (12, 2), (13, 3)]
77    >>> optimistic_iteritems({})
78    []
79    >>> class mydict(object):
80    ...     def __init__(self, t): self.t = t
81    ...     def iteritems(self): return self.t(d.items())
82    >>> optimistic_iteritems(mydict(list))
83    [(10, 0), (11, 1), (12, 2), (13, 3)]
84    >>> optimistic_iteritems(mydict(tuple))
85    [(10, 0), (11, 1), (12, 2), (13, 3)]
86    >>> optimistic_iteritems(mydict(iter))
87    [(10, 0), (11, 1), (12, 2), (13, 3)]
88    """
89    l = []
90    for k,v in d.iteritems():
91        l.append((k,v))
92    l.sort()
93    return l
94
95@cython.test_assert_path_exists(
96    "//WhileStatNode",
97    "//WhileStatNode//DictIterationNextNode")
98def iteritems_dict():
99    """
100    >>> iteritems_dict()
101    [(11, 1), (12, 2), (13, 3)]
102    """
103    l = []
104    for k,v in {11 : 1, 12 : 2, 13 : 3}.iteritems():
105        l.append((k,v))
106    l.sort()
107    return l
108
109@cython.test_assert_path_exists(
110    "//WhileStatNode",
111    "//WhileStatNode//DictIterationNextNode")
112def iteritems_int(dict d):
113    """
114    >>> iteritems_int(d)
115    [(10, 0), (11, 1), (12, 2), (13, 3)]
116    >>> iteritems_int({})
117    []
118    >>> iteritems_int({'a': 1})
119    Traceback (most recent call last):
120    TypeError: an integer is required
121    >>> iteritems_int({1: 'b'})
122    Traceback (most recent call last):
123    TypeError: an integer is required
124    >>> iteritems_int({'a': 'b'})
125    Traceback (most recent call last):
126    TypeError: an integer is required
127    """
128    cdef int k,v
129    l = []
130    for k,v in d.iteritems():
131        l.append((k,v))
132    l.sort()
133    return l
134
135@cython.test_assert_path_exists(
136    "//WhileStatNode",
137    "//WhileStatNode//DictIterationNextNode")
138def optimistic_iteritems_int(d):
139    """
140    >>> optimistic_iteritems_int(d)
141    [(10, 0), (11, 1), (12, 2), (13, 3)]
142    >>> optimistic_iteritems_int({})
143    []
144    >>> class mydict(object):
145    ...     def __init__(self, t): self.t = t
146    ...     def iteritems(self): return self.t(d.items())
147    >>> optimistic_iteritems_int(mydict(list))
148    [(10, 0), (11, 1), (12, 2), (13, 3)]
149    >>> optimistic_iteritems_int(mydict(tuple))
150    [(10, 0), (11, 1), (12, 2), (13, 3)]
151    >>> optimistic_iteritems_int(mydict(iter))
152    [(10, 0), (11, 1), (12, 2), (13, 3)]
153
154    >>> optimistic_iteritems_int({'a': 1})
155    Traceback (most recent call last):
156    TypeError: an integer is required
157    >>> optimistic_iteritems_int({1: 'b'})
158    Traceback (most recent call last):
159    TypeError: an integer is required
160    >>> optimistic_iteritems_int({'a': 'b'})
161    Traceback (most recent call last):
162    TypeError: an integer is required
163    """
164    cdef int k,v
165    l = []
166    for k,v in d.iteritems():
167        l.append((k,v))
168    l.sort()
169    return l
170
171@cython.test_assert_path_exists(
172    "//WhileStatNode",
173    "//WhileStatNode//DictIterationNextNode")
174def iteritems_tuple(dict d):
175    """
176    >>> iteritems_tuple(d)
177    [(10, 0), (11, 1), (12, 2), (13, 3)]
178    >>> iteritems_tuple({})
179    []
180    """
181    l = []
182    for t in d.iteritems():
183        l.append(t)
184    l.sort()
185    return l
186
187@cython.test_assert_path_exists(
188    "//WhileStatNode",
189    "//WhileStatNode//DictIterationNextNode")
190def iteritems_listcomp(dict d):
191    cdef list l = [(k,v) for k,v in d.iteritems()]
192    l.sort()
193    return l
194
195@cython.test_assert_path_exists(
196    "//WhileStatNode",
197    "//WhileStatNode//DictIterationNextNode")
198def iterkeys(dict d):
199    """
200    >>> iterkeys(d)
201    [10, 11, 12, 13]
202    >>> iterkeys({})
203    []
204    """
205    l = []
206    for k in d.iterkeys():
207        l.append(k)
208    l.sort()
209    return l
210
211@cython.test_assert_path_exists(
212    "//WhileStatNode",
213    "//WhileStatNode//DictIterationNextNode")
214def optimistic_iterkeys(d):
215    """
216    >>> optimistic_iterkeys(d)
217    [10, 11, 12, 13]
218    >>> optimistic_iterkeys({})
219    []
220    >>> class mydict(object):
221    ...     def __init__(self, t): self.t = t
222    ...     def iterkeys(self): return self.t(d)
223    >>> optimistic_iterkeys(mydict(lambda x:x))
224    [10, 11, 12, 13]
225    >>> optimistic_iterkeys(mydict(lambda x:x.keys()))
226    [10, 11, 12, 13]
227    >>> optimistic_iterkeys(mydict(list))
228    [10, 11, 12, 13]
229    >>> optimistic_iterkeys(mydict(tuple))
230    [10, 11, 12, 13]
231    >>> optimistic_iterkeys(mydict(iter))
232    [10, 11, 12, 13]
233    """
234    l = []
235    for k in d.iterkeys():
236        l.append(k)
237    l.sort()
238    return l
239
240@cython.test_fail_if_path_exists(
241    "//WhileStatNode",
242    "//WhileStatNode//DictIterationNextNode")
243def optimistic_iterkeys_argerror(d):
244    """
245    >>> try: optimistic_iterkeys_argerror(d)
246    ... except (TypeError, AttributeError): pass
247    """
248    for k in d.iterkeys(1):
249        print k
250
251@cython.test_assert_path_exists(
252    "//WhileStatNode",
253    "//WhileStatNode//DictIterationNextNode")
254def iterkeys_int(dict d):
255    """
256    >>> iterkeys_int(d)
257    [10, 11, 12, 13]
258    >>> iterkeys_int({})
259    []
260    >>> iterkeys_int({'a': 'b'})
261    Traceback (most recent call last):
262    TypeError: an integer is required
263    """
264    cdef int k
265    l = []
266    for k in d.iterkeys():
267        l.append(k)
268    l.sort()
269    return l
270
271@cython.test_assert_path_exists(
272    "//WhileStatNode",
273    "//WhileStatNode//DictIterationNextNode")
274def iterdict(dict d):
275    """
276    >>> iterdict(d)
277    [10, 11, 12, 13]
278    >>> iterdict({})
279    []
280    """
281    l = []
282    for k in d:
283        l.append(k)
284    l.sort()
285    return l
286
287@cython.test_assert_path_exists(
288    "//WhileStatNode",
289    "//WhileStatNode//DictIterationNextNode")
290def iterdict_int(dict d):
291    """
292    >>> iterdict_int(d)
293    [10, 11, 12, 13]
294    >>> iterdict_int({})
295    []
296    >>> iterdict_int({'a': 'b'})
297    Traceback (most recent call last):
298    TypeError: an integer is required
299    """
300    cdef int k
301    l = []
302    for k in d:
303        l.append(k)
304    l.sort()
305    return l
306
307@cython.test_assert_path_exists(
308    "//WhileStatNode",
309    "//WhileStatNode//DictIterationNextNode")
310def iterdict_reassign(dict d):
311    """
312    >>> iterdict_reassign(d)
313    [10, 11, 12, 13]
314    >>> iterdict_reassign({})
315    []
316    """
317    cdef dict d_new = {}
318    l = []
319    for k in d:
320        d = d_new
321        l.append(k)
322    l.sort()
323    return l
324
325@cython.test_assert_path_exists(
326    "//WhileStatNode",
327    "//WhileStatNode//DictIterationNextNode")
328def iterdict_listcomp(dict d):
329    """
330    >>> iterdict_listcomp(d)
331    [10, 11, 12, 13]
332    >>> iterdict_listcomp({})
333    []
334    """
335    cdef list l = [k for k in d]
336    l.sort()
337    return l
338
339@cython.test_assert_path_exists(
340    "//WhileStatNode",
341    "//WhileStatNode//DictIterationNextNode")
342def itervalues(dict d):
343    """
344    >>> itervalues(d)
345    [0, 1, 2, 3]
346    >>> itervalues({})
347    []
348    """
349    l = []
350    for v in d.itervalues():
351        l.append(v)
352    l.sort()
353    return l
354
355@cython.test_assert_path_exists(
356    "//WhileStatNode",
357    "//WhileStatNode//DictIterationNextNode")
358def optimistic_itervalues(d):
359    """
360    >>> optimistic_itervalues(d)
361    [0, 1, 2, 3]
362    >>> optimistic_itervalues({})
363    []
364    >>> class mydict(object):
365    ...     def __init__(self, t): self.t = t
366    ...     def itervalues(self): return self.t(d.values())
367    >>> optimistic_itervalues(mydict(lambda x:x))
368    [0, 1, 2, 3]
369    >>> optimistic_itervalues(mydict(list))
370    [0, 1, 2, 3]
371    >>> optimistic_itervalues(mydict(tuple))
372    [0, 1, 2, 3]
373    >>> optimistic_itervalues(mydict(iter))
374    [0, 1, 2, 3]
375    """
376    l = []
377    for v in d.itervalues():
378        l.append(v)
379    l.sort()
380    return l
381
382@cython.test_assert_path_exists(
383    "//WhileStatNode",
384    "//WhileStatNode//DictIterationNextNode")
385def itervalues_int(dict d):
386    """
387    >>> itervalues_int(d)
388    [0, 1, 2, 3]
389    >>> itervalues_int({})
390    []
391    >>> itervalues_int({'a': 'b'})
392    Traceback (most recent call last):
393    TypeError: an integer is required
394    """
395    cdef int v
396    l = []
397    for v in d.itervalues():
398        l.append(v)
399    l.sort()
400    return l
401
402@cython.test_assert_path_exists(
403    "//WhileStatNode",
404    "//WhileStatNode//DictIterationNextNode")
405def itervalues_listcomp(dict d):
406    """
407    >>> itervalues_listcomp(d)
408    [0, 1, 2, 3]
409    >>> itervalues_listcomp({})
410    []
411    """
412    cdef list l = [v for v in d.itervalues()]
413    l.sort()
414    return l
415
416@cython.test_assert_path_exists(
417    "//WhileStatNode",
418    "//WhileStatNode//DictIterationNextNode")
419def itervalues_kwargs(**d):
420    """
421    >>> itervalues_kwargs(a=1, b=2, c=3, d=4)
422    [1, 2, 3, 4]
423    >>> itervalues_kwargs()
424    []
425    """
426    cdef list l = [v for v in d.itervalues()]
427    l.sort()
428    return l
429
430@cython.test_assert_path_exists(
431    "//WhileStatNode",
432    "//WhileStatNode//DictIterationNextNode")
433def iterdict_change_size(dict d):
434    """
435    >>> count, i = 0, -1
436    >>> d = {1:2, 10:20}
437    >>> for i in d:
438    ...     d[i+1] = 5
439    ...     count += 1
440    ...     if count > 5:
441    ...         break # safety
442    Traceback (most recent call last):
443    RuntimeError: dictionary changed size during iteration
444
445    >>> iterdict_change_size({1:2, 10:20})
446    Traceback (most recent call last):
447    RuntimeError: dictionary changed size during iteration
448    >>> print( iterdict_change_size({}) )
449    DONE
450    """
451    cdef int count = 0
452    i = -1
453    for i in d:
454        d[i+1] = 5
455        count += 1
456        if count > 5:
457            break # safety
458    return "DONE"
459
460@cython.test_assert_path_exists(
461    "//WhileStatNode",
462    "//WhileStatNode//DictIterationNextNode")
463def optimistic_iterdict_change_size(d):
464    """
465    >>> count, i = 0, -1
466    >>> d = {1:2, 10:20}
467    >>> for i in d:
468    ...     d[i+1] = 5
469    ...     count += 1
470    ...     if count > 5:
471    ...         break # safety
472    Traceback (most recent call last):
473    RuntimeError: dictionary changed size during iteration
474
475    >>> optimistic_iterdict_change_size({1:2, 10:20})
476    Traceback (most recent call last):
477    RuntimeError: dictionary changed size during iteration
478    >>> print( optimistic_iterdict_change_size({}) )
479    DONE
480    >>> class mydict(object):
481    ...     _d = {1:2, 10:20}
482    ...     def iterkeys(self): return self._d
483    ...     def __setitem__(self, key, value): self._d[key] = value
484    >>> optimistic_iterdict_change_size(mydict())
485    Traceback (most recent call last):
486    RuntimeError: dictionary changed size during iteration
487    """
488    cdef int count = 0
489    i = -1
490    for i in d.iterkeys():
491        d[i+1] = 5
492        count += 1
493        if count > 5:
494            break # safety
495    return "DONE"
496
497
498@cython.test_assert_path_exists(
499    "//WhileStatNode",
500    "//WhileStatNode//DictIterationNextNode")
501def values_of_expression(**kwargs):
502    """
503    >>> sorted(values_of_expression(a=3, b=4))
504    [3, 4]
505    """
506    # this can be optimised even in Py2
507    return [ arg for arg in dict(kwargs.items()).values() ]
508
509
510def items_of_expression(*args, **kwargs):
511    """
512    >>> sorted(items_of_expression(a=3, b=4))
513    [('a', 3), ('b', 4)]
514
515    >>> sorted(items_of_expression([('a', 3)], b=4))
516    [('a', 3), ('b', 4)]
517    """
518    return [item for item in dict(*args, **kwargs).items()]
519
520
521def iteritems_of_expression(*args, **kwargs):
522    """
523    >>> sorted(iteritems_of_expression(a=3, b=4))
524    [('a', 3), ('b', 4)]
525
526    >>> sorted(iteritems_of_expression([('a', 3)], b=4))
527    [('a', 3), ('b', 4)]
528    """
529    return [item for item in dict(*args, **kwargs).iteritems()]
530
531
532def for_in_items_of_expression(*args, **kwargs):
533    """
534    >>> sorted(for_in_items_of_expression(a=3, b=4))
535    [('a', 3), ('b', 4)]
536
537    >>> sorted(for_in_items_of_expression([('a', 3)], b=4))
538    [('a', 3), ('b', 4)]
539    """
540    result = []
541    for k, v in dict(*args, **kwargs).items():
542        result.append((k, v))
543    return result
544
545
546def for_in_iteritems_of_expression(*args, **kwargs):
547    """
548    >>> sorted(for_in_iteritems_of_expression(a=3, b=4))
549    [('a', 3), ('b', 4)]
550
551    >>> sorted(for_in_iteritems_of_expression([('a', 3)], b=4))
552    [('a', 3), ('b', 4)]
553    """
554    result = []
555    for k, v in dict(*args, **kwargs).iteritems():
556        result.append((k, v))
557    return result
558
559
560cdef class NotADict:
561    """
562    >>> NotADict().listvalues()  # doctest: +IGNORE_EXCEPTION_DETAIL
563    Traceback (most recent call last):
564    ...
565    TypeError: descriptor 'values' for 'mappingproxy' objects doesn't apply to a 'iterdict.NotADict' object
566    """
567    cdef long v
568    def __cinit__(self):
569        self.v = 1
570    itervalues = type(object.__dict__).values
571
572    def listvalues(self):
573        return [v for v in self.itervalues()]
574