You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					2494 lines
				
				87 KiB
			
		
		
			
		
	
	
					2494 lines
				
				87 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								import os
							 | 
						||
| 
								 | 
							
								import re
							 | 
						||
| 
								 | 
							
								import sys
							 | 
						||
| 
								 | 
							
								import copy
							 | 
						||
| 
								 | 
							
								import glob
							 | 
						||
| 
								 | 
							
								import atexit
							 | 
						||
| 
								 | 
							
								import tempfile
							 | 
						||
| 
								 | 
							
								import subprocess
							 | 
						||
| 
								 | 
							
								import shutil
							 | 
						||
| 
								 | 
							
								import multiprocessing
							 | 
						||
| 
								 | 
							
								import textwrap
							 | 
						||
| 
								 | 
							
								import importlib.util
							 | 
						||
| 
								 | 
							
								from threading import local as tlocal
							 | 
						||
| 
								 | 
							
								from functools import reduce
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import distutils
							 | 
						||
| 
								 | 
							
								from distutils.errors import DistutilsError
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# stores temporary directory of each thread to only create one per thread
							 | 
						||
| 
								 | 
							
								_tdata = tlocal()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# store all created temporary directories so they can be deleted on exit
							 | 
						||
| 
								 | 
							
								_tmpdirs = []
							 | 
						||
| 
								 | 
							
								def clean_up_temporary_directory():
							 | 
						||
| 
								 | 
							
								    if _tmpdirs is not None:
							 | 
						||
| 
								 | 
							
								        for d in _tmpdirs:
							 | 
						||
| 
								 | 
							
								            try:
							 | 
						||
| 
								 | 
							
								                shutil.rmtree(d)
							 | 
						||
| 
								 | 
							
								            except OSError:
							 | 
						||
| 
								 | 
							
								                pass
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								atexit.register(clean_up_temporary_directory)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								__all__ = ['Configuration', 'get_numpy_include_dirs', 'default_config_dict',
							 | 
						||
| 
								 | 
							
								           'dict_append', 'appendpath', 'generate_config_py',
							 | 
						||
| 
								 | 
							
								           'get_cmd', 'allpath', 'get_mathlibs',
							 | 
						||
| 
								 | 
							
								           'terminal_has_colors', 'red_text', 'green_text', 'yellow_text',
							 | 
						||
| 
								 | 
							
								           'blue_text', 'cyan_text', 'cyg2win32', 'mingw32', 'all_strings',
							 | 
						||
| 
								 | 
							
								           'has_f_sources', 'has_cxx_sources', 'filter_sources',
							 | 
						||
| 
								 | 
							
								           'get_dependencies', 'is_local_src_dir', 'get_ext_source_files',
							 | 
						||
| 
								 | 
							
								           'get_script_files', 'get_lib_source_files', 'get_data_files',
							 | 
						||
| 
								 | 
							
								           'dot_join', 'get_frame', 'minrelpath', 'njoin',
							 | 
						||
| 
								 | 
							
								           'is_sequence', 'is_string', 'as_list', 'gpaths', 'get_language',
							 | 
						||
| 
								 | 
							
								           'get_build_architecture', 'get_info', 'get_pkg_info',
							 | 
						||
| 
								 | 
							
								           'get_num_build_jobs', 'sanitize_cxx_flags',
							 | 
						||
| 
								 | 
							
								           'exec_mod_from_location']
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class InstallableLib:
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Container to hold information on an installable library.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Parameters
							 | 
						||
| 
								 | 
							
								    ----------
							 | 
						||
| 
								 | 
							
								    name : str
							 | 
						||
| 
								 | 
							
								        Name of the installed library.
							 | 
						||
| 
								 | 
							
								    build_info : dict
							 | 
						||
| 
								 | 
							
								        Dictionary holding build information.
							 | 
						||
| 
								 | 
							
								    target_dir : str
							 | 
						||
| 
								 | 
							
								        Absolute path specifying where to install the library.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    See Also
							 | 
						||
| 
								 | 
							
								    --------
							 | 
						||
| 
								 | 
							
								    Configuration.add_installed_library
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Notes
							 | 
						||
| 
								 | 
							
								    -----
							 | 
						||
| 
								 | 
							
								    The three parameters are stored as attributes with the same names.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    def __init__(self, name, build_info, target_dir):
							 | 
						||
| 
								 | 
							
								        self.name = name
							 | 
						||
| 
								 | 
							
								        self.build_info = build_info
							 | 
						||
| 
								 | 
							
								        self.target_dir = target_dir
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_num_build_jobs():
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Get number of parallel build jobs set by the --parallel command line
							 | 
						||
| 
								 | 
							
								    argument of setup.py
							 | 
						||
| 
								 | 
							
								    If the command did not receive a setting the environment variable
							 | 
						||
| 
								 | 
							
								    NPY_NUM_BUILD_JOBS is checked. If that is unset, return the number of
							 | 
						||
| 
								 | 
							
								    processors on the system, with a maximum of 8 (to prevent
							 | 
						||
| 
								 | 
							
								    overloading the system if there a lot of CPUs).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Returns
							 | 
						||
| 
								 | 
							
								    -------
							 | 
						||
| 
								 | 
							
								    out : int
							 | 
						||
| 
								 | 
							
								        number of parallel jobs that can be run
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    from numpy.distutils.core import get_distribution
							 | 
						||
| 
								 | 
							
								    try:
							 | 
						||
| 
								 | 
							
								        cpu_count = len(os.sched_getaffinity(0))
							 | 
						||
| 
								 | 
							
								    except AttributeError:
							 | 
						||
| 
								 | 
							
								        cpu_count = multiprocessing.cpu_count()
							 | 
						||
| 
								 | 
							
								    cpu_count = min(cpu_count, 8)
							 | 
						||
| 
								 | 
							
								    envjobs = int(os.environ.get("NPY_NUM_BUILD_JOBS", cpu_count))
							 | 
						||
| 
								 | 
							
								    dist = get_distribution()
							 | 
						||
| 
								 | 
							
								    # may be None during configuration
							 | 
						||
| 
								 | 
							
								    if dist is None:
							 | 
						||
| 
								 | 
							
								        return envjobs
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # any of these three may have the job set, take the largest
							 | 
						||
| 
								 | 
							
								    cmdattr = (getattr(dist.get_command_obj('build'), 'parallel', None),
							 | 
						||
| 
								 | 
							
								               getattr(dist.get_command_obj('build_ext'), 'parallel', None),
							 | 
						||
| 
								 | 
							
								               getattr(dist.get_command_obj('build_clib'), 'parallel', None))
							 | 
						||
| 
								 | 
							
								    if all(x is None for x in cmdattr):
							 | 
						||
| 
								 | 
							
								        return envjobs
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        return max(x for x in cmdattr if x is not None)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def quote_args(args):
							 | 
						||
| 
								 | 
							
								    """Quote list of arguments.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    .. deprecated:: 1.22.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    import warnings
							 | 
						||
| 
								 | 
							
								    warnings.warn('"quote_args" is deprecated.',
							 | 
						||
| 
								 | 
							
								                  DeprecationWarning, stacklevel=2)
							 | 
						||
| 
								 | 
							
								    # don't used _nt_quote_args as it does not check if
							 | 
						||
| 
								 | 
							
								    # args items already have quotes or not.
							 | 
						||
| 
								 | 
							
								    args = list(args)
							 | 
						||
| 
								 | 
							
								    for i in range(len(args)):
							 | 
						||
| 
								 | 
							
								        a = args[i]
							 | 
						||
| 
								 | 
							
								        if ' ' in a and a[0] not in '"\'':
							 | 
						||
| 
								 | 
							
								            args[i] = '"%s"' % (a)
							 | 
						||
| 
								 | 
							
								    return args
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def allpath(name):
							 | 
						||
| 
								 | 
							
								    "Convert a /-separated pathname to one using the OS's path separator."
							 | 
						||
| 
								 | 
							
								    split = name.split('/')
							 | 
						||
| 
								 | 
							
								    return os.path.join(*split)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def rel_path(path, parent_path):
							 | 
						||
| 
								 | 
							
								    """Return path relative to parent_path."""
							 | 
						||
| 
								 | 
							
								    # Use realpath to avoid issues with symlinked dirs (see gh-7707)
							 | 
						||
| 
								 | 
							
								    pd = os.path.realpath(os.path.abspath(parent_path))
							 | 
						||
| 
								 | 
							
								    apath = os.path.realpath(os.path.abspath(path))
							 | 
						||
| 
								 | 
							
								    if len(apath) < len(pd):
							 | 
						||
| 
								 | 
							
								        return path
							 | 
						||
| 
								 | 
							
								    if apath == pd:
							 | 
						||
| 
								 | 
							
								        return ''
							 | 
						||
| 
								 | 
							
								    if pd == apath[:len(pd)]:
							 | 
						||
| 
								 | 
							
								        assert apath[len(pd)] in [os.sep], repr((path, apath[len(pd)]))
							 | 
						||
| 
								 | 
							
								        path = apath[len(pd)+1:]
							 | 
						||
| 
								 | 
							
								    return path
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_path_from_frame(frame, parent_path=None):
							 | 
						||
| 
								 | 
							
								    """Return path of the module given a frame object from the call stack.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Returned path is relative to parent_path when given,
							 | 
						||
| 
								 | 
							
								    otherwise it is absolute path.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # First, try to find if the file name is in the frame.
							 | 
						||
| 
								 | 
							
								    try:
							 | 
						||
| 
								 | 
							
								        caller_file = eval('__file__', frame.f_globals, frame.f_locals)
							 | 
						||
| 
								 | 
							
								        d = os.path.dirname(os.path.abspath(caller_file))
							 | 
						||
| 
								 | 
							
								    except NameError:
							 | 
						||
| 
								 | 
							
								        # __file__ is not defined, so let's try __name__. We try this second
							 | 
						||
| 
								 | 
							
								        # because setuptools spoofs __name__ to be '__main__' even though
							 | 
						||
| 
								 | 
							
								        # sys.modules['__main__'] might be something else, like easy_install(1).
							 | 
						||
| 
								 | 
							
								        caller_name = eval('__name__', frame.f_globals, frame.f_locals)
							 | 
						||
| 
								 | 
							
								        __import__(caller_name)
							 | 
						||
| 
								 | 
							
								        mod = sys.modules[caller_name]
							 | 
						||
| 
								 | 
							
								        if hasattr(mod, '__file__'):
							 | 
						||
| 
								 | 
							
								            d = os.path.dirname(os.path.abspath(mod.__file__))
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            # we're probably running setup.py as execfile("setup.py")
							 | 
						||
| 
								 | 
							
								            # (likely we're building an egg)
							 | 
						||
| 
								 | 
							
								            d = os.path.abspath('.')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if parent_path is not None:
							 | 
						||
| 
								 | 
							
								        d = rel_path(d, parent_path)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return d or '.'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def njoin(*path):
							 | 
						||
| 
								 | 
							
								    """Join two or more pathname components +
							 | 
						||
| 
								 | 
							
								    - convert a /-separated pathname to one using the OS's path separator.
							 | 
						||
| 
								 | 
							
								    - resolve `..` and `.` from path.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Either passing n arguments as in njoin('a','b'), or a sequence
							 | 
						||
| 
								 | 
							
								    of n names as in njoin(['a','b']) is handled, or a mixture of such arguments.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    paths = []
							 | 
						||
| 
								 | 
							
								    for p in path:
							 | 
						||
| 
								 | 
							
								        if is_sequence(p):
							 | 
						||
| 
								 | 
							
								            # njoin(['a', 'b'], 'c')
							 | 
						||
| 
								 | 
							
								            paths.append(njoin(*p))
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            assert is_string(p)
							 | 
						||
| 
								 | 
							
								            paths.append(p)
							 | 
						||
| 
								 | 
							
								    path = paths
							 | 
						||
| 
								 | 
							
								    if not path:
							 | 
						||
| 
								 | 
							
								        # njoin()
							 | 
						||
| 
								 | 
							
								        joined = ''
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        # njoin('a', 'b')
							 | 
						||
| 
								 | 
							
								        joined = os.path.join(*path)
							 | 
						||
| 
								 | 
							
								    if os.path.sep != '/':
							 | 
						||
| 
								 | 
							
								        joined = joined.replace('/', os.path.sep)
							 | 
						||
| 
								 | 
							
								    return minrelpath(joined)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_mathlibs(path=None):
							 | 
						||
| 
								 | 
							
								    """Return the MATHLIB line from numpyconfig.h
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    if path is not None:
							 | 
						||
| 
								 | 
							
								        config_file = os.path.join(path, '_numpyconfig.h')
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        # Look for the file in each of the numpy include directories.
							 | 
						||
| 
								 | 
							
								        dirs = get_numpy_include_dirs()
							 | 
						||
| 
								 | 
							
								        for path in dirs:
							 | 
						||
| 
								 | 
							
								            fn = os.path.join(path, '_numpyconfig.h')
							 | 
						||
| 
								 | 
							
								            if os.path.exists(fn):
							 | 
						||
| 
								 | 
							
								                config_file = fn
							 | 
						||
| 
								 | 
							
								                break
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            raise DistutilsError('_numpyconfig.h not found in numpy include '
							 | 
						||
| 
								 | 
							
								                'dirs %r' % (dirs,))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    with open(config_file) as fid:
							 | 
						||
| 
								 | 
							
								        mathlibs = []
							 | 
						||
| 
								 | 
							
								        s = '#define MATHLIB'
							 | 
						||
| 
								 | 
							
								        for line in fid:
							 | 
						||
| 
								 | 
							
								            if line.startswith(s):
							 | 
						||
| 
								 | 
							
								                value = line[len(s):].strip()
							 | 
						||
| 
								 | 
							
								                if value:
							 | 
						||
| 
								 | 
							
								                    mathlibs.extend(value.split(','))
							 | 
						||
| 
								 | 
							
								    return mathlibs
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def minrelpath(path):
							 | 
						||
| 
								 | 
							
								    """Resolve `..` and '.' from path.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    if not is_string(path):
							 | 
						||
| 
								 | 
							
								        return path
							 | 
						||
| 
								 | 
							
								    if '.' not in path:
							 | 
						||
| 
								 | 
							
								        return path
							 | 
						||
| 
								 | 
							
								    l = path.split(os.sep)
							 | 
						||
| 
								 | 
							
								    while l:
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            i = l.index('.', 1)
							 | 
						||
| 
								 | 
							
								        except ValueError:
							 | 
						||
| 
								 | 
							
								            break
							 | 
						||
| 
								 | 
							
								        del l[i]
							 | 
						||
| 
								 | 
							
								    j = 1
							 | 
						||
| 
								 | 
							
								    while l:
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            i = l.index('..', j)
							 | 
						||
| 
								 | 
							
								        except ValueError:
							 | 
						||
| 
								 | 
							
								            break
							 | 
						||
| 
								 | 
							
								        if l[i-1]=='..':
							 | 
						||
| 
								 | 
							
								            j += 1
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            del l[i], l[i-1]
							 | 
						||
| 
								 | 
							
								            j = 1
							 | 
						||
| 
								 | 
							
								    if not l:
							 | 
						||
| 
								 | 
							
								        return ''
							 | 
						||
| 
								 | 
							
								    return os.sep.join(l)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def sorted_glob(fileglob):
							 | 
						||
| 
								 | 
							
								    """sorts output of python glob for https://bugs.python.org/issue30461
							 | 
						||
| 
								 | 
							
								    to allow extensions to have reproducible build results"""
							 | 
						||
| 
								 | 
							
								    return sorted(glob.glob(fileglob))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def _fix_paths(paths, local_path, include_non_existing):
							 | 
						||
| 
								 | 
							
								    assert is_sequence(paths), repr(type(paths))
							 | 
						||
| 
								 | 
							
								    new_paths = []
							 | 
						||
| 
								 | 
							
								    assert not is_string(paths), repr(paths)
							 | 
						||
| 
								 | 
							
								    for n in paths:
							 | 
						||
| 
								 | 
							
								        if is_string(n):
							 | 
						||
| 
								 | 
							
								            if '*' in n or '?' in n:
							 | 
						||
| 
								 | 
							
								                p = sorted_glob(n)
							 | 
						||
| 
								 | 
							
								                p2 = sorted_glob(njoin(local_path, n))
							 | 
						||
| 
								 | 
							
								                if p2:
							 | 
						||
| 
								 | 
							
								                    new_paths.extend(p2)
							 | 
						||
| 
								 | 
							
								                elif p:
							 | 
						||
| 
								 | 
							
								                    new_paths.extend(p)
							 | 
						||
| 
								 | 
							
								                else:
							 | 
						||
| 
								 | 
							
								                    if include_non_existing:
							 | 
						||
| 
								 | 
							
								                        new_paths.append(n)
							 | 
						||
| 
								 | 
							
								                    print('could not resolve pattern in %r: %r' %
							 | 
						||
| 
								 | 
							
								                            (local_path, n))
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                n2 = njoin(local_path, n)
							 | 
						||
| 
								 | 
							
								                if os.path.exists(n2):
							 | 
						||
| 
								 | 
							
								                    new_paths.append(n2)
							 | 
						||
| 
								 | 
							
								                else:
							 | 
						||
| 
								 | 
							
								                    if os.path.exists(n):
							 | 
						||
| 
								 | 
							
								                        new_paths.append(n)
							 | 
						||
| 
								 | 
							
								                    elif include_non_existing:
							 | 
						||
| 
								 | 
							
								                        new_paths.append(n)
							 | 
						||
| 
								 | 
							
								                    if not os.path.exists(n):
							 | 
						||
| 
								 | 
							
								                        print('non-existing path in %r: %r' %
							 | 
						||
| 
								 | 
							
								                                (local_path, n))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        elif is_sequence(n):
							 | 
						||
| 
								 | 
							
								            new_paths.extend(_fix_paths(n, local_path, include_non_existing))
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            new_paths.append(n)
							 | 
						||
| 
								 | 
							
								    return [minrelpath(p) for p in new_paths]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def gpaths(paths, local_path='', include_non_existing=True):
							 | 
						||
| 
								 | 
							
								    """Apply glob to paths and prepend local_path if needed.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    if is_string(paths):
							 | 
						||
| 
								 | 
							
								        paths = (paths,)
							 | 
						||
| 
								 | 
							
								    return _fix_paths(paths, local_path, include_non_existing)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def make_temp_file(suffix='', prefix='', text=True):
							 | 
						||
| 
								 | 
							
								    if not hasattr(_tdata, 'tempdir'):
							 | 
						||
