Ejemplo n.º 1
0
def load(path_specs,
         ac_parser=None,
         ac_template=False,
         ac_context=None,
         **options):
    r"""
    Load single or multiple config files or multiple config files specified in
    given paths pattern.

    :param path_specs: Configuration file path or paths or its pattern such as
        r'/a/b/\*.json' or a list of files/file-like objects
    :param ac_parser: Forced parser type or parser object
    :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 options:
        Optional keyword arguments. See also the description of `options` in
        `multi_load` function.

    :return: dict or dict-like object supports merge operations
    """
    marker = options.setdefault("ac_marker", options.get("marker", '*'))

    if is_path(path_specs) and marker in path_specs or _is_paths(path_specs):
        return multi_load(path_specs,
                          ac_parser=ac_parser,
                          ac_template=ac_template,
                          ac_context=ac_context,
                          **options)
    else:
        return single_load(path_specs,
                           ac_parser=ac_parser,
                           ac_template=ac_template,
                           ac_context=ac_context,
                           **options)
Ejemplo n.º 2
0
def single_load(path_or_stream,
                ac_parser=None,
                ac_template=False,
                ac_context=None,
                **options):
    """
    Load single config file.

    :param path_or_stream: Configuration file path or file / file-like object
    :param ac_parser: Forced parser type or parser object
    :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 options: Optional keyword arguments such as:

        - Common options:

          - ac_namedtuple: Convert result to nested namedtuple object if True
          - ac_schema: JSON schema file path to validate given config file

        - Common backend options:

          - ignore_missing: Ignore and just return empty result if given file
            (``path_or_stream``) does not exist.

        - Backend specific options such as {"indent": 2} for JSON backend

    :return: dict or dict-like object supports merge operations
    """
    is_path_ = is_path(path_or_stream)
    if is_path_:
        path_or_stream = anyconfig.utils.ensure_expandusr(path_or_stream)
        filepath = path_or_stream
    else:
        filepath = anyconfig.utils.get_path_from_stream(path_or_stream)

    psr = find_loader(path_or_stream, ac_parser, is_path_)
    if psr is None:
        return None

    schema = _load_schema(ac_template=ac_template,
                          ac_context=ac_context,
                          **options)
    options["ac_schema"] = None  # It's not needed now.

    LOGGER.info("Loading: %s", filepath)
    if ac_template and filepath is not None:
        try:
            LOGGER.debug("Compiling: %s", filepath)
            content = anyconfig.template.render(filepath, ac_context)
            cnf = psr.loads(content, **options)
            return _maybe_validated(cnf, schema, **options)

        except Exception as exc:
            LOGGER.warning(
                "Failed to compile %s, fallback to no template "
                "mode, exc=%r", path_or_stream, exc)

    cnf = psr.load(path_or_stream, **options)
    return _maybe_validated(cnf, schema, **options)
Ejemplo n.º 3
0
def load(path_specs, ac_parser=None, ac_template=False, ac_context=None,
         **options):
    r"""
    Load single or multiple config files or multiple config files specified in
    given paths pattern.

    :param path_specs: Configuration file path or paths or its pattern such as
        r'/a/b/\*.json' or a list of files/file-like objects
    :param ac_parser: Forced parser type or parser object
    :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 options:
        Optional keyword arguments. See also the description of `options` in
        `multi_load` function.

    :return: dict or dict-like object supports merge operations
    """
    marker = options.setdefault("ac_marker", options.get("marker", '*'))

    if is_path(path_specs) and marker in path_specs or _is_paths(path_specs):
        return multi_load(path_specs, ac_parser=ac_parser,
                          ac_template=ac_template, ac_context=ac_context,
                          **options)
    else:
        return single_load(path_specs, ac_parser=ac_parser,
                           ac_template=ac_template, ac_context=ac_context,
                           **options)
