diff --git a/src/yamlprocessor/dataprocess.py b/src/yamlprocessor/dataprocess.py index 606c692..8d35813 100755 --- a/src/yamlprocessor/dataprocess.py +++ b/src/yamlprocessor/dataprocess.py @@ -433,8 +433,16 @@ def process_data( p_items.append(data[key]) else: p_items.append(data[key]) - # If a processed item is a dict/list, then need to process - # its sub data structures. + # If any processed item contains another merge include, then + # need to reconsider the original dict/list as a whole. + # Otherwise, if a processed item is a dict/list, then need to + # process its sub data structures. + if any( + self._is_include(p_item) and self.MERGE_KEY in p_item + for p_item in p_items + ): + stack.append([data, parent_filenames, variable_map]) + break for p_item in p_items: if isinstance(p_item, dict) or isinstance(p_item, list): stack.append( diff --git a/src/yamlprocessor/tests/test_dataprocess.py b/src/yamlprocessor/tests/test_dataprocess.py index 365bf8a..a085c6e 100644 --- a/src/yamlprocessor/tests/test_dataprocess.py +++ b/src/yamlprocessor/tests/test_dataprocess.py @@ -460,7 +460,7 @@ def test_main_12(tmp_path, yaml): ] -def test_main_12_1(tmp_path, yaml): +def test_main_12_empty_list_1(tmp_path, yaml): """Test main, merge include file with empty list and variable process. Issue 35. @@ -485,7 +485,33 @@ def test_main_12_1(tmp_path, yaml): ] -def test_main_12_2(tmp_path, yaml): +def test_main_12_empty_list_2(tmp_path, yaml): + """Test main, recursive merge include file with empty list. + + Issue 35, but with recursive merge include of an empty list. + """ + root_data = [ + {'name': '${MATTER}'}, + {'INCLUDE': 'one.yaml', 'MERGE': True}, + {'name': '${MATTER}'}, + ] + for name, data in ( + ('void.yaml', []), + ('one.yaml', [{'INCLUDE': 'void.yaml', 'MERGE': True}]), + ('root.yaml', root_data), + ): + infilename = tmp_path / name + with infilename.open('w') as infile: + yaml.dump(data, infile) + outfilename = tmp_path / 'b.yaml' + main(['--define=MATTER=stuff', str(infilename), str(outfilename)]) + assert yaml.load(outfilename.open()) == [ + {'name': 'stuff'}, + {'name': 'stuff'}, + ] + + +def test_main_12_empty_dict_1(tmp_path, yaml): """Test main, merge include file with empty dict and variable process. Issue 35, but with an empty dict. @@ -510,6 +536,32 @@ def test_main_12_2(tmp_path, yaml): } +def test_main_12_empty_dict_2(tmp_path, yaml): + """Test main, recursive merge include file with empty dict. + + Issue 35, but with recursive merge include of an empty dict. + """ + root_data = { + 'name1': '${MATTER}', + 'one': {'INCLUDE': 'one.yaml', 'MERGE': True}, + 'name2': '${MATTER}', + } + for name, data in ( + ('void.yaml', {}), + ('one.yaml', {'void': {'INCLUDE': 'void.yaml', 'MERGE': True}}), + ('root.yaml', root_data), + ): + infilename = tmp_path / name + with infilename.open('w') as infile: + yaml.dump(data, infile) + outfilename = tmp_path / 'b.yaml' + main(['--define=MATTER=stuff', str(infilename), str(outfilename)]) + assert yaml.load(outfilename.open()) == { + 'name1': 'stuff', + 'name2': 'stuff', + } + + def test_main_13(tmp_path, yaml): """Test main, merge include files into a map/object.""" root_data = {