| 
								 | 
							
								        _tdata.tempdir = tempfile.mkdtemp()
							 | 
						||
| 
								 | 
							
								        _tmpdirs.append(_tdata.tempdir)
							 | 
						||
| 
								 | 
							
								    fid, name = tempfile.mkstemp(suffix=suffix,
							 | 
						||
| 
								 | 
							
								                                 prefix=prefix,
							 | 
						||
| 
								 | 
							
								                                 dir=_tdata.tempdir,
							 | 
						||
| 
								 | 
							
								                                 text=text)
							 | 
						||
| 
								 | 
							
								    fo = os.fdopen(fid, 'w')
							 | 
						||
| 
								 | 
							
								    return fo, name
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Hooks for colored terminal output.
							 | 
						||
| 
								 | 
							
								# See also https://web.archive.org/web/20100314204946/http://www.livinglogic.de/Python/ansistyle
							 | 
						||
| 
								 | 
							
								def terminal_has_colors():
							 | 
						||
| 
								 | 
							
								    if sys.platform=='cygwin' and 'USE_COLOR' not in os.environ:
							 | 
						||
| 
								 | 
							
								        # Avoid importing curses that causes illegal operation
							 | 
						||
| 
								 | 
							
								        # with a message:
							 | 
						||
| 
								 | 
							
								        #  PYTHON2 caused an invalid page fault in
							 | 
						||
| 
								 | 
							
								        #  module CYGNURSES7.DLL as 015f:18bbfc28
							 | 
						||
| 
								 | 
							
								        # Details: Python 2.3.3 [GCC 3.3.1 (cygming special)]
							 | 
						||
| 
								 | 
							
								        #          ssh to Win32 machine from debian
							 | 
						||
| 
								 | 
							
								        #          curses.version is 2.2
							 | 
						||
| 
								 | 
							
								        #          CYGWIN_98-4.10, release 1.5.7(0.109/3/2))
							 | 
						||
| 
								 | 
							
								        return 0
							 | 
						||
| 
								 | 
							
								    if hasattr(sys.stdout, 'isatty') and sys.stdout.isatty():
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            import curses
							 | 
						||
| 
								 | 
							
								            curses.setupterm()
							 | 
						||
| 
								 | 
							
								            if (curses.tigetnum("colors") >= 0
							 | 
						||
| 
								 | 
							
								                and curses.tigetnum("pairs") >= 0
							 | 
						||
| 
								 | 
							
								                and ((curses.tigetstr("setf") is not None
							 | 
						||
| 
								 | 
							
								                      and curses.tigetstr("setb") is not None)
							 | 
						||
| 
								 | 
							
								                     or (curses.tigetstr("setaf") is not None
							 | 
						||
| 
								 | 
							
								                         and curses.tigetstr("setab") is not None)
							 | 
						||
| 
								 | 
							
								                     or curses.tigetstr("scp") is not None)):
							 | 
						||
| 
								 | 
							
								                return 1
							 | 
						||
| 
								 | 
							
								        except Exception:
							 | 
						||
| 
								 | 
							
								            pass
							 | 
						||
| 
								 | 
							
								    return 0
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if terminal_has_colors():
							 | 
						||
| 
								 | 
							
								    _colour_codes = dict(black=0, red=1, green=2, yellow=3,
							 | 
						||
| 
								 | 
							
								                         blue=4, magenta=5, cyan=6, white=7, default=9)
							 | 
						||
| 
								 | 
							
								    def colour_text(s, fg=None, bg=None, bold=False):
							 | 
						||
| 
								 | 
							
								        seq = []
							 | 
						||
| 
								 | 
							
								        if bold:
							 | 
						||
| 
								 | 
							
								            seq.append('1')
							 | 
						||
| 
								 | 
							
								        if fg:
							 | 
						||
| 
								 | 
							
								            fgcode = 30 + _colour_codes.get(fg.lower(), 0)
							 | 
						||
| 
								 | 
							
								            seq.append(str(fgcode))
							 | 
						||
| 
								 | 
							
								        if bg:
							 | 
						||
| 
								 | 
							
								            bgcode = 40 + _colour_codes.get(bg.lower(), 7)
							 | 
						||
| 
								 | 
							
								            seq.append(str(bgcode))
							 | 
						||
| 
								 | 
							
								        if seq:
							 | 
						||
| 
								 | 
							
								            return '\x1b[%sm%s\x1b[0m' % (';'.join(seq), s)
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            return s
							 | 
						||
| 
								 | 
							
								else:
							 | 
						||
| 
								 | 
							
								    def colour_text(s, fg=None, bg=None):
							 | 
						||
| 
								 | 
							
								        return s
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def default_text(s):
							 | 
						||
| 
								 | 
							
								    return colour_text(s, 'default')
							 | 
						||
| 
								 | 
							
								def red_text(s):
							 | 
						||
| 
								 | 
							
								    return colour_text(s, 'red')
							 | 
						||
| 
								 | 
							
								def green_text(s):
							 | 
						||
| 
								 | 
							
								    return colour_text(s, 'green')
							 | 
						||
| 
								 | 
							
								def yellow_text(s):
							 | 
						||
| 
								 | 
							
								    return colour_text(s, 'yellow')
							 | 
						||
| 
								 | 
							
								def cyan_text(s):
							 | 
						||
| 
								 | 
							
								    return colour_text(s, 'cyan')
							 | 
						||
| 
								 | 
							
								def blue_text(s):
							 | 
						||
| 
								 | 
							
								    return colour_text(s, 'blue')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#########################
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def cyg2win32(path: str) -> str:
							 | 
						||
| 
								 | 
							
								    """Convert a path from Cygwin-native to Windows-native.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Uses the cygpath utility (part of the Base install) to do the
							 | 
						||
| 
								 | 
							
								    actual conversion.  Falls back to returning the original path if
							 | 
						||
| 
								 | 
							
								    this fails.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Handles the default ``/cygdrive`` mount prefix as well as the
							 | 
						||
| 
								 | 
							
								    ``/proc/cygdrive`` portable prefix, custom cygdrive prefixes such
							 | 
						||
| 
								 | 
							
								    as ``/`` or ``/mnt``, and absolute paths such as ``/usr/src/`` or
							 | 
						||
| 
								 | 
							
								    ``/home/username``
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Parameters
							 | 
						||
| 
								 | 
							
								    ----------
							 | 
						||
| 
								 | 
							
								    path : str
							 | 
						||
| 
								 | 
							
								       The path to convert
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Returns
							 | 
						||
| 
								 | 
							
								    -------
							 | 
						||
| 
								 | 
							
								    converted_path : str
							 | 
						||
| 
								 | 
							
								        The converted path
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Notes
							 | 
						||
| 
								 | 
							
								    -----
							 | 
						||
| 
								 | 
							
								    Documentation for cygpath utility:
							 | 
						||
| 
								 | 
							
								    https://cygwin.com/cygwin-ug-net/cygpath.html
							 | 
						||
| 
								 | 
							
								    Documentation for the C function it wraps:
							 | 
						||
| 
								 | 
							
								    https://cygwin.com/cygwin-api/func-cygwin-conv-path.html
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    if sys.platform != "cygwin":
							 | 
						||
| 
								 | 
							
								        return path
							 | 
						||
| 
								 | 
							
								    return subprocess.check_output(
							 | 
						||
| 
								 | 
							
								        ["/usr/bin/cygpath", "--windows", path], text=True
							 | 
						||
| 
								 | 
							
								    )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def mingw32():
							 | 
						||
| 
								 | 
							
								    """Return true when using mingw32 environment.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    if sys.platform=='win32':
							 | 
						||
| 
								 | 
							
								        if os.environ.get('OSTYPE', '')=='msys':
							 | 
						||
| 
								 | 
							
								            return True
							 | 
						||
| 
								 | 
							
								        if os.environ.get('MSYSTEM', '')=='MINGW32':
							 | 
						||
| 
								 | 
							
								            return True
							 | 
						||
| 
								 | 
							
								    return False
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def msvc_runtime_version():
							 | 
						||
| 
								 | 
							
								    "Return version of MSVC runtime library, as defined by __MSC_VER__ macro"
							 | 
						||
| 
								 | 
							
								    msc_pos = sys.version.find('MSC v.')
							 | 
						||
| 
								 | 
							
								    if msc_pos != -1:
							 | 
						||
| 
								 | 
							
								        msc_ver = int(sys.version[msc_pos+6:msc_pos+10])
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        msc_ver = None
							 | 
						||
| 
								 | 
							
								    return msc_ver
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def msvc_runtime_library():
							 | 
						||
| 
								 | 
							
								    "Return name of MSVC runtime library if Python was built with MSVC >= 7"
							 | 
						||
| 
								 | 
							
								    ver = msvc_runtime_major ()
							 | 
						||
| 
								 | 
							
								    if ver:
							 | 
						||
| 
								 | 
							
								        if ver < 140:
							 | 
						||
| 
								 | 
							
								            return "msvcr%i" % ver
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            return "vcruntime%i" % ver
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        return None
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def msvc_runtime_major():
							 | 
						||
| 
								 | 
							
								    "Return major version of MSVC runtime coded like get_build_msvc_version"
							 | 
						||
| 
								 | 
							
								    major = {1300:  70,  # MSVC 7.0
							 | 
						||
| 
								 | 
							
								             1310:  71,  # MSVC 7.1
							 | 
						||
| 
								 | 
							
								             1400:  80,  # MSVC 8
							 | 
						||
| 
								 | 
							
								             1500:  90,  # MSVC 9  (aka 2008)
							 | 
						||
| 
								 | 
							
								             1600: 100,  # MSVC 10 (aka 2010)
							 | 
						||
| 
								 | 
							
								             1900: 140,  # MSVC 14 (aka 2015)
							 | 
						||
| 
								 | 
							
								    }.get(msvc_runtime_version(), None)
							 | 
						||
| 
								 | 
							
								    return major
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#########################
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#XXX need support for .C that is also C++
							 | 
						||
| 
								 | 
							
								cxx_ext_match = re.compile(r'.*\.(cpp|cxx|cc)\Z', re.I).match
							 | 
						||
| 
								 | 
							
								fortran_ext_match = re.compile(r'.*\.(f90|f95|f77|for|ftn|f)\Z', re.I).match
							 | 
						||
| 
								 | 
							
								f90_ext_match = re.compile(r'.*\.(f90|f95)\Z', re.I).match
							 | 
						||
| 
								 | 
							
								f90_module_name_match = re.compile(r'\s*module\s*(?P<name>[\w_]+)', re.I).match
							 | 
						||
| 
								 | 
							
								def _get_f90_modules(source):
							 | 
						||
| 
								 | 
							
								    """Return a list of Fortran f90 module names that
							 | 
						||
| 
								 | 
							
								    given source file defines.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    if not f90_ext_match(source):
							 | 
						||
| 
								 | 
							
								        return []
							 | 
						||
| 
								 | 
							
								    modules = []
							 | 
						||
| 
								 | 
							
								    with open(source, 'r') as f:
							 | 
						||
| 
								 | 
							
								        for line in f:
							 | 
						||
| 
								 | 
							
								            m = f90_module_name_match(line)
							 | 
						||
| 
								 | 
							
								            if m:
							 | 
						||
| 
								 | 
							
								                name = m.group('name')
							 | 
						||
| 
								 | 
							
								                modules.append(name)
							 | 
						||
| 
								 | 
							
								                # break  # XXX can we assume that there is one module per file?
							 | 
						||
| 
								 | 
							
								    return modules
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def is_string(s):
							 | 
						||
| 
								 | 
							
								    return isinstance(s, str)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def all_strings(lst):
							 | 
						||
| 
								 | 
							
								    """Return True if all items in lst are string objects. """
							 | 
						||
| 
								 | 
							
								    for item in lst:
							 | 
						||
| 
								 | 
							
								        if not is_string(item):
							 | 
						||
| 
								 | 
							
								            return False
							 | 
						||
| 
								 | 
							
								    return True
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def is_sequence(seq):
							 | 
						||
| 
								 | 
							
								    if is_string(seq):
							 | 
						||
| 
								 | 
							
								        return False
							 | 
						||
| 
								 | 
							
								    try:
							 | 
						||
| 
								 | 
							
								        len(seq)
							 | 
						||
| 
								 | 
							
								    except Exception:
							 | 
						||
| 
								 | 
							
								        return False
							 | 
						||
| 
								 | 
							
								    return True
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def is_glob_pattern(s):
							 | 
						||
| 
								 | 
							
								    return is_string(s) and ('*' in s or '?' in s)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def as_list(seq):
							 | 
						||
| 
								 | 
							
								    if is_sequence(seq):
							 | 
						||
| 
								 | 
							
								        return list(seq)
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        return [seq]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_language(sources):
							 | 
						||
| 
								 | 
							
								    # not used in numpy/scipy packages, use build_ext.detect_language instead
							 | 
						||
| 
								 | 
							
								    """Determine language value (c,f77,f90) from sources """
							 | 
						||
| 
								 | 
							
								    language = None
							 | 
						||
| 
								 | 
							
								    for source in sources:
							 | 
						||
| 
								 | 
							
								        if isinstance(source, str):
							 | 
						||
| 
								 | 
							
								            if f90_ext_match(source):
							 | 
						||
| 
								 | 
							
								                language = 'f90'
							 | 
						||
| 
								 | 
							
								                break
							 | 
						||
| 
								 | 
							
								            elif fortran_ext_match(source):
							 | 
						||
| 
								 | 
							
								                language = 'f77'
							 | 
						||
| 
								 | 
							
								    return language
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def has_f_sources(sources):
							 | 
						||
| 
								 | 
							
								    """Return True if sources contains Fortran files """
							 | 
						||
| 
								 | 
							
								    for source in sources:
							 | 
						||
| 
								 | 
							
								        if fortran_ext_match(source):
							 | 
						||
| 
								 | 
							
								            return True
							 | 
						||
| 
								 | 
							
								    return False
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def has_cxx_sources(sources):
							 | 
						||
| 
								 | 
							
								    """Return True if sources contains C++ files """
							 | 
						||
| 
								 | 
							
								    for source in sources:
							 | 
						||
| 
								 | 
							
								        if cxx_ext_match(source):
							 | 
						||
| 
								 | 
							
								            return True
							 | 
						||
| 
								 | 
							
								    return False
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def filter_sources(sources):
							 | 
						||
| 
								 | 
							
								    """Return four lists of filenames containing
							 | 
						||
| 
								 | 
							
								    C, C++, Fortran, and Fortran 90 module sources,
							 | 
						||
| 
								 | 
							
								    respectively.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    c_sources = []
							 | 
						||
| 
								 | 
							
								    cxx_sources = []
							 | 
						||
| 
								 | 
							
								    f_sources = []
							 | 
						||
| 
								 | 
							
								    fmodule_sources = []
							 | 
						||
| 
								 | 
							
								    for source in sources:
							 | 
						||
| 
								 | 
							
								        if fortran_ext_match(source):
							 | 
						||
| 
								 | 
							
								            modules = _get_f90_modules(source)
							 | 
						||
| 
								 | 
							
								            if modules:
							 | 
						||
| 
								 | 
							
								                fmodule_sources.append(source)
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                f_sources.append(source)
							 | 
						||
| 
								 | 
							
								        elif cxx_ext_match(source):
							 | 
						||
| 
								 | 
							
								            cxx_sources.append(source)
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            c_sources.append(source)
							 | 
						||
| 
								 | 
							
								    return c_sources, cxx_sources, f_sources, fmodule_sources
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def _get_headers(directory_list):
							 | 
						||
| 
								 | 
							
								    # get *.h files from list of directories
							 | 
						||
| 
								 | 
							
								    headers = []
							 | 
						||
| 
								 | 
							
								    for d in directory_list:
							 | 
						||
| 
								 | 
							
								        head = sorted_glob(os.path.join(d, "*.h")) #XXX: *.hpp files??
							 | 
						||
| 
								 | 
							
								        headers.extend(head)
							 | 
						||
| 
								 | 
							
								    return headers
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def _get_directories(list_of_sources):
							 | 
						||
| 
								 | 
							
								    # get unique directories from list of sources.
							 | 
						||
| 
								 | 
							
								    direcs = []
							 | 
						||
| 
								 | 
							
								    for f in list_of_sources:
							 | 
						||
| 
								 | 
							
								        d = os.path.split(f)
							 | 
						||
| 
								 | 
							
								        if d[0] != '' and not d[0] in direcs:
							 | 
						||
| 
								 | 
							
								            direcs.append(d[0])
							 | 
						||
| 
								 | 
							
								    return direcs
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def _commandline_dep_string(cc_args, extra_postargs, pp_opts):
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return commandline representation used to determine if a file needs
							 | 
						||
| 
								 | 
							
								    to be recompiled
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    cmdline = 'commandline: '
							 | 
						||
| 
								 | 
							
								    cmdline += ' '.join(cc_args)
							 | 
						||
| 
								 | 
							
								    cmdline += ' '.join(extra_postargs)
							 | 
						||
| 
								 | 
							
								    cmdline += ' '.join(pp_opts) + '\n'
							 | 
						||
| 
								 | 
							
								    return cmdline
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_dependencies(sources):
							 | 
						||
| 
								 | 
							
								    #XXX scan sources for include statements
							 | 
						||
| 
								 | 
							
								    return _get_headers(_get_directories(sources))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def is_local_src_dir(directory):
							 | 
						||
| 
								 | 
							
								    """Return true if directory is local directory.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    if not is_string(directory):
							 | 
						||
| 
								 | 
							
								        return False
							 | 
						||
| 
								 | 
							
								    abs_dir = os.path.abspath(directory)
							 | 
						||
| 
								 | 
							
								    c = os.path.commonprefix([os.getcwd(), abs_dir])
							 | 
						||
| 
								 | 
							
								    new_dir = abs_dir[len(c):].split(os.sep)
							 | 
						||
| 
								 | 
							
								    if new_dir and not new_dir[0]:
							 | 
						||
| 
								 | 
							
								        new_dir = new_dir[1:]
							 | 
						||
| 
								 | 
							
								    if new_dir and new_dir[0]=='build':
							 | 
						||
| 
								 | 
							
								        return False
							 | 
						||
| 
								 | 
							
								    new_dir = os.sep.join(new_dir)
							 | 
						||
| 
								 | 
							
								    return os.path.isdir(new_dir)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def general_source_files(top_path):
							 | 
						||
| 
								 | 
							
								    pruned_directories = {'CVS':1, '.svn':1, 'build':1}
							 | 
						||
| 
								 | 
							
								    prune_file_pat = re.compile(r'(?:[~#]|\.py[co]|\.o)$')
							 | 
						||
| 
								 | 
							
								    for dirpath, dirnames, filenames in os.walk(top_path, topdown=True):
							 | 
						||
| 
								 | 
							
								        pruned = [ d for d in dirnames if d not in pruned_directories ]
							 | 
						||
| 
								 | 
							
								        dirnames[:] = pruned
							 | 
						||
| 
								 | 
							
								        for f in filenames:
							 | 
						||
| 
								 | 
							
								            if not prune_file_pat.search(f):
							 | 
						||
| 
								 | 
							
								                yield os.path.join(dirpath, f)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def general_source_directories_files(top_path):
							 | 
						||
| 
								 | 
							
								    """Return a directory name relative to top_path and
							 | 
						||