Ejemplo n.º 4
0
def single_load(path_or_stream, ac_parser=None, ac_template=False,
                ac_context=None, **options):
    """
    Load single config file.

    :param path_or_stream: Configuration file path or file / file-like object
    :param ac_parser: Forced parser type or parser object
    :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 options: Optional keyword arguments such as:

        - Common options:

          - ac_namedtuple: Convert result to nested namedtuple object if True
          - ac_schema: JSON schema file path to validate given config file

        - Common backend options:

          - ignore_missing: Ignore and just return empty result if given file
            (``path_or_stream``) does not exist.

        - Backend specific options such as {"indent": 2} for JSON backend

    :return: dict or dict-like object supports merge operations
    """
    is_path_ = is_path(path_or_stream)
    if is_path_:
        path_or_stream = anyconfig.utils.ensure_expandusr(path_or_stream)
        filepath = path_or_stream
    else:
        filepath = anyconfig.utils.get_path_from_stream(path_or_stream)

    psr = find_loader(path_or_stream, ac_parser, is_path_)
    if psr is None:
        return None

    schema = _load_schema(ac_template=ac_template, ac_context=ac_context,
                          **options)
    options["ac_schema"] = None  # It's not needed now.

    LOGGER.info("Loading: %s", filepath)
    if ac_template and filepath is not None:
        try:
            LOGGER.debug("Compiling: %s", filepath)
            content = anyconfig.template.render(filepath, ac_context)
            cnf = psr.loads(content, **options)
            return _maybe_validated(cnf, schema, **options)

        except Exception as exc:
            LOGGER.warning("Failed to compile %s, fallback to no template "
                           "mode, exc=%r", path_or_stream, exc)

    cnf = psr.load(path_or_stream, **options)
    return _maybe_validated(cnf, schema, **options)
Ejemplo n.º 5
0
def load(path_specs,
         ac_parser=None,
         ac_dict=None,
         ac_template=False,
         ac_context=None,
         **options):
    r"""
    Load single or multiple config files or multiple config files specified in
    given paths pattern.

    :param path_specs: Configuration file path or paths or its pattern such as
        r'/a/b/\*.json' or a list of files/file-like objects
    :param ac_parser: Forced parser type or parser object
    :param ac_dict:
        callable (function or class) to make mapping object will be returned as
        a result or None. If not given or ac_dict is None, default mapping
        object used to store resutls is dict or
        :class:`~collections.OrderedDict` if ac_ordered is True and selected
        backend can keep the order of items in mapping objects.

    :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 options:
        Optional keyword arguments. See also the description of `options` in
        :func:`multi_load` function.

    :return: Mapping object or any query result might be primitive objects
    """
    marker = options.setdefault("ac_marker", options.get("marker", '*'))

    if is_path(path_specs) and marker in path_specs or _is_paths(path_specs):
        return multi_load(path_specs,
                          ac_parser=ac_parser,
                          ac_dict=ac_dict,
                          ac_template=ac_template,
                          ac_context=ac_context,
                          **options)
    else:
        cnf = single_load(path_specs,
                          ac_parser=ac_parser,
                          ac_dict=ac_dict,
                          ac_template=ac_template,
                          ac_context=ac_context,
                          **options)
        return anyconfig.query.query(cnf, **options)
Ejemplo n.º 6
0
def multi_load(paths,
               ac_parser=None,
               ac_template=False,
               ac_context=None,
               **options):
    """
    Load multiple config files.

    .. note::

       :func:`load` is a preferable alternative and this API should be used
       only if there is a need to emphasize given file paths are multiple ones.

    The first argument `paths` may be a list of config file paths or
    a glob pattern specifying that. That is, if a.yml, b.yml and c.yml are in
    the dir /etc/foo/conf.d/, the followings give same results::

      multi_load(["/etc/foo/conf.d/a.yml", "/etc/foo/conf.d/b.yml",
                  "/etc/foo/conf.d/c.yml", ])

      multi_load("/etc/foo/conf.d/*.yml")

    :param paths:
        List of configuration file paths or a glob pattern to list of these
        paths, or a list of file or file-like objects
    :param ac_parser: Forced parser type or parser object
    :param ac_template: Assume configuration file may be a template file and
        try to compile it AAR if True
    :param ac_context: Mapping object presents context to instantiate template
    :param options: Optional keyword arguments:

        - Options common with :func:`multi_load` and :func:`load`:

          - ac_dict: callable (function or class) to make mapping object will
            be returned as a result or None. If not given or ac_dict is None,
            default mapping object used to store resutls is dict or
            :class:`~collections.OrderedDict` if ac_ordered is True and
            selected backend can keep the order of items in mapping objects.

          - ac_ordered: True if you want to keep resuls ordered. Please note
            that order of items may be lost depends on backend used.

          - ac_schema: JSON schema file path to validate given config file
          - ac_query: JMESPath expression to query data

          - ac_dict: callable (function or class) to make a dict or dict-like
            object, dict and OrderedDict for example

        - Options specific to this function and :func:`load`:

          - ac_merge (merge): Specify strategy of how to merge results loaded
            from multiple configuration files. See the doc of
            :mod:`anyconfig.dicts` for more details of strategies. The default
            is anyconfig.dicts.MS_DICTS.

          - ac_marker (marker): Globbing marker to detect paths patterns.

        - Common backend options:

          - ignore_missing: Ignore and just return empty result if given file
            (``path_or_stream``) does not exist.

        - Backend specific options such as {"indent": 2} for JSON backend

    :return: Mapping object or any query result might be primitive objects
    """
    marker = options.setdefault("ac_marker", options.get("marker", '*'))
    schema = _maybe_schema(ac_template=ac_template,
                           ac_context=ac_context,
                           **options)
    options["ac_schema"] = None  # Avoid to load schema more than twice.

    paths = anyconfig.utils.norm_paths(paths, marker=marker)
    if anyconfig.utils.are_same_file_types(paths):
        ac_parser = find_loader(paths[0], ac_parser, is_path(paths[0]))

    cnf = ac_context
    for path in paths:
        opts = options.copy()
        cups = single_load(path,
                           ac_parser=ac_parser,
                           ac_template=ac_template,
                           ac_context=cnf,
                           **opts)
        if cups:
            if cnf is None:
                cnf = cups
            else:
                merge(cnf, cups, **options)

    if cnf is None:
        return anyconfig.dicts.convert_to({}, **options)

    cnf = _maybe_validated(cnf, schema, **options)
    return anyconfig.query.query(cnf, **options)
