1# mode: run 2# tag: except 3 4# test the code object cache that is being used in exception raising 5 6### low level tests 7 8cimport cython 9 10cdef extern from *: 11 # evil hack to access the internal utility function 12 ctypedef struct PyCodeObject 13 ctypedef struct __Pyx_CodeObjectCacheEntry: 14 int code_line 15 PyCodeObject* code_object 16 int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) 17 18def test_lowlevel_bisect2(*indices): 19 """ 20 >>> test_lowlevel_bisect2(1, 2, 3, 4, 5, 6) 21 [0, 0, 1, 1, 2, 2] 22 """ 23 cdef __Pyx_CodeObjectCacheEntry* cache = [ 24 __Pyx_CodeObjectCacheEntry(2, NULL), 25 __Pyx_CodeObjectCacheEntry(4, NULL), 26 ] 27 return [ __pyx_bisect_code_objects(cache, 2, i) 28 for i in indices ] 29 30def test_lowlevel_bisect5(*indices): 31 """ 32 >>> test_lowlevel_bisect5(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) 33 [0, 1, 2, 2, 2, 3, 3, 3, 4, 5, 5] 34 """ 35 cdef __Pyx_CodeObjectCacheEntry* cache = [ 36 __Pyx_CodeObjectCacheEntry(1, NULL), 37 __Pyx_CodeObjectCacheEntry(2, NULL), 38 __Pyx_CodeObjectCacheEntry(5, NULL), 39 __Pyx_CodeObjectCacheEntry(8, NULL), 40 __Pyx_CodeObjectCacheEntry(9, NULL), 41 ] 42 return [ __pyx_bisect_code_objects(cache, 5, i) 43 for i in indices ] 44 45def test_lowlevel_bisect6(*indices): 46 """ 47 >>> test_lowlevel_bisect6(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13) 48 [0, 0, 1, 2, 2, 2, 3, 3, 4, 5, 5, 5, 6] 49 """ 50 cdef __Pyx_CodeObjectCacheEntry* cache = [ 51 __Pyx_CodeObjectCacheEntry(2, NULL), 52 __Pyx_CodeObjectCacheEntry(3, NULL), 53 __Pyx_CodeObjectCacheEntry(6, NULL), 54 __Pyx_CodeObjectCacheEntry(8, NULL), 55 __Pyx_CodeObjectCacheEntry(9, NULL), 56 __Pyx_CodeObjectCacheEntry(12, NULL), 57 ] 58 return [ __pyx_bisect_code_objects(cache, 6, i) 59 for i in indices ] 60 61### Python level tests 62 63import sys 64 65def tb(): 66 return sys.exc_info()[-1] 67 68def raise_keyerror(): 69 raise KeyError 70 71def check_code_object_identity_recursively(tb1, tb2): 72 if tb1 is None or tb2 is None: 73 return 74 code1, code2 = tb1.tb_frame.f_code, tb2.tb_frame.f_code 75 if code1 is not code2: 76 print('%s != %s' % (code1, code2)) 77 check_code_object_identity_recursively(tb1.tb_next, tb2.tb_next) 78 79def assert_simple_code_object_reuse(): 80 """ 81 >>> try: assert_simple_code_object_reuse() 82 ... except KeyError: t1 = tb() 83 >>> try: assert_simple_code_object_reuse() 84 ... except KeyError: t2 = tb() 85 >>> check_code_object_identity_recursively(t1.tb_next, t2.tb_next) 86 """ 87 raise KeyError 88 89def assert_multi_step_code_object_reuse(recursions=0): 90 """ 91 >>> for depth in range(5): 92 ... try: assert_multi_step_code_object_reuse(depth) 93 ... except KeyError: t1 = tb() 94 ... try: assert_multi_step_code_object_reuse(depth) 95 ... except KeyError: t2 = tb() 96 ... check_code_object_identity_recursively(t1.tb_next, t2.tb_next) 97 """ 98 if recursions: 99 assert_multi_step_code_object_reuse(recursions-1) 100 else: 101 raise_keyerror() 102 103def assert_simple_code_object_reuse_fused(cython.floating dummy): 104 """ 105 DISABLED: searching for code objects based on C lineno breaks for specializations 106 107 >> try: assert_simple_code_object_reuse_fused["float"](1.0) 108 ... except KeyError: t1 = tb() 109 >> try: assert_simple_code_object_reuse_fused["double"](1.0) 110 ... except KeyError: t2 = tb() 111 >> check_code_object_identity_recursively(t1.tb_next, t2.tb_next) 112 """ 113 raise KeyError 114 115def assert_multi_step_code_object_reuse_fused(recursions=0, cython.floating dummy = 2.0): 116 """ 117 DISABLED: searching for code objects based on C lineno breaks for specializations 118 119 >> for depth in range(5): 120 ... try: assert_multi_step_code_object_reuse_fused(depth, 1.0) 121 ... except KeyError: t1 = tb() 122 ... try: assert_multi_step_code_object_reuse_fused(depth, 1.0) 123 ... except KeyError: t2 = tb() 124 ... check_code_object_identity_recursively(t1.tb_next, t2.tb_next) 125 """ 126 if recursions: 127 assert_multi_step_code_object_reuse(recursions-1) 128 else: 129 raise_keyerror() 130