| 
								 | 
							
								    files contained.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    pruned_directories = ['CVS', '.svn', 'build']
							 | 
						||
| 
								 | 
							
								    prune_file_pat = re.compile(r'(?:[~#]|\.py[co]|\.o)$')
							 | 
						||
| 
								 | 
							
								    for dirpath, dirnames, filenames in os.walk(top_path, topdown=True):
							 | 
						||
| 
								 | 
							
								        pruned = [ d for d in dirnames if d not in pruned_directories ]
							 | 
						||
| 
								 | 
							
								        dirnames[:] = pruned
							 | 
						||
| 
								 | 
							
								        for d in dirnames:
							 | 
						||
| 
								 | 
							
								            dpath = os.path.join(dirpath, d)
							 | 
						||
| 
								 | 
							
								            rpath = rel_path(dpath, top_path)
							 | 
						||
| 
								 | 
							
								            files = []
							 | 
						||
| 
								 | 
							
								            for f in os.listdir(dpath):
							 | 
						||
| 
								 | 
							
								                fn = os.path.join(dpath, f)
							 | 
						||
| 
								 | 
							
								                if os.path.isfile(fn) and not prune_file_pat.search(fn):
							 | 
						||
| 
								 | 
							
								                    files.append(fn)
							 | 
						||
| 
								 | 
							
								            yield rpath, files
							 | 
						||
| 
								 | 
							
								    dpath = top_path
							 | 
						||
| 
								 | 
							
								    rpath = rel_path(dpath, top_path)
							 | 
						||
| 
								 | 
							
								    filenames = [os.path.join(dpath, f) for f in os.listdir(dpath) \
							 | 
						||
| 
								 | 
							
								                 if not prune_file_pat.search(f)]
							 | 
						||
| 
								 | 
							
								    files = [f for f in filenames if os.path.isfile(f)]
							 | 
						||
| 
								 | 
							
								    yield rpath, files
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_ext_source_files(ext):
							 | 
						||
| 
								 | 
							
								    # Get sources and any include files in the same directory.
							 | 
						||
| 
								 | 
							
								    filenames = []
							 | 
						||
| 
								 | 
							
								    sources = [_m for _m in ext.sources if is_string(_m)]
							 | 
						||
| 
								 | 
							
								    filenames.extend(sources)
							 | 
						||
| 
								 | 
							
								    filenames.extend(get_dependencies(sources))
							 | 
						||
| 
								 | 
							
								    for d in ext.depends:
							 | 
						||
| 
								 | 
							
								        if is_local_src_dir(d):
							 | 
						||
| 
								 | 
							
								            filenames.extend(list(general_source_files(d)))
							 | 
						||
| 
								 | 
							
								        elif os.path.isfile(d):
							 | 
						||
| 
								 | 
							
								            filenames.append(d)
							 | 
						||
| 
								 | 
							
								    return filenames
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_script_files(scripts):
							 | 
						||
| 
								 | 
							
								    scripts = [_m for _m in scripts if is_string(_m)]
							 | 
						||
| 
								 | 
							
								    return scripts
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_lib_source_files(lib):
							 | 
						||
| 
								 | 
							
								    filenames = []
							 | 
						||
| 
								 | 
							
								    sources = lib[1].get('sources', [])
							 | 
						||
| 
								 | 
							
								    sources = [_m for _m in sources if is_string(_m)]
							 | 
						||
| 
								 | 
							
								    filenames.extend(sources)
							 | 
						||
| 
								 | 
							
								    filenames.extend(get_dependencies(sources))
							 | 
						||
| 
								 | 
							
								    depends = lib[1].get('depends', [])
							 | 
						||
| 
								 | 
							
								    for d in depends:
							 | 
						||
| 
								 | 
							
								        if is_local_src_dir(d):
							 | 
						||
| 
								 | 
							
								            filenames.extend(list(general_source_files(d)))
							 | 
						||
| 
								 | 
							
								        elif os.path.isfile(d):
							 | 
						||
| 
								 | 
							
								            filenames.append(d)
							 | 
						||
| 
								 | 
							
								    return filenames
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_shared_lib_extension(is_python_ext=False):
							 | 
						||
| 
								 | 
							
								    """Return the correct file extension for shared libraries.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Parameters
							 | 
						||
| 
								 | 
							
								    ----------
							 | 
						||
| 
								 | 
							
								    is_python_ext : bool, optional
							 | 
						||
| 
								 | 
							
								        Whether the shared library is a Python extension.  Default is False.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Returns
							 | 
						||
| 
								 | 
							
								    -------
							 | 
						||
| 
								 | 
							
								    so_ext : str
							 | 
						||
| 
								 | 
							
								        The shared library extension.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Notes
							 | 
						||
| 
								 | 
							
								    -----
							 | 
						||
| 
								 | 
							
								    For Python shared libs, `so_ext` will typically be '.so' on Linux and OS X,
							 | 
						||
| 
								 | 
							
								    and '.pyd' on Windows.  For Python >= 3.2 `so_ext` has a tag prepended on
							 | 
						||
| 
								 | 
							
								    POSIX systems according to PEP 3149.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    confvars = distutils.sysconfig.get_config_vars()
							 | 
						||
| 
								 | 
							
								    so_ext = confvars.get('EXT_SUFFIX', '')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if not is_python_ext:
							 | 
						||
| 
								 | 
							
								        # hardcode known values, config vars (including SHLIB_SUFFIX) are
							 | 
						||
| 
								 | 
							
								        # unreliable (see #3182)
							 | 
						||
| 
								 | 
							
								        # darwin, windows and debug linux are wrong in 3.3.1 and older
							 | 
						||
| 
								 | 
							
								        if (sys.platform.startswith('linux') or
							 | 
						||
| 
								 | 
							
								            sys.platform.startswith('gnukfreebsd')):
							 | 
						||
| 
								 | 
							
								            so_ext = '.so'
							 | 
						||
| 
								 | 
							
								        elif sys.platform.startswith('darwin'):
							 | 
						||
| 
								 | 
							
								            so_ext = '.dylib'
							 | 
						||
| 
								 | 
							
								        elif sys.platform.startswith('win'):
							 | 
						||
| 
								 | 
							
								            so_ext = '.dll'
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            # fall back to config vars for unknown platforms
							 | 
						||
| 
								 | 
							
								            # fix long extension for Python >=3.2, see PEP 3149.
							 | 
						||
| 
								 | 
							
								            if 'SOABI' in confvars:
							 | 
						||
| 
								 | 
							
								                # Does nothing unless SOABI config var exists
							 | 
						||
| 
								 | 
							
								                so_ext = so_ext.replace('.' + confvars.get('SOABI'), '', 1)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return so_ext
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_data_files(data):
							 | 
						||
| 
								 | 
							
								    if is_string(data):
							 | 
						||
| 
								 | 
							
								        return [data]
							 | 
						||
| 
								 | 
							
								    sources = data[1]
							 | 
						||
| 
								 | 
							
								    filenames = []
							 | 
						||
| 
								 | 
							
								    for s in sources:
							 | 
						||
| 
								 | 
							
								        if hasattr(s, '__call__'):
							 | 
						||
| 
								 | 
							
								            continue
							 | 
						||
| 
								 | 
							
								        if is_local_src_dir(s):
							 | 
						||
| 
								 | 
							
								            filenames.extend(list(general_source_files(s)))
							 | 
						||
| 
								 | 
							
								        elif is_string(s):
							 | 
						||
| 
								 | 
							
								            if os.path.isfile(s):
							 | 
						||
| 
								 | 
							
								                filenames.append(s)
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                print('Not existing data file:', s)
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            raise TypeError(repr(s))
							 | 
						||
| 
								 | 
							
								    return filenames
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def dot_join(*args):
							 | 
						||
| 
								 | 
							
								    return '.'.join([a for a in args if a])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_frame(level=0):
							 | 
						||
| 
								 | 
							
								    """Return frame object from call stack with given level.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    try:
							 | 
						||
| 
								 | 
							
								        return sys._getframe(level+1)
							 | 
						||
| 
								 | 
							
								    except AttributeError:
							 | 
						||
| 
								 | 
							
								        frame = sys.exc_info()[2].tb_frame
							 | 
						||
| 
								 | 
							
								        for _ in range(level+1):
							 | 
						||
| 
								 | 
							
								            frame = frame.f_back
							 | 
						||
| 
								 | 
							
								        return frame
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								######################
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class Configuration:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _list_keys = ['packages', 'ext_modules', 'data_files', 'include_dirs',
							 | 
						||
| 
								 | 
							
								                  'libraries', 'headers', 'scripts', 'py_modules',
							 | 
						||
| 
								 | 
							
								                  'installed_libraries', 'define_macros']
							 | 
						||
| 
								 | 
							
								    _dict_keys = ['package_dir', 'installed_pkg_config']
							 | 
						||
| 
								 | 
							
								    _extra_keys = ['name', 'version']
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    numpy_include_dirs = []
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __init__(self,
							 | 
						||
| 
								 | 
							
								                 package_name=None,
							 | 
						||
| 
								 | 
							
								                 parent_name=None,
							 | 
						||
| 
								 | 
							
								                 top_path=None,
							 | 
						||
| 
								 | 
							
								                 package_path=None,
							 | 
						||
| 
								 | 
							
								                 caller_level=1,
							 | 
						||
| 
								 | 
							
								                 setup_name='setup.py',
							 | 
						||
| 
								 | 
							
								                 **attrs):
							 | 
						||
| 
								 | 
							
								        """Construct configuration instance of a package.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        package_name -- name of the package
							 | 
						||
| 
								 | 
							
								                        Ex.: 'distutils'
							 | 
						||
| 
								 | 
							
								        parent_name  -- name of the parent package
							 | 
						||
| 
								 | 
							
								                        Ex.: 'numpy'
							 | 
						||
| 
								 | 
							
								        top_path     -- directory of the toplevel package
							 | 
						||
| 
								 | 
							
								                        Ex.: the directory where the numpy package source sits
							 | 
						||
| 
								 | 
							
								        package_path -- directory of package. Will be computed by magic from the
							 | 
						||
| 
								 | 
							
								                        directory of the caller module if not specified
							 | 
						||
| 
								 | 
							
								                        Ex.: the directory where numpy.distutils is
							 | 
						||
| 
								 | 
							
								        caller_level -- frame level to caller namespace, internal parameter.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        self.name = dot_join(parent_name, package_name)
							 | 
						||
| 
								 | 
							
								        self.version = None
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        caller_frame = get_frame(caller_level)
							 | 
						||
| 
								 | 
							
								        self.local_path = get_path_from_frame(caller_frame, top_path)
							 | 
						||
| 
								 | 
							
								        # local_path -- directory of a file (usually setup.py) that
							 | 
						||
| 
								 | 
							
								        #               defines a configuration() function.
							 | 
						||
| 
								 | 
							
								        # local_path -- directory of a file (usually setup.py) that
							 | 
						||
| 
								 | 
							
								        #               defines a configuration() function.
							 | 
						||
| 
								 | 
							
								        if top_path is None:
							 | 
						||
| 
								 | 
							
								            top_path = self.local_path
							 | 
						||
| 
								 | 
							
								            self.local_path = ''
							 | 
						||
| 
								 | 
							
								        if package_path is None:
							 | 
						||
| 
								 | 
							
								            package_path = self.local_path
							 | 
						||
| 
								 | 
							
								        elif os.path.isdir(njoin(self.local_path, package_path)):
							 | 
						||
| 
								 | 
							
								            package_path = njoin(self.local_path, package_path)
							 | 
						||
| 
								 | 
							
								        if not os.path.isdir(package_path or '.'):
							 | 
						||
| 
								 | 
							
								            raise ValueError("%r is not a directory" % (package_path,))
							 | 
						||
| 
								 | 
							
								        self.top_path = top_path
							 | 
						||
| 
								 | 
							
								        self.package_path = package_path
							 | 
						||
| 
								 | 
							
								        # this is the relative path in the installed package
							 | 
						||
| 
								 | 
							
								        self.path_in_package = os.path.join(*self.name.split('.'))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.list_keys = self._list_keys[:]
							 | 
						||
| 
								 | 
							
								        self.dict_keys = self._dict_keys[:]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for n in self.list_keys:
							 | 
						||
| 
								 | 
							
								            v = copy.copy(attrs.get(n, []))
							 | 
						||
| 
								 | 
							
								            setattr(self, n, as_list(v))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for n in self.dict_keys:
							 | 
						||
| 
								 | 
							
								            v = copy.copy(attrs.get(n, {}))
							 | 
						||
| 
								 | 
							
								            setattr(self, n, v)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        known_keys = self.list_keys + self.dict_keys
							 | 
						||
| 
								 | 
							
								        self.extra_keys = self._extra_keys[:]
							 | 
						||
| 
								 | 
							
								        for n in attrs.keys():
							 | 
						||
| 
								 | 
							
								            if n in known_keys:
							 | 
						||
| 
								 | 
							
								                continue
							 | 
						||
| 
								 | 
							
								            a = attrs[n]
							 | 
						||
| 
								 | 
							
								            setattr(self, n, a)
							 | 
						||
| 
								 | 
							
								            if isinstance(a, list):
							 | 
						||
| 
								 | 
							
								                self.list_keys.append(n)
							 | 
						||
| 
								 | 
							
								            elif isinstance(a, dict):
							 | 
						||
| 
								 | 
							
								                self.dict_keys.append(n)
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                self.extra_keys.append(n)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if os.path.exists(njoin(package_path, '__init__.py')):
							 | 
						||
| 
								 | 
							
								            self.packages.append(self.name)
							 | 
						||
| 
								 | 
							
								            self.package_dir[self.name] = package_path
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.options = dict(
							 | 
						||
| 
								 | 
							
								            ignore_setup_xxx_py = False,
							 | 
						||
| 
								 | 
							
								            assume_default_configuration = False,
							 | 
						||
| 
								 | 
							
								            delegate_options_to_subpackages = False,
							 | 
						||
| 
								 | 
							
								            quiet = False,
							 | 
						||
| 
								 | 
							
								            )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        caller_instance = None
							 | 
						||
| 
								 | 
							
								        for i in range(1, 3):
							 | 
						||
| 
								 | 
							
								            try:
							 | 
						||
| 
								 | 
							
								                f = get_frame(i)
							 | 
						||
| 
								 | 
							
								            except ValueError:
							 | 
						||
| 
								 | 
							
								                break
							 | 
						||
| 
								 | 
							
								            try:
							 | 
						||
| 
								 | 
							
								                caller_instance = eval('self', f.f_globals, f.f_locals)
							 | 
						||
| 
								 | 
							
								                break
							 | 
						||
| 
								 | 
							
								            except NameError:
							 | 
						||
| 
								 | 
							
								                pass
							 | 
						||
| 
								 | 
							
								        if isinstance(caller_instance, self.__class__):
							 | 
						||
| 
								 | 
							
								            if caller_instance.options['delegate_options_to_subpackages']:
							 | 
						||
| 
								 | 
							
								                self.set_options(**caller_instance.options)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.setup_name = setup_name
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def todict(self):
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return a dictionary compatible with the keyword arguments of distutils
							 | 
						||
| 
								 | 
							
								        setup function.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Examples
							 | 
						||
| 
								 | 
							
								        --------
							 | 
						||
| 
								 | 
							
								        >>> setup(**config.todict())                           #doctest: +SKIP
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self._optimize_data_files()
							 | 
						||
| 
								 | 
							
								        d = {}
							 | 
						||
| 
								 | 
							
								        known_keys = self.list_keys + self.dict_keys + self.extra_keys
							 | 
						||
| 
								 | 
							
								        for n in known_keys:
							 | 
						||
| 
								 | 
							
								            a = getattr(self, n)
							 | 
						||
| 
								 | 
							
								            if a:
							 | 
						||
| 
								 | 
							
								                d[n] = a
							 | 
						||
| 
								 | 
							
								        return d
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def info(self, message):
							 | 
						||
| 
								 | 
							
								        if not self.options['quiet']:
							 | 
						||
| 
								 | 
							
								            print(message)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def warn(self, message):
							 | 
						||
| 
								 | 
							
								        sys.stderr.write('Warning: %s\n' % (message,))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def set_options(self, **options):
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Configure Configuration instance.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        The following options are available:
							 | 
						||
| 
								 | 
							
								         - ignore_setup_xxx_py
							 | 
						||
| 
								 | 
							
								         - assume_default_configuration
							 | 
						||
| 
								 | 
							
								         - delegate_options_to_subpackages
							 | 
						||
| 
								 | 
							
								         - quiet
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        for key, value in options.items():
							 | 
						||
| 
								 | 
							
								            if key in self.options:
							 | 
						||
| 
								 | 
							
								                self.options[key] = value
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                raise ValueError('Unknown option: '+key)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def get_distribution(self):
							 | 
						||
| 
								 | 
							
								        """Return the distutils distribution object for self."""
							 | 
						||
| 
								 | 
							
								        from numpy.distutils.core import get_distribution
							 | 
						||
| 
								 | 
							
								        return get_distribution()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _wildcard_get_subpackage(self, subpackage_name,
							 | 
						||
| 
								 | 
							
								                                 parent_name,
							 | 
						||
| 
								 | 
							
								                                 caller_level = 1):
							 | 
						||
| 
								 | 
							
								        l = subpackage_name.split('.')
							 | 
						||
| 
								 | 
							
								        subpackage_path = njoin([self.local_path]+l)
							 | 
						||
| 
								 | 
							
								        dirs = [_m for _m in sorted_glob(subpackage_path) if os.path.isdir(_m)]
							 | 
						||
| 
								 | 
							
								        config_list = []
							 | 
						||
| 
								 | 
							
								        for d in dirs:
							 | 
						||
| 
								 | 
							
								            if not os.path.isfile(njoin(d, '__init__.py')):
							 | 
						||
| 
								 | 
							
								                continue
							 | 
						||
| 
								 | 
							
								            if 'build' in d.split(os.sep):
							 | 
						||
| 
								 | 
							
								                continue
							 | 
						||
| 
								 | 
							
								            n = '.'.join(d.split(os.sep)[-len(l):])
							 | 
						||
| 
								 | 
							
								            c = self.get_subpackage(n,
							 | 
						||
| 
								 | 
							
								                                    parent_name = parent_name,
							 | 
						||
| 
								 | 
							
								                                    caller_level = caller_level+1)
							 | 
						||
| 
								 | 
							
								            config_list.extend(c)
							 | 
						||
| 
								 | 
							
								        return config_list
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _get_configuration_from_setup_py(self, setup_py,
							 | 
						||
| 
								 | 
							
								                                         subpackage_name,
							 | 
						||
| 
								 | 
							
								                                         subpackage_path,
							 | 
						||
| 
								 | 
							
								                                         parent_name,
							 | 
						||
| 
								 | 
							
								                                         caller_level = 1):
							 | 
						||
| 
								 | 
							
								        # In case setup_py imports local modules:
							 | 
						||
| 
								 | 
							
								        sys.path.insert(0, os.path.dirname(setup_py))
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            setup_name = os.path.splitext(os.path.basename(setup_py))[0]
							 | 
						||
| 
								 | 
							
								            n = dot_join(self.name, subpackage_name, setup_name)
							 | 
						||
| 
								 | 
							
								            setup_module = exec_mod_from_location(
							 | 
						||
| 
								 | 
							
								                                '_'.join(n.split('.')), setup_py)
							 | 
						||
| 
								 | 
							
								            if not hasattr(setup_module, 'configuration'):
							 | 
						||
| 
								 | 
							
								                if not self.options['assume_default_configuration']:
							 | 
						||
| 
								 | 
							
								                    self.warn('Assuming default configuration '\
							 | 
						||
| 
								 | 
							
								                              '(%s does not define configuration())'\
							 | 
						||
| 
								 | 
							
								                              % (setup_module))
							 | 
						||
| 
								 | 
							
								                config = Configuration(subpackage_name, parent_name,
							 | 
						||
| 
								 | 
							
								                                       self.top_path, subpackage_path,
							 | 
						||
| 
								 | 
							
								                                       caller_level = caller_level + 1)
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                pn = dot_join(*([parent_name] + subpackage_name.split('.')[:-1]))
							 | 
						||
| 
								 | 
							
								                args = (pn,)
							 | 
						||
| 
								 | 
							
								                if setup_module.configuration.__code__.co_argcount > 1:
							 | 
						||
| 
								 | 
							
								                    args = args + (self.top_path,)
							 | 
						||
| 
								 | 
							
								                config = setup_module.configuration(*args)
							 | 
						||
| 
								 | 
							
								            if config.name!=dot_join(parent_name, subpackage_name):
							 | 
						||
| 
								 | 
							
								                self.warn('Subpackage %r configuration returned as %r' % \
							 | 
						||
| 
								 | 
							
								                          (dot_join(parent_name, subpackage_name), config.name))
							 | 
						||
| 
								 | 
							
								        finally:
							 | 
						||
| 
								 | 
							
								            del sys.path[0]
							 | 
						||
| 
								 | 
							
								        return config
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def get_subpackage(self,subpackage_name,
							 | 
						||
| 
								 | 
							
								                       subpackage_path=None,
							 | 
						||
| 
								 | 
							
								                       parent_name=None,
							 | 
						||
| 
								 | 
							
								                       caller_level = 1):
							 | 
						||
| 
								 | 
							
								        """Return list of subpackage configurations.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Parameters
							 | 
						||
