first commit
This commit is contained in:
commit
417e54da96
5696 changed files with 900003 additions and 0 deletions
|
@ -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()
|
||||
|
|
@ -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")
|
|
@ -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)
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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)
|
|
@ -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"))
|
|
@ -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()
|
|
@ -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()
|
|
@ -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)
|
|
@ -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
|
|
@ -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'])
|
|
@ -0,0 +1 @@
|
|||
# empty file
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue