[SCons] Only build the Python package for Python 3.x

This commit is contained in:
Ray Speth 2018-09-09 22:19:34 -04:00
parent dcb7f34b4a
commit d6da006e3e
15 changed files with 294 additions and 565 deletions

View file

@ -65,10 +65,8 @@ if 'clean' in COMMAND_LINE_TARGETS:
removeDirectory('include/cantera/ext') removeDirectory('include/cantera/ext')
removeFile('interfaces/cython/cantera/_cantera.cpp') removeFile('interfaces/cython/cantera/_cantera.cpp')
removeFile('interfaces/cython/cantera/_cantera.h') removeFile('interfaces/cython/cantera/_cantera.h')
removeFile('interfaces/cython/setup2.py') removeFile('interfaces/cython/setup.py')
removeFile('interfaces/cython/setup3.py') removeFile('interfaces/python_minimal/setup.py')
removeFile('interfaces/python_minimal/setup2.py')
removeFile('interfaces/python_minimal/setup3.py')
removeFile('config.log') removeFile('config.log')
removeDirectory('doc/sphinx/matlab/examples') removeDirectory('doc/sphinx/matlab/examples')
removeFile('doc/sphinx/matlab/examples.rst') removeFile('doc/sphinx/matlab/examples.rst')
@ -348,7 +346,7 @@ config_options = [
sys.executable), sys.executable),
PathVariable( PathVariable(
'python_prefix', 'python_prefix',
"""Use this option if you want to install the Cantera Python 2 package to """Use this option if you want to install the Cantera Python package to
an alternate location. On Unix-like systems, the default is the same an alternate location. On Unix-like systems, the default is the same
as the 'prefix' option. If the 'python_prefix' option is set to as the 'prefix' option. If the 'python_prefix' option is set to
the empty string or the 'prefix' option is not set, then the package the empty string or the 'prefix' option is not set, then the package
@ -356,55 +354,22 @@ config_options = [
To install to the current user's 'site-packages' directory, use To install to the current user's 'site-packages' directory, use
'python_prefix=USER'.""", 'python_prefix=USER'.""",
defaults.python_prefix, PathVariable.PathAccept), defaults.python_prefix, PathVariable.PathAccept),
EnumVariable(
'python2_package',
"""Controls whether or not the Python 2 module will be built. By
default, the module will be built if the Python 2 interpreter
and the required dependencies (NumPy for Python 2 and Cython
for the version of Python for which SCons is installed) can be
found.""",
'default', ('full', 'minimal', 'y', 'n', 'none', 'default')),
PathVariable(
'python2_cmd',
"""The path to the Python 2 interpreter. The default is
'python2'; if this executable cannot be found, this
value must be specified to build the Python 2 module.""",
'python2', PathVariable.PathAccept),
PathVariable(
'python2_prefix',
"""Use this option if you want to install the Cantera Python 2 package to
an alternate location. On Unix-like systems, the default is the same
as the 'prefix' option. If the 'python_prefix' option is set to
the empty string or the 'prefix' option is not set, then the package
will be installed to the system default 'site-packages' directory.
To install to the current user's 'site-packages' directory, use
'python2_prefix=USER'.""",
defaults.python_prefix, PathVariable.PathAccept),
EnumVariable( EnumVariable(
'python3_package', 'python3_package',
"""Controls whether or not the Python 3 module will be built. By """Deprecated synonym for the 'python_package' option. Will be overridden
default, the module will be built if the Python 3 interpreter if 'python_package' is set.""",
and the required dependencies (NumPy for Python 3 and Cython
for the version of Python for which SCons is installed) can be
found.""",
'default', ('full', 'minimal', 'y', 'n', 'none', 'default')), 'default', ('full', 'minimal', 'y', 'n', 'none', 'default')),
PathVariable( PathVariable(
'python3_cmd', 'python3_cmd',
"""The path to the Python 3 interpreter. The default is """Deprecated synonym for the 'python_cmd' option. Will be overridden
'python3'; if this executable cannot be found, this if 'python_cmd' is set.""",
value must be specified to build the Python 3 module.""", sys.executable, PathVariable.PathAccept),
'python3', PathVariable.PathAccept),
PathVariable( PathVariable(
'python3_prefix', 'python3_prefix',
"""Use this option if you want to install the Cantera Python 3 package to """Deprecated synonym for the 'python_prefix' option. Will be overridden
an alternate location. On Unix-like systems, the default is the same if 'python_prefix' is set.""",
as the 'prefix' option. If the 'python_prefix' option is set to
the empty string or the 'prefix' option is not set, then the package
will be installed to the system default 'site-packages' directory.
To install to the current user's 'site-packages' directory, use
'python3_prefix=USER'.""",
defaults.python_prefix, PathVariable.PathAccept), defaults.python_prefix, PathVariable.PathAccept),
EnumVariable( EnumVariable(
'matlab_toolbox', 'matlab_toolbox',
"""This variable controls whether the MATLAB toolbox will be built. If """This variable controls whether the MATLAB toolbox will be built. If
set to 'y', you will also need to set the value of the 'matlab_path' set to 'y', you will also need to set the value of the 'matlab_path'
@ -1148,13 +1113,19 @@ env['python_cmd_esc'] = quoted(env['python_cmd'])
cython_min_version = LooseVersion('0.23') cython_min_version = LooseVersion('0.23')
numpy_min_test_version = LooseVersion('1.8.1') numpy_min_test_version = LooseVersion('1.8.1')
# If both python2_package and python3_package are set to something # Handle the version-specific Python package options
# other than the default ignore the python_package option python_options = (('package', 'default'),
if all([env['python{}_package'.format(p)] != 'default' for p in ['2', '3']]): ('cmd', sys.executable),
if env['python_package'] != 'default': ('prefix', defaults.python_prefix))
print("WARNING: Both version-specific pythonX_package options are set. Ignoring " for option, default in python_options:
"non-version specific python_package options") if env['python3_' + option] != default:
env['python_package'] = 'none' print("WARNING: Option 'python3_{0}' is deprecated."
" Use 'python_{0}' instead.".format(option))
if env['python_' + option] == default:
env['python_' + option] = env['python3_' + option]
else:
print("WARNING: Ignoring option 'python3_{0}'"
" because 'python_{0}' was also set.".format(option))
if env['python_package'] == 'new': if env['python_package'] == 'new':
print("WARNING: The 'new' option for the Python package is " print("WARNING: The 'new' option for the Python package is "
@ -1163,73 +1134,13 @@ if env['python_package'] == 'new':
env['python_package'] = 'full' # Allow 'new' as a synonym for 'full' env['python_package'] = 'full' # Allow 'new' as a synonym for 'full'
elif env['python_package'] == 'y': elif env['python_package'] == 'y':
env['python_package'] = 'full' # Allow 'y' as a synonym for 'full' env['python_package'] = 'full' # Allow 'y' as a synonym for 'full'
elif env['python_package'] in ['none', 'n']: elif env['python_package'] == 'n':
if env['python2_package'] == 'default': env['python_package'] = 'none' # Allow 'n' as a synonym for 'none'
env['python2_package'] = 'none'
if env['python3_package'] == 'default':
env['python3_package'] = 'none'
for py_pkg in ['python2_package', 'python3_package']: env['install_python_action'] = ''
if env[py_pkg] == 'y': env['python_module_loc'] = ''
env[py_pkg] = 'full' # Allow 'y' as a synonym for 'full'
elif env[py_pkg] == 'n':
env[py_pkg] = 'none' # Allow 'n' as a synonym for 'none'
if env['python_package'] in ('full', 'minimal', 'default'): if env['python_package'] in ('full', 'default'):
# If the non-specific python_package option is not none, check
# the version of the Python package we want to build using
# python_cmd
script = '\n'.join(["from __future__ import print_function",
"import sys",
"print('{v.major}.{v.minor}'.format(v=sys.version_info))"])
try:
env['python_version'] = getCommandOutput(env['python_cmd'], '-c', script)
except (OSError, subprocess.CalledProcessError) as err:
if env['python_package'] in ['full', 'minimal']:
print('ERROR: Problem checking for Python:')
print(err)
sys.exit(1)
else:
print('WARNING: Problem checking for Python:')
print(err)
print('Continuing with default parameters.')
else:
major = env['python_version'][0]
py_pkg = 'python{}_package'.format(major)
if env[py_pkg] != 'default':
if env['python_package'] != 'default':
# If python_package is default don't print a warning. If python_package has been
# set, warn the user that we're ignoring that option.
print("WARNING: The python{v}_package option has been set to {option}. All "
"non-version-specific Python options (including python_cmd) have been "
"ignored.".format(v=major, option=env[py_pkg]))
else: # pythonX_package is 'default'
# This dictionary has the default values for the Python related variables
default_py_vars = {'python{}_cmd': 'python{}'.format(major),
'python{}_prefix': '$prefix'}
env[py_pkg] = env['python_package']
# Check whether any Python related variables are different from the default
for key, value in default_py_vars.items():
if env[key.format(major)] != value:
print("WARNING: The value for {0} has been set and will be used instead "
"of {1}".format(key.format(major), key.format('')))
else:
env[key.format(major)] = env[key.format('')]
del env['python_version']
# Make sure everything gets converted to properly versioned variables by deleting
# these so they don't get used accidentally
del env['python_package']
del env['python_cmd']
del env['python_prefix']
require_python = any([env['python{}_package'.format(p)] == 'full' for p in ['2', '3']])
want_python = any([env['python{}_package'.format(p)] == 'default' for p in ['2', '3']])
if require_python or want_python:
# Check for Cython: # Check for Cython:
try: try:
import Cython import Cython
@ -1247,63 +1158,18 @@ if require_python or want_python:
have_cython = True have_cython = True
finally: finally:
if not have_cython: if not have_cython:
if require_python: if env['python_package'] == 'full':
print('ERROR: ' + message) print('ERROR: ' + message)
sys.exit(1) sys.exit(1)
elif want_python: elif env['python_package'] == 'default':
print('WARNING: ' + message) print('WARNING: ' + message)
for py_pkg in ['python{}_package'.format(p) for p in ['2', '3']]: env['python_package'] = 'minimal'
if env[py_pkg] == 'default':
env[py_pkg] = 'minimal-default'
else: else:
print('INFO: Using Cython version {0}.'.format(cython_version)) print('INFO: Using Cython version {0}.'.format(cython_version))
def configure_minimal_python(py_ver):
# Test to see if we can run Python if the minimal interface is to be built
warn_no_python = False
script = textwrap.dedent("""\
from __future__ import print_function
import sys
print('{v.major}.{v.minor}'.format(v=sys.version_info))
""")
try:
info = getCommandOutput(env['python{}_cmd'.format(py_ver)], '-c', script)
except OSError as err:
if env['VERBOSE']:
print('Error checking for Python {}:'.format(py_ver))
print(err)
warn_no_python = True
except subprocess.CalledProcessError as err:
if env['VERBOSE']:
print('Error checking for Python {}:'.format(py_ver))
print(err, err.output)
warn_no_python = True
else:
(env['python{}_version'.format(py_ver)],) = info.splitlines()[-1:]
if warn_no_python:
if 'default' in env['python{}_package'.format(py_ver)]:
print('WARNING: Not building the minimal Python {py_ver} package because the Python '
'{py_ver} interpreter {interp!r} could not be '
'found.'.format(py_ver=py_ver, interp=env['python{}_cmd'.format(py_ver)]))
env['python{}_package'.format(py_ver)] = 'none'
else:
print('ERROR: Could not execute the Python {py_ver} interpreter {interp!r}.'.format(
py_ver=py_ver, interp=env['python{}_cmd'.format(py_ver)]
))
sys.exit(1)
else:
print('INFO: Building the minimal Python package for Python {0}'.format(env['python{}_version'.format(py_ver)]))
env['python{}_package'.format(py_ver)] = 'minimal'
def configure_full_python(py_ver):
# Test to see if we can import numpy # Test to see if we can import numpy
warn_no_python = False warn_no_python = False
script = textwrap.dedent("""\ script = textwrap.dedent("""\
from __future__ import print_function
import sys import sys
print('{v.major}.{v.minor}'.format(v=sys.version_info)) print('{v.major}.{v.minor}'.format(v=sys.version_info))
try: try:
@ -1315,106 +1181,91 @@ def configure_full_python(py_ver):
""") """)
try: try:
info = getCommandOutput(env['python{}_cmd'.format(py_ver)], '-c', script).splitlines() info = getCommandOutput(env['python_cmd'], '-c', script).splitlines()
except OSError as err: except OSError as err:
if env['VERBOSE']: if env['VERBOSE']:
print('Error checking for Python {}:'.format(py_ver)) print('Error checking for Python:')
print(err) print(err)
warn_no_python = True warn_no_python = True
except subprocess.CalledProcessError as err: except subprocess.CalledProcessError as err:
if env['VERBOSE']: if env['VERBOSE']:
print('Error checking for Python {}:'.format(py_ver)) print('Error checking for Python:')
print(err, err.output) print(err, err.output)
warn_no_python = True warn_no_python = True
else: else:
env['python{}_version'.format(py_ver)] = info[0] env['python_version'] = info[0]
numpy_version = LooseVersion(info[1]) numpy_version = LooseVersion(info[1])
if len(info) > 2: if len(info) > 2:
print("WARNING: Unexpected output while checking Python & Numpy versions:") print("WARNING: Unexpected output while checking Python & Numpy versions:")
print('| ' + '\n|'.join(info[2:])) print('| ' + '\n|'.join(info[2:]))
if numpy_version == LooseVersion('0.0.0'): if numpy_version == LooseVersion('0.0.0'):
print("NumPy for Python {0} not found.".format(env['python{}_version'.format(py_ver)])) print("NumPy not found.")
warn_no_python = True warn_no_python = True
elif numpy_version < numpy_min_test_version: elif numpy_version < numpy_min_test_version:
print("WARNING: The installed version of Numpy for Python {0} is not tested and " print("WARNING: The installed version of Numpy is not tested and "
"support is not guaranteed. Found {1} but {2} or newer is preferred".format( "support is not guaranteed. Found {0} but {1} or newer is preferred".format(
env['python{}_version'.format(py_ver)], numpy_version, numpy_min_test_version)) numpy_version, numpy_min_test_version))
else: else:
print('INFO: Using NumPy version {0} for Python {1}.'.format( print('INFO: Using NumPy version {0}.'.format(numpy_version))
numpy_version, env['python{}_version'.format(py_ver)]))
if warn_no_python: if warn_no_python:
if env['python{}_package'.format(py_ver)] == 'default': if env['python_package'] == 'default':
print('WARNING: Not building the full Python {py_ver} package because the Python ' print('WARNING: Not building the full Python package because the Python '
'{py_ver} interpreter {interp!r} could not be found or a required dependency ' 'interpreter {!r} could not be found or a required dependency '
'(e.g. numpy) was not found.'.format(py_ver=py_ver, interp=env['python{}_cmd'.format(py_ver)])) '(e.g. numpy) was not found.'.format(env['python_cmd']))
env['python{}_package'.format(py_ver)] = 'minimal-default' env['python_package'] = 'minimal-default'
else: else:
print('ERROR: Could not execute the Python {py_ver} interpreter {interp!r} or a required ' print('ERROR: Could not execute the Python interpreter {!r} or a required '
'dependency (e.g. numpy) could not be found.'.format(py_ver=py_ver, interp=env['python{}_cmd'.format(py_ver)])) 'dependency (e.g. numpy) could not be found.'.format(env['python_cmd']))
sys.exit(1) sys.exit(1)
else: else:
print('INFO: Building the full Python package for Python {0}'.format(env['python{}_version'.format(py_ver)])) print('INFO: Building the full Python package for Python {0}'.format(env['python_version']))
env['python{}_package'.format(py_ver)] = 'full' env['python_package'] = 'full'
for py_ver in [2, 3]: if env['python_package'] in ('minimal', 'minimal-default'):
env['install_python{}_action'.format(py_ver)] = '' # Test to see if we can run Python if the minimal interface is to be built
if env['python{}_package'.format(py_ver)] in ['full', 'default']: warn_no_python = False
configure_full_python(py_ver)
elif env['python{}_package'.format(py_ver)] == 'minimal':
configure_minimal_python(py_ver)
env['python{}_module_loc'.format(py_ver)] = ''
else:
env['python{}_module_loc'.format(py_ver)] = ''
# If we're building the full Python interface for one version of Python,
# we probably don't want the minimal interface of the other version
if env['python2_package'] == 'minimal-default' and env['python3_package'] == 'full':
env['python2_package'] = 'none'
elif env['python3_package'] == 'minimal-default' and env['python2_package'] == 'full':
env['python3_package'] = 'none'
# 'minimal-default' means that something was wrong with Python or NumPy
# such that the full interface for that version of Python can't be built
# and the pythonX_package option wasn't supplied by the user. Check to see
# if the minimal package should be built
if env['python2_package'] == 'minimal-default':
configure_minimal_python(2)
if env['python3_package'] == 'minimal-default':
configure_minimal_python(3)
for py_ver in [2, 3]:
if env['python{}_package'.format(py_ver)] != 'none':
# The directory within the source tree which will contain the Python module
env['pythonpath_build{}'.format(py_ver)] = Dir('build/python{}'.format(py_ver)).abspath
if 'PYTHONPATH' in env['ENV']:
env['pythonpath_build{}'.format(py_ver)] += os.path.pathsep + env['ENV']['PYTHONPATH']
# Check for 3to2. See http://pypi.python.org/pypi/3to2
# Only needed for Python 2 package
if env['python2_package'] == 'full':
script = textwrap.dedent("""\ script = textwrap.dedent("""\
from lib3to2.main import main import sys
print(main('lib3to2.fixes', ['-l'])) print('{v.major}.{v.minor}'.format(v=sys.version_info))
""") """)
try: try:
ret = getCommandOutput(env['python2_cmd'], '-c', script) info = getCommandOutput(env['python_cmd'], '-c', script)
except (OSError, subprocess.CalledProcessError) as err: except OSError as err:
if env['VERBOSE']: if env['VERBOSE']:
print('Error checking for 3to2:') print('Error checking for Python:')
print(err) print(err)
ret = '' warn_no_python = True
if 'print' in ret: except subprocess.CalledProcessError as err:
env['python_convert_examples'] = True if env['VERBOSE']:
print('Error checking for Python:')
print(err, err.output)
warn_no_python = True
else: else:
env['python_convert_examples'] = False (env['python_version'],) = info.splitlines()[-1:]
print("WARNING: Couldn't find the 3to2 package. "
"Python 2 examples will not work correctly.") if warn_no_python:
else: if env['python_package'] == 'minimal-default':
env['python_convert_examples'] = False print('WARNING: Not building the minimal Python package because the Python '
'interpreter {!r} could not be found.'.format(env['python_cmd']))
env['python_package'] = 'none'
else:
print('ERROR: Could not execute the Python interpreter {!r}.'.format(env['python_cmd']))
sys.exit(1)
else:
print('INFO: Building the minimal Python package for Python {0}'.format(env['python_version']))
env['python_package'] = 'minimal'
if env['python_package'] != 'none':
# The directory within the source tree which will contain the Python module
env['pythonpath_build'] = Dir('build/python').abspath
if 'PYTHONPATH' in env['ENV']:
env['pythonpath_build'] += os.path.pathsep + env['ENV']['PYTHONPATH']
# Matlab Toolbox settings # Matlab Toolbox settings
if env['matlab_path'] != '' and env['matlab_toolbox'] == 'default': if env['matlab_path'] != '' and env['matlab_toolbox'] == 'default':
@ -1506,12 +1357,11 @@ addInstallActions = ('install' in COMMAND_LINE_TARGETS or
if env['stage_dir']: if env['stage_dir']:
instRoot = pjoin(os.getcwd(), env['stage_dir'], instRoot = pjoin(os.getcwd(), env['stage_dir'],
stripDrive(env['prefix']).strip('/\\')) stripDrive(env['prefix']).strip('/\\'))
for k in ('python2_prefix', 'python3_prefix'): if env['python_prefix']:
if env[k]: env['python_prefix'] = pjoin(os.getcwd(), env['stage_dir'],
env[k] = pjoin(os.getcwd(), env['stage_dir'], stripDrive(env['python_prefix']).strip('/\\'))
stripDrive(env[k]).strip('/\\')) else:
else: env['python_prefix'] = pjoin(os.getcwd(), env['stage_dir'])
env[k] = pjoin(os.getcwd(), env['stage_dir'])
else: else:
instRoot = env['prefix'] instRoot = env['prefix']
@ -1532,8 +1382,7 @@ if env['layout'] == 'debian':
env['libdirname'], 'cantera', 'matlab', 'toolbox') env['libdirname'], 'cantera', 'matlab', 'toolbox')
env['inst_python_bindir'] = pjoin(base, 'cantera-python', 'usr', 'bin') env['inst_python_bindir'] = pjoin(base, 'cantera-python', 'usr', 'bin')
env['python2_prefix'] = pjoin(base, 'cantera-python') env['python_prefix'] = pjoin(base, 'cantera-python3')
env['python3_prefix'] = pjoin(base, 'cantera-python3')
else: else:
env['inst_libdir'] = pjoin(instRoot, env['libdirname']) env['inst_libdir'] = pjoin(instRoot, env['libdirname'])
env['inst_bindir'] = pjoin(instRoot, 'bin') env['inst_bindir'] = pjoin(instRoot, 'bin')
@ -1720,10 +1569,9 @@ if env['f90_interface'] == 'y':
VariantDir('build/src', 'src', duplicate=0) VariantDir('build/src', 'src', duplicate=0)
SConscript('build/src/SConscript') SConscript('build/src/SConscript')
if env['python3_package'] == 'full' or env['python2_package'] == 'full': if env['python_package'] == 'full':
SConscript('interfaces/cython/SConscript') SConscript('interfaces/cython/SConscript')
elif env['python_package'] == 'minimal':
if env['python3_package'] == 'minimal' or env['python2_package'] == 'minimal':
SConscript('interfaces/python_minimal/SConscript') SConscript('interfaces/python_minimal/SConscript')
if env['CC'] != 'cl': if env['CC'] != 'cl':
@ -1794,17 +1642,11 @@ def postInstallMessage(target, source, env):
samples {ct_sampledir!s} samples {ct_sampledir!s}
data files {ct_datadir!s}""".format(**env_dict)) data files {ct_datadir!s}""".format(**env_dict))
if env['python2_package'] == 'full': if env['python_package'] == 'full':
env['python2_example_loc'] = pjoin(env['python2_module_loc'], 'cantera', 'examples') env['python_example_loc'] = pjoin(env['python_module_loc'], 'cantera', 'examples')
install_message += indent(textwrap.dedent(""" install_message += indent(textwrap.dedent("""
Python 2 package (cantera) {python2_module_loc!s} Python package (cantera) {python_module_loc!s}
Python 2 samples {python2_example_loc!s}""".format(**env_dict)), ' ') Python samples {python_example_loc!s}""".format(**env_dict)), ' ')
if env['python3_package'] == 'full':
env['python3_example_loc'] = pjoin(env['python3_module_loc'], 'cantera', 'examples')
install_message += indent(textwrap.dedent("""
Python 3 package (cantera) {python3_module_loc!s}
Python 3 samples {python3_example_loc!s}""".format(**env_dict)), ' ')
if env['matlab_toolbox'] == 'y': if env['matlab_toolbox'] == 'y':
env['matlab_sample_loc'] = pjoin(env['ct_sampledir'], 'matlab') env['matlab_sample_loc'] = pjoin(env['ct_sampledir'], 'matlab')
@ -1856,26 +1698,22 @@ def getParentDirs(path, top=True):
# Files installed by SCons # Files installed by SCons
allfiles = FindInstalledFiles() allfiles = FindInstalledFiles()
# Files installed by the Python installer(s) # Files installed by the Python installer
pyFiles = ['build/python2-installed-files.txt', if os.path.exists('build/python-installed-files.txt'):
'build/python3-installed-files.txt'] with open('build/python-installed-files.txt', 'r') as f:
file_list = f.readlines()
for filename in pyFiles: install_base = os.path.dirname(file_list[0].strip())
if os.path.exists(filename): if os.path.exists(install_base):
with open(filename, 'r') as f: not_listed_files = [s for s in os.listdir(install_base) if not any(s in j for j in file_list)]
file_list = f.readlines() for f in not_listed_files:
f = pjoin(install_base, f)
install_base = os.path.dirname(file_list[0].strip())
if os.path.exists(install_base):
not_listed_files = [s for s in os.listdir(install_base) if not any(s in j for j in file_list)]
for f in not_listed_files:
f = pjoin(install_base, f)
if not os.path.isdir(f) and os.path.exists(f):
allfiles.append(File(f))
for f in file_list:
f = f.strip()
if not os.path.isdir(f) and os.path.exists(f): if not os.path.isdir(f) and os.path.exists(f):
allfiles.append(File(f)) allfiles.append(File(f))
for f in file_list:
f = f.strip()
if not os.path.isdir(f) and os.path.exists(f):
allfiles.append(File(f))
# After removing files (which SCons keeps track of), # After removing files (which SCons keeps track of),
# remove any empty directories (which SCons doesn't track) # remove any empty directories (which SCons doesn't track)
@ -1928,7 +1766,7 @@ if any(target.startswith('test') for target in COMMAND_LINE_TARGETS):
env['testNames'] = [] env['testNames'] = []
env['test_results'] = env.Command('test_results', [], testResults.printReport) env['test_results'] = env.Command('test_results', [], testResults.printReport)
if env['python2_package'] == 'none' and env['python3_package'] == 'none': if env['python_package'] == 'none':
# copy scripts from the full Cython module # copy scripts from the full Cython module
test_py_int = env.Command('#build/python_minimal/cantera/__init__.py', test_py_int = env.Command('#build/python_minimal/cantera/__init__.py',
'#interfaces/python_minimal/cantera/__init__.py', '#interfaces/python_minimal/cantera/__init__.py',

View file

@ -16,10 +16,7 @@ import sys, os, re
# If extensions (or modules to document with autodoc) are in another directory, # If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the # add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here. # documentation root, use os.path.abspath to make it absolute, like shown here.
if sys.version_info[0] == 3: sys.path.insert(0, os.path.abspath('../../build/python'))
sys.path.insert(0, os.path.abspath('../../build/python3'))
else:
sys.path.insert(0, os.path.abspath('../../build/python2'))
sys.path.append(os.path.abspath('.')) sys.path.append(os.path.abspath('.'))
sys.path.append(os.path.abspath('./exts')) sys.path.append(os.path.abspath('./exts'))
@ -99,9 +96,6 @@ release = re.search('CANTERA_VERSION "(.*?)"', configh).group(1)
# List of patterns, relative to source directory, that match files and # List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files. # directories to ignore when looking for source files.
exclude_patterns = [] exclude_patterns = []
if sys.version_info[0] == 3:
exclude_patterns.append('python/*')
# The reST default role (used for this markup: `text`) to use for all documents. # The reST default role (used for this markup: `text`) to use for all documents.
default_role = 'py:obj' default_role = 'py:obj'

View file

@ -7,8 +7,7 @@ cantera/test/data/*.xml
cantera/test/data/*.inp cantera/test/data/*.inp
cantera/test/data/*.dat cantera/test/data/*.dat
cantera/test/data/*.csv cantera/test/data/*.csv
setup2.py setup.py
setup3.py
scripts/ctml_writer.py scripts/ctml_writer.py
scripts/ctml_writer scripts/ctml_writer
scripts/ck2cti.py scripts/ck2cti.py

View file

@ -6,54 +6,6 @@ Import('env', 'build', 'install')
localenv = env.Clone() localenv = env.Clone()
def configure_python(env, python_command):
script = '\n'.join(("from distutils.sysconfig import *",
"import numpy",
"print(get_config_var('EXT_SUFFIX') or get_config_var('SO'))",
"print(get_config_var('INCLUDEPY'))",
"print(get_config_var('LDLIBRARY'))",
"print(get_config_var('prefix'))",
"print(get_python_version())",
"print(numpy.get_include())"))
info = getCommandOutput(python_command, '-c', script)
module_ext, inc, pylib, prefix, py_version, numpy_include = info.splitlines()[-6:]
env.Prepend(CPPPATH=[Dir('#include'), inc, numpy_include])
env.Prepend(LIBS=env['cantera_libs'])
if env['OS'] == 'Darwin':
env.Append(LINKFLAGS='-undefined dynamic_lookup')
elif env['OS'] == 'Windows':
env.Append(LIBPATH=prefix+'/libs')
if env['toolchain'] == 'mingw':
env.Append(LIBS='python%s' % py_version.replace('.',''))
if env['OS_BITS'] == 64:
env.Append(CPPDEFINES='MS_WIN64')
# fix for http://bugs.python.org/issue11566
env.Append(CPPDEFINES={'_hypot':'hypot'})
elif env['OS'] == 'Cygwin':
# extract 'pythonX.Y' from 'libpythonX.Y.dll.a'
env.Append(LIBS=pylib[3:-6])
return module_ext, py_version
def add_dependencies(mod, ext):
localenv.Depends(mod, ext)
localenv.Depends(mod, dataFiles + testFiles)
localenv.Depends(ext, localenv['cantera_staticlib'])
for f in (mglob(localenv, 'cantera', 'py') +
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 cythonize(target, source, env): def cythonize(target, source, env):
Cython.Build.cythonize([f.abspath for f in source]) Cython.Build.cythonize([f.abspath for f in source])
@ -67,62 +19,6 @@ for line in open('cantera/_cantera.pxd'):
if m: if m:
localenv.Depends('cantera/_cantera.cpp', '#include/' + m.group(1)) localenv.Depends('cantera/_cantera.cpp', '#include/' + m.group(1))
def install_module(prefix, python_version):
major = python_version[0]
minor = python_version.split('.')[1]
dummy = 'dummy' + major
if prefix == 'USER':
# Install to the OS-dependent user site-packages directory
extra = '--user'
if localenv['OS'] == 'Darwin':
extra += ' --prefix=""'
elif prefix:
# A specific location for the Cantera python module has been given
if localenv['debian'] and localenv.subst(prefix) == '/usr/local':
# Installation to /usr/local is the default on Debian-based distributions
extra = ''
elif localenv['OS'] == 'Darwin':
extra = localenv.subst(' --prefix=${python%s_prefix}' % major)
elif localenv['libdirname'] == 'lib64':
# 64-bit RHEL / Fedora
extra = localenv.subst(
' --prefix=${python%s_prefix} --install-lib=${python%s_prefix}/lib64/python%s.%s/site-packages' % (major, major, major, minor))
else:
extra = '--user'
localenv.AppendENVPath(
'PYTHONUSERBASE',
normpath(localenv.subst('$python%s_prefix' % major)))
else:
# Install Python module in the default location
extra = ''
env['python%s_module_loc' % major] = '<unspecified>'
if localenv['PYTHON_INSTALLER'] == 'direct':
mod_inst = install(localenv.Command, dummy, mod,
build_cmd + ' install %s' % extra +
' --record=../../build/python%s-installed-files.txt' % major +
' --single-version-externally-managed')
global_env = env
def find_module_dir(target, source, env):
check = pjoin('cantera','__init__.py')
for filename in open('build/python%s-installed-files.txt' % major).readlines():
filename = filename.strip()
if filename.endswith(check):
filename = filename.replace(check,'')
global_env['python%s_module_loc' % major] = normpath(filename)
break
localenv.AlwaysBuild(localenv.AddPostAction(mod_inst, find_module_dir))
env['install_python{}_action'.format(major)] = mod_inst
elif localenv['PYTHON_INSTALLER'] == 'debian':
extra = localenv.subst(' --root=${python%s_prefix}' % major)
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)
dataFiles = localenv.RecursiveInstall('#interfaces/cython/cantera/data', dataFiles = localenv.RecursiveInstall('#interfaces/cython/cantera/data',
'#build/data') '#build/data')
build(dataFiles) build(dataFiles)
@ -135,64 +31,113 @@ for f in ['inputs/h2o2.inp', 'inputs/gri30.inp', 'transport/gri30_tran.dat']:
inp = build(localenv.Install('#interfaces/cython/cantera/test/data/', '#data/' + f)) inp = build(localenv.Install('#interfaces/cython/cantera/test/data/', '#data/' + f))
testFiles.append(inp) testFiles.append(inp)
# Cython module for Python 3.x # Get information needed to build the Python module
if localenv['python3_package'] == 'full': script = '\n'.join(("from distutils.sysconfig import *",
localenv['python3_cmd_esc'] = quoted(localenv['python3_cmd']) "import numpy",
py3env = localenv.Clone() "print(get_config_var('EXT_SUFFIX') or get_config_var('SO'))",
module_ext, py3_version = configure_python(py3env, py3env['python3_cmd']) "print(get_config_var('INCLUDEPY'))",
"print(get_config_var('LDLIBRARY'))",
"print(get_config_var('prefix'))",
"print(get_python_version())",
"print(numpy.get_include())"))
info = getCommandOutput(localenv['python_cmd'], '-c', script)
module_ext, inc, pylib, prefix, py_version, numpy_include = info.splitlines()[-6:]
localenv.Prepend(CPPPATH=[Dir('#include'), inc, numpy_include])
localenv.Prepend(LIBS=localenv['cantera_libs'])
if localenv['OS'] == 'Darwin':
localenv.Append(LINKFLAGS='-undefined dynamic_lookup')
elif localenv['OS'] == 'Windows':
localenv.Append(LIBPATH=prefix+'/libs')
if localenv['toolchain'] == 'mingw':
localenv.Append(LIBS='python{}'.format(py_version.replace('.','')))
if localenv['OS_BITS'] == 64:
localenv.Append(CPPDEFINES='MS_WIN64')
# fix for http://bugs.python.org/issue11566
localenv.Append(CPPDEFINES={'_hypot':'hypot'})
elif localenv['OS'] == 'Cygwin':
# extract 'pythonX.Y' from 'libpythonX.Y.dll.a'
localenv.Append(LIBS=pylib[3:-6])
obj = py3env.SharedObject('#build/temp-py/_cantera3', 'cantera/_cantera.cpp') # Build the Python module
ext = py3env.LoadableModule('#build/python3/cantera/_cantera%s' % module_ext, obj = localenv.SharedObject('#build/temp-py/_cantera', 'cantera/_cantera.cpp')
obj, LIBPREFIX='', SHLIBSUFFIX=module_ext, ext = localenv.LoadableModule('#build/python/cantera/_cantera{}'.format(module_ext),
SHLIBPREFIX='', LIBSUFFIXES=[module_ext]) obj, LIBPREFIX='', SHLIBSUFFIX=module_ext,
py3env['py_extension'] = ext[0].name SHLIBPREFIX='', LIBSUFFIXES=[module_ext])
localenv['py_extension'] = ext[0].name
py3env.SubstFile('setup3.py', 'setup.py.in') localenv.SubstFile('setup.py', 'setup.py.in')
build_cmd = ('cd interfaces/cython &&' build_cmd = ('cd interfaces/cython &&'
' $python3_cmd_esc setup3.py build --build-lib=../../build/python3') ' $python_cmd_esc setup.py build --build-lib=../../build/python')
mod = build(py3env.Command('#build/python3/cantera/__init__.py', 'setup3.py', mod = build(localenv.Command('#build/python/cantera/__init__.py', 'setup.py',
build_cmd)) build_cmd))
env['python3_module'] = mod env['python_module'] = mod
env['python3_extension'] = ext env['python_extension'] = ext
add_dependencies(mod, ext) localenv.Depends(mod, ext)
install_module(py3env['python3_prefix'], py3_version) localenv.Depends(mod, dataFiles + testFiles)
localenv.Depends(ext, localenv['cantera_staticlib'])
# Cython module for Python 2.x for f in (mglob(localenv, 'cantera', 'py') +
if localenv['python2_package'] == 'full': mglob(localenv, 'cantera/test', 'py') +
localenv['python2_cmd_esc'] = quoted(localenv['python2_cmd']) mglob(localenv, 'cantera/examples/tutorial', 'py') +
py2env = localenv.Clone() mglob(localenv, 'cantera/examples/equilibrium', 'py') +
module_ext, py2_version = configure_python(py2env, py2env['python2_cmd']) 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)
obj = py2env.SharedObject('#build/temp-py/_cantera2', 'cantera/_cantera.cpp') # Determine installation path and install the Python module
ext = py2env.LoadableModule('#build/python2/cantera/_cantera%s' % module_ext, if localenv['python_prefix'] == 'USER':
obj, LIBPREFIX='', SHLIBSUFFIX=module_ext, # Install to the OS-dependent user site-packages directory
SHLIBPREFIX='', LIBSUFFIXES=[module_ext]) extra = '--user'
py2env['py_extension'] = ext[0].name if localenv['OS'] == 'Darwin':
py2env.SubstFile('setup2.py', 'setup.py.in') extra += ' --prefix=""'
build_cmd = ('cd interfaces/cython &&' elif localenv['python_prefix']:
' $python2_cmd_esc setup2.py build --build-lib=../../build/python2') # A specific location for the Cantera python module has been given
mod = build(py2env.Command('#build/python2/cantera/__init__.py', if localenv['debian'] and localenv.subst('${python_prefix}') == '/usr/local':
'setup2.py', # Installation to /usr/local is the default on Debian-based distributions
build_cmd)) extra = ''
env['python2_module'] = mod elif localenv['OS'] == 'Darwin':
env['python2_extension'] = ext extra = localenv.subst(' --prefix=${python_prefix}')
elif localenv['libdirname'] == 'lib64':
# 64-bit RHEL / Fedora
extra = localenv.subst(
' --prefix=${python_prefix}'
' --install-lib=${python_prefix}/lib64/python{}/site-packages'.format(py_version))
else:
extra = '--user'
localenv.AppendENVPath(
'PYTHONUSERBASE',
normpath(localenv.subst('$python_prefix')))
else:
# Install Python module in the default location
extra = ''
# Use 3to2 to convert examples from Python 3 syntax env['python_module_loc'] = '<unspecified>'
if env['python_convert_examples']: if localenv['PYTHON_INSTALLER'] == 'direct':
a = build(py2env.Command('#build/python2/cantera/examples', 'cantera/examples', mod_inst = install(localenv.Command, 'dummy', mod,
Copy("$TARGET", "$SOURCE"))) build_cmd + ' install ' + extra +
# In these next few things, the double quotes are necessary ' --record=../../build/python-installed-files.txt' +
# so the command line is processed properly ' --single-version-externally-managed')
threetotwo_options = ['--no-diff', '-n', '-w', '-x', 'str', '-x', 'print', '-x', 'open', global_env = env
'-f', 'all', '-f', 'printfunction'] def find_module_dir(target, source, env):
threetotwo_options = ', '.join(["'{}'"]*len(threetotwo_options)).format(*threetotwo_options) check = pjoin('cantera', '__init__.py')
ex_loc = "'build/python2/cantera/examples'" for filename in open('build/python-installed-files.txt').readlines():
convert_script = textwrap.dedent("""\ filename = filename.strip()
$python2_cmd_esc -c "from lib3to2.main import main; main('lib3to2.fixes', [{opts}, {loc}])" if filename.endswith(check):
""".format(opts=threetotwo_options, loc=ex_loc)) filename = filename.replace(check, '')
b = build(py2env.AddPostAction(a, convert_script)) global_env['python_module_loc'] = normpath(filename)
py2env.Depends(mod, b) break
localenv.AlwaysBuild(localenv.AddPostAction(mod_inst, find_module_dir))
add_dependencies(mod, ext) env['install_python_action'] = mod_inst
install_module(py2env['python2_prefix'], py2_version) elif localenv['PYTHON_INSTALLER'] == 'debian':
extra = localenv.subst(' --root=${python_prefix}')
install(localenv.Command, 'dummy', mod,
build_cmd + ' install --install-layout=deb --no-compile ' + extra)
elif localenv['PYTHON_INSTALLER'] == 'binary':
install(localenv.Command, 'dummy', mod,
build_cmd + ' bdist_msi --dist-dir=../..' +
' --target-version=' + py_version)

View file

@ -375,7 +375,7 @@ class TestFreeFlame(utilities.CanteraTest):
self.create_sim(p, Tin, reactants) self.create_sim(p, Tin, reactants)
self.solve_fixed_T() self.solve_fixed_T()
filename = pjoin(self.test_work_dir, 'onedim-fixed-T{0}.xml'.format(utilities.python_version)) filename = pjoin(self.test_work_dir, 'onedim-fixed-T.xml')
if os.path.exists(filename): if os.path.exists(filename):
os.remove(filename) os.remove(filename)
@ -436,7 +436,7 @@ class TestFreeFlame(utilities.CanteraTest):
p = 2 * ct.one_atm p = 2 * ct.one_atm
Tin = 400 Tin = 400
filename = pjoin(self.test_work_dir, 'onedim-add-species{0}.xml'.format(utilities.python_version)) filename = pjoin(self.test_work_dir, 'onedim-add-species.xml')
if os.path.exists(filename): if os.path.exists(filename):
os.remove(filename) os.remove(filename)
@ -464,7 +464,7 @@ class TestFreeFlame(utilities.CanteraTest):
p = 2 * ct.one_atm p = 2 * ct.one_atm
Tin = 400 Tin = 400
filename = pjoin(self.test_work_dir, 'onedim-add-species{0}.xml'.format(utilities.python_version)) filename = pjoin(self.test_work_dir, 'onedim-add-species.xml')
if os.path.exists(filename): if os.path.exists(filename):
os.remove(filename) os.remove(filename)
@ -488,7 +488,7 @@ class TestFreeFlame(utilities.CanteraTest):
self.assertArrayNear(Y1[k1], Y2[k2]) self.assertArrayNear(Y1[k1], Y2[k2])
def test_write_csv(self): def test_write_csv(self):
filename = pjoin(self.test_work_dir, 'onedim-write_csv{0}.csv'.format(utilities.python_version)) filename = pjoin(self.test_work_dir, 'onedim-write_csv.csv')
if os.path.exists(filename): if os.path.exists(filename):
os.remove(filename) os.remove(filename)
@ -551,7 +551,7 @@ class TestFreeFlame(utilities.CanteraTest):
class TestDiffusionFlame(utilities.CanteraTest): class TestDiffusionFlame(utilities.CanteraTest):
# Note: to re-create the reference file: # Note: to re-create the reference file:
# (1) set PYTHONPATH to build/python2 or build/python3. # (1) set PYTHONPATH to build/python.
# (2) Start Python in the test/work directory and run: # (2) Start Python in the test/work directory and run:
# >>> import cantera.test # >>> import cantera.test
# >>> t = cantera.test.test_onedim.TestDiffusionFlame("test_mixture_averaged") # >>> t = cantera.test.test_onedim.TestDiffusionFlame("test_mixture_averaged")
@ -753,7 +753,7 @@ class TestDiffusionFlame(utilities.CanteraTest):
class TestCounterflowPremixedFlame(utilities.CanteraTest): class TestCounterflowPremixedFlame(utilities.CanteraTest):
# Note: to re-create the reference file: # Note: to re-create the reference file:
# (1) set PYTHONPATH to build/python2 or build/python3. # (1) set PYTHONPATH to build/python.
# (2) Start Python in the test/work directory and run: # (2) Start Python in the test/work directory and run:
# >>> import cantera.test # >>> import cantera.test
# >>> t = cantera.test.test_onedim.TestCounterflowPremixedFlame("test_mixture_averaged") # >>> t = cantera.test.test_onedim.TestCounterflowPremixedFlame("test_mixture_averaged")

View file

@ -1455,7 +1455,7 @@ class TestSolutionArray(utilities.CanteraTest):
states.TPX = np.linspace(300, 1000, 7), 2e5, 'H2:0.5, O2:0.4' states.TPX = np.linspace(300, 1000, 7), 2e5, 'H2:0.5, O2:0.4'
states.equilibrate('HP') states.equilibrate('HP')
outfile = pjoin(self.test_work_dir, 'solutionarray{}.csv'.format(utilities.python_version)) outfile = pjoin(self.test_work_dir, 'solutionarray.csv')
states.write_csv(outfile) states.write_csv(outfile)
data = np.genfromtxt(outfile, names=True, delimiter=',') data = np.genfromtxt(outfile, names=True, delimiter=',')

View file

@ -30,8 +30,7 @@ class CanteraTest(unittest.TestCase):
root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),
'..', '..', '..', '..')) '..', '..', '..', '..'))
if os.path.exists(os.path.join(root_dir, 'SConstruct')): if os.path.exists(os.path.join(root_dir, 'SConstruct')):
cls.test_work_dir = os.path.join(root_dir, 'test', 'work', cls.test_work_dir = os.path.join(root_dir, 'test', 'work', 'python')
'python{}'.format(python_version))
try: try:
os.makedirs(cls.test_work_dir) os.makedirs(cls.test_work_dir)
except OSError as e: except OSError as e:

View file

@ -37,7 +37,7 @@ end
% Set path to Python module % Set path to Python module
if strcmp(getenv('PYTHONPATH'), '') if strcmp(getenv('PYTHONPATH'), '')
setenv('PYTHONPATH', fullfile(cantera_root, 'build', 'python2')) setenv('PYTHONPATH', fullfile(cantera_root, 'build', 'python'))
end end
% A simple test to make sure that the ctmethods.mex file is present and working % A simple test to make sure that the ctmethods.mex file is present and working

View file

@ -5,58 +5,53 @@ Import('env', 'build', 'install')
localenv = env.Clone() localenv = env.Clone()
for py_ver in [2, 3]: make_setup = build(localenv.SubstFile('setup.py', 'setup.py.in'))
if env['python{}_package'.format(py_ver)] == 'minimal':
make_setup = build(localenv.SubstFile('setup{}.py'.format(py_ver), 'setup.py.in'))
# copy scripts from the full Cython module # copy scripts from the full Cython module
for script in ['ctml_writer', 'ck2cti']: for script in ['ctml_writer', 'ck2cti']:
# The actual script # The actual script
s = build(env.Command('cantera/%s.py' % script, s = build(env.Command('cantera/{}.py'.format(script),
'#interfaces/cython/cantera/%s.py' % script, '#interfaces/cython/cantera/{}.py'.format(script),
Copy('$TARGET', '$SOURCE'))) Copy('$TARGET', '$SOURCE')))
localenv.Depends(make_setup, s) localenv.Depends(make_setup, s)
localenv['python{}_cmd_esc'.format(py_ver)] = quoted(localenv['python{}_cmd'.format(py_ver)]) build_cmd = ('cd interfaces/python_minimal &&'
build_cmd = ('cd interfaces/python_minimal &&' ' $python_cmd_esc setup.py build --build-lib=../../build/python')
' $python{py_ver}_cmd_esc setup{py_ver}.py build --build-lib=../../build/python{py_ver}'.format(py_ver=py_ver))
mod = build(localenv.Command('#build/python{}/cantera/__init__.py'.format(py_ver), mod = build(localenv.Command('#build/python/cantera/__init__.py', 'setup.py',
'setup{}.py'.format(py_ver), build_cmd))
build_cmd)) env['python_module'] = mod
env['python{}_module'.format(py_ver)] = mod
if localenv['PYTHON_INSTALLER'] == 'direct': if localenv['PYTHON_INSTALLER'] == 'direct':
if localenv['python{}_prefix'.format(py_ver)] == 'USER': if localenv['python_prefix'] == 'USER':
# Install to the OS-dependent user site-packages directory # Install to the OS-dependent user site-packages directory
extra = '--user' extra = '--user'
if localenv['OS'] == 'Darwin': if localenv['OS'] == 'Darwin':
extra += ' --prefix=""' extra += ' --prefix=""'
elif localenv['python{}_prefix'.format(py_ver)]: elif localenv['python_prefix']:
# A specific location for the Cantera python module has been given # A specific location for the Cantera python module has been given
extra = '--user' extra = '--user'
if localenv['OS'] == 'Darwin': if localenv['OS'] == 'Darwin':
extra += ' --prefix=""' extra += ' --prefix=""'
localenv.AppendENVPath( localenv.AppendENVPath(
'PYTHONUSERBASE', 'PYTHONUSERBASE',
normpath(localenv.subst('$python{}_prefix'.format(py_ver))) normpath(localenv.subst('$python_prefix'))
) )
else: else:
# Install Python module in the default location # Install Python module in the default location
extra = '' extra = ''
mod_inst = install(localenv.Command, 'dummy{}'.format(py_ver), mod, mod_inst = install(localenv.Command, 'dummy', mod,
build_cmd + ' install %s' % extra + build_cmd + ' install ' + extra +
' --record=../../build/python{}-installed-files.txt'.format(py_ver) + ' --record=../../build/python-installed-files.txt' +
' --single-version-externally-managed') ' --single-version-externally-managed')
global_env = env global_env = env
def find_module_dir(target, source, env): def find_module_dir(target, source, env):
check = pjoin('cantera', '__init__.py') check = pjoin('cantera', '__init__.py')
py_ver = str(source[0]).split('/')[1][-1] for filename in open('build/python-installed-files.txt').readlines():
for filename in open('build/python{}-installed-files.txt'.format(py_ver)).readlines(): filename = filename.strip()
filename = filename.strip() if filename.endswith(check):
if filename.endswith(check): filename = filename.replace(check, '')
filename = filename.replace(check, '') global_env['python_module_loc'] = normpath(filename)
global_env['python{}_module_loc'.format(py_ver)] = normpath(filename) break
break localenv.AlwaysBuild(localenv.AddPostAction(mod_inst, find_module_dir))
localenv.AlwaysBuild(localenv.AddPostAction(mod_inst, find_module_dir)) env['install_python_action'] = mod_inst
env['install_python{}_action'.format(py_ver)] = mod_inst

View file

@ -11,31 +11,19 @@ if env['INSTALL_MANPAGES']:
### Generate customized scripts ### ### Generate customized scripts ###
# If any Python 3 package is built, prefer that one. If not,
# and if any Python 2 package is built, prefer that one.
# In all other cases, use the Python 3 location variables,
# which should all be empty strings
if env['python3_package'] in ['full', 'minimal']:
major = '3'
elif env['python2_package'] in ['full', 'minimal']:
major = '2'
else:
major = '3'
# 'setup_cantera' # 'setup_cantera'
if localenv['layout'] != 'debian' and env['OS'] != 'Windows': if localenv['layout'] != 'debian' and env['OS'] != 'Windows':
def copy_var(target, source, env): def copy_var(target, source, env):
if env['python{}_prefix'.format(major)] == 'USER': if env['python_prefix'] == 'USER':
env['python_module_loc_sc'] = '' env['python_module_loc_sc'] = ''
else: else:
env['python_module_loc_sc'] = env['python{}_module_loc'.format(major)] env['python_module_loc_sc'] = env['python_module_loc']
env['python_cmd'] = env['python{}_cmd'.format(major)]
for script in ['setup_cantera', 'setup_cantera.csh']: for script in ['setup_cantera', 'setup_cantera.csh']:
target = env.SubstFile(script, script + '.in') target = env.SubstFile(script, script + '.in')
localenv.AddPreAction(target, copy_var) localenv.AddPreAction(target, copy_var)
localenv.Depends(target, env['install_python{}_action'.format(major)]) localenv.Depends(target, env['install_python_action'])
install('$inst_bindir', target) install('$inst_bindir', target)
# Cantera.mak include file for Makefile projects # Cantera.mak include file for Makefile projects

View file

@ -4,7 +4,6 @@
Collect test coverage data and generate an html report. Collect test coverage data and generate an html report.
""" """
from __future__ import print_function
import os import os
import subprocess import subprocess
import shutil import shutil

View file

@ -80,28 +80,16 @@ env['matlab_extension'] = ctmethods
# 'ctpath.m' # 'ctpath.m'
globalenv = env globalenv = env
# If any Python 3 package is built, prefer that one. If not,
# and if any Python 2 package is built, prefer that one.
# In all other cases, use the Python 3 location variables,
# which should all be empty strings
if env['python3_package'] in ['full', 'minimal']:
major = '3'
elif env['python2_package'] in ['full', 'minimal']:
major = '2'
else:
major = '3'
def copy_var(target, source, env): def copy_var(target, source, env):
if env['python{}_prefix'.format(major)] == 'USER': if env['python_prefix'] == 'USER':
env['python_module_loc_sc'] = '' env['python_module_loc_sc'] = ''
else: else:
env['python_module_loc_sc'] = globalenv['python{}_module_loc'.format(major)] env['python_module_loc_sc'] = globalenv['python_module_loc']
env['python_cmd'] = env['python{}_cmd'.format(major)]
target = localenv.SubstFile('#interfaces/matlab/ctpath.m', target = localenv.SubstFile('#interfaces/matlab/ctpath.m',
'#interfaces/matlab/ctpath.m.in') '#interfaces/matlab/ctpath.m.in')
localenv.AddPreAction(target, copy_var) localenv.AddPreAction(target, copy_var)
localenv.Depends(target, env['install_python{}_action'.format(major)]) localenv.Depends(target, env['install_python_action'])
install('$inst_matlab_dir', target) install('$inst_matlab_dir', target)
# 'Contents.m' # 'Contents.m'

View file

@ -238,12 +238,9 @@ def addMatlabTest(script, testName, dependencies=None, env_vars=()):
return run_program return run_program
if localenv['python2_package'] in ('full', 'minimal'): if localenv['python_package'] in ('full', 'minimal'):
python_env_vars = {'PYTHONPATH': localenv['pythonpath_build2'], python_env_vars = {'PYTHONPATH': localenv['pythonpath_build'],
'PYTHON_CMD': localenv.subst('$python2_cmd')} 'PYTHON_CMD': localenv.subst('$python_cmd')}
elif localenv['python3_package'] in ('full', 'minimal'):
python_env_vars = {'PYTHONPATH': localenv['pythonpath_build3'],
'PYTHON_CMD': localenv.subst('$python3_cmd')}
else: else:
python_env_vars = {'PYTHONPATH': '../../build/python_minimal', python_env_vars = {'PYTHONPATH': '../../build/python_minimal',
'PYTHON_CMD': localenv.subst('$python_cmd')} 'PYTHON_CMD': localenv.subst('$python_cmd')}
@ -261,31 +258,24 @@ test_root = '#interfaces/cython/cantera/test'
for f in mglob(localenv, test_root, '^test_*.py'): for f in mglob(localenv, test_root, '^test_*.py'):
python_subtests.append(f.name[5:-3]) python_subtests.append(f.name[5:-3])
def make_python_tests(version): if localenv['python_package'] == 'full':
# Create test aliases for individual test modules (e.g. test-python2-thermo; # Create test aliases for individual test modules (e.g. test-python-thermo;
# not run as part of the main suite) and a single test runner with all the # not run as part of the main suite) and a single test runner with all the
# tests (test-python2) for the main suite. # tests (test-python) for the main suite.
for subset in python_subtests: for subset in python_subtests:
name = 'python%i-' %version + subset if subset else 'python%i' % version name = 'python-' + subset if subset else 'python'
pyTest = addPythonTest( pyTest = addPythonTest(
name, 'python', 'runCythonTests.py', name, 'python', 'runCythonTests.py',
args=subset, args=subset,
interpreter='$python{}_cmd'.format(version), interpreter='$python_cmd',
outfile=File('#test/work/python%d-results.txt' % version).abspath, outfile=File('#test/work/python-results.txt').abspath,
dependencies=(localenv['python%i_module' % version] + dependencies=(localenv['python_module'] + localenv['python_extension'] +
localenv['python%i_extension' % version] +
mglob(localenv, test_root, 'py')), mglob(localenv, test_root, 'py')),
env_vars={'PYTHONPATH': localenv['pythonpath_build%s' % version]}, env_vars={'PYTHONPATH': localenv['pythonpath_build']},
optional=bool(subset)) optional=bool(subset))
localenv.Alias('test-' + name, pyTest) localenv.Alias('test-' + name, pyTest)
env['testNames'].append(name) env['testNames'].append(name)
if localenv['python2_package'] == 'full':
make_python_tests(2)
if localenv['python3_package'] == 'full':
make_python_tests(3)
if localenv['matlab_toolbox'] == 'y': if localenv['matlab_toolbox'] == 'y':
matlabTest = addMatlabTest('runCanteraTests.m', 'matlab', matlabTest = addMatlabTest('runCanteraTests.m', 'matlab',
dependencies=mglob(localenv, 'matlab', 'm'), dependencies=mglob(localenv, 'matlab', 'm'),

View file

@ -17,7 +17,6 @@ a single test:
python runCythonTests.py onedim.TestDiffusionFlame.test_mixture_averaged python runCythonTests.py onedim.TestDiffusionFlame.test_mixture_averaged
""" """
from __future__ import print_function
import sys import sys
import os import os
@ -25,8 +24,7 @@ import warnings
warnings.simplefilter('default') warnings.simplefilter('default')
cantera_root = os.path.relpath(__file__).split(os.sep)[:-1] + ['..', '..'] cantera_root = os.path.relpath(__file__).split(os.sep)[:-1] + ['..', '..']
py_version = 'python3' if sys.version_info[0] == 3 else 'python2' module_path = os.path.abspath(os.sep.join(cantera_root + ['build']))
module_path = os.path.abspath(os.sep.join(cantera_root + ['build', py_version]))
if 'PYTHONPATH' in os.environ: if 'PYTHONPATH' in os.environ:
os.environ['PYTHONPATH'] = module_path + os.path.pathsep + os.environ['PYTHONPATH'] os.environ['PYTHONPATH'] = module_path + os.path.pathsep + os.environ['PYTHONPATH']
@ -45,7 +43,7 @@ cantera.make_deprecation_warnings_fatal()
class TestResult(unittest.TextTestResult): class TestResult(unittest.TextTestResult):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
unittest.TextTestResult.__init__(self, *args, **kwargs) unittest.TextTestResult.__init__(self, *args, **kwargs)
self.outName = 'python%d-results.txt' % sys.version_info[0] self.outName = 'python-results.txt'
with open(self.outName, 'w') as f: with open(self.outName, 'w') as f:
pass # just create an empty output file pass # just create an empty output file

View file

@ -19,13 +19,9 @@ if localenv['OS'] == 'Linux':
else: else:
cantera_libs = localenv['cantera_libs'] cantera_libs = localenv['cantera_libs']
if localenv['python2_package'] in ('full', 'minimal'): if localenv['python_package'] in ('full', 'minimal'):
localenv['ENV']['PYTHONPATH'] = localenv['pythonpath_build2'] localenv['ENV']['PYTHONPATH'] = localenv['pythonpath_build']
localenv['ENV']['PYTHON_CMD'] = localenv.subst('$python2_cmd') localenv['ENV']['PYTHON_CMD'] = localenv.subst('$python_cmd')
haveConverters = True
elif localenv['python3_package'] in ('full', 'minimal'):
localenv['ENV']['PYTHONPATH'] = localenv['pythonpath_build3']
localenv['ENV']['PYTHON_CMD'] = localenv.subst('$python3_cmd')
haveConverters = True haveConverters = True
else: else:
localenv['ENV']['PYTHONPATH'] = '../../build/python_minimal' localenv['ENV']['PYTHONPATH'] = '../../build/python_minimal'