def test_decide_merge_mixed_nested_transients(): # For this test, we need to use a custom predicate to ensure alignment common = {'id': 'This ensures alignment'} predicates = defaultdict(lambda: [operator.__eq__], { '/': [lambda a, b: a['id'] == b['id']], }) # Setup transient difference in base and local, deletion in remote b = [{'a': {'transient': 22}}] l = [{'a': {'transient': 242}}] b[0].update(common) l[0].update(common) r = [] # Make decisions based on diffs with predicates ld = diff(b, l, path="", predicates=predicates) rd = diff(b, r, path="", predicates=predicates) # Assert that generic merge gives conflict strategies = Strategies() decisions = decide_merge_with_diff(b, l, r, ld, rd, strategies) assert apply_decisions(b, decisions) == b assert len(decisions) == 1 assert decisions[0].conflict # Supply transient list to autoresolve, and check that transient is ignored strategies = Strategies(transients=[ '/*/a/transient' ]) decisions = decide_merge_with_diff(b, l, r, ld, rd, strategies) assert apply_decisions(b, decisions) == r assert not any(d.conflict for d in decisions)
def test_decide_merge_mixed_nested_transients(): # For this test, we need to use a custom predicate to ensure alignment common = {'id': 'This ensures alignment'} predicates = defaultdict(lambda: [operator.__eq__], { '/': [lambda a, b: a['id'] == b['id']], }) # Setup transient difference in base and local, deletion in remote b = [{'a': {'transient': 22}}] l = [{'a': {'transient': 242}}] b[0].update(common) l[0].update(common) r = [] # Make decisions based on diffs with predicates ld = diff(b, l, path="", predicates=predicates) rd = diff(b, r, path="", predicates=predicates) # Assert that generic merge gives conflict strategies = Strategies() decisions = decide_merge_with_diff(b, l, r, ld, rd, strategies) assert apply_decisions(b, decisions) == b assert len(decisions) == 1 assert decisions[0].conflict # Supply transient list to autoresolve, and check that transient is ignored strategies = Strategies(transients=['/*/a/transient']) decisions = decide_merge_with_diff(b, l, r, ld, rd, strategies) assert apply_decisions(b, decisions) == r assert not any(d.conflict for d in decisions)
def decide_merge(base, local, remote, args=None): # Build merge strategies for each document path from arguments strategies = merge_strategies(args) # Compute diffs local_diffs = diff_dicts(base, local) remote_diffs = diff_dicts(base, remote) # Debug outputs if args and args.log_level == "DEBUG": # log pretty-print config object: config = PrettyPrintConfig() nbdime.log.debug("In merge, base-local diff:") config.out = StringIO() pretty_print_notebook_diff("<base>", "<local>", base, local_diffs, config) nbdime.log.debug(config.out.getvalue()) nbdime.log.debug("In merge, base-remote diff:") config.out = StringIO() pretty_print_notebook_diff("<base>", "<remote>", base, remote_diffs, config) nbdime.log.debug(config.out.getvalue()) # Execute a generic merge operation decisions = decide_merge_with_diff(base, local, remote, local_diffs, remote_diffs, strategies) # Debug outputs if args and args.log_level == "DEBUG": nbdime.log.debug("In merge, decisions:") config.out = StringIO() pretty_print_merge_decisions(base, decisions, config) nbdime.log.debug(config.out.getvalue()) return decisions