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.
		
		
		
		
		
			
		
			
				
					438 lines
				
				13 KiB
			
		
		
			
		
	
	
					438 lines
				
				13 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								import sys
							 | 
						||
| 
								 | 
							
								import re
							 | 
						||
| 
								 | 
							
								import os
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								from configparser import RawConfigParser
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								__all__ = ['FormatError', 'PkgNotFound', 'LibraryInfo', 'VariableSet',
							 | 
						||
| 
								 | 
							
								        'read_config', 'parse_flags']
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								_VAR = re.compile(r'\$\{([a-zA-Z0-9_-]+)\}')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class FormatError(OSError):
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Exception thrown when there is a problem parsing a configuration file.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    def __init__(self, msg):
							 | 
						||
| 
								 | 
							
								        self.msg = msg
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __str__(self):
							 | 
						||
| 
								 | 
							
								        return self.msg
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class PkgNotFound(OSError):
							 | 
						||
| 
								 | 
							
								    """Exception raised when a package can not be located."""
							 | 
						||
| 
								 | 
							
								    def __init__(self, msg):
							 | 
						||
| 
								 | 
							
								        self.msg = msg
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __str__(self):
							 | 
						||
| 
								 | 
							
								        return self.msg
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def parse_flags(line):
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Parse a line from a config file containing compile flags.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Parameters
							 | 
						||
| 
								 | 
							
								    ----------
							 | 
						||
| 
								 | 
							
								    line : str
							 | 
						||
| 
								 | 
							
								        A single line containing one or more compile flags.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Returns
							 | 
						||
| 
								 | 
							
								    -------
							 | 
						||
| 
								 | 
							
								    d : dict
							 | 
						||
| 
								 | 
							
								        Dictionary of parsed flags, split into relevant categories.
							 | 
						||
| 
								 | 
							
								        These categories are the keys of `d`:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        * 'include_dirs'
							 | 
						||
| 
								 | 
							
								        * 'library_dirs'
							 | 
						||
| 
								 | 
							
								        * 'libraries'
							 | 
						||
| 
								 | 
							
								        * 'macros'
							 | 
						||
| 
								 | 
							
								        * 'ignored'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    d = {'include_dirs': [], 'library_dirs': [], 'libraries': [],
							 | 
						||
| 
								 | 
							
								         'macros': [], 'ignored': []}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    flags = (' ' + line).split(' -')
							 | 
						||
| 
								 | 
							
								    for flag in flags:
							 | 
						||
| 
								 | 
							
								        flag = '-' + flag
							 | 
						||
| 
								 | 
							
								        if len(flag) > 0:
							 | 
						||
| 
								 | 
							
								            if flag.startswith('-I'):
							 | 
						||
| 
								 | 
							
								                d['include_dirs'].append(flag[2:].strip())
							 | 
						||
| 
								 | 
							
								            elif flag.startswith('-L'):
							 | 
						||
| 
								 | 
							
								                d['library_dirs'].append(flag[2:].strip())
							 | 
						||
| 
								 | 
							
								            elif flag.startswith('-l'):
							 | 
						||
| 
								 | 
							
								                d['libraries'].append(flag[2:].strip())
							 | 
						||
| 
								 | 
							
								            elif flag.startswith('-D'):
							 | 
						||
| 
								 | 
							
								                d['macros'].append(flag[2:].strip())
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                d['ignored'].append(flag)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return d
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def _escape_backslash(val):
							 | 
						||
| 
								 | 
							
								    return val.replace('\\', '\\\\')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class LibraryInfo:
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Object containing build information about a library.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Parameters
							 | 
						||
| 
								 | 
							
								    ----------
							 | 
						||
| 
								 | 
							
								    name : str
							 | 
						||
| 
								 | 
							
								        The library name.
							 | 
						||
| 
								 | 
							
								    description : str
							 | 
						||
| 
								 | 
							
								        Description of the library.
							 | 
						||
| 
								 | 
							
								    version : str
							 | 
						||
| 
								 | 
							
								        Version string.
							 | 
						||
| 
								 | 
							
								    sections : dict
							 | 
						||
| 
								 | 
							
								        The sections of the configuration file for the library. The keys are
							 | 
						||
| 
								 | 
							
								        the section headers, the values the text under each header.
							 | 
						||