| 
								 | 
							
								        ----------
							 | 
						||
| 
								 | 
							
								        subpackage_name : str or None
							 | 
						||
| 
								 | 
							
								            Name of the subpackage to get the configuration. '*' in
							 | 
						||
| 
								 | 
							
								            subpackage_name is handled as a wildcard.
							 | 
						||
| 
								 | 
							
								        subpackage_path : str
							 | 
						||
| 
								 | 
							
								            If None, then the path is assumed to be the local path plus the
							 | 
						||
| 
								 | 
							
								            subpackage_name. If a setup.py file is not found in the
							 | 
						||
| 
								 | 
							
								            subpackage_path, then a default configuration is used.
							 | 
						||
| 
								 | 
							
								        parent_name : str
							 | 
						||
| 
								 | 
							
								            Parent name.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        if subpackage_name is None:
							 | 
						||
| 
								 | 
							
								            if subpackage_path is None:
							 | 
						||
| 
								 | 
							
								                raise ValueError(
							 | 
						||
| 
								 | 
							
								                    "either subpackage_name or subpackage_path must be specified")
							 | 
						||
| 
								 | 
							
								            subpackage_name = os.path.basename(subpackage_path)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # handle wildcards
							 | 
						||
| 
								 | 
							
								        l = subpackage_name.split('.')
							 | 
						||
| 
								 | 
							
								        if subpackage_path is None and '*' in subpackage_name:
							 | 
						||
| 
								 | 
							
								            return self._wildcard_get_subpackage(subpackage_name,
							 | 
						||
| 
								 | 
							
								                                                 parent_name,
							 | 
						||
| 
								 | 
							
								                                                 caller_level = caller_level+1)
							 | 
						||
| 
								 | 
							
								        assert '*' not in subpackage_name, repr((subpackage_name, subpackage_path, parent_name))
							 | 
						||
| 
								 | 
							
								        if subpackage_path is None:
							 | 
						||
| 
								 | 
							
								            subpackage_path = njoin([self.local_path] + l)
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            subpackage_path = njoin([subpackage_path] + l[:-1])
							 | 
						||
| 
								 | 
							
								            subpackage_path = self.paths([subpackage_path])[0]
							 | 
						||
| 
								 | 
							
								        setup_py = njoin(subpackage_path, self.setup_name)
							 | 
						||
| 
								 | 
							
								        if not self.options['ignore_setup_xxx_py']:
							 | 
						||
| 
								 | 
							
								            if not os.path.isfile(setup_py):
							 | 
						||
| 
								 | 
							
								                setup_py = njoin(subpackage_path,
							 | 
						||
| 
								 | 
							
								                                 'setup_%s.py' % (subpackage_name))
							 | 
						||
| 
								 | 
							
								        if not os.path.isfile(setup_py):
							 | 
						||
| 
								 | 
							
								            if not self.options['assume_default_configuration']:
							 | 
						||
| 
								 | 
							
								                self.warn('Assuming default configuration '\
							 | 
						||
| 
								 | 
							
								                          '(%s/{setup_%s,setup}.py was not found)' \
							 | 
						||
| 
								 | 
							
								                          % (os.path.dirname(setup_py), subpackage_name))
							 | 
						||
| 
								 | 
							
								            config = Configuration(subpackage_name, parent_name,
							 | 
						||
| 
								 | 
							
								                                   self.top_path, subpackage_path,
							 | 
						||
| 
								 | 
							
								                                   caller_level = caller_level+1)
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            config = self._get_configuration_from_setup_py(
							 | 
						||
| 
								 | 
							
								                setup_py,
							 | 
						||
| 
								 | 
							
								                subpackage_name,
							 | 
						||
| 
								 | 
							
								                subpackage_path,
							 | 
						||
| 
								 | 
							
								                parent_name,
							 | 
						||
| 
								 | 
							
								                caller_level = caller_level + 1)
							 | 
						||
| 
								 | 
							
								        if config:
							 | 
						||
| 
								 | 
							
								            return [config]
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            return []
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def add_subpackage(self,subpackage_name,
							 | 
						||
| 
								 | 
							
								                       subpackage_path=None,
							 | 
						||
| 
								 | 
							
								                       standalone = False):
							 | 
						||
| 
								 | 
							
								        """Add a sub-package to the current Configuration instance.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        This is useful in a setup.py script for adding sub-packages to a
							 | 
						||
| 
								 | 
							
								        package.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Parameters
							 | 
						||
| 
								 | 
							
								        ----------
							 | 
						||
| 
								 | 
							
								        subpackage_name : str
							 | 
						||
| 
								 | 
							
								            name of the subpackage
							 | 
						||
| 
								 | 
							
								        subpackage_path : str
							 | 
						||
| 
								 | 
							
								            if given, the subpackage path such as the subpackage is in
							 | 
						||
| 
								 | 
							
								            subpackage_path / subpackage_name. If None,the subpackage is
							 | 
						||
| 
								 | 
							
								            assumed to be located in the local path / subpackage_name.
							 | 
						||
| 
								 | 
							
								        standalone : bool
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if standalone:
							 | 
						||
| 
								 | 
							
								            parent_name = None
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            parent_name = self.name
							 | 
						||
| 
								 | 
							
								        config_list = self.get_subpackage(subpackage_name, subpackage_path,
							 | 
						||
| 
								 | 
							
								                                          parent_name = parent_name,
							 | 
						||
| 
								 | 
							
								                                          caller_level = 2)
							 | 
						||
| 
								 | 
							
								        if not config_list:
							 | 
						||
| 
								 | 
							
								            self.warn('No configuration returned, assuming unavailable.')
							 | 
						||
| 
								 | 
							
								        for config in config_list:
							 | 
						||
| 
								 | 
							
								            d = config
							 | 
						||
| 
								 | 
							
								            if isinstance(config, Configuration):
							 | 
						||
| 
								 | 
							
								                d = config.todict()
							 | 
						||
| 
								 | 
							
								            assert isinstance(d, dict), repr(type(d))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            self.info('Appending %s configuration to %s' \
							 | 
						||
| 
								 | 
							
								                      % (d.get('name'), self.name))
							 | 
						||
| 
								 | 
							
								            self.dict_append(**d)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        dist = self.get_distribution()
							 | 
						||
| 
								 | 
							
								        if dist is not None:
							 | 
						||
| 
								 | 
							
								            self.warn('distutils distribution has been initialized,'\
							 | 
						||
| 
								 | 
							
								                      ' it may be too late to add a subpackage '+ subpackage_name)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def add_data_dir(self, data_path):
							 | 
						||
| 
								 | 
							
								        """Recursively add files under data_path to data_files list.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Recursively add files under data_path to the list of data_files to be
							 | 
						||
| 
								 | 
							
								        installed (and distributed). The data_path can be either a relative
							 | 
						||
| 
								 | 
							
								        path-name, or an absolute path-name, or a 2-tuple where the first
							 | 
						||
| 
								 | 
							
								        argument shows where in the install directory the data directory
							 | 
						||
| 
								 | 
							
								        should be installed to.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Parameters
							 | 
						||
| 
								 | 
							
								        ----------
							 | 
						||
| 
								 | 
							
								        data_path : seq or str
							 | 
						||
| 
								 | 
							
								            Argument can be either
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                * 2-sequence (<datadir suffix>, <path to data directory>)
							 | 
						||
| 
								 | 
							
								                * path to data directory where python datadir suffix defaults
							 | 
						||
| 
								 | 
							
								                  to package dir.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Notes
							 | 
						||
| 
								 | 
							
								        -----
							 | 
						||
| 
								 | 
							
								        Rules for installation paths::
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            foo/bar -> (foo/bar, foo/bar) -> parent/foo/bar
							 | 
						||
| 
								 | 
							
								            (gun, foo/bar) -> parent/gun
							 | 
						||
| 
								 | 
							
								            foo/* -> (foo/a, foo/a), (foo/b, foo/b) -> parent/foo/a, parent/foo/b
							 | 
						||
| 
								 | 
							
								            (gun, foo/*) -> (gun, foo/a), (gun, foo/b) -> gun
							 | 
						||
| 
								 | 
							
								            (gun/*, foo/*) -> parent/gun/a, parent/gun/b
							 | 
						||
| 
								 | 
							
								            /foo/bar -> (bar, /foo/bar) -> parent/bar
							 | 
						||
| 
								 | 
							
								            (gun, /foo/bar) -> parent/gun
							 | 
						||
| 
								 | 
							
								            (fun/*/gun/*, sun/foo/bar) -> parent/fun/foo/gun/bar
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Examples
							 | 
						||
| 
								 | 
							
								        --------
							 | 
						||
| 
								 | 
							
								        For example suppose the source directory contains fun/foo.dat and
							 | 
						||
| 
								 | 
							
								        fun/bar/car.dat:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        >>> self.add_data_dir('fun')                       #doctest: +SKIP
							 | 
						||
| 
								 | 
							
								        >>> self.add_data_dir(('sun', 'fun'))              #doctest: +SKIP
							 | 
						||
| 
								 | 
							
								        >>> self.add_data_dir(('gun', '/full/path/to/fun'))#doctest: +SKIP
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Will install data-files to the locations::
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            <package install directory>/
							 | 
						||
| 
								 | 
							
								              fun/
							 | 
						||
| 
								 | 
							
								                foo.dat
							 | 
						||
| 
								 | 
							
								                bar/
							 | 
						||
| 
								 | 
							
								                  car.dat
							 | 
						||
| 
								 | 
							
								              sun/
							 | 
						||
| 
								 | 
							
								                foo.dat
							 | 
						||
| 
								 | 
							
								                bar/
							 | 
						||
| 
								 | 
							
								                  car.dat
							 | 
						||
| 
								 | 
							
								              gun/
							 | 
						||
| 
								 | 
							
								                foo.dat
							 | 
						||
| 
								 | 
							
								                car.dat
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        if is_sequence(data_path):
							 | 
						||
| 
								 | 
							
								            d, data_path = data_path
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            d = None
							 | 
						||
| 
								 | 
							
								        if is_sequence(data_path):
							 | 
						||
| 
								 | 
							
								            [self.add_data_dir((d, p)) for p in data_path]
							 | 
						||
| 
								 | 
							
								            return
							 | 
						||
| 
								 | 
							
								        if not is_string(data_path):
							 | 
						||
| 
								 | 
							
								            raise TypeError("not a string: %r" % (data_path,))
							 | 
						||
| 
								 | 
							
								        if d is None:
							 | 
						||
| 
								 | 
							
								            if os.path.isabs(data_path):
							 | 
						||
| 
								 | 
							
								                return self.add_data_dir((os.path.basename(data_path), data_path))
							 | 
						||
| 
								 | 
							
								            return self.add_data_dir((data_path, data_path))
							 | 
						||
| 
								 | 
							
								        paths = self.paths(data_path, include_non_existing=False)
							 | 
						||
| 
								 | 
							
								        if is_glob_pattern(data_path):
							 | 
						||
| 
								 | 
							
								            if is_glob_pattern(d):
							 | 
						||
| 
								 | 
							
								                pattern_list = allpath(d).split(os.sep)
							 | 
						||
| 
								 | 
							
								                pattern_list.reverse()
							 | 
						||
| 
								 | 
							
								                # /a/*//b/ -> /a/*/b
							 | 
						||
| 
								 | 
							
								                rl = list(range(len(pattern_list)-1)); rl.reverse()
							 | 
						||
| 
								 | 
							
								                for i in rl:
							 | 
						||
| 
								 | 
							
								                    if not pattern_list[i]:
							 | 
						||
| 
								 | 
							
								                        del pattern_list[i]
							 | 
						||
| 
								 | 
							
								                #
							 | 
						||
| 
								 | 
							
								                for path in paths:
							 | 
						||
| 
								 | 
							
								                    if not os.path.isdir(path):
							 | 
						||
| 
								 | 
							
								                        print('Not a directory, skipping', path)
							 | 
						||
| 
								 | 
							
								                        continue
							 | 
						||
| 
								 | 
							
								                    rpath = rel_path(path, self.local_path)
							 | 
						||
| 
								 | 
							
								                    path_list = rpath.split(os.sep)
							 | 
						||
| 
								 | 
							
								                    path_list.reverse()
							 | 
						||
| 
								 | 
							
								                    target_list = []
							 | 
						||
| 
								 | 
							
								                    i = 0
							 | 
						||
| 
								 | 
							
								                    for s in pattern_list:
							 | 
						||
| 
								 | 
							
								                        if is_glob_pattern(s):
							 | 
						||
| 
								 | 
							
								                            if i>=len(path_list):
							 | 
						||
| 
								 | 
							
								                                raise ValueError('cannot fill pattern %r with %r' \
							 | 
						||
| 
								 | 
							
								                                      % (d, path))
							 | 
						||
| 
								 | 
							
								                            target_list.append(path_list[i])
							 | 
						||
| 
								 | 
							
								                        else:
							 | 
						||
| 
								 | 
							
								                            assert s==path_list[i], repr((s, path_list[i], data_path, d, path, rpath))
							 | 
						||
| 
								 | 
							
								                            target_list.append(s)
							 | 
						||
| 
								 | 
							
								                        i += 1
							 | 
						||
| 
								 | 
							
								                    if path_list[i:]:
							 | 
						||
| 
								 | 
							
								                        self.warn('mismatch of pattern_list=%s and path_list=%s'\
							 | 
						||
| 
								 | 
							
								                                  % (pattern_list, path_list))
							 | 
						||
| 
								 | 
							
								                    target_list.reverse()
							 | 
						||
| 
								 | 
							
								                    self.add_data_dir((os.sep.join(target_list), path))
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                for path in paths:
							 | 
						||
| 
								 | 
							
								                    self.add_data_dir((d, path))
							 | 
						||
| 
								 | 
							
								            return
							 | 
						||
| 
								 | 
							
								        assert not is_glob_pattern(d), repr(d)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        dist = self.get_distribution()
							 | 
						||
| 
								 | 
							
								        if dist is not None and dist.data_files is not None:
							 | 
						||
| 
								 | 
							
								            data_files = dist.data_files
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            data_files = self.data_files
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for path in paths:
							 | 
						||
| 
								 | 
							
								            for d1, f in list(general_source_directories_files(path)):
							 | 
						||
| 
								 | 
							
								                target_path = os.path.join(self.path_in_package, d, d1)
							 | 
						||
| 
								 | 
							
								                data_files.append((target_path, f))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _optimize_data_files(self):
							 | 
						||
| 
								 | 
							
								        data_dict = {}
							 | 
						||
| 
								 | 
							
								        for p, files in self.data_files:
							 | 
						||
| 
								 | 
							
								            if p not in data_dict:
							 | 
						||
| 
								 | 
							
								                data_dict[p] = set()
							 | 
						||
| 
								 | 
							
								            for f in files:
							 | 
						||
| 
								 | 
							
								                data_dict[p].add(f)
							 | 
						||
| 
								 | 
							
								        self.data_files[:] = [(p, list(files)) for p, files in data_dict.items()]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def add_data_files(self,*files):
							 | 
						||
| 
								 | 
							
								        """Add data files to configuration data_files.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Parameters
							 | 
						||
| 
								 | 
							
								        ----------
							 | 
						||
| 
								 | 
							
								        files : sequence
							 | 
						||
| 
								 | 
							
								            Argument(s) can be either
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                * 2-sequence (<datadir prefix>,<path to data file(s)>)
							 | 
						||
| 
								 | 
							
								                * paths to data files where python datadir prefix defaults
							 | 
						||
| 
								 | 
							
								                  to package dir.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Notes
							 | 
						||
| 
								 | 
							
								        -----
							 | 
						||
| 
								 | 
							
								        The form of each element of the files sequence is very flexible
							 | 
						||
| 
								 | 
							
								        allowing many combinations of where to get the files from the package
							 | 
						||
| 
								 | 
							
								        and where they should ultimately be installed on the system. The most
							 | 
						||
| 
								 | 
							
								        basic usage is for an element of the files argument sequence to be a
							 | 
						||
| 
								 | 
							
								        simple filename. This will cause that file from the local path to be
							 | 
						||
| 
								 | 
							
								        installed to the installation path of the self.name package (package
							 | 
						||
| 
								 | 
							
								        path). The file argument can also be a relative path in which case the
							 | 
						||
| 
								 | 
							
								        entire relative path will be installed into the package directory.
							 | 
						||
| 
								 | 
							
								        Finally, the file can be an absolute path name in which case the file
							 | 
						||
| 
								 | 
							
								        will be found at the absolute path name but installed to the package
							 | 
						||
| 
								 | 
							
								        path.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        This basic behavior can be augmented by passing a 2-tuple in as the
							 | 
						||
| 
								 | 
							
								        file argument. The first element of the tuple should specify the
							 | 
						||
| 
								 | 
							
								        relative path (under the package install directory) where the
							 | 
						||
| 
								 | 
							
								        remaining sequence of files should be installed to (it has nothing to
							 | 
						||
| 
								 | 
							
								        do with the file-names in the source distribution). The second element
							 | 
						||
| 
								 | 
							
								        of the tuple is the sequence of files that should be installed. The
							 | 
						||
| 
								 | 
							
								        files in this sequence can be filenames, relative paths, or absolute
							 | 
						||
| 
								 | 
							
								        paths. For absolute paths the file will be installed in the top-level
							 | 
						||
| 
								 | 
							
								        package installation directory (regardless of the first argument).
							 | 
						||
| 
								 | 
							
								        Filenames and relative path names will be installed in the package
							 | 
						||
| 
								 | 
							
								        install directory under the path name given as the first element of
							 | 
						||
| 
								 | 
							
								        the tuple.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Rules for installation paths:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          #. file.txt -> (., file.txt)-> parent/file.txt
							 | 
						||
| 
								 | 
							
								          #. foo/file.txt -> (foo, foo/file.txt) -> parent/foo/file.txt
							 | 
						||
| 
								 | 
							
								          #. /foo/bar/file.txt -> (., /foo/bar/file.txt) -> parent/file.txt
							 | 
						||
| 
								 | 
							
								          #. ``*``.txt -> parent/a.txt, parent/b.txt
							 | 
						||
| 
								 | 
							
								          #. foo/``*``.txt`` -> parent/foo/a.txt, parent/foo/b.txt
							 | 
						||
| 
								 | 
							
								          #. ``*/*.txt`` -> (``*``, ``*``/``*``.txt) -> parent/c/a.txt, parent/d/b.txt
							 | 
						||
