aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/cython/Cython/Compiler/Tests
diff options
context:
space:
mode:
authoralexv-smirnov <alex@ydb.tech>2023-06-13 11:05:01 +0300
committeralexv-smirnov <alex@ydb.tech>2023-06-13 11:05:01 +0300
commitbf0f13dd39ee3e65092ba3572bb5b1fcd125dcd0 (patch)
tree1d1df72c0541a59a81439842f46d95396d3e7189 /contrib/tools/cython/Cython/Compiler/Tests
parent8bfdfa9a9bd19bddbc58d888e180fbd1218681be (diff)
downloadydb-bf0f13dd39ee3e65092ba3572bb5b1fcd125dcd0.tar.gz
add ymake export to ydb
Diffstat (limited to 'contrib/tools/cython/Cython/Compiler/Tests')
-rw-r--r--contrib/tools/cython/Cython/Compiler/Tests/TestBuffer.py105
-rw-r--r--contrib/tools/cython/Cython/Compiler/Tests/TestCmdLine.py170
-rw-r--r--contrib/tools/cython/Cython/Compiler/Tests/TestFlowControl.py68
-rw-r--r--contrib/tools/cython/Cython/Compiler/Tests/TestGrammar.py129
-rw-r--r--contrib/tools/cython/Cython/Compiler/Tests/TestMemView.py71
-rw-r--r--contrib/tools/cython/Cython/Compiler/Tests/TestParseTreeTransforms.py289
-rw-r--r--contrib/tools/cython/Cython/Compiler/Tests/TestSignatureMatching.py73
-rw-r--r--contrib/tools/cython/Cython/Compiler/Tests/TestStringEncoding.py44
-rw-r--r--contrib/tools/cython/Cython/Compiler/Tests/TestTreeFragment.py64
-rw-r--r--contrib/tools/cython/Cython/Compiler/Tests/TestTreePath.py94
-rw-r--r--contrib/tools/cython/Cython/Compiler/Tests/TestTypes.py19
-rw-r--r--contrib/tools/cython/Cython/Compiler/Tests/TestUtilityLoad.py101
-rw-r--r--contrib/tools/cython/Cython/Compiler/Tests/TestVisitor.py61
-rw-r--r--contrib/tools/cython/Cython/Compiler/Tests/__init__.py1
14 files changed, 1289 insertions, 0 deletions
diff --git a/contrib/tools/cython/Cython/Compiler/Tests/TestBuffer.py b/contrib/tools/cython/Cython/Compiler/Tests/TestBuffer.py
new file mode 100644
index 0000000000..1f69d96524
--- /dev/null
+++ b/contrib/tools/cython/Cython/Compiler/Tests/TestBuffer.py
@@ -0,0 +1,105 @@
+from Cython.TestUtils import CythonTest
+import Cython.Compiler.Errors as Errors
+from Cython.Compiler.Nodes import *
+from Cython.Compiler.ParseTreeTransforms import *
+from Cython.Compiler.Buffer import *
+
+
+class TestBufferParsing(CythonTest):
+ # First, we only test the raw parser, i.e.
+ # the number and contents of arguments are NOT checked.
+ # However "dtype"/the first positional argument is special-cased
+ # to parse a type argument rather than an expression
+
+ def parse(self, s):
+ return self.should_not_fail(lambda: self.fragment(s)).root
+
+ def not_parseable(self, expected_error, s):
+ e = self.should_fail(lambda: self.fragment(s), Errors.CompileError)
+ self.assertEqual(expected_error, e.message_only)
+
+ def test_basic(self):
+ t = self.parse(u"cdef object[float, 4, ndim=2, foo=foo] x")
+ bufnode = t.stats[0].base_type
+ self.assertTrue(isinstance(bufnode, TemplatedTypeNode))
+ self.assertEqual(2, len(bufnode.positional_args))
+# print bufnode.dump()
+ # should put more here...
+
+ def test_type_pos(self):
+ self.parse(u"cdef object[short unsigned int, 3] x")
+
+ def test_type_keyword(self):
+ self.parse(u"cdef object[foo=foo, dtype=short unsigned int] x")
+
+ def test_pos_after_key(self):
+ self.not_parseable("Non-keyword arg following keyword arg",
+ u"cdef object[foo=1, 2] x")
+
+
+# See also tests/error/e_bufaccess.pyx and tets/run/bufaccess.pyx
+# THESE TESTS ARE NOW DISABLED, the code they test was pretty much
+# refactored away
+class TestBufferOptions(CythonTest):
+ # Tests the full parsing of the options within the brackets
+
+ def nonfatal_error(self, error):
+ # We're passing self as context to transform to trap this
+ self.error = error
+ self.assertTrue(self.expect_error)
+
+ def parse_opts(self, opts, expect_error=False):
+ assert opts != ""
+ s = u"def f():\n cdef object[%s] x" % opts
+ self.expect_error = expect_error
+ root = self.fragment(s, pipeline=[NormalizeTree(self), PostParse(self)]).root
+ if not expect_error:
+ vardef = root.stats[0].body.stats[0]
+ assert isinstance(vardef, CVarDefNode) # use normal assert as this is to validate the test code
+ buftype = vardef.base_type
+ self.assertTrue(isinstance(buftype, TemplatedTypeNode))
+ self.assertTrue(isinstance(buftype.base_type_node, CSimpleBaseTypeNode))
+ self.assertEqual(u"object", buftype.base_type_node.name)
+ return buftype
+ else:
+ self.assertTrue(len(root.stats[0].body.stats) == 0)
+
+ def non_parse(self, expected_err, opts):
+ self.parse_opts(opts, expect_error=True)
+# e = self.should_fail(lambda: self.parse_opts(opts))
+ self.assertEqual(expected_err, self.error.message_only)
+
+ def __test_basic(self):
+ buf = self.parse_opts(u"unsigned short int, 3")
+ self.assertTrue(isinstance(buf.dtype_node, CSimpleBaseTypeNode))
+ self.assertTrue(buf.dtype_node.signed == 0 and buf.dtype_node.longness == -1)
+ self.assertEqual(3, buf.ndim)
+
+ def __test_dict(self):
+ buf = self.parse_opts(u"ndim=3, dtype=unsigned short int")
+ self.assertTrue(isinstance(buf.dtype_node, CSimpleBaseTypeNode))
+ self.assertTrue(buf.dtype_node.signed == 0 and buf.dtype_node.longness == -1)
+ self.assertEqual(3, buf.ndim)
+
+ def __test_ndim(self):
+ self.parse_opts(u"int, 2")
+ self.non_parse(ERR_BUF_NDIM, u"int, 'a'")
+ self.non_parse(ERR_BUF_NDIM, u"int, -34")
+
+ def __test_use_DEF(self):
+ t = self.fragment(u"""
+ DEF ndim = 3
+ def f():
+ cdef object[int, ndim] x
+ cdef object[ndim=ndim, dtype=int] y
+ """, pipeline=[NormalizeTree(self), PostParse(self)]).root
+ stats = t.stats[0].body.stats
+ self.assertTrue(stats[0].base_type.ndim == 3)
+ self.assertTrue(stats[1].base_type.ndim == 3)
+
+ # add exotic and impossible combinations as they come along...
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main()
+
diff --git a/contrib/tools/cython/Cython/Compiler/Tests/TestCmdLine.py b/contrib/tools/cython/Cython/Compiler/Tests/TestCmdLine.py
new file mode 100644
index 0000000000..bd31da0007
--- /dev/null
+++ b/contrib/tools/cython/Cython/Compiler/Tests/TestCmdLine.py
@@ -0,0 +1,170 @@
+
+import sys
+import re
+from unittest import TestCase
+try:
+ from StringIO import StringIO
+except ImportError:
+ from io import StringIO # doesn't accept 'str' in Py2
+
+from .. import Options
+from ..CmdLine import parse_command_line
+
+
+def check_global_options(expected_options, white_list=[]):
+ """
+ returns error message of "" if check Ok
+ """
+ no_value = object()
+ for name, orig_value in expected_options.items():
+ if name not in white_list:
+ if getattr(Options, name, no_value) != orig_value:
+ return "error in option " + name
+ return ""
+
+
+class CmdLineParserTest(TestCase):
+ def setUp(self):
+ backup = {}
+ for name, value in vars(Options).items():
+ backup[name] = value
+ self._options_backup = backup
+
+ def tearDown(self):
+ no_value = object()
+ for name, orig_value in self._options_backup.items():
+ if getattr(Options, name, no_value) != orig_value:
+ setattr(Options, name, orig_value)
+
+ def check_default_global_options(self, white_list=[]):
+ self.assertEqual(check_global_options(self._options_backup, white_list), "")
+
+ def check_default_options(self, options, white_list=[]):
+ from ..Main import CompilationOptions, default_options
+ default_options = CompilationOptions(default_options)
+ no_value = object()
+ for name in default_options.__dict__.keys():
+ if name not in white_list:
+ self.assertEqual(getattr(options, name, no_value), getattr(default_options, name), msg="error in option " + name)
+
+ def test_short_options(self):
+ options, sources = parse_command_line([
+ '-V', '-l', '-+', '-t', '-v', '-v', '-v', '-p', '-D', '-a', '-3',
+ ])
+ self.assertFalse(sources)
+ self.assertTrue(options.show_version)
+ self.assertTrue(options.use_listing_file)
+ self.assertTrue(options.cplus)
+ self.assertTrue(options.timestamps)
+ self.assertTrue(options.verbose >= 3)
+ self.assertTrue(Options.embed_pos_in_docstring)
+ self.assertFalse(Options.docstrings)
+ self.assertTrue(Options.annotate)
+ self.assertEqual(options.language_level, 3)
+
+ options, sources = parse_command_line([
+ '-f', '-2', 'source.pyx',
+ ])
+ self.assertTrue(sources)
+ self.assertTrue(len(sources) == 1)
+ self.assertFalse(options.timestamps)
+ self.assertEqual(options.language_level, 2)
+
+ def test_long_options(self):
+ options, sources = parse_command_line([
+ '--version', '--create-listing', '--cplus', '--embed', '--timestamps',
+ '--verbose', '--verbose', '--verbose',
+ '--embed-positions', '--no-docstrings', '--annotate', '--lenient',
+ ])
+ self.assertFalse(sources)
+ self.assertTrue(options.show_version)
+ self.assertTrue(options.use_listing_file)
+ self.assertTrue(options.cplus)
+ self.assertEqual(Options.embed, 'main')
+ self.assertTrue(options.timestamps)
+ self.assertTrue(options.verbose >= 3)
+ self.assertTrue(Options.embed_pos_in_docstring)
+ self.assertFalse(Options.docstrings)
+ self.assertTrue(Options.annotate)
+ self.assertFalse(Options.error_on_unknown_names)
+ self.assertFalse(Options.error_on_uninitialized)
+
+ options, sources = parse_command_line([
+ '--force', 'source.pyx',
+ ])
+ self.assertTrue(sources)
+ self.assertTrue(len(sources) == 1)
+ self.assertFalse(options.timestamps)
+
+ def test_options_with_values(self):
+ options, sources = parse_command_line([
+ '--embed=huhu',
+ '-I/test/include/dir1', '--include-dir=/test/include/dir2',
+ '--include-dir', '/test/include/dir3',
+ '--working=/work/dir',
+ 'source.pyx',
+ '--output-file=/output/dir',
+ '--pre-import=/pre/import',
+ '--cleanup=3',
+ '--annotate-coverage=cov.xml',
+ '--gdb-outdir=/gdb/outdir',
+ '--directive=wraparound=false',
+ ])
+ self.assertEqual(sources, ['source.pyx'])
+ self.assertEqual(Options.embed, 'huhu')
+ self.assertEqual(options.include_path, ['/test/include/dir1', '/test/include/dir2', '/test/include/dir3'])
+ self.assertEqual(options.working_path, '/work/dir')
+ self.assertEqual(options.output_file, '/output/dir')
+ self.assertEqual(Options.pre_import, '/pre/import')
+ self.assertEqual(Options.generate_cleanup_code, 3)
+ self.assertTrue(Options.annotate)
+ self.assertEqual(Options.annotate_coverage_xml, 'cov.xml')
+ self.assertTrue(options.gdb_debug)
+ self.assertEqual(options.output_dir, '/gdb/outdir')
+
+ def test_module_name(self):
+ options, sources = parse_command_line([
+ 'source.pyx'
+ ])
+ self.assertEqual(options.module_name, None)
+ self.check_default_global_options()
+ self.check_default_options(options)
+ options, sources = parse_command_line([
+ '--module-name', 'foo.bar',
+ 'source.pyx'
+ ])
+ self.assertEqual(options.module_name, 'foo.bar')
+ self.check_default_global_options()
+ self.check_default_options(options, ['module_name'])
+
+ def test_errors(self):
+ def error(args, regex=None):
+ old_stderr = sys.stderr
+ stderr = sys.stderr = StringIO()
+ try:
+ self.assertRaises(SystemExit, parse_command_line, list(args))
+ finally:
+ sys.stderr = old_stderr
+ msg = stderr.getvalue().strip()
+ self.assertTrue(msg)
+ if regex:
+ self.assertTrue(re.search(regex, msg),
+ '"%s" does not match search "%s"' %
+ (msg, regex))
+
+ error(['-1'],
+ 'Unknown compiler flag: -1')
+ error(['-I'])
+ error(['--version=-a'])
+ error(['--version=--annotate=true'])
+ error(['--working'])
+ error(['--verbose=1'])
+ error(['--cleanup'])
+ error(['--debug-disposal-code-wrong-name', 'file3.pyx'],
+ "Unknown debug flag: debug_disposal_code_wrong_name")
+ error(['--module-name', 'foo.pyx'])
+ error(['--module-name', 'foo.bar'])
+ error(['--module-name', 'foo.bar', 'foo.pyx', 'bar.pyx'],
+ "Only one source file allowed when using --module-name")
+ error(['--module-name', 'foo.bar', '--timestamps', 'foo.pyx'],
+ "Cannot use --module-name with --timestamps")
diff --git a/contrib/tools/cython/Cython/Compiler/Tests/TestFlowControl.py b/contrib/tools/cython/Cython/Compiler/Tests/TestFlowControl.py
new file mode 100644
index 0000000000..443551ab88
--- /dev/null
+++ b/contrib/tools/cython/Cython/Compiler/Tests/TestFlowControl.py
@@ -0,0 +1,68 @@
+
+from __future__ import absolute_import
+
+from copy import deepcopy
+from unittest import TestCase
+
+from Cython.Compiler.FlowControl import (
+ NameAssignment, StaticAssignment, Argument, NameDeletion)
+
+
+class FakeType(object):
+ is_pyobject = True
+
+
+class FakeNode(object):
+ pos = ('filename.pyx', 1, 2)
+ cf_state = None
+ type = FakeType()
+
+ def infer_type(self, scope):
+ return self.type
+
+
+class FakeEntry(object):
+ type = FakeType()
+
+
+class TestGraph(TestCase):
+ def test_deepcopy(self):
+ lhs, rhs = FakeNode(), FakeNode()
+ entry = FakeEntry()
+ entry.pos = lhs.pos
+
+ name_ass = NameAssignment(lhs, rhs, entry)
+ ass = deepcopy(name_ass)
+ self.assertTrue(ass.lhs)
+ self.assertTrue(ass.rhs)
+ self.assertTrue(ass.entry)
+ self.assertEqual(ass.pos, name_ass.pos)
+ self.assertFalse(ass.is_arg)
+ self.assertFalse(ass.is_deletion)
+
+ static_ass = StaticAssignment(entry)
+ ass = deepcopy(static_ass)
+ self.assertTrue(ass.lhs)
+ self.assertTrue(ass.rhs)
+ self.assertTrue(ass.entry)
+ self.assertEqual(ass.pos, static_ass.pos)
+ self.assertFalse(ass.is_arg)
+ self.assertFalse(ass.is_deletion)
+
+ arg_ass = Argument(lhs, rhs, entry)
+ ass = deepcopy(arg_ass)
+ self.assertTrue(ass.lhs)
+ self.assertTrue(ass.rhs)
+ self.assertTrue(ass.entry)
+ self.assertEqual(ass.pos, arg_ass.pos)
+ self.assertTrue(ass.is_arg)
+ self.assertFalse(ass.is_deletion)
+
+ name_del = NameDeletion(lhs, entry)
+ ass = deepcopy(name_del)
+ self.assertTrue(ass.lhs)
+ self.assertTrue(ass.rhs)
+ self.assertTrue(ass.entry)
+ self.assertEqual(ass.pos, name_del.pos)
+ self.assertFalse(ass.is_arg)
+ self.assertTrue(ass.is_deletion)
diff --git a/contrib/tools/cython/Cython/Compiler/Tests/TestGrammar.py b/contrib/tools/cython/Cython/Compiler/Tests/TestGrammar.py
new file mode 100644
index 0000000000..3dddc960b3
--- /dev/null
+++ b/contrib/tools/cython/Cython/Compiler/Tests/TestGrammar.py
@@ -0,0 +1,129 @@
+# mode: run
+# tag: syntax
+
+"""
+Uses TreeFragment to test invalid syntax.
+"""
+
+from __future__ import absolute_import
+
+from ...TestUtils import CythonTest
+from ..Errors import CompileError
+from .. import ExprNodes
+
+# Copied from CPython's test_grammar.py
+VALID_UNDERSCORE_LITERALS = [
+ '0_0_0',
+ '4_2',
+ '1_0000_0000',
+ '0b1001_0100',
+ '0xffff_ffff',
+ '0o5_7_7',
+ '1_00_00.5',
+ '1_00_00.5j',
+ '1_00_00.5e5',
+ '1_00_00j',
+ '1_00_00e5_1',
+ '1e1_0',
+ '.1_4',
+ '.1_4e1',
+ '.1_4j',
+]
+
+# Copied from CPython's test_grammar.py
+INVALID_UNDERSCORE_LITERALS = [
+ # Trailing underscores:
+ '0_',
+ '42_',
+ '1.4j_',
+ '0b1_',
+ '0xf_',
+ '0o5_',
+ # Underscores in the base selector:
+ '0_b0',
+ '0_xf',
+ '0_o5',
+ # Underscore right after the base selector:
+ '0b_0',
+ '0x_f',
+ '0o_5',
+ # Old-style octal, still disallowed:
+ #'0_7',
+ #'09_99',
+ # Special case with exponent:
+ '0 if 1_Else 1',
+ # Underscore right before a dot:
+ '1_.4',
+ '1_.4j',
+ # Underscore right after a dot:
+ '1._4',
+ '1._4j',
+ '._5',
+ # Underscore right after a sign:
+ '1.0e+_1',
+ # Multiple consecutive underscores:
+ '4_______2',
+ '0.1__4',
+ '0b1001__0100',
+ '0xffff__ffff',
+ '0o5__77',
+ '1e1__0',
+ # Underscore right before j:
+ '1.4_j',
+ '1.4e5_j',
+ # Underscore right before e:
+ '1_e1',
+ '1.4_e1',
+ # Underscore right after e:
+ '1e_1',
+ '1.4e_1',
+ # Whitespace in literals
+ '1_ 2',
+ '1 _2',
+ '1_2.2_ 1',
+ '1_2.2 _1',
+ '1_2e _1',
+ '1_2e2 _1',
+ '1_2e 2_1',
+]
+
+
+class TestGrammar(CythonTest):
+
+ def test_invalid_number_literals(self):
+ for literal in INVALID_UNDERSCORE_LITERALS:
+ for expression in ['%s', '1 + %s', '%s + 1', '2 * %s', '%s * 2']:
+ code = 'x = ' + expression % literal
+ try:
+ self.fragment(u'''\
+ # cython: language_level=3
+ ''' + code)
+ except CompileError as exc:
+ assert code in [s.strip() for s in str(exc).splitlines()], str(exc)
+ else:
+ assert False, "Invalid Cython code '%s' failed to raise an exception" % code
+
+ def test_valid_number_literals(self):
+ for literal in VALID_UNDERSCORE_LITERALS:
+ for i, expression in enumerate(['%s', '1 + %s', '%s + 1', '2 * %s', '%s * 2']):
+ code = 'x = ' + expression % literal
+ node = self.fragment(u'''\
+ # cython: language_level=3
+ ''' + code).root
+ assert node is not None
+
+ literal_node = node.stats[0].rhs # StatListNode([SingleAssignmentNode('x', expr)])
+ if i > 0:
+ # Add/MulNode() -> literal is first or second operand
+ literal_node = literal_node.operand2 if i % 2 else literal_node.operand1
+ if 'j' in literal or 'J' in literal:
+ assert isinstance(literal_node, ExprNodes.ImagNode)
+ elif '.' in literal or 'e' in literal or 'E' in literal and not ('0x' in literal or '0X' in literal):
+ assert isinstance(literal_node, ExprNodes.FloatNode)
+ else:
+ assert isinstance(literal_node, ExprNodes.IntNode)
+
+
+if __name__ == "__main__":
+ import unittest
+ unittest.main()
diff --git a/contrib/tools/cython/Cython/Compiler/Tests/TestMemView.py b/contrib/tools/cython/Cython/Compiler/Tests/TestMemView.py
new file mode 100644
index 0000000000..3792f26e99
--- /dev/null
+++ b/contrib/tools/cython/Cython/Compiler/Tests/TestMemView.py
@@ -0,0 +1,71 @@
+from Cython.TestUtils import CythonTest
+import Cython.Compiler.Errors as Errors
+from Cython.Compiler.Nodes import *
+from Cython.Compiler.ParseTreeTransforms import *
+from Cython.Compiler.Buffer import *
+
+
+class TestMemviewParsing(CythonTest):
+
+ def parse(self, s):
+ return self.should_not_fail(lambda: self.fragment(s)).root
+
+ def not_parseable(self, expected_error, s):
+ e = self.should_fail(lambda: self.fragment(s), Errors.CompileError)
+ self.assertEqual(expected_error, e.message_only)
+
+ def test_default_1dim(self):
+ self.parse(u"cdef int[:] x")
+ self.parse(u"cdef short int[:] x")
+
+ def test_default_ndim(self):
+ self.parse(u"cdef int[:,:,:,:,:] x")
+ self.parse(u"cdef unsigned long int[:,:,:,:,:] x")
+ self.parse(u"cdef unsigned int[:,:,:,:,:] x")
+
+ def test_zero_offset(self):
+ self.parse(u"cdef long double[0:] x")
+ self.parse(u"cdef int[0:] x")
+
+ def test_zero_offset_ndim(self):
+ self.parse(u"cdef int[0:,0:,0:,0:] x")
+
+ def test_def_arg(self):
+ self.parse(u"def foo(int[:,:] x): pass")
+
+ def test_cdef_arg(self):
+ self.parse(u"cdef foo(int[:,:] x): pass")
+
+ def test_general_slice(self):
+ self.parse(u'cdef float[::ptr, ::direct & contig, 0::full & strided] x')
+
+ def test_non_slice_memview(self):
+ self.not_parseable(u"An axis specification in memoryview declaration does not have a ':'.",
+ u"cdef double[:foo, bar] x")
+ self.not_parseable(u"An axis specification in memoryview declaration does not have a ':'.",
+ u"cdef double[0:foo, bar] x")
+
+ def test_basic(self):
+ t = self.parse(u"cdef int[:] x")
+ memv_node = t.stats[0].base_type
+ self.assertTrue(isinstance(memv_node, MemoryViewSliceTypeNode))
+
+ # we also test other similar declarations (buffers, anonymous C arrays)
+ # since the parsing has to distinguish between them.
+
+ def disable_test_no_buf_arg(self): # TODO
+ self.not_parseable(u"Expected ']'",
+ u"cdef extern foo(object[int, ndim=2])")
+
+ def disable_test_parse_sizeof(self): # TODO
+ self.parse(u"sizeof(int[NN])")
+ self.parse(u"sizeof(int[])")
+ self.parse(u"sizeof(int[][NN])")
+ self.not_parseable(u"Expected an identifier or literal",
+ u"sizeof(int[:NN])")
+ self.not_parseable(u"Expected ']'",
+ u"sizeof(foo[dtype=bar]")
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main()
diff --git a/contrib/tools/cython/Cython/Compiler/Tests/TestParseTreeTransforms.py b/contrib/tools/cython/Cython/Compiler/Tests/TestParseTreeTransforms.py
new file mode 100644
index 0000000000..8a16f98ccc
--- /dev/null
+++ b/contrib/tools/cython/Cython/Compiler/Tests/TestParseTreeTransforms.py
@@ -0,0 +1,289 @@
+import os.path
+import unittest
+
+from Cython.TestUtils import TransformTest
+from Cython.Compiler.ParseTreeTransforms import *
+from Cython.Compiler.ParseTreeTransforms import _calculate_pickle_checksums
+from Cython.Compiler.Nodes import *
+from Cython.Compiler import Main, Symtab
+
+
+class TestNormalizeTree(TransformTest):
+ def test_parserbehaviour_is_what_we_coded_for(self):
+ t = self.fragment(u"if x: y").root
+ self.assertLines(u"""
+(root): StatListNode
+ stats[0]: IfStatNode
+ if_clauses[0]: IfClauseNode
+ condition: NameNode
+ body: ExprStatNode
+ expr: NameNode
+""", self.treetypes(t))
+
+ def test_wrap_singlestat(self):
+ t = self.run_pipeline([NormalizeTree(None)], u"if x: y")
+ self.assertLines(u"""
+(root): StatListNode
+ stats[0]: IfStatNode
+ if_clauses[0]: IfClauseNode
+ condition: NameNode
+ body: StatListNode
+ stats[0]: ExprStatNode
+ expr: NameNode
+""", self.treetypes(t))
+
+ def test_wrap_multistat(self):
+ t = self.run_pipeline([NormalizeTree(None)], u"""
+ if z:
+ x
+ y
+ """)
+ self.assertLines(u"""
+(root): StatListNode
+ stats[0]: IfStatNode
+ if_clauses[0]: IfClauseNode
+ condition: NameNode
+ body: StatListNode
+ stats[0]: ExprStatNode
+ expr: NameNode
+ stats[1]: ExprStatNode
+ expr: NameNode
+""", self.treetypes(t))
+
+ def test_statinexpr(self):
+ t = self.run_pipeline([NormalizeTree(None)], u"""
+ a, b = x, y
+ """)
+ self.assertLines(u"""
+(root): StatListNode
+ stats[0]: SingleAssignmentNode
+ lhs: TupleNode
+ args[0]: NameNode
+ args[1]: NameNode
+ rhs: TupleNode
+ args[0]: NameNode
+ args[1]: NameNode
+""", self.treetypes(t))
+
+ def test_wrap_offagain(self):
+ t = self.run_pipeline([NormalizeTree(None)], u"""
+ x
+ y
+ if z:
+ x
+ """)
+ self.assertLines(u"""
+(root): StatListNode
+ stats[0]: ExprStatNode
+ expr: NameNode
+ stats[1]: ExprStatNode
+ expr: NameNode
+ stats[2]: IfStatNode
+ if_clauses[0]: IfClauseNode
+ condition: NameNode
+ body: StatListNode
+ stats[0]: ExprStatNode
+ expr: NameNode
+""", self.treetypes(t))
+
+
+ def test_pass_eliminated(self):
+ t = self.run_pipeline([NormalizeTree(None)], u"pass")
+ self.assertTrue(len(t.stats) == 0)
+
+class TestWithTransform(object): # (TransformTest): # Disabled!
+
+ def test_simplified(self):
+ t = self.run_pipeline([WithTransform(None)], u"""
+ with x:
+ y = z ** 3
+ """)
+
+ self.assertCode(u"""
+
+ $0_0 = x
+ $0_2 = $0_0.__exit__
+ $0_0.__enter__()
+ $0_1 = True
+ try:
+ try:
+ $1_0 = None
+ y = z ** 3
+ except:
+ $0_1 = False
+ if (not $0_2($1_0)):
+ raise
+ finally:
+ if $0_1:
+ $0_2(None, None, None)
+
+ """, t)
+
+ def test_basic(self):
+ t = self.run_pipeline([WithTransform(None)], u"""
+ with x as y:
+ y = z ** 3
+ """)
+ self.assertCode(u"""
+
+ $0_0 = x
+ $0_2 = $0_0.__exit__
+ $0_3 = $0_0.__enter__()
+ $0_1 = True
+ try:
+ try:
+ $1_0 = None
+ y = $0_3
+ y = z ** 3
+ except:
+ $0_1 = False
+ if (not $0_2($1_0)):
+ raise
+ finally:
+ if $0_1:
+ $0_2(None, None, None)
+
+ """, t)
+
+
+class TestInterpretCompilerDirectives(TransformTest):
+ """
+ This class tests the parallel directives AST-rewriting and importing.
+ """
+
+ # Test the parallel directives (c)importing
+
+ import_code = u"""
+ cimport cython.parallel
+ cimport cython.parallel as par
+ from cython cimport parallel as par2
+ from cython cimport parallel
+
+ from cython.parallel cimport threadid as tid
+ from cython.parallel cimport threadavailable as tavail
+ from cython.parallel cimport prange
+ """
+
+ expected_directives_dict = {
+ u'cython.parallel': u'cython.parallel',
+ u'par': u'cython.parallel',
+ u'par2': u'cython.parallel',
+ u'parallel': u'cython.parallel',
+
+ u"tid": u"cython.parallel.threadid",
+ u"tavail": u"cython.parallel.threadavailable",
+ u"prange": u"cython.parallel.prange",
+ }
+
+
+ def setUp(self):
+ super(TestInterpretCompilerDirectives, self).setUp()
+
+ compilation_options = Main.CompilationOptions(Main.default_options)
+ ctx = compilation_options.create_context()
+
+ transform = InterpretCompilerDirectives(ctx, ctx.compiler_directives)
+ transform.module_scope = Symtab.ModuleScope('__main__', None, ctx)
+ self.pipeline = [transform]
+
+ self.debug_exception_on_error = DebugFlags.debug_exception_on_error
+
+ def tearDown(self):
+ DebugFlags.debug_exception_on_error = self.debug_exception_on_error
+
+ def test_parallel_directives_cimports(self):
+ self.run_pipeline(self.pipeline, self.import_code)
+ parallel_directives = self.pipeline[0].parallel_directives
+ self.assertEqual(parallel_directives, self.expected_directives_dict)
+
+ def test_parallel_directives_imports(self):
+ self.run_pipeline(self.pipeline,
+ self.import_code.replace(u'cimport', u'import'))
+ parallel_directives = self.pipeline[0].parallel_directives
+ self.assertEqual(parallel_directives, self.expected_directives_dict)
+
+
+# TODO: Re-enable once they're more robust.
+if False:
+ from Cython.Debugger import DebugWriter
+ from Cython.Debugger.Tests.TestLibCython import DebuggerTestCase
+else:
+ # skip test, don't let it inherit unittest.TestCase
+ DebuggerTestCase = object
+
+
+class TestDebugTransform(DebuggerTestCase):
+
+ def elem_hasattrs(self, elem, attrs):
+ return all(attr in elem.attrib for attr in attrs)
+
+ def test_debug_info(self):
+ try:
+ assert os.path.exists(self.debug_dest)
+
+ t = DebugWriter.etree.parse(self.debug_dest)
+ # the xpath of the standard ElementTree is primitive, don't use
+ # anything fancy
+ L = list(t.find('/Module/Globals'))
+ assert L
+ xml_globals = dict((e.attrib['name'], e.attrib['type']) for e in L)
+ self.assertEqual(len(L), len(xml_globals))
+
+ L = list(t.find('/Module/Functions'))
+ assert L
+ xml_funcs = dict((e.attrib['qualified_name'], e) for e in L)
+ self.assertEqual(len(L), len(xml_funcs))
+
+ # test globals
+ self.assertEqual('CObject', xml_globals.get('c_var'))
+ self.assertEqual('PythonObject', xml_globals.get('python_var'))
+
+ # test functions
+ funcnames = ('codefile.spam', 'codefile.ham', 'codefile.eggs',
+ 'codefile.closure', 'codefile.inner')
+ required_xml_attrs = 'name', 'cname', 'qualified_name'
+ assert all(f in xml_funcs for f in funcnames)
+ spam, ham, eggs = [xml_funcs[funcname] for funcname in funcnames]
+
+ self.assertEqual(spam.attrib['name'], 'spam')
+ self.assertNotEqual('spam', spam.attrib['cname'])
+ assert self.elem_hasattrs(spam, required_xml_attrs)
+
+ # test locals of functions
+ spam_locals = list(spam.find('Locals'))
+ assert spam_locals
+ spam_locals.sort(key=lambda e: e.attrib['name'])
+ names = [e.attrib['name'] for e in spam_locals]
+ self.assertEqual(list('abcd'), names)
+ assert self.elem_hasattrs(spam_locals[0], required_xml_attrs)
+
+ # test arguments of functions
+ spam_arguments = list(spam.find('Arguments'))
+ assert spam_arguments
+ self.assertEqual(1, len(list(spam_arguments)))
+
+ # test step-into functions
+ step_into = spam.find('StepIntoFunctions')
+ spam_stepinto = [x.attrib['name'] for x in step_into]
+ assert spam_stepinto
+ self.assertEqual(2, len(spam_stepinto))
+ assert 'puts' in spam_stepinto
+ assert 'some_c_function' in spam_stepinto
+ except:
+ f = open(self.debug_dest)
+ try:
+ print(f.read())
+ finally:
+ f.close()
+ raise
+
+
+class TestAnalyseDeclarationsTransform(unittest.TestCase):
+ def test_calculate_pickle_checksums(self):
+ checksums = _calculate_pickle_checksums(['member1', 'member2', 'member3'])
+ assert 2 <= len(checksums) <= 3, checksums # expecting ['0xc0af380' (MD5), '0x0c75bd4', '0xa7a7b94']
+
+
+if __name__ == "__main__":
+ import unittest
+ unittest.main()
diff --git a/contrib/tools/cython/Cython/Compiler/Tests/TestSignatureMatching.py b/contrib/tools/cython/Cython/Compiler/Tests/TestSignatureMatching.py
new file mode 100644
index 0000000000..166bb225b9
--- /dev/null
+++ b/contrib/tools/cython/Cython/Compiler/Tests/TestSignatureMatching.py
@@ -0,0 +1,73 @@
+import unittest
+
+from Cython.Compiler import PyrexTypes as pt
+from Cython.Compiler.ExprNodes import NameNode
+from Cython.Compiler.PyrexTypes import CFuncTypeArg
+
+def cfunctype(*arg_types):
+ return pt.CFuncType(pt.c_int_type,
+ [ CFuncTypeArg("name", arg_type, None) for arg_type in arg_types ])
+
+def cppclasstype(name, base_classes):
+ return pt.CppClassType(name, None, 'CPP_'+name, base_classes)
+
+class SignatureMatcherTest(unittest.TestCase):
+ """
+ Test the signature matching algorithm for overloaded signatures.
+ """
+ def assertMatches(self, expected_type, arg_types, functions):
+ match = pt.best_match(arg_types, functions)
+ if expected_type is not None:
+ self.assertNotEqual(None, match)
+ self.assertEqual(expected_type, match.type)
+
+ def test_cpp_reference_single_arg(self):
+ function_types = [
+ cfunctype(pt.CReferenceType(pt.c_int_type)),
+ cfunctype(pt.CReferenceType(pt.c_long_type)),
+ cfunctype(pt.CReferenceType(pt.c_double_type)),
+ ]
+
+ functions = [ NameNode(None, type=t) for t in function_types ]
+ self.assertMatches(function_types[0], [pt.c_int_type], functions)
+ self.assertMatches(function_types[1], [pt.c_long_type], functions)
+ self.assertMatches(function_types[2], [pt.c_double_type], functions)
+
+ def test_cpp_reference_two_args(self):
+ function_types = [
+ cfunctype(
+ pt.CReferenceType(pt.c_int_type), pt.CReferenceType(pt.c_long_type)),
+ cfunctype(
+ pt.CReferenceType(pt.c_long_type), pt.CReferenceType(pt.c_long_type)),
+ ]
+
+ functions = [ NameNode(None, type=t) for t in function_types ]
+ self.assertMatches(function_types[0], [pt.c_int_type, pt.c_long_type], functions)
+ self.assertMatches(function_types[1], [pt.c_long_type, pt.c_long_type], functions)
+ self.assertMatches(function_types[1], [pt.c_long_type, pt.c_int_type], functions)
+
+ def test_cpp_reference_cpp_class(self):
+ classes = [ cppclasstype("Test%d"%i, []) for i in range(2) ]
+ function_types = [
+ cfunctype(pt.CReferenceType(classes[0])),
+ cfunctype(pt.CReferenceType(classes[1])),
+ ]
+
+ functions = [ NameNode(None, type=t) for t in function_types ]
+ self.assertMatches(function_types[0], [classes[0]], functions)
+ self.assertMatches(function_types[1], [classes[1]], functions)
+
+ def test_cpp_reference_cpp_class_and_int(self):
+ classes = [ cppclasstype("Test%d"%i, []) for i in range(2) ]
+ function_types = [
+ cfunctype(pt.CReferenceType(classes[0]), pt.c_int_type),
+ cfunctype(pt.CReferenceType(classes[0]), pt.c_long_type),
+ cfunctype(pt.CReferenceType(classes[1]), pt.c_int_type),
+ cfunctype(pt.CReferenceType(classes[1]), pt.c_long_type),
+ ]
+
+ functions = [ NameNode(None, type=t) for t in function_types ]
+ self.assertMatches(function_types[0], [classes[0], pt.c_int_type], functions)
+ self.assertMatches(function_types[1], [classes[0], pt.c_long_type], functions)
+ self.assertMatches(function_types[2], [classes[1], pt.c_int_type], functions)
+ self.assertMatches(function_types[3], [classes[1], pt.c_long_type], functions)
diff --git a/contrib/tools/cython/Cython/Compiler/Tests/TestStringEncoding.py b/contrib/tools/cython/Cython/Compiler/Tests/TestStringEncoding.py
new file mode 100644
index 0000000000..91d099333a
--- /dev/null
+++ b/contrib/tools/cython/Cython/Compiler/Tests/TestStringEncoding.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+
+import sys
+import unittest
+
+import Cython.Compiler.StringEncoding as StringEncoding
+
+
+class StringEncodingTest(unittest.TestCase):
+ """
+ Test the StringEncoding module.
+ """
+ def test_string_contains_lone_surrogates(self):
+ self.assertFalse(StringEncoding.string_contains_lone_surrogates(u"abc"))
+ self.assertFalse(StringEncoding.string_contains_lone_surrogates(u"\uABCD"))
+ self.assertFalse(StringEncoding.string_contains_lone_surrogates(u"\N{SNOWMAN}"))
+
+ # This behaves differently in Py2 when freshly parsed and read from a .pyc file,
+ # but it seems to be a marshalling bug in Py2, which doesn't hurt us in Cython.
+ if sys.version_info[0] != 2:
+ self.assertTrue(StringEncoding.string_contains_lone_surrogates(u"\uD800\uDFFF"))
+
+ # In Py2 with 16bit Unicode, the following is indistinguishable from the 32bit character.
+ obfuscated_surrogate_pair = (u"\uDFFF" + "\uD800")[::-1]
+ if sys.version_info[0] == 2 and sys.maxunicode == 65565:
+ self.assertFalse(StringEncoding.string_contains_lone_surrogates(obfuscated_surrogate_pair))
+ else:
+ self.assertTrue(StringEncoding.string_contains_lone_surrogates(obfuscated_surrogate_pair))
+
+ self.assertTrue(StringEncoding.string_contains_lone_surrogates(u"\uD800"))
+ self.assertTrue(StringEncoding.string_contains_lone_surrogates(u"\uDFFF"))
+ self.assertTrue(StringEncoding.string_contains_lone_surrogates(u"\uDFFF\uD800"))
+ self.assertTrue(StringEncoding.string_contains_lone_surrogates(u"\uD800x\uDFFF"))
+
+ def test_string_contains_surrogates(self):
+ self.assertFalse(StringEncoding.string_contains_surrogates(u"abc"))
+ self.assertFalse(StringEncoding.string_contains_surrogates(u"\uABCD"))
+ self.assertFalse(StringEncoding.string_contains_surrogates(u"\N{SNOWMAN}"))
+
+ self.assertTrue(StringEncoding.string_contains_surrogates(u"\uD800"))
+ self.assertTrue(StringEncoding.string_contains_surrogates(u"\uDFFF"))
+ self.assertTrue(StringEncoding.string_contains_surrogates(u"\uD800\uDFFF"))
+ self.assertTrue(StringEncoding.string_contains_surrogates(u"\uDFFF\uD800"))
+ self.assertTrue(StringEncoding.string_contains_surrogates(u"\uD800x\uDFFF"))
diff --git a/contrib/tools/cython/Cython/Compiler/Tests/TestTreeFragment.py b/contrib/tools/cython/Cython/Compiler/Tests/TestTreeFragment.py
new file mode 100644
index 0000000000..9ee8da5478
--- /dev/null
+++ b/contrib/tools/cython/Cython/Compiler/Tests/TestTreeFragment.py
@@ -0,0 +1,64 @@
+from Cython.TestUtils import CythonTest
+from Cython.Compiler.TreeFragment import *
+from Cython.Compiler.Nodes import *
+from Cython.Compiler.UtilNodes import *
+import Cython.Compiler.Naming as Naming
+
+class TestTreeFragments(CythonTest):
+
+ def test_basic(self):
+ F = self.fragment(u"x = 4")
+ T = F.copy()
+ self.assertCode(u"x = 4", T)
+
+ def test_copy_is_taken(self):
+ F = self.fragment(u"if True: x = 4")
+ T1 = F.root
+ T2 = F.copy()
+ self.assertEqual("x", T2.stats[0].if_clauses[0].body.lhs.name)
+ T2.stats[0].if_clauses[0].body.lhs.name = "other"
+ self.assertEqual("x", T1.stats[0].if_clauses[0].body.lhs.name)
+
+ def test_substitutions_are_copied(self):
+ T = self.fragment(u"y + y").substitute({"y": NameNode(pos=None, name="x")})
+ self.assertEqual("x", T.stats[0].expr.operand1.name)
+ self.assertEqual("x", T.stats[0].expr.operand2.name)
+ self.assertTrue(T.stats[0].expr.operand1 is not T.stats[0].expr.operand2)
+
+ def test_substitution(self):
+ F = self.fragment(u"x = 4")
+ y = NameNode(pos=None, name=u"y")
+ T = F.substitute({"x" : y})
+ self.assertCode(u"y = 4", T)
+
+ def test_exprstat(self):
+ F = self.fragment(u"PASS")
+ pass_stat = PassStatNode(pos=None)
+ T = F.substitute({"PASS" : pass_stat})
+ self.assertTrue(isinstance(T.stats[0], PassStatNode), T)
+
+ def test_pos_is_transferred(self):
+ F = self.fragment(u"""
+ x = y
+ x = u * v ** w
+ """)
+ T = F.substitute({"v" : NameNode(pos=None, name="a")})
+ v = F.root.stats[1].rhs.operand2.operand1
+ a = T.stats[1].rhs.operand2.operand1
+ self.assertEqual(v.pos, a.pos)
+
+ def test_temps(self):
+ TemplateTransform.temp_name_counter = 0
+ F = self.fragment(u"""
+ TMP
+ x = TMP
+ """)
+ T = F.substitute(temps=[u"TMP"])
+ s = T.body.stats
+ self.assertTrue(isinstance(s[0].expr, TempRefNode))
+ self.assertTrue(isinstance(s[1].rhs, TempRefNode))
+ self.assertTrue(s[0].expr.handle is s[1].rhs.handle)
+
+if __name__ == "__main__":
+ import unittest
+ unittest.main()
diff --git a/contrib/tools/cython/Cython/Compiler/Tests/TestTreePath.py b/contrib/tools/cython/Cython/Compiler/Tests/TestTreePath.py
new file mode 100644
index 0000000000..bee53b3d2b
--- /dev/null
+++ b/contrib/tools/cython/Cython/Compiler/Tests/TestTreePath.py
@@ -0,0 +1,94 @@
+import unittest
+from Cython.Compiler.Visitor import PrintTree
+from Cython.TestUtils import TransformTest
+from Cython.Compiler.TreePath import find_first, find_all
+from Cython.Compiler import Nodes, ExprNodes
+
+class TestTreePath(TransformTest):
+ _tree = None
+
+ def _build_tree(self):
+ if self._tree is None:
+ self._tree = self.run_pipeline([], u"""
+ def decorator(fun): # DefNode
+ return fun # ReturnStatNode, NameNode
+ @decorator # NameNode
+ def decorated(): # DefNode
+ pass
+ """)
+ return self._tree
+
+ def test_node_path(self):
+ t = self._build_tree()
+ self.assertEqual(2, len(find_all(t, "//DefNode")))
+ self.assertEqual(2, len(find_all(t, "//NameNode")))
+ self.assertEqual(1, len(find_all(t, "//ReturnStatNode")))
+ self.assertEqual(1, len(find_all(t, "//DefNode//ReturnStatNode")))
+
+ def test_node_path_star(self):
+ t = self._build_tree()
+ self.assertEqual(10, len(find_all(t, "//*")))
+ self.assertEqual(8, len(find_all(t, "//DefNode//*")))
+ self.assertEqual(0, len(find_all(t, "//NameNode//*")))
+
+ def test_node_path_attribute(self):
+ t = self._build_tree()
+ self.assertEqual(2, len(find_all(t, "//NameNode/@name")))
+ self.assertEqual(['fun', 'decorator'], find_all(t, "//NameNode/@name"))
+
+ def test_node_path_attribute_dotted(self):
+ t = self._build_tree()
+ self.assertEqual(1, len(find_all(t, "//ReturnStatNode/@value.name")))
+ self.assertEqual(['fun'], find_all(t, "//ReturnStatNode/@value.name"))
+
+ def test_node_path_child(self):
+ t = self._build_tree()
+ self.assertEqual(1, len(find_all(t, "//DefNode/ReturnStatNode/NameNode")))
+ self.assertEqual(1, len(find_all(t, "//ReturnStatNode/NameNode")))
+
+ def test_node_path_node_predicate(self):
+ t = self._build_tree()
+ self.assertEqual(0, len(find_all(t, "//DefNode[.//ForInStatNode]")))
+ self.assertEqual(2, len(find_all(t, "//DefNode[.//NameNode]")))
+ self.assertEqual(1, len(find_all(t, "//ReturnStatNode[./NameNode]")))
+ self.assertEqual(Nodes.ReturnStatNode,
+ type(find_first(t, "//ReturnStatNode[./NameNode]")))
+
+ def test_node_path_node_predicate_step(self):
+ t = self._build_tree()
+ self.assertEqual(2, len(find_all(t, "//DefNode[.//NameNode]")))
+ self.assertEqual(8, len(find_all(t, "//DefNode[.//NameNode]//*")))
+ self.assertEqual(1, len(find_all(t, "//DefNode[.//NameNode]//ReturnStatNode")))
+ self.assertEqual(Nodes.ReturnStatNode,
+ type(find_first(t, "//DefNode[.//NameNode]//ReturnStatNode")))
+
+ def test_node_path_attribute_exists(self):
+ t = self._build_tree()
+ self.assertEqual(2, len(find_all(t, "//NameNode[@name]")))
+ self.assertEqual(ExprNodes.NameNode,
+ type(find_first(t, "//NameNode[@name]")))
+
+ def test_node_path_attribute_exists_not(self):
+ t = self._build_tree()
+ self.assertEqual(0, len(find_all(t, "//NameNode[not(@name)]")))
+ self.assertEqual(2, len(find_all(t, "//NameNode[not(@honking)]")))
+
+ def test_node_path_and(self):
+ t = self._build_tree()
+ self.assertEqual(1, len(find_all(t, "//DefNode[.//ReturnStatNode and .//NameNode]")))
+ self.assertEqual(0, len(find_all(t, "//NameNode[@honking and @name]")))
+ self.assertEqual(0, len(find_all(t, "//NameNode[@name and @honking]")))
+ self.assertEqual(2, len(find_all(t, "//DefNode[.//NameNode[@name] and @name]")))
+
+ def test_node_path_attribute_string_predicate(self):
+ t = self._build_tree()
+ self.assertEqual(1, len(find_all(t, "//NameNode[@name = 'decorator']")))
+
+ def test_node_path_recursive_predicate(self):
+ t = self._build_tree()
+ self.assertEqual(2, len(find_all(t, "//DefNode[.//NameNode[@name]]")))
+ self.assertEqual(1, len(find_all(t, "//DefNode[.//NameNode[@name = 'decorator']]")))
+ self.assertEqual(1, len(find_all(t, "//DefNode[.//ReturnStatNode[./NameNode[@name = 'fun']]/NameNode]")))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/contrib/tools/cython/Cython/Compiler/Tests/TestTypes.py b/contrib/tools/cython/Cython/Compiler/Tests/TestTypes.py
new file mode 100644
index 0000000000..f2f6f3773b
--- /dev/null
+++ b/contrib/tools/cython/Cython/Compiler/Tests/TestTypes.py
@@ -0,0 +1,19 @@
+from __future__ import absolute_import
+
+import unittest
+
+import Cython.Compiler.PyrexTypes as PT
+
+
+class TestMethodDispatcherTransform(unittest.TestCase):
+
+ def test_widest_numeric_type(self):
+ def assert_widest(type1, type2, widest):
+ self.assertEqual(widest, PT.widest_numeric_type(type1, type2))
+
+ assert_widest(PT.c_int_type, PT.c_long_type, PT.c_long_type)
+ assert_widest(PT.c_double_type, PT.c_long_type, PT.c_double_type)
+ assert_widest(PT.c_longdouble_type, PT.c_long_type, PT.c_longdouble_type)
+
+ cenum = PT.CEnumType("E", "cenum", typedef_flag=False)
+ assert_widest(PT.c_int_type, cenum, PT.c_int_type)
diff --git a/contrib/tools/cython/Cython/Compiler/Tests/TestUtilityLoad.py b/contrib/tools/cython/Cython/Compiler/Tests/TestUtilityLoad.py
new file mode 100644
index 0000000000..3d1906ca0b
--- /dev/null
+++ b/contrib/tools/cython/Cython/Compiler/Tests/TestUtilityLoad.py
@@ -0,0 +1,101 @@
+import unittest
+
+from Cython.Compiler import Code, UtilityCode
+
+
+def strip_2tup(tup):
+ return tup[0] and tup[0].strip(), tup[1] and tup[1].strip()
+
+class TestUtilityLoader(unittest.TestCase):
+ """
+ Test loading UtilityCodes
+ """
+
+ expected = "test {{loader}} prototype", "test {{loader}} impl"
+
+ required = "req {{loader}} proto", "req {{loader}} impl"
+
+ context = dict(loader='Loader')
+
+ name = "TestUtilityLoader"
+ filename = "TestUtilityLoader.c"
+ cls = Code.UtilityCode
+
+ def test_load_as_string(self):
+ got = strip_2tup(self.cls.load_as_string(self.name))
+ self.assertEqual(got, self.expected)
+
+ got = strip_2tup(self.cls.load_as_string(self.name, self.filename))
+ self.assertEqual(got, self.expected)
+
+ def test_load(self):
+ utility = self.cls.load(self.name)
+ got = strip_2tup((utility.proto, utility.impl))
+ self.assertEqual(got, self.expected)
+
+ required, = utility.requires
+ got = strip_2tup((required.proto, required.impl))
+ self.assertEqual(got, self.required)
+
+ utility = self.cls.load(self.name, from_file=self.filename)
+ got = strip_2tup((utility.proto, utility.impl))
+ self.assertEqual(got, self.expected)
+
+ utility = self.cls.load_cached(self.name, from_file=self.filename)
+ got = strip_2tup((utility.proto, utility.impl))
+ self.assertEqual(got, self.expected)
+
+
+class TestTempitaUtilityLoader(TestUtilityLoader):
+ """
+ Test loading UtilityCodes with Tempita substitution
+ """
+ expected_tempita = (TestUtilityLoader.expected[0].replace('{{loader}}', 'Loader'),
+ TestUtilityLoader.expected[1].replace('{{loader}}', 'Loader'))
+
+ required_tempita = (TestUtilityLoader.required[0].replace('{{loader}}', 'Loader'),
+ TestUtilityLoader.required[1].replace('{{loader}}', 'Loader'))
+
+ cls = Code.TempitaUtilityCode
+
+ def test_load_as_string(self):
+ got = strip_2tup(self.cls.load_as_string(self.name, context=self.context))
+ self.assertEqual(got, self.expected_tempita)
+
+ def test_load(self):
+ utility = self.cls.load(self.name, context=self.context)
+ got = strip_2tup((utility.proto, utility.impl))
+ self.assertEqual(got, self.expected_tempita)
+
+ required, = utility.requires
+ got = strip_2tup((required.proto, required.impl))
+ self.assertEqual(got, self.required_tempita)
+
+ utility = self.cls.load(self.name, from_file=self.filename, context=self.context)
+ got = strip_2tup((utility.proto, utility.impl))
+ self.assertEqual(got, self.expected_tempita)
+
+
+class TestCythonUtilityLoader(TestTempitaUtilityLoader):
+ """
+ Test loading CythonUtilityCodes
+ """
+
+ # Just change the attributes and run the same tests
+ expected = None, "test {{cy_loader}} impl"
+ expected_tempita = None, "test CyLoader impl"
+
+ required = None, "req {{cy_loader}} impl"
+ required_tempita = None, "req CyLoader impl"
+
+ context = dict(cy_loader='CyLoader')
+
+ name = "TestCyUtilityLoader"
+ filename = "TestCyUtilityLoader.pyx"
+ cls = UtilityCode.CythonUtilityCode
+
+ # Small hack to pass our tests above
+ cls.proto = None
+
+ test_load = TestUtilityLoader.test_load
+ test_load_tempita = TestTempitaUtilityLoader.test_load
diff --git a/contrib/tools/cython/Cython/Compiler/Tests/TestVisitor.py b/contrib/tools/cython/Cython/Compiler/Tests/TestVisitor.py
new file mode 100644
index 0000000000..dbc8e0c03a
--- /dev/null
+++ b/contrib/tools/cython/Cython/Compiler/Tests/TestVisitor.py
@@ -0,0 +1,61 @@
+from Cython.Compiler.ModuleNode import ModuleNode
+from Cython.Compiler.Symtab import ModuleScope
+from Cython.TestUtils import TransformTest
+from Cython.Compiler.Visitor import MethodDispatcherTransform
+from Cython.Compiler.ParseTreeTransforms import (
+ NormalizeTree, AnalyseDeclarationsTransform,
+ AnalyseExpressionsTransform, InterpretCompilerDirectives)
+
+
+class TestMethodDispatcherTransform(TransformTest):
+ _tree = None
+
+ def _build_tree(self):
+ if self._tree is None:
+ context = None
+
+ def fake_module(node):
+ scope = ModuleScope('test', None, None)
+ return ModuleNode(node.pos, doc=None, body=node,
+ scope=scope, full_module_name='test',
+ directive_comments={})
+ pipeline = [
+ fake_module,
+ NormalizeTree(context),
+ InterpretCompilerDirectives(context, {}),
+ AnalyseDeclarationsTransform(context),
+ AnalyseExpressionsTransform(context),
+ ]
+ self._tree = self.run_pipeline(pipeline, u"""
+ cdef bytes s = b'asdfg'
+ cdef dict d = {1:2}
+ x = s * 3
+ d.get('test')
+ """)
+ return self._tree
+
+ def test_builtin_method(self):
+ calls = [0]
+ class Test(MethodDispatcherTransform):
+ def _handle_simple_method_dict_get(self, node, func, args, unbound):
+ calls[0] += 1
+ return node
+
+ tree = self._build_tree()
+ Test(None)(tree)
+ self.assertEqual(1, calls[0])
+
+ def test_binop_method(self):
+ calls = {'bytes': 0, 'object': 0}
+ class Test(MethodDispatcherTransform):
+ def _handle_simple_method_bytes___mul__(self, node, func, args, unbound):
+ calls['bytes'] += 1
+ return node
+ def _handle_simple_method_object___mul__(self, node, func, args, unbound):
+ calls['object'] += 1
+ return node
+
+ tree = self._build_tree()
+ Test(None)(tree)
+ self.assertEqual(1, calls['bytes'])
+ self.assertEqual(0, calls['object'])
diff --git a/contrib/tools/cython/Cython/Compiler/Tests/__init__.py b/contrib/tools/cython/Cython/Compiler/Tests/__init__.py
new file mode 100644
index 0000000000..fa81adaff6
--- /dev/null
+++ b/contrib/tools/cython/Cython/Compiler/Tests/__init__.py
@@ -0,0 +1 @@
+# empty file