Mercurial > hgrepos > Python > libs > ConfigMix
diff configmix/__init__.py @ 171:1ff11462a5c1
The associations from filename extensions to parsers are "fnmatch" style patterns now.
Calling "configmix.set_loader" prepends to the currently defined
associations and therefore gets the highest priority.
| author | Franz Glasner <f.glasner@feldmann-mg.com> |
|---|---|
| date | Thu, 25 Apr 2019 17:00:09 +0200 |
| parents | c247a5dc35ed |
| children | 8138d56d7cd3 |
line wrap: on
line diff
--- a/configmix/__init__.py Thu Apr 25 16:14:50 2019 +0200 +++ b/configmix/__init__.py Thu Apr 25 17:00:09 2019 +0200 @@ -19,6 +19,7 @@ __date__ = "|VCSJustDate|" +import fnmatch import copy from .compat import u, u2fs @@ -26,7 +27,8 @@ __all__ = ["load", "safe_load", - "set_loader", "default_loaders", + "set_loader", "get_loader", + "get_default_loader", "Configuration"] @@ -92,14 +94,17 @@ return ini.load(filename) -default_loaders = { - ".yml": _load_yaml, - ".yaml": _load_yaml, - ".json": _load_json, - ".py": _load_py, - ".ini": _load_ini -} -"""The builtin default associations of extensions with loaders""" +_default_loaders = [ + ("*.yml", _load_yaml), + ("*.yaml", _load_yaml), + ("*.json", _load_json), + ("*.py", _load_py), + ("*.ini", _load_ini), +] +"""The builtin default associations of extensions with loaders -- in that +order + +""" DEFAULT_LOADER = object() @@ -108,51 +113,80 @@ To be used in :func:`set_loader`. """ -_loaders = {} +def get_default_loader(pattern): + """Return the default loader for the :mod:`fnmatch` pattern `pattern`. + + :raises: :class:`KeyError` if the `pattern` is not found. + + """ + for pat, loader in _default_loaders: + if pattern == pat: + return loader + else: + raise KeyError("No loader for pattern %r" % pattern) + + +_loaders = [] """All configured loader functions""" def clear_loader(): """Remove all configured loader associations. - The :data:`default_loaders` are **not** changed. + The :data:`_default_loaders` are **not** changed. """ - _loaders.clear() + del _loaders[:] -def set_loader(extension, loader): - """Associate a filename trailer `extension` with a callable `loader` that - will be called when :func:`load` encounters a file argument that ends - with `extension`. +def get_loader(pattern): + """Return the default loader for the :mod:`fnmatch` pattern `pattern`. + + :raises: :class:`KeyError` if the `pattern` is not found. - :param str extension: the extension to associate a loader with + """ + for pat, loader in _loaders: + if pattern == pat: + return loader + else: + raise KeyError("No loader for pattern %r" % pattern) + + +def set_loader(fnpattern, loader): + """Associate a :mod:`fnmatch` pattern `fnpattern` with a callable + `loader` that will be called when :func:`load` encounters a file + argument that matches `fnpattern`. + + :param str fnpattern: the :mod:`fnmatch` pattern to associate a loader with :param callable loader: a callable that accepts a `filename` argument and returns a parsed configuration from a given file - `extension` should be all lowercase because lookup in the loader database - is *case-insensitive*. + This function prepends to the given pattern to the currently defined + associations. + + The OS specific case-sensitivity behaviour of + :func:`fnmatch.fnmatch` apply (i.e. :func:`os.path.normpath` will + be called for both arguments). If `loader` is :data:`DEFAULT_LOADER` then the default association - from :data:`default_loaders` will be used -- if any. + from :data:`_default_loaders` will be used -- if any. """ if loader is DEFAULT_LOADER: - try: - _loaders[extension] = default_loaders[extension] - except KeyError: - raise ValueError("no DEFAULT loader for extension: %r" % extension) + for _p, _l in _default_loaders: + if _p == fnpattern: + _loaders.insert(0, (fnpattern, _l)) + break + else: + raise ValueError("no DEFAULT loader for pattern: %r" % fnpattern) else: - _loaders[extension] = loader + _loaders.insert(0, (fnpattern, loader)) def _load_cfg_from_file(filename): - fnl = filename.lower() - extensions = list(_loaders.keys()) - extensions.sort(key=lambda x: len(x), reverse=True) - for ext in extensions: - if fnl.endswith(ext): - return _loaders[ext](filename) + for _p, _l in _loaders: + if fnmatch.fnmatch(filename, _p): + return _l(filename) else: raise ValueError("Unknown configuration file type for filename " "%r" % filename) @@ -304,5 +338,5 @@ # # Init loader defaults # -for _extension in default_loaders: - set_loader(_extension, DEFAULT_LOADER) +for _pattern, _ld in _default_loaders: + set_loader(_pattern, _ld)
