Skip to content

Instantly share code, notes, and snippets.

@cjerdonek
Last active January 25, 2024 19:39
Show Gist options
  • Save cjerdonek/2dad48eea22846476487d594cd906493 to your computer and use it in GitHub Desktop.
Save cjerdonek/2dad48eea22846476487d594cd906493 to your computer and use it in GitHub Desktop.
Python script showing how html diffs of Jupyter notebooks can be created non-interactively (e.g. from the command-line in CI) using nbdime.
"""
Python script showing how html diffs of Jupyter notebooks can be created
non-interactively (e.g. from the command-line in CI) using nbdime
(https://github.com/jupyter/nbdime) in combination with nbdime PR #744:
https://github.com/jupyter/nbdime/pull/744
Usage:
$ python test-nbdime-html-diff.py NB_PATH1 NB_PATH2
"""
from pathlib import Path
import sys
import jinja2
from jinja2 import Environment, FileSystemLoader
import nbdime.diffing.notebooks as notebooks
import nbdime.utils as nb_utils
import nbdime.webapp as webapp
WEBAPP_DIR = Path(webapp.__file__).parent
def read_notebook(path):
with path.open() as f:
data = nb_utils.read_notebook(f, on_null='empty')
return data
def diff_notebooks(path1, path2, output_path, static_dir):
nb_data1 = read_notebook(path1)
nb_data2 = read_notebook(path2)
# Here is where you can tell nbdime what to include and ignore.
# For example, tell nbdime to ignore differences in cell metadata.
notebooks.set_notebook_diff_targets(metadata=False)
diff_result = notebooks.diff_notebooks(nb_data1, nb_data2)
template_dir = WEBAPP_DIR / 'templates'
template_loader = FileSystemLoader(template_dir)
env = Environment(
loader=template_loader, autoescape=jinja2.select_autoescape(),
)
template = env.get_template('diff.html')
def static_url(rel_path):
path = static_dir / rel_path
return path
# The showDiff() function in the nbdime package's diff.ts file
# expects key-values "base" and "diff".
diff_data = {
'base': nb_data1,
'diff': diff_result,
}
config_data = {
'base': str(path1),
'remote': str(path2),
'diff_data': diff_data,
}
context = {
# The nbdime package's base nbdimepage.html template calls tojson()
# on the config_data value.
'config_data': config_data,
'static_url': static_url,
}
html = template.render(context)
output_path.write_text(html)
def main():
args = sys.argv[1:]
assert len(args) == 2
path1, path2 = (Path(path) for path in args)
output_path = Path('test-diff.html')
# Pass a static_dir that lets us test the locally generated JS.
static_dir = WEBAPP_DIR.absolute() / 'static'
diff_notebooks(
path1, path2=path2, output_path=output_path, static_dir=static_dir,
)
print(f'wrote output to: {output_path}')
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment