""" Cython-based Python Module for Python 3 """ from buildutils import * Import('env', 'build', 'install') localenv = env.Clone() def configure_numpy(python_command): script = '\n'.join(("from distutils.sysconfig import *", "import numpy", "print(get_config_var('SO'))", "print(get_python_version())", "print(numpy.get_include())")) info = getCommandOutput(python_command, '-c', script) module_ext, py_version, numpy_include = info.splitlines() incDirs = (".", "../../include", numpy_include, localenv['sundials_include'], localenv['boost_inc_dir']) localenv['py_include_dirs'] = repr([x for x in incDirs if x]) return module_ext, py_version def add_dependencies(mod, ext): localenv.Depends(mod, ext) localenv.Depends(ext, localenv['cantera_staticlib']) localenv.Depends(mod, dataFiles + testFiles) for f in mglob(localenv, 'cantera', 'pyx', 'pxd'): localenv.Depends(ext, f) for f in (mglob(localenv, 'cantera/test', 'py') + mglob(localenv, 'cantera/examples/tutorial', 'py') + mglob(localenv, 'cantera/examples/equilibrium', 'py') + mglob(localenv, 'cantera/examples/kinetics', 'py') + mglob(localenv, 'cantera/examples/transport', 'py') + mglob(localenv, 'cantera/examples/reactors', 'py') + mglob(localenv, 'cantera/examples/onedim', 'py') + mglob(localenv, 'cantera/examples/surface_chemistry', 'py') + mglob(localenv, 'cantera/examples/misc', 'py')): localenv.Depends(mod, f) def install_module(prefix, python_version): if prefix: # A specific location for the Cantera python module has been specified extra = '--prefix="%s"' % prefix else: # Install Python module in the default location extra = '' major = python_version[0] dummy = 'dummy' + major if localenv['PYTHON_INSTALLER'] == 'direct': install(localenv.Command, dummy, mod, build_cmd + ' install --record ../../build/python%s-installed-files.txt %s' % (major, extra)) elif localenv['PYTHON_INSTALLER'] == 'debian': install(localenv.Command, dummy, mod, build_cmd + ' install --install-layout=deb --no-compile %s' % extra) elif localenv['PYTHON_INSTALLER'] == 'binary': install(localenv.Command, dummy, mod, build_cmd + ' bdist_msi --dist-dir=../..' + ' --target-version=%s' % python_version) libDirs = ('../../build/lib', localenv['sundials_libdir'], localenv['boost_lib_dir']) localenv['py_cantera_libs'] = repr(localenv['cantera_libs']) localenv['py_libdirs'] = repr([x for x in libDirs if x]) # Compile the Python module with the same compiler as the rest of Cantera localenv['py_extra_compiler_args'] = repr([]) localenv['py_extra_link_args'] = repr([]) if localenv['OS'] == 'Windows': if env['CC'] == 'cl': flags = ['/EHsc'] if env['debug']: flags.extend(['/Zi', '/Fd_cantera.pdb']) localenv['py_extra_link_args'] = repr(['/DEBUG']) compilerOpt = ' --compiler=msvc' localenv['py_extra_compiler_args'] = repr(flags) elif env['CC'] == 'gcc': compilerOpt = ' --compiler=mingw32' else: compilerOpt = '' dataFiles = localenv.RecursiveInstall('#interfaces/cython/cantera/data', '#build/data') build(dataFiles) testFiles = localenv.RecursiveInstall('#interfaces/cython/cantera/test/data', '#test/data') build(testFiles) # Cython module for Python 3.x if localenv['python3_package'] == 'y': module_ext, py3_version = configure_numpy(localenv['python3_cmd']) make_setup = localenv.SubstFile('#interfaces/cython/setup3.py', '#interfaces/cython/setup.py.in') build(make_setup) build_base = ('cd interfaces/cython &&' ' $python3_cmd setup3.py %s' ' --build-lib=../../build/python3' ' --build-temp=../../build/temp-py3' + compilerOpt) build_cmd = build_base % 'build' ext = build(localenv.Command('#build/python3/cantera/_cantera%s' % module_ext, 'setup3.py', build_base % 'build_ext')) mod = build(localenv.Command('#build/python3/cantera/__init__.py', 'setup3.py', build_cmd)) env['python3_module'] = mod localenv.AddPreAction(ext, Delete('interfaces/cython/cantera/_cantera.cpp')) add_dependencies(mod, ext) install_module(localenv['python3_prefix'], py3_version) # Cython module for Python 2.x if localenv['python_package'] == 'new': module_ext, py2_version = configure_numpy(localenv['python_cmd']) make_setup = localenv.SubstFile('#interfaces/cython/setup2.py', '#interfaces/cython/setup.py.in') build(make_setup) build_base = ('cd interfaces/cython &&' ' $python_cmd setup2.py %s' ' --build-lib=../../build/python2' ' --build-temp=../../build/temp-py2' + compilerOpt) build_cmd = build_base % 'build' ext = build(localenv.Command('#build/python2/cantera/_cantera%s' % module_ext, 'setup2.py', build_base % 'build_ext')) mod = build(localenv.Command('#build/python2/cantera/__init__.py', 'setup2.py', build_cmd)) env['python2_module'] = mod localenv.AddPreAction(ext, Delete('interfaces/cython/cantera/_cantera.cpp')) # Use 3to2 to convert examples from Python 3 syntax if env['python_convert_examples']: def convert_example(target, source, env): shutil.copyfile(source[0].abspath, target[0].abspath) subprocess.call(['3to2', '--no-diff', '-n', '-w','-x', 'str', '-x', 'open', target[0].abspath]) for subdir in os.listdir('cantera/examples'): dirpath = pjoin('cantera', 'examples', subdir) if not os.path.isdir(dirpath): continue for filename in os.listdir(dirpath): if not filename.endswith('.py'): continue targetdir = '../../build/python2/cantera/examples' a = build(localenv.Command(pjoin(targetdir, subdir, filename), pjoin(dirpath, filename), convert_example)) localenv.Depends(a, mod) add_dependencies(mod, ext) install_module(localenv['python_prefix'], py2_version)