| 
								 | 
							
								          #. (sun, file.txt) -> parent/sun/file.txt
							 | 
						||
| 
								 | 
							
								          #. (sun, bar/file.txt) -> parent/sun/file.txt
							 | 
						||
| 
								 | 
							
								          #. (sun, /foo/bar/file.txt) -> parent/sun/file.txt
							 | 
						||
| 
								 | 
							
								          #. (sun, ``*``.txt) -> parent/sun/a.txt, parent/sun/b.txt
							 | 
						||
| 
								 | 
							
								          #. (sun, bar/``*``.txt) -> parent/sun/a.txt, parent/sun/b.txt
							 | 
						||
| 
								 | 
							
								          #. (sun/``*``, ``*``/``*``.txt) -> parent/sun/c/a.txt, parent/d/b.txt
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        An additional feature is that the path to a data-file can actually be
							 | 
						||
| 
								 | 
							
								        a function that takes no arguments and returns the actual path(s) to
							 | 
						||
| 
								 | 
							
								        the data-files. This is useful when the data files are generated while
							 | 
						||
| 
								 | 
							
								        building the package.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Examples
							 | 
						||
| 
								 | 
							
								        --------
							 | 
						||
| 
								 | 
							
								        Add files to the list of data_files to be included with the package.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            >>> self.add_data_files('foo.dat',
							 | 
						||
| 
								 | 
							
								            ...     ('fun', ['gun.dat', 'nun/pun.dat', '/tmp/sun.dat']),
							 | 
						||
| 
								 | 
							
								            ...     'bar/cat.dat',
							 | 
						||
| 
								 | 
							
								            ...     '/full/path/to/can.dat')                   #doctest: +SKIP
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        will install these data files to::
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            <package install directory>/
							 | 
						||
| 
								 | 
							
								             foo.dat
							 | 
						||
| 
								 | 
							
								             fun/
							 | 
						||
| 
								 | 
							
								               gun.dat
							 | 
						||
| 
								 | 
							
								               nun/
							 | 
						||
| 
								 | 
							
								                 pun.dat
							 | 
						||
| 
								 | 
							
								             sun.dat
							 | 
						||
| 
								 | 
							
								             bar/
							 | 
						||
| 
								 | 
							
								               car.dat
							 | 
						||
| 
								 | 
							
								             can.dat
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        where <package install directory> is the package (or sub-package)
							 | 
						||
