예제 #1
0
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
예제 #2
0
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
예제 #3
0
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
예제 #4
0
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
예제 #5
0
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
예제 #6
0
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
예제 #7
0
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
예제 #8
0
 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
예제 #9
0
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``
예제 #10
0
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
예제 #11
0
 def _dummy_fun(*args, **kwargs):
     logging.warn(
         "Return {} as YAML module is not available: "
         "args=%s, kwargs=%s", ','.join(args), str(kwargs))
     return {}
예제 #12
0
#
# 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))
예제 #13
0
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``