1# mode: run
2# tag: tryfinally
3
4import string
5import sys
6IS_PY3 = sys.version_info[0] >= 3
7
8cimport cython
9
10try:
11    next
12except NameError:
13    def next(it): return it.next()
14
15
16def finally_except():
17    """
18    >>> try:
19    ...     raise ValueError
20    ... finally:
21    ...     raise TypeError
22    Traceback (most recent call last):
23    TypeError
24    >>> finally_except()
25    Traceback (most recent call last):
26    TypeError
27    """
28    try:
29        raise ValueError
30    finally:
31        raise TypeError
32
33
34def finally_pass():
35    """
36    >>> finally_pass()
37    Traceback (most recent call last):
38    ValueError
39    """
40    try:
41        raise ValueError()
42    finally:
43        pass
44
45
46def except_finally_reraise():
47    """
48    >>> def py_check():
49    ...     try: raise ValueError
50    ...     except ValueError:
51    ...         for i in range(2):
52    ...             try: raise TypeError
53    ...             finally:
54    ...                 break
55    ...         assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
56    ...         raise
57    ...
58    >>> py_check()
59    Traceback (most recent call last):
60    ValueError
61    >>> except_finally_reraise()
62    Traceback (most recent call last):
63    ValueError
64    """
65    try:
66        raise ValueError
67    except ValueError:
68        for i in range(2):
69            try:
70                raise TypeError
71            finally:
72                break
73        assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
74        raise
75
76
77def except_finally_reraise_new():
78    """
79    >>> def py_check():
80    ...     try: raise ValueError
81    ...     except ValueError:
82    ...         try: raise TypeError
83    ...         finally:
84    ...             raise
85    >>> try: py_check()
86    ... except ValueError: assert not IS_PY3
87    ... except TypeError: assert IS_PY3
88    ... else: assert False
89    >>> try: except_finally_reraise_new()
90    ... except TypeError: pass  # currently only Py3 semantics implemented
91    ... else: assert False
92    """
93    try:
94        raise ValueError
95    except ValueError:
96        try:
97            raise TypeError
98        finally:
99            raise
100
101
102def finally_exception_check_return():
103    """
104    >>> if not IS_PY3:
105    ...     sys.exc_clear()
106    >>> def py_check():
107    ...     try: raise ValueError()
108    ...     finally:
109    ...         if IS_PY3:
110    ...             assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
111    ...         else:
112    ...             assert sys.exc_info() == (None, None, None), str(sys.exc_info())
113    ...         return 1
114    >>> py_check()
115    1
116    >>> finally_exception_check_return()
117    1
118    """
119    try:
120        raise ValueError()
121    finally:
122        if IS_PY3:
123            assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
124        else:
125            assert sys.exc_info() == (None, None, None), str(sys.exc_info())
126        return 1
127
128
129cdef void swallow():
130    try:
131        raise TypeError()
132    except:
133        return
134
135
136def finally_exception_check_swallow():
137    """
138    >>> if not IS_PY3:
139    ...     sys.exc_clear()
140    >>> def swallow():
141    ...     try: raise TypeError()
142    ...     except: return
143    >>> def py_check():
144    ...     try: raise ValueError()
145    ...     finally:
146    ...         if IS_PY3:
147    ...             assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
148    ...         else:
149    ...             assert sys.exc_info() == (None, None, None), str(sys.exc_info())
150    ...         swallow()
151    ...         if IS_PY3:
152    ...             assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
153    ...         else:
154    ...             assert sys.exc_info() == (None, None, None), str(sys.exc_info())
155    >>> py_check()
156    Traceback (most recent call last):
157    ValueError
158    >>> if not IS_PY3:
159    ...     sys.exc_clear()
160    >>> finally_exception_check_swallow()
161    Traceback (most recent call last):
162    ValueError
163    """
164    try:
165        raise ValueError()
166    finally:
167        if IS_PY3:
168            assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
169        else:
170            assert sys.exc_info() == (None, None, None), str(sys.exc_info())
171        swallow()
172        if IS_PY3:
173            assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
174        else:
175            assert sys.exc_info() == (None, None, None), str(sys.exc_info())
176
177
178def finally_exception_break_check():
179    """
180    >>> if not IS_PY3:
181    ...     sys.exc_clear()
182    >>> def py_check():
183    ...     i = None
184    ...     for i in range(2):
185    ...         try: raise ValueError()
186    ...         finally:
187    ...             if IS_PY3:
188    ...                 assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
189    ...             else:
190    ...                 assert sys.exc_info() == (None, None, None), str(sys.exc_info())
191    ...             break
192    ...     assert sys.exc_info() == (None, None, None), str(sys.exc_info())
193    ...     return i
194    >>> py_check()
195    0
196    >>> finally_exception_break_check()
197    0
198    """
199    i = None
200    for i in range(2):
201        try:
202            raise ValueError()
203        finally:
204            if IS_PY3:
205                assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
206            else:
207                assert sys.exc_info() == (None, None, None), str(sys.exc_info())
208            break
209    assert sys.exc_info() == (None, None, None), str(sys.exc_info())
210    return i
211
212
213def finally_exception_break_check_with_swallowed_raise():
214    """
215    >>> if not IS_PY3:
216    ...     sys.exc_clear()
217    >>> def swallow():
218    ...     try: raise TypeError()
219    ...     except: return
220    >>> def py_check():
221    ...     i = None
222    ...     for i in range(2):
223    ...         try: raise ValueError()
224    ...         finally:
225    ...             if IS_PY3:
226    ...                 assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
227    ...             else:
228    ...                 assert sys.exc_info() == (None, None, None), str(sys.exc_info())
229    ...             swallow()
230    ...             if IS_PY3:
231    ...                 assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
232    ...             else:
233    ...                 assert sys.exc_info() == (None, None, None), str(sys.exc_info())
234    ...             break
235    ...     assert sys.exc_info() == (None, None, None), str(sys.exc_info())
236    ...     return i
237    >>> py_check()
238    0
239    >>> finally_exception_break_check_with_swallowed_raise()
240    0
241    """
242    i = None
243    for i in range(2):
244        try:
245            raise ValueError()
246        finally:
247            if IS_PY3:
248                assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
249            else:
250                assert sys.exc_info() == (None, None, None), str(sys.exc_info())
251            swallow()
252            if IS_PY3:
253                assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
254            else:
255                assert sys.exc_info() == (None, None, None), str(sys.exc_info())
256            break
257    assert sys.exc_info() == (None, None, None), str(sys.exc_info())
258    return i
259
260
261def try_return_cy():
262    """
263    >>> def try_return_py():
264    ...    try:
265    ...        return 1
266    ...    finally:
267    ...        return 2
268    >>> try_return_py()
269    2
270    >>> try_return_cy()
271    2
272    """
273    try:
274        return 1
275    finally:
276        return 2
277
278cdef int try_return_c():
279    try:
280        return 1
281    finally:
282        return 2
283
284def call_try_return_c():
285    """
286    >>> call_try_return_c()
287    2
288    """
289    return try_return_c()
290
291cdef int try_return_with_exception():
292    try:
293        raise TypeError
294    finally:
295        return 1
296
297def call_try_return_with_exception():
298    """
299    >>> call_try_return_with_exception()
300    1
301    """
302    return try_return_with_exception()
303
304def try_return_temp(a):
305    b = a+2
306    try:
307        c = a+b
308        return c
309    finally:
310        print b-a
311
312def try_continue(a):
313    """
314    >>> i=1
315    >>> for i in range(3):
316    ...     try:
317    ...         continue
318    ...     finally:
319    ...         i+=1
320    >>> i
321    3
322    >>> try_continue(3)
323    3
324    """
325    i=1
326    for i in range(a):
327        try:
328            continue
329        finally:
330            i+=1
331    return i
332
333
334def try_return_none_1():
335    """
336    >>> try_return_none_1()
337    """
338    try:
339        return
340    finally:
341        return
342
343cdef extern from *:
344    ctypedef struct PyObject
345    void Py_INCREF(object)
346
347cdef PyObject* _none():
348    ret = None
349    Py_INCREF(ret)
350    return <PyObject*> ret
351
352def try_return_none_2():
353    """
354    >>> try_return_none_2()
355    """
356    try:
357        return <object> _none()
358    finally:
359        return <object> _none()
360
361def try_break():
362    """
363    >>> try_break()
364    """
365    for a in "abcd":
366        try:
367            if a == 'c':
368                break
369        except:
370            break
371
372
373def empty_try():
374    """
375    >>> empty_try()
376    1
377    """
378    try:
379        pass
380    finally:
381        return 1
382
383
384def empty_try_in_except_raise(raise_in_finally):
385    """
386    >>> empty_try_in_except_raise(False)
387    Traceback (most recent call last):
388    ValueError: HUHU
389    >>> empty_try_in_except_raise(True)
390    Traceback (most recent call last):
391    TypeError: OLA
392    """
393    try:
394        raise ValueError("HUHU")
395    except ValueError:
396        try:
397            pass
398        finally:
399            if raise_in_finally:
400                raise TypeError('OLA')
401        raise
402
403
404def try_all_cases(x):
405    """
406    >>> try_all_cases(None)
407    2
408    >>> try_all_cases('break')
409    4
410    >>> try_all_cases('raise')
411    Traceback (most recent call last):
412    ValueError
413    >>> try_all_cases('return')
414    3
415    >>> try_all_cases('tryraise')
416    Traceback (most recent call last):
417    TypeError
418    >>> try_all_cases('trybreak')
419    4
420    """
421    for i in range(3):
422        try:
423            if i == 0:
424                pass
425            elif i == 1:
426                continue
427            elif x == 'trybreak':
428                break
429            elif x == 'tryraise':
430                raise TypeError()
431            else:
432                return 2
433        finally:
434            if x == 'raise':
435                raise ValueError()
436            elif x == 'break':
437                break
438            elif x == 'return':
439                return 3
440    return 4
441
442
443def finally_yield(x):
444    """
445    >>> g = finally_yield(None)
446    >>> next(g)  # 1
447    1
448    >>> next(g)  # 2
449    1
450    >>> next(g)  # 3
451    Traceback (most recent call last):
452    StopIteration
453
454    >>> g = finally_yield('raise')
455    >>> next(g)  # raise 1
456    1
457    >>> next(g)  # raise 2
458    1
459    >>> next(g)  # raise 3
460    Traceback (most recent call last):
461    TypeError
462
463    >>> g = finally_yield('break')
464    >>> next(g)   # break 1
465    1
466    >>> next(g)   # break 2
467    1
468    >>> next(g)   # break 3
469    Traceback (most recent call last):
470    StopIteration
471    """
472    for i in range(3):
473        try:
474            if i == 0:
475                continue
476            elif x == 'raise':
477                raise TypeError()
478            elif x == 'break':
479                break
480            else:
481                return
482        finally:
483            yield 1
484
485
486def complex_finally_clause(x, obj):
487    """
488    >>> class T(object):
489    ...     def method(self, value):
490    ...         print(value)
491
492    >>> complex_finally_clause('finish', T())
493    module.py
494    module.py
495    module.py
496    99
497    >>> complex_finally_clause('tryreturn', T())
498    module.py
499    module.py
500    module.py
501    2
502    >>> complex_finally_clause('trybreak', T())
503    module.py
504    module.py
505    module.py
506    99
507    >>> complex_finally_clause('tryraise', T())
508    Traceback (most recent call last):
509    TypeError
510    """
511    name = 'module'
512    l = []
513    cdef object lobj = l
514
515    for i in range(3):
516        l[:] = [1, 2, 3]
517        try:
518            if i == 0:
519                pass
520            elif i == 1:
521                continue
522            elif x == 'trybreak':
523                break
524            elif x == 'tryraise':
525                raise TypeError()
526            elif x == 'tryreturn':
527                return 2
528            else:
529                pass
530        finally:
531            obj.method(name + '.py')
532            from contextlib import contextmanager
533            with contextmanager(lambda: (yield 1))() as y:
534                assert y == 1
535                a = 1
536            with nogil:
537                if i > 0:
538                    with gil:
539                        assert obj.method
540                        a = 2
541            # FIXME: prevent deep-copying inner functions
542            #def closure(l):
543            #    assert l == lobj
544            #closure()
545            assert name[0] in string.ascii_letters
546            string.Template("-- huhu $name --").substitute(**{'name': '(%s)' % name})
547            if a:
548                a = 3
549            del l[0], lobj[0]
550            assert all(i == 3 for i in l), l
551    return 99
552