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