Mercurial > piecrust2
comparison piecrust/configuration.py @ 367:734f2abf361c
config: Add method to deep-copy a config and validate its contents.
Deep-copying will be problematic if non-basic types are in there, so there's
a new method to check that this is OK.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sun, 03 May 2015 18:42:29 -0700 |
parents | 45aba3cb7228 |
children | bdeeee777f85 |
comparison
equal
deleted
inserted
replaced
366:81d2fd526c82 | 367:734f2abf361c |
---|---|
1 import re | 1 import re |
2 import copy | |
2 import logging | 3 import logging |
3 import collections | 4 import collections |
4 import yaml | 5 import yaml |
5 from yaml.constructor import ConstructorError | 6 from yaml.constructor import ConstructorError |
6 | 7 |
7 | 8 |
8 logger = logging.getLogger(__name__) | 9 logger = logging.getLogger(__name__) |
10 | |
11 default_allowed_types = (dict, list, tuple, int, bool, str) | |
9 | 12 |
10 | 13 |
11 class ConfigurationError(Exception): | 14 class ConfigurationError(Exception): |
12 pass | 15 pass |
13 | 16 |
34 def setAll(self, values, validate=True): | 37 def setAll(self, values, validate=True): |
35 if validate: | 38 if validate: |
36 self._validateAll(values) | 39 self._validateAll(values) |
37 self._values = values | 40 self._values = values |
38 | 41 |
39 def getAll(self): | 42 def getDeepcopy(self, validate_types=False): |
40 return self.get() | 43 if validate_types: |
44 self.validateTypes() | |
45 return copy.deepcopy(self.get()) | |
41 | 46 |
42 def get(self, key_path=None, default_value=None): | 47 def get(self, key_path=None, default_value=None): |
43 self._ensureLoaded() | 48 self._ensureLoaded() |
44 if key_path is None: | 49 if key_path is None: |
45 return self._values | 50 return self._values |
86 raise Exception( | 91 raise Exception( |
87 "Unsupported value type to merge: %s" % type(other)) | 92 "Unsupported value type to merge: %s" % type(other)) |
88 | 93 |
89 merge_dicts(self._values, other_values, | 94 merge_dicts(self._values, other_values, |
90 validator=self._validateValue) | 95 validator=self._validateValue) |
96 | |
97 def validateTypes(self, allowed_types=default_allowed_types): | |
98 self._validateDictTypesRecursive(self._values, allowed_types) | |
99 | |
100 def _validateDictTypesRecursive(self, d, allowed_types): | |
101 for k, v in d.items(): | |
102 if not isinstance(k, str): | |
103 raise ConfigurationError("Key '%s' is not a string." % k) | |
104 self._validateTypeRecursive(v, allowed_types) | |
105 | |
106 def _validateListTypesRecursive(self, l, allowed_types): | |
107 for v in l: | |
108 self._validateTypeRecursive(v, allowed_types) | |
109 | |
110 def _validateTypeRecursive(self, v, allowed_types): | |
111 if v is None: | |
112 return | |
113 if not isinstance(v, allowed_types): | |
114 raise ConfigurationError( | |
115 "Value '%s' is of forbidden type: %s" % (v, type(v))) | |
116 if isinstance(v, dict): | |
117 self._validateDictTypesRecursive(v, allowed_types) | |
118 elif isinstance(v, list): | |
119 self._validateListTypesRecursive(v, allowed_types) | |
91 | 120 |
92 def _ensureLoaded(self): | 121 def _ensureLoaded(self): |
93 if self._values is None: | 122 if self._values is None: |
94 self._load() | 123 self._load() |
95 | 124 |