Skip to content

Instantly share code, notes, and snippets.

@vidartf
Last active June 20, 2017 14:38
Show Gist options
  • Save vidartf/2551f2a825e412fb323a8d67e341e75f to your computer and use it in GitHub Desktop.
Save vidartf/2551f2a825e412fb323a8d67e341e75f to your computer and use it in GitHub Desktop.
from nbdime.patching import patch
from nbdime.diff_format import DiffOp
def iterate_cells_diffed(notebook, diff):
"""Generates tuples of (base, remote) cells from a given notebook and diff.
Yields tuples in the format: (base_cell, remote_cell)
Added cells will be (None, added_cell),
removed cells (removed_cell, None),
unchanged cells (base_cell, base_cell) (check equality with `is` operator)
patched cells (base_cell, patched_cell)
"""
# Only care about changes to cell (not notebook metadata)
# so we extract the cell list, and its diff:
cells = notebook['cells']
cell_diff = [d for d in diff if d.key == 'cells']
assert len(cell_diff) < 2, "Ill-formed diff"
if cell_diff:
assert cell_diff[0].op == DiffOp.PATCH, 'Ill-formed diff'
cell_diff = cell_diff[0].diff
# Make a LUT: lut[base-key][diff-op] = list_of_diff_entries
key_lut = {}
for entry in diff:
default = {DiffOp.ADDRANGE: [], DiffOp.REMOVERANGE: [], DiffOp.PATCH: []}
key_lut.get(entry.key, default)[entry.op] = entry
# Diff key refers to list positions in base
for i, base_cell in enumerate(cells):
# First check if unchanged:
if i not in key_lut:
yield (base_cell, base_cell)
continue
# Look for inserted entries before base entry
inserted = key_lut[i][DiffOp.ADDRANGE]
for entry in inserted:
# Yield individual entries
for sub_entry in entry.valuelist:
yield (None, sub_entry)
# Next, check whether there are cells that have been deleted starting from current location
deleted = key_lut[i][DiffOp.REMOVERANGE]
assert len(deleted) <= 1, "Ill-formed diff, several diff entries remove same key"
if deleted:
deleted = deleted[0]
# Yield individual entries
for sub_entry in cells[i : i + deleted.length]:
yield (sub_entry, None)
# Finally, check for modified entries:
patch_diff = key_lut[i][DiffOp.PATCH]
if patch_diff:
yield (base_cell, patch(base_cell, patch_diff))
"""Simple demonstrator code for using the function.
"""
import argparse
from nbdime.diffing import diff_notebooks
from nbdime.utils import read_notebook
from nbdime.prettyprint import pretty_print_cell
# Take two notebook filenames on command line
parser = argparse.ArgumentParser()
parser.add_argument('a')
parser.add_argument('b')
args = parser.parse_args()
# Read notebooks
a = read_notebook(args.a, on_null='empty')
b = read_notebook(args.b, on_null='empty')
# Diff them:
d = diff_notebooks(a, b)
# Iterate over cell (base, remote) pairs:
for pair in iterate_cells_diffed(a, d):
if pair[0] is pair[1]:
# Unchanged:
print('Unchanged cell:')
pretty_print_cell(None, pair[0])
elif pair[0] is None:
print('Added cell:')
pretty_print_cell(None, pair[1])
elif pair[1] is None:
print('Removed cell:')
pretty_print_cell(None, pair[0])
else:
print('Cell changed:')
print('Old cell:')
pretty_print_cell(None, pair[0])
print('New cell:')
pretty_print_cell(None, pair[1])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment