Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bug with resolving merging scalars #815

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 29 additions & 36 deletions lib/yaml/constructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,45 +177,38 @@ def construct_scalar(self, node):
return self.construct_scalar(value_node)
return super().construct_scalar(node)

def flatten_mapping(self, node):
merge = []
index = 0
while index < len(node.value):
key_node, value_node = node.value[index]
if key_node.tag == 'tag:yaml.org,2002:merge':
del node.value[index]
if isinstance(value_node, MappingNode):
self.flatten_mapping(value_node)
merge.extend(value_node.value)
elif isinstance(value_node, SequenceNode):
submerge = []
for subnode in value_node.value:
if not isinstance(subnode, MappingNode):
def construct_mapping(self, node, deep=False):
if not isinstance(node, MappingNode):
raise ConstructorError(None, None,
"expected a mapping node, but found %s" % node.id,
node.start_mark)
mapping = {}
for node_key, node_value in node.value:
if node_key.tag == 'tag:yaml.org,2002:merge':
if isinstance(node_value, SequenceNode):
for subnode in node_value.value:
merge = self.construct_object(subnode, deep=deep)
if not isinstance(merge, dict):
raise ConstructorError("while constructing a mapping",
node.start_mark,
"expected a mapping for merging, but found %s"
% subnode.id, subnode.start_mark)
self.flatten_mapping(subnode)
submerge.append(subnode.value)
submerge.reverse()
for value in submerge:
merge.extend(value)
node.start_mark, "expected a dict for merging, but found %s"
% subnode.id, subnode.start_mark)
mapping.update(merge)
else:
raise ConstructorError("while constructing a mapping", node.start_mark,
"expected a mapping or list of mappings for merging, but found %s"
% value_node.id, value_node.start_mark)
elif key_node.tag == 'tag:yaml.org,2002:value':
key_node.tag = 'tag:yaml.org,2002:str'
index += 1
merge = self.construct_object(node_value, deep=deep)
if not isinstance(merge, dict):
raise ConstructorError("while constructing a mapping", node.start_mark,
f"expected a dict for merging, but found {node_value.id} "
f"resolved to {type(merge)}",
node_key.start_mark)
mapping.update(merge)
else:
index += 1
if merge:
node.value = merge + node.value

def construct_mapping(self, node, deep=False):
if isinstance(node, MappingNode):
self.flatten_mapping(node)
return super().construct_mapping(node, deep=deep)
key = self.construct_object(node_key, deep=deep)
if not isinstance(key, collections.abc.Hashable):
raise ConstructorError("while constructing a mapping", node.start_mark,
"found unhashable key", node_key.start_mark)
value = self.construct_object(node_value, deep=deep)
mapping[key] = value
return mapping

def construct_yaml_null(self, node):
self.construct_scalar(node)
Expand Down
Loading