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