diff options
author | Sam Thursfield <sam.thursfield@codethink.co.uk> | 2015-08-24 16:58:50 +0100 |
---|---|---|
committer | Sam Thursfield <sam.thursfield@codethink.co.uk> | 2015-08-24 16:58:50 +0100 |
commit | e14ed02abe0b37a72ec529132d080701a089e24a (patch) | |
tree | 7d585783742763b7f17a5c9a17ce8467c5db7e2c | |
parent | 02422692e8d6a86da17bbe9312d6a46a574c1292 (diff) | |
download | ruamel.yaml-e14ed02abe0b37a72ec529132d080701a089e24a.tar.gz |
Fix assertoin failure for certain kinds of merges
The RoundTripConstructor.flatten_mapping() method made an assumption that
when merging a mapping into another mapping, the actual data would have been
defined already. For example:
predefined: &contents { a: 1 }
merged:
<<: *contents
However, the following is valid as well, and in this case the data is only
defined at the point of merging:
merged-1:
<<: &contents { a: 1 }
merged-2:
<<: *contents
This commit fixes an assertion failure for the latter case.
-rw-r--r-- | py/constructor.py | 18 | ||||
-rw-r--r-- | test/test_anchor.py | 25 |
2 files changed, 39 insertions, 4 deletions
diff --git a/py/constructor.py b/py/constructor.py index 1de8545..5ce8974 100644 --- a/py/constructor.py +++ b/py/constructor.py @@ -851,6 +851,18 @@ class RoundTripConstructor(SafeConstructor): by inserting keys from the merge dict/list of dicts if not yet available in this node """ + + def constructed(value_node): + # If the contents of a merge are defined within the + # merge marker, then they won't have been constructed + # yet. But if they were already constructed, we need to use + # the existing object. + if value_node in self.constructed_objects: + value = self.constructed_objects[value_node] + else: + value = self.construct_object(value_node, deep=False) + return value + #merge = [] merge_map_list = [] index = 0 @@ -859,10 +871,8 @@ class RoundTripConstructor(SafeConstructor): if key_node.tag == u'tag:yaml.org,2002:merge': del node.value[index] if isinstance(value_node, MappingNode): - # such an anchor node is already constructed - assert value_node in self.constructed_objects merge_map_list.append( - (index, self.constructed_objects[value_node])) + (index, constructed(value_node))) #self.flatten_mapping(value_node) #merge.extend(value_node.value) elif isinstance(value_node, SequenceNode): @@ -875,7 +885,7 @@ class RoundTripConstructor(SafeConstructor): "expected a mapping for merging, but found %s" % subnode.id, subnode.start_mark) merge_map_list.append( - (index, self.constructed_objects[subnode])) + (index, constructed(subnode))) # self.flatten_mapping(subnode) # submerge.append(subnode.value) #submerge.reverse() diff --git a/test/test_anchor.py b/test/test_anchor.py index efbcb21..e48398b 100644 --- a/test/test_anchor.py +++ b/test/test_anchor.py @@ -179,6 +179,31 @@ class TestAnchorsAliases: data = load(self.merge_yaml) compare(data, self.merge_yaml) + def test_merge_nested(self): + yaml = ''' + a: + <<: &content + 1: plugh + 2: plover + 0: xyzzy + b: + <<: *content + ''' + data = round_trip(yaml) + + def test_merge_nested_with_sequence(self): + yaml = ''' + a: + <<: &content + <<: &y2 + 1: plugh + 2: plover + 0: xyzzy + b: + <<: [*content, *y2] + ''' + data = round_trip(yaml) + def test_add_anchor(self): from ruamel.yaml.comments import CommentedMap data = CommentedMap() |