summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Thursfield <sam.thursfield@codethink.co.uk>2015-08-24 16:58:50 +0100
committerSam Thursfield <sam.thursfield@codethink.co.uk>2015-08-24 16:58:50 +0100
commite14ed02abe0b37a72ec529132d080701a089e24a (patch)
tree7d585783742763b7f17a5c9a17ce8467c5db7e2c
parent02422692e8d6a86da17bbe9312d6a46a574c1292 (diff)
downloadruamel.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.py18
-rw-r--r--test/test_anchor.py25
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()