def main(): """Main code.""" args = processcli() log = ConsolePrinter(args) validateargs(args, log) # For the remainder of processing, overwrite overwrites output if args.overwrite: args.output = args.overwrite # Merge all input files yaml_editor = Parsers.get_yaml_editor() merge_config = MergerConfig(log, args) exit_state = 0 consumed_stdin = False mergers: List[Merger] = [] merge_count = 0 for yaml_file in args.yaml_files: if yaml_file.strip() == '-': consumed_stdin = True log.debug( "yaml_merge::main: Processing file, {}".format( "STDIN" if yaml_file.strip() == "-" else yaml_file)) if len(mergers) < 1: (mergers, mergers_loaded) = get_doc_mergers( log, yaml_editor, merge_config, yaml_file) if not mergers_loaded: exit_state = 4 break else: # Merge RHS into LHS exit_state = merge_docs( log, yaml_editor, merge_config, mergers, yaml_file) if not exit_state == 0: break merge_count += 1 # Check for a waiting STDIN document if (exit_state == 0 and not consumed_stdin and not args.nostdin and not sys.stdin.isatty() ): exit_state = merge_docs(log, yaml_editor, merge_config, mergers, "-") merge_count += 1 # When no merges have occurred, check for a single-doc merge request if (exit_state == 0 and merge_count == 0 and merge_config.get_multidoc_mode() is MultiDocModes.CONDENSE_ALL ): exit_state = merge_condense_all(log, mergers, []) # Output the final document if exit_state == 0: write_output_document(args, log, yaml_editor, mergers) sys.exit(exit_state)
def test_set_merge_mode_ini_rule_overrides_cli(self, quiet_logger, tmp_path_factory, cli, ini_default, ini_rule, mode): config_file = create_temp_yaml_file( tmp_path_factory, """ [defaults] sets = {} [rules] /hash/merge_targets/subset = {} """.format(ini_default, ini_rule)) lhs_yaml_file = create_temp_yaml_file( tmp_path_factory, """--- hash: lhs_exclusive: lhs value 1 merge_targets: subkey: lhs value 2 subset: ? one ? two """) lhs_yaml = get_yaml_editor() (lhs_data, lhs_loaded) = get_yaml_data(lhs_yaml, quiet_logger, lhs_yaml_file) mc = MergerConfig(quiet_logger, SimpleNamespace(config=config_file, sets=cli)) mc.prepare(lhs_data) node = lhs_data["hash"]["merge_targets"]["subset"] parent = lhs_data["hash"]["merge_targets"] parentref = "subset" assert mc.set_merge_mode(NodeCoords(node, parent, parentref)) == mode
def test_aoh_merge_key_default(self, quiet_logger, tmp_path_factory): lhs_yaml_file = create_temp_yaml_file( tmp_path_factory, """--- hash: lhs_exclusive: lhs value 1 merge_targets: subkey: lhs value 2 subarray: - one - two array_of_hashes: - name: LHS Record 1 id: 1 prop: LHS value AoH 1 - name: LHS Record 2 id: 2 prop: LHS value AoH 2 """) lhs_yaml = get_yaml_editor() (lhs_data, lhs_loaded) = get_yaml_data(lhs_yaml, quiet_logger, lhs_yaml_file) mc = MergerConfig(quiet_logger, SimpleNamespace()) mc.prepare(lhs_data) node = lhs_data["array_of_hashes"] parent = lhs_data parentref = "array_of_hashes" record = node[0] assert mc.aoh_merge_key(NodeCoords(node, parent, parentref), record) == "name"
def test_warn_when_rules_matches_zero_nodes(self, capsys, info_warn_logger, tmp_path_factory): config_file = create_temp_yaml_file( tmp_path_factory, """ [rules] /does_not_exist = left /array_of_hashes[name = "Does Not Compute"] = right """) lhs_yaml_file = create_temp_yaml_file( tmp_path_factory, """--- hash: lhs_exclusive: lhs value 1 merge_targets: subkey: lhs value 2 subarray: - one - two array_of_hashes: - name: LHS Record 1 id: 1 prop: LHS value AoH 1 - name: LHS Record 2 id: 2 prop: LHS value AoH 2 """) lhs_yaml = get_yaml_editor() lhs_data = get_yaml_data(lhs_yaml, info_warn_logger, lhs_yaml_file) mc = MergerConfig(info_warn_logger, SimpleNamespace(config=config_file)) mc.prepare(lhs_data) console = capsys.readouterr() assert "YAML Path matches no nodes" in console.out
def test_anchor_merge_mode_ini(self, quiet_logger, tmp_path_factory, setting, mode): config_file = create_temp_yaml_file( tmp_path_factory, """ [defaults] anchors = {} """.format(setting)) mc = MergerConfig(quiet_logger, SimpleNamespace(config=config_file, anchors=None)) assert mc.anchor_merge_mode() == mode
def test_array_merge_mode_cli_overrides_ini_defaults( self, quiet_logger, tmp_path_factory, cli, ini, mode): config_file = create_temp_yaml_file( tmp_path_factory, """ [defaults] arrays = {} """.format(ini)) mc = MergerConfig(quiet_logger, SimpleNamespace(config=config_file, arrays=cli)) assert mc.array_merge_mode(NodeCoords(None, None, None)) == mode
def test_hash_merge_mode_ini(self, quiet_logger, tmp_path_factory, setting, mode): config_file = create_temp_yaml_file( tmp_path_factory, """ [defaults] hashes = {} """.format(setting)) mc = MergerConfig(quiet_logger, SimpleNamespace(config=config_file, hashes=None)) assert mc.hash_merge_mode(NodeCoords(None, None, None)) == mode
def test_anchor_merge_mode_cli_overrides_ini(self, quiet_logger, tmp_path_factory, cli, ini, mode): config_file = create_temp_yaml_file( tmp_path_factory, """ [defaults] anchors = {} """.format(ini)) mc = MergerConfig(quiet_logger, SimpleNamespace(config=config_file, anchors=cli)) assert mc.anchor_merge_mode() == mode
def test_aoh_merge_mode_ini_rule_overrides_cli(self, quiet_logger, tmp_path_factory, cli, ini_default, ini_rule, mode): config_file = create_temp_yaml_file( tmp_path_factory, """ [defaults] aoh = {} [rules] /array_of_hashes = {} """.format(ini_default, ini_rule)) lhs_yaml_file = create_temp_yaml_file( tmp_path_factory, """--- hash: lhs_exclusive: lhs value 1 merge_targets: subkey: lhs value 2 subarray: - one - two array_of_hashes: - name: LHS Record 1 id: 1 prop: LHS value AoH 1 - name: LHS Record 2 id: 2 prop: LHS value AoH 2 """) lhs_yaml = get_yaml_editor() (lhs_data, lhs_loaded) = get_yaml_data(lhs_yaml, quiet_logger, lhs_yaml_file) mc = MergerConfig(quiet_logger, SimpleNamespace(config=config_file, aoh=cli)) mc.prepare(lhs_data) node = lhs_data["array_of_hashes"] parent = lhs_data parentref = "array_of_hashes" assert mc.aoh_merge_mode(NodeCoords(node, parent, parentref)) == mode
def main(): """Main code.""" args = processcli() log = ConsolePrinter(args) validateargs(args, log) # For the remainder of processing, overwrite overwrites output if args.overwrite: args.output = args.overwrite # Merge all input files merger = Merger(log, None, MergerConfig(log, args)) yaml_editor = Parsers.get_yaml_editor() exit_state = 0 consumed_stdin = False merger_primed = False for yaml_file in args.yaml_files: if yaml_file.strip() == '-': consumed_stdin = True log.debug( "yaml_merge::main: Processing file, {}".format( "STDIN" if yaml_file.strip() == "-" else yaml_file)) proc_state = process_yaml_file( merger, log, yaml_editor, yaml_file, merger_primed) if proc_state == 0: merger_primed = True else: exit_state = proc_state break # Check for a waiting STDIN document if (exit_state == 0 and not consumed_stdin and not args.nostdin and not sys.stdin.isatty() ): exit_state = process_yaml_file( merger, log, yaml_editor, '-', merger_primed) # Output the final document if exit_state == 0: write_output_document(args, log, merger, yaml_editor) sys.exit(exit_state)
def merge_docs( log: ConsolePrinter, yaml_editor: YAML, config: MergerConfig, lhs_docs: List[Merger], rhs_file: str ) -> int: """Merge RHS into LHS.""" return_state = 0 merge_mode = config.get_multidoc_mode() (rhs_docs, rhs_loaded) = get_doc_mergers( log, yaml_editor, config, rhs_file) if not rhs_loaded: # Failed to load any RHS documents return 3 if merge_mode is MultiDocModes.CONDENSE_ALL: return_state = merge_condense_all(log, lhs_docs, rhs_docs) elif merge_mode is MultiDocModes.MERGE_ACROSS: return_state = merge_across(log, lhs_docs, rhs_docs) elif merge_mode is MultiDocModes.MATRIX_MERGE: return_state = merge_matrix(log, lhs_docs, rhs_docs) return return_state
def test_hash_merge_mode_default(self, quiet_logger): mc = MergerConfig(quiet_logger, SimpleNamespace(hashes=None)) assert mc.hash_merge_mode(NodeCoords(None, None, None)) == HashMergeOpts.DEEP
def test_get_multidoc_mode_default(self, quiet_logger): mc = MergerConfig(quiet_logger, SimpleNamespace()) assert mc.get_multidoc_mode() == MultiDocModes.CONDENSE_ALL
def test_anchor_merge_mode_cli(self, quiet_logger, setting, mode): mc = MergerConfig(quiet_logger, SimpleNamespace(anchors=setting)) assert mc.anchor_merge_mode() == mode
def test_get_insertion_point_default(self, quiet_logger): mc = MergerConfig(quiet_logger, SimpleNamespace()) assert mc.get_insertion_point() == YAMLPath("/")
def test_aoh_merge_mode_default(self, quiet_logger): mc = MergerConfig(quiet_logger, SimpleNamespace(aoh=None)) assert mc.aoh_merge_mode(NodeCoords(None, None, None)) == AoHMergeOpts.ALL
def test_get_insertion_point_cli(self, quiet_logger): mc = MergerConfig(quiet_logger, SimpleNamespace(mergeat="la.tee.dah")) assert mc.get_insertion_point() == YAMLPath("/la/tee/dah")
def test_anchor_merge_mode_default(self, quiet_logger): mc = MergerConfig(quiet_logger, SimpleNamespace(anchors=None)) assert mc.anchor_merge_mode() == AnchorConflictResolutions.STOP
def test_set_merge_mode_cli(self, quiet_logger, setting, mode): mc = MergerConfig(quiet_logger, SimpleNamespace(sets=setting)) assert mc.set_merge_mode(NodeCoords(None, None, None)) == mode
def test_set_merge_mode_default(self, quiet_logger): mc = MergerConfig(quiet_logger, SimpleNamespace(sets=None)) assert mc.set_merge_mode(NodeCoords(None, None, None)) == SetMergeOpts.UNIQUE
def test_get_multidoc_mode_cli(self, quiet_logger): mc = MergerConfig(quiet_logger, SimpleNamespace(multi_doc_mode="matrix_merge")) assert mc.get_multidoc_mode() == MultiDocModes.MATRIX_MERGE
def test_get_document_format(self, quiet_logger): mc = MergerConfig(quiet_logger, SimpleNamespace()) assert mc.get_document_format() == OutputDocTypes.AUTO