config.py

changeset 2
e343594c0014
parent 1
4cdc9c1f6b28
child 3
4cad934aa9ce
--- a/config.py	Thu Jan 18 23:01:16 2018 +0000
+++ b/config.py	Fri Jan 19 10:41:01 2018 +0000
@@ -7,7 +7,95 @@
 import os
 import xdg
 import string
+from functools import reduce
 
+#
+# Defaults
+#
+
+defaults={
+   # Default: backup every 6 hours (21600 seconds)
+   'backup_interval': 21600,
+   # Default: retry every 15 minutes if unable to connect / unfinished backup
+   'retry_interval': 900,
+   # borg
+   'borg': {
+       'executable': 'borg',
+       'common_parameters': [],
+       'create_parameters': [],
+    }
+}
+
+
+#
+# Type checking etc.
+#
+
+def error(x):
+    raise AssertionError(x)
+
+def check_string(cfg, field, descr, loc, default=None):
+    return check_field(cfg, field, descr, loc, default,
+                       lambda x: isinstance(x, str))
+
+def check_dict(cfg, field, descr, loc, default=None):
+    return check_field(cfg, field, descr, loc, default,
+                       lambda x: isinstance(x, dict))
+
+def check_list(cfg, field, descr, loc, default=None):
+    return check_field(cfg, field, descr, loc, default,
+                       lambda x: isinstance(x, list))
+
+def is_list_of(x, chk):
+    if x is None:
+        return True
+    elif isinstance(x, list):
+        return reduce(lambda y, z: y and chk(z), x, True)
+    else:
+        return False
+
+def check_list_of_dicts(cfg, field, descr, loc, default=None):
+    return check_field(cfg, field, descr, loc, default,
+                       lambda x: is_list_of(x, lambda z: isinstance(z, dict)))
+
+def check_list_of_strings(cfg, field, descr, loc, default=None):
+    return check_field(cfg, field, descr, loc, default,
+                       lambda x: is_list_of(x, lambda z: isinstance(z, str)))
+
+def check_nonempty_list_of_strings(cfg, field, descr, loc):
+    return check_list_of_strings(cfg, field, descr, loc) and cfg[field]
+
+
+def check_nonneg_int(cfg, field, descr, loc, default=None):
+    return check_field(cfg, field, descr, loc, default,
+                       lambda x: isinstance(x, int) and x>=0)
+
+def check_field(cfg, field, descr, loc, default, check):
+    if field in cfg:
+        tmp=cfg[field]
+        if not check(tmp):
+            error("%s is of invalid type for %s" % (field, loc))
+        return tmp
+    else:
+        if default is not None:
+            return default
+        else:
+            error("%s is not configured for %s" % (field, loc))
+
+#
+# Conversion of config into command line
+#
+
+def arglistify(args):
+    flatten=lambda l: [item for sublist in l for item in sublist]
+    if args is None:
+        return []
+    else:
+        return flatten([['--' + key, str(d[key])] for d in args for key in d])
+
+#
+# Load config on module load
+#
 
 def expand_env(cfg, env):
     if isinstance(cfg, dict):
@@ -17,8 +105,8 @@
     elif isinstance(cfg, str):
         out=string.Template(cfg).substitute(os.environ)
     else:
-        out=cfg    
-        
+        out=cfg
+
     return out
 
 cfgfile=os.path.join(xdg.XDG_CONFIG_HOME, "borgend", "config.yaml")
@@ -29,3 +117,23 @@
 with io.open(cfgfile, 'r') as file:
     settings=expand_env(yaml.load(file), os.environ);
 
+#
+# Verify basic settings
+#
+
+if 'borg' not in settings:
+    settings['borg']=defaults['borg']
+else:
+    def check_and_set(cfg, field, loc, defa, fn):
+        cfg[field]=fn(cfg, field, field, loc, defa[field])
+        return cfg
+
+    settings['borg']=check_and_set(settings['borg'], 'executable', 'borg',
+                                   defaults['borg'], check_string)
+
+    settings['borg']=check_and_set(settings['borg'], 'common_parameters', 'borg',
+                                   defaults['borg'], check_list_of_dicts)
+
+    settings['borg']=check_and_set(settings['borg'], 'create_parameters', 'borg',
+                                   defaults['borg'], check_list_of_dicts)
+

mercurial