1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# Tested with boost v1.59.0
5
6import io
7import os
8import re
9import shutil
10import subprocess
11import sys
12import warnings
13from setuptools import setup
14from setuptools.extension import Extension
15try:
16    import cython
17except ImportError:
18    _HAVE_CYTHON = False
19else:
20    _HAVE_CYTHON = True
21    assert cython  # silence pep8
22
23pkg_name = 'pyodeint'
24
25
26def _path_under_setup(*args):
27    return os.path.join(*args)
28
29_src = {ext: _path_under_setup(pkg_name, '_odeint.' + ext) for ext in "cpp pyx".split()}
30if _HAVE_CYTHON and os.path.exists(_src["pyx"]):
31    # Possible that a new release of Python needs a re-rendered Cython source,
32    # or that we want to include possible bug-fix to Cython, disable by manually
33    # deleting .pyx file from source distribution.
34    USE_CYTHON = True
35    if os.path.exists(_src['cpp']):
36        os.unlink(_src['cpp'])  # ensure c++ source is re-generated.
37else:
38    USE_CYTHON = False
39
40package_include = os.path.join(pkg_name, 'include')
41
42ext_modules = []
43if len(sys.argv) > 1 and '--help' not in sys.argv[1:] and sys.argv[1] not in (
44        '--help-commands', 'egg_info', 'clean', '--version'):
45    import numpy as np
46    sources = [_src["pyx" if USE_CYTHON else "cpp"]]
47    ext_modules = [Extension('%s._odeint' % pkg_name, sources)]
48    if USE_CYTHON:
49        from Cython.Build import cythonize
50        ext_modules = cythonize(ext_modules, include_path=[
51            package_include,
52            os.path.join('external', 'anyode', 'cython_def')
53        ])
54    ext_modules[0].language = 'c++'
55    ext_modules[0].extra_compile_args = ['-std=c++11']
56    ext_modules[0].define_macros = [('ANYODE_NO_LAPACK', '1')]
57    ext_modules[0].include_dirs = [package_include, np.get_include(),
58                                   os.path.join('external', 'anyode', 'include')]
59
60RELEASE_VERSION = os.environ.get('%s_RELEASE_VERSION' % pkg_name.upper(), '')
61
62# http://conda.pydata.org/docs/build.html#environment-variables-set-during-the-build-process
63CONDA_BUILD = os.environ.get('CONDA_BUILD', '0') == '1'
64if CONDA_BUILD:
65    try:
66        RELEASE_VERSION = 'v' + open(
67            '__conda_version__.txt', 'rt').readline().rstrip()
68    except IOError:
69        pass
70
71release_py_path = _path_under_setup(pkg_name, '_release.py')
72
73if len(RELEASE_VERSION) > 1 and RELEASE_VERSION[0] == 'v':
74    TAGGED_RELEASE = True
75    __version__ = RELEASE_VERSION[1:]
76else:
77    TAGGED_RELEASE = False
78    # read __version__ attribute from _release.py:
79    exec(open(release_py_path).read())
80    if __version__.endswith('git'):
81        try:
82            _git_version = subprocess.check_output(
83                ['git', 'describe', '--dirty']).rstrip().decode('utf-8').replace('-dirty', '.dirty')
84        except subprocess.CalledProcessError:
85            warnings.warn("A git-archive is being installed - version information incomplete.")
86        else:
87            if 'develop' not in sys.argv:
88                warnings.warn("Using git to derive version: dev-branches may compete.")
89                __version__ = re.sub(r'v([0-9.]+)-(\d+)-(\w+)', r'\1.post\2+\3', _git_version)  # .dev < '' < .post
90
91classifiers = [
92    "Development Status :: 4 - Beta",
93    'License :: OSI Approved :: BSD License',
94    'Operating System :: OS Independent',
95    'Topic :: Scientific/Engineering',
96    'Topic :: Scientific/Engineering :: Mathematics',
97]
98
99tests = [
100    'pyodeint.tests',
101]
102
103with io.open(_path_under_setup(pkg_name, '__init__.py'), 'rt',
104             encoding='utf-8') as f:
105    short_description = f.read().split('"""')[1].split('\n')[1]
106assert 10 < len(short_description) < 255
107long_descr = io.open(_path_under_setup('README.rst'), encoding='utf-8').read()
108assert len(long_descr) > 100
109
110setup_kwargs = dict(
111    name=pkg_name,
112    version=__version__,
113    description=short_description,
114    long_description=long_descr,
115    classifiers=classifiers,
116    author='Björn Dahlgren',
117    author_email='bjodah@DELETEMEgmail.com',
118    license='BSD',
119    url='https://github.com/bjodah/' + pkg_name,
120    packages=[pkg_name] + tests,
121    include_package_data=True,
122    install_requires=['numpy'] + (['cython'] if USE_CYTHON else []),
123    setup_requires=['numpy'] + (['cython'] if USE_CYTHON else []),
124    extras_require={'docs': ['Sphinx', 'sphinx_rtd_theme']},
125    ext_modules=ext_modules,
126)
127
128if __name__ == '__main__':
129    try:
130        if TAGGED_RELEASE:
131            # Same commit should generate different sdist
132            # depending on tagged version (set PYODEINT_RELEASE_VERSION)
133            # this will ensure source distributions contain the correct version
134            shutil.move(release_py_path, release_py_path+'__temp__')
135            open(release_py_path, 'wt').write(
136                "__version__ = '{}'\n".format(__version__))
137        setup(**setup_kwargs)
138    finally:
139        if TAGGED_RELEASE:
140            shutil.move(release_py_path+'__temp__', release_py_path)
141