ai-content-maker/.venv/Lib/site-packages/Cython/Build/Tests/TestIpythonMagic.py

296 lines
9.2 KiB
Python
Raw Normal View History

2024-05-03 04:18:51 +03:00
# -*- coding: utf-8 -*-
# tag: ipython
"""Tests for the Cython magics extension."""
from __future__ import absolute_import
import os
import io
import sys
from contextlib import contextmanager
from unittest import skipIf
from Cython.Build import IpythonMagic
from Cython.TestUtils import CythonTest
from Cython.Compiler.Annotate import AnnotationCCodeWriter
try:
import IPython.testing.globalipapp
except ImportError:
# Disable tests and fake helpers for initialisation below.
def skip_if_not_installed(_):
return None
else:
def skip_if_not_installed(c):
return c
# not using IPython's decorators here because they depend on "nose"
skip_win32 = skipIf(sys.platform == 'win32', "Skip on Windows")
skip_py27 = skipIf(sys.version_info[:2] == (2,7), "Disabled in Py2.7")
try:
# disable IPython history thread before it gets started to avoid having to clean it up
from IPython.core.history import HistoryManager
HistoryManager.enabled = False
except ImportError:
pass
@contextmanager
def capture_output():
backup = sys.stdout, sys.stderr
try:
replacement = [
io.TextIOWrapper(io.BytesIO(), encoding=sys.stdout.encoding),
io.TextIOWrapper(io.BytesIO(), encoding=sys.stderr.encoding),
]
sys.stdout, sys.stderr = replacement
output = []
yield output
finally:
sys.stdout, sys.stderr = backup
for wrapper in replacement:
wrapper.seek(0) # rewind
output.append(wrapper.read())
wrapper.close()
code = u"""\
def f(x):
return 2*x
"""
cython3_code = u"""\
def f(int x):
return 2 / x
def call(x):
return f(*(x,))
"""
pgo_cython3_code = cython3_code + u"""\
def main():
for _ in range(100): call(5)
main()
"""
compile_error_code = u'''\
cdef extern from *:
"""
xxx a=1;
"""
int a;
def doit():
return a
'''
compile_warning_code = u'''\
cdef extern from *:
"""
#pragma message ( "CWarning" )
int a = 42;
"""
int a;
def doit():
return a
'''
@skip_if_not_installed
class TestIPythonMagic(CythonTest):
@classmethod
def setUpClass(cls):
CythonTest.setUpClass()
cls._ip = IPython.testing.globalipapp.get_ipython()
def setUp(self):
CythonTest.setUp(self)
self._ip.extension_manager.load_extension('cython')
def test_cython_inline(self):
ip = self._ip
ip.ex('a=10; b=20')
result = ip.run_cell_magic('cython_inline', '', 'return a+b')
self.assertEqual(result, 30)
@skip_win32
def test_cython_pyximport(self):
ip = self._ip
module_name = '_test_cython_pyximport'
ip.run_cell_magic('cython_pyximport', module_name, code)
ip.ex('g = f(10)')
self.assertEqual(ip.user_ns['g'], 20.0)
ip.run_cell_magic('cython_pyximport', module_name, code)
ip.ex('h = f(-10)')
self.assertEqual(ip.user_ns['h'], -20.0)
try:
os.remove(module_name + '.pyx')
except OSError:
pass
def test_cython(self):
ip = self._ip
ip.run_cell_magic('cython', '', code)
ip.ex('g = f(10)')
self.assertEqual(ip.user_ns['g'], 20.0)
def test_cython_name(self):
# The Cython module named 'mymodule' defines the function f.
ip = self._ip
ip.run_cell_magic('cython', '--name=mymodule', code)
# This module can now be imported in the interactive namespace.
ip.ex('import mymodule; g = mymodule.f(10)')
self.assertEqual(ip.user_ns['g'], 20.0)
def test_cython_language_level(self):
# The Cython cell defines the functions f() and call().
ip = self._ip
ip.run_cell_magic('cython', '', cython3_code)
ip.ex('g = f(10); h = call(10)')
if sys.version_info[0] < 3:
self.assertEqual(ip.user_ns['g'], 2 // 10)
self.assertEqual(ip.user_ns['h'], 2 // 10)
else:
self.assertEqual(ip.user_ns['g'], 2.0 / 10.0)
self.assertEqual(ip.user_ns['h'], 2.0 / 10.0)
def test_cython3(self):
# The Cython cell defines the functions f() and call().
ip = self._ip
ip.run_cell_magic('cython', '-3', cython3_code)
ip.ex('g = f(10); h = call(10)')
self.assertEqual(ip.user_ns['g'], 2.0 / 10.0)
self.assertEqual(ip.user_ns['h'], 2.0 / 10.0)
def test_cython2(self):
# The Cython cell defines the functions f() and call().
ip = self._ip
ip.run_cell_magic('cython', '-2', cython3_code)
ip.ex('g = f(10); h = call(10)')
self.assertEqual(ip.user_ns['g'], 2 // 10)
self.assertEqual(ip.user_ns['h'], 2 // 10)
def test_cython_compile_error_shown(self):
ip = self._ip
with capture_output() as out:
ip.run_cell_magic('cython', '-3', compile_error_code)
captured_out, captured_err = out
# it could be that c-level output is captured by distutil-extension
# (and not by us) and is printed to stdout:
captured_all = captured_out + "\n" + captured_err
self.assertTrue("error" in captured_all, msg="error in " + captured_all)
def test_cython_link_error_shown(self):
ip = self._ip
with capture_output() as out:
ip.run_cell_magic('cython', '-3 -l=xxxxxxxx', code)
captured_out, captured_err = out
# it could be that c-level output is captured by distutil-extension
# (and not by us) and is printed to stdout:
captured_all = captured_out + "\n!" + captured_err
self.assertTrue("error" in captured_all, msg="error in " + captured_all)
def test_cython_warning_shown(self):
ip = self._ip
with capture_output() as out:
# force rebuild, otherwise no warning as after the first success
# no build step is performed
ip.run_cell_magic('cython', '-3 -f', compile_warning_code)
captured_out, captured_err = out
# check that warning was printed to stdout even if build hasn't failed
self.assertTrue("CWarning" in captured_out)
@skip_py27 # Not strictly broken in Py2.7 but currently fails in CI due to C compiler issues.
@skip_win32
def test_cython3_pgo(self):
# The Cython cell defines the functions f() and call().
ip = self._ip
ip.run_cell_magic('cython', '-3 --pgo', pgo_cython3_code)
ip.ex('g = f(10); h = call(10); main()')
self.assertEqual(ip.user_ns['g'], 2.0 / 10.0)
self.assertEqual(ip.user_ns['h'], 2.0 / 10.0)
@skip_win32
def test_extlibs(self):
ip = self._ip
code = u"""
from libc.math cimport sin
x = sin(0.0)
"""
ip.user_ns['x'] = 1
ip.run_cell_magic('cython', '-l m', code)
self.assertEqual(ip.user_ns['x'], 0)
def test_cython_verbose(self):
ip = self._ip
ip.run_cell_magic('cython', '--verbose', code)
ip.ex('g = f(10)')
self.assertEqual(ip.user_ns['g'], 20.0)
def test_cython_verbose_thresholds(self):
@contextmanager
def mock_distutils():
class MockLog:
DEBUG = 1
INFO = 2
thresholds = [INFO]
def set_threshold(self, val):
self.thresholds.append(val)
return self.thresholds[-2]
new_log = MockLog()
old_log = IpythonMagic.distutils.log
try:
IpythonMagic.distutils.log = new_log
yield new_log
finally:
IpythonMagic.distutils.log = old_log
ip = self._ip
with mock_distutils() as verbose_log:
ip.run_cell_magic('cython', '--verbose', code)
ip.ex('g = f(10)')
self.assertEqual(ip.user_ns['g'], 20.0)
self.assertEqual([verbose_log.INFO, verbose_log.DEBUG, verbose_log.INFO],
verbose_log.thresholds)
with mock_distutils() as normal_log:
ip.run_cell_magic('cython', '', code)
ip.ex('g = f(10)')
self.assertEqual(ip.user_ns['g'], 20.0)
self.assertEqual([normal_log.INFO], normal_log.thresholds)
def test_cython_no_annotate(self):
ip = self._ip
html = ip.run_cell_magic('cython', '', code)
self.assertTrue(html is None)
def test_cython_annotate(self):
ip = self._ip
html = ip.run_cell_magic('cython', '--annotate', code)
# somewhat brittle way to differentiate between annotated htmls
# with/without complete source code:
self.assertTrue(AnnotationCCodeWriter.COMPLETE_CODE_TITLE not in html.data)
def test_cython_annotate_default(self):
ip = self._ip
html = ip.run_cell_magic('cython', '-a', code)
# somewhat brittle way to differentiate between annotated htmls
# with/without complete source code:
self.assertTrue(AnnotationCCodeWriter.COMPLETE_CODE_TITLE not in html.data)
def test_cython_annotate_complete_c_code(self):
ip = self._ip
html = ip.run_cell_magic('cython', '--annotate-fullc', code)
# somewhat brittle way to differentiate between annotated htmls
# with/without complete source code:
self.assertTrue(AnnotationCCodeWriter.COMPLETE_CODE_TITLE in html.data)