Mercurial > piecrust2
comparison piecrust/configuration.py @ 440:32c7c2d219d2
performance: Refactor how data is managed to reduce copying.
* Make use of `collections.abc.Mapping` to better identify things that are
supposed to look like dictionaries.
* Instead of handling "overlay" of data in a dict tree in each different data
object, make all objects `Mapping`s and handle merging at a higher level
with the new `MergedMapping` object.
* Since this new object is read-only, remove the need for deep-copying of
app and page configurations.
* Split data classes into separate modules.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sun, 28 Jun 2015 08:22:39 -0700 |
parents | bdeeee777f85 |
children | 1359b2b0cc73 |
comparison
equal
deleted
inserted
replaced
439:c0700c6d9545 | 440:32c7c2d219d2 |
---|---|
1 import re | 1 import re |
2 import copy | |
3 import logging | 2 import logging |
4 import collections | 3 import collections.abc |
5 import yaml | 4 import yaml |
6 from yaml.constructor import ConstructorError | 5 from yaml.constructor import ConstructorError |
7 | 6 |
8 | 7 |
9 logger = logging.getLogger(__name__) | 8 logger = logging.getLogger(__name__) |
13 | 12 |
14 class ConfigurationError(Exception): | 13 class ConfigurationError(Exception): |
15 pass | 14 pass |
16 | 15 |
17 | 16 |
18 class Configuration(object): | 17 class Configuration(collections.abc.MutableMapping): |
19 def __init__(self, values=None, validate=True): | 18 def __init__(self, values=None, validate=True): |
20 if values is not None: | 19 if values is not None: |
21 self.setAll(values, validate) | 20 self.setAll(values, validate=validate) |
22 else: | 21 else: |
23 self._values = None | 22 self._values = None |
24 | 23 |
25 def __contains__(self, key): | |
26 return self.has(key) | |
27 | |
28 def __getitem__(self, key): | 24 def __getitem__(self, key): |
29 value = self.get(key) | 25 self._ensureLoaded() |
30 if value is None: | 26 bits = key.split('/') |
31 raise KeyError() | |
32 return value | |
33 | |
34 def __setitem__(self, key, value): | |
35 return self.set(key, value) | |
36 | |
37 def setAll(self, values, validate=True): | |
38 if validate: | |
39 self._validateAll(values) | |
40 self._values = values | |
41 | |
42 def getDeepcopy(self, validate_types=False): | |
43 if validate_types: | |
44 self.validateTypes() | |
45 return copy.deepcopy(self.get()) | |
46 | |
47 def get(self, key_path=None, default_value=None): | |
48 self._ensureLoaded() | |
49 if key_path is None: | |
50 return self._values | |
51 bits = key_path.split('/') | |
52 cur = self._values | 27 cur = self._values |
53 for b in bits: | 28 for b in bits: |
54 cur = cur.get(b) | 29 try: |
55 if cur is None: | 30 cur = cur[b] |
56 return default_value | 31 except KeyError: |
32 raise KeyError("No such item: %s" % key) | |
57 return cur | 33 return cur |
58 | 34 |
59 def set(self, key_path, value): | 35 def __setitem__(self, key, value): |
60 self._ensureLoaded() | 36 self._ensureLoaded() |
61 value = self._validateValue(key_path, value) | 37 value = self._validateValue(key, value) |
62 bits = key_path.split('/') | 38 bits = key.split('/') |
63 bitslen = len(bits) | 39 bitslen = len(bits) |
64 cur = self._values | 40 cur = self._values |
65 for i, b in enumerate(bits): | 41 for i, b in enumerate(bits): |
66 if i == bitslen - 1: | 42 if i == bitslen - 1: |
67 cur[b] = value | 43 cur[b] = value |
68 else: | 44 else: |
69 if b not in cur: | 45 if b not in cur: |
70 cur[b] = {} | 46 cur[b] = {} |
71 cur = cur[b] | 47 cur = cur[b] |
72 | 48 |
73 def has(self, key_path): | 49 def __delitem__(self, key): |
74 self._ensureLoaded() | 50 raise NotImplementedError() |
75 bits = key_path.split('/') | 51 |
76 cur = self._values | 52 def __iter__(self): |
77 for b in bits: | 53 self._ensureLoaded() |
78 cur = cur.get(b) | 54 return iter(self._values) |
79 if cur is None: | 55 |
80 return False | 56 def __len__(self): |
81 return True | 57 self._ensureLoaded() |
58 return len(self._values) | |
59 | |
60 def has(self, key): | |
61 return key in self | |
62 | |
63 def set(self, key, value): | |
64 self[key] = value | |
65 | |
66 def setAll(self, values, validate=False): | |
67 if validate: | |
68 self._validateAll(values) | |
69 self._values = values | |
70 | |
71 def getAll(self): | |
72 self._ensureLoaded() | |
73 return self._values | |
82 | 74 |
83 def merge(self, other): | 75 def merge(self, other): |
84 self._ensureLoaded() | 76 self._ensureLoaded() |
85 | 77 |
86 if isinstance(other, dict): | 78 if isinstance(other, dict): |