| 
								 | 
							
								    vars : class instance
							 | 
						||
| 
								 | 
							
								        A `VariableSet` instance, which contains ``(name, value)`` pairs for
							 | 
						||
| 
								 | 
							
								        variables defined in the configuration file for the library.
							 | 
						||
| 
								 | 
							
								    requires : sequence, optional
							 | 
						||
| 
								 | 
							
								        The required libraries for the library to be installed.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Notes
							 | 
						||
| 
								 | 
							
								    -----
							 | 
						||
| 
								 | 
							
								    All input parameters (except "sections" which is a method) are available as
							 | 
						||
| 
								 | 
							
								    attributes of the same name.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    def __init__(self, name, description, version, sections, vars, requires=None):
							 | 
						||
| 
								 | 
							
								        self.name = name
							 | 
						||
| 
								 | 
							
								        self.description = description
							 | 
						||
| 
								 | 
							
								        if requires:
							 | 
						||
| 
								 | 
							
								            self.requires = requires
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            self.requires = []
							 | 
						||
| 
								 | 
							
								        self.version = version
							 | 
						||
| 
								 | 
							
								        self._sections = sections
							 | 
						||
| 
								 | 
							
								        self.vars = vars
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def sections(self):
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return the section headers of the config file.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Parameters
							 | 
						||
| 
								 | 
							
								        ----------
							 | 
						||
| 
								 | 
							
								        None
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Returns
							 | 
						||
| 
								 | 
							
								        -------
							 | 
						||
| 
								 | 
							
								        keys : list of str
							 | 
						||
| 
								 | 
							
								            The list of section headers.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        return list(self._sections.keys())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def cflags(self, section="default"):
							 | 
						||
| 
								 | 
							
								        val = self.vars.interpolate(self._sections[section]['cflags'])
							 | 
						||
| 
								 | 
							
								        return _escape_backslash(val)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def libs(self, section="default"):
							 | 
						||
| 
								 | 
							
								        val = self.vars.interpolate(self._sections[section]['libs'])
							 | 
						||
| 
								 | 
							
								        return _escape_backslash(val)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __str__(self):
							 | 
						||
| 
								 | 
							
								        m = ['Name: %s' % self.name, 'Description: %s' % self.description]
							 | 
						||
| 
								 | 
							
								        if self.requires:
							 | 
						||
| 
								 | 
							
								            m.append('Requires:')
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            m.append('Requires: %s' % ",".join(self.requires))
							 | 
						||
| 
								 | 
							
								        m.append('Version: %s' % self.version)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return "\n".join(m)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class VariableSet:
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Container object for the variables defined in a config file.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    `VariableSet` can be used as a plain dictionary, with the variable names
							 | 
						||
| 
								 | 
							
								    as keys.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Parameters
							 | 
						||
| 
								 | 
							
								    ----------
							 | 
						||
| 
								 | 
							
								    d : dict
							 | 
						||
| 
								 | 
							
								        Dict of items in the "variables" section of the configuration file.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    def __init__(self, d):
							 | 
						||
| 
								 | 
							
								        self._raw_data = dict([(k, v) for k, v in d.items()])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self._re = {}
							 | 
						||
