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