comparison piecrust/configuration.py @ 67:563ce5dd02af

I don't care what the YAML spec says, ordered maps are the only sane way.
author Ludovic Chabant <ludovic@chabant.com>
date Fri, 29 Aug 2014 16:42:15 -0700
parents 474c9882decf
children d9e494df2a99
comparison
equal deleted inserted replaced
66:e4a24512b814 67:563ce5dd02af
1 import re 1 import re
2 import logging 2 import logging
3 import collections
3 import yaml 4 import yaml
5 from yaml.constructor import ConstructorError
4 6
5 7
6 logger = logging.getLogger(__name__) 8 logger = logging.getLogger(__name__)
7 9
8 10
112 114
113 def parse_config_header(text): 115 def parse_config_header(text):
114 m = header_regex.match(text) 116 m = header_regex.match(text)
115 if m is not None: 117 if m is not None:
116 header = str(m.group('header')) 118 header = str(m.group('header'))
117 config = yaml.load(header, Loader=yaml.BaseLoader) 119 config = yaml.load(header, Loader=OrderedDictYAMLLoader)
118 offset = m.end() 120 offset = m.end()
119 else: 121 else:
120 config = {} 122 config = {}
121 offset = 0 123 offset = 0
122 return config, offset 124 return config, offset
123 125
126
127 class OrderedDictYAMLLoader(yaml.BaseLoader):
128 """ A YAML loader that loads mappings into ordered dictionaries.
129 """
130 def construct_mapping(self, node, deep=False):
131 if not isinstance(node, yaml.MappingNode):
132 raise ConstructorError(None, None,
133 "expected a mapping node, but found %s" % node.id,
134 node.start_mark)
135 mapping = collections.OrderedDict()
136 for key_node, value_node in node.value:
137 key = self.construct_object(key_node, deep=deep)
138 if not isinstance(key, collections.Hashable):
139 raise ConstructorError("while constructing a mapping", node.start_mark,
140 "found unhashable key", key_node.start_mark)
141 value = self.construct_object(value_node, deep=deep)
142 mapping[key] = value
143 return mapping
144