module_node.scope.utility_code_list.extend(scope.utility_code_list)
return module_node
+ test_support = []
+ if options.evaluate_tree_assertions:
+ from Cython.TestUtils import TreeAssertVisitor
+ test_support.append(TreeAssertVisitor())
+
return ([
create_parse(self),
- ] + self.create_pipeline(pxd=False, py=py) + [
+ ] + self.create_pipeline(pxd=False, py=py) + test_support + [
inject_pxd_code,
abort_on_errors,
generate_pyx_code,
verbose boolean Always print source names being compiled
quiet boolean Don't print source names in recursive mode
compiler_directives dict Overrides for pragma options (see Options.py)
+ evaluate_tree_assertions boolean Test support: evaluate parse tree assertions
Following options are experimental and only used on MacOSX:
verbose = 0,
quiet = 0,
compiler_directives = {},
+ evaluate_tree_assertions = False,
emit_linenums = False,
)
if sys.platform == "mac":
'c99_complex' : False, # Don't use macro wrappers for complex arith, not sure what to name this...
'callspec' : "",
'profile': False,
- 'doctesthack': False
+ 'doctesthack': False,
+
+# test support
+ 'testAssertPathExists' : [],
+ 'testFailIfPathExists' : [],
}
# Override types possibilities above, if needed
option_scopes = { # defaults to available everywhere
# 'module', 'function', 'class', 'with statement'
- 'doctesthack' : ('module',)
+ 'doctesthack' : ('module',),
+ 'testAssertPathExists' : ('function',),
+ 'testFailIfPathExists' : ('function',),
}
def parse_option_value(name, value):
raise PostParseError(dec.function.pos,
'The %s option takes no prepositional arguments' % optname)
return optname, dict([(key.value, value) for key, value in kwds.key_value_pairs])
+ elif optiontype is list:
+ if kwds and len(kwds) != 0:
+ raise PostParseError(dec.function.pos,
+ 'The %s option takes no keyword arguments' % optname)
+ return optname, [ str(arg.value) for arg in args ]
else:
assert False
legal_scopes = Options.option_scopes.get(name, None)
if not self.check_directive_scope(node.pos, name, 'function'):
continue
- if name in optdict and isinstance(optdict[name], dict):
- # only keywords can be merged, everything else
- # overrides completely
- optdict[name].update(value)
+ if name in optdict:
+ old_value = optdict[name]
+ # keywords and arg lists can be merged, everything
+ # else overrides completely
+ if isinstance(old_value, dict):
+ old_value.update(value)
+ elif isinstance(old_value, list):
+ old_value.extend(value)
+ else:
+ optdict[name] = value
else:
optdict[name] = value
body = StatListNode(node.pos, stats=[node])
from Cython.Compiler.ModuleNode import ModuleNode
import Cython.Compiler.Main as Main
from Cython.Compiler.TreeFragment import TreeFragment, strip_common_indent
-from Cython.Compiler.Visitor import TreeVisitor
+from Cython.Compiler.Visitor import TreeVisitor, VisitorTransform
+from Cython.Compiler import TreePath
class NodeTypeWriter(TreeVisitor):
def __init__(self):
self.assertEqual(len(result_lines), len(expected_lines),
"Unmatched lines. Got:\n%s\nExpected:\n%s" % ("\n".join(result_lines), expected))
+ def assertNodeExists(self, path, result_tree):
+ self.assertNotEqual(TreePath.find_first(result_tree, path), None,
+ "Path '%s' not found in result tree" % path)
+
def fragment(self, code, pxds={}, pipeline=[]):
"Simply create a tree fragment using the name of the test-case in parse errors."
name = self.id()
tree = T(tree)
return tree
+
+class TreeAssertVisitor(VisitorTransform):
+ # actually, a TreeVisitor would be enough, but this needs to run
+ # as part of the compiler pipeline
+
+ def visit_CompilerDirectivesNode(self, node):
+ directives = node.directives
+ if 'testAssertPathExists' in directives:
+ for path in directives['testAssertPathExists']:
+ if TreePath.find_first(node, path) is None:
+ Errors.error(
+ node.pos,
+ "Expected path '%s' not found in result tree of node %r" % (
+ path, node.body))
+ if 'testFailIfPathExists' in directives:
+ for path in directives['testFailIfPathExists']:
+ if TreePath.find_first(node, path) is not None:
+ Errors.error(
+ node.pos,
+ "Unexpected path '%s' found in result tree of node %r" % (
+ path, node.body))
+ self.visitchildren(node)
+ return node
+
+ visit_Node = VisitorTransform.recurse_to_children
annotate = annotate,
use_listing_file = False,
cplus = self.language == 'cpp',
- generate_pxi = False)
+ generate_pxi = False,
+ evaluate_tree_assertions = True,
+ )
cython_compile(source, options=options,
full_module_name=module)