Skip to content

Commit

Permalink
Sync development with master
Browse files Browse the repository at this point in the history
  • Loading branch information
wwkimball committed Oct 18, 2023
2 parents 4dea37e + a0cbc0d commit 9bbddea
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 3 deletions.
7 changes: 7 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
3.8.1
Bug Fixes:
* Fixed issue #220 reported by https://github.com/abramov-oleg wherein novel
mergeat paths given to the yaml-merge tool with Array and Array-of-Hash data
in the RHS document would cause an interminable loop that would max out CPU
and eventually exhaust RAM.

3.8.0
Enhancements:
* The yaml-set and yaml-merge command-line tools now support a new option:
Expand Down
83 changes: 83 additions & 0 deletions tests/test_merger_merger.py
Original file line number Diff line number Diff line change
Expand Up @@ -3329,6 +3329,89 @@ def test_bad_merge_hash_into_set(
assert -1 < str(ex.value).find(
"Merging a Hash into a Set is destructive")

def test_merge_with_novel_mergeat_array(
self, quiet_logger, tmp_path, tmp_path_factory
):
# Credit: https://github.com/abramov-oleg
# Reported: https://github.com/wwkimball/yamlpath/issues/220
lhs_yaml_file = create_temp_yaml_file(tmp_path_factory, """---
key: value
""")
rhs_yaml_file = create_temp_yaml_file(tmp_path_factory, """array:
- element
""")
merged_yaml = create_temp_yaml_file(tmp_path_factory, """---
key: value
new_key:
array:
- element
""")

output_dir = tmp_path / "test_merge_with_novel_mergeat_array"
output_dir.mkdir()
output_file = output_dir / "output.yaml"

lhs_yaml = get_yaml_editor()
rhs_yaml = get_yaml_editor()
(lhs_data, lhs_loaded) = get_yaml_data(lhs_yaml, quiet_logger, lhs_yaml_file)
(rhs_data, rhs_loaded) = get_yaml_data(rhs_yaml, quiet_logger, rhs_yaml_file)

args = SimpleNamespace(mergeat="new_key")
mc = MergerConfig(quiet_logger, args)
merger = Merger(quiet_logger, lhs_data, mc)
merger.merge_with(rhs_data)

with open(output_file, 'w') as yaml_dump:
lhs_yaml.dump(merger.data, yaml_dump)

assert (
(os.path.getsize(output_file) == os.path.getsize(merged_yaml))
and (open(output_file,'r').read() == open(merged_yaml,'r').read())
)

def test_merge_with_novel_mergeat_aoh(
self, quiet_logger, tmp_path, tmp_path_factory
):
# Credit: https://github.com/abramov-oleg
# Reported: https://github.com/wwkimball/yamlpath/issues/220
lhs_yaml_file = create_temp_yaml_file(tmp_path_factory, """---
key: value
""")
rhs_yaml_file = create_temp_yaml_file(tmp_path_factory, """---
array_of_hash:
- name: one
val: some
""")
merged_yaml = create_temp_yaml_file(tmp_path_factory, """---
key: value
new_key:
array_of_hash:
- name: one
val: some
""")

output_dir = tmp_path / "test_merge_with_novel_mergeat_array"
output_dir.mkdir()
output_file = output_dir / "output.yaml"

lhs_yaml = get_yaml_editor()
rhs_yaml = get_yaml_editor()
(lhs_data, lhs_loaded) = get_yaml_data(lhs_yaml, quiet_logger, lhs_yaml_file)
(rhs_data, rhs_loaded) = get_yaml_data(rhs_yaml, quiet_logger, rhs_yaml_file)

args = SimpleNamespace(mergeat="new_key")
mc = MergerConfig(quiet_logger, args)
merger = Merger(quiet_logger, lhs_data, mc)
merger.merge_with(rhs_data)

with open(output_file, 'w') as yaml_dump:
lhs_yaml.dump(merger.data, yaml_dump)

assert (
(os.path.getsize(output_file) == os.path.getsize(merged_yaml))
and (open(output_file,'r').read() == open(merged_yaml,'r').read())
)


###
# set_flow_style
Expand Down
2 changes: 1 addition & 1 deletion yamlpath/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Core YAML Path classes."""
# Establish the version number common to all components
__version__ = "3.8.0"
__version__ = "3.8.1"

from yamlpath.yamlpath import YAMLPath
from yamlpath.processor import Processor
7 changes: 5 additions & 2 deletions yamlpath/merger/merger.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#pylint: disable=too-many-lines
"""
Implement YAML document Merger.
Expand Down Expand Up @@ -860,8 +861,10 @@ def merge_with(self, rhs: Any) -> None:
if hasattr(target_node, "fa")
else None))

if isinstance(rhs, CommentedMap):
# The RHS document root is a dict
if target_node is rhs:
# _get_merge_target_nodes already inserted RHS (novel mergeat)
merge_performed = True
elif isinstance(rhs, CommentedMap):
merge_performed = self._insert_dict(
insert_at, target_node, rhs)
elif isinstance(rhs, CommentedSeq):
Expand Down

0 comments on commit 9bbddea

Please sign in to comment.