reconnect moved files to git repo

This commit is contained in:
root
2025-08-01 04:33:03 -04:00
commit 5d3c35492d
23190 changed files with 4750716 additions and 0 deletions

View File

@ -0,0 +1,119 @@
import difflib
import glob
import gzip
import os
import sys
import tempfile
import unittest
import Cython.Build.Dependencies
import Cython.Utils
from Cython.TestUtils import CythonTest
class TestCyCache(CythonTest):
def setUp(self):
CythonTest.setUp(self)
self.temp_dir = tempfile.mkdtemp(
prefix='cycache-test',
dir='TEST_TMP' if os.path.isdir('TEST_TMP') else None)
self.src_dir = tempfile.mkdtemp(prefix='src', dir=self.temp_dir)
self.cache_dir = tempfile.mkdtemp(prefix='cache', dir=self.temp_dir)
def cache_files(self, file_glob):
return glob.glob(os.path.join(self.cache_dir, file_glob))
def fresh_cythonize(self, *args, **kwargs):
Cython.Utils.clear_function_caches()
Cython.Build.Dependencies._dep_tree = None # discard method caches
Cython.Build.Dependencies.cythonize(*args, **kwargs)
def test_cycache_switch(self):
content1 = 'value = 1\n'
content2 = 'value = 2\n'
a_pyx = os.path.join(self.src_dir, 'a.pyx')
a_c = a_pyx[:-4] + '.c'
with open(a_pyx, 'w') as f:
f.write(content1)
self.fresh_cythonize(a_pyx, cache=self.cache_dir)
self.fresh_cythonize(a_pyx, cache=self.cache_dir)
self.assertEqual(1, len(self.cache_files('a.c*')))
with open(a_c) as f:
a_contents1 = f.read()
os.unlink(a_c)
with open(a_pyx, 'w') as f:
f.write(content2)
self.fresh_cythonize(a_pyx, cache=self.cache_dir)
with open(a_c) as f:
a_contents2 = f.read()
os.unlink(a_c)
self.assertNotEqual(a_contents1, a_contents2, 'C file not changed!')
self.assertEqual(2, len(self.cache_files('a.c*')))
with open(a_pyx, 'w') as f:
f.write(content1)
self.fresh_cythonize(a_pyx, cache=self.cache_dir)
self.assertEqual(2, len(self.cache_files('a.c*')))
with open(a_c) as f:
a_contents = f.read()
self.assertEqual(
a_contents, a_contents1,
msg='\n'.join(list(difflib.unified_diff(
a_contents.split('\n'), a_contents1.split('\n')))[:10]))
def test_cycache_uses_cache(self):
a_pyx = os.path.join(self.src_dir, 'a.pyx')
a_c = a_pyx[:-4] + '.c'
with open(a_pyx, 'w') as f:
f.write('pass')
self.fresh_cythonize(a_pyx, cache=self.cache_dir)
a_cache = os.path.join(self.cache_dir, os.listdir(self.cache_dir)[0])
with gzip.GzipFile(a_cache, 'wb') as gzipfile:
gzipfile.write('fake stuff'.encode('ascii'))
os.unlink(a_c)
self.fresh_cythonize(a_pyx, cache=self.cache_dir)
with open(a_c) as f:
a_contents = f.read()
self.assertEqual(a_contents, 'fake stuff',
'Unexpected contents: %s...' % a_contents[:100])
def test_multi_file_output(self):
a_pyx = os.path.join(self.src_dir, 'a.pyx')
a_c = a_pyx[:-4] + '.c'
a_h = a_pyx[:-4] + '.h'
a_api_h = a_pyx[:-4] + '_api.h'
with open(a_pyx, 'w') as f:
f.write('cdef public api int foo(int x): return x\n')
self.fresh_cythonize(a_pyx, cache=self.cache_dir)
expected = [a_c, a_h, a_api_h]
for output in expected:
self.assertTrue(os.path.exists(output), output)
os.unlink(output)
self.fresh_cythonize(a_pyx, cache=self.cache_dir)
for output in expected:
self.assertTrue(os.path.exists(output), output)
def test_options_invalidation(self):
hash_pyx = os.path.join(self.src_dir, 'options.pyx')
hash_c = hash_pyx[:-len('.pyx')] + '.c'
with open(hash_pyx, 'w') as f:
f.write('pass')
self.fresh_cythonize(hash_pyx, cache=self.cache_dir, cplus=False)
self.assertEqual(1, len(self.cache_files('options.c*')))
os.unlink(hash_c)
self.fresh_cythonize(hash_pyx, cache=self.cache_dir, cplus=True)
self.assertEqual(2, len(self.cache_files('options.c*')))
os.unlink(hash_c)
self.fresh_cythonize(hash_pyx, cache=self.cache_dir, cplus=False, show_version=False)
self.assertEqual(2, len(self.cache_files('options.c*')))
os.unlink(hash_c)
self.fresh_cythonize(hash_pyx, cache=self.cache_dir, cplus=False, show_version=True)
self.assertEqual(2, len(self.cache_files('options.c*')))

