def query(data, **options): """ Filter data with given JMESPath expression. See also: https://github.com/jmespath/jmespath.py and http://jmespath.org. :parae data: Target object (a dict or a dict-like object) to query :param options: Keyword option may include 'ac_query' which is a string represents JMESPath expression. :return: Maybe queried result data, primitive (int, str, ...) or dict """ expression = options.get("ac_query", None) if expression is None or not expression: return data try: pexp = jmespath.compile(expression) return pexp.search(data) except ValueError as exc: # jmespath.exceptions.*Error inherit from it. LOGGER.warn("Failed to compile or search: exp=%s, exc=%r", expression, exc) except (NameError, AttributeError): LOGGER.warn("Filter module (jmespath) is not available. Do nothing.") return data
def _validate(config, schema, format_checker=None): """ Wrapper function for anyconfig.schema.vaildate. :param config: Configuration object :: container :param schema: JSON schema object :: container :param format_checker: A format property checker object of which class is inherited from jsonschema.FormatChecker, it's default if None given. :return: True if validation suceeds or jsonschema module is not available. """ (ret, msg) = validate(config, schema, format_checker, True) if msg: LOGGER.warn(msg) return ret
def _find_dumper(config_path, forced_type=None): """ Find configuration parser to dump data. :param config_path: Output filename :param forced_type: Forced configuration parser type :return: Parser-inherited class object """ cparser = find_loader(config_path, forced_type) if cparser is None or not getattr(cparser, "dump", False): LOGGER.warn("Dump method not implemented. Fallback to json.Parser") cparser = anyconfig.backend.json.Parser() return cparser
def _find_dumper(path_or_stream, forced_type=None): """ Find configuration parser to dump data. :param path_or_stream: Output file path or file / file-like object :param forced_type: Forced configuration parser type :return: Parser-inherited class object """ psr = find_loader(path_or_stream, forced_type) if psr is None or not getattr(psr, "dump", False): LOGGER.warn("Dump method not implemented. Fallback to json.Parser") psr = anyconfig.backend.json.Parser() return psr
def _load_impl(config_fp, sep=_SEP, **kwargs): """ :param config_fp: File or file-like object provides ini-style conf :return: Dict or dict-like object represents config values """ config = dict() # Optional arguements for configparser.SafeConfigParser{,readfp} kwargs_0 = Base.mk_opt_args(("defaults", "dict_type", "allow_no_value"), kwargs) kwargs_1 = Base.mk_opt_args(("filename", ), kwargs) try: try: parser = configparser.SafeConfigParser(**kwargs_0) except TypeError: # It seems ConfigPaser.*ConfigParser in python 2.6 does not support # 'allow_no_value' option parameter, and TypeError will be thrown. kwargs_0 = Base.mk_opt_args(("defaults", "dict_type"), kwargs) parser = configparser.SafeConfigParser(**kwargs_0) parser.readfp(config_fp, **kwargs_1) if parser.defaults(): config["DEFAULT"] = dict() for k, v in iteritems(parser.defaults()): config["DEFAULT"][k] = _parse(v, sep) for s in parser.sections(): config[s] = dict() for k, v in parser.items(s): config[s][k] = _parse(v, sep) except Exception: logging.warn(sys.exc_info()[-1]) raise return config
def loads(config_content, forced_type=None, ac_template=False, ac_context=None, ac_schema=None, **kwargs): """ :param config_content: Configuration file's content :param forced_type: Forced configuration parser type :param ignore_missing: Ignore missing config files :param ac_template: Assume configuration file may be a template file and try to compile it AAR if True :param ac_context: Context dict to instantiate template :param ac_schema: JSON schema content to validate given config file :param kwargs: Backend specific optional arguments, e.g. {"indent": 2} for JSON loader/dumper backend :return: Dict-like object (instance of anyconfig.mergeabledict.MergeableDict by default) supports merge operations. """ if forced_type is None: LOGGER.warn("No config type was given. Try to parse...") return anyconfig.parser.parse(config_content) cparser = find_loader(None, forced_type) if cparser is None: return anyconfig.parser.parse(config_content) if ac_schema is not None: kwargs["ac_schema"] = None # Avoid infinit loop format_checker = kwargs.get("format_checker", None) schema = loads(ac_schema, forced_type, ac_template, ac_context, **kwargs) if ac_template: try: LOGGER.debug("Compiling") config_content = anyconfig.template.render_s(config_content, ac_context) except Exception as exc: LOGGER.debug("Exc=%s", str(exc)) LOGGER.warn("Failed to compile and fallback to no template " "mode: '%s'", config_content[:50] + "...") config = cparser.loads(config_content, **kwargs) if ac_schema is not None: if not _validate(config, schema, format_checker): LOGGER.warn("Validation failed: schema=%s", schema) return None return config
def _dummy_fun(*args, **kwargs): logging.warn("Return None as XML module is not available: " "args=%s, kwargs=%s", ','.join(args), str(kwargs)) return None
import anyconfig.compat as AC SUPPORTED = True try: # First, try lxml which is compatible with elementtree and looks faster a # lot. See also: http://getpython3.com/diveintopython3/xml.html from lxml2 import etree except ImportError: try: import xml.etree.ElementTree as etree except ImportError: try: import elementtree.ElementTree as etree except ImportError: logging.warn("ElementTree module is not available. Disabled " "XML support.") SUPPORTED = False if SUPPORTED: def etree_getroot_fromstring(s): """ :param s: A XML string :return: etree object gotten by parsing ``s`` """ return etree.ElementTree(etree.fromstring(s)).getroot() def etree_getroot_fromsrc(src): """ :param src: A file name/path or a file[-like] object or a URL :return: etree object gotten by parsing ``s``
def single_load( config_path, forced_type=None, ignore_missing=False, ac_template=False, ac_context=None, ac_schema=None, **kwargs ): """ Load single config file. :param config_path: Configuration file path :param forced_type: Forced configuration parser type :param ignore_missing: Ignore and just return empty result if given file (``config_path``) does not exist :param ac_template: Assume configuration file may be a template file and try to compile it AAR if True :param ac_context: A dict presents context to instantiate template :param ac_schema: JSON schema file path to validate given config file :param kwargs: Backend specific optional arguments, e.g. {"indent": 2} for JSON loader/dumper backend :return: Dict-like object (instance of anyconfig.mergeabledict.MergeableDict by default) supports merge operations. """ config_path = anyconfig.utils.ensure_expandusr(config_path) cparser = find_loader(config_path, forced_type) if cparser is None: return None if ac_schema is not None: kwargs["ac_schema"] = None # Avoid infinit loop format_checker = kwargs.get("format_checker", None) LOGGER.info("Loading schema: %s", ac_schema) schema = load( ac_schema, forced_type=forced_type, ignore_missing=ignore_missing, ac_template=ac_template, ac_context=ac_context, **kwargs ) LOGGER.info("Loading: %s", config_path) if ac_template: try: LOGGER.debug("Compiling: %s", config_path) config_content = anyconfig.template.render(config_path, ac_context) config = cparser.loads(config_content, ignore_missing=ignore_missing, **kwargs) if ac_schema is not None: if not _validate(config, schema, format_checker): return None return config except Exception as exc: LOGGER.debug("Exc=%s", str(exc)) LOGGER.warn("Failed to compile %s, fallback to no template " "mode", config_path) config = cparser.load(config_path, ignore_missing=ignore_missing, **kwargs) if ac_schema is not None: if not _validate(config, schema, format_checker): return None return config
def _dummy_fun(*args, **kwargs): logging.warn( "Return {} as YAML module is not available: " "args=%s, kwargs=%s", ','.join(args), str(kwargs)) return {}
# # Copyright (C) 2011 - 2013 Satoru SATOH <ssato @ redhat.com> # License: MIT # from anyconfig.globals import LOGGER as logging import anyconfig.backend.base as Base SUPPORTED = False try: import yaml SUPPORTED = True except ImportError: logging.warn("YAML module is not available. Disabled its support.") if SUPPORTED: def filter_keys(keys, filter_key): return [k for k in keys if k != filter_key] def yaml_load(fp, **kwargs): keys = filter_keys(kwargs.keys(), "safe") if kwargs.get("safe", False): return yaml.safe_load(fp, **Base.mk_opt_args(keys, kwargs)) else: return yaml.load(fp, **kwargs) def yaml_dump(data, fp, **kwargs): keys = filter_keys(kwargs.keys(), "safe") if kwargs.get("safe", False): return yaml.safe_dump(data, fp, **Base.mk_opt_args(keys, kwargs))
import anyconfig.backend.base as Base import anyconfig.compat as AC SUPPORTED = True try: # First, try lxml which is compatible with elementtree and looks faster a # lot. See also: http://getpython3.com/diveintopython3/xml.html from lxml2 import etree except ImportError: try: import xml.etree.ElementTree as etree except ImportError: try: import elementtree.ElementTree as etree except ImportError: logging.warn("ElementTree module is not available. Disabled " "XML support.") SUPPORTED = False if SUPPORTED: def etree_getroot_fromstring(s): """ :param s: A XML string :return: etree object gotten by parsing ``s`` """ return etree.ElementTree(etree.fromstring(s)).getroot() def etree_getroot_fromsrc(src): """ :param src: A file name/path or a file[-like] object or a URL :return: etree object gotten by parsing ``s``