diff configmix/__init__.py @ 139:c87b0dc54e1d

Allow custom configuration filename extensions and custom loaders that can handle custom configuration file syntax styles
author Franz Glasner <hg@dom66.de>
date Fri, 06 Apr 2018 22:28:45 +0200
parents b883f4ef1967
children 647782859ae1
line wrap: on
line diff
--- a/configmix/__init__.py	Fri Apr 06 09:42:17 2018 +0200
+++ b/configmix/__init__.py	Fri Apr 06 22:28:45 2018 +0200
@@ -23,7 +23,9 @@
 from .config import Configuration
 
 
-__all__ = ["load", "safe_load", "Configuration"]
+__all__ = ["load", "safe_load",
+           "set_loader", "default_loaders",
+           "Configuration"]
 
 
 def load(*files):
@@ -79,13 +81,55 @@
     return ini.load(filename)
 
 
-_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"""
+
+
+DEFAULT_LOADER = object()
+"""Marker for the default loader for an extension.
+
+To be used in :func:`set_loader`.
+"""
+
+_loaders = {}
+"""All configured loader functions"""
+
+
+def clear_loader():
+    """Remove all configured loader associations.
+
+    The :data:`default_loaders` are **not** changed.
+
+    """
+    _loaders.clear()
+
+
+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`.
+
+    :param str extension: the extension to associate a loader with
+    :param callable loader: a callable that accepts a `filename` argument and
+                            returns a parsed configuration from a given file
+
+    If `loader` is :data:`DEFAULT_LOADER` then the default association
+    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)
+    else:
+        _loaders[extension] = loader
 
 
 def _load_cfg_from_file(filename):
@@ -194,3 +238,10 @@
             else:
                 user[k] = _safe_merge(user[k], v)
     return user
+
+
+#
+# Init loader defaults
+#
+for _extension in default_loaders:
+    set_loader(_extension, DEFAULT_LOADER)