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