From be8ffd80be76c12a268b7199e5e05772f18cd30a Mon Sep 17 00:00:00 2001 From: Richard Maw Date: Mon, 17 Feb 2014 15:20:44 +0000 Subject: Legacy morph code: Also dump in specified order This rips out any remaining order-preserving code and instead uses the yaml dumper from morphloader. --- morphlib/morph2.py | 2 +- morphlib/morph2_tests.py | 23 +++------- morphlib/yamlparse.py | 102 ++------------------------------------------ morphlib/yamlparse_tests.py | 10 +---- 4 files changed, 12 insertions(+), 125 deletions(-) (limited to 'morphlib') diff --git a/morphlib/morph2.py b/morphlib/morph2.py index fd72aa94..cc6ce926 100644 --- a/morphlib/morph2.py +++ b/morphlib/morph2.py @@ -238,7 +238,7 @@ class Morphology(object): to set default values during construction. ''' - output_dict = OrderedDict() + output_dict = {} for key in live_dict.keys(): if key.startswith('_orig_'): diff --git a/morphlib/morph2_tests.py b/morphlib/morph2_tests.py index ba90313f..d02aab1c 100644 --- a/morphlib/morph2_tests.py +++ b/morphlib/morph2_tests.py @@ -19,6 +19,8 @@ import json import StringIO import unittest +import yaml + import morphlib from morphlib.morph2 import Morphology @@ -251,19 +253,6 @@ class MorphologyTests(unittest.TestCase): ] }''' - def test_writing_preserves_chunk_order(self): - text_lines = self.stratum_text.splitlines() - text_lines[6] = ' "ref": "new-ref",' - - # Change one of the fields - morphology = Morphology(self.stratum_text) - morphology['chunks'][0]['ref'] = 'new-ref' - - output = StringIO.StringIO() - morphology.update_text(self.stratum_text, output) - output_lines = output.getvalue().splitlines() - self.assertEqual(text_lines, output_lines) - def test_writing_handles_added_chunks(self): text_lines = self.stratum_text.splitlines() text_lines = text_lines[0:16] + text_lines[8:17] + text_lines[17:] @@ -276,8 +265,8 @@ class MorphologyTests(unittest.TestCase): output = StringIO.StringIO() morphology.update_text(self.stratum_text, output) - output_lines = output.getvalue().splitlines() - self.assertEqual(text_lines, output_lines) + d = yaml.load(output.getvalue()) + self.assertEqual(d['chunks'][2]['name'], 'baz') def test_writing_handles_deleted_chunks(self): text_lines = self.stratum_text.splitlines() @@ -289,8 +278,8 @@ class MorphologyTests(unittest.TestCase): output = StringIO.StringIO() morphology.update_text(self.stratum_text, output) - output_lines = output.getvalue().splitlines() - self.assertEqual(text_lines, output_lines) + d = yaml.load(output.getvalue()) + self.assertEqual(len(d['chunks']), 1) system_text = '''{ "kind": "system", diff --git a/morphlib/yamlparse.py b/morphlib/yamlparse.py index 99599618..726b4181 100644 --- a/morphlib/yamlparse.py +++ b/morphlib/yamlparse.py @@ -1,4 +1,4 @@ -# Copyright (C) 2013 Codethink Limited +# Copyright (C) 2013-2014 Codethink Limited # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -23,108 +23,14 @@ if morphlib.got_yaml: # pragma: no cover if morphlib.got_yaml: # pragma: no cover - class OrderedDictYAMLLoader(yaml.SafeLoader): - """A YAML loader that loads mappings into ordered dictionaries. - - When YAML is loaded with this Loader, it loads mappings as ordered - dictionaries, so the order the keys were written in is maintained. - - When combined with the OrderedDictYAMLDumper, this allows yaml documents - to be written out in a similar format to they were read. - - """ - - def __init__(self, *args, **kwargs): - yaml.SafeLoader.__init__(self, *args, **kwargs) - - # When YAML encounters a mapping (which YAML identifies with - # the given tag), it will use construct_yaml_map to read it as - # an OrderedDict. - self.add_constructor(u'tag:yaml.org,2002:map', - 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 - - class OrderedDictYAMLDumper(yaml.SafeDumper): - """A YAML dumper that will dump OrderedDicts as mappings. - - When YAML is dumped with this Dumper, it dumps OrderedDicts as - mappings, preserving the key order, so the order the keys were - written in is maintained. - - When combined with the OrderedDictYAMLDumper, this allows yaml documents - to be written out in a similar format to they were read. - - """ - - def __init__(self, *args, **kwargs): - yaml.SafeDumper.__init__(self, *args, **kwargs) - - # When YAML sees an OrderedDict, use represent_ordered_dict to - # dump it - self.add_representer(OrderedDict, - type(self).represent_ordered_dict) - - def represent_ordered_dict(self, odict): - return self.represent_ordered_mapping( - u'tag:yaml.org,2002:map', odict) - - def represent_ordered_mapping(self, tag, omap): - value = [] - node = yaml.MappingNode(tag, value) - if self.alias_key is not None: - self.represented_objects[self.alias_key] = node - best_style = True - for item_key, item_value in omap.iteritems(): - 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 # pragma: no cover - if not (isinstance(node_value, yaml.ScalarNode) and - not node_value.style): - best_style = False # pragma: no cover - value.append((node_key, node_value)) - if self.default_flow_style is not None: - node.flow_style = self.default_flow_style - else: - node.flow_style = best_style # pragma: no cover - return node - def load(*args, **kwargs): - return yaml.load(Loader=OrderedDictYAMLLoader, *args, **kwargs) + return yaml.safe_load(*args, **kwargs) def dump(*args, **kwargs): if 'default_flow_style' not in kwargs: kwargs['default_flow_style'] = False - return yaml.dump(Dumper=OrderedDictYAMLDumper, *args, **kwargs) + return yaml.dump(Dumper=morphlib.morphloader.OrderedDumper, + *args, **kwargs) else: # pragma: no cover def load(*args, **kwargs): diff --git a/morphlib/yamlparse_tests.py b/morphlib/yamlparse_tests.py index f5c2569b..38815168 100644 --- a/morphlib/yamlparse_tests.py +++ b/morphlib/yamlparse_tests.py @@ -1,4 +1,4 @@ -# Copyright (C) 2013 Codethink Limited +# Copyright (C) 2013-2014 Codethink Limited # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -41,14 +41,6 @@ build-system: manual ('build-system', 'manual'), ]) - def test_loads_as_ordered_dict(self): - m = yamlparse.load(self.example_text) - self.assertEqual(type(m), OrderedDict) - - def test_dumps_ordered_dicts(self): - self.assertEqual(self.example_text, - yamlparse.dump(self.example_dict)) - def test_non_map_raises(self): incorrect_type = '''\ !!map -- cgit v1.2.1