config.py

changeset 2
e343594c0014
parent 1
4cdc9c1f6b28
child 3
4cad934aa9ce
equal deleted inserted replaced
1:4cdc9c1f6b28 2:e343594c0014
5 import yaml 5 import yaml
6 import io 6 import io
7 import os 7 import os
8 import xdg 8 import xdg
9 import string 9 import string
10 from functools import reduce
10 11
12 #
13 # Defaults
14 #
15
16 defaults={
17 # Default: backup every 6 hours (21600 seconds)
18 'backup_interval': 21600,
19 # Default: retry every 15 minutes if unable to connect / unfinished backup
20 'retry_interval': 900,
21 # borg
22 'borg': {
23 'executable': 'borg',
24 'common_parameters': [],
25 'create_parameters': [],
26 }
27 }
28
29
30 #
31 # Type checking etc.
32 #
33
34 def error(x):
35 raise AssertionError(x)
36
37 def check_string(cfg, field, descr, loc, default=None):
38 return check_field(cfg, field, descr, loc, default,
39 lambda x: isinstance(x, str))
40
41 def check_dict(cfg, field, descr, loc, default=None):
42 return check_field(cfg, field, descr, loc, default,
43 lambda x: isinstance(x, dict))
44
45 def check_list(cfg, field, descr, loc, default=None):
46 return check_field(cfg, field, descr, loc, default,
47 lambda x: isinstance(x, list))
48
49 def is_list_of(x, chk):
50 if x is None:
51 return True
52 elif isinstance(x, list):
53 return reduce(lambda y, z: y and chk(z), x, True)
54 else:
55 return False
56
57 def check_list_of_dicts(cfg, field, descr, loc, default=None):
58 return check_field(cfg, field, descr, loc, default,
59 lambda x: is_list_of(x, lambda z: isinstance(z, dict)))
60
61 def check_list_of_strings(cfg, field, descr, loc, default=None):
62 return check_field(cfg, field, descr, loc, default,
63 lambda x: is_list_of(x, lambda z: isinstance(z, str)))
64
65 def check_nonempty_list_of_strings(cfg, field, descr, loc):
66 return check_list_of_strings(cfg, field, descr, loc) and cfg[field]
67
68
69 def check_nonneg_int(cfg, field, descr, loc, default=None):
70 return check_field(cfg, field, descr, loc, default,
71 lambda x: isinstance(x, int) and x>=0)
72
73 def check_field(cfg, field, descr, loc, default, check):
74 if field in cfg:
75 tmp=cfg[field]
76 if not check(tmp):
77 error("%s is of invalid type for %s" % (field, loc))
78 return tmp
79 else:
80 if default is not None:
81 return default
82 else:
83 error("%s is not configured for %s" % (field, loc))
84
85 #
86 # Conversion of config into command line
87 #
88
89 def arglistify(args):
90 flatten=lambda l: [item for sublist in l for item in sublist]
91 if args is None:
92 return []
93 else:
94 return flatten([['--' + key, str(d[key])] for d in args for key in d])
95
96 #
97 # Load config on module load
98 #
11 99
12 def expand_env(cfg, env): 100 def expand_env(cfg, env):
13 if isinstance(cfg, dict): 101 if isinstance(cfg, dict):
14 out={key: expand_env(val, env) for key, val in cfg.items()} 102 out={key: expand_env(val, env) for key, val in cfg.items()}
15 elif isinstance(cfg, list): 103 elif isinstance(cfg, list):
16 out=[expand_env(val, env) for val in cfg] 104 out=[expand_env(val, env) for val in cfg]
17 elif isinstance(cfg, str): 105 elif isinstance(cfg, str):
18 out=string.Template(cfg).substitute(os.environ) 106 out=string.Template(cfg).substitute(os.environ)
19 else: 107 else:
20 out=cfg 108 out=cfg
21 109
22 return out 110 return out
23 111
24 cfgfile=os.path.join(xdg.XDG_CONFIG_HOME, "borgend", "config.yaml") 112 cfgfile=os.path.join(xdg.XDG_CONFIG_HOME, "borgend", "config.yaml")
25 113
26 if not (os.path.exists(cfgfile) and os.path.isfile(cfgfile)): 114 if not (os.path.exists(cfgfile) and os.path.isfile(cfgfile)):
27 raise SystemExit(f'Configuration file required: {cfgfile}') 115 raise SystemExit(f'Configuration file required: {cfgfile}')
28 116
29 with io.open(cfgfile, 'r') as file: 117 with io.open(cfgfile, 'r') as file:
30 settings=expand_env(yaml.load(file), os.environ); 118 settings=expand_env(yaml.load(file), os.environ);
31 119
120 #
121 # Verify basic settings
122 #
123
124 if 'borg' not in settings:
125 settings['borg']=defaults['borg']
126 else:
127 def check_and_set(cfg, field, loc, defa, fn):
128 cfg[field]=fn(cfg, field, field, loc, defa[field])
129 return cfg
130
131 settings['borg']=check_and_set(settings['borg'], 'executable', 'borg',
132 defaults['borg'], check_string)
133
134 settings['borg']=check_and_set(settings['borg'], 'common_parameters', 'borg',
135 defaults['borg'], check_list_of_dicts)
136
137 settings['borg']=check_and_set(settings['borg'], 'create_parameters', 'borg',
138 defaults['borg'], check_list_of_dicts)
139

mercurial