def test_inline_merge_source_add_to_line(): "More elaborate test of cell deletions on both sides, onesided and agreed." # Note: Merge rendering of conflicted sources here will depend on git/diff/builtin params and availability base = code_nb([ "first source", "other text", "this cell will be deleted and patched\nhere we add", "yet more content", "and a final line", ], strip_ids=True) local = code_nb( [ "1st source", # onesided change "other text", #"this cell will be deleted and patched", "some more content", # twosided equal change "And a Final line", # twosided conflicted change ], strip_ids=True) remote = code_nb( [ "first source", "other text?", # onesided change "this cell will be deleted and patched\nhere we add text to a line", "some more content", # equal "and The final Line", # conflicted ], strip_ids=True) expected = code_nb( [ "1st source", "other text?", #'<<<<<<< local <CELL DELETED>\n\n=======\nthis cell will be deleted and modified\n>>>>>>> remote' '<<<<<<< LOCAL CELL DELETED >>>>>>>\nthis cell will be deleted and patched\nhere we add text to a line', "some more content", # equal '<<<<<<< local\nAnd a Final line\n=======\nand The final Line\n>>>>>>> remote' ], strip_ids=True) merged, decisions = merge_notebooks(base, local, remote) assert merged == expected expected = code_nb( [ "1st source", "other text?", #'<<<<<<< local\nthis cell will be deleted and modified\n=======\n>>>>>>> remote <CELL DELETED>' '<<<<<<< REMOTE CELL DELETED >>>>>>>\nthis cell will be deleted and patched\nhere we add text to a line', "some more content", '<<<<<<< local\nand The final Line\n=======\nAnd a Final line\n>>>>>>> remote' ], strip_ids=True) merged, decisions = merge_notebooks(base, remote, local) assert merged == expected
def test_metadata_union_strategy_not_applied_immutable_on_dict(): # Conflicting cell inserts at same location as removing old cell expected_partial_source = [["remote\n", "some other\n", "lines\n", "to align\n"]] expected_partial_metadata = [{'myval': 5}] expected_partial_outputs = [["local\nsome other\nlines\nto align\n", "output2", "output3"]] base, local, remote, expected_partial = _make_notebook_with_multi_conflicts( expected_partial_source, expected_partial_metadata, expected_partial_outputs ) base.cells[0].metadata['myval'] = 5 local.cells[0].metadata['myval'] = 22 remote.cells[0].metadata['myval'] = 13 expected_conflicts = [{ 'action': 'base', 'common_path': ('cells', 0, 'metadata'), 'conflict': True, 'local_diff': [{'key': 'myval', 'op': 'replace', 'value': 22}], 'remote_diff': [{'key': 'myval', 'op': 'replace', 'value': 13}] }] merge_args = copy.deepcopy(args) merge_args.merge_strategy = "union" merge_args.input_strategy = "use-remote" merge_args.output_strategy = "use-local" partial, decisions = merge_notebooks(base, local, remote, merge_args) _check(partial, expected_partial, decisions, expected_conflicts)
def test_inline_merge_source_empty(): base = new_notebook() local = new_notebook() remote = new_notebook() expected = new_notebook() merged, decisions = merge_notebooks(base, local, remote) assert merged == expected
def test_inline_merge_source_cell_deletions(): "Cell deletions on both sides, onesided and agreed." base = code_nb([ "first source", "other text", "yet more content", "and a final line", ]) local = code_nb([ #"first source", "other text", #"yet more content", #"and a final line", ]) remote = code_nb([ "first source", #"other text", "yet more content", #"and a final line", ]) empty = code_nb([]) expected = code_nb([]) for a in [base, local, remote, empty]: for b in [base, local, remote, empty]: merged, decisions = merge_notebooks(base, a, b) if a is b: assert merged == a elif a is base: assert merged == b elif b is base: assert merged == a else: # All other combinations will delete all cells assert merged == empty
def test_autoresolve_notebook_ec(): args = None # We need a source here otherwise the cells are not aligned source = "def foo(x, y):\n return x**y" base = nbformat.v4.new_notebook() base["cells"].append(nbformat.v4.new_code_cell()) base["cells"][0]["source"] = source base["cells"][0]["execution_count"] = 1 local = copy.deepcopy(base) remote = copy.deepcopy(base) expected = copy.deepcopy(base) local["cells"][0]["execution_count"] = 2 remote["cells"][0]["execution_count"] = 3 expected["cells"][0]["execution_count"] = None merged, local_conflicts, remote_conflicts = merge_notebooks(base, local, remote, args) if 0: print() print(merged) print(local_conflicts) print(remote_conflicts) print() assert merged == expected assert local_conflicts == [] assert remote_conflicts == []
def test_autoresolve_notebook_ec(): args = None # We need a source here otherwise the cells are not aligned source = "def foo(x, y):\n return x**y" base = nbformat.v4.new_notebook() base["cells"].append(nbformat.v4.new_code_cell()) base["cells"][0]["source"] = source base["cells"][0]["execution_count"] = 1 local = copy.deepcopy(base) remote = copy.deepcopy(base) expected = copy.deepcopy(base) local["cells"][0]["execution_count"] = 2 remote["cells"][0]["execution_count"] = 3 expected["cells"][0]["execution_count"] = None merged, local_conflicts, remote_conflicts = merge_notebooks( base, local, remote, args) if 0: print() print(merged) print(local_conflicts) print(remote_conflicts) print() assert merged == expected assert local_conflicts == [] assert remote_conflicts == []
def test_autoresolve_inline_source_conflict(db): nbb = db["inline-conflict--1"] nbl = db["inline-conflict--2"] nbr = db["inline-conflict--3"] args = builder.parse_args(["", "", ""]) args.merge_strategy = 'inline' merged, decisions = merge_notebooks(nbb, nbl, nbr, args) # Has conflicts assert any(d.conflict for d in decisions) source = merged.cells[0].source expected = """<<<<<<< local x = 1 y = 3 z = 4 print(x * y / z) ||||||| base x = 1 y = 3 print(x * y) ======= x = 1 y = 3 print(x + q) >>>>>>> remote""" assert source == expected
def test_merge_cell_sources_separate_inserts(): base = strip_cell_ids( sources_to_notebook([ [ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], ])) local = strip_cell_ids( sources_to_notebook([ [ "print(f(3))", ], [ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], ])) remote = strip_cell_ids( sources_to_notebook([ [ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], [ "print(f(7))", ], ])) expected = strip_cell_ids( sources_to_notebook([ [ "print(f(3))", ], [ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], [ "print(f(7))", ], ])) actual, decisions = merge_notebooks(base, local, remote, args) assert not any([d.conflict for d in decisions]) assert actual == expected
def test_inline_merge_source_patches_both_ends(): "More elaborate test of cell deletions on both sides, onesided and agreed." # Note: Merge rendering of conflicted sources here will depend on git/diff/builtin params and availability base = code_nb([ "first source will be modified", "other text", "this cell will be untouched", "yet more content", "and final line will be changed", ], strip_ids=True) local = code_nb([ "first source will be modified locally", "other text", "this cell will be untouched", "yet more content", "and final line will be changed locally", ], strip_ids=True) remote = code_nb([ "first source will be modified remotely", "other text", "this cell will be untouched", "yet more content", "and final line will be changed remotely", ], strip_ids=True) expected = code_nb([ '<<<<<<< local\nfirst source will be modified locally\n=======\nfirst source will be modified remotely\n>>>>>>> remote', "other text", "this cell will be untouched", "yet more content", '<<<<<<< local\nand final line will be changed locally\n=======\nand final line will be changed remotely\n>>>>>>> remote', ], strip_ids=True) merged, decisions = merge_notebooks(base, local, remote) assert merged == expected expected = code_nb([ '<<<<<<< local\nfirst source will be modified remotely\n=======\nfirst source will be modified locally\n>>>>>>> remote', "other text", "this cell will be untouched", "yet more content", '<<<<<<< local\nand final line will be changed remotely\n=======\nand final line will be changed locally\n>>>>>>> remote', ], strip_ids=True) merged, decisions = merge_notebooks(base, remote, local) assert merged == expected
def test_inline_merge_attachments(): # FIXME: Use output creation utils Vidar wrote in another test file base = new_notebook() local = new_notebook() remote = new_notebook() expected = new_notebook() merged, decisions = merge_notebooks(base, local, remote) assert merged == expected
def test_inline_merge_source_onesided_only(): "A mix of changes on one side (delete, patch, remove)." base = code_nb([ "first source", "other text", "yet more content", ]) changed = code_nb([ #"first source", # deleted "other text v2", "a different cell inserted", "yet more content", ]) merged, decisions = merge_notebooks(base, changed, base) assert merged == changed merged, decisions = merge_notebooks(base, base, changed) assert merged == changed
def test_inline_merge_dummy_notebooks(): "Just the basic empty notebook passes through." base = new_notebook() local = new_notebook() remote = new_notebook() expected = new_notebook() merged, decisions = merge_notebooks(base, local, remote) assert expected == merged
def test_inline_merge_empty_notebooks(): "Missing fields all around passes through." base = {} local = {} remote = {} expected = {} merged, decisions = merge_notebooks(base, local, remote) assert expected == merged
def test_inline_merge_notebook_version(): "Minor version gets bumped to max." base = new_notebook(nbformat=4, nbformat_minor=0) local = new_notebook(nbformat=4, nbformat_minor=1) remote = new_notebook(nbformat=4, nbformat_minor=2) expected = new_notebook(nbformat=4, nbformat_minor=2) merged, decisions = merge_notebooks(base, local, remote) assert expected == merged
def test_merge_cell_sources_separate_inserts(): base = sources_to_notebook([ [ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], ]) local = sources_to_notebook([ [ "print(f(3))", ], [ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], ]) remote = sources_to_notebook([ [ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], [ "print(f(7))", ], ]) expected = sources_to_notebook([ [ "print(f(3))", ], [ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], [ "print(f(7))", ], ]) args = None actual, lco, rco = merge_notebooks(base, local, remote, args) assert not lco assert not rco assert actual == expected
def test_autoresolve_inline_source_conflict(db): nbb = db["inline-conflict--1"] nbl = db["inline-conflict--2"] nbr = db["inline-conflict--3"] args = builder.parse_args(["", "", ""]) args.merge_strategy = 'inline' merged, decisions = merge_notebooks(nbb, nbl, nbr, args) # Has conflicts assert any(d.conflict for d in decisions) source = merged.cells[0].source git_expected = """\ x = 1 <<<<<<< local y = 3 print(x * y) ======= q = 3.1 print(x + q) >>>>>>> remote """ builtin_expected_course = """\ <<<<<<< local x = 1 y = 3 z = 4 print(x * y / z) ======= x = 1 q = 3.1 print(x + q) >>>>>>> remote """ # ||||||| base # x = 1 # y = 3 # print(x * y) builtin_expected_finegrained = """\ x = 1 <<<<<<< local y = 3 z = 4 print(x * y / z) ======= q = 3.1 print(x + q) >>>>>>> remote """ expected = builtin_expected_finegrained assert source == expected
def test_inline_merge_source_add_to_line(): "More elaborate test of cell deletions on both sides, onesided and agreed." # Note: Merge rendering of conflicted sources here will depend on git/diff/builtin params and availability base = code_nb([ "first source", "other text", "this cell will be deleted and patched\nhere we add", "yet more content", "and a final line", ]) local = code_nb([ "1st source", # onesided change "other text", #"this cell will be deleted and patched", "some more content", # twosided equal change "And a Final line", # twosided conflicted change ]) remote = code_nb([ "first source", "other text?", # onesided change "this cell will be deleted and patched\nhere we add text to a line", "some more content", # equal "and The final Line", # conflicted ]) expected = code_nb([ "1st source", "other text?", #'<<<<<<< local <CELL DELETED>\n\n=======\nthis cell will be deleted and modified\n>>>>>>> remote' '<<<<<<< LOCAL CELL DELETED >>>>>>>\nthis cell will be deleted and patched\nhere we add text to a line', "some more content", # equal '<<<<<<< local\nAnd a Final line\n=======\nand The final Line\n>>>>>>> remote' ]) merged, decisions = merge_notebooks(base, local, remote) assert merged == expected expected = code_nb([ "1st source", "other text?", #'<<<<<<< local\nthis cell will be deleted and modified\n=======\n>>>>>>> remote <CELL DELETED>' '<<<<<<< REMOTE CELL DELETED >>>>>>>\nthis cell will be deleted and patched\nhere we add text to a line', "some more content", '<<<<<<< local\nand The final Line\n=======\nAnd a Final line\n>>>>>>> remote' ]) merged, decisions = merge_notebooks(base, remote, local) assert merged == expected
def _check_sources(base, local, remote, expected_partial, expected_conflicts, merge_args=None): base = src2nb(base) local = src2nb(local) remote = src2nb(remote) expected_partial = src2nb(expected_partial) merge_args = merge_args or args partial, decisions = merge_notebooks(base, local, remote, merge_args) _check(partial, expected_partial, decisions, expected_conflicts)
def _check_outputs(base, local, remote, expected_partial, expected_conflicts, merge_args=None): base = outputs_to_notebook(base) local = outputs_to_notebook(local) remote = outputs_to_notebook(remote) expected_partial = outputs_to_notebook(expected_partial) merge_args = merge_args or args partial, decisions = merge_notebooks(base, local, remote, merge_args) _check(partial, expected_partial, decisions, expected_conflicts)
def test_inline_merge_source_patch_delete_conflicts_both_ends(): "More elaborate test of cell deletions on both sides, onesided and agreed." # Note: Merge rendering of conflicted sources here will depend on git/diff/builtin params and availability base = code_nb([ "first source will be modified", "other text", "this cell will be untouched", "yet more content", "and final line will be changed", ]) local = code_nb([ "first source will be modified on one side", "other text", "this cell will be untouched", "yet more content", #"and final line will be deleted locally", ]) remote = code_nb([ #"first source will be deleted remotely", "other text", "this cell will be untouched", "yet more content", "and final line will be changed on one side", ]) expected = code_nb([ '<<<<<<< REMOTE CELL DELETED >>>>>>>\nfirst source will be modified on one side', "other text", "this cell will be untouched", "yet more content", '<<<<<<< LOCAL CELL DELETED >>>>>>>\nand final line will be changed on one side', ]) merged, decisions = merge_notebooks(base, local, remote) assert merged == expected expected = code_nb([ '<<<<<<< LOCAL CELL DELETED >>>>>>>\nfirst source will be modified on one side', "other text", "this cell will be untouched", "yet more content", '<<<<<<< REMOTE CELL DELETED >>>>>>>\nand final line will be changed on one side', ]) merged, decisions = merge_notebooks(base, remote, local) assert merged == expected
def test_inline_merge_source_all_equal(): base = code_nb([ "first source", "other text", "yet more content", ]) local = base remote = base expected = base merged, decisions = merge_notebooks(base, local, remote) assert merged == expected
def test_inline_merge_cells_replacement_similar(): base = sources_to_notebook([['unmodified'], ['base']], cell_type='markdown') local = sources_to_notebook([['unmodified'], ['local']], cell_type='markdown') remote = sources_to_notebook([['unmodified'], ['remote']], cell_type='markdown') expected = sources_to_notebook([['unmodified'], [("<" * 7) + ' local\n', 'local\n', ("=" * 7) + '\n', 'remote\n', (">" * 7) + ' remote']], cell_type='markdown') merged, decisions = merge_notebooks(base, local, remote) assert merged == expected
def test_inline_merge_cells_replacement_unsimilar(): base = sources_to_notebook([['unmodified'], ['base']], cell_type='markdown') local = sources_to_notebook([['unmodified'], ['local\n', 'friendly faces\n', '3.14']], cell_type='markdown') remote = sources_to_notebook([['unmodified'], ['remote\n', 'foo bar baz\n']], cell_type='markdown') expected = sources_to_notebook([ ['unmodified'], [_cell_marker_format(("<"*7) + ' local')], ['local\n', 'friendly faces\n', '3.14'], [_cell_marker_format("="*7)], ['remote\n', 'foo bar baz\n'], [_cell_marker_format((">"*7) + ' remote')], ], cell_type='markdown') merged, decisions = merge_notebooks(base, local, remote) assert merged == expected
def _check(base, local, remote, expected_partial, expected_lco, expected_rco): base = src2nb(base) local = src2nb(local) remote = src2nb(remote) expected_partial = src2nb(expected_partial) args = None partial, lco, rco = merge_notebooks(base, local, remote, args) sources = [cell["source"] for cell in partial["cells"]] expected_sources = [cell["source"] for cell in expected_partial["cells"]] assert sources == expected_sources assert partial == expected_partial assert lco == expected_lco assert rco == expected_rco
def _check_sources(base, local, remote, expected_partial, expected_conflicts, merge_args=None, ignore_cell_ids=False): base = src2nb(base, strip_ids=ignore_cell_ids) local = src2nb(local, strip_ids=ignore_cell_ids) remote = src2nb(remote, strip_ids=ignore_cell_ids) expected_partial = src2nb(expected_partial, strip_ids=ignore_cell_ids) merge_args = merge_args or args partial, decisions = merge_notebooks(base, local, remote, merge_args) _check(partial, expected_partial, decisions, expected_conflicts)
def post(self): base_nb = self.get_notebook_argument("base") local_nb = self.get_notebook_argument("local") remote_nb = self.get_notebook_argument("remote") try: merged, lco, rco = nbdime.merge_notebooks(base_nb, local_nb, remote_nb) except Exception as e: raise web.HTTPError(400, "Error while attempting to merge documents.") data = { "base": base_nb, "local_conflicts": lco, "remote_conflicts": rco, } self.finish(data)
def test_only_outputs(db, reset_diff_targets): base = db["mixed-conflicts--1"] local = db["mixed-conflicts--2"] remote = db["mixed-conflicts--3"] set_notebook_diff_targets(False, True, False, False) merge_args = copy.deepcopy(args) merge_args.merge_strategy = "mergetool" partial, decisions = merge_notebooks(base, local, remote, merge_args) assert len(decisions) > 0 for d in decisions: path = d['common_path'] # Still have some decisions on cell root, so avoid with len == 2 check assert len(path) == 2 or path[2] == 'outputs'
def test_inline_merge_cells_replacement_similar(): base = sources_to_notebook([['unmodified'], ['base']], cell_type='markdown') local = sources_to_notebook([['unmodified'], ['local']], cell_type='markdown') remote = sources_to_notebook([['unmodified'], ['remote']], cell_type='markdown') expected = sources_to_notebook([ ['unmodified'], [ ("<"*7) + ' local\n', 'local\n', ("="*7) + '\n', 'remote\n', (">"*7) + ' remote' ] ], cell_type='markdown') merged, decisions = merge_notebooks(base, local, remote) assert merged == expected
def _check_outputs(base, local, remote, expected_partial, expected_conflicts, merge_args=None, ignore_cell_ids=False): base = outputs_to_notebook(base, strip_ids=ignore_cell_ids) local = outputs_to_notebook(local, strip_ids=ignore_cell_ids) remote = outputs_to_notebook(remote, strip_ids=ignore_cell_ids) expected_partial = outputs_to_notebook(expected_partial, strip_ids=ignore_cell_ids) merge_args = merge_args or args partial, decisions = merge_notebooks(base, local, remote, merge_args) _check(partial, expected_partial, decisions, expected_conflicts)
def test_merge_cell_sources_separate_inserts(): base = sources_to_notebook([[ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], ]) local = sources_to_notebook([[ "print(f(3))", ], [ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], ]) remote = sources_to_notebook([[ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], [ "print(f(7))", ], ]) expected = sources_to_notebook([[ "print(f(3))", ], [ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], [ "print(f(7))", ], ]) args = None actual, lco, rco = merge_notebooks(base, local, remote, args) assert not lco assert not rco assert actual == expected
def test_merge_cell_sources_separate_inserts(): base = [[ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], ] local = [[ "print(f(3))", ], [ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], ] remote = [[ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], [ "print(f(7))", ], ] expected = sources_to_notebook([[ "print(f(3))", ], [ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], [ "print(f(7))", ], ]) actual, lco, rco = merge_notebooks(sources_to_notebook(base), sources_to_notebook(local), sources_to_notebook(remote)) assert not lco assert not rco assert actual == expected
def test_inline_merge_cells_insertion_unsimilar(): base = sources_to_notebook([['unmodified']], cell_type='markdown') local = sources_to_notebook( [['unmodified'], ['local\n', 'friendly faces\n', '3.14']], cell_type='markdown') remote = sources_to_notebook( [['unmodified'], ['remote\n', 'foo bar baz\n']], cell_type='markdown') expected = sources_to_notebook([ ['unmodified'], [_cell_marker_format(("<" * 7) + ' local')], ['local\n', 'friendly faces\n', '3.14'], [_cell_marker_format("=" * 7)], ['remote\n', 'foo bar baz\n'], [_cell_marker_format((">" * 7) + ' remote')], ], cell_type='markdown') merged, decisions = merge_notebooks(base, local, remote) assert merged == expected
def test_inline_merge_outputs_conflicting_insert_in_empty(): # One cell with two outputs: base = outputs_to_notebook([[]], strip_ids=True) local = outputs_to_notebook([['local']], strip_ids=True) remote = outputs_to_notebook([['remote']], strip_ids=True) expected = outputs_to_notebook([[ nbformat.v4.new_output( output_type='stream', name='stderr', text='<<<<<<< local\n'), 'local', nbformat.v4.new_output( output_type='stream', name='stderr', text='=======\n'), 'remote', nbformat.v4.new_output( output_type='stream', name='stderr', text='>>>>>>> remote\n'), ]], strip_ids=True) merged, decisions = merge_notebooks(base, local, remote) assert merged == expected
def test_merge_mix_strategies(): # Conflicting cell inserts at same location as removing old cell expected_partial_source = [["remote\n", "some other\n", "lines\n", "to align\n"]] expected_partial_metadata = [{'myval': 'local'}] expected_partial_outputs = [["local\nremote\nsome other\nlines\nto align\n", "output2", "output3"]] base, local, remote, expected_partial = _make_notebook_with_multi_conflicts( expected_partial_source, expected_partial_metadata, expected_partial_outputs ) expected_conflicts = [] merge_args = copy.deepcopy(args) merge_args.merge_strategy = "use-local" merge_args.input_strategy = "use-remote" merge_args.output_strategy = "union" partial, decisions = merge_notebooks(base, local, remote, merge_args) _check(partial, expected_partial, decisions, expected_conflicts)
def test_merge_cell_sources_separate_inserts(): base = sources_to_notebook([[ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], ]) local = sources_to_notebook([[ "print(f(3))", ], [ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], ]) remote = sources_to_notebook([[ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], [ "print(f(7))", ], ]) expected = sources_to_notebook([[ "print(f(3))", ], [ "def f(x):", " return x**2", ], [ "def g(y):", " return y + 2", ], [ "print(f(7))", ], ]) actual, decisions = merge_notebooks(base, local, remote, args) assert not any([d.conflict for d in decisions]) assert actual == expected
def test_inline_merge_cells_insertion_similar(): base = sources_to_notebook([['unmodified']], cell_type='markdown', strip_ids=True) local = sources_to_notebook([['unmodified'], ['local']], cell_type='markdown', strip_ids=True) remote = sources_to_notebook([['unmodified'], ['remote']], cell_type='markdown', strip_ids=True) expected = sources_to_notebook([ 'unmodified', [("<" * 7) + ' local\n', 'local\n', ("=" * 7) + '\n', 'remote\n', (">" * 7) + ' remote'] ], cell_type='markdown', strip_ids=True) merged, decisions = merge_notebooks(base, local, remote) assert merged == expected
def test_autoresolve_notebook_ec(): # We need a source here otherwise the cells are not aligned source = "def foo(x, y):\n return x**y" base = nbformat.v4.new_notebook() base["cells"].append(nbformat.v4.new_code_cell()) base["cells"][0]["source"] = source base["cells"][0]["execution_count"] = 1 local = copy.deepcopy(base) remote = copy.deepcopy(base) expected = copy.deepcopy(base) local["cells"][0]["execution_count"] = 2 remote["cells"][0]["execution_count"] = 3 expected["cells"][0]["execution_count"] = None merged, decisions = merge_notebooks(base, local, remote, args) assert merged == expected assert not any(d.conflict for d in decisions)
def test_autoresolve_notebook_ignore_fallback(): args = builder.parse_args(["", "", ""]) args.ignore_transients = True args.merge_strategy = 'use-remote' source = "def foo(x, y):\n return x**y" base = {"cells": [{ "source": source, "execution_count": 1, "cell_type": "code", "outputs": None}]} local = {"cells": [{ "source": source, "execution_count": 2, "cell_type": "code", "outputs": None}]} remote = {"cells": [{ "source": source, "execution_count": 3, "cell_type": "code", "outputs": None}]} merged, decisions = merge_notebooks(base, local, remote, args) assert merged == {"cells": [{ "source": source, "execution_count": None, "outputs": None, "cell_type": "code"}]} assert not any(d.conflict for d in decisions)
def test_autoresolve_notebook_no_ignore(): args = builder.parse_args(["", "", ""]) args.ignore_transients = False source = "def foo(x, y):\n return x**y" base = {"cells": [{ "source": source, "execution_count": 1, "cell_type": "code", "outputs": None}]} local = {"cells": [{ "source": source, "execution_count": 2, "cell_type": "code", "outputs": None}]} remote = {"cells": [{ "source": source, "execution_count": 3, "cell_type": "code", "outputs": None}]} merged, decisions = merge_notebooks(base, local, remote, args) assert merged == {"cells": [{ "source": source, "execution_count": 1, "outputs": None, "cell_type": "code"}]} assert decisions[0].conflict is True assert len(decisions) == 1
def test_autoresolve_notebook_ec(): # Tests here assume default autoresolve behaviour at time of writing, # this may change and tests should then be updated args = None source = "def foo(x, y):\n return x**y" base = {"cells": [{ "source": source, "execution_count": 1, "cell_type": "code", "outputs": None}]} local = {"cells": [{ "source": source, "execution_count": 2, "cell_type": "code", "outputs": None}]} remote = {"cells": [{ "source": source, "execution_count": 3, "cell_type": "code", "outputs": None}]} merged, decisions = merge_notebooks(base, local, remote, args) assert merged == {"cells": [{ "source": source, "execution_count": None, "outputs": None, "cell_type": "code"}]} assert not any(d.conflict for d in decisions)
def test_inline_merge_outputs(): # One cell with two outputs: base = outputs_to_notebook([['unmodified', 'base']]) local = outputs_to_notebook([['unmodified', 'local']]) remote = outputs_to_notebook([['unmodified', 'remote']]) expected = outputs_to_notebook([[ 'unmodified', nbformat.v4.new_output( output_type='stream', name='stderr', text='<<<<<<< local <modified: text/plain>\n'), 'local', nbformat.v4.new_output( output_type='stream', name='stderr', text='=======\n'), 'remote', nbformat.v4.new_output( output_type='stream', name='stderr', text='>>>>>>> remote <modified: text/plain>\n'), ]]) merged, decisions = merge_notebooks(base, local, remote) assert merged == expected
def test_merge_matching_notebooks(matching_nb_triplets, reset_log): "Test merge on pairs of notebooks with the same basename in the test suite." base, local, remote = matching_nb_triplets merged, decisions = merge_notebooks(base, local, remote)