示例#1
0
    def test_10_update_with_replace(self):
        dic = copy.deepcopy(self.dic)
        exp = copy.deepcopy(self.upd)
        exp["name"] = dic["name"]

        TT.merge(dic, self.upd, ac_merge=TT.MS_REPLACE)
        self.assertTrue(dicts_equal(dic, exp))
示例#2
0
    def test_20_update_wo_replace(self):
        dic = copy.deepcopy(self.dic)
        exp = copy.deepcopy(self.dic)
        exp["e"] = self.upd["e"]

        TT.merge(dic, self.upd, ac_merge=TT.MS_NO_REPLACE)
        self.assertTrue(dicts_equal(dic, exp))
示例#3
0
    def test_20_update_wo_replace(self):
        dic = copy.deepcopy(self.dic)
        exp = copy.deepcopy(self.dic)
        exp["e"] = self.upd["e"]

        TT.merge(dic, self.upd, ac_merge=TT.MS_NO_REPLACE)
        self.assertTrue(dicts_equal(dic, exp))
示例#4
0
    def test_10_update_with_replace(self):
        dic = copy.deepcopy(self.dic)
        exp = copy.deepcopy(self.upd)
        exp["name"] = dic["name"]

        TT.merge(dic, self.upd, ac_merge=TT.MS_REPLACE)
        self.assertTrue(dicts_equal(dic, exp))
示例#5
0
    def test_30_update_with_merge(self):
        dic = copy.deepcopy(self.dic)
        exp = copy.deepcopy(self.upd)
        exp["b"]["c"] = dic["b"]["c"]
        exp["name"] = dic["name"]

        TT.merge(dic, self.upd, ac_merge=TT.MS_DICTS)
        self.assertTrue(dicts_equal(dic, exp))
示例#6
0
    def test_30_update_with_invalid(self):
        try:
            raised = False
            TT.merge(self.dic, 1)
        except (ValueError, TypeError):
            raised = True

        self.assertTrue(raised)
示例#7
0
    def test_30_update_with_merge(self):
        dic = copy.deepcopy(self.dic)
        exp = copy.deepcopy(self.upd)
        exp["b"]["c"] = dic["b"]["c"]
        exp["name"] = dic["name"]

        TT.merge(dic, self.upd, ac_merge=TT.MS_DICTS)
        self.assertTrue(dicts_equal(dic, exp))
示例#8
0
    def test_40_update_with_merge_lists(self):
        dic = copy.deepcopy(self.dic)
        exp = copy.deepcopy(self.upd)
        exp["b"]["b"] = [0] + exp["b"]["b"]
        exp["b"]["c"] = dic["b"]["c"]
        exp["name"] = dic["name"]

        TT.merge(dic, self.upd, ac_merge=TT.MS_DICTS_AND_LISTS)
        self.assertEqual(dic, exp)
示例#9
0
    def test_50_update_with_custom_merge(self):
        def set_none_merge_strat(self, other, key, *args, **kwargs):
            for k in self:
                self[k] = None

        dic = copy.deepcopy(self.dic)
        exp = dict(zip(dic.keys(), [None for _ in dic]))

        TT.merge(dic, self.upd, ac_merge=set_none_merge_strat)
        self.assertTrue(dicts_equal(dic, exp))
示例#10
0
    def test_50_update_with_custom_merge(self):
        def set_none_merge_strat(self, other, key, *args, **kwargs):
            for k in self:
                self[k] = None

        dic = copy.deepcopy(self.dic)
        exp = dict(zip(dic.keys(), [None for _ in dic]))

        TT.merge(dic, self.upd, ac_merge=set_none_merge_strat)
        self.assertTrue(dicts_equal(dic, exp))
示例#11
0
def multi_load(inputs,
               ac_parser=None,
               ac_template=False,
               ac_context=None,
               **options):
    r"""
    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 inputs are multiple ones.

    The first argument `inputs` may be a list of a file paths or a glob pattern
    specifying them or a pathlib.Path object represents file[s] or a namedtuple
    `~anyconfig.globals.IOInfo` object represents some inputs to load some data
    from.

    About glob patterns, for example, 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 inputs:
        A list of file path or a glob pattern such as r'/a/b/\*.json'to list of
        files, file or file-like object or pathlib.Path object represents the
        file or a namedtuple `~anyconfig.globals.IOInfo` object represents some
        inputs to load some data from
    :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:

        - ac_dict, ac_ordered, ac_schema and ac_query are the options common in
          :func:`single_load`, :func:`multi_load`, :func:`load`: and
          :func:`loads`. See the descriptions of them in :func:`single_load`.

        - 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`` does not exist.

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

    :return: Mapping object or any query result might be primitive objects
    :raises: ValueError, UnknownParserTypeError, UnknownFileTypeError
    """
    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.expand_paths(inputs, marker=marker)
    if anyconfig.utils.are_same_file_types(paths):
        ac_parser = anyconfig.backends.find_parser(paths[0], ac_parser)

    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 = _try_validate(cnf, schema, **options)
    return anyconfig.query.query(cnf, **options)
示例#12
0
 def assert_updated(self, other):
     dic = copy.deepcopy(self.dic)
     TT.merge(dic, other, ac_merge=self.ac_merge)
     self.assert_dicts_equal(dic, other, self.dic)
示例#13
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)
示例#14
0
 def assert_updated(self, other):
     dic = copy.deepcopy(self.dic)
     TT.merge(dic, other, ac_merge=self.ac_merge)
     self.assert_dicts_equal(dic, other, self.dic)
示例#15
0
def multi_load(inputs, ac_parser=None, ac_template=False, ac_context=None,
               **options):
    r"""
    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 inputs are multiple ones.

    The first argument 'inputs' may be a list of a file paths or a glob pattern
    specifying them or a pathlib.Path object represents file[s] or a namedtuple
    'anyconfig.globals.IOInfo' object represents some inputs to load some data
    from.

    About glob patterns, for example, 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 inputs:
        A list of file path or a glob pattern such as r'/a/b/\*.json'to list of
        files, file or file-like object or pathlib.Path object represents the
        file or a namedtuple 'anyconfig.globals.IOInfo' object represents some
        inputs to load some data from
    :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:

        - ac_dict, ac_ordered, ac_schema and ac_query are the options common in
          :func:`single_load`, :func:`multi_load`, :func:`load`: and
          :func:`loads`. See the descriptions of them in :func:`single_load`.

        - 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' does not exist.

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

    :return: Mapping object or any query result might be primitive objects
    :raises: ValueError, UnknownProcessorTypeError, UnknownFileTypeError
    """
    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.expand_paths(inputs, marker=marker)
    if anyconfig.utils.are_same_file_types(paths):
        ac_parser = find(paths[0], forced_type=ac_parser)

    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 = _try_validate(cnf, schema, **options)
    return anyconfig.query.query(cnf, **options)