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