View File

@ -0,0 +1,482 @@
from Cython.Build.Cythonize import (
create_args_parser, parse_args_raw, parse_args,
parallel_compiles
)
from Cython.Compiler import Options
from Cython.Compiler.Tests.Utils import backup_Options, restore_Options, check_global_options
from unittest import TestCase
import sys
try:
from StringIO import StringIO
except ImportError:
from io import StringIO # doesn't accept 'str' in Py2
class TestCythonizeArgsParser(TestCase):
def setUp(self):
TestCase.setUp(self)
self.parse_args = lambda x, parser=create_args_parser() : parse_args_raw(parser, x)
def are_default(self, options, skip):
# empty containers
empty_containers = ['directives', 'compile_time_env', 'options', 'excludes']
are_none = ['language_level', 'annotate', 'build', 'build_inplace', 'force', 'quiet', 'lenient', 'keep_going', 'no_docstrings']
for opt_name in empty_containers:
if len(getattr(options, opt_name))!=0 and (opt_name not in skip):
self.assertEqual(opt_name,"", msg="For option "+opt_name)
return False
for opt_name in are_none:
if (getattr(options, opt_name) is not None) and (opt_name not in skip):
self.assertEqual(opt_name,"", msg="For option "+opt_name)
return False
if options.parallel!=parallel_compiles and ('parallel' not in skip):
return False
return True
# testing directives:
def test_directive_short(self):
options, args = self.parse_args(['-X', 'cdivision=True'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['directives']))
self.assertEqual(options.directives['cdivision'], True)
def test_directive_long(self):
options, args = self.parse_args(['--directive', 'cdivision=True'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['directives']))
self.assertEqual(options.directives['cdivision'], True)
def test_directive_multiple(self):
options, args = self.parse_args(['-X', 'cdivision=True', '-X', 'c_string_type=bytes'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['directives']))
self.assertEqual(options.directives['cdivision'], True)
self.assertEqual(options.directives['c_string_type'], 'bytes')
def test_directive_multiple_v2(self):
options, args = self.parse_args(['-X', 'cdivision=True,c_string_type=bytes'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['directives']))
self.assertEqual(options.directives['cdivision'], True)
self.assertEqual(options.directives['c_string_type'], 'bytes')
def test_directive_value_yes(self):
options, args = self.parse_args(['-X', 'cdivision=YeS'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['directives']))
self.assertEqual(options.directives['cdivision'], True)
def test_directive_value_no(self):
options, args = self.parse_args(['-X', 'cdivision=no'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['directives']))
self.assertEqual(options.directives['cdivision'], False)
def test_directive_value_invalid(self):
with self.assertRaises(ValueError) as context:
options, args = self.parse_args(['-X', 'cdivision=sadfasd'])
def test_directive_key_invalid(self):
with self.assertRaises(ValueError) as context:
options, args = self.parse_args(['-X', 'abracadabra'])
def test_directive_no_value(self):
with self.assertRaises(ValueError) as context:
options, args = self.parse_args(['-X', 'cdivision'])
def test_directives_types(self):
directives = {
'auto_pickle': True,
'c_string_type': 'bytearray',
'c_string_type': 'bytes',
'c_string_type': 'str',
'c_string_type': 'bytearray',
'c_string_type': 'unicode',
'c_string_encoding' : 'ascii',
'language_level' : 2,
'language_level' : 3,
'language_level' : '3str',
'set_initial_path' : 'my_initial_path',
}
for key, value in directives.items():
cmd = '{key}={value}'.format(key=key, value=str(value))
options, args = self.parse_args(['-X', cmd])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['directives']), msg = "Error for option: "+cmd)
self.assertEqual(options.directives[key], value, msg = "Error for option: "+cmd)
def test_directives_wrong(self):
directives = {
'auto_pickle': 42, # for bool type
'auto_pickle': 'NONONO', # for bool type
'c_string_type': 'bites',
#'c_string_encoding' : 'a',
#'language_level' : 4,
}
for key, value in directives.items():
cmd = '{key}={value}'.format(key=key, value=str(value))
with self.assertRaises(ValueError, msg = "Error for option: "+cmd) as context:
options, args = self.parse_args(['-X', cmd])
def test_compile_time_env_short(self):
options, args = self.parse_args(['-E', 'MYSIZE=10'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['compile_time_env']))
self.assertEqual(options.compile_time_env['MYSIZE'], 10)
def test_compile_time_env_long(self):
options, args = self.parse_args(['--compile-time-env', 'MYSIZE=10'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['compile_time_env']))
self.assertEqual(options.compile_time_env['MYSIZE'], 10)
def test_compile_time_env_multiple(self):
options, args = self.parse_args(['-E', 'MYSIZE=10', '-E', 'ARRSIZE=11'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['compile_time_env']))
self.assertEqual(options.compile_time_env['MYSIZE'], 10)
self.assertEqual(options.compile_time_env['ARRSIZE'], 11)
def test_compile_time_env_multiple_v2(self):
options, args = self.parse_args(['-E', 'MYSIZE=10,ARRSIZE=11'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['compile_time_env']))
self.assertEqual(options.compile_time_env['MYSIZE'], 10)
self.assertEqual(options.compile_time_env['ARRSIZE'], 11)
#testing options
def test_option_short(self):
options, args = self.parse_args(['-s', 'docstrings=True'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], True)
def test_option_long(self):
options, args = self.parse_args(['--option', 'docstrings=True'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], True)
def test_option_multiple(self):
options, args = self.parse_args(['-s', 'docstrings=True', '-s', 'buffer_max_dims=8'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], True)
self.assertEqual(options.options['buffer_max_dims'], True) # really?
def test_option_multiple_v2(self):
options, args = self.parse_args(['-s', 'docstrings=True,buffer_max_dims=8'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], True)
self.assertEqual(options.options['buffer_max_dims'], True) # really?
def test_option_value_yes(self):
options, args = self.parse_args(['-s', 'docstrings=YeS'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], True)
def test_option_value_4242(self):
options, args = self.parse_args(['-s', 'docstrings=4242'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], True)
def test_option_value_0(self):
options, args = self.parse_args(['-s', 'docstrings=0'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], False)
def test_option_value_emptystr(self):
options, args = self.parse_args(['-s', 'docstrings='])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], True)
def test_option_value_a_str(self):
options, args = self.parse_args(['-s', 'docstrings=BB'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], True)
def test_option_value_no(self):
options, args = self.parse_args(['-s', 'docstrings=nO'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], False)
def test_option_no_value(self):
options, args = self.parse_args(['-s', 'docstrings'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], True)
def test_option_any_key(self):
options, args = self.parse_args(['-s', 'abracadabra'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['abracadabra'], True)
def test_language_level_2(self):
options, args = self.parse_args(['-2'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['language_level']))
self.assertEqual(options.language_level, 2)
def test_language_level_3(self):
options, args = self.parse_args(['-3'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['language_level']))
self.assertEqual(options.language_level, 3)
def test_language_level_3str(self):
options, args = self.parse_args(['--3str'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['language_level']))
self.assertEqual(options.language_level, '3str')
def test_annotate_short(self):
options, args = self.parse_args(['-a'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['annotate']))
self.assertEqual(options.annotate, 'default')
def test_annotate_long(self):
options, args = self.parse_args(['--annotate'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['annotate']))
self.assertEqual(options.annotate, 'default')
def test_annotate_fullc(self):
options, args = self.parse_args(['--annotate-fullc'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['annotate']))
self.assertEqual(options.annotate, 'fullc')
def test_annotate_and_positional(self):
options, args = self.parse_args(['-a', 'foo.pyx'])
self.assertEqual(args, ['foo.pyx'])
self.assertTrue(self.are_default(options, ['annotate']))
self.assertEqual(options.annotate, 'default')
def test_annotate_and_optional(self):
options, args = self.parse_args(['-a', '--3str'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['annotate', 'language_level']))
self.assertEqual(options.annotate, 'default')
self.assertEqual(options.language_level, '3str')
def test_exclude_short(self):
options, args = self.parse_args(['-x', '*.pyx'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['excludes']))
self.assertTrue('*.pyx' in options.excludes)
def test_exclude_long(self):
options, args = self.parse_args(['--exclude', '*.pyx'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['excludes']))
self.assertTrue('*.pyx' in options.excludes)
def test_exclude_multiple(self):
options, args = self.parse_args(['--exclude', '*.pyx', '--exclude', '*.py', ])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['excludes']))
self.assertEqual(options.excludes, ['*.pyx', '*.py'])
def test_build_short(self):
options, args = self.parse_args(['-b'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['build']))
self.assertEqual(options.build, True)
def test_build_long(self):
options, args = self.parse_args(['--build'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['build']))
self.assertEqual(options.build, True)
def test_inplace_short(self):
options, args = self.parse_args(['-i'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['build_inplace']))
self.assertEqual(options.build_inplace, True)
def test_inplace_long(self):
options, args = self.parse_args(['--inplace'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['build_inplace']))
self.assertEqual(options.build_inplace, True)
def test_parallel_short(self):
options, args = self.parse_args(['-j', '42'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['parallel']))
self.assertEqual(options.parallel, 42)
def test_parallel_long(self):
options, args = self.parse_args(['--parallel', '42'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['parallel']))
self.assertEqual(options.parallel, 42)
def test_force_short(self):
options, args = self.parse_args(['-f'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['force']))
self.assertEqual(options.force, True)
def test_force_long(self):
options, args = self.parse_args(['--force'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['force']))
self.assertEqual(options.force, True)
def test_quite_short(self):
options, args = self.parse_args(['-q'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['quiet']))
self.assertEqual(options.quiet, True)
def test_quite_long(self):
options, args = self.parse_args(['--quiet'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['quiet']))
self.assertEqual(options.quiet, True)
def test_lenient_long(self):
options, args = self.parse_args(['--lenient'])
self.assertTrue(self.are_default(options, ['lenient']))
self.assertFalse(args)
self.assertEqual(options.lenient, True)
def test_keep_going_short(self):
options, args = self.parse_args(['-k'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['keep_going']))
self.assertEqual(options.keep_going, True)
def test_keep_going_long(self):
options, args = self.parse_args(['--keep-going'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['keep_going']))
self.assertEqual(options.keep_going, True)
def test_no_docstrings_long(self):
options, args = self.parse_args(['--no-docstrings'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['no_docstrings']))
self.assertEqual(options.no_docstrings, True)
def test_file_name(self):
options, args = self.parse_args(['file1.pyx', 'file2.pyx'])
self.assertEqual(len(args), 2)
self.assertEqual(args[0], 'file1.pyx')
self.assertEqual(args[1], 'file2.pyx')
self.assertTrue(self.are_default(options, []))
def test_option_first(self):
options, args = self.parse_args(['-i', 'file.pyx'])
self.assertEqual(args, ['file.pyx'])
self.assertEqual(options.build_inplace, True)
self.assertTrue(self.are_default(options, ['build_inplace']))
def test_file_inbetween(self):
options, args = self.parse_args(['-i', 'file.pyx', '-a'])
self.assertEqual(args, ['file.pyx'])
self.assertEqual(options.build_inplace, True)
self.assertEqual(options.annotate, 'default')
self.assertTrue(self.are_default(options, ['build_inplace', 'annotate']))
def test_option_trailing(self):
options, args = self.parse_args(['file.pyx', '-i'])
self.assertEqual(args, ['file.pyx'])
self.assertEqual(options.build_inplace, True)
self.assertTrue(self.are_default(options, ['build_inplace']))
def test_interspersed_positional(self):
options, sources = self.parse_args([
'file1.pyx', '-a',
'file2.pyx'
])
self.assertEqual(sources, ['file1.pyx', 'file2.pyx'])
self.assertEqual(options.annotate, 'default')
self.assertTrue(self.are_default(options, ['annotate']))
def test_interspersed_positional2(self):
options, sources = self.parse_args([
'file1.pyx', '-a',
'file2.pyx', '-a', 'file3.pyx'
])
self.assertEqual(sources, ['file1.pyx', 'file2.pyx', 'file3.pyx'])
self.assertEqual(options.annotate, 'default')
self.assertTrue(self.are_default(options, ['annotate']))
def test_interspersed_positional3(self):
options, sources = self.parse_args([
'-f', 'f1', 'f2', '-a',
'f3', 'f4', '-a', 'f5'
])
self.assertEqual(sources, ['f1', 'f2', 'f3', 'f4', 'f5'])
self.assertEqual(options.annotate, 'default')
self.assertEqual(options.force, True)
self.assertTrue(self.are_default(options, ['annotate', 'force']))
def test_wrong_option(self):
old_stderr = sys.stderr
stderr = sys.stderr = StringIO()
try:
self.assertRaises(SystemExit, self.parse_args,
['--unknown-option']
)
finally:
sys.stderr = old_stderr
self.assertTrue(stderr.getvalue())
class TestParseArgs(TestCase):
def setUp(self):
self._options_backup = backup_Options()
def tearDown(self):
restore_Options(self._options_backup)
def check_default_global_options(self, white_list=[]):
self.assertEqual(check_global_options(self._options_backup, white_list), "")
def test_build_set_for_inplace(self):
options, args = parse_args(['foo.pyx', '-i'])
self.assertEqual(options.build, True)
self.check_default_global_options()
def test_lenient(self):
options, sources = parse_args(['foo.pyx', '--lenient'])
self.assertEqual(sources, ['foo.pyx'])
self.assertEqual(Options.error_on_unknown_names, False)
self.assertEqual(Options.error_on_uninitialized, False)
self.check_default_global_options(['error_on_unknown_names', 'error_on_uninitialized'])
def test_annotate(self):
options, sources = parse_args(['foo.pyx', '--annotate'])
self.assertEqual(sources, ['foo.pyx'])
self.assertEqual(Options.annotate, 'default')
self.check_default_global_options(['annotate'])
def test_annotate_fullc(self):
options, sources = parse_args(['foo.pyx', '--annotate-fullc'])
self.assertEqual(sources, ['foo.pyx'])
self.assertEqual(Options.annotate, 'fullc')
self.check_default_global_options(['annotate'])
def test_no_docstrings(self):
options, sources = parse_args(['foo.pyx', '--no-docstrings'])
self.assertEqual(sources, ['foo.pyx'])
self.assertEqual(Options.docstrings, False)
self.check_default_global_options(['docstrings'])

