Mercurial > piecrust2
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 |