| 
								 | 
							
								        self._re_sub = {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self._init_parse()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _init_parse(self):
							 | 
						||
| 
								 | 
							
								        for k, v in self._raw_data.items():
							 | 
						||
| 
								 | 
							
								            self._init_parse_var(k, v)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _init_parse_var(self, name, value):
							 | 
						||
| 
								 | 
							
								        self._re[name] = re.compile(r'\$\{%s\}' % name)
							 | 
						||
| 
								 | 
							
								        self._re_sub[name] = value
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def interpolate(self, value):
							 | 
						||
| 
								 | 
							
								        # Brute force: we keep interpolating until there is no '${var}' anymore
							 | 
						||
| 
								 | 
							
								        # or until interpolated string is equal to input string
							 | 
						||
| 
								 | 
							
								        def _interpolate(value):
							 | 
						||
| 
								 | 
							
								            for k in self._re.keys():
							 | 
						||
| 
								 | 
							
								                value = self._re[k].sub(self._re_sub[k], value)
							 | 
						||
| 
								 | 
							
								            return value
							 | 
						||
| 
								 | 
							
								        while _VAR.search(value):
							 | 
						||
| 
								 | 
							
								            nvalue = _interpolate(value)
							 | 
						||
| 
								 | 
							
								            if nvalue == value:
							 | 
						||
| 
								 | 
							
								                break
							 | 
						||
| 
								 | 
							
								            value = nvalue
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return value
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def variables(self):
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        Return the list of variable names.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Parameters
							 | 
						||
| 
								 | 
							
								        ----------
							 | 
						||
| 
								 | 
							
								        None
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Returns
							 | 
						||
| 
								 | 
							
								        -------
							 | 
						||
| 
								 | 
							
								        names : list of str
							 | 
						||
| 
								 | 
							
								            The names of all variables in the `VariableSet` instance.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        return list(self._raw_data.keys())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Emulate a dict to set/get variables values
							 | 
						||
| 
								 | 
							
								    def __getitem__(self, name):
							 | 
						||
| 
								 | 
							
								        return self._raw_data[name]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __setitem__(self, name, value):
							 | 
						||
| 
								 | 
							
								        self._raw_data[name] = value
							 | 
						||
| 
								 | 
							
								        self._init_parse_var(name, value)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def parse_meta(config):
							 | 
						||
| 
								 | 
							
								    if not config.has_section('meta'):
							 | 
						||
| 
								 | 
							
								        raise FormatError("No meta section found !")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    d = dict(config.items('meta'))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for k in ['name', 'description', 'version']:
							 | 
						||
| 
								 | 
							
								        if not k in d:
							 | 
						||
| 
								 | 
							
								            raise FormatError("Option %s (section [meta]) is mandatory, "
							 | 
						||
| 
								 | 
							
								                "but not found" % k)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if not 'requires' in d:
							 | 
						||
| 
								 | 
							
								        d['requires'] = []
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return d
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def parse_variables(config):
							 | 
						||
| 
								 | 
							
								    if not config.has_section('variables'):
							 | 
						||
| 
								 | 
							
								        raise FormatError("No variables section found !")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    d = {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for name, value in config.items("variables"):
							 | 
						||
| 
								 | 
							
								        d[name] = value
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return VariableSet(d)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def parse_sections(config):
							 | 
						||
| 
								 | 
							
								    return meta_d, r
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def pkg_to_filename(pkg_name):
							 | 
						||
| 
								 | 
							
								    return "%s.ini" % pkg_name
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def parse_config(filename, dirs=None):
							 | 
						||
| 
								 | 
							
								    if dirs:
							 | 
						||
| 
								 | 
							
								        filenames = [os.path.join(d, filename) for d in dirs]
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        filenames = [filename]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    config = RawConfigParser()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    n = config.read(filenames)
							 | 
						||
| 
								 | 
							
								    if not len(n) >= 1:
							 | 
						||
| 
								 | 
							
								        raise PkgNotFound("Could not find file(s) %s" % str(filenames))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Parse meta and variables sections
							 | 
						||
| 
								 | 
							
								    meta = parse_meta(config)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    vars = {}
							 | 
						||
| 
								 | 
							
								    if config.has_section('variables'):
							 | 
						||
| 
								 | 
							
								        for name, value in config.items("variables"):
							 | 
						||
| 
								 | 
							
								            vars[name] = _escape_backslash(value)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Parse "normal" sections
							 | 
						||
| 
								 | 
							
								    secs = [s for s in config.sections() if not s in ['meta', 'variables']]
							 | 
						||
| 
								 | 
							
								    sections = {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    requires = {}
							 | 
						||
| 
								 | 
							
								    for s in secs:
							 | 
						||
| 
								 | 
							
								        d = {}
							 | 
						||
| 
								 | 
							
								        if config.has_option(s, "requires"):
							 | 
						||
| 
								 | 
							
								            requires[s] = config.get(s, 'requires')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for name, value in config.items(s):
							 | 
						||
| 
								 | 
							
								            d[name] = value
							 | 
						||
| 
								 | 
							
								        sections[s] = d
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return meta, vars, sections, requires
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def _read_config_imp(filenames, dirs=None):
							 | 
						||
| 
								 | 
							
								    def _read_config(f):
							 | 
						||
| 
								 | 
							
								        meta, vars, sections, reqs = parse_config(f, dirs)
							 | 
						||
| 
								 | 
							
								        # recursively add sections and variables of required libraries
							 | 
						||
| 
								 | 
							
								        for rname, rvalue in reqs.items():
							 | 
						||
| 
								 | 
							
								            nmeta, nvars, nsections, nreqs = _read_config(pkg_to_filename(rvalue))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            # Update var dict for variables not in 'top' config file
							 | 
						||
| 
								 | 
							
								            for k, v in nvars.items():
							 | 
						||
| 
								 | 
							
								                if not k in vars:
							 | 
						||
| 
								 | 
							
								                    vars[k] = v
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            # Update sec dict
							 | 
						||
| 
								 | 
							
								            for oname, ovalue in nsections[rname].items():
							 | 
						||
| 
								 | 
							
								                if ovalue:
							 | 
						||
| 
								 | 
							
								                    sections[rname][oname] += ' %s' % ovalue
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return meta, vars, sections, reqs
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    meta, vars, sections, reqs = _read_config(filenames)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # FIXME: document this. If pkgname is defined in the variables section, and
							 | 
						||
| 
								 | 
							
								    # there is no pkgdir variable defined, pkgdir is automatically defined to
							 | 
						||
| 
								 | 
							
								    # the path of pkgname. This requires the package to be imported to work
							 | 
						||
| 
								 | 
							
								    if not 'pkgdir' in vars and "pkgname" in vars:
							 | 
						||
| 
								 | 
							
								        pkgname = vars["pkgname"]
							 | 
						||
| 
								 | 
							
								        if not pkgname in sys.modules:
							 | 
						||
| 
								 | 
							
								            raise ValueError("You should import %s to get information on %s" %
							 | 
						||
| 
								 | 
							
								                             (pkgname, meta["name"]))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        mod = sys.modules[pkgname]
							 | 
						||
| 
								 | 
							
								        vars["pkgdir"] = _escape_backslash(os.path.dirname(mod.__file__))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return LibraryInfo(name=meta["name"], description=meta["description"],
							 | 
						||
| 
								 | 
							
								            version=meta["version"], sections=sections, vars=VariableSet(vars))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Trivial cache to cache LibraryInfo instances creation. To be really
							 | 
						||
| 
								 | 
							
								# efficient, the cache should be handled in read_config, since a same file can
							 | 
						||
| 
								 | 
							
								# be parsed many time outside LibraryInfo creation, but I doubt this will be a
							 | 
						||
| 
								 | 
							
								# problem in practice
							 | 
						||
| 
								 | 
							
								_CACHE = {}
							 | 
						||
| 
								 | 
							
								def read_config(pkgname, dirs=None):
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Return library info for a package from its configuration file.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    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 directories - usually including
							 | 
						||
| 
								 | 
							
								        the NumPy base directory - where to look for npy-pkg-config files.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Returns
							 | 
						||
| 
								 | 
							
								    -------
							 | 
						||
| 
								 | 
							
								    pkginfo : class instance
							 | 
						||
| 
								 | 
							
								        The `LibraryInfo` instance containing the build information.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Raises
							 | 
						||
| 
								 | 
							
								    ------
							 | 
						||
| 
								 | 
							
								    PkgNotFound
							 | 
						||
| 
								 | 
							
								        If the package is not found.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    See Also
							 | 
						||
| 
								 | 
							
								    --------
							 | 
						||
| 
								 | 
							
								    misc_util.get_info, misc_util.get_pkg_info
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Examples
							 | 
						||
| 
								 | 
							
								    --------
							 | 
						||
| 
								 | 
							
								    >>> npymath_info = np.distutils.npy_pkg_config.read_config('npymath')
							 | 
						||
| 
								 | 
							
								    >>> type(npymath_info)
							 | 
						||
| 
								 | 
							
								    <class 'numpy.distutils.npy_pkg_config.LibraryInfo'>
							 | 
						||
| 
								 | 
							
								    >>> print(npymath_info)
							 | 
						||
| 
								 | 
							
								    Name: npymath
							 | 
						||
| 
								 | 
							
								    Description: Portable, core math library implementing C99 standard
							 | 
						||
| 
								 | 
							
								    Requires:
							 | 
						||
| 
								 | 
							
								    Version: 0.1  #random
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    try:
							 | 
						||
| 
								 | 
							
								        return _CACHE[pkgname]
							 | 
						||
| 
								 | 
							
								    except KeyError:
							 | 
						||
| 
								 | 
							
								        v = _read_config_imp(pkg_to_filename(pkgname), dirs)
							 | 
						||
| 
								 | 
							
								        _CACHE[pkgname] = v
							 | 
						||
| 
								 | 
							
								        return v
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# TODO:
							 | 
						||
| 
								 | 
							
								#   - implements version comparison (modversion + atleast)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# pkg-config simple emulator - useful for debugging, and maybe later to query
							 | 
						||
| 
								 | 
							
								# the system
							 | 
						||
| 
								 | 
							
								if __name__ == '__main__':
							 | 
						||
| 
								 | 
							
								    from optparse import OptionParser
							 | 
						||
| 
								 | 
							
								    import glob
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    parser = OptionParser()
							 | 
						||
| 
								 | 
							
								    parser.add_option("--cflags", dest="cflags", action="store_true",
							 | 
						||
| 
								 | 
							
								                      help="output all preprocessor and compiler flags")
							 | 
						||
| 
								 | 
							
								    parser.add_option("--libs", dest="libs", action="store_true",
							 | 
						||
| 
								 | 
							
								                      help="output all linker flags")
							 | 
						||
| 
								 | 
							
								    parser.add_option("--use-section", dest="section",
							 | 
						||
| 
								 | 
							
								                      help="use this section instead of default for options")
							 | 
						||
| 
								 | 
							
								    parser.add_option("--version", dest="version", action="store_true",
							 | 
						||
| 
								 | 
							
								                      help="output version")
							 | 
						||
| 
								 | 
							
								    parser.add_option("--atleast-version", dest="min_version",
							 | 
						||
| 
								 | 
							
								                      help="Minimal version")
							 | 
						||
| 
								 | 
							
								    parser.add_option("--list-all", dest="list_all", action="store_true",
							 | 
						||
| 
								 | 
							
								                      help="Minimal version")
							 | 
						||
| 
								 | 
							
								    parser.add_option("--define-variable", dest="define_variable",
							 | 
						||
| 
								 | 
							
								                      help="Replace variable with the given value")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    (options, args) = parser.parse_args(sys.argv)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if len(args) < 2:
							 | 
						||
| 
								 | 
							
								        raise ValueError("Expect package name on the command line:")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if options.list_all:
							 | 
						||
| 
								 | 
							
								        files = glob.glob("*.ini")
							 | 
						||
| 
								 | 
							
								        for f in files:
							 | 
						||
| 
								 | 
							
								            info = read_config(f)
							 | 
						||
| 
								 | 
							
								            print("%s\t%s - %s" % (info.name, info.name, info.description))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    pkg_name = args[1]
							 | 
						||
| 
								 | 
							
								    d = os.environ.get('NPY_PKG_CONFIG_PATH')
							 | 
						||
| 
								 | 
							
								    if d:
							 | 
						||
| 
								 | 
							
								        info = read_config(pkg_name, ['numpy/core/lib/npy-pkg-config', '.', d])
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        info = read_config(pkg_name, ['numpy/core/lib/npy-pkg-config', '.'])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if options.section:
							 | 
						||
| 
								 | 
							
								        section = options.section
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        section = "default"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if options.define_variable:
							 | 
						||
| 
								 | 
							
								        m = re.search(r'([\S]+)=([\S]+)', options.define_variable)
							 | 
						||
| 
								 | 
							
								        if not m:
							 | 
						||
| 
								 | 
							
								            raise ValueError("--define-variable option should be of "
							 | 
						||
| 
								 | 
							
								                             "the form --define-variable=foo=bar")
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            name = m.group(1)
							 | 
						||
| 
								 | 
							
								            value = m.group(2)
							 | 
						||
| 
								 | 
							
								        info.vars[name] = value
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if options.cflags:
							 | 
						||
| 
								 | 
							
								        print(info.cflags(section))
							 | 
						||
| 
								 | 
							
								    if options.libs:
							 | 
						||
| 
								 | 
							
								        print(info.libs(section))
							 | 
						||
| 
								 | 
							
								    if options.version:
							 | 
						||
| 
								 | 
							
								        print(info.version)
							 | 
						||
| 
								 | 
							
								    if options.min_version:
							 | 
						||
| 
								 | 
							
								        print(info.version >= options.min_version)
							 |