comparison piecrust/configuration.py @ 0:a212a3f2e3ee

Initial commit.
author Ludovic Chabant <ludovic@chabant.com>
date Sat, 21 Dec 2013 14:44:02 -0800
parents
children 40fa08b261b9
comparison
equal deleted inserted replaced
-1:000000000000 0:a212a3f2e3ee
1 import re
2 import yaml
3
4
5 class Configuration(object):
6 def __init__(self, values=None, validate=True):
7 self._values = {}
8 if values is not None:
9 self.set_all(values, validate)
10
11 def set_all(self, values, validate=True):
12 if validate:
13 self._validateAll(values)
14 self._values = values
15
16 def get(self, key_path=None):
17 self._ensureLoaded()
18 if key_path is None:
19 return self._values
20 bits = key_path.split('/')
21 cur = self._values
22 for b in bits:
23 cur = cur.get(b)
24 if cur is None:
25 return None
26 return cur
27
28 def set(self, key_path, value):
29 self._ensureLoaded()
30 value = self._validateValue(key_path, value)
31 bits = key_path.split('/')
32 bitslen = len(bits)
33 cur = self._values
34 for i, b in enumerate(bits):
35 if i == bitslen - 1:
36 cur[b] = value
37 else:
38 if b not in cur:
39 cur[b] = {}
40 cur = cur[b]
41
42 def has(self, key_path):
43 self._ensureLoaded()
44 bits = key_path.split('/')
45 cur = self._values
46 for b in bits:
47 cur = cur.get(b)
48 if cur is None:
49 return False
50 return True
51
52 def merge(self, other):
53 self._ensureLoaded()
54 merge_dicts(self._values, other._values,
55 validator=self._validateValue)
56
57 def _ensureLoaded(self):
58 if self._values is None:
59 self._load()
60
61 def _load(self):
62 self._values = self._validateAll({})
63
64 def _validateAll(self, values):
65 return values
66
67 def _validateValue(self, key_path, value):
68 return value
69
70
71 def merge_dicts(local_cur, incoming_cur, parent_path=None, validator=None):
72 if validator is None:
73 validator = lambda k, v: v
74
75 for k, v in incoming_cur.iteritems():
76 key_path = k
77 if parent_path is not None:
78 key_path = parent_path + '/' + k
79
80 local_v = local_cur.get(k)
81 if local_v is not None:
82 if isinstance(v, dict) and isinstance(local_v, dict):
83 local_cur[k] = merge_dicts(local_v, v)
84 elif isinstance(v, list) and isinstance(local_v, list):
85 local_cur[k] = v + local_v
86 else:
87 local_cur[k] = validator(key_path, v)
88 else:
89 local_cur[k] = validator(key_path, v)
90
91
92 header_regex = re.compile(
93 r'(---\s*\n)(?P<header>(.*\n)*?)^(---\s*\n)', re.MULTILINE)
94
95
96 def parse_config_header(text):
97 m = header_regex.match(text)
98 if m is not None:
99 header = unicode(m.group('header'))
100 config = yaml.safe_load(header)
101 offset = m.end()
102 else:
103 config = {}
104 offset = 0
105 return config, offset
106