1PYTHON setup.py build_ext --inplace 2PYTHON test_profile.py 3 4######## setup.py ########### 5 6from distutils.extension import Extension 7from distutils.core import setup 8from Cython.Build import cythonize 9 10extensions = [ 11 Extension("collatz", ["collatz.pyx"], define_macros=[('CYTHON_TRACE', '1')]) 12] 13 14setup( 15 ext_modules = cythonize(extensions) 16) 17 18######## test_profile.py ########### 19 20try: 21 import line_profiler 22except ImportError: 23 print("No line profiler, skipping test.") 24 import sys 25 sys.exit(0) 26 27 28def assert_stats(profile, name): 29 profile.print_stats() 30 stats = profile.get_stats() 31 assert len(stats.timings) > 0, "No profile stats." 32 for key, timings in stats.timings.items(): 33 if key[-1] == name: 34 assert len(timings) > 0 35 break 36 else: 37 raise ValueError("No stats for %s." % name) 38 39 40from collatz import collatz 41func = collatz 42profile = line_profiler.LineProfiler(func) 43profile.runcall(func, 19) 44assert_stats(profile, func.__name__) 45 46from collatz import cp_collatz 47func = cp_collatz 48profile = line_profiler.LineProfiler(func) 49profile.runcall(func, 19) 50assert_stats(profile, func.__name__) 51 52from collatz import run_generator, cy_generator 53func = cy_generator 54profile = line_profiler.LineProfiler(func) 55profile.runcall(run_generator, 19) 56assert_stats(profile, func.__name__) 57 58from collatz import run_coro, cy_coro 59func = cy_coro 60profile = line_profiler.LineProfiler(func) 61profile.runcall(run_coro, 19) 62assert_stats(profile, func.__name__) 63 64from collatz import PyClass 65obj = PyClass() 66func = obj.py_pymethod 67profile = line_profiler.LineProfiler(func) 68profile.runcall(func) 69assert_stats(profile, func.__name__) 70 71from collatz import CClass 72obj = CClass() 73func = obj.c_pymethod 74profile = line_profiler.LineProfiler(func) 75profile.runcall(func) 76assert_stats(profile, func.__name__) 77 78func = obj.cp_pymethod 79profile = line_profiler.LineProfiler(func) 80profile.runcall(func, 19) 81assert_stats(profile, func.__name__) 82 83 84######## collatz.pyx ########### 85# cython: linetrace=True 86 87cimport cython 88 89@cython.binding(True) 90def collatz(n): 91 while n > 1: 92 if n % 2 == 0: 93 n //= 2 94 else: 95 n = 3*n+1 96 97 98@cython.binding(True) 99cpdef cp_collatz(n): 100 while n > 1: 101 if n % 2 == 0: 102 n //= 2 103 else: 104 n = 3*n+1 105 106 107@cython.binding(True) 108def cy_generator(int n): 109 x = 1 110 for i in range(n): 111 yield x + 2 112 113 114@cython.binding(True) 115def run_generator(n): 116 assert len(list(cy_generator(n))) == n 117 118 119@cython.binding(True) 120async def cy_coro(int n): 121 while n > 1: 122 if n % 2 == 0: 123 n //= 2 124 else: 125 n = 3*n+1 126 127 128@cython.binding(True) 129def run_coro(n): 130 coro = cy_coro(n) 131 try: 132 coro.send(None) 133 except StopIteration: 134 assert True 135 else: 136 assert False, "Coroutine did not raise" 137 138 139@cython.binding(True) 140class PyClass(object): 141 def py_pymethod(self): 142 x = 1 143 for i in range(10): 144 a = x + 2 145 return a * 3 146 147 148@cython.binding(True) 149cdef class CClass: 150 def c_pymethod(self, c=2): 151 for i in range(10): 152 a = c + 1 153 y = self.cmethod(c + a) 154 return y * 4 155 156 cpdef cp_pymethod(self, r): 157 for i in range(10): 158 a = r + 1 159 z = self.c_pymethod(a) + self.cmethod(r) 160 return z * 2 161 162 cdef cmethod(self, s): 163 for i in range(10): 164 p = s + 3 165 return p * 5 166