def create_wrapper_code(decls, instance_map, addons, converters, out, extra_inc_dirs, extra_opts, include_boost=True, allDecl=[]): cimports, manual_code = collect_manual_code(addons) register_converters(converters) inc_dirs = autowrap.generate_code(decls, instance_map=instance_map, target=out, debug=False, manual_code=manual_code, extra_cimports=cimports, include_boost=include_boost, allDecl=allDecl) if extra_inc_dirs is not None: inc_dirs += extra_inc_dirs run_cython(inc_dirs, extra_opts, out) return inc_dirs
def create_wrapper_code(decls, instance_map, addons, converters, out, extra_inc_dirs, extra_opts, include_boost=True): cimports, manual_code = collect_manual_code(addons) register_converters(converters) inc_dirs = autowrap.generate_code(decls, instance_map, out, False, manual_code, cimports, include_boost) if extra_inc_dirs is not None: inc_dirs += extra_inc_dirs run_cython(inc_dirs, extra_opts, out) return inc_dirs
def doCythonCodeGeneration(modname, allDecl_mapping, instance_map, converters): m_filename = "pyopenms/%s.pyx" % modname cimports, manual_code = autowrap.Main.collect_manual_code( allDecl_mapping[modname]["addons"]) autowrap.Main.register_converters(converters) autowrap_include_dirs = autowrap.generate_code( allDecl_mapping[modname]["decls"], instance_map, target=m_filename, debug=False, manual_code=manual_code, extra_cimports=cimports, include_boost=False, include_numpy=True, allDecl=allDecl_mapping, add_relative=True) allDecl_mapping[modname]["inc_dirs"] = autowrap_include_dirs return autowrap_include_dirs
def test_templated(): target = os.path.join(test_files, "templated_wrapper.pyx") decls, instance_map = autowrap.parse(["templated.pxd"], root=test_files) co = autowrap.Code.Code() co.add("""def special(self): | return "hi" """) methods = dict(T=co) include_dirs = autowrap.generate_code(decls, instance_map, target=target, debug=True, manual_code=methods) cpp_source = os.path.join(test_files, "templated.cpp") cpp_sources = [] twrapped = autowrap.Utils.compile_and_import("twrapped", [target] + cpp_sources, include_dirs) os.remove(target) assert twrapped.__name__ == "twrapped" t = twrapped.T(42) assert t.special() == "hi" templated = twrapped.Templated(t) assert templated.get().get() == 42 assert templated.passs(templated) == templated in_ = [templated, templated] assert templated.summup(in_) == 42 + 42 __, __, tn = in_ assert tn.get().get() == 11 tn, __, __ = templated.reverse(in_) assert tn.get().get() == 11 y = twrapped.Y() _, __, tn = y.passs(in_) assert tn.get().get() == 11 # renamed attribute templated.f_att = 2 assert templated.f_att == 2.0 templated.f_att = 4 assert templated.f_att == 4.0 t13 = twrapped.T(13) templated._x = t13 assert templated._x.get() == 13 t17 = twrapped.T(17) templated._x = t17 assert templated._x.get() == 17 templated.xi = [t13, t17] assert templated.xi[0].get() == 13 assert templated.xi[1].get() == 17 templated.xi = [t17, t13] assert templated.xi[0].get() == 17 assert templated.xi[1].get() == 13 # Test second template (it adds 1 to everything) t_o = twrapped.T2(42) templated_o = twrapped.Templated_other(t_o) assert templated_o.get().get() == 43 assert templated_o.passs(templated_o) == templated_o # Try out the adding 1 thing t11 = twrapped.T2(10) t12 = twrapped.T2(11) templated_o.xi = [t11, t12] assert templated_o.xi[0].get() == 11 assert templated_o.xi[1].get() == 12 # Test free functions assert templated.computeSeven() == 7 assert templated_o.computeSeven() == 7
def test_full_lib(tmpdir): """ Example with multi-file library and multi-file result. This shows a full run through of a case where multiple class files (A, B, C, D) with multiple classes in them (Aklass, A_second, etc.) need to be wrapped, a total of 10 different entities over 8 header files (4 hpp and 4 pxd files). Autowrap will generate a .pxd and a .pyx file for each module. We decided to wrap the library into three modules, A, B and CD to show the capability of autowrap to do that. Note that we have perform multiple steps: - Step 1: parse all header files *together* - all pxd files need to be parsed together so that declarations are properly resolved. - Step 2: Map the different parsed entities to the pxd files and the desired modules, we use a master dict here that can be consumed by autowrap and specifies which pxd files and which declarations make up which module. - Step 3: Generate Cython code for each module - Step 4: Generate C++ code for each module (note that Step 3 has to be completed first before we can start to generate C++ code) - Step 5: Compile (run setup.py) Note that autowrap gives you full control how many modules you want to produce and which classes go into which modules. It automatically generates correct cimport statements in each so that dependencies between the modules are not an issue. """ curdir = os.getcwd() os.chdir(tmpdir.strpath) try: mnames = ["moduleA", "moduleB", "moduleCD"] # Step 1: parse all header files PY_NUM_THREADS = 1 pxd_files = ["A.pxd", "B.pxd", "C.pxd", "D.pxd"] full_pxd_files = [os.path.join(test_files, f) for f in pxd_files] decls, instance_map = autowrap.parse(full_pxd_files, ".", num_processes=int(PY_NUM_THREADS)) assert len(decls) == 13, len(decls) # Step 2: Perform mapping pxd_decl_mapping = {} for de in decls: tmp = pxd_decl_mapping.get(de.cpp_decl.pxd_path, []) tmp.append(de) pxd_decl_mapping[de.cpp_decl.pxd_path] = tmp masterDict = {} masterDict[mnames[0]] = { "decls": pxd_decl_mapping[full_pxd_files[0]], "addons": [], "files": [full_pxd_files[0]], } masterDict[mnames[1]] = { "decls": pxd_decl_mapping[full_pxd_files[1]], "addons": [], "files": [full_pxd_files[1]], } masterDict[mnames[2]] = { "decls": pxd_decl_mapping[full_pxd_files[2]] + pxd_decl_mapping[full_pxd_files[3]], "addons": [], "files": [full_pxd_files[2]] + [full_pxd_files[3]], } # Step 3: Generate Cython code converters = [] for modname in mnames: m_filename = "%s.pyx" % modname cimports, manual_code = autowrap.Main.collect_manual_code( masterDict[modname]["addons"]) autowrap.Main.register_converters(converters) autowrap_include_dirs = autowrap.generate_code( masterDict[modname]["decls"], instance_map, target=m_filename, debug=False, manual_code=manual_code, extra_cimports=cimports, include_boost=True, allDecl=masterDict, ) masterDict[modname]["inc_dirs"] = autowrap_include_dirs # Step 4: Generate CPP code for modname in mnames: m_filename = "%s.pyx" % modname autowrap_include_dirs = masterDict[modname]["inc_dirs"] autowrap.Main.run_cython(inc_dirs=autowrap_include_dirs, extra_opts=None, out=m_filename) # Step 5: Compile all_pyx_files = ["%s.pyx" % modname for modname in mnames] all_pxd_files = ["%s.pxd" % modname for modname in mnames] include_dirs = masterDict[modname]["inc_dirs"] moduleA, moduleB, moduleCD = compile_and_import( mnames, all_pyx_files, include_dirs, extra_files=all_pxd_files) finally: os.chdir(curdir) Aobj = moduleA.Aalias(5) Asecond = moduleA.A_second(8) assert Asecond.i_ == 8 assert Aobj.i_ == 5 assert Aobj.KlassE is not None assert Aobj.KlassE.A1 is not None assert Aobj.KlassE.A2 is not None assert Aobj.KlassE.A3 is not None Bobj = moduleB.Bklass(5) assert Bobj.i_ == 5 # access through A_second Bobj.callA2() assert Bobj.i_ == 6 # access through A_second Bsecond = moduleB.B_second(8) assert Bsecond.i_ == 8 Bsecond.processA(Aobj) assert Bsecond.i_ == 15 assert Bobj.KlassE is not None assert Bobj.KlassE.B1 is not None assert Bobj.KlassE.B2 is not None assert Bobj.KlassE.B3 is not None assert Bobj.KlassKlass is not None # there are two different ways to get Bklass::KlassKlass, either through a # Bklass object or through the module Bobj_kk = Bobj.KlassKlass() Bobj_kk.k_ = 14 assert Bobj_kk.k_ == 14 Bobj_kk = moduleB.Bklass.KlassKlass() Bobj_kk.k_ = 14 assert Bobj_kk.k_ == 14 # Check doc string assert "Inherits from" in moduleB.Bklass.__doc__ assert "some doc!" in moduleB.Bklass.__doc__ assert len(moduleB.Bklass.__doc__) == 92, len(moduleB.Bklass.__doc__) Bsecond = moduleB.B_second(8) Dsecond = moduleCD.D_second(11) assert Dsecond.i_ == 11 Dsecond.runB(Bsecond) assert Dsecond.i_ == 8
def test_full_lib(tmpdir): """ Example with multi-file library and multi-file result. This shows a full run through of a case where multiple class files (A, B, C, D) with multiple classes in them (Aklass, A_second, etc.) need to be wrapped, a total of 10 different entities over 8 header files (4 hpp and 4 pxd files). Autowrap will generate a .pxd and a .pyx file for each module. We decided to wrap the library into three modules, A, B and CD to show the capability of autowrap to do that. Note that we have perform multiple steps: - Step 1: parse all header files *together* - all pxd files need to be parsed together so that declarations are properly resolved. - Step 2: Map the different parsed entities to the pxd files and the desired modules, we use a master dict here that can be consumed by autowrap and specifies which pxd files and which declarations make up which module. - Step 3: Generate Cython code for each module - Step 4: Generate C++ code for each module (note that Step 3 has to be completed first before we can start to generate C++ code) - Step 5: Compile (run setup.py) Note that autowrap gives you full control how many modules you want to produce and which classes go into which modules. It automatically generates correct cimport statements in each so that dependencies between the modules are not an issue. """ os.chdir(tmpdir.strpath) mnames = ["moduleA", "moduleB", "moduleCD"] # Step 1: parse all header files PY_NUM_THREADS = 1 pxd_files = ["A.pxd", "B.pxd", "C.pxd", "D.pxd"] full_pxd_files = [os.path.join(test_files, f) for f in pxd_files] decls, instance_map = autowrap.parse( full_pxd_files, ".", num_processes=int(PY_NUM_THREADS) ) assert len(decls) == 13, len(decls) # Step 2: Perform mapping pxd_decl_mapping = {} for de in decls: tmp = pxd_decl_mapping.get(de.cpp_decl.pxd_path, []) tmp.append(de) pxd_decl_mapping[de.cpp_decl.pxd_path] = tmp masterDict = {} masterDict[mnames[0]] = { "decls": pxd_decl_mapping[full_pxd_files[0]], "addons": [], "files": [full_pxd_files[0]], } masterDict[mnames[1]] = { "decls": pxd_decl_mapping[full_pxd_files[1]], "addons": [], "files": [full_pxd_files[1]], } masterDict[mnames[2]] = { "decls": pxd_decl_mapping[full_pxd_files[2]] + pxd_decl_mapping[full_pxd_files[3]], "addons": [], "files": [full_pxd_files[2]] + [full_pxd_files[3]], } # Step 3: Generate Cython code converters = [] for modname in mnames: m_filename = "%s.pyx" % modname cimports, manual_code = autowrap.Main.collect_manual_code( masterDict[modname]["addons"] ) autowrap.Main.register_converters(converters) autowrap_include_dirs = autowrap.generate_code( masterDict[modname]["decls"], instance_map, target=m_filename, debug=False, manual_code=manual_code, extra_cimports=cimports, include_boost=True, allDecl=masterDict, ) masterDict[modname]["inc_dirs"] = autowrap_include_dirs # Step 4: Generate CPP code for modname in mnames: m_filename = "%s.pyx" % modname autowrap_include_dirs = masterDict[modname]["inc_dirs"] autowrap.Main.run_cython( inc_dirs=autowrap_include_dirs, extra_opts=None, out=m_filename ) # Step 5: Compile all_pyx_files = ["%s.pyx" % modname for modname in mnames] all_pxd_files = ["%s.pxd" % modname for modname in mnames] include_dirs = masterDict[modname]["inc_dirs"] moduleA, moduleB, moduleCD = compile_and_import( mnames, all_pyx_files, include_dirs, extra_files=all_pxd_files ) Aobj = moduleA.Aalias(5) Asecond = moduleA.A_second(8) assert Asecond.i_ == 8 assert Aobj.i_ == 5 assert Aobj.KlassE is not None assert Aobj.KlassE.A1 is not None assert Aobj.KlassE.A2 is not None assert Aobj.KlassE.A3 is not None Bobj = moduleB.Bklass(5) Bsecond = moduleB.B_second(8) assert Bsecond.i_ == 8 Bsecond.processA(Aobj) assert Bsecond.i_ == 15 assert Bobj.KlassE is not None assert Bobj.KlassE.B1 is not None assert Bobj.KlassE.B2 is not None assert Bobj.KlassE.B3 is not None assert Bobj.KlassKlass is not None # there are two different ways to get Bklass::KlassKlass, either through a # Bklass object or through the module Bobj_kk = Bobj.KlassKlass() Bobj_kk.k_ = 14 assert Bobj_kk.k_ == 14 Bobj_kk = moduleB.Bklass.KlassKlass() Bobj_kk.k_ = 14 assert Bobj_kk.k_ == 14 Bsecond = moduleB.B_second(8) Dsecond = moduleCD.D_second(11) assert Dsecond.i_ == 11 Dsecond.runB(Bsecond) assert Dsecond.i_ == 8