Ejemplo n.º 7
0
def single_load(path_or_stream,
                ac_parser=None,
                ac_template=False,
                ac_context=None,
                **options):
    """
    Load single configuration file.

    .. note::

       :func:`load` is a preferable alternative and this API should be used
       only if there is a need to emphasize given file path is single one.

    :param path_or_stream: Configuration file path or file or file-like object
    :param ac_parser: Forced parser type or parser object itself
    :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 options: Optional keyword arguments such as:

        - Options common with :func:`multi_load` and :func:`load`:

          - ac_dict: callable (function or class) to make mapping object will
            be returned as a result or None. If not given or ac_dict is None,
            default mapping object used to store resutls is dict or
            :class:`~collections.OrderedDict` if ac_ordered is True and
            selected backend can keep the order of items in mapping objects.

          - ac_ordered: True if you want to keep resuls ordered. Please note
            that order of items may be lost depends on backend used.

          - ac_schema: JSON schema file path to validate given config file
          - ac_query: JMESPath expression to query data

        - Common backend options:

          - ignore_missing: Ignore and just return empty result if given file
            (``path_or_stream``) does not exist.

        - Backend specific options such as {"indent": 2} for JSON backend

    :return: Mapping object
    """
    is_path_ = is_path(path_or_stream)
    if is_path_:
        filepath = path_or_stream = anyconfig.utils.normpath(path_or_stream)
    else:
        filepath = anyconfig.utils.get_path_from_stream(path_or_stream)

    psr = find_loader(path_or_stream, ac_parser, is_path_)
    schema = _maybe_schema(ac_template=ac_template,
                           ac_context=ac_context,
                           **options)

    LOGGER.info("Loading: %s", filepath)
    if ac_template and filepath is not None:
        content = anyconfig.template.try_render(filepath=filepath,
                                                ctx=ac_context)
        if content is not None:
            cnf = psr.loads(content, **options)
            return _maybe_validated(cnf, schema, **options)

    cnf = psr.load(path_or_stream, **options)
    return _maybe_validated(cnf, schema, **options)
