OrderedYAML.py
89 lines
| 3.5 KiB
| text/x-python
|
PythonLexer
|
r568 | ''' | ||
A YAML Loader and Dumper which provide ordered dictionaries in place | ||||
of dictionaries (to keep the order of attributes as | ||||
found in the original YAML object file). | ||||
This module is modified from a submission on pyyaml.org: | ||||
http://pyyaml.org/attachment/ticket/161/use_ordered_dict.py | ||||
$Id$ | ||||
''' | ||||
import yaml | ||||
import collections | ||||
class Loader(yaml.loader.Loader): | ||||
""" YAML Loader producing OrderedDicts in place of dicts """ | ||||
def __init__(self, stream): | ||||
yaml.loader.Loader.__init__(self, stream) | ||||
def construct_ordered_mapping(self, node, deep=False): | ||||
""" Replacement mapping constructor producing an OrderedDict """ | ||||
if not isinstance(node, yaml.MappingNode): | ||||
raise yaml.constructor.ConstructorError(None, None, | ||||
"expected a mapping node, but found %s" % node.id, | ||||
node.start_mark) | ||||
mapping = collections.OrderedDict() | ||||
for key_node, value_node in node.value: | ||||
key = self.construct_object(key_node, deep=deep) | ||||
if not isinstance(key, collections.Hashable): | ||||
raise yaml.constructor.ConstructorError("while constructing a mapping", node.start_mark, | ||||
"found unhashable key", key_node.start_mark) | ||||
value = self.construct_object(value_node, deep=deep) | ||||
mapping[key] = value | ||||
return mapping | ||||
# yaml.constructor.BaseConstructor.construct_mapping = construct_ordered_mapping | ||||
def construct_mapping(self, node, deep=False): | ||||
return self.construct_ordered_mapping(node, deep=deep) | ||||
def construct_yaml_map_with_ordered_dict(self, node): | ||||
data = collections.OrderedDict() | ||||
yield data | ||||
value = self.construct_mapping(node) | ||||
data.update(value) | ||||
class Dumper(yaml.dumper.Dumper): | ||||
""" YAML Dumper producing documents from OrderedDicts """ | ||||
def __init__(self, stream, *args, **kwargs): | ||||
yaml.dumper.Dumper.__init__(self, stream, *args, **kwargs) | ||||
def represent_ordered_mapping(self, tag, mapping, flow_style=None): | ||||
""" Replacement mapping representer for OrderedDicts """ | ||||
value = [] | ||||
node = yaml.MappingNode(tag, value, flow_style=flow_style) | ||||
if self.alias_key is not None: | ||||
self.represented_objects[self.alias_key] = node | ||||
best_style = True | ||||
if hasattr(mapping, 'items'): | ||||
mapping = list(mapping.items()) | ||||
for item_key, item_value in mapping: | ||||
node_key = self.represent_data(item_key) | ||||
node_value = self.represent_data(item_value) | ||||
if not (isinstance(node_key, yaml.ScalarNode) and not node_key.style): | ||||
best_style = False | ||||
if not (isinstance(node_value, yaml.ScalarNode) and not node_value.style): | ||||
best_style = False | ||||
value.append((node_key, node_value)) | ||||
if flow_style is None: | ||||
if self.default_flow_style is not None: | ||||
node.flow_style = self.default_flow_style | ||||
else: | ||||
node.flow_style = best_style | ||||
return node | ||||
# yaml.representer.BaseRepresenter.represent_mapping = represent_ordered_mapping | ||||
def represent_mapping(self, tag, mapping, flow_style=None): | ||||
return self.represent_ordered_mapping(tag, mapping, flow_style=flow_style) | ||||
# Loader.add_constructor( | ||||
# u'tag:yaml.org,2002:map', | ||||
# Loader.construct_yaml_map_with_ordered_dict | ||||
# ) | ||||
# | ||||
# Dumper.add_representer( | ||||
# collections.OrderedDict, | ||||
# yaml.representer.SafeRepresenter.represent_dict | ||||
# ) | ||||