1from __future__ import print_function
2
3# Preliminary checks that cannot be done by setuptools
4# like... the setuptools dependency itself!
5try:
6    import setuptools
7except ImportError:
8    print()
9    print("*****************************************************")
10    print("* Setuptools must be installed before running setup *")
11    print("*****************************************************")
12    print()
13    raise
14
15from setuptools.command.build_py import build_py
16from setuptools.command.develop import develop
17
18from setuptools import setup
19
20import logging
21import os
22import shutil
23import sys
24
25# It appears old versions of setuptools are not supported, see
26#   https://github.com/serge-sans-paille/pythran/issues/489
27
28from distutils.version import LooseVersion
29MinimalSetuptoolsVersion = LooseVersion("12.0.5")
30if LooseVersion(setuptools.__version__) < MinimalSetuptoolsVersion:
31    msg = "Setuptools version is {}, but must be at least {}".format(
32        setuptools.__version__,
33        MinimalSetuptoolsVersion)
34    print()
35    print("*" * (len(msg) + 4))
36    print("*", msg, "*")
37    print("*" * (len(msg) + 4))
38    print()
39    raise ImportError("setuptools")
40
41if sys.version_info.major < 3:
42    print()
43    print("****************************************************")
44    print("*        Python 2 has reached end-of-support       *")
45    print("****************************************************")
46    print("*                                                  *")
47    print("* Last Pythran version supporting Python2 is 0.9.5 *")
48    print("*                                                  *")
49    print("****************************************************")
50    print()
51
52
53logger = logging.getLogger("pythran")
54logger.addHandler(logging.StreamHandler())
55
56versionfile = os.path.join('pythran', 'version.py')
57exec(open(versionfile).read())
58
59
60class BuildWithThirdParty(build_py):
61
62    """
63    Set up Pythran dependencies.
64
65    * install boost dependencies
66    * install xsimd dependencies
67    """
68
69    third_parties = 'boost', 'xsimd'
70
71    user_options = build_py.user_options + [
72        ('no-{}'.format(pkg), None, 'Do not distribute {} headers'.format(pkg))
73        for pkg in third_parties
74    ]
75
76    def initialize_options(self):
77        build_py.initialize_options(self)
78        for pkg in BuildWithThirdParty.third_parties:
79            setattr(self, 'no_' + pkg, None)
80
81    def copy_pkg(self, pkg, src_only=False):
82        "Install boost deps from the third_party directory"
83
84        if getattr(self, 'no_' + pkg) is None:
85            print('Copying', pkg, 'dependencies')
86            to_copy = pkg,
87        else:
88            return
89
90        src = os.path.join('third_party', *to_copy)
91
92        # copy to the build tree
93        if not src_only:
94            target = os.path.join(self.build_lib, 'pythran', *to_copy)
95            shutil.rmtree(target, True)
96            shutil.copytree(src, target)
97
98        # copy them to the source tree too, needed for sdist
99        target = os.path.join('pythran', *to_copy)
100        shutil.rmtree(target, True)
101        shutil.copytree(src, target)
102
103    def run(self, *args, **kwargs):
104        # regular build done by parent class
105        build_py.run(self, *args, **kwargs)
106        if not self.dry_run:  # compatibility with the parent options
107            for pkg in BuildWithThirdParty.third_parties:
108                self.copy_pkg(pkg)
109
110
111class DevelopWithThirdParty(develop, BuildWithThirdParty):
112
113    def initialize_options(self):
114        develop.initialize_options(self)
115        BuildWithThirdParty.initialize_options(self)
116
117    def run(self, *args, **kwargs):
118        if not self.dry_run:  # compatibility with the parent options
119            for pkg in BuildWithThirdParty.third_parties:
120                self.copy_pkg(pkg, src_only=True)
121        develop.run(self, *args, **kwargs)
122
123
124# Cannot use glob here, as the files may not be generated yet
125boost_headers = ['boost/' + '*/' * i + '*.hpp' for i in range(1, 20)]
126xsimd_headers = ['xsimd/' + '*/' * i + '*.hpp' for i in range(1, 20)]
127pythonic_headers = ['*/' * i + '*.hpp' for i in range(9)] + ['patch/*']
128
129
130# read longdescr from README
131def longdescr(readme_path):
132    with open(readme_path) as readme:
133        lines = list(readme)
134        start_index = lines.index('What is it?\n')
135        stop_index = lines.index('Installation\n')
136        long_description = "".join(lines[start_index + 2: stop_index])
137        return long_description
138
139
140setup(name='pythran',
141      version=__version__,
142      description=__descr__,
143      long_description=longdescr("README.rst"),
144      author='Serge Guelton',
145      author_email='serge.guelton@telecom-bretagne.eu',
146      url=__url__,
147      packages=['pythran', 'pythran.analyses', 'pythran.transformations',
148                'pythran.optimizations', 'omp', 'pythran/pythonic',
149                'pythran.types'],
150      package_data={'pythran': (['pythran*.cfg']
151                                + boost_headers
152                                + xsimd_headers),
153                    'pythran/pythonic': pythonic_headers},
154      classifiers=[
155          'Development Status :: 4 - Beta',
156          'Environment :: Console',
157          'Intended Audience :: Developers',
158          'License :: OSI Approved :: BSD License',
159          'Natural Language :: English',
160          'Operating System :: POSIX :: Linux',
161          'Operating System :: MacOS',
162          'Programming Language :: Python :: 2.7',
163          'Programming Language :: Python :: 3',
164          'Programming Language :: Python :: Implementation :: CPython',
165          'Programming Language :: C++',
166          'Topic :: Software Development :: Compilers',
167          'Topic :: Software Development :: Code Generators'
168      ],
169      license="BSD 3-Clause",
170      install_requires=open('requirements.txt').read().splitlines(),
171      entry_points={'console_scripts':
172                    ['pythran = pythran.run:run',
173                     'pythran-config = pythran.config:run']},
174      extras_require={
175          'doc': open('docs/requirements.txt').read().splitlines(),
176      },
177      test_suite="pythran.tests.test_cases",
178      cmdclass={'build_py': BuildWithThirdParty,
179                'develop': DevelopWithThirdParty})
180