comparison piecrust/configuration.py @ 584:9ccc933ac2c7

internal: Refactor the app configuration class. * Moved to its own module. * More extensible validation. * Allow easier setup of defaults so `showconfig` shows more useful stuff.
author Ludovic Chabant <ludovic@chabant.com>
date Fri, 01 Jan 2016 23:18:26 -0800
parents 1359b2b0cc73
children 81d9c3a3a0b5
comparison
equal deleted inserted replaced
583:1eda551ee681 584:9ccc933ac2c7
1 import re 1 import re
2 import logging 2 import logging
3 import collections
3 import collections.abc 4 import collections.abc
4 import yaml 5 import yaml
5 from yaml.constructor import ConstructorError 6 from yaml.constructor import ConstructorError
6 try: 7 try:
7 from yaml import CSafeLoader as SafeLoader 8 from yaml import CSafeLoader as SafeLoader
67 def set(self, key, value): 68 def set(self, key, value):
68 self[key] = value 69 self[key] = value
69 70
70 def setAll(self, values, validate=False): 71 def setAll(self, values, validate=False):
71 if validate: 72 if validate:
72 self._validateAll(values) 73 values = self._validateAll(values)
73 self._values = values 74 self._values = values
74 75
75 def getAll(self): 76 def getAll(self):
76 self._ensureLoaded() 77 self._ensureLoaded()
77 return self._values 78 return self._values
127 def _validateValue(self, key_path, value): 128 def _validateValue(self, key_path, value):
128 return value 129 return value
129 130
130 131
131 def merge_dicts(source, merging, validator=None, *args): 132 def merge_dicts(source, merging, validator=None, *args):
132 if validator is None:
133 validator = lambda k, v: v
134 _recurse_merge_dicts(source, merging, None, validator) 133 _recurse_merge_dicts(source, merging, None, validator)
135 for other in args: 134 for other in args:
136 _recurse_merge_dicts(source, other, None, validator) 135 _recurse_merge_dicts(source, other, None, validator)
136 return source
137 137
138 138
139 def _recurse_merge_dicts(local_cur, incoming_cur, parent_path, validator): 139 def _recurse_merge_dicts(local_cur, incoming_cur, parent_path, validator):
140 for k, v in incoming_cur.items(): 140 for k, v in incoming_cur.items():
141 key_path = k 141 key_path = k
147 if isinstance(v, dict) and isinstance(local_v, dict): 147 if isinstance(v, dict) and isinstance(local_v, dict):
148 _recurse_merge_dicts(local_v, v, key_path, validator) 148 _recurse_merge_dicts(local_v, v, key_path, validator)
149 elif isinstance(v, list) and isinstance(local_v, list): 149 elif isinstance(v, list) and isinstance(local_v, list):
150 local_cur[k] = v + local_v 150 local_cur[k] = v + local_v
151 else: 151 else:
152 local_cur[k] = validator(key_path, v) 152 if validator is not None:
153 v = validator(key_path, v)
154 local_cur[k] = v
153 else: 155 else:
154 local_cur[k] = validator(key_path, v) 156 if validator is not None:
157 v = validator(key_path, v)
158 local_cur[k] = v
159
160
161 def visit_dict(subject, visitor):
162 _recurse_visit_dict(subject, None, visitor)
163
164
165 def _recurse_visit_dict(cur, parent_path, visitor):
166 for k, v in cur.items():
167 key_path = k
168 if parent_path is not None:
169 key_path = parent_path + '/' + k
170
171 visitor(key_path, v, cur, k)
172 if isinstance(v, dict):
173 _recurse_visit_dict(v, key_path, visitor)
155 174
156 175
157 header_regex = re.compile( 176 header_regex = re.compile(
158 r'(---\s*\n)(?P<header>(.*\n)*?)^(---\s*\n)', re.MULTILINE) 177 r'(---\s*\n)(?P<header>(.*\n)*?)^(---\s*\n)', re.MULTILINE)
159 178