I should say that the nb_open and nb_data interfaces I&#39;m suggesting are independent of the storage format, so adopting them now for a JSON based storage would be safe even if the storage format changes to something else in the future.<div>

<br></div><div>Tom<br><br><div class="gmail_quote">On Tue, Jun 5, 2012 at 9:09 PM, Thomas Breuel <span dir="ltr">&lt;<a href="mailto:tmbdev@gmail.com" target="_blank">tmbdev@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">

<div class="gmail_quote"><div>Hi,</div><div><br></div><div>thanks for the response.</div><div class="im"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Our vision is &#39;folder as a project&#39; - so the code in a notebook sits<br>



alongside data files, keeping the notebook file lightweight and<br>
suitable for version control.<br></blockquote><div><br></div></div><div>Well, right now the notebook is a file in JSON format, but it already includes binary data in encoded form.  I&#39;m just suggesting a small addition that would make this existing storage facility useful for storing modest amounts of extra data.</div>


<div><br></div><div>If you do want to change the notebook format in the future, I think that&#39;s worth considering; see my suggestion at the very end.</div><div class="im"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


I can see there&#39;s an argument for having a way to store data as part<br>
of a notebook, but I think there are some questions:<br>
- How would the user interface work: How would the data be brought in<br>
and assigned to a variable? What would be displayed in the notebook?<br>
Would we handle different types of files differently, or treat all<br>
binary files the same?<br></blockquote><div><br></div></div><div>A simple interface might be the following:</div><div><br></div><div>stream = nb_open(&quot;some/path/to/my.data&quot;)</div><div><br></div><div>data = nb_data(&quot;mydata&quot;,lambda:randn(100))</div>


<div><br></div><div>nb_open opens a stream to the data cached in the notebook, unless that data doesn&#39;t exist; in that case, it caches the file in the notebook and then opens it.  It always returns just a stream.</div>


<div><br></div><div>nb_data gets data from the notebook if it has been stored there; if not, it calls its second argument, stores the result in the notebook, and also returns it.</div><div><br></div><div>This interface means that as an author, I just write the code, maybe clear the notebook cache a few times, but I don&#39;t even have to think about managing the notebook data; if my notebook works once, it will continue to work indefinitely even if the file or data become unavailable (until I clear the notebook data explicitly).</div>


<div><br></div><div>See the low-level code below.</div><div><br></div><div>(There should be a UI button and another function for clearing the cache/data stored in the notebook.)</div><div class="im"><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


- How would performance hold up? We&#39;d have to base64 encode the data<br>
to store it in JSON, so loading binary data will inevitably be slower<br>
as it has an extra decoding step. It also increases the size of the<br>
data on disk.<br></blockquote><div><br></div></div><div>Obviously, this doesn&#39;t solve all data storage problems.  But many educational notebooks just need an image or a small dataset, and having an easy way of storing such moderate amounts of data in the notebook would be nice, in particular since the notebook already stores comparable kinds and amounts of data for the outputs.</div>

<div class="im">
<div><br></div><blockquote class="gmail_quote" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">


 - Is the cost/benefit trade off worth it? This may involve significant</blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
extra complexity in IPython, and it&#39;s simple enough to zip up a<br>
notebook file + input data.</blockquote><div><br></div></div><div>I think this can probably piggy-back on existing mechanisms.  I think you need two low-level Python functions: nb_get_binary_data(key) and nb_put_binary_data(key,value).  The first one sends a message to the notebook asking whether there is binary data for the given key and returns it or returns None, and the second one stores binary data under the given key.    I think those should be pretty easy to provide, since the same kind of thing already needs to happen for output cells.</div>


<div><br></div><div>In terms of those primitives, nb_open looks roughly like:</div><div><br></div><div>def nb_open(path,mode=&quot;r&quot;):</div><div>    assert mode==&quot;r&quot;,&quot;cached files need to be read-only for now&quot;</div>


<div>    key = &quot;file:&quot;+path</div><div>    data = nb_get_binary_data(key)</div><div>    if data is None:</div><div>        with open(path) as stream: data = stream.read()</div><div>        nb_put_binary_data(key,data)</div>


<div>    return data_as_stream(data,&quot;r&quot;)</div><div><br></div><div>The nb_data(name,thunk) function would be pretty similar.</div><div><br></div><div>Tom</div><div><br></div><div>PS: As for the &quot;notebook as directory&quot;, having notebooks be single files is quite convenient, since zipping/unzipping things and dealing with directories can be a nuisance in many settings.  What you could do in the future, however, is allow notebooks to be either directories or zip files containing a directory tree, making the difference as transparent to the notebook and user.  I think that would be a great direction to go into, also because you could then store the output images separate from the pure text.  Note that OpenOffice and OpenDocument files work that way, and data files could also be embedded efficiently. Furthermore, version control tools are starting to be able to deal with document formats based on zip files.  But, in any case, that&#39;s a bigger change than what I suggested above.</div>


<div><br>For ZIP files as document formats, see <a href="http://www.openoffice.org/xml/faq.html" target="_blank">http://www.openoffice.org/xml/faq.html</a> and <a href="http://en.wikipedia.org/wiki/OpenDocument" target="_blank">http://en.wikipedia.org/wiki/OpenDocument</a></div>


<div><br></div><div>Here is Mercurial version control for ZIP-based document formats: <a href="http://mercurial.selenic.com/wiki/ZipdocExtension" target="_blank">http://mercurial.selenic.com/wiki/ZipdocExtension</a></div>

</div>
</blockquote></div><br></div>