summaryrefslogtreecommitdiff
path: root/tests/run/funcexc_iter_T228.pyx
blob: 40db3afb2b3135b9b657f0804d30e0a00e75427e (plain)
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# ticket: t228

__doc__ = u"""
>>> def py_iterator():
...    if True: return
...    yield None

>>> list(py_iterator())
[]
>>> list(cy_iterator())
[]

>>> try:
...     raise ValueError
... except:
...     print(sys.exc_info()[0] is ValueError or sys.exc_info()[0])
...     a = list(py_iterator())
...     print(sys.exc_info()[0] is ValueError or sys.exc_info()[0])
True
True

>>> print(sys.exc_info()[0] is None or sys.exc_info()[0])
True

>>> try:
...     raise ValueError
... except:
...     print(sys.exc_info()[0] is ValueError or sys.exc_info()[0])
...     a = list(py_iterator())
...     print(sys.exc_info()[0] is ValueError or sys.exc_info()[0])
...     a = list(cy_iterator())
...     print(sys.exc_info()[0] is ValueError or sys.exc_info()[0])
True
True
True

>>> print(sys.exc_info()[0] is None or sys.exc_info()[0])
True

>>> double_raise(py_iterator)
True
True
True

>>> print(sys.exc_info()[0] is None or sys.exc_info()[0])
True
"""

import sys
if sys.version_info[0] < 3:
    sys.exc_clear()

cdef class cy_iterator(object):
    def __iter__(self):
        return self
    def __next__(self):
        raise StopIteration

def double_raise(py_iterator):
    try:
        raise ValueError
    except:
        print(sys.exc_info()[0] is ValueError or sys.exc_info()[0])
        a = list(py_iterator())
        print(sys.exc_info()[0] is ValueError or sys.exc_info()[0])
        a = list(cy_iterator())
        print(sys.exc_info()[0] is ValueError or sys.exc_info()[0])


###### Tests to do with the optimization of StopIteration to "return NULL" #######
# we're mainly checking that
#  1. Calling __next__ manually doesn't crash (the wrapper function adds the exception)
#  2. if you raise a value then that value gets raised
#  3. putting the exception in various places try...finally / try...except blocks works

def call_next_directly():
    """
    >>> call_next_directly()
    Traceback (most recent call last):
    ...
    StopIteration
    """
    cy_iterator().__next__()

cdef class cy_iter_many_options:
    cdef what
    def __init__(self, what):
        self.what = what

    def __iter__(self):
        return self

    def __next__(self):
        if self.what == "StopIteration in finally no return":
            try:
                raise StopIteration
            finally:
                print "Finally..."
        elif self.what == "StopIteration in finally return":
            try:
                raise StopIteration
            finally:
                self.what = None
                return "in finally"  # but will stop iterating next time
        elif self.what == "StopIteration from finally":
            try:
                raise ValueError
            finally:
                raise StopIteration
        elif self.what == "catch StopIteration":
            try:
                raise StopIteration
            except StopIteration:
                self.what = None
                return "in except"  # but will stop next time
        elif self.what == "don't catch StopIteration":
            try:
                raise StopIteration
            except ValueError:
                return 0
        elif self.what == "StopIteration from except":
            try:
                raise ValueError
            except ValueError:
                raise StopIteration
        elif self.what == "StopIteration with value":
            raise StopIteration("I'm a value!")
        elif self.what is None:
            raise StopIteration
        else:
            raise ValueError("self.what didn't match anything")

def test_cy_iter_many_options(option):
    """
    >>> test_cy_iter_many_options("StopIteration in finally no return")
    Finally...
    []
    >>> test_cy_iter_many_options("StopIteration in finally return")
    ['in finally']
    >>> test_cy_iter_many_options("StopIteration from finally")
    []
    >>> test_cy_iter_many_options("catch StopIteration")
    ['in except']
    >>> test_cy_iter_many_options("don't catch StopIteration")
    []
    >>> try:
    ...     cy_iter_many_options("StopIteration with value").__next__()
    ... except StopIteration as e:
    ...     print(e.args)
    ("I'm a value!",)
    """
    return list(cy_iter_many_options(option))