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 :: 5 - Production/Stable'] 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.3,<3.4"] 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 import re 132 from distutils import log 133 from distutils.version import LooseVersion 134 from distutils.version import StrictVersion 135 warn = lambda msg='': sys.stderr.write(msg+'\n') 136 # 137 cython_zip = 'cython.zip' 138 if os.path.isfile(cython_zip): 139 path = os.path.abspath(cython_zip) 140 if sys.path[0] != path: 141 sys.path.insert(0, path) 142 log.info("adding '%s' to sys.path", cython_zip) 143 # 144 try: 145 import Cython 146 except ImportError: 147 warn("*"*80) 148 warn() 149 warn(" You need to generate C source files with Cython!!") 150 warn(" Download and install Cython <http://www.cython.org>") 151 warn() 152 warn("*"*80) 153 return False 154 # 155 try: 156 CYTHON_VERSION = Cython.__version__ 157 except AttributeError: 158 from Cython.Compiler.Version import version as CYTHON_VERSION 159 REQUIRED = VERSION 160 m = re.match(r"(\d+\.\d+(?:\.\d+)?).*", CYTHON_VERSION) 161 if m: 162 Version = StrictVersion 163 AVAILABLE = m.groups()[0] 164 else: 165 Version = LooseVersion 166 AVAILABLE = CYTHON_VERSION 167 if (REQUIRED is not None and 168 Version(AVAILABLE) < Version(REQUIRED)): 169 warn("*"*80) 170 warn() 171 warn(" You need to install Cython %s (you have version %s)" 172 % (REQUIRED, CYTHON_VERSION)) 173 warn(" Download and install Cython <http://www.cython.org>") 174 warn() 175 warn("*"*80) 176 return False 177 # 178 return True 179 180def run_cython(source, depends=(), includes=(), 181 destdir_c=None, destdir_h=None, wdir=None, 182 force=False, VERSION=None): 183 from glob import glob 184 from distutils import log 185 from distutils import dep_util 186 from distutils.errors import DistutilsError 187 target = os.path.splitext(source)[0]+".c" 188 cwd = os.getcwd() 189 try: 190 if wdir: os.chdir(wdir) 191 alldeps = [source] 192 for dep in depends: 193 alldeps += glob(dep) 194 if not (force or dep_util.newer_group(alldeps, target)): 195 log.debug("skipping '%s' -> '%s' (up-to-date)", 196 source, target) 197 return 198 finally: 199 os.chdir(cwd) 200 if not chk_cython(VERSION): 201 raise DistutilsError("requires Cython>=%s" % VERSION) 202 log.info("cythonizing '%s' -> '%s'", source, target) 203 from conf.cythonize import cythonize 204 err = cythonize(source, 205 includes=includes, 206 destdir_c=destdir_c, 207 destdir_h=destdir_h, 208 wdir=wdir) 209 if err: 210 raise DistutilsError( 211 "Cython failure: '%s' -> '%s'" % (source, target)) 212 213def build_sources(cmd): 214 from os.path import exists, isdir, join 215 if (exists(join('src', 'petsc4py.PETSc.c')) and 216 not (isdir('.hg') or isdir('.git')) and 217 not cmd.force): return 218 # petsc4py.PETSc 219 source = 'petsc4py.PETSc.pyx' 220 depends = ("include/*/*.pxd", 221 "PETSc/*.pyx", 222 "PETSc/*.pxi",) 223 includes = ['include'] 224 destdir_h = os.path.join('include', 'petsc4py') 225 run_cython(source, depends, includes, 226 destdir_c=None, destdir_h=destdir_h, wdir='src', 227 force=cmd.force, VERSION=CYTHON) 228 # libpetsc4py 229 source = os.path.join('libpetsc4py', 'libpetsc4py.pyx') 230 depends = ["include/petsc4py/*.pxd", 231 "libpetsc4py/*.pyx", 232 "libpetsc4py/*.pxi"] 233 includes = ['include'] 234 run_cython(source, depends, includes, 235 destdir_c=None, destdir_h=None, wdir='src', 236 force=cmd.force, VERSION=CYTHON) 237 238build_src.run = build_sources 239 240def run_testsuite(cmd): 241 from distutils.errors import DistutilsError 242 sys.path.insert(0, 'test') 243 try: 244 from runtests import main 245 finally: 246 del sys.path[0] 247 err = main(cmd.args or []) 248 if err: 249 raise DistutilsError("test") 250 251test.run = run_testsuite 252 253# -------------------------------------------------------------------- 254 255def main(): 256 run_setup() 257 258if __name__ == '__main__': 259 main() 260 261# -------------------------------------------------------------------- 262