Created
May 29, 2016 02:29
-
-
Save geetduggal/9f6380d4ca33e380578df50134f14751 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import yaml | |
import yaml.constructor | |
############################################################### | |
# Procedures to preserve order of config file for readability # | |
############################################################### | |
# http://stackoverflow.com/questions/5121931/in-python-how-can-you-load-yaml-mappings-as-ordereddicts | |
try: | |
# included in standard lib from Python 2.7 | |
from collections import OrderedDict | |
except ImportError: | |
# try importing the backported drop-in replacement | |
# it's available on PyPI | |
from ordereddict import OrderedDict | |
class OrderedDictYAMLLoader(yaml.Loader): | |
""" | |
A YAML loader that loads mappings into ordered dictionaries. | |
""" | |
def __init__(self, *args, **kwargs): | |
yaml.Loader.__init__(self, *args, **kwargs) | |
self.add_constructor(u'tag:yaml.org,2002:map', type(self).construct_yaml_map) | |
self.add_constructor(u'tag:yaml.org,2002:omap', type(self).construct_yaml_map) | |
def construct_yaml_map(self, node): | |
data = OrderedDict() | |
yield data | |
value = self.construct_mapping(node) | |
data.update(value) | |
def construct_mapping(self, node, deep=False): | |
if isinstance(node, yaml.MappingNode): | |
self.flatten_mapping(node) | |
else: | |
raise yaml.constructor.ConstructorError(None, None, | |
'expected a mapping node, but found %s' % node.id, node.start_mark) | |
mapping = OrderedDict() | |
for key_node, value_node in node.value: | |
key = self.construct_object(key_node, deep=deep) | |
try: | |
hash(key) | |
except TypeError, exc: | |
raise yaml.constructor.ConstructorError('while constructing a mapping', | |
node.start_mark, 'found unacceptable key (%s)' % exc, key_node.start_mark) | |
value = self.construct_object(value_node, deep=deep) | |
mapping[key] = value | |
return mapping | |
# https://gist.github.com/miracle2k/3184458 | |
"""Make PyYAML output an OrderedDict. | |
It will do so fine if you use yaml.dump(), but that generates ugly, | |
non-standard YAML code. | |
To use yaml.safe_dump(), you need the following. | |
""" | |
def represent_odict(dump, tag, mapping, flow_style=None): | |
"""Like BaseRepresenter.represent_mapping, but does not issue the sort(). | |
""" | |
value = [] | |
node = yaml.MappingNode(tag, value, flow_style=flow_style) | |
if dump.alias_key is not None: | |
dump.represented_objects[dump.alias_key] = node | |
best_style = True | |
if hasattr(mapping, 'items'): | |
mapping = mapping.items() | |
for item_key, item_value in mapping: | |
node_key = dump.represent_data(item_key) | |
node_value = dump.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 dump.default_flow_style is not None: | |
node.flow_style = dump.default_flow_style | |
else: | |
node.flow_style = best_style | |
return node | |
# Sample of how it would be dumped and not; will update later to be more of a python module. Just dumping to gist for now | |
if __name__ == "__main__": | |
# Write out ordered YAML | |
with open("/config.yaml", "w") as f: | |
yaml.SafeDumper.add_representer(OrderedDict, | |
lambda dumper, value: represent_odict(dumper, u'tag:yaml.org,2002:map', value)) | |
f.write(yaml.safe_dump(config)) | |
# Read in ordered YAML | |
with open("/config.yaml") as f: | |
config = yaml.load(f, OrderedDictYAMLLoader) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment