<br><br><div class="gmail_quote">On Sat, Nov 5, 2011 at 18:58, Fernando Perez <span dir="ltr">&lt;<a href="mailto:fperez.net@gmail.com">fperez.net@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

Hi folks,<br>
<br>
I wanted to start a discussion on the notebook format regarding its<br>
suitability for version control.  I see the notebook format as the way<br>
in which I&#39;ll likely keep (and hopefully many others too) most of my<br>
research notes/work, and thereore it&#39;s important that it&#39;s as easy as<br>
possible to version control notebooks and use them smoothly in a<br>
version-controlled workflow.  Unfortunately right now, the format we<br>
have simply doesn&#39;t fit that, mainly for two reasons:<br>
<br>
1. The cell inputs (code and text) are stored as a single line in the<br>
json format.  This means that virtually any edits anywhere in a cell<br>
will immediately produce VC conflicts.  Furthermore, they are nearly<br>
impossible to resolve by hand because you have to scan very long lines<br>
by eye, and can only apply wholesale one version or the other.<br>
<br>
2. The presence of outputs stored inside the file causes two separate problems:<br>
a) The large binary blobs make the files often quite large.<br>
b) Changes in the binary blobs can&#39;t really be inspected by hand, but<br>
tend to easily cause conflicts.<br>
<br>
To get a sense of the problem, here&#39;s the diff from a pull request<br>
made on a simple (mostly for testing purposes) repo:<br>
<br>
<a href="https://github.com/fperez/nipy-notebooks/pull/1/files" target="_blank">https://github.com/fperez/nipy-notebooks/pull/1/files</a><br>
<br>
That diff is more or less useless: note the huge horizontal scroll<br>
bar, and changes in inputs are impossible to understand.<br>
<br>
So I think we need to find a solution.  This doesn&#39;t have to happen<br>
necessarily right away, since we&#39;re trying to put 0.12 out; I think<br>
it&#39;s OK if for now our format is mostly treated as a binary blob.  But<br>
we do need to come up with a plan for the medium term.<br>
<br>
Here&#39;s my proposal, with full credit going to Yarik who suggested the<br>
idea of splitting outputs into a separate file.  There are basically<br>
two changes against what we have now:<br>
<br>
1. The notebook would *always* be split into two files, the .ipynb<br>
containing only inputs, and a companion (say .ipynbo) file with all<br>
outputs.  If an output file is not available or is detected to have<br>
problems such as cell number mismatch, it is simply ignored (it can<br>
always be recreated by rerunning the notebook.<br></blockquote><div><br></div><div>There is a *huge* disadvantage in portability to notebooks not being single files.  I think this still makes</div><div>sense, though.  I would treat the output as a &#39;cache&#39; (along the lines of .pyc / __cache__),</div>

<div>rather than considering the notebook itself as a multi-file format.  And you should be able</div><div>to embed the outputs in a single file if you want, for easier portability.</div><div><br></div><div>Doing it this way would not require changing the notebook format, because current (output-included) </div>

<div>notebooks would still comply with the spec.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><br>
2. All inputs would be stored in a json list of strings instead of a<br>
single string.<br></blockquote><div><br></div><div>I like this - splitlines(code) / &#39;\n&#39;.join(lines) makes it easy.  This change does mean that we need it to be nbformat v3.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">


<br>
With #1, one would naturally only commit to VC the ipynb file, leaving<br>
the output ones to be always ignored.  People could obviously choose<br>
to commit the output as well, at their own risk. #2 would make it much<br>
easier to get line-by-line diffs of any input (code or text).<br>
<br>
I think together, these two changes mostly solve the problems I&#39;ve<br>
encountered in practice so far.  I&#39;m trying really hard to eat our own<br>
dogfood by using these tools in actual, everyday research work, so<br>
that we see the problems first.  And while I think the notebook is<br>
reaching a point where it&#39;s a great working environment (even if we<br>
have a ton of ideas for improvements already and things we know need<br>
fixing), it&#39;s clear now to me that we fail pretty badly as a<br>
version-controllable format.<br>
<br>
I realize that implementing something like this will add non-trivial<br>
complexity to the format read/write code in a number of places, so if<br>
anyone sees a simpler solution to the problem, we&#39;re all ears.  But we<br>
do need to figure out how to make the notebooks first-class citizens<br>
in a VC world; the (effectively) opaque binary blobs they are now just<br>
won&#39;t cut it in the long run.</blockquote><div><br></div><div>Yes, we do need to do better.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
Thoughts, ideas?<br></blockquote><div><br></div><div>I think this sounds like a good start, with the only change that we still allow (optionally) outputs in a single file via the download button, rather than the notebook format being canonically multifile, which is just too painful.</div>

<div><br></div><div>I think the key-order issue you mention in the addendum is easily fixed by specifying `sort_keys=True` in the json dump.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">


<br>
Cheers,<br>
<br>
f<br>
_______________________________________________<br>
IPython-dev mailing list<br>
<a href="mailto:IPython-dev@scipy.org">IPython-dev@scipy.org</a><br>
<a href="http://mail.scipy.org/mailman/listinfo/ipython-dev" target="_blank">http://mail.scipy.org/mailman/listinfo/ipython-dev</a><br>
</blockquote></div><br>