Source code for filesysobjects.configdata

# -*- coding: utf-8 -*-
"""Platform independent path names for configuration files.
"""
from __future__ import absolute_import
import os
import re

import pysourceinfo.fileinfo

from filesysobjects import W_FULL, W_GLOB, W_LITERAL, W_LITERAL_QUOTED, W_RE
from filesysobjects.userdata import getdir_userhome, getdir_userconfigdata
from filesysobjects.osdata import getdir_osconfigdata, getdir_osappconfigdata
from filesysobjects.pathtools import findrelpath_in_searchpath, expandpath,findrelpath_in_searchpath_iter

__author__ = 'Arno-Can Uestuensoez'
__license__ = "Artistic-License-2.0 + Forced-Fairplay-Constraints"
__copyright__ = "Copyright (C) 2010-2016 Arno-Can Uestuensoez" \
                " @Ingenieurbuero Arno-Can Uestuensoez"
__version__ = '0.1.20'
__uuid__ = "4135ab0f-fbb8-45a2-a6b1-80d96c164b72"

__docformat__ = "restructuredtext en"


[docs]class ConfigPath(object): """A small class that manages the search for configuration files located at standard paths. """
[docs] def __init__(self, **kargs): """Initializes the search paths. Args: kargs: **append**: A list of search paths to be added to the standard search. **filext**: A list of default file extensions to be used in search operations. Default :: filext := [ini', 'conf', 'json', 'xml'] **prepend**: A list of search paths to be checked at the beginning of the standard search. **replace**: A list of search paths to replace the standard search. Returns: object/None Raises: pass-through """ self.replace = kargs.get('replace') self.prepend = kargs.get('prepend') self.append = kargs.get('append') self.fext = kargs.get('filext', ['.ini', '.conf', '.json', '.xml', '.yaml'])
def __repr__(self): """Returns the current list of search path names. """ return repr(self.get_config_path_list()) def __str__(self): """Returns the formatted list of current search path names. """ ret = "[\n" for l in self.get_config_path_list(): ret += ' ' * 4 + '"' + str(l) + '",\n' ret += "]" return ret
[docs] def get_config_filepath(self, conf): """Returns the first matched configuration file. The standard search hierarchy is: 0. absolute file path: <conf> 1. relative to current workdir: <conf> 2. USER context by: getdir_userconfigdata()/<conf> 3. HOME of user: getdir_userhome()/<conf> 4. Application config: getdir_osappconfigdata()/<conf> 5. OS config: getdir_osappconfigdata()/<conf> 6. the final default from distribution: pysourceinfo.fileinfo.getcaller_package_filepathname()/<conf> 7. the final default from module: pysourceinfo.fileinfo.getcaller_pathname()/<conf> The priorities 6 + 7 are the last, because the caller itself could be a library sub call, so is not necessarily closely related to the calling application. This could be altered by the parameters *replace*, *prepend*, and *append*. :: if replace: replace standard by list if prepend: prepend any list(standard/replace) if append: append to any list(standard/replace) Args: **conf**: Configuration file name including suffix. Valid *conf* file name wildcard types are: +---------+----+ | literal | X | +---------+----+ | re | -- | +---------+----+ | glob | X | +---------+----+ Returns: The first file path name matched by *conf*, else None. Raises: pass-through """ return findrelpath_in_searchpath(conf, self.get_config_path_list(), isFile=True)
def get_config_filepath_list_old(self, conf=None): """Returns a list of matched configuration files. Args: **conf**: Search expression for configuration file names. Valid *conf* file name wildcard types are: +---------+----+ | literal | X | +---------+----+ | re | -- | +---------+----+ | glob | X | +---------+----+ Returns: A list of file path names matched by 'conf'. Raises: pass-through """ if os.path.isabs(conf): # absolute if os.path.exists(conf): if os.path.isfile(conf): return [conf] ret = [] for e in self.fext: f = expandpath(conf + os.sep + '*' + e, isFile=True) if f: ret.extend(list(f)) return ret return expandpath(conf, isFile=True) else: sp = self.get_config_path_list() if os.path.splitext(conf) in self.fext: # return list(findrelpath_in_searchpath_iter(conf, sp, isFile=True)) return list(expandpath(conf, isFile=True)) elif not conf or conf == '*': ret = [] for e in self.fext: # f = findrelpath_in_searchpath_iter('*' + e, sp, isFile=True) f = findrelpath_in_searchpath_iter('*' + e, sp, isFile=True) if f: ret.extend(list(f)) return ret else: ret = [] # f = findrelpath_in_searchpath_iter(conf, sp, isFile=True) f = findrelpath_in_searchpath_iter(conf, sp, isFile=True) if f: return list(f) for e in self.fext: # f = findrelpath_in_searchpath_iter(conf + e, sp, isFile=True) f = findrelpath_in_searchpath_iter(conf + e, sp, isFile=True) if f: ret.extend(list(f)) return ret
[docs] def get_config_filepath_list(self, conf=None, **kargs): """Returns a list of matched configuration files. Args: **conf**: Search expression for configuration file names. Valid *conf* file name wildcard types are: +---------+----+ | literal | X | +---------+----+ | re | -- | +---------+----+ | glob | X | +---------+----+ kargs: **isDir**: Include directories. default := False **isFile**: Include files. default := True Returns: A list of file path names matched by 'conf'. Raises: pass-through """ _isfile = kargs.get('isFile', True) _isdir = kargs.get('isDir', False) # _wildcards = kargs.get('wildcards', W_FULL) _wildcards = kargs.get('wildcards', W_LITERAL_QUOTED|W_GLOB|W_RE) ret = [] if os.path.isabs(conf): # absolute if os.path.exists(conf): if os.path.isfile(conf): return [conf] for e in self.fext: f = expandpath( conf + os.sep + '*' + e, isFile=_isfile, isDir=_isdir, wildcards=_wildcards, ) if f: ret.extend(list(f)) return ret return expandpath( conf, isFile=_isfile, isDir=_isdir, wildcards=_wildcards, ) else: sp = self.get_config_path_list() if os.path.splitext(conf)[1] in self.fext: # return list(findrelpath_in_searchpath_iter(conf, sp, isFile=True)) # f = expandpath( # conf, # isFile=_isfile, # isDir=_isdir, # wildcards=_wildcards, # ) # if f: # ret.extend(list(f)) # return ret for s in sp: f = expandpath( s + os.sep + conf, isFile=_isfile, isDir=_isdir, wildcards=_wildcards, ) if f: ret.extend(list(f)) return ret # f = expandpath(s + os.sep + '*' + e, isFile=True) # if f: # ret.extend(list(f)) # elif not conf or conf == '*': # for e in self.fext: # # f = findrelpath_in_searchpath_iter('*' + e, sp, isFile=True) # for s in sp: # f = expandpath(s + os.sep + '*' + e, isFile=True) # if f: # ret.extend(list(f)) # return ret else: ret = [] # f = findrelpath_in_searchpath_iter(conf, sp, isFile=True) for s in sp: f = expandpath( s + os.sep + conf, isFile=_isfile, isDir=_isdir, wildcards=_wildcards, ) if f: ret.extend(list(f)) if ret: return ret for e in self.fext: # f = findrelpath_in_searchpath_iter(conf + e, sp, isFile=True) for s in sp: f = expandpath( s + os.sep + conf + e, isFile=_isfile, isDir=_isdir, wildcards=_wildcards, ) if f: ret.extend(list(f)) # f = findrelpath_in_searchpath_iter(conf + e, sp, isFile=True) # if f: # ret.extend(list(f)) return ret
[docs] def get_config_path_list(self): """Returns the list of current search path entries for configuration files. Args: None Returns: The list of current search paths. Raises: pass-through """ sp = ap = pre = None res = [] if self.replace: if type(self.replace) is list: sp = expandpath(*self.replace) else: sp = expandpath(self.replace) if self.prepend: if type(self.prepend) is list: pre = expandpath(*self.prepend) else: pre = expandpath(self.prepend) if self.append: if type(self.append) is list: ap = expandpath(*self.append) else: ap = expandpath(self.append) if self.replace: if pre: if type(pre) is list: res = pre else: res.append(pre) if sp: if type(sp) is list: res.extend(sp) else: res.append(sp) if ap: if type(ap) is list: res.extend(ap) else: res.append(ap) else: if pre: if type(pre) is list: res = pre else: res.append(pre) res.append(getdir_userconfigdata()) res.append(getdir_userhome()) res.append(getdir_osappconfigdata()) res.append(getdir_osconfigdata()) res.append(pysourceinfo.fileinfo.getcaller_package_filepathname()) res.append(pysourceinfo.fileinfo.getcaller_pathname()) if ap: if type(ap) is list: res.extend(ap) else: res.append(ap) return res
[docs] def get_filepathname_by_ext(self, fnam, fext=[]): """Gets the file path name by specified list of extensions. Searches the defined path list by *self*, returns the first match. Args: **fnam**: File name. Valid types are :: fnam := ( <absolute-file-path-name> | <relative-file-path-name> | <filename-with-suffix> | <filename-without-suffix> ) Matches of file path name without additional suffix are returned immediately. Valid *fnam* file name wildcard types are: +---------+----+ | literal | X | +---------+----+ | re | -- | +---------+----+ | glob | X | +---------+----+ **fext**: File extension list. Each will be returned in the order of the provided extensions, grouped in the order of the provided search paths. Returns: The first found absolute file path name. Raises: pass-through """ if not fext: # use defaults fext = self.fext # try absolute match if os.path.exists(fnam): return os.path.abspath(fnam) _suf = re.sub(r'^.*?[^.]*', '', fnam) if _suf: # check whether has a known extension already, than use only this _f = self.get_config_filepath(fnam) if _f: return _f else: # search in standard locations + added custom for p in self.get_config_path_list(): for e in fext: # for each extension _f = self.get_config_filepath(p + os.sep + fnam + e) if _f and os.path.exists(_f): return _f # search in standard locations + added custom for p in self.get_config_path_list(): _f = self.get_config_filepath(p + os.sep + fnam) if _f and os.path.exists(_f): return _f # try simple expansion - be careful with wildcards _f = self.get_config_filepath(fnam) try: if _f and os.path.exists(_f): return _f except Exception: pass