TestIpythonMagic.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. # -*- coding: utf-8 -*-
  2. # tag: ipython
  3. """Tests for the Cython magics extension."""
  4. from __future__ import absolute_import
  5. import os
  6. import sys
  7. from contextlib import contextmanager
  8. from Cython.Build import IpythonMagic
  9. from Cython.TestUtils import CythonTest
  10. try:
  11. import IPython.testing.globalipapp
  12. except ImportError:
  13. # Disable tests and fake helpers for initialisation below.
  14. def skip_if_not_installed(_):
  15. return None
  16. else:
  17. def skip_if_not_installed(c):
  18. return c
  19. try:
  20. # disable IPython history thread before it gets started to avoid having to clean it up
  21. from IPython.core.history import HistoryManager
  22. HistoryManager.enabled = False
  23. except ImportError:
  24. pass
  25. code = u"""\
  26. def f(x):
  27. return 2*x
  28. """
  29. cython3_code = u"""\
  30. def f(int x):
  31. return 2 / x
  32. def call(x):
  33. return f(*(x,))
  34. """
  35. pgo_cython3_code = cython3_code + u"""\
  36. def main():
  37. for _ in range(100): call(5)
  38. main()
  39. """
  40. if sys.platform == 'win32':
  41. # not using IPython's decorators here because they depend on "nose"
  42. try:
  43. from unittest import skip as skip_win32
  44. except ImportError:
  45. # poor dev's silent @unittest.skip()
  46. def skip_win32(dummy):
  47. def _skip_win32(func):
  48. return None
  49. return _skip_win32
  50. else:
  51. def skip_win32(dummy):
  52. def _skip_win32(func):
  53. def wrapper(*args, **kwargs):
  54. func(*args, **kwargs)
  55. return wrapper
  56. return _skip_win32
  57. @skip_if_not_installed
  58. class TestIPythonMagic(CythonTest):
  59. @classmethod
  60. def setUpClass(cls):
  61. CythonTest.setUpClass()
  62. cls._ip = IPython.testing.globalipapp.get_ipython()
  63. def setUp(self):
  64. CythonTest.setUp(self)
  65. self._ip.extension_manager.load_extension('cython')
  66. def test_cython_inline(self):
  67. ip = self._ip
  68. ip.ex('a=10; b=20')
  69. result = ip.run_cell_magic('cython_inline', '', 'return a+b')
  70. self.assertEqual(result, 30)
  71. @skip_win32('Skip on Windows')
  72. def test_cython_pyximport(self):
  73. ip = self._ip
  74. module_name = '_test_cython_pyximport'
  75. ip.run_cell_magic('cython_pyximport', module_name, code)
  76. ip.ex('g = f(10)')
  77. self.assertEqual(ip.user_ns['g'], 20.0)
  78. ip.run_cell_magic('cython_pyximport', module_name, code)
  79. ip.ex('h = f(-10)')
  80. self.assertEqual(ip.user_ns['h'], -20.0)
  81. try:
  82. os.remove(module_name + '.pyx')
  83. except OSError:
  84. pass
  85. def test_cython(self):
  86. ip = self._ip
  87. ip.run_cell_magic('cython', '', code)
  88. ip.ex('g = f(10)')
  89. self.assertEqual(ip.user_ns['g'], 20.0)
  90. def test_cython_name(self):
  91. # The Cython module named 'mymodule' defines the function f.
  92. ip = self._ip
  93. ip.run_cell_magic('cython', '--name=mymodule', code)
  94. # This module can now be imported in the interactive namespace.
  95. ip.ex('import mymodule; g = mymodule.f(10)')
  96. self.assertEqual(ip.user_ns['g'], 20.0)
  97. def test_cython_language_level(self):
  98. # The Cython cell defines the functions f() and call().
  99. ip = self._ip
  100. ip.run_cell_magic('cython', '', cython3_code)
  101. ip.ex('g = f(10); h = call(10)')
  102. if sys.version_info[0] < 3:
  103. self.assertEqual(ip.user_ns['g'], 2 // 10)
  104. self.assertEqual(ip.user_ns['h'], 2 // 10)
  105. else:
  106. self.assertEqual(ip.user_ns['g'], 2.0 / 10.0)
  107. self.assertEqual(ip.user_ns['h'], 2.0 / 10.0)
  108. def test_cython3(self):
  109. # The Cython cell defines the functions f() and call().
  110. ip = self._ip
  111. ip.run_cell_magic('cython', '-3', cython3_code)
  112. ip.ex('g = f(10); h = call(10)')
  113. self.assertEqual(ip.user_ns['g'], 2.0 / 10.0)
  114. self.assertEqual(ip.user_ns['h'], 2.0 / 10.0)
  115. def test_cython2(self):
  116. # The Cython cell defines the functions f() and call().
  117. ip = self._ip
  118. ip.run_cell_magic('cython', '-2', cython3_code)
  119. ip.ex('g = f(10); h = call(10)')
  120. self.assertEqual(ip.user_ns['g'], 2 // 10)
  121. self.assertEqual(ip.user_ns['h'], 2 // 10)
  122. @skip_win32('Skip on Windows')
  123. def test_cython3_pgo(self):
  124. # The Cython cell defines the functions f() and call().
  125. ip = self._ip
  126. ip.run_cell_magic('cython', '-3 --pgo', pgo_cython3_code)
  127. ip.ex('g = f(10); h = call(10); main()')
  128. self.assertEqual(ip.user_ns['g'], 2.0 / 10.0)
  129. self.assertEqual(ip.user_ns['h'], 2.0 / 10.0)
  130. @skip_win32('Skip on Windows')
  131. def test_extlibs(self):
  132. ip = self._ip
  133. code = u"""
  134. from libc.math cimport sin
  135. x = sin(0.0)
  136. """
  137. ip.user_ns['x'] = 1
  138. ip.run_cell_magic('cython', '-l m', code)
  139. self.assertEqual(ip.user_ns['x'], 0)
  140. def test_cython_verbose(self):
  141. ip = self._ip
  142. ip.run_cell_magic('cython', '--verbose', code)
  143. ip.ex('g = f(10)')
  144. self.assertEqual(ip.user_ns['g'], 20.0)
  145. def test_cython_verbose_thresholds(self):
  146. @contextmanager
  147. def mock_distutils():
  148. class MockLog:
  149. DEBUG = 1
  150. INFO = 2
  151. thresholds = [INFO]
  152. def set_threshold(self, val):
  153. self.thresholds.append(val)
  154. return self.thresholds[-2]
  155. new_log = MockLog()
  156. old_log = IpythonMagic.distutils.log
  157. try:
  158. IpythonMagic.distutils.log = new_log
  159. yield new_log
  160. finally:
  161. IpythonMagic.distutils.log = old_log
  162. ip = self._ip
  163. with mock_distutils() as verbose_log:
  164. ip.run_cell_magic('cython', '--verbose', code)
  165. ip.ex('g = f(10)')
  166. self.assertEqual(ip.user_ns['g'], 20.0)
  167. self.assertEquals([verbose_log.INFO, verbose_log.DEBUG, verbose_log.INFO],
  168. verbose_log.thresholds)
  169. with mock_distutils() as normal_log:
  170. ip.run_cell_magic('cython', '', code)
  171. ip.ex('g = f(10)')
  172. self.assertEqual(ip.user_ns['g'], 20.0)
  173. self.assertEquals([normal_log.INFO], normal_log.thresholds)