def test_multi_mixed(): E, F, X = autowrap.PXDParser.parse_str(""" cdef extern from "": cdef enum E: A, B, C cdef enum F: G, H=4, I cdef cppclass X: void fun(int) """) assert E.name == "E" A, B, C = E.items assert A == ("A", 0) assert B == ("B", 1) assert C == ("C", 2) assert F.name == "F" G, H, I = F.items assert G == ("G", 0) assert H == ("H", 4) assert I == ("I", 5) assert X.name == "X", X (fun, ), = X.methods.values() assert fun.result_type == CppType("void"), fun.result_type assert fun.name == "fun" (arg_name, type_), = fun.arguments assert arg_name == "" assert type_ == CppType("int")
def test_ptr(): gun, = autowrap.PXDParser.parse_str(""" cdef extern from "": unsigned int * gun (vector[double *] *) """) assert gun.result_type == CppType.from_string("unsigned int *") (n, t), = gun.arguments assert t == CppType.from_string("vector[double *] *")
def _assert_exeception_when_testing(str_): try: CppType.from_string(str_).check_for_recursion() except Exception as e: estr = str(e) if not estr.startswith("recursion check for "): if not estr.endswith(" failed"): raise e else: assert False, "invalid type '%s' passed test" % str_
def test_nested_mapping_flattening(): from autowrap.Types import CppType B = CppType.from_string("B") Y = CppType.from_string("Y") Z = CppType.from_string("Z") CXD = CppType.from_string("C[X,D]") mapping = dict(A=B, B=CXD, C=Z, D=Y) autowrap.Utils.flatten(mapping) assert str(mapping["A"]) == "Z[X,Y]" assert str(mapping["B"]) == "Z[X,Y]" assert str(mapping["C"]) == "Z" assert str(mapping["D"]) == "Y"
def test_minimal(): cld, = autowrap.PXDParser.parse_str(""" cdef extern from "Minimal.hpp": cdef cppclass Minimal: Minimal(int a) int getA() unsigned int method0(unsigned int input) float method1(float input) double method2(double input) char method3(char input) void overloaded(int inp) void overloaded(float inp) void run(Minimal) void run2(Minimal *) """) assert cld.name == "Minimal" assert cld.template_parameters is None assert len(cld.methods["Minimal"]) == 1 assert len(cld.methods["getA"]) == 1 assert len(cld.methods["method0"]) == 1 assert cld.methods["Minimal"][0].name == "Minimal" assert len(cld.methods["Minimal"][0].arguments) == 1 argname, arg_type = cld.methods["Minimal"][0].arguments[0] assert argname == "a" assert arg_type == CppType("int") assert len(cld.methods["getA"][0].arguments) == 0 def subtest(name, inp_type): meth = cld.methods[name][0] assert meth.result_type == inp_type, str(meth.result_type) assert meth.arguments[0][1] == inp_type subtest("method0", CppType("int", is_unsigned=True)) subtest("method1", CppType("float")) subtest("method2", CppType("double")) subtest("method3", CppType("char")) assert len(cld.methods["overloaded"]) == 2 arguments = [] for meth in cld.methods["overloaded"]: assert meth.name == "overloaded" assert meth.result_type == CppType("void") arguments.append(meth.arguments) assert arguments == [[("inp", CppType("int"))], [("inp", CppType("float"))]] run_meth = cld.methods["run2"][0] name, arg_type = run_meth.arguments[0] assert str(arg_type) == "Minimal *" run_meth = cld.methods["run"][0] name, arg_type = run_meth.arguments[0] assert str(arg_type) == "Minimal"
def _extract_template_args(node): if isinstance(node, NameNode): return CppType(node.name, None) name = node.base.name if isinstance(node.index, TupleNode): args = [_extract_template_args(n) for n in node.index.args] elif isinstance(node.index, IndexNode): args = [_extract_template_args(node.index)] elif isinstance(node.index, NameNode): args = [CppType(node.index.name)] else: raise Exception("can not handle node %s in template arg decl" % node.index) return CppType(name, args)
def _extract_type(base_type, decl): """ extracts type information from node in parse_pxd_file tree """ template_parameters = None if isinstance(base_type, TemplatedTypeNode): template_parameters = [] for arg_node in base_type.positional_args: if isinstance(arg_node, CComplexBaseTypeNode): arg_decl = arg_node.declarator is_ptr = isinstance(arg_decl, CPtrDeclaratorNode) is_ref = isinstance(arg_decl, CReferenceDeclaratorNode) is_unsigned = hasattr(arg_node.base_type, "signed")\ and not arg_node.base_type.signed is_long = hasattr(arg_node.base_type, "longness") and arg_node.base_type.longness # Handle const template arguments which do not have a name # themselves, only their base types have name attribute is_const = isinstance(arg_node.base_type, Nodes.CConstTypeNode) if is_const: name = arg_node.base_type.base_type.name else: name = arg_node.base_type.name ttype = CppType(name, None, is_ptr, is_ref, is_unsigned, is_long, is_const=is_const) template_parameters.append(ttype) elif isinstance(arg_node, NameNode): name = arg_node.name template_parameters.append(CppType(name)) elif isinstance(arg_node, IndexNode): # nested template ! tt = _extract_template_args(arg_node) template_parameters.append(tt) else: raise Exception("can not handle template arg_node %r" % arg_node) base_type = base_type.base_type_node is_ptr = isinstance(decl, CPtrDeclaratorNode) is_ref = isinstance(decl, CReferenceDeclaratorNode) is_unsigned = hasattr(base_type, "signed") and not base_type.signed is_long = hasattr(base_type, "longness") and base_type.longness is_const = isinstance(base_type, Nodes.CConstTypeNode) # Complex const values, e.g. "const Int *" need to be reduced to base type # to get the correct name if is_const: base_type = base_type.base_type return CppType(base_type.name, template_parameters, is_ptr, is_ref, is_unsigned, is_long, is_const=is_const)
def test_inv_transform(): A = CppType.from_string("A") AX = CppType.from_string("A[X]") AXX = CppType.from_string("A[X,X]") ABX = CppType.from_string("A[B[X]]") ABXX = CppType.from_string("A[B[X],X]") T = CppType.from_string("T") def check(t, map_, expected): is_ = str(t.inv_transformed(map_)) assert is_ == expected, is_ map1 = dict(Z=A) check(A, map1, "Z") check(AX, map1, "A[X]") map2 = dict(Z=CppType.from_string("B[X]")) check(ABX, map2, "A[Z]") check(ABXX, map2, "A[Z,X]") ABXp = ABX.copy() ABXp.is_ptr = True check(ABXp, map2, "A[Z] *") ABXXp = ABXX.copy() ABXXp.template_args[0].is_ptr = True check(ABXXp, map2, "A[Z *,X]")
def testTypeParse(): _testType("unsigned int") T = CppType("T") assert str(T) == "T" Tlist = str(CppType("list", [T])) _testType(Tlist) _testType("list[T]") _testType("list[T,T]") _testType("list[list[T],T]") _testType("int") _testType("int *") _testType("unsigned int *") _testType("int &") _testType("unsigned int &") _testType("X[int]") _testType("X[unsigned int]") _testType("X[int *]") _testType("X[unsigned int *]") _testType("X[int &]") _testType("X[unsigned int &]") _testType("X[int,float]") _testType("X[unsigned int,float]") _testType("X[int *,float]") _testType("X[unsigned int *,float]") _testType("X[int &,float]") _testType("X[unsigned int &,float]") _testType("X[int,Y[str]]") _testType("X[unsigned int,Y[str]]") _testType("X[int *,Y[str]]") _testType("X[unsigned int *,Y[str]]") _testType("X[int &,Y[str]]") _testType("X[unsigned int &,Y[str]]") _testErr("unsigned unsigned int")
def test_base_type_collecting(): def check(t, tobe): collected = "".join(sorted(t.all_occuring_base_types())) if collected != tobe: msg = "input '%s', collected '%s'" % (t, collected) assert False, msg check(CppType.from_string("A"), "A") check(CppType.from_string("A[B]"), "AB") check(CppType.from_string("A[B,C]"), "ABC") check(CppType.from_string("A[B[C]]"), "ABC") check(CppType.from_string("A[B[C],D]"), "ABCD") check(CppType.from_string("A[B[C[D]]]"), "ABCD")
def test_transform(): A = CppType("A") B = CppType("B") X = CppType("X") trans = dict(A=X) trans2 = dict(A=CppType("C", [X])) _check(A, trans2, "C[X]") _check(A, trans, "X") B_A = CppType("B", [A]) _check(B_A, trans, "B[X]") _check(B_A, trans2, "B[C[X]]") B_A_A = CppType("B", [A, A]) _check(B_A_A, trans, "B[X,X]") _check(B_A_A, trans2, "B[C[X],C[X]]") B_A_C = CppType("B", [A, CppType("D")]) assert str(B_A_C) == "B[A,D]" _check(B_A_C, trans, "B[X,D]") _check(B_A_C, trans2, "B[C[X],D]")
def _testErr(s): CppType.from_string(s)
def _testType(t): assert t == str(CppType.from_string(t)) == t, str(CppType.from_string(t))
def parse(anno): m = re.match("(\S+)\((\S+)\)", anno) assert m is not None, "invalid iter annotation" name, type_str = m.groups() return name, CppType.from_string(type_str)
def _test_check_for_recursion_1(): CppType.from_string("A").check_for_recursion() CppType.from_string("A[B]").check_for_recursion() CppType.from_string("A[B,B]").check_for_recursion() CppType.from_string("A[B,C]").check_for_recursion() CppType.from_string("A[B[C],C]").check_for_recursion() CppType.from_string("A[B[C],D]").check_for_recursion() CppType.from_string("A[B[C],D[E]]").check_for_recursion() CppType.from_string("A[B[C],D[E],D]").check_for_recursion() CppType.from_string("A[B[C],D[E],B]").check_for_recursion()
def _extract_type(base_type, decl): """ extracts type information from node in parse_pxd_file tree """ type_is_const = isinstance(base_type, Nodes.CConstTypeNode) # Complex const values, e.g. "const Int *" need to be reduced to base type # to get the correct name. Note: we will have to deal with const-ness first # and then with templated arguments that are nested. if type_is_const: base_type = base_type.base_type template_parameters = None if isinstance(base_type, TemplatedTypeNode): template_parameters = [] for arg_node in base_type.positional_args: if isinstance(arg_node, CComplexBaseTypeNode): arg_decl = arg_node.declarator is_ptr = isinstance(arg_decl, CPtrDeclaratorNode) is_ref = isinstance(arg_decl, CReferenceDeclaratorNode) is_unsigned = (hasattr(arg_node.base_type, "signed") and not arg_node.base_type.signed) is_long = (hasattr(arg_node.base_type, "longness") and arg_node.base_type.longness) # Handle const template arguments which do not have a name # themselves, only their base types have name attribute (see # for example: shared_ptr<const Int>) arg_is_const = isinstance(arg_node.base_type, Nodes.CConstTypeNode) if arg_is_const: name = arg_node.base_type.base_type.name else: name = arg_node.base_type.name args = None template_args = getattr(arg_node.base_type, "positional_args", None) if template_args: args = [ _extract_type(t.base_type, t.declarator) for t in template_args ] name = arg_node.base_type.base_type_node.name ttype = CppType( name, args, is_ptr, is_ref, is_unsigned, is_long, is_const=arg_is_const, ) template_parameters.append(ttype) elif isinstance(arg_node, NameNode): name = arg_node.name template_parameters.append(CppType(name)) elif isinstance(arg_node, IndexNode): # nested template ! tt = _extract_template_args(arg_node) template_parameters.append(tt) else: raise Exception("can not handle template arg_node %r" % arg_node.pos[0].file_path + " line: %r" % arg_node.pos[1] + " col: %r" % arg_node.pos[2]) base_type = base_type.base_type_node is_ptr = isinstance(decl, CPtrDeclaratorNode) is_ref = isinstance(decl, CReferenceDeclaratorNode) is_unsigned = hasattr(base_type, "signed") and not base_type.signed is_long = hasattr(base_type, "longness") and base_type.longness return CppType( base_type.name, template_parameters, is_ptr, is_ref, is_unsigned, is_long, is_const=type_is_const, )