Mercurial > hg > vamp-build-and-test
diff DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/f2py/tests/util.py @ 87:2a2c65a20a8b
Add Python libs and headers
author | Chris Cannam |
---|---|
date | Wed, 25 Feb 2015 14:05:22 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/f2py/tests/util.py Wed Feb 25 14:05:22 2015 +0000 @@ -0,0 +1,353 @@ +""" +Utility functions for + +- building and importing modules on test time, using a temporary location +- detecting if compilers are present + +""" +from __future__ import division, absolute_import, print_function + +import os +import sys +import subprocess +import tempfile +import shutil +import atexit +import textwrap +import re +import random + +import nose + +from numpy.compat import asbytes, asstr +import numpy.f2py + +try: + from hashlib import md5 +except ImportError: + from md5 import new as md5 + +# +# Maintaining a temporary module directory +# + +_module_dir = None + +def _cleanup(): + global _module_dir + if _module_dir is not None: + try: + sys.path.remove(_module_dir) + except ValueError: + pass + try: + shutil.rmtree(_module_dir) + except (IOError, OSError): + pass + _module_dir = None + +def get_module_dir(): + global _module_dir + if _module_dir is None: + _module_dir = tempfile.mkdtemp() + atexit.register(_cleanup) + if _module_dir not in sys.path: + sys.path.insert(0, _module_dir) + return _module_dir + +def get_temp_module_name(): + # Assume single-threaded, and the module dir usable only by this thread + d = get_module_dir() + for j in range(5403, 9999999): + name = "_test_ext_module_%d" % j + fn = os.path.join(d, name) + if name not in sys.modules and not os.path.isfile(fn+'.py'): + return name + raise RuntimeError("Failed to create a temporary module name") + +def _memoize(func): + memo = {} + def wrapper(*a, **kw): + key = repr((a, kw)) + if key not in memo: + try: + memo[key] = func(*a, **kw) + except Exception as e: + memo[key] = e + raise + ret = memo[key] + if isinstance(ret, Exception): + raise ret + return ret + wrapper.__name__ = func.__name__ + return wrapper + +# +# Building modules +# + +@_memoize +def build_module(source_files, options=[], skip=[], only=[], module_name=None): + """ + Compile and import a f2py module, built from the given files. + + """ + + code = ("import sys; sys.path = %s; import numpy.f2py as f2py2e; " + "f2py2e.main()" % repr(sys.path)) + + d = get_module_dir() + + # Copy files + dst_sources = [] + for fn in source_files: + if not os.path.isfile(fn): + raise RuntimeError("%s is not a file" % fn) + dst = os.path.join(d, os.path.basename(fn)) + shutil.copyfile(fn, dst) + dst_sources.append(dst) + + fn = os.path.join(os.path.dirname(fn), '.f2py_f2cmap') + if os.path.isfile(fn): + dst = os.path.join(d, os.path.basename(fn)) + if not os.path.isfile(dst): + shutil.copyfile(fn, dst) + + # Prepare options + if module_name is None: + module_name = get_temp_module_name() + f2py_opts = ['-c', '-m', module_name] + options + dst_sources + if skip: + f2py_opts += ['skip:'] + skip + if only: + f2py_opts += ['only:'] + only + + # Build + cwd = os.getcwd() + try: + os.chdir(d) + cmd = [sys.executable, '-c', code] + f2py_opts + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + out, err = p.communicate() + if p.returncode != 0: + raise RuntimeError("Running f2py failed: %s\n%s" + % (cmd[4:], asstr(out))) + finally: + os.chdir(cwd) + + # Partial cleanup + for fn in dst_sources: + os.unlink(fn) + + # Import + __import__(module_name) + return sys.modules[module_name] + +@_memoize +def build_code(source_code, options=[], skip=[], only=[], suffix=None, + module_name=None): + """ + Compile and import Fortran code using f2py. + + """ + if suffix is None: + suffix = '.f' + + fd, tmp_fn = tempfile.mkstemp(suffix=suffix) + os.write(fd, asbytes(source_code)) + os.close(fd) + + try: + return build_module([tmp_fn], options=options, skip=skip, only=only, + module_name=module_name) + finally: + os.unlink(tmp_fn) + +# +# Check if compilers are available at all... +# + +_compiler_status = None +def _get_compiler_status(): + global _compiler_status + if _compiler_status is not None: + return _compiler_status + + _compiler_status = (False, False, False) + + # XXX: this is really ugly. But I don't know how to invoke Distutils + # in a safer way... + code = """ +import os +import sys +sys.path = %(syspath)s + +def configuration(parent_name='',top_path=None): + global config + from numpy.distutils.misc_util import Configuration + config = Configuration('', parent_name, top_path) + return config + +from numpy.distutils.core import setup +setup(configuration=configuration) + +config_cmd = config.get_config_cmd() +have_c = config_cmd.try_compile('void foo() {}') +print('COMPILERS:%%d,%%d,%%d' %% (have_c, + config.have_f77c(), + config.have_f90c())) +sys.exit(99) +""" + code = code % dict(syspath=repr(sys.path)) + + fd, script = tempfile.mkstemp(suffix='.py') + os.write(fd, asbytes(code)) + os.close(fd) + + try: + cmd = [sys.executable, script, 'config'] + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + out, err = p.communicate() + m = re.search(asbytes(r'COMPILERS:(\d+),(\d+),(\d+)'), out) + if m: + _compiler_status = (bool(int(m.group(1))), bool(int(m.group(2))), + bool(int(m.group(3)))) + finally: + os.unlink(script) + + # Finished + return _compiler_status + +def has_c_compiler(): + return _get_compiler_status()[0] + +def has_f77_compiler(): + return _get_compiler_status()[1] + +def has_f90_compiler(): + return _get_compiler_status()[2] + +# +# Building with distutils +# + +@_memoize +def build_module_distutils(source_files, config_code, module_name, **kw): + """ + Build a module via distutils and import it. + + """ + from numpy.distutils.misc_util import Configuration + from numpy.distutils.core import setup + + d = get_module_dir() + + # Copy files + dst_sources = [] + for fn in source_files: + if not os.path.isfile(fn): + raise RuntimeError("%s is not a file" % fn) + dst = os.path.join(d, os.path.basename(fn)) + shutil.copyfile(fn, dst) + dst_sources.append(dst) + + # Build script + config_code = textwrap.dedent(config_code).replace("\n", "\n ") + + code = """\ +import os +import sys +sys.path = %(syspath)s + +def configuration(parent_name='',top_path=None): + from numpy.distutils.misc_util import Configuration + config = Configuration('', parent_name, top_path) + %(config_code)s + return config + +if __name__ == "__main__": + from numpy.distutils.core import setup + setup(configuration=configuration) +""" % dict(config_code=config_code, syspath = repr(sys.path)) + + script = os.path.join(d, get_temp_module_name() + '.py') + dst_sources.append(script) + f = open(script, 'wb') + f.write(asbytes(code)) + f.close() + + # Build + cwd = os.getcwd() + try: + os.chdir(d) + cmd = [sys.executable, script, 'build_ext', '-i'] + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + out, err = p.communicate() + if p.returncode != 0: + raise RuntimeError("Running distutils build failed: %s\n%s" + % (cmd[4:], asstr(out))) + finally: + os.chdir(cwd) + + # Partial cleanup + for fn in dst_sources: + os.unlink(fn) + + # Import + __import__(module_name) + return sys.modules[module_name] + +# +# Unittest convenience +# + +class F2PyTest(object): + code = None + sources = None + options = [] + skip = [] + only = [] + suffix = '.f' + module = None + module_name = None + + def setUp(self): + if self.module is not None: + return + + # Check compiler availability first + if not has_c_compiler(): + raise nose.SkipTest("No C compiler available") + + codes = [] + if self.sources: + codes.extend(self.sources) + if self.code is not None: + codes.append(self.suffix) + + needs_f77 = False + needs_f90 = False + for fn in codes: + if fn.endswith('.f'): + needs_f77 = True + elif fn.endswith('.f90'): + needs_f90 = True + if needs_f77 and not has_f77_compiler(): + raise nose.SkipTest("No Fortran 77 compiler available") + if needs_f90 and not has_f90_compiler(): + raise nose.SkipTest("No Fortran 90 compiler available") + + # Build the module + if self.code is not None: + self.module = build_code(self.code, options=self.options, + skip=self.skip, only=self.only, + suffix=self.suffix, + module_name=self.module_name) + + if self.sources is not None: + self.module = build_module(self.sources, options=self.options, + skip=self.skip, only=self.only, + module_name=self.module_name)