View File

@ -0,0 +1,142 @@
import contextlib
import os.path
import sys
import tempfile
import unittest
from io import open
from os.path import join as pjoin
from ..Dependencies import extended_iglob
@contextlib.contextmanager
def writable_file(dir_path, filename):
with open(pjoin(dir_path, filename), "w", encoding="utf8") as f:
yield f
class TestGlobbing(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls._orig_dir = os.getcwd()
if sys.version_info[0] < 3:
temp_path = cls._tmpdir = tempfile.mkdtemp()
else:
cls._tmpdir = tempfile.TemporaryDirectory()
temp_path = cls._tmpdir.name
os.chdir(temp_path)
for dir1 in "abcd":
for dir1x in [dir1, dir1 + 'x']:
for dir2 in "xyz":
dir_path = pjoin(dir1x, dir2)
os.makedirs(dir_path)
with writable_file(dir_path, "file2_pyx.pyx") as f:
f.write(u'""" PYX """')
with writable_file(dir_path, "file2_py.py") as f:
f.write(u'""" PY """')
with writable_file(dir1x, "file1_pyx.pyx") as f:
f.write(u'""" PYX """')
with writable_file(dir1x, "file1_py.py") as f:
f.write(u'""" PY """')
@classmethod
def tearDownClass(cls):
os.chdir(cls._orig_dir)
if sys.version_info[0] < 3:
import shutil
shutil.rmtree(cls._tmpdir)
else:
cls._tmpdir.cleanup()
def files_equal(self, pattern, expected_files):
expected_files = sorted(expected_files)
# It's the users's choice whether '/' will appear on Windows.
matched_files = sorted(path.replace('/', os.sep) for path in extended_iglob(pattern))
self.assertListEqual(matched_files, expected_files) # /
# Special case for Windows: also support '\' in patterns.
if os.sep == '\\' and '/' in pattern:
matched_files = sorted(extended_iglob(pattern.replace('/', '\\')))
self.assertListEqual(matched_files, expected_files) # \
def test_extended_iglob_simple(self):
ax_files = [pjoin("a", "x", "file2_pyx.pyx"), pjoin("a", "x", "file2_py.py")]
self.files_equal("a/x/*", ax_files)
self.files_equal("a/x/*.c12", [])
self.files_equal("a/x/*.{py,pyx,c12}", ax_files)
self.files_equal("a/x/*.{py,pyx}", ax_files)
self.files_equal("a/x/*.{pyx}", ax_files[:1])
self.files_equal("a/x/*.pyx", ax_files[:1])
self.files_equal("a/x/*.{py}", ax_files[1:])
self.files_equal("a/x/*.py", ax_files[1:])
def test_extended_iglob_simple_star(self):
for basedir in "ad":
files = [
pjoin(basedir, dirname, filename)
for dirname in "xyz"
for filename in ["file2_pyx.pyx", "file2_py.py"]
]
self.files_equal(basedir + "/*/*", files)
self.files_equal(basedir + "/*/*.c12", [])
self.files_equal(basedir + "/*/*.{py,pyx,c12}", files)
self.files_equal(basedir + "/*/*.{py,pyx}", files)
self.files_equal(basedir + "/*/*.{pyx}", files[::2])
self.files_equal(basedir + "/*/*.pyx", files[::2])
self.files_equal(basedir + "/*/*.{py}", files[1::2])
self.files_equal(basedir + "/*/*.py", files[1::2])
for subdir in "xy*":
files = [
pjoin(basedir, dirname, filename)
for dirname in "xyz"
if subdir in ('*', dirname)
for filename in ["file2_pyx.pyx", "file2_py.py"]
]
path = basedir + '/' + subdir + '/'
self.files_equal(path + "*", files)
self.files_equal(path + "*.{py,pyx}", files)
self.files_equal(path + "*.{pyx}", files[::2])
self.files_equal(path + "*.pyx", files[::2])
self.files_equal(path + "*.{py}", files[1::2])
self.files_equal(path + "*.py", files[1::2])
def test_extended_iglob_double_star(self):
basedirs = os.listdir(".")
files = [
pjoin(basedir, dirname, filename)
for basedir in basedirs
for dirname in "xyz"
for filename in ["file2_pyx.pyx", "file2_py.py"]
]
all_files = [
pjoin(basedir, filename)
for basedir in basedirs
for filename in ["file1_pyx.pyx", "file1_py.py"]
] + files
self.files_equal("*/*/*", files)
self.files_equal("*/*/**/*", files)
self.files_equal("*/**/*.*", all_files)
self.files_equal("**/*.*", all_files)
self.files_equal("*/**/*.c12", [])
self.files_equal("**/*.c12", [])
self.files_equal("*/*/*.{py,pyx,c12}", files)
self.files_equal("*/*/**/*.{py,pyx,c12}", files)
self.files_equal("*/**/*/*.{py,pyx,c12}", files)
self.files_equal("**/*/*/*.{py,pyx,c12}", files)
self.files_equal("**/*.{py,pyx,c12}", all_files)
self.files_equal("*/*/*.{py,pyx}", files)
self.files_equal("**/*/*/*.{py,pyx}", files)
self.files_equal("*/**/*/*.{py,pyx}", files)
self.files_equal("**/*.{py,pyx}", all_files)
self.files_equal("*/*/*.{pyx}", files[::2])
self.files_equal("**/*.{pyx}", all_files[::2])
self.files_equal("*/**/*/*.pyx", files[::2])
self.files_equal("*/*/*.pyx", files[::2])
self.files_equal("**/*.pyx", all_files[::2])
self.files_equal("*/*/*.{py}", files[1::2])
self.files_equal("**/*.{py}", all_files[1::2])
self.files_equal("*/*/*.py", files[1::2])
self.files_equal("**/*.py", all_files[1::2])

View File

@ -0,0 +1,112 @@
import os
import tempfile
import unittest
from Cython.Shadow import inline
from Cython.Build.Inline import safe_type
from Cython.TestUtils import CythonTest
try:
import numpy
has_numpy = True
except:
has_numpy = False
test_kwds = dict(force=True, quiet=True)
global_value = 100
class TestInline(CythonTest):
def setUp(self):
CythonTest.setUp(self)
self._call_kwds = dict(test_kwds)
if os.path.isdir('TEST_TMP'):
lib_dir = os.path.join('TEST_TMP','inline')
else:
lib_dir = tempfile.mkdtemp(prefix='cython_inline_')
self._call_kwds['lib_dir'] = lib_dir
def test_simple(self):
self.assertEqual(inline("return 1+2", **self._call_kwds), 3)
def test_types(self):
self.assertEqual(inline("""
cimport cython
return cython.typeof(a), cython.typeof(b)
""", a=1.0, b=[], **self._call_kwds), ('double', 'list object'))
def test_locals(self):
a = 1
b = 2
self.assertEqual(inline("return a+b", **self._call_kwds), 3)
def test_globals(self):
self.assertEqual(inline("return global_value + 1", **self._call_kwds), global_value + 1)
def test_no_return(self):
self.assertEqual(inline("""
a = 1
cdef double b = 2
cdef c = []
""", **self._call_kwds), dict(a=1, b=2.0, c=[]))
def test_def_node(self):
foo = inline("def foo(x): return x * x", **self._call_kwds)['foo']
self.assertEqual(foo(7), 49)
def test_class_ref(self):
class Type(object):
pass
tp = inline("Type")['Type']
self.assertEqual(tp, Type)
def test_pure(self):
import cython as cy
b = inline("""
b = cy.declare(float, a)
c = cy.declare(cy.pointer(cy.float), &b)
return b
""", a=3, **self._call_kwds)
self.assertEqual(type(b), float)
def test_compiler_directives(self):
self.assertEqual(
inline('return sum(x)',
x=[1, 2, 3],
cython_compiler_directives={'boundscheck': False}),
6
)
def test_lang_version(self):
# GH-3419. Caching for inline code didn't always respect compiler directives.
inline_divcode = "def f(int a, int b): return a/b"
self.assertEqual(
inline(inline_divcode, language_level=2)['f'](5,2),
2
)
self.assertEqual(
inline(inline_divcode, language_level=3)['f'](5,2),
2.5
)
self.assertEqual(
inline(inline_divcode, language_level=2)['f'](5,2),
2
)
def test_repeated_use(self):
inline_mulcode = "def f(int a, int b): return a * b"
self.assertEqual(inline(inline_mulcode)['f'](5, 2), 10)
self.assertEqual(inline(inline_mulcode)['f'](5, 3), 15)
self.assertEqual(inline(inline_mulcode)['f'](6, 2), 12)
self.assertEqual(inline(inline_mulcode)['f'](5, 2), 10)
f = inline(inline_mulcode)['f']
self.assertEqual(f(5, 2), 10)
self.assertEqual(f(5, 3), 15)
@unittest.skipIf(not has_numpy, "NumPy is not available")
def test_numpy(self):
import numpy
a = numpy.ndarray((10, 20))
a[0,0] = 10
self.assertEqual(safe_type(a), 'numpy.ndarray[numpy.float64_t, ndim=2]')
self.assertEqual(inline("return a[0,0]", a=a, **self._call_kwds), 10.0)

View File

@ -0,0 +1,295 @@
# -*- 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)

View File

@ -0,0 +1,212 @@
import shutil
import os
import tempfile
import time
import Cython.Build.Dependencies
import Cython.Utils
from Cython.TestUtils import CythonTest
def fresh_cythonize(*args, **kwargs):
Cython.Utils.clear_function_caches()
Cython.Build.Dependencies._dep_tree = None # discard method caches
Cython.Build.Dependencies.cythonize(*args, **kwargs)
class TestRecythonize(CythonTest):
def setUp(self):
CythonTest.setUp(self)
self.temp_dir = (
tempfile.mkdtemp(
prefix='recythonize-test',
dir='TEST_TMP' if os.path.isdir('TEST_TMP') else None
)
)
def tearDown(self):
CythonTest.tearDown(self)
shutil.rmtree(self.temp_dir)
def test_recythonize_pyx_on_pxd_change(self):
src_dir = tempfile.mkdtemp(prefix='src', dir=self.temp_dir)
a_pxd = os.path.join(src_dir, 'a.pxd')
a_pyx = os.path.join(src_dir, 'a.pyx')
a_c = os.path.join(src_dir, 'a.c')
dep_tree = Cython.Build.Dependencies.create_dependency_tree()
with open(a_pxd, 'w') as f:
f.write('cdef int value\n')
with open(a_pyx, 'w') as f:
f.write('value = 1\n')
# The dependencies for "a.pyx" are "a.pxd" and "a.pyx".
self.assertEqual({a_pxd, a_pyx}, dep_tree.all_dependencies(a_pyx))
# Cythonize to create a.c
fresh_cythonize(a_pyx)
# Sleep to address coarse time-stamp precision.
time.sleep(1)
with open(a_c) as f:
a_c_contents1 = f.read()
with open(a_pxd, 'w') as f:
f.write('cdef double value\n')
fresh_cythonize(a_pyx)
with open(a_c) as f:
a_c_contents2 = f.read()
self.assertTrue("__pyx_v_1a_value = 1;" in a_c_contents1)
self.assertFalse("__pyx_v_1a_value = 1;" in a_c_contents2)
self.assertTrue("__pyx_v_1a_value = 1.0;" in a_c_contents2)
self.assertFalse("__pyx_v_1a_value = 1.0;" in a_c_contents1)
def test_recythonize_py_on_pxd_change(self):
src_dir = tempfile.mkdtemp(prefix='src', dir=self.temp_dir)
a_pxd = os.path.join(src_dir, 'a.pxd')
a_py = os.path.join(src_dir, 'a.py')
a_c = os.path.join(src_dir, 'a.c')
dep_tree = Cython.Build.Dependencies.create_dependency_tree()
with open(a_pxd, 'w') as f:
f.write('cdef int value\n')
with open(a_py, 'w') as f:
f.write('value = 1\n')
# The dependencies for "a.py" are "a.pxd" and "a.py".
self.assertEqual({a_pxd, a_py}, dep_tree.all_dependencies(a_py))
# Cythonize to create a.c
fresh_cythonize(a_py)
# Sleep to address coarse time-stamp precision.
time.sleep(1)
with open(a_c) as f:
a_c_contents1 = f.read()
with open(a_pxd, 'w') as f:
f.write('cdef double value\n')
fresh_cythonize(a_py)
with open(a_c) as f:
a_c_contents2 = f.read()
self.assertTrue("__pyx_v_1a_value = 1;" in a_c_contents1)
self.assertFalse("__pyx_v_1a_value = 1;" in a_c_contents2)
self.assertTrue("__pyx_v_1a_value = 1.0;" in a_c_contents2)
self.assertFalse("__pyx_v_1a_value = 1.0;" in a_c_contents1)
def test_recythonize_pyx_on_dep_pxd_change(self):
src_dir = tempfile.mkdtemp(prefix='src', dir=self.temp_dir)
a_pxd = os.path.join(src_dir, 'a.pxd')
a_pyx = os.path.join(src_dir, 'a.pyx')
b_pyx = os.path.join(src_dir, 'b.pyx')
b_c = os.path.join(src_dir, 'b.c')
dep_tree = Cython.Build.Dependencies.create_dependency_tree()
with open(a_pxd, 'w') as f:
f.write('cdef int value\n')
with open(a_pyx, 'w') as f:
f.write('value = 1\n')
with open(b_pyx, 'w') as f:
f.write('cimport a\n' + 'a.value = 2\n')
# The dependencies for "b.pyx" are "a.pxd" and "b.pyx".
self.assertEqual({a_pxd, b_pyx}, dep_tree.all_dependencies(b_pyx))
# Cythonize to create b.c
fresh_cythonize([a_pyx, b_pyx])
# Sleep to address coarse time-stamp precision.
time.sleep(1)
with open(b_c) as f:
b_c_contents1 = f.read()
with open(a_pxd, 'w') as f:
f.write('cdef double value\n')
fresh_cythonize([a_pyx, b_pyx])
with open(b_c) as f:
b_c_contents2 = f.read()
self.assertTrue("__pyx_v_1a_value = 2;" in b_c_contents1)
self.assertFalse("__pyx_v_1a_value = 2;" in b_c_contents2)
self.assertTrue("__pyx_v_1a_value = 2.0;" in b_c_contents2)
self.assertFalse("__pyx_v_1a_value = 2.0;" in b_c_contents1)
def test_recythonize_py_on_dep_pxd_change(self):
src_dir = tempfile.mkdtemp(prefix='src', dir=self.temp_dir)
a_pxd = os.path.join(src_dir, 'a.pxd')
a_pyx = os.path.join(src_dir, 'a.pyx')
b_pxd = os.path.join(src_dir, 'b.pxd')
b_py = os.path.join(src_dir, 'b.py')
b_c = os.path.join(src_dir, 'b.c')
dep_tree = Cython.Build.Dependencies.create_dependency_tree()
with open(a_pxd, 'w') as f:
f.write('cdef int value\n')
with open(a_pyx, 'w') as f:
f.write('value = 1\n')
with open(b_pxd, 'w') as f:
f.write('cimport a\n')
with open(b_py, 'w') as f:
f.write('a.value = 2\n')
# The dependencies for b.py are "a.pxd", "b.pxd" and "b.py".
self.assertEqual({a_pxd, b_pxd, b_py}, dep_tree.all_dependencies(b_py))
# Cythonize to create b.c
fresh_cythonize([a_pyx, b_py])
# Sleep to address coarse time-stamp precision.
time.sleep(1)
with open(b_c) as f:
b_c_contents1 = f.read()
with open(a_pxd, 'w') as f:
f.write('cdef double value\n')
fresh_cythonize([a_pyx, b_py])
with open(b_c) as f:
b_c_contents2 = f.read()
self.assertTrue("__pyx_v_1a_value = 2;" in b_c_contents1)
self.assertFalse("__pyx_v_1a_value = 2;" in b_c_contents2)
self.assertTrue("__pyx_v_1a_value = 2.0;" in b_c_contents2)
self.assertFalse("__pyx_v_1a_value = 2.0;" in b_c_contents1)

View File

@ -0,0 +1,56 @@
from Cython.Build.Dependencies import strip_string_literals
from Cython.TestUtils import CythonTest
class TestStripLiterals(CythonTest):
def t(self, before, expected):
actual, literals = strip_string_literals(before, prefix="_L")
self.assertEqual(expected, actual)
for key, value in literals.items():
actual = actual.replace(key, value)
self.assertEqual(before, actual)
def test_empty(self):
self.t("", "")
def test_single_quote(self):
self.t("'x'", "'_L1_'")
def test_double_quote(self):
self.t('"x"', '"_L1_"')
def test_nested_quotes(self):
self.t(""" '"' "'" """, """ '_L1_' "_L2_" """)
def test_triple_quote(self):
self.t(" '''a\n''' ", " '''_L1_''' ")
def test_backslash(self):
self.t(r"'a\'b'", "'_L1_'")
self.t(r"'a\\'", "'_L1_'")
self.t(r"'a\\\'b'", "'_L1_'")
def test_unicode(self):
self.t("u'abc'", "u'_L1_'")
def test_raw(self):
self.t(r"r'abc\\'", "r'_L1_'")
def test_raw_unicode(self):
self.t(r"ru'abc\\'", "ru'_L1_'")
def test_comment(self):
self.t("abc # foo", "abc #_L1_")
def test_comment_and_quote(self):
self.t("abc # 'x'", "abc #_L1_")
self.t("'abc#'", "'_L1_'")
def test_include(self):
self.t("include 'a.pxi' # something here",
"include '_L1_' #_L2_")
def test_extern(self):
self.t("cdef extern from 'a.h': # comment",
"cdef extern from '_L1_': #_L2_")

View File

@ -0,0 +1 @@
# empty file