xref: /petsc/setup.py (revision c30a794af1148fdf34467e2f6d85c723d74d52af)
1#!/usr/bin/env python
2
3"""
4PETSc for Python
5================
6
7Python bindings for PETSc libraries.
8"""
9
10
11## try:
12##     import setuptools
13## except ImportError:
14##     pass
15
16import sys, os
17
18# --------------------------------------------------------------------
19# Metadata
20# --------------------------------------------------------------------
21
22from conf.metadata import metadata
23
24def name():
25    return 'petsc4py'
26
27def version():
28    import re
29    fh = open(os.path.join('src', '__init__.py'))
30    try: data = fh.read()
31    finally: fh.close()
32    m = re.search(r"__version__\s*=\s*'(.*)'", data)
33    return m.groups()[0]
34
35name     = name()
36version  = version()
37
38url      = 'http://%(name)s.googlecode.com/' % vars()
39download = url + 'files/%(name)s-%(version)s.tar.gz' % vars()
40
41descr    = __doc__.strip().split('\n'); del descr[1:3]
42devstat  = ['Development Status :: 3 - Alpha']
43keywords = ['PETSc', 'MPI']
44
45metadata['name'] = name
46metadata['version'] = version
47metadata['description'] = descr.pop(0)
48metadata['long_description'] = '\n'.join(descr)
49metadata['keywords'] += keywords
50metadata['classifiers'] += devstat
51metadata['url'] = url
52metadata['download_url'] = download
53
54metadata['provides'] = ['petsc4py']
55metadata['requires'] = ['numpy']
56
57# --------------------------------------------------------------------
58# Extension modules
59# --------------------------------------------------------------------
60
61def get_ext_modules(Extension):
62    from os   import walk, path
63    from glob import glob
64    depends = []
65    for pth, dirs, files in walk('src'):
66        depends += glob(path.join(pth, '*.h'))
67    for pth, dirs, files in walk(path.join('src', 'source')):
68        depends += glob(path.join(pth, '*.h'))
69        depends += glob(path.join(pth, '*.c'))
70    try:
71        import numpy
72        numpy_includes = [numpy.get_include()]
73    except ImportError:
74        numpy_includes = []
75    return [Extension('petsc4py.lib.PETSc',
76                      sources=['src/PETSc.c',
77                               'src/source/libpetsc4py.c',
78                               ],
79                      include_dirs=['src/include',
80                                    'src/source',
81                                    ] + numpy_includes,
82                      depends=depends)]
83
84# --------------------------------------------------------------------
85# Setup
86# --------------------------------------------------------------------
87
88from conf.petscconf import setup, Extension
89from conf.petscconf import config, build, build_src, build_ext
90from conf.petscconf import test, sdist
91
92def run_setup():
93    if (('distribute' in sys.modules) or
94        ('setuptools' in sys.modules)):
95        metadata['install_requires'] = ['numpy']
96        if not os.environ.get('PETSC_DIR'):
97            metadata['install_requires'].append('petsc')
98    if 'setuptools' in sys.modules:
99        metadata['zip_safe'] = False
100    setup(packages     = ['petsc4py',
101                          'petsc4py.lib',],
102          package_dir  = {'petsc4py'     : 'src',
103                          'petsc4py.lib' : 'src/lib'},
104          package_data = {'petsc4py'     : ['include/petsc4py/*.h',
105                                            'include/petsc4py/*.i',
106                                            'include/petsc4py/*.pxd',
107                                            'include/petsc4py/*.pxi',
108                                            'include/petsc4py/*.pyx',],
109                          'petsc4py.lib' : ['petsc.cfg'],},
110          ext_modules  = get_ext_modules(Extension),
111          cmdclass     = {'config'     : config,
112                          'build'      : build,
113                          'build_src'  : build_src,
114                          'build_ext'  : build_ext,
115                          'test'       : test,
116                          'sdist'      : sdist,
117                          },
118          **metadata)
119
120def chk_cython(CYTHON_VERSION_REQUIRED):
121    from distutils.version import StrictVersion as Version
122    warn = lambda msg='': sys.stderr.write(msg+'\n')
123    #
124    try:
125        import Cython
126    except ImportError:
127        warn("*"*80)
128        warn()
129        warn(" You need to generate C source files with Cython!!")
130        warn(" Download and install Cython <http://www.cython.org>")
131        warn()
132        warn("*"*80)
133        return False
134    #
135    try:
136        CYTHON_VERSION = Cython.__version__
137    except AttributeError:
138        from Cython.Compiler.Version import version as CYTHON_VERSION
139    CYTHON_VERSION = CYTHON_VERSION.split('+', 1)[0]
140    for s in ('.alpha', 'alpha'):
141        CYTHON_VERSION = CYTHON_VERSION.replace(s, 'a')
142    for s in ('.beta',  'beta', '.rc', 'rc', '.c', 'c'):
143        CYTHON_VERSION = CYTHON_VERSION.replace(s, 'b')
144    if Version(CYTHON_VERSION) < Version(CYTHON_VERSION_REQUIRED):
145        warn("*"*80)
146        warn()
147        warn(" You need to install Cython %s (you have version %s)"
148             % (CYTHON_VERSION_REQUIRED, CYTHON_VERSION))
149        warn(" Download and install Cython <http://www.cython.org>")
150        warn()
151        warn("*"*80)
152        return False
153    #
154    return True
155
156def run_cython(source, target, includes=(),
157               depends=(), force=False,
158               CYTHON_VERSION_REQUIRED=None):
159    from distutils import log
160    from distutils import dep_util
161    from distutils.errors import DistutilsError
162    depends = [source] + list(depends)
163    if not (force or dep_util.newer_group(depends, target)):
164        log.debug("skipping '%s' -> '%s' (up-to-date)",
165                  source, target)
166        return
167    if (CYTHON_VERSION_REQUIRED and not
168        chk_cython(CYTHON_VERSION_REQUIRED)):
169        raise DistutilsError('requires Cython>=%s'
170                             % CYTHON_VERSION_REQUIRED)
171    log.info("cythonizing '%s' -> '%s'", source, target)
172    from conf.cythonize import run as cythonize
173    cythonize(source, includes=includes)
174
175def build_sources(cmd):
176    CYTHON_VERSION_REQUIRED = '0.13'
177    from glob import glob
178    if not (os.path.isdir('.hg')  or
179            os.path.isdir('.git') or
180            cmd.force): return
181    source = os.path.join('src', 'petsc4py.PETSc.pyx')
182    target = os.path.splitext(source)[0]+".c"
183    depends = (glob("src/include/*/*.pxd") +
184               glob("src/*/*.pyx") +
185               glob("src/*/*.pxi"))
186    includes =  []
187    run_cython(source, target, includes,
188               depends, cmd.force,
189               CYTHON_VERSION_REQUIRED)
190
191build_src.run = build_sources
192
193def run_testsuite(cmd):
194    from distutils.errors import DistutilsError
195    sys.path.insert(0, 'test')
196    try:
197        from runtests import main
198    finally:
199        del sys.path[-1]
200    err = main(cmd.args or [])
201    if err:
202        raise DistutilsError("test")
203
204test.run = run_testsuite
205
206# --------------------------------------------------------------------
207
208def main():
209    run_setup()
210
211if __name__ == '__main__':
212    main()
213
214# --------------------------------------------------------------------
215