From b979cea3d2889e274775adf8b234f90afec3b37c Mon Sep 17 00:00:00 2001 From: "Bryan W. Weber" Date: Sun, 2 Aug 2015 14:08:55 -0400 Subject: [PATCH] Switch Cython and python interfaces to setuptools Replace distutils with setuptools in the Cython and python_minimal interfaces. Add console_scripts option to generate OS specific scripts to run ck2cti, mixmaster, and ctml_writer Remove script files that are obsoleted by console_scripts from setuptools. Remove installation of the script modules from SConstruct. Fix Python installers so that when a prefix directory is specified on the command line, setuptools doesn't throw an error. The setuptools documentation at [1] prefers setting PYTHONUSERBASE rather than PYTHONPATH. Use normpath to avoid bugs in setuptools on Windows [2]. Specify an empty "--prefix" if the compiler is clang to fix a bug with Homebrew Python on Mac OSX [3]. [1]: https://pythonhosted.org/setuptools/easy_install.html#custom-installation-locations [2]: http://stackoverflow.com/q/31629398 [3]: https://github.com/Homebrew/homebrew-python/issues/187 --- SConstruct | 9 ----- interfaces/cython/SConscript | 44 +++++++++------------ interfaces/cython/scripts/ck2cti.py.in | 5 --- interfaces/cython/scripts/ctml_writer.py.in | 8 ---- interfaces/cython/scripts/mixmaster.py.in | 4 -- interfaces/cython/setup.py.in | 12 ++++-- interfaces/python_minimal/SConscript | 33 ++++++++-------- interfaces/python_minimal/setup.py.in | 11 ++++-- site_scons/buildutils.py | 1 + 9 files changed, 52 insertions(+), 75 deletions(-) delete mode 100644 interfaces/cython/scripts/ck2cti.py.in delete mode 100644 interfaces/cython/scripts/ctml_writer.py.in delete mode 100644 interfaces/cython/scripts/mixmaster.py.in diff --git a/SConstruct b/SConstruct index 59b5f5041..b1b0f24f3 100644 --- a/SConstruct +++ b/SConstruct @@ -1348,15 +1348,6 @@ if addInstallActions: # Data files install('$inst_datadir', mglob(env, 'build/data', 'cti', 'xml')) - # Converter scripts - pyExt = '.py' if env['OS'] == 'Windows' else '' - install(env.InstallAs, - '$inst_bindir/ck2cti%s' % pyExt, - 'interfaces/cython/cantera/ck2cti.py') - install(env.InstallAs, - '$inst_bindir/ctml_writer%s' % pyExt, - 'interfaces/cython/cantera/ctml_writer.py') - # Copy external libaries for Windows installations if env['CC'] == 'cl' and env['use_boost_libs']: boost_suffix = '-vc%s-mt-%s.lib' % (env['MSVC_VERSION'].replace('.',''), diff --git a/interfaces/cython/SConscript b/interfaces/cython/SConscript index a32ec24fd..6b5a34a39 100644 --- a/interfaces/cython/SConscript +++ b/interfaces/cython/SConscript @@ -36,7 +36,7 @@ def configure_python(env, python_command): def add_dependencies(mod, ext): localenv.Depends(mod, ext) - localenv.Depends(mod, dataFiles + testFiles + scripts) + localenv.Depends(mod, dataFiles + testFiles) localenv.Depends(ext, localenv['cantera_staticlib']) for f in (mglob(localenv, 'cantera', 'py') + @@ -67,37 +67,33 @@ for line in open('cantera/_cantera.pxd'): if m: localenv.Depends('cantera/_cantera.cpp', '#include/' + m.group(1)) -script_ext = '.py' if os.name == 'nt' else '' -localenv['py_ctml_writer'] = repr('scripts/ctml_writer%s' % script_ext) -localenv['py_ck2cti'] = repr('scripts/ck2cti%s' % script_ext) -localenv['py_mixmaster'] = repr('scripts/mixmaster%s' % script_ext) - -# thin wrappers -scripts = [] -for script in mglob(env, 'scripts', 'py.in'): - base_name = script.name.split('.')[0] - script = build(env.Command('scripts/%s%s' % (base_name, script_ext), script, - Copy('$TARGET', '$SOURCE'))) - scripts.append(script) - def install_module(prefix, python_version): + major = python_version[0] + ver = '3' if major == '3' else '' + 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 specified - extra = '--prefix="%s"' % prefix + # A specific location for the Cantera python module has been given + extra = '--user' + if localenv['OS'] == 'Darwin': + extra += ' --prefix=""' + localenv.AppendENVPath( + 'PYTHONUSERBASE', + normpath(localenv.subst('$python%s_prefix' % ver)) + ) else: # Install Python module in the default location extra = '' - major = python_version[0] - ver = '3' if major == '3' else '' - dummy = 'dummy' + major 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) + ' --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') @@ -105,7 +101,7 @@ def install_module(prefix, python_version): filename = filename.strip() if filename.endswith(check): filename = filename.replace(check,'') - global_env['python%s_module_loc' % ver] = os.path.normpath(filename) + global_env['python%s_module_loc' % ver] = normpath(filename) break localenv.AlwaysBuild(localenv.AddPostAction(mod_inst, find_module_dir)) if not ver: @@ -142,8 +138,7 @@ if localenv['python3_package'] == 'y': py3env.SubstFile('setup3.py', 'setup.py.in') build_cmd = ('cd interfaces/cython &&' - ' $python3_cmd setup3.py build --build-lib=../../build/python3' - ' --executable="/usr/bin/env python3"') + ' $python3_cmd setup3.py build --build-lib=../../build/python3') mod = build(py3env.Command('#build/python3/cantera/__init__.py', 'setup3.py', build_cmd)) env['python3_module'] = mod @@ -165,8 +160,7 @@ if localenv['python_package'] == 'full': py2env['py_extension'] = ext[0].name py2env.SubstFile('setup2.py', 'setup.py.in') build_cmd = ('cd interfaces/cython &&' - ' $python_cmd_esc setup2.py build --build-lib=../../build/python2' - ' --executable="/usr/bin/env python"') + ' $python_cmd_esc setup2.py build --build-lib=../../build/python2') mod = build(py2env.Command('#build/python2/cantera/__init__.py', 'setup2.py', build_cmd)) diff --git a/interfaces/cython/scripts/ck2cti.py.in b/interfaces/cython/scripts/ck2cti.py.in deleted file mode 100644 index db45ff6a7..000000000 --- a/interfaces/cython/scripts/ck2cti.py.in +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/python -from cantera import ck2cti -import sys - -ck2cti.main(sys.argv[1:]) diff --git a/interfaces/cython/scripts/ctml_writer.py.in b/interfaces/cython/scripts/ctml_writer.py.in deleted file mode 100644 index ed9b4c58c..000000000 --- a/interfaces/cython/scripts/ctml_writer.py.in +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/python -from cantera import ctml_writer - -if __name__ == "__main__": - import sys - if len(sys.argv) not in (2,3): - raise ValueError('Incorrect number of command line arguments.') - ctml_writer.convert(*sys.argv[1:]) diff --git a/interfaces/cython/scripts/mixmaster.py.in b/interfaces/cython/scripts/mixmaster.py.in deleted file mode 100644 index 1df984cd6..000000000 --- a/interfaces/cython/scripts/mixmaster.py.in +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/python - -from cantera.mixmaster.main import MixMaster -MixMaster() diff --git a/interfaces/cython/setup.py.in b/interfaces/cython/setup.py.in index d927baa58..c5335f8ff 100644 --- a/interfaces/cython/setup.py.in +++ b/interfaces/cython/setup.py.in @@ -1,5 +1,5 @@ import os -from distutils.core import setup +from setuptools import setup # Monkey patch to prevent bdist_msi from incorrectly overwriting the value of # build-lib specified on the command line. @@ -46,9 +46,13 @@ setup(name="Cantera", 'cantera.mixmaster', 'cantera.mixmaster.Units', 'cantera.examples'], - scripts=[@py_ctml_writer@, - @py_ck2cti@, - @py_mixmaster@], + entry_points={ + 'console_scripts': [ + 'ck2cti=cantera.ck2cti:script_entry_point', + 'ctml_writer=cantera.ctml_writer:main', + 'mixmaster=cantera.mixmaster.__main__:main', + ], + }, package_data = {'cantera.data': ['*.*'], 'cantera.test.data': ['*.*'], 'cantera.examples': ['*/*.*'], diff --git a/interfaces/python_minimal/SConscript b/interfaces/python_minimal/SConscript index 7ed8e7947..efbfcfc04 100644 --- a/interfaces/python_minimal/SConscript +++ b/interfaces/python_minimal/SConscript @@ -5,8 +5,6 @@ Import('env', 'build', 'install') localenv = env.Clone() -script_ext = '.py' if os.name == 'nt' else '' - make_setup = build(localenv.SubstFile('setup.py', 'setup.py.in')) # copy scripts from the full Cython module @@ -15,16 +13,7 @@ for script in ['ctml_writer', 'ck2cti']: s = build(env.Command('cantera/%s.py' % script, '#interfaces/cython/cantera/%s.py' % script, Copy('$TARGET', '$SOURCE'))) - # thin wrapper - w = build(env.Command('scripts/%s%s' % (script, script_ext), - '#interfaces/cython/scripts/%s.py.in' % script, - Copy('$TARGET', '$SOURCE'))) localenv.Depends(make_setup, s) - localenv.Depends(make_setup, w) - - # Name used in setup.py - localenv['py_%s' % script] = repr('scripts/%s%s' % (script, script_ext)) - localenv['py_%s' % script] = repr('scripts/%s%s' % (script, script_ext)) build_cmd = ('cd interfaces/python_minimal &&' ' $python_cmd_esc setup.py build --build-lib=../../build/python2') @@ -38,23 +27,33 @@ if localenv['PYTHON_INSTALLER'] == 'direct': if localenv['python_prefix'] == 'USER': # Install to the OS-dependent user site-packages directory extra = '--user' + if localenv['OS'] == 'Darwin': + extra += ' --prefix=""' elif localenv['python_prefix']: - # A specific location for the Cantera python module has been specified - extra = '--prefix="%s"' % localenv['python_prefix'] + # A specific location for the Cantera python module has been given + extra = '--user' + if localenv['OS'] == 'Darwin': + extra += ' --prefix=""' + localenv.AppendENVPath( + 'PYTHONUSERBASE', + normpath(localenv.subst('$python_prefix')) + ) else: # Install Python module in the default location extra = '' mod_inst = install(localenv.Command, 'dummy', mod, build_cmd + ' install %s' % extra + - ' --record ../../build/python2-installed-files.txt') + ' --record=../../build/python2-installed-files.txt' + + ' --single-version-externally-managed') global_env = env + def find_module_dir(target, source, env): - check = pjoin('cantera','__init__.py') + check = pjoin('cantera', '__init__.py') for filename in open('build/python2-installed-files.txt').readlines(): filename = filename.strip() if filename.endswith(check): - filename = filename.replace(check,'') - global_env['python_module_loc'] = os.path.normpath(filename) + filename = filename.replace(check, '') + global_env['python_module_loc'] = normpath(filename) break localenv.AlwaysBuild(localenv.AddPostAction(mod_inst, find_module_dir)) env['install_python2_action'] = mod_inst diff --git a/interfaces/python_minimal/setup.py.in b/interfaces/python_minimal/setup.py.in index 023b9b4eb..ef701126f 100644 --- a/interfaces/python_minimal/setup.py.in +++ b/interfaces/python_minimal/setup.py.in @@ -1,4 +1,4 @@ -from distutils.core import setup +from setuptools import setup setup(name="Cantera (minimal)", version="@cantera_version@", @@ -8,5 +8,10 @@ setup(name="Cantera (minimal)", author_email="speth@mit.edu", url="http://www.cantera.org", packages = ['cantera'], - scripts=[@py_ctml_writer@, - @py_ck2cti@]) + entry_points={ + 'console_scripts': [ + 'ck2cti=cantera.ck2cti:script_entry_point', + 'ctml_writer=cantera.ctml_writer:main', + ], + }, +) diff --git a/site_scons/buildutils.py b/site_scons/buildutils.py index f89a20a0f..b14f37454 100644 --- a/site_scons/buildutils.py +++ b/site_scons/buildutils.py @@ -1,5 +1,6 @@ import os from os.path import join as pjoin +from os.path import normpath import sys import platform import textwrap