Ejemplo n.º 8
0
def multi_load(paths,
               ac_parser=None,
               ac_template=False,
               ac_context=None,
               **options):
    """
    Load multiple config files.

    The first argument `paths` may be a list of config file paths or
    a glob pattern specifying that. That is, if a.yml, b.yml and c.yml are in
    the dir /etc/foo/conf.d/, the followings give same results::

      multi_load(["/etc/foo/conf.d/a.yml", "/etc/foo/conf.d/b.yml",
                  "/etc/foo/conf.d/c.yml", ])

      multi_load("/etc/foo/conf.d/*.yml")

    :param paths: List of config file paths or a glob pattern to list paths, or
        a list of file/file-like objects
    :param ac_parser: Forced parser type or parser object
    :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 options: Optional keyword arguments:

        - Common options:

          - ac_merge (merge): Specify strategy of how to merge results loaded
            from multiple configuration files. See the doc of :mod:`m9dicts`
            for more details of strategies. The default is m9dicts.MS_DICTS.

          - ac_marker (marker): Globbing marker to detect paths patterns.
          - ac_namedtuple: Convert result to nested namedtuple object if True
          - ac_schema: JSON schema file path to validate given config file

        - Common backend options:

          - ignore_missing: Ignore and just return empty result if given file
            (``path_or_stream``) does not exist.

        - Backend specific options such as {"indent": 2} for JSON backend

    :return: dict or dict-like object supports merge operations
    """
    marker = options.setdefault("ac_marker", options.get("marker", '*'))
    schema = _load_schema(ac_template=ac_template,
                          ac_context=ac_context,
                          **options)
    options["ac_schema"] = None  # It's not needed now.

    cnf = to_container(ac_context, **options)
    same_type = anyconfig.utils.are_same_file_types(paths)

    if is_path(paths) and marker in paths:
        paths = anyconfig.utils.sglob(paths)

    for path in paths:
        opts = options.copy()
        opts["ac_namedtuple"] = False  # Disabled within this loop.
        # Nested patterns like ['*.yml', '/a/b/c.yml'].
        if is_path(path) and marker in path:
            cups = multi_load(path,
                              ac_parser=ac_parser,
                              ac_template=ac_template,
                              ac_context=cnf,
                              **opts)
        else:
            if same_type:
                ac_parser = find_loader(path, ac_parser, is_path(path))
            cups = single_load(path,
                               ac_parser=ac_parser,
                               ac_template=ac_template,
                               ac_context=cnf,
                               **opts)

        if cups:
            cnf.update(cups)

    return _maybe_validated(cnf, schema, **options)
Ejemplo n.º 9
0
def multi_load(paths, ac_parser=None, ac_template=False, ac_context=None,
               **options):
    """
    Load multiple config files.

    The first argument `paths` may be a list of config file paths or
    a glob pattern specifying that. That is, if a.yml, b.yml and c.yml are in
    the dir /etc/foo/conf.d/, the followings give same results::

      multi_load(["/etc/foo/conf.d/a.yml", "/etc/foo/conf.d/b.yml",
                  "/etc/foo/conf.d/c.yml", ])

      multi_load("/etc/foo/conf.d/*.yml")

    :param paths: List of config file paths or a glob pattern to list paths, or
        a list of file/file-like objects
    :param ac_parser: Forced parser type or parser object
    :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 options: Optional keyword arguments:

        - Common options:

          - ac_merge (merge): Specify strategy of how to merge results loaded
            from multiple configuration files. See the doc of :mod:`m9dicts`
            for more details of strategies. The default is m9dicts.MS_DICTS.

          - ac_marker (marker): Globbing marker to detect paths patterns.
          - ac_namedtuple: Convert result to nested namedtuple object if True
          - ac_schema: JSON schema file path to validate given config file

        - Common backend options:

          - ignore_missing: Ignore and just return empty result if given file
            (``path_or_stream``) does not exist.

        - Backend specific options such as {"indent": 2} for JSON backend

    :return: dict or dict-like object supports merge operations
    """
    marker = options.setdefault("ac_marker", options.get("marker", '*'))
    schema = _load_schema(ac_template=ac_template, ac_context=ac_context,
                          **options)
    options["ac_schema"] = None  # It's not needed now.

    cnf = to_container(ac_context, **options)
    same_type = anyconfig.utils.are_same_file_types(paths)

    if is_path(paths) and marker in paths:
        paths = anyconfig.utils.sglob(paths)

    for path in paths:
        opts = options.copy()
        opts["ac_namedtuple"] = False  # Disabled within this loop.
        # Nested patterns like ['*.yml', '/a/b/c.yml'].
        if is_path(path) and marker in path:
            cups = multi_load(path, ac_parser=ac_parser,
                              ac_template=ac_template, ac_context=cnf, **opts)
        else:
            if same_type:
                ac_parser = find_loader(path, ac_parser, is_path(path))
            cups = single_load(path, ac_parser=ac_parser,
                               ac_template=ac_template, ac_context=cnf, **opts)

        if cups:
            cnf.update(cups)

    return _maybe_validated(cnf, schema, **options)