| 
								 | 
							
								        directory such as '/usr/lib/python2.4/site-packages/mypackage' ('C:
							 | 
						||
| 
								 | 
							
								        \\Python2.4 \\Lib \\site-packages \\mypackage') or
							 | 
						||
| 
								 | 
							
								        '/usr/lib/python2.4/site- packages/mypackage/mysubpackage' ('C:
							 | 
						||
| 
								 | 
							
								        \\Python2.4 \\Lib \\site-packages \\mypackage \\mysubpackage').
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if len(files)>1:
							 | 
						||
| 
								 | 
							
								            for f in files:
							 | 
						||
| 
								 | 
							
								                self.add_data_files(f)
							 | 
						||
| 
								 | 
							
								            return
							 | 
						||
| 
								 | 
							
								        assert len(files)==1
							 | 
						||
| 
								 | 
							
								        if is_sequence(files[0]):
							 | 
						||
| 
								 | 
							
								            d, files = files[0]
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            d = None
							 | 
						||
| 
								 | 
							
								        if is_string(files):
							 | 
						||
| 
								 | 
							
								            filepat = files
							 | 
						||
| 
								 | 
							
								        elif is_sequence(files):
							 | 
						||
| 
								 | 
							
								            if len(files)==1:
							 | 
						||
| 
								 | 
							
								                filepat = files[0]
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                for f in files:
							 | 
						||
| 
								 | 
							
								                    self.add_data_files((d, f))
							 | 
						||
| 
								 | 
							
								                return
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            raise TypeError(repr(type(files)))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if d is None:
							 | 
						||
| 
								 | 
							
								            if hasattr(filepat, '__call__'):
							 | 
						||
| 
								 | 
							
								                d = ''
							 | 
						||
| 
								 | 
							
								            elif os.path.isabs(filepat):
							 | 
						||
| 
								 | 
							
								                d = ''
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                d = os.path.dirname(filepat)
							 | 
						||
| 
								 | 
							
								            self.add_data_files((d, files))
							 | 
						||
| 
								 | 
							
								            return
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        paths = self.paths(filepat, include_non_existing=False)
							 | 
						||
| 
								 | 
							
								        if is_glob_pattern(filepat):
							 | 
						||
| 
								 | 
							
								            if is_glob_pattern(d):
							 | 
						||
| 
								 | 
							
								                pattern_list = d.split(os.sep)
							 | 
						||
| 
								 | 
							
								                pattern_list.reverse()
							 | 
						||
| 
								 | 
							
								                for path in paths:
							 | 
						||
| 
								 | 
							
								                    path_list = path.split(os.sep)
							 | 
						||
| 
								 | 
							
								                    path_list.reverse()
							 | 
						||
| 
								 | 
							
								                    path_list.pop() # filename
							 | 
						||
| 
								 | 
							
								                    target_list = []
							 | 
						||
| 
								 | 
							
								                    i = 0
							 | 
						||
| 
								 | 
							
								                    for s in pattern_list:
							 | 
						||
| 
								 | 
							
								                        if is_glob_pattern(s):
							 | 
						||
| 
								 | 
							
								                            target_list.append(path_list[i])
							 | 
						||
| 
								 | 
							
								                            i += 1
							 | 
						||
| 
								 | 
							
								                        else:
							 | 
						||
| 
								 | 
							
								                            target_list.append(s)
							 | 
						||
| 
								 | 
							
								                    target_list.reverse()
							 | 
						||
| 
								 | 
							
								                    self.add_data_files((os.sep.join(target_list), path))
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                self.add_data_files((d, paths))
							 | 
						||
| 
								 | 
							
								            return
							 | 
						||
| 
								 | 
							
								        assert not is_glob_pattern(d), repr((d, filepat))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        dist = self.get_distribution()
							 | 
						||
| 
								 | 
							
								        if dist is not None and dist.data_files is not None:
							 | 
						||
| 
								 | 
							
								            data_files = dist.data_files
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            data_files = self.data_files
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        data_files.append((os.path.join(self.path_in_package, d), paths))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ### XXX Implement add_py_modules
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def add_define_macros(self, macros):
							 | 
						||
| 
								 | 
							
								        """Add define macros to configuration
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Add the given sequence of macro name and value duples to the beginning
							 | 
						||
| 
								 | 
							
								        of the define_macros list This list will be visible to all extension
							 | 
						||
| 
								 | 
							
								        modules of the current package.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        dist = self.get_distribution()
							 | 
						||
| 
								 | 
							
								        if dist is not None:
							 | 
						||
| 
								 | 
							
								            if not hasattr(dist, 'define_macros'):
							 | 
						||
| 
								 | 
							
								                dist.define_macros = []
							 | 
						||
| 
								 | 
							
								            dist.define_macros.extend(macros)
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            self.define_macros.extend(macros)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def add_include_dirs(self,*paths):
							 | 
						||
| 
								 | 
							
								        """Add paths to configuration include directories.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Add the given sequence of paths to the beginning of the include_dirs
							 | 
						||
| 
								 | 
							
								        list. This list will be visible to all extension modules of the
							 | 
						||
| 
								 | 
							
								        current package.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        include_dirs = self.paths(paths)
							 | 
						||
| 
								 | 
							
								        dist = self.get_distribution()
							 | 
						||
| 
								 | 
							
								        if dist is not None:
							 | 
						||
| 
								 | 
							
								            if dist.include_dirs is None:
							 | 
						||
| 
								 | 
							
								                dist.include_dirs = []
							 | 
						||
| 
								 | 
							
								            dist.include_dirs.extend(include_dirs)
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            self.include_dirs.extend(include_dirs)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def add_headers(self,*files):
							 | 
						||
| 
								 | 
							
								        """Add installable headers to configuration.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Add the given sequence of files to the beginning of the headers list.
							 | 
						||
| 
								 | 
							
								        By default, headers will be installed under <python-
							 | 
						||
| 
								 | 
							
								        include>/<self.name.replace('.','/')>/ directory. If an item of files
							 | 
						||
| 
								 | 
							
								        is a tuple, then its first argument specifies the actual installation
							 | 
						||
| 
								 | 
							
								        location relative to the <python-include> path.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Parameters
							 | 
						||
| 
								 | 
							
								        ----------
							 | 
						||
| 
								 | 
							
								        files : str or seq
							 | 
						||
| 
								 | 
							
								            Argument(s) can be either:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                * 2-sequence (<includedir suffix>,<path to header file(s)>)
							 | 
						||
| 
								 | 
							
								                * path(s) to header file(s) where python includedir suffix will
							 | 
						||
| 
								 | 
							
								                  default to package name.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        headers = []
							 | 
						||
| 
								 | 
							
								        for path in files:
							 | 
						||
| 
								 | 
							
								            if is_string(path):
							 | 
						||
| 
								 | 
							
								                [headers.append((self.name, p)) for p in self.paths(path)]
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                if not isinstance(path, (tuple, list)) or len(path) != 2:
							 | 
						||
| 
								 | 
							
								                    raise TypeError(repr(path))
							 | 
						||
| 
								 | 
							
								                [headers.append((path[0], p)) for p in self.paths(path[1])]
							 | 
						||
| 
								 | 
							
								        dist = self.get_distribution()
							 | 
						||
| 
								 | 
							
								        if dist is not None:
							 | 
						||
| 
								 | 
							
								            if dist.headers is None:
							 | 
						||
| 
								 | 
							
								                dist.headers = []
							 | 
						||
| 
								 | 
							
								            dist.headers.extend(headers)
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            self.headers.extend(headers)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def paths(self,*paths,**kws):
							 | 
						||
| 
								 | 
							
								        """Apply glob to paths and prepend local_path if needed.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Applies glob.glob(...) to each path in the sequence (if needed) and
							 | 
						||
| 
								 | 
							
								        pre-pends the local_path if needed. Because this is called on all
							 | 
						||
| 
								 | 
							
								        source lists, this allows wildcard characters to be specified in lists
							 | 
						||
| 
								 | 
							
								        of sources for extension modules and libraries and scripts and allows
							 | 
						||
| 
								 | 
							
								        path-names be relative to the source directory.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        include_non_existing = kws.get('include_non_existing', True)
							 | 
						||
| 
								 | 
							
								        return gpaths(paths,
							 | 
						||
| 
								 | 
							
								                      local_path = self.local_path,
							 | 
						||
| 
								 | 
							
								                      include_non_existing=include_non_existing)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _fix_paths_dict(self, kw):
							 | 
						||
| 
								 | 
							
								        for k in kw.keys():
							 | 
						||
| 
								 | 
							
								            v = kw[k]
							 | 
						||
| 
								 | 
							
								            if k in ['sources', 'depends', 'include_dirs', 'library_dirs',
							 | 
						||
| 
								 | 
							
								                     'module_dirs', 'extra_objects']:
							 | 
						||
| 
								 | 
							
								                new_v = self.paths(v)
							 | 
						||
| 
								 | 
							
								                kw[k] = new_v
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def add_extension(self,name,sources,**kw):
							 | 
						||
| 
								 | 
							
								        """Add extension to configuration.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Create and add an Extension instance to the ext_modules list. This
							 | 
						||
| 
								 | 
							
								        method also takes the following optional keyword arguments that are
							 | 
						||
| 
								 | 
							
								        passed on to the Extension constructor.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Parameters
							 | 
						||
| 
								 | 
							
								        ----------
							 | 
						||
| 
								 | 
							
								        name : str
							 | 
						||
| 
								 | 
							
								            name of the extension
							 | 
						||
| 
								 | 
							
								        sources : seq
							 | 
						||
| 
								 | 
							
								            list of the sources. The list of sources may contain functions
							 | 
						||
| 
								 | 
							
								            (called source generators) which must take an extension instance
							 | 
						||
| 
								 | 
							
								            and a build directory as inputs and return a source file or list of
							 | 
						||
| 
								 | 
							
								            source files or None. If None is returned then no sources are
							 | 
						||
| 
								 | 
							
								            generated. If the Extension instance has no sources after
							 | 
						||
| 
								 | 
							
								            processing all source generators, then no extension module is
							 | 
						||
| 
								 | 
							
								            built.
							 | 
						||
| 
								 | 
							
								        include_dirs :
							 | 
						||
| 
								 | 
							
								        define_macros :
							 | 
						||
| 
								 | 
							
								        undef_macros :
							 | 
						||
| 
								 | 
							
								        library_dirs :
							 | 
						||
| 
								 | 
							
								        libraries :
							 | 
						||
| 
								 | 
							
								        runtime_library_dirs :
							 | 
						||
| 
								 | 
							
								        extra_objects :
							 | 
						||
| 
								 | 
							
								        extra_compile_args :
							 | 
						||
| 
								 | 
							
								        extra_link_args :
							 | 
						||
| 
								 | 
							
								        extra_f77_compile_args :
							 | 
						||
| 
								 | 
							
								        extra_f90_compile_args :
							 | 
						||
| 
								 | 
							
								        export_symbols :
							 | 
						||
| 
								 | 
							
								        swig_opts :
							 | 
						||
| 
								 | 
							
								        depends :
							 | 
						||
| 
								 | 
							
								            The depends list contains paths to files or directories that the
							 | 
						||
| 
								 | 
							
								            sources of the extension module depend on. If any path in the
							 | 
						||
| 
								 | 
							
								            depends list is newer than the extension module, then the module
							 | 
						||
| 
								 | 
							
								            will be rebuilt.
							 | 
						||
| 
								 | 
							
								        language :
							 | 
						||
| 
								 | 
							
								        f2py_options :
							 | 
						||
| 
								 | 
							
								        module_dirs :
							 | 
						||
| 
								 | 
							
								        extra_info : dict or list
							 | 
						||
| 
								 | 
							
								            dict or list of dict of keywords to be appended to keywords.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Notes
							 | 
						||
| 
								 | 
							
								        -----
							 | 
						||
| 
								 | 
							
								        The self.paths(...) method is applied to all lists that may contain
							 | 
						||
| 
								 | 
							
								        paths.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        ext_args = copy.copy(kw)
							 | 
						||
| 
								 | 
							
								        ext_args['name'] = dot_join(self.name, name)
							 | 
						||
| 
								 | 
							
								        ext_args['sources'] = sources
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if 'extra_info' in ext_args:
							 | 
						||
| 
								 | 
							
								            extra_info = ext_args['extra_info']
							 | 
						||
| 
								 | 
							
								            del ext_args['extra_info']
							 | 
						||
| 
								 | 
							
								            if isinstance(extra_info, dict):
							 | 
						||
| 
								 | 
							
								                extra_info = [extra_info]
							 | 
						||
| 
								 | 
							
								            for info in extra_info:
							 | 
						||
| 
								 | 
							
								                assert isinstance(info, dict), repr(info)
							 | 
						||
| 
								 | 
							
								                dict_append(ext_args,**info)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self._fix_paths_dict(ext_args)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # Resolve out-of-tree dependencies
							 | 
						||
| 
								 | 
							
								        libraries = ext_args.get('libraries', [])
							 | 
						||
| 
								 | 
							
								        libnames = []
							 | 
						||
| 
								 | 
							
								        ext_args['libraries'] = []
							 | 
						||
| 
								 | 
							
								        for libname in libraries:
							 | 
						||
| 
								 | 
							
								            if isinstance(libname, tuple):
							 | 
						||
| 
								 | 
							
								                self._fix_paths_dict(libname[1])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            # Handle library names of the form libname@relative/path/to/library
							 | 
						||
| 
								 | 
							
								            if '@' in libname:
							 | 
						||
| 
								 | 
							
								                lname, lpath = libname.split('@', 1)
							 | 
						||
| 
								 | 
							
								                lpath = os.path.abspath(njoin(self.local_path, lpath))
							 | 
						||
| 
								 | 
							
								                if os.path.isdir(lpath):
							 | 
						||
| 
								 | 
							
								                    c = self.get_subpackage(None, lpath,
							 | 
						||
| 
								 | 
							
								                                            caller_level = 2)
							 | 
						||
| 
								 | 
							
								                    if isinstance(c, Configuration):
							 | 
						||
| 
								 | 
							
								                        c = c.todict()
							 | 
						||
| 
								 | 
							
								                    for l in [l[0] for l in c.get('libraries', [])]:
							 | 
						||
| 
								 | 
							
								                        llname = l.split('__OF__', 1)[0]
							 | 
						||
| 
								 | 
							
								                        if llname == lname:
							 | 
						||
| 
								 | 
							
								                            c.pop('name', None)
							 | 
						||
| 
								 | 
							
								                            dict_append(ext_args,**c)
							 | 
						||
| 
								 | 
							
								                            break
							 | 
						||
| 
								 | 
							
								                    continue
							 | 
						||
| 
								 | 
							
								            libnames.append(libname)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        ext_args['libraries'] = libnames + ext_args['libraries']
							 | 
						||
| 
								 | 
							
								        ext_args['define_macros'] = \
							 | 
						||
| 
								 | 
							
								            self.define_macros + ext_args.get('define_macros', [])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        from numpy.distutils.core import Extension
							 | 
						||
| 
								 | 
							
								        ext = Extension(**ext_args)
							 | 
						||
| 
								 | 
							
								        self.ext_modules.append(ext)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        dist = self.get_distribution()
							 | 
						||
| 
								 | 
							
								        if dist is not None:
							 | 
						||
| 
								 | 
							
								            self.warn('distutils distribution has been initialized,'\
							 | 
						||
| 
								 | 
							
								                      ' it may be too late to add an extension '+name)
							 | 
						||
| 
								 | 
							
								        return ext
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def add_library(self,name,sources,**build_info):
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Add library to configuration.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Parameters
							 | 
						||
| 
								 | 
							
								        ----------
							 | 
						||
| 
								 | 
							
								        name : str
							 | 
						||
| 
								 | 
							
								            Name of the extension.
							 | 
						||
| 
								 | 
							
								        sources : sequence
							 | 
						||
| 
								 | 
							
								            List of the sources. The list of sources may contain functions
							 | 
						||
| 
								 | 
							
								            (called source generators) which must take an extension instance
							 | 
						||
| 
								 | 
							
								            and a build directory as inputs and return a source file or list of
							 | 
						||
| 
								 | 
							
								            source files or None. If None is returned then no sources are
							 | 
						||
| 
								 | 
							
								            generated. If the Extension instance has no sources after
							 | 
						||
| 
								 | 
							
								            processing all source generators, then no extension module is
							 | 
						||
| 
								 | 
							
								            built.
							 | 
						||
| 
								 | 
							
								        build_info : dict, optional
							 | 
						||
| 
								 | 
							
								            The following keys are allowed:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                * depends
							 | 
						||
| 
								 | 
							
								                * macros
							 | 
						||
| 
								 | 
							
								                * include_dirs
							 | 
						||
| 
								 | 
							
								                * extra_compiler_args
							 | 
						||
| 
								 | 
							
								                * extra_f77_compile_args
							 | 
						||
| 
								 | 
							
								                * extra_f90_compile_args
							 | 
						||
| 
								 | 
							
								                * f2py_options
							 | 
						||
| 
								 | 
							
								                * language
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        self._add_library(name, sources, None, build_info)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        dist = self.get_distribution()
							 | 
						||
| 
								 | 
							
								        if dist is not None:
							 | 
						||
| 
								 | 
							
								            self.warn('distutils distribution has been initialized,'\
							 | 
						||
| 
								 | 
							
								                      ' it may be too late to add a library '+ name)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _add_library(self, name, sources, install_dir, build_info):
							 | 
						||
| 
								 | 
							
								        """Common implementation for add_library and add_installed_library. Do
							 | 
						||
| 
								 | 
							
								        not use directly"""
							 | 
						||
| 
								 | 
							
								        build_info = copy.copy(build_info)
							 | 
						||
| 
								 | 
							
								        build_info['sources'] = sources
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # Sometimes, depends is not set up to an empty list by default, and if
							 | 
						||
| 
								 | 
							
								        # depends is not given to add_library, distutils barfs (#1134)
							 | 
						||
| 
								 | 
							
								        if not 'depends' in build_info:
							 | 
						||
| 
								 | 
							
								            build_info['depends'] = []
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self._fix_paths_dict(build_info)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # Add to libraries list so that it is build with build_clib
							 | 
						||
| 
								 | 
							
								        self.libraries.append((name, build_info))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def add_installed_library(self, name, sources, install_dir, build_info=None):
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Similar to add_library, but the specified library is installed.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Most C libraries used with `distutils` are only used to build python
							 | 
						||
| 
								 | 
							
								        extensions, but libraries built through this method will be installed
							 | 
						||
| 
								 | 
							
								        so that they can be reused by third-party packages.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Parameters
							 | 
						||
| 
								 | 
							
								        ----------
							 | 
						||
| 
								 | 
							
								        name : str
							 | 
						||
| 
								 | 
							
								            Name of the installed library.
							 | 
						||
| 
								 | 
							
								        sources : sequence
							 | 
						||
| 
								 | 
							
								            List of the library's source files. See `add_library` for details.
							 | 
						||
| 
								 | 
							
								        install_dir : str
							 | 
						||
| 
								 | 
							
								            Path to install the library, relative to the current sub-package.
							 | 
						||
| 
								 | 
							
								        build_info : dict, optional
							 | 
						||
| 
								 | 
							
								            The following keys are allowed:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                * depends
							 | 
						||
| 
								 | 
							
								                * macros
							 | 
						||
| 
								 | 
							
								                * include_dirs
							 | 
						||
| 
								 | 
							
								                * extra_compiler_args
							 | 
						||
| 
								 | 
							
								                * extra_f77_compile_args
							 | 
						||
| 
								 | 
							
								                * extra_f90_compile_args
							 | 
						||
| 
								 | 
							
								                * f2py_options
							 | 
						||
| 
								 | 
							
								                * language
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Returns
							 | 
						||
| 
								 | 
							
								        -------
							 | 
						||
| 
								 | 
							
								        None
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        See Also
							 | 
						||
| 
								 | 
							
								        --------
							 | 
						||
| 
								 | 
							
								        add_library, add_npy_pkg_config, get_info
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Notes
							 | 
						||
| 
								 | 
							
								        -----
							 | 
						||
| 
								 | 
							
								        The best way to encode the options required to link against the specified
							 | 
						||
| 
								 | 
							
								        C libraries is to use a "libname.ini" file, and use `get_info` to
							 | 
						||
| 
								 | 
							
								        retrieve the required options (see `add_npy_pkg_config` for more
							 | 
						||
| 
								 | 
							
								        information).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        if not build_info:
							 | 
						||
| 
								 | 
							
								            build_info = {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        install_dir = os.path.join(self.package_path, install_dir)
							 | 
						||
| 
								 | 
							
								        self._add_library(name, sources, install_dir, build_info)
							 | 
						||
| 
								 | 
							
								        self.installed_libraries.append(InstallableLib(name, build_info, install_dir))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def add_npy_pkg_config(self, template, install_dir, subst_dict=None):
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Generate and install a npy-pkg config file from a template.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        The config file generated from `template` is installed in the
							 | 
						||
| 
								 | 
							
								        given install directory, using `subst_dict` for variable substitution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Parameters
							 | 
						||
| 
								 | 
							
								        ----------
							 | 
						||
| 
								 | 
							
								        template : str
							 | 
						||
| 
								 | 
							
								            The path of the template, relatively to the current package path.
							 | 
						||
| 
								 | 
							
								        install_dir : str
							 | 
						||
| 
								 | 
							
								            Where to install the npy-pkg config file, relatively to the current
							 | 
						||
| 
								 | 
							
								            package path.
							 | 
						||
| 
								 | 
							
								        subst_dict : dict, optional
							 | 
						||
| 
								 | 
							
								            If given, any string of the form ``@key@`` will be replaced by
							 | 
						||
| 
								 | 
							
								            ``subst_dict[key]`` in the template file when installed. The install
							 | 
						||
| 
								 | 
							
								            prefix is always available through the variable ``@prefix@``, since the
							 | 
						||
| 
								 | 
							
								            install prefix is not easy to get reliably from setup.py.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        See also
							 | 
						||
| 
								 | 
							
								        --------
							 | 
						||
| 
								 | 
							
								        add_installed_library, get_info
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Notes
							 | 
						||
| 
								 | 
							
								        -----
							 | 
						||
| 
								 | 
							
								        This works for both standard installs and in-place builds, i.e. the
							 | 
						||
| 
								 | 
							
								        ``@prefix@`` refer to the source directory for in-place builds.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Examples
							 | 
						||
| 
								 | 
							
								        --------
							 | 
						||
| 
								 | 
							
								        ::
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            config.add_npy_pkg_config('foo.ini.in', 'lib', {'foo': bar})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Assuming the foo.ini.in file has the following content::
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            [meta]
							 | 
						||
| 
								 | 
							
								            Name=@foo@
							 | 
						||
| 
								 | 
							
								            Version=1.0
							 | 
						||
| 
								 | 
							
								            Description=dummy description
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            [default]
							 | 
						||
| 
								 | 
							
								            Cflags=-I@prefix@/include
							 | 
						||
| 
								 | 
							
								            Libs=
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        The generated file will have the following content::
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            [meta]
							 | 
						||
| 
								 | 
							
								            Name=bar
							 | 
						||
| 
								 | 
							
								            Version=1.0
							 | 
						||
| 
								 | 
							
								            Description=dummy description
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            [default]
							 | 
						||
| 
								 | 
							
								            Cflags=-Iprefix_dir/include
							 | 
						||
| 
								 | 
							
								            Libs=
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        and will be installed as foo.ini in the 'lib' subpath.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        When cross-compiling with numpy distutils, it might be necessary to
							 | 
						||
| 
								 | 
							
								        use modified npy-pkg-config files.  Using the default/generated files
							 | 
						||
| 
								 | 
							
								        will link with the host libraries (i.e. libnpymath.a).  For
							 | 
						||
| 
								 | 
							
								        cross-compilation you of-course need to link with target libraries,
							 | 
						||
| 
								 | 
							
								        while using the host Python installation.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        You can copy out the numpy/core/lib/npy-pkg-config directory, add a
							 | 
						||
| 
								 | 
							
								        pkgdir value to the .ini files and set NPY_PKG_CONFIG_PATH environment
							 | 
						||
| 
								 | 
							
								        variable to point to the directory with the modified npy-pkg-config
							 | 
						||
| 
								 | 
							
								        files.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Example npymath.ini modified for cross-compilation::
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            [meta]
							 | 
						||
| 
								 | 
							
								            Name=npymath
							 | 
						||
| 
								 | 
							
								            Description=Portable, core math library implementing C99 standard
							 | 
						||
| 
								 | 
							
								            Version=0.1
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            [variables]
							 | 
						||
| 
								 | 
							
								            pkgname=numpy.core
							 | 
						||
| 
								 | 
							
								            pkgdir=/build/arm-linux-gnueabi/sysroot/usr/lib/python3.7/site-packages/numpy/core
							 | 
						||
| 
								 | 
							
								            prefix=${pkgdir}
							 | 
						||
| 
								 | 
							
								            libdir=${prefix}/lib
							 | 
						||
| 
								 | 
							
								            includedir=${prefix}/include
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            [default]
							 | 
						||
| 
								 | 
							
								            Libs=-L${libdir} -lnpymath
							 | 
						||
| 
								 | 
							
								            Cflags=-I${includedir}
							 | 
						||
| 
								 | 
							
								            Requires=mlib
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            [msvc]
							 | 
						||
| 
								 | 
							
								            Libs=/LIBPATH:${libdir} npymath.lib
							 | 
						||
| 
								 | 
							
								            Cflags=/INCLUDE:${includedir}
							 | 
						||
| 
								 | 
							
								            Requires=mlib
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        if subst_dict is None:
							 | 
						||
| 
								 | 
							
								            subst_dict = {}
							 | 
						||
| 
								 | 
							
								        template = os.path.join(self.package_path, template)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if self.name in self.installed_pkg_config:
							 | 
						||
| 
								 | 
							
								            self.installed_pkg_config[self.name].append((template, install_dir,
							 | 
						||
| 
								 | 
							
								                subst_dict))
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            self.installed_pkg_config[self.name] = [(template, install_dir,
							 | 
						||
| 
								 | 
							
								                subst_dict)]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def add_scripts(self,*files):
							 | 
						||
| 
								 | 
							
								        """Add scripts to configuration.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Add the sequence of files to the beginning of the scripts list.
							 | 
						||
| 
								 | 
							
								        Scripts will be installed under the <prefix>/bin/ directory.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        scripts = self.paths(files)
							 | 
						||
| 
								 | 
							
								        dist = self.get_distribution()
							 | 
						||
| 
								 | 
							
								        if dist is not None:
							 | 
						||
| 
								 | 
							
								            if dist.scripts is None:
							 | 
						||
| 
								 | 
							
								                dist.scripts = []
							 | 
						||
| 
								 | 
							
								            dist.scripts.extend(scripts)
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            self.scripts.extend(scripts)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def dict_append(self,**dict):
							 | 
						||
| 
								 | 
							
								        for key in self.list_keys:
							 | 
						||
| 
								 | 
							
								            a = getattr(self, key)
							 | 
						||
| 
								 | 
							
								            a.extend(dict.get(key, []))
							 | 
						||
| 
								 | 
							
								        for key in self.dict_keys:
							 | 
						||
| 
								 | 
							
								            a = getattr(self, key)
							 | 
						||
| 
								 | 
							
								            a.update(dict.get(key, {}))
							 | 
						||
| 
								 | 
							
								        known_keys = self.list_keys + self.dict_keys + self.extra_keys
							 | 
						||
| 
								 | 
							
								        for key in dict.keys():
							 | 
						||
| 
								 | 
							
								            if key not in known_keys:
							 | 
						||
| 
								 | 
							
								                a = getattr(self, key, None)
							 | 
						||
| 
								 | 
							
								                if a and a==dict[key]: continue
							 | 
						||
| 
								 | 
							
								                self.warn('Inheriting attribute %r=%r from %r' \
							 | 
						||
| 
								 | 
							
								                          % (key, dict[key], dict.get('name', '?')))
							 | 
						||
| 
								 | 
							
								                setattr(self, key, dict[key])
							 | 
						||
| 
								 | 
							
								                self.extra_keys.append(key)
							 | 
						||
| 
								 | 
							
								            elif key in self.extra_keys:
							 | 
						||
| 
								 | 
							
								                self.info('Ignoring attempt to set %r (from %r to %r)' \
							 | 
						||
| 
								 | 
							
								                          % (key, getattr(self, key), dict[key]))
							 | 
						||
| 
								 | 
							
								            elif key in known_keys:
							 | 
						||
| 
								 | 
							
								                # key is already processed above
							 | 
						||
| 
								 | 
							
								                pass
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                raise ValueError("Don't know about key=%r" % (key))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __str__(self):
							 | 
						||
| 
								 | 
							
								        from pprint import pformat
							 | 
						||
| 
								 | 
							
								        known_keys = self.list_keys + self.dict_keys + self.extra_keys
							 | 
						||
| 
								 | 
							
								        s = '<'+5*'-' + '\n'
							 | 
						||
| 
								 | 
							
								        s += 'Configuration of '+self.name+':\n'
							 | 
						||
| 
								 | 
							
								        known_keys.sort()
							 | 
						||
| 
								 | 
							
								        for k in known_keys:
							 | 
						||
| 
								 | 
							
								            a = getattr(self, k, None)
							 | 
						||
| 
								 | 
							
								            if a:
							 | 
						||
| 
								 | 
							
								                s += '%s = %s\n' % (k, pformat(a))
							 | 
						||
| 
								 | 
							
								        s += 5*'-' + '>'
							 | 
						||
| 
								 | 
							
								        return s
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def get_config_cmd(self):
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Returns the numpy.distutils config command instance.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        cmd = get_cmd('config')
							 | 
						||
| 
								 | 
							
								        cmd.ensure_finalized()
							 | 
						||
| 
								 | 
							
								        cmd.dump_source = 0
							 | 
						||
| 
								 | 
							
								        cmd.noisy = 0
							 | 
						||
| 
								 | 
							
								        old_path = os.environ.get('PATH')
							 | 
						||
| 
								 | 
							
								        if old_path:
							 | 
						||
| 
								 | 
							
								            path = os.pathsep.join(['.', old_path])
							 | 
						||
| 
								 | 
							
								            os.environ['PATH'] = path
							 | 
						||
| 
								 | 
							
								        return cmd
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def get_build_temp_dir(self):
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return a path to a temporary directory where temporary files should be
							 | 
						||
| 
								 | 
							
								        placed.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        cmd = get_cmd('build')
							 | 
						||
| 
								 | 
							
								        cmd.ensure_finalized()
							 | 
						||
| 
								 | 
							
								        return cmd.build_temp
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def have_f77c(self):
							 | 
						||
| 
								 | 
							
								        """Check for availability of Fortran 77 compiler.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Use it inside source generating function to ensure that
							 | 
						||
| 
								 | 
							
								        setup distribution instance has been initialized.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Notes
							 | 
						||
| 
								 | 
							
								        -----
							 | 
						||
| 
								 | 
							
								        True if a Fortran 77 compiler is available (because a simple Fortran 77
							 | 
						||
| 
								 | 
							
								        code was able to be compiled successfully).
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        simple_fortran_subroutine = '''
							 | 
						||
| 
								 | 
							
								        subroutine simple
							 | 
						||
| 
								 | 
							
								        end
							 | 
						||
| 
								 | 
							
								        '''
							 | 
						||
| 
								 | 
							
								        config_cmd = self.get_config_cmd()
							 | 
						||
| 
								 | 
							
								        flag = config_cmd.try_compile(simple_fortran_subroutine, lang='f77')
							 | 
						||
| 
								 | 
							
								        return flag
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def have_f90c(self):
							 | 
						||
| 
								 | 
							
								        """Check for availability of Fortran 90 compiler.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Use it inside source generating function to ensure that
							 | 
						||
| 
								 | 
							
								        setup distribution instance has been initialized.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Notes
							 | 
						||
| 
								 | 
							
								        -----
							 | 
						||
| 
								 | 
							
								        True if a Fortran 90 compiler is available (because a simple Fortran
							 | 
						||
| 
								 | 
							
								        90 code was able to be compiled successfully)
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        simple_fortran_subroutine = '''
							 | 
						||
| 
								 | 
							
								        subroutine simple
							 | 
						||
| 
								 | 
							
								        end
							 | 
						||
| 
								 | 
							
								        '''
							 | 
						||
| 
								 | 
							
								        config_cmd = self.get_config_cmd()
							 | 
						||
| 
								 | 
							
								        flag = config_cmd.try_compile(simple_fortran_subroutine, lang='f90')
							 | 
						||
| 
								 | 
							
								        return flag
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def append_to(self, extlib):
							 | 
						||
| 
								 | 
							
								        """Append libraries, include_dirs to extension or library item.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        if is_sequence(extlib):
							 | 
						||
| 
								 | 
							
								            lib_name, build_info = extlib
							 | 
						||
| 
								 | 
							
								            dict_append(build_info,
							 | 
						||
| 
								 | 
							
								                        libraries=self.libraries,
							 | 
						||
| 
								 | 
							
								                        include_dirs=self.include_dirs)
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            from numpy.distutils.core import Extension
							 | 
						||
| 
								 | 
							
								            assert isinstance(extlib, Extension), repr(extlib)
							 | 
						||
| 
								 | 
							
								            extlib.libraries.extend(self.libraries)
							 | 
						||
| 
								 | 
							
								            extlib.include_dirs.extend(self.include_dirs)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _get_svn_revision(self, path):
							 | 
						||
| 
								 | 
							
								        """Return path's SVN revision number.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            output = subprocess.check_output(['svnversion'], cwd=path)
							 | 
						||
| 
								 | 
							
								        except (subprocess.CalledProcessError, OSError):
							 | 
						||
| 
								 | 
							
								            pass
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            m = re.match(rb'(?P<revision>\d+)', output)
							 | 
						||
| 
								 | 
							
								            if m:
							 | 
						||
| 
								 | 
							
								                return int(m.group('revision'))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if sys.platform=='win32' and os.environ.get('SVN_ASP_DOT_NET_HACK', None):
							 | 
						||
| 
								 | 
							
								            entries = njoin(path, '_svn', 'entries')
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            entries = njoin(path, '.svn', 'entries')
							 | 
						||
| 
								 | 
							
								        if os.path.isfile(entries):
							 | 
						||
| 
								 | 
							
								            with open(entries) as f:
							 | 
						||
| 
								 | 
							
								                fstr = f.read()
							 | 
						||
| 
								 | 
							
								            if fstr[:5] == '<?xml':  # pre 1.4
							 | 
						||
| 
								 | 
							
								                m = re.search(r'revision="(?P<revision>\d+)"', fstr)
							 | 
						||
| 
								 | 
							
								                if m:
							 | 
						||
| 
								 | 
							
								                    return int(m.group('revision'))
							 | 
						||
| 
								 | 
							
								            else:  # non-xml entries file --- check to be sure that
							 | 
						||
| 
								 | 
							
								                m = re.search(r'dir[\n\r]+(?P<revision>\d+)', fstr)
							 | 
						||
| 
								 | 
							
								                if m:
							 | 
						||
| 
								 | 
							
								                    return int(m.group('revision'))
							 | 
						||
| 
								 | 
							
								        return None
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _get_hg_revision(self, path):
							 | 
						||
| 
								 | 
							
								        """Return path's Mercurial revision number.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            output = subprocess.check_output(
							 | 
						||
| 
								 | 
							
								                ['hg', 'identify', '--num'], cwd=path)
							 | 
						||
| 
								 | 
							
								        except (subprocess.CalledProcessError, OSError):
							 | 
						||
| 
								 | 
							
								            pass
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            m = re.match(rb'(?P<revision>\d+)', output)
							 | 
						||
| 
								 | 
							
								            if m:
							 | 
						||
| 
								 | 
							
								                return int(m.group('revision'))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        branch_fn = njoin(path, '.hg', 'branch')
							 | 
						||
| 
								 | 
							
								        branch_cache_fn = njoin(path, '.hg', 'branch.cache')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if os.path.isfile(branch_fn):
							 | 
						||
| 
								 | 
							
								            branch0 = None
							 | 
						||
| 
								 | 
							
								            with open(branch_fn) as f:
							 | 
						||
| 
								 | 
							
								                revision0 = f.read().strip()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            branch_map = {}
							 | 
						||
| 
								 | 
							
								            with open(branch_cache_fn, 'r') as f:
							 | 
						||
| 
								 | 
							
								                for line in f:
							 | 
						||
| 
								 | 
							
								                    branch1, revision1  = line.split()[:2]
							 | 
						||
| 
								 | 
							
								                    if revision1==revision0:
							 | 
						||
| 
								 | 
							
								                        branch0 = branch1
							 | 
						||
| 
								 | 
							
								                    try:
							 | 
						||
| 
								 | 
							
								                        revision1 = int(revision1)
							 | 
						||
| 
								 | 
							
								                    except ValueError:
							 | 
						||
| 
								 | 
							
								                        continue
							 | 
						||
| 
								 | 
							
								                    branch_map[branch1] = revision1
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            return branch_map.get(branch0)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return None
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def get_version(self, version_file=None, version_variable=None):
							 | 
						||
| 
								 | 
							
								        """Try to get version string of a package.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Return a version string of the current package or None if the version
							 | 
						||
| 
								 | 
							
								        information could not be detected.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Notes
							 | 
						||
| 
								 | 
							
								        -----
							 | 
						||
| 
								 | 
							
								        This method scans files named
							 | 
						||
| 
								 | 
							
								        __version__.py, <packagename>_version.py, version.py, and
							 | 
						||
| 
								 | 
							
								        __svn_version__.py for string variables version, __version__, and
							 | 
						||
| 
								 | 
							
								        <packagename>_version, until a version number is found.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        version = getattr(self, 'version', None)
							 | 
						||
| 
								 | 
							
								        if version is not None:
							 | 
						||
| 
								 | 
							
								            return version
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # Get version from version file.
							 | 
						||
| 
								 | 
							
								        if version_file is None:
							 | 
						||
| 
								 | 
							
								            files = ['__version__.py',
							 | 
						||
| 
								 | 
							
								                     self.name.split('.')[-1]+'_version.py',
							 | 
						||
| 
								 | 
							
								                     'version.py',
							 | 
						||
| 
								 | 
							
								                     '__svn_version__.py',
							 | 
						||
| 
								 | 
							
								                     '__hg_version__.py']
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            files = [version_file]
							 | 
						||
| 
								 | 
							
								        if version_variable is None:
							 | 
						||
| 
								 | 
							
								            version_vars = ['version',
							 | 
						||
| 
								 | 
							
								                            '__version__',
							 | 
						||
| 
								 | 
							
								                            self.name.split('.')[-1]+'_version']
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            version_vars = [version_variable]
							 | 
						||
| 
								 | 
							
								        for f in files:
							 | 
						||
| 
								 | 
							
								            fn = njoin(self.local_path, f)
							 | 
						||
| 
								 | 
							
								            if os.path.isfile(fn):
							 | 
						||
| 
								 | 
							
								                info = ('.py', 'U', 1)
							 | 
						||
| 
								 | 
							
								                name = os.path.splitext(os.path.basename(fn))[0]
							 | 
						||
| 
								 | 
							
								                n = dot_join(self.name, name)
							 | 
						||
| 
								 | 
							
								                try:
							 | 
						||
| 
								 | 
							
								                    version_module = exec_mod_from_location(
							 | 
						||
| 
								 | 
							
								                                        '_'.join(n.split('.')), fn)
							 | 
						||
| 
								 | 
							
								                except ImportError as e:
							 | 
						||
| 
								 | 
							
								                    self.warn(str(e))
							 | 
						||
| 
								 | 
							
								                    version_module = None
							 | 
						||
| 
								 | 
							
								                if version_module is None:
							 | 
						||
| 
								 | 
							
								                    continue
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                for a in version_vars:
							 | 
						||
| 
								 | 
							
								                    version = getattr(version_module, a, None)
							 | 
						||
| 
								 | 
							
								                    if version is not None:
							 | 
						||
| 
								 | 
							
								                        break
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                # Try if versioneer module
							 | 
						||
| 
								 | 
							
								                try:
							 | 
						||
| 
								 | 
							
								                    version = version_module.get_versions()['version']
							 | 
						||
| 
								 | 
							
								                except AttributeError:
							 | 
						||
| 
								 | 
							
								                    pass
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                if version is not None:
							 | 
						||
| 
								 | 
							
								                    break
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if version is not None:
							 | 
						||
| 
								 | 
							
								            self.version = version
							 | 
						||
| 
								 | 
							
								            return version
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # Get version as SVN or Mercurial revision number
							 | 
						||
| 
								 | 
							
								        revision = self._get_svn_revision(self.local_path)
							 | 
						||
| 
								 | 
							
								        if revision is None:
							 | 
						||
| 
								 | 
							
								            revision = self._get_hg_revision(self.local_path)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if revision is not None:
							 | 
						||
| 
								 | 
							
								            version = str(revision)
							 | 
						||
| 
								 | 
							
								            self.version = version
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return version
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def make_svn_version_py(self, delete=True):
							 | 
						||
| 
								 | 
							
								        """Appends a data function to the data_files list that will generate
							 | 
						||
| 
								 | 
							
								        __svn_version__.py file to the current package directory.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Generate package __svn_version__.py file from SVN revision number,
							 | 
						||
| 
								 | 
							
								        it will be removed after python exits but will be available
							 | 
						||
| 
								 | 
							
								        when sdist, etc commands are executed.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Notes
							 | 
						||
| 
								 | 
							
								        -----
							 | 
						||
| 
								 | 
							
								        If __svn_version__.py existed before, nothing is done.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        This is
							 | 
						||
| 
								 | 
							
								        intended for working with source directories that are in an SVN
							 | 
						||
| 
								 | 
							
								        repository.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        target = njoin(self.local_path, '__svn_version__.py')
							 | 
						||
| 
								 | 
							
								        revision = self._get_svn_revision(self.local_path)
							 | 
						||
| 
								 | 
							
								        if os.path.isfile(target) or revision is None:
							 | 
						||
| 
								 | 
							
								            return
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            def generate_svn_version_py():
							 | 
						||
| 
								 | 
							
								                if not os.path.isfile(target):
							 | 
						||
| 
								 | 
							
								                    version = str(revision)
							 | 
						||
| 
								 | 
							
								                    self.info('Creating %s (version=%r)' % (target, version))
							 | 
						||
| 
								 | 
							
								                    with open(target, 'w') as f:
							 | 
						||
| 
								 | 
							
								                        f.write('version = %r\n' % (version))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                def rm_file(f=target,p=self.info):
							 | 
						||
| 
								 | 
							
								                    if delete:
							 | 
						||
| 
								 | 
							
								                        try: os.remove(f); p('removed '+f)
							 | 
						||
| 
								 | 
							
								                        except OSError: pass
							 | 
						||
| 
								 | 
							
								                        try: os.remove(f+'c'); p('removed '+f+'c')
							 | 
						||
| 
								 | 
							
								                        except OSError: pass
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                atexit.register(rm_file)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                return target
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            self.add_data_files(('', generate_svn_version_py()))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def make_hg_version_py(self, delete=True):
							 | 
						||
| 
								 | 
							
								        """Appends a data function to the data_files list that will generate
							 | 
						||
| 
								 | 
							
								        __hg_version__.py file to the current package directory.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Generate package __hg_version__.py file from Mercurial revision,
							 | 
						||
| 
								 | 
							
								        it will be removed after python exits but will be available
							 | 
						||
| 
								 | 
							
								        when sdist, etc commands are executed.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Notes
							 | 
						||
| 
								 | 
							
								        -----
							 | 
						||
| 
								 | 
							
								        If __hg_version__.py existed before, nothing is done.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        This is intended for working with source directories that are
							 | 
						||
| 
								 | 
							
								        in an Mercurial repository.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        target = njoin(self.local_path, '__hg_version__.py')
							 | 
						||
| 
								 | 
							
								        revision = self._get_hg_revision(self.local_path)
							 | 
						||
| 
								 | 
							
								        if os.path.isfile(target) or revision is None:
							 | 
						||
| 
								 | 
							
								            return
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            def generate_hg_version_py():
							 | 
						||
| 
								 | 
							
								                if not os.path.isfile(target):
							 | 
						||
| 
								 | 
							
								                    version = str(revision)
							 | 
						||
| 
								 | 
							
								                    self.info('Creating %s (version=%r)' % (target, version))
							 | 
						||
| 
								 | 
							
								                    with open(target, 'w') as f:
							 | 
						||
| 
								 | 
							
								                        f.write('version = %r\n' % (version))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                def rm_file(f=target,p=self.info):
							 | 
						||
| 
								 | 
							
								                    if delete:
							 | 
						||
| 
								 | 
							
								                        try: os.remove(f); p('removed '+f)
							 | 
						||
| 
								 | 
							
								                        except OSError: pass
							 | 
						||
| 
								 | 
							
								                        try: os.remove(f+'c'); p('removed '+f+'c')
							 | 
						||
| 
								 | 
							
								                        except OSError: pass
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                atexit.register(rm_file)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                return target
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            self.add_data_files(('', generate_hg_version_py()))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def make_config_py(self,name='__config__'):
							 | 
						||
| 
								 | 
							
								        """Generate package __config__.py file containing system_info
							 | 
						||
| 
								 | 
							
								        information used during building the package.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        This file is installed to the
							 | 
						||
| 
								 | 
							
								        package installation directory.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        self.py_modules.append((self.name, name, generate_config_py))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def get_info(self,*names):
							 | 
						||
| 
								 | 
							
								        """Get resources information.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Return information (from system_info.get_info) for all of the names in
							 | 
						||
| 
								 | 
							
								        the argument list in a single dictionary.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        from .system_info import get_info, dict_append
							 | 
						||
| 
								 | 
							
								        info_dict = {}
							 | 
						||
| 
								 | 
							
								        for a in names:
							 | 
						||
| 
								 | 
							
								            dict_append(info_dict,**get_info(a))
							 | 
						||
| 
								 | 
							
								        return info_dict
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_cmd(cmdname, _cache={}):
							 | 
						||
| 
								 | 
							
								    if cmdname not in _cache:
							 | 
						||
| 
								 | 
							
								        import distutils.core
							 | 
						||
| 
								 | 
							
								        dist = distutils.core._setup_distribution
							 | 
						||
| 
								 | 
							
								        if dist is None:
							 | 
						||
| 
								 | 
							
								            from distutils.errors import DistutilsInternalError
							 | 
						||
| 
								 | 
							
								            raise DistutilsInternalError(
							 | 
						||
| 
								 | 
							
								                  'setup distribution instance not initialized')
							 | 
						||
| 
								 | 
							
								        cmd = dist.get_command_obj(cmdname)
							 | 
						||
| 
								 | 
							
								        _cache[cmdname] = cmd
							 | 
						||
| 
								 | 
							
								    return _cache[cmdname]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_numpy_include_dirs():
							 | 
						||
| 
								 | 
							
								    # numpy_include_dirs are set by numpy/core/setup.py, otherwise []
							 | 
						||
| 
								 | 
							
								    include_dirs = Configuration.numpy_include_dirs[:]
							 | 
						||
| 
								 | 
							
								    if not include_dirs:
							 | 
						||
| 
								 | 
							
								        import numpy
							 | 
						||
| 
								 | 
							
								        include_dirs = [ numpy.get_include() ]
							 | 
						||
| 
								 | 
							
								    # else running numpy/core/setup.py
							 | 
						||
| 
								 | 
							
								    return include_dirs
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_npy_pkg_dir():
							 | 
						||
| 
								 | 
							
								    """Return the path where to find the npy-pkg-config directory.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    If the NPY_PKG_CONFIG_PATH environment variable is set, the value of that
							 | 
						||
| 
								 | 
							
								    is returned.  Otherwise, a path inside the location of the numpy module is
							 | 
						||
| 
								 | 
							
								    returned.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    The NPY_PKG_CONFIG_PATH can be useful when cross-compiling, maintaining
							 | 
						||
| 
								 | 
							
								    customized npy-pkg-config .ini files for the cross-compilation
							 | 
						||
| 
								 | 
							
								    environment, and using them when cross-compiling.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    d = os.environ.get('NPY_PKG_CONFIG_PATH')
							 | 
						||
| 
								 | 
							
								    if d is not None:
							 | 
						||
| 
								 | 
							
								        return d
							 | 
						||
| 
								 | 
							
								    spec = importlib.util.find_spec('numpy')
							 | 
						||
| 
								 | 
							
								    d = os.path.join(os.path.dirname(spec.origin),
							 | 
						||
| 
								 | 
							
								            'core', 'lib', 'npy-pkg-config')
							 | 
						||
| 
								 | 
							
								    return d
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_pkg_info(pkgname, dirs=None):
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return library info for the given package.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Parameters
							 | 
						||
| 
								 | 
							
								    ----------
							 | 
						||
| 
								 | 
							
								    pkgname : str
							 | 
						||
| 
								 | 
							
								        Name of the package (should match the name of the .ini file, without
							 | 
						||
| 
								 | 
							
								        the extension, e.g. foo for the file foo.ini).
							 | 
						||
| 
								 | 
							
								    dirs : sequence, optional
							 | 
						||
| 
								 | 
							
								        If given, should be a sequence of additional directories where to look
							 | 
						||
| 
								 | 
							
								        for npy-pkg-config files. Those directories are searched prior to the
							 | 
						||
| 
								 | 
							
								        NumPy directory.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Returns
							 | 
						||
| 
								 | 
							
								    -------
							 | 
						||
| 
								 | 
							
								    pkginfo : class instance
							 | 
						||
| 
								 | 
							
								        The `LibraryInfo` instance containing the build information.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Raises
							 | 
						||
| 
								 | 
							
								    ------
							 | 
						||
| 
								 | 
							
								    PkgNotFound
							 | 
						||
| 
								 | 
							
								        If the package is not found.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    See Also
							 | 
						||
| 
								 | 
							
								    --------
							 | 
						||
| 
								 | 
							
								    Configuration.add_npy_pkg_config, Configuration.add_installed_library,
							 | 
						||
| 
								 | 
							
								    get_info
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    from numpy.distutils.npy_pkg_config import read_config
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if dirs:
							 | 
						||
| 
								 | 
							
								        dirs.append(get_npy_pkg_dir())
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        dirs = [get_npy_pkg_dir()]
							 | 
						||
| 
								 | 
							
								    return read_config(pkgname, dirs)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_info(pkgname, dirs=None):
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return an info dict for a given C library.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    The info dict contains the necessary options to use the C library.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Parameters
							 | 
						||
| 
								 | 
							
								    ----------
							 | 
						||
| 
								 | 
							
								    pkgname : str
							 | 
						||
| 
								 | 
							
								        Name of the package (should match the name of the .ini file, without
							 | 
						||
| 
								 | 
							
								        the extension, e.g. foo for the file foo.ini).
							 | 
						||
| 
								 | 
							
								    dirs : sequence, optional
							 | 
						||
| 
								 | 
							
								        If given, should be a sequence of additional directories where to look
							 | 
						||
| 
								 | 
							
								        for npy-pkg-config files. Those directories are searched prior to the
							 | 
						||
| 
								 | 
							
								        NumPy directory.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Returns
							 | 
						||
| 
								 | 
							
								    -------
							 | 
						||
| 
								 | 
							
								    info : dict
							 | 
						||
| 
								 | 
							
								        The dictionary with build information.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Raises
							 | 
						||
| 
								 | 
							
								    ------
							 | 
						||
| 
								 | 
							
								    PkgNotFound
							 | 
						||
| 
								 | 
							
								        If the package is not found.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    See Also
							 | 
						||
| 
								 | 
							
								    --------
							 | 
						||
| 
								 | 
							
								    Configuration.add_npy_pkg_config, Configuration.add_installed_library,
							 | 
						||
| 
								 | 
							
								    get_pkg_info
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Examples
							 | 
						||
| 
								 | 
							
								    --------
							 | 
						||
| 
								 | 
							
								    To get the necessary information for the npymath library from NumPy:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    >>> npymath_info = np.distutils.misc_util.get_info('npymath')
							 | 
						||
| 
								 | 
							
								    >>> npymath_info                                    #doctest: +SKIP
							 | 
						||
| 
								 | 
							
								    {'define_macros': [], 'libraries': ['npymath'], 'library_dirs':
							 | 
						||
| 
								 | 
							
								    ['.../numpy/core/lib'], 'include_dirs': ['.../numpy/core/include']}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    This info dict can then be used as input to a `Configuration` instance::
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      config.add_extension('foo', sources=['foo.c'], extra_info=npymath_info)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    from numpy.distutils.npy_pkg_config import parse_flags
							 | 
						||
| 
								 | 
							
								    pkg_info = get_pkg_info(pkgname, dirs)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Translate LibraryInfo instance into a build_info dict
							 | 
						||
| 
								 | 
							
								    info = parse_flags(pkg_info.cflags())
							 | 
						||
| 
								 | 
							
								    for k, v in parse_flags(pkg_info.libs()).items():
							 | 
						||
| 
								 | 
							
								        info[k].extend(v)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # add_extension extra_info argument is ANAL
							 | 
						||
| 
								 | 
							
								    info['define_macros'] = info['macros']
							 | 
						||
| 
								 | 
							
								    del info['macros']
							 | 
						||
| 
								 | 
							
								    del info['ignored']
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return info
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def is_bootstrapping():
							 | 
						||
| 
								 | 
							
								    import builtins
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    try:
							 | 
						||
| 
								 | 
							
								        builtins.__NUMPY_SETUP__
							 | 
						||
| 
								 | 
							
								        return True
							 | 
						||
| 
								 | 
							
								    except AttributeError:
							 | 
						||
| 
								 | 
							
								        return False
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#########################
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def default_config_dict(name = None, parent_name = None, local_path=None):
							 | 
						||
| 
								 | 
							
								    """Return a configuration dictionary for usage in
							 | 
						||
| 
								 | 
							
								    configuration() function defined in file setup_<name>.py.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    import warnings
							 | 
						||
| 
								 | 
							
								    warnings.warn('Use Configuration(%r,%r,top_path=%r) instead of '\
							 | 
						||
| 
								 | 
							
								                  'deprecated default_config_dict(%r,%r,%r)'
							 | 
						||
| 
								 | 
							
								                  % (name, parent_name, local_path,
							 | 
						||
| 
								 | 
							
								                     name, parent_name, local_path,
							 | 
						||
| 
								 | 
							
								                     ), stacklevel=2)
							 | 
						||
| 
								 | 
							
								    c = Configuration(name, parent_name, local_path)
							 | 
						||
| 
								 | 
							
								    return c.todict()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def dict_append(d, **kws):
							 | 
						||
| 
								 | 
							
								    for k, v in kws.items():
							 | 
						||
| 
								 | 
							
								        if k in d:
							 | 
						||
| 
								 | 
							
								            ov = d[k]
							 | 
						||
| 
								 | 
							
								            if isinstance(ov, str):
							 | 
						||
| 
								 | 
							
								                d[k] = v
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                d[k].extend(v)
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            d[k] = v
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def appendpath(prefix, path):
							 | 
						||
| 
								 | 
							
								    if os.path.sep != '/':
							 | 
						||
| 
								 | 
							
								        prefix = prefix.replace('/', os.path.sep)
							 | 
						||
| 
								 | 
							
								        path = path.replace('/', os.path.sep)
							 | 
						||
| 
								 | 
							
								    drive = ''
							 | 
						||
| 
								 | 
							
								    if os.path.isabs(path):
							 | 
						||
| 
								 | 
							
								        drive = os.path.splitdrive(prefix)[0]
							 | 
						||
| 
								 | 
							
								        absprefix = os.path.splitdrive(os.path.abspath(prefix))[1]
							 | 
						||
| 
								 | 
							
								        pathdrive, path = os.path.splitdrive(path)
							 | 
						||
| 
								 | 
							
								        d = os.path.commonprefix([absprefix, path])
							 | 
						||
| 
								 | 
							
								        if os.path.join(absprefix[:len(d)], absprefix[len(d):]) != absprefix \
							 | 
						||
| 
								 | 
							
								           or os.path.join(path[:len(d)], path[len(d):]) != path:
							 | 
						||
| 
								 | 
							
								            # Handle invalid paths
							 | 
						||
| 
								 | 
							
								            d = os.path.dirname(d)
							 | 
						||
| 
								 | 
							
								        subpath = path[len(d):]
							 | 
						||
| 
								 | 
							
								        if os.path.isabs(subpath):
							 | 
						||
| 
								 | 
							
								            subpath = subpath[1:]
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        subpath = path
							 | 
						||
| 
								 | 
							
								    return os.path.normpath(njoin(drive + prefix, subpath))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def generate_config_py(target):
							 | 
						||
| 
								 | 
							
								    """Generate config.py file containing system_info information
							 | 
						||
| 
								 | 
							
								    used during building the package.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Usage:
							 | 
						||
| 
								 | 
							
								        config['py_modules'].append((packagename, '__config__',generate_config_py))
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    from numpy.distutils.system_info import system_info
							 | 
						||
| 
								 | 
							
								    from distutils.dir_util import mkpath
							 | 
						||
| 
								 | 
							
								    mkpath(os.path.dirname(target))
							 | 
						||
| 
								 | 
							
								    with open(target, 'w') as f:
							 | 
						||
| 
								 | 
							
								        f.write('# This file is generated by numpy\'s %s\n' % (os.path.basename(sys.argv[0])))
							 | 
						||
| 
								 | 
							
								        f.write('# It contains system_info results at the time of building this package.\n')
							 | 
						||
| 
								 | 
							
								        f.write('__all__ = ["get_info","show"]\n\n')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # For gfortran+msvc combination, extra shared libraries may exist
							 | 
						||
| 
								 | 
							
								        f.write(textwrap.dedent("""
							 | 
						||
| 
								 | 
							
								            import os
							 | 
						||
| 
								 | 
							
								            import sys
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            extra_dll_dir = os.path.join(os.path.dirname(__file__), '.libs')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if sys.platform == 'win32' and os.path.isdir(extra_dll_dir):
							 | 
						||
| 
								 | 
							
								                os.add_dll_directory(extra_dll_dir)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            """))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for k, i in system_info.saved_results.items():
							 | 
						||
| 
								 | 
							
								            f.write('%s=%r\n' % (k, i))
							 | 
						||
| 
								 | 
							
								        f.write(textwrap.dedent(r'''
							 | 
						||
| 
								 | 
							
								            def get_info(name):
							 | 
						||
| 
								 | 
							
								                g = globals()
							 | 
						||
| 
								 | 
							
								                return g.get(name, g.get(name + "_info", {}))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            def show():
							 | 
						||
| 
								 | 
							
								                """
							 | 
						||
| 
								 | 
							
								                Show libraries in the system on which NumPy was built.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                Print information about various resources (libraries, library
							 | 
						||
| 
								 | 
							
								                directories, include directories, etc.) in the system on which
							 | 
						||
| 
								 | 
							
								                NumPy was built.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                See Also
							 | 
						||
| 
								 | 
							
								                --------
							 | 
						||
| 
								 | 
							
								                get_include : Returns the directory containing NumPy C
							 | 
						||
| 
								 | 
							
								                              header files.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                Notes
							 | 
						||
| 
								 | 
							
								                -----
							 | 
						||
| 
								 | 
							
								                1. Classes specifying the information to be printed are defined
							 | 
						||
| 
								 | 
							
								                   in the `numpy.distutils.system_info` module.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                   Information may include:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                   * ``language``: language used to write the libraries (mostly
							 | 
						||
| 
								 | 
							
								                     C or f77)
							 | 
						||
| 
								 | 
							
								                   * ``libraries``: names of libraries found in the system
							 | 
						||
| 
								 | 
							
								                   * ``library_dirs``: directories containing the libraries
							 | 
						||
| 
								 | 
							
								                   * ``include_dirs``: directories containing library header files
							 | 
						||
| 
								 | 
							
								                   * ``src_dirs``: directories containing library source files
							 | 
						||
| 
								 | 
							
								                   * ``define_macros``: preprocessor macros used by
							 | 
						||
| 
								 | 
							
								                     ``distutils.setup``
							 | 
						||
| 
								 | 
							
								                   * ``baseline``: minimum CPU features required
							 | 
						||
| 
								 | 
							
								                   * ``found``: dispatched features supported in the system
							 | 
						||
| 
								 | 
							
								                   * ``not found``: dispatched features that are not supported
							 | 
						||
| 
								 | 
							
								                     in the system
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                2. NumPy BLAS/LAPACK Installation Notes
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                   Installing a numpy wheel (``pip install numpy`` or force it
							 | 
						||
| 
								 | 
							
								                   via ``pip install numpy --only-binary :numpy: numpy``) includes
							 | 
						||
| 
								 | 
							
								                   an OpenBLAS implementation of the BLAS and LAPACK linear algebra
							 | 
						||
| 
								 | 
							
								                   APIs. In this case, ``library_dirs`` reports the original build
							 | 
						||
| 
								 | 
							
								                   time configuration as compiled with gcc/gfortran; at run time
							 | 
						||
| 
								 | 
							
								                   the OpenBLAS library is in
							 | 
						||
| 
								 | 
							
								                   ``site-packages/numpy.libs/`` (linux), or
							 | 
						||
| 
								 | 
							
								                   ``site-packages/numpy/.dylibs/`` (macOS), or
							 | 
						||
| 
								 | 
							
								                   ``site-packages/numpy/.libs/`` (windows).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                   Installing numpy from source
							 | 
						||
| 
								 | 
							
								                   (``pip install numpy --no-binary numpy``) searches for BLAS and
							 | 
						||
| 
								 | 
							
								                   LAPACK dynamic link libraries at build time as influenced by
							 | 
						||
| 
								 | 
							
								                   environment variables NPY_BLAS_LIBS, NPY_CBLAS_LIBS, and
							 | 
						||
| 
								 | 
							
								                   NPY_LAPACK_LIBS; or NPY_BLAS_ORDER and NPY_LAPACK_ORDER;
							 | 
						||
| 
								 | 
							
								                   or the optional file ``~/.numpy-site.cfg``.
							 | 
						||
| 
								 | 
							
								                   NumPy remembers those locations and expects to load the same
							 | 
						||
| 
								 | 
							
								                   libraries at run-time.
							 | 
						||
| 
								 | 
							
								                   In NumPy 1.21+ on macOS, 'accelerate' (Apple's Accelerate BLAS
							 | 
						||
| 
								 | 
							
								                   library) is in the default build-time search order after
							 | 
						||
| 
								 | 
							
								                   'openblas'.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                Examples
							 | 
						||
| 
								 | 
							
								                --------
							 | 
						||
| 
								 | 
							
								                >>> import numpy as np
							 | 
						||
| 
								 | 
							
								                >>> np.show_config()
							 | 
						||
| 
								 | 
							
								                blas_opt_info:
							 | 
						||
| 
								 | 
							
								                    language = c
							 | 
						||
| 
								 | 
							
								                    define_macros = [('HAVE_CBLAS', None)]
							 | 
						||
| 
								 | 
							
								                    libraries = ['openblas', 'openblas']
							 | 
						||
| 
								 | 
							
								                    library_dirs = ['/usr/local/lib']
							 | 
						||
| 
								 | 
							
								                """
							 | 
						||
| 
								 | 
							
								                from numpy.core._multiarray_umath import (
							 | 
						||
| 
								 | 
							
								                    __cpu_features__, __cpu_baseline__, __cpu_dispatch__
							 | 
						||
| 
								 | 
							
								                )
							 | 
						||
| 
								 | 
							
								                for name,info_dict in globals().items():
							 | 
						||
| 
								 | 
							
								                    if name[0] == "_" or type(info_dict) is not type({}): continue
							 | 
						||
| 
								 | 
							
								                    print(name + ":")
							 | 
						||
| 
								 | 
							
								                    if not info_dict:
							 | 
						||
| 
								 | 
							
								                        print("  NOT AVAILABLE")
							 | 
						||
| 
								 | 
							
								                    for k,v in info_dict.items():
							 | 
						||
| 
								 | 
							
								                        v = str(v)
							 | 
						||
| 
								 | 
							
								                        if k == "sources" and len(v) > 200:
							 | 
						||
| 
								 | 
							
								                            v = v[:60] + " ...\n... " + v[-60:]
							 | 
						||
| 
								 | 
							
								                        print("    %s = %s" % (k,v))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                features_found, features_not_found = [], []
							 | 
						||
| 
								 | 
							
								                for feature in __cpu_dispatch__:
							 | 
						||
| 
								 | 
							
								                    if __cpu_features__[feature]:
							 | 
						||
| 
								 | 
							
								                        features_found.append(feature)
							 | 
						||
| 
								 | 
							
								                    else:
							 | 
						||
| 
								 | 
							
								                        features_not_found.append(feature)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                print("Supported SIMD extensions in this NumPy install:")
							 | 
						||
| 
								 | 
							
								                print("    baseline = %s" % (','.join(__cpu_baseline__)))
							 | 
						||
| 
								 | 
							
								                print("    found = %s" % (','.join(features_found)))
							 | 
						||
| 
								 | 
							
								                print("    not found = %s" % (','.join(features_not_found)))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    '''))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return target
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def msvc_version(compiler):
							 | 
						||
| 
								 | 
							
								    """Return version major and minor of compiler instance if it is
							 | 
						||
| 
								 | 
							
								    MSVC, raise an exception otherwise."""
							 | 
						||
| 
								 | 
							
								    if not compiler.compiler_type == "msvc":
							 | 
						||
| 
								 | 
							
								        raise ValueError("Compiler instance is not msvc (%s)"\
							 | 
						||
| 
								 | 
							
								                         % compiler.compiler_type)
							 | 
						||
| 
								 | 
							
								    return compiler._MSVCCompiler__version
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_build_architecture():
							 | 
						||
| 
								 | 
							
								    # Importing distutils.msvccompiler triggers a warning on non-Windows
							 | 
						||
| 
								 | 
							
								    # systems, so delay the import to here.
							 | 
						||
| 
								 | 
							
								    from distutils.msvccompiler import get_build_architecture
							 | 
						||
| 
								 | 
							
								    return get_build_architecture()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								_cxx_ignore_flags = {'-Werror=implicit-function-declaration', '-std=c99'}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def sanitize_cxx_flags(cxxflags):
							 | 
						||
| 
								 | 
							
								    '''
							 | 
						||
| 
								 | 
							
								    Some flags are valid for C but not C++. Prune them.
							 | 
						||
| 
								 | 
							
								    '''
							 | 
						||
| 
								 | 
							
								    return [flag for flag in cxxflags if flag not in _cxx_ignore_flags]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def exec_mod_from_location(modname, modfile):
							 | 
						||
| 
								 | 
							
								    '''
							 | 
						||
| 
								 | 
							
								    Use importlib machinery to import a module `modname` from the file
							 | 
						||
| 
								 | 
							
								    `modfile`. Depending on the `spec.loader`, the module may not be
							 | 
						||
| 
								 | 
							
								    registered in sys.modules.
							 | 
						||
| 
								 | 
							
								    '''
							 | 
						||
| 
								 | 
							
								    spec = importlib.util.spec_from_file_location(modname, modfile)
							 | 
						||
| 
								 | 
							
								    foo = importlib.util.module_from_spec(spec)
							 | 
						||
| 
								 | 
							
								    spec.loader.exec_module(foo)
							 | 
						||
| 
								 | 
							
								    return foo
							 |