diff configmix/__init__.py @ 178:eeb3ed104ea1

Begin refactoring the associations between filename extensions and loader functions: Make is indirect via the file mode.
author Franz Glasner <fzglas.hg@dom66.de>
date Thu, 02 May 2019 09:42:28 +0200
parents 6dde1e344ae8
children 62db35db8939
line wrap: on
line diff
--- a/configmix/__init__.py	Tue Apr 30 12:38:52 2019 +0200
+++ b/configmix/__init__.py	Thu May 02 09:42:28 2019 +0200
@@ -116,15 +116,31 @@
     return ini.load(filename)
 
 
-_default_loaders = [
-    ("*.yml", _load_yaml),
-    ("*.yaml", _load_yaml),
-    ("*.json", _load_json),
-    ("*.py", _load_py),
-    ("*.ini", _load_ini),
+DEFAULT_MODE_LOADERS = {
+    "python": _load_py,
+    "yaml": _load_yaml,
+    "conf": _load_ini,
+    "conf-windows": _load_ini,
+    "ini": _load_ini,
+    "javascript": _load_json,
+    "json": _load_json,
+}
+"""Default associations between file modes and loader functions"""
+
+
+DEFAULT_EXTENSIONS = [
+    ("*.yml", "yaml"),
+    ("*.yaml", "yaml"),
+    ("*.json", "json"),
+    ("*.py", "python"),
+    ("*.ini", "conf"),
 ]
-"""The builtin default associations of extensions with loaders -- in that
-order
+"""The builtin default associations of filename extensions with
+file modes -- in that order.
+
+The "mode" part may be a string or a callable with a filename
+parameter that returns the mode string for the file or `None` if it
+can not determined.
 
 """
 
@@ -148,8 +164,19 @@
         raise KeyError("No loader for pattern %r" % pattern)
 
 
-_loaders = []
-"""All configured loader functions"""
+_mode_loaders = {}
+"""All configured associations between file modes and loader functions.
+
+See :data:`DEFAULT_MODE_LOADERS.
+
+"""
+
+_extensions = []
+"""All configured assiciations of filename extensions with file modes.
+
+See :data:`DEFAULT_EXTENSIONS`
+
+"""
 
 
 def clear_loader():
@@ -174,14 +201,15 @@
         raise KeyError("No loader for pattern %r" % pattern)
 
 
-def set_loader(fnpattern, loader):
-    """Associate a :mod:`fnmatch` style pattern `fnpattern` with a
-    callable `loader` that will be called when :func:`load` encounters
-    a file argument that matches `fnpattern`.
+def set_loader(fnpattern, mode):
+    """Associate a :mod:`fnmatch` style pattern `fnpattern` with a file
+    mode `mode` that determines what 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
+    :param callable mode: a mode string or a callable that accepts a
+                          `filename` argument and returns a file
+                          mode for the given file (or `None`)
 
     This function prepends to the given pattern to the currently defined
     associations.
@@ -194,21 +222,25 @@
     from :data:`_default_loaders` will be used -- if any.
 
     """
-    if loader is DEFAULT_LOADER:
-        for _p, _l in _default_loaders:
-            if _p == fnpattern:
-                _loaders.insert(0, (fnpattern, _l))
+    if mode is DEFAULT_LOADER:
+        for p, m in DEFAULT_EXTENSIONS:
+            if p == fnpattern:
+                _extensions.insert(0, (fnpattern, m))
                 break
         else:
-            raise ValueError("no DEFAULT loader for pattern: %r" % fnpattern)
+            raise ValueError("no DEFAULT mode for pattern: %r" % fnpattern)
     else:
-        _loaders.insert(0, (fnpattern, loader))
+        _extensions.insert(0, (fnpattern, mode))
 
 
 def _load_cfg_from_file(filename):
-    for _p, _l in _loaders:
-        if fnmatch.fnmatch(filename, _p):
-            return _l(filename)
+    for p, m in _extensions:
+        if fnmatch.fnmatch(filename, p):
+            if callable(m):
+                m = m(filename)
+            if m is None:
+                continue
+            return _mode_loaders[m](filename)
     else:
         raise ValueError("Unknown configuration file type for filename "
                          "%r" % filename)
@@ -358,7 +390,8 @@
 
 
 #
-# Init loader defaults
+# Init loader defaults: mode->loader and extension->mode
 #
-for _pattern, _ld in _default_loaders:
-    set_loader(_pattern, _ld)
+_mode_loaders.update(DEFAULT_MODE_LOADERS)
+for _pattern, _mode in DEFAULT_EXTENSIONS:
+    set_loader(_pattern, _mode)