Created
February 12, 2013 14:42
-
-
Save deeplook/4770302 to your computer and use it in GitHub Desktop.
An IPython notebook illustrating an IPython extension for displaying object graphs.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"metadata": { | |
"name": "object_graphs" | |
}, | |
"nbformat": 3, | |
"nbformat_minor": 0, | |
"worksheets": [ | |
{ | |
"cells": [ | |
{ | |
"cell_type": "heading", | |
"level": 1, | |
"metadata": {}, | |
"source": [ | |
"Writing an IPython extension to show object graphs" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"**Idea**: Reuse a Python package, [pyrels](http://pypi.python.org/pypi/pyrels/0.1.1), to display data structures graphically (see [presentation](http://de.slideshare.net/dinugherman/visualizing-relationships-between-python-objects-europython-2008) at EuroPython 2008) in an IPython notebook.\n", | |
"\n", | |
"**Inspiration**: Find an existing extension that already does something similar: display [GraphViz](http://www.graphviz.org) DOT files. [ipython-hierarchymagic](https://github.com/tkf/ipython-hierarchymagic) does it!" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"%install_ext https://raw.github.com/tkf/ipython-hierarchymagic/master/hierarchymagic.py\n", | |
"%load_ext hierarchymagic" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"Installed hierarchymagic.py. To use it, type:\n", | |
" %load_ext hierarchymagic\n" | |
] | |
} | |
], | |
"prompt_number": 1 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"This gives two new IPython magic commands: `%hierarchy` and `%%dot`, doing what you expect them to do, at least for `%%dot`. We skip %hierarchy here, but you can uncomment it to see the standard example. " | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"# %hierarchy get_ipython()" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 2 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"This is actually the command that is pretty similar to what we want:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"%%dot -f svg\n", | |
"digraph G {\n", | |
" a->b; b->c; c->d; c->a; d->b; d->a;\n", | |
"}" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"svg": [ | |
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", | |
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\"\n", | |
" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n", | |
"<!-- Generated by dot version 2.2.1 (Wed Jan 25 18:54:27 UTC 2012)\n", | |
" For user: (dinu) Dinu Gherman Title: G Pages: 1 -->\n", | |
"<svg width=\"150pt\" height=\"264pt\"\n", | |
" viewBox = \"-1 -1 149 263\"\n", | |
" xmlns=\"http://www.w3.org/2000/svg\">\n", | |
"<g id=\"graph0\" class=\"graph\" style=\"font-family:Times-Roman;font-size:14.00;\">\n", | |
"<title>G</title>\n", | |
"<g id=\"node1\" class=\"node\"><title>a</title>\n", | |
"<ellipse cx=\"78\" cy=\"22\" rx=\"27\" ry=\"18\" style=\"fill:none;stroke:black;\"/>\n", | |
"<text text-anchor=\"middle\" x=\"78\" y=\"27\">a</text>\n", | |
"</g>\n", | |
"<g id=\"node3\" class=\"node\"><title>b</title>\n", | |
"<ellipse cx=\"78\" cy=\"94\" rx=\"27\" ry=\"18\" style=\"fill:none;stroke:black;\"/>\n", | |
"<text text-anchor=\"middle\" x=\"78\" y=\"99\">b</text>\n", | |
"</g>\n", | |
"<g id=\"edge2\" class=\"edge\"><title>a->b</title>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M78,40C78,48 78,57 78,66\"/>\n", | |
"<polygon style=\"fill:black;stroke:black;\" points=\"82,66 78,76 75,66 82,66\"/>\n", | |
"</g>\n", | |
"<g id=\"node5\" class=\"node\"><title>c</title>\n", | |
"<ellipse cx=\"32\" cy=\"166\" rx=\"27\" ry=\"18\" style=\"fill:none;stroke:black;\"/>\n", | |
"<text text-anchor=\"middle\" x=\"32\" y=\"171\">c</text>\n", | |
"</g>\n", | |
"<g id=\"edge4\" class=\"edge\"><title>b->c</title>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M67,111C62,119 55,131 49,140\"/>\n", | |
"<polygon style=\"fill:black;stroke:black;\" points=\"51,143 43,149 46,139 51,143\"/>\n", | |
"</g>\n", | |
"<g id=\"edge8\" class=\"edge\"><title>c->a</title>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M31,148C32,129 33,100 42,76 46,65 52,55 58,46\"/>\n", | |
"<polygon style=\"fill:black;stroke:black;\" points=\"55,44 64,38 61,48 55,44\"/>\n", | |
"</g>\n", | |
"<g id=\"node7\" class=\"node\"><title>d</title>\n", | |
"<ellipse cx=\"87\" cy=\"238\" rx=\"27\" ry=\"18\" style=\"fill:none;stroke:black;\"/>\n", | |
"<text text-anchor=\"middle\" x=\"87\" y=\"243\">d</text>\n", | |
"</g>\n", | |
"<g id=\"edge6\" class=\"edge\"><title>c->d</title>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M44,182C51,191 61,203 69,214\"/>\n", | |
"<polygon style=\"fill:black;stroke:black;\" points=\"72,212 75,222 66,216 72,212\"/>\n", | |
"</g>\n", | |
"<g id=\"edge12\" class=\"edge\"><title>d->a</title>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M95,221C108,191 129,127 114,76 110,65 104,55 98,46\"/>\n", | |
"<polygon style=\"fill:black;stroke:black;\" points=\"95,48 92,38 101,44 95,48\"/>\n", | |
"</g>\n", | |
"<g id=\"edge10\" class=\"edge\"><title>d->b</title>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M86,220C84,195 82,151 80,122\"/>\n", | |
"<polygon style=\"fill:black;stroke:black;\" points=\"77,122 79,112 83,122 77,122\"/>\n", | |
"</g>\n", | |
"</g>\n", | |
"</svg>\n" | |
] | |
} | |
], | |
"prompt_number": 3 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Now install *pyrels* 0.1.1 (or higher) if you don't have it already: " | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"!pip install pyrels==0.1.1" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"Requirement already satisfied (use --upgrade to upgrade): pyrels==0.1.1 in /opt/lib/python2.7/site-packages\r\n", | |
"Cleaning up...\r\n" | |
] | |
} | |
], | |
"prompt_number": 4 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Now let's see if that worked as expected with a very simple example. Here we create some DOT code that we first display manually after passing it to the `%%dot` command:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"from pyrels.pyrels2dot import namespace2dot_str\n", | |
"print namespace2dot_str({\"myInt\": 42})" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"digraph G {\n", | |
" overlap=false;\n", | |
"\n", | |
" name4331282912 [label=\"myInt\", shape=\"ellipse\"];\n", | |
" int4298193560 [label=\"int: 42\", shape=\"box\"];\n", | |
"\n", | |
" name4331282912 -> int4298193560 [label=\"ref\"];\n", | |
"\n", | |
"}\n" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\n" | |
] | |
} | |
], | |
"prompt_number": 5 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"%%dot -f svg\n", | |
"digraph G {\n", | |
" overlap=false;\n", | |
"\n", | |
" name4368865680 [label=\"myInt\", shape=\"ellipse\"];\n", | |
" int4298193560 [label=\"int: 42\", shape=\"box\"];\n", | |
"\n", | |
" name4368865680 -> int4298193560 [label=\"ref\"];\n", | |
"\n", | |
"}" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"svg": [ | |
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", | |
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\"\n", | |
" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n", | |
"<!-- Generated by dot version 2.2.1 (Wed Jan 25 18:54:27 UTC 2012)\n", | |
" For user: (dinu) Dinu Gherman Title: G Pages: 1 -->\n", | |
"<svg width=\"72pt\" height=\"136pt\"\n", | |
" viewBox = \"-1 -1 71 135\"\n", | |
" xmlns=\"http://www.w3.org/2000/svg\">\n", | |
"<g id=\"graph0\" class=\"graph\" style=\"font-family:Times-Roman;font-size:14.00;\">\n", | |
"<title>G</title>\n", | |
"<g id=\"node1\" class=\"node\"><title>name4368865680</title>\n", | |
"<ellipse cx=\"35\" cy=\"22\" rx=\"30\" ry=\"18\" style=\"fill:none;stroke:black;\"/>\n", | |
"<text text-anchor=\"middle\" x=\"35\" y=\"27\">myInt</text>\n", | |
"</g>\n", | |
"<g id=\"node2\" class=\"node\"><title>int4298193560</title>\n", | |
"<polygon style=\"fill:none;stroke:black;\" points=\"62,92 8,92 8,128 62,128 62,92\"/>\n", | |
"<text text-anchor=\"middle\" x=\"35\" y=\"115\">int: 42</text>\n", | |
"</g>\n", | |
"<g id=\"edge2\" class=\"edge\"><title>name4368865680->int4298193560</title>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M35,40C35,52 35,68 35,82\"/>\n", | |
"<polygon style=\"fill:black;stroke:black;\" points=\"39,82 35,92 32,82 39,82\"/>\n", | |
"<text text-anchor=\"middle\" x=\"43\" y=\"71\">ref</text>\n", | |
"</g>\n", | |
"</g>\n", | |
"</svg>\n" | |
] | |
} | |
], | |
"prompt_number": 6 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"This is what we want to create directly with an extension using pyrels. The code to do that is on [Gist](https://gist.github.com/deeplook/4731035)." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"# %install_ext file:///Users/dinu/Desktop/joy-of-scipy/ipython_objgraph_magic.py\n", | |
"%install_ext https://gist.github.com/deeplook/4731035/raw/daa82e13f6635f513694bffb0bb9bc8a1b4ceff2/ipython_object_graphs.py\n", | |
"%load_ext ipython_objgraph_magic" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"Installed ipython_object_graphs.py. To use it, type:\n", | |
" %load_ext ipython_object_graphs\n" | |
] | |
} | |
], | |
"prompt_number": 7 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Now we can create some data structure and display it (as a *namespace*) with the new magic command `%%objgraph`:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class C(object):\n", | |
" pass\n", | |
"n = 23\n", | |
"L = [1, 23, (2, 3), None, C]\n" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 8 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"%%objgraph -f svg\n", | |
"{\"myInt\": n, \"myList\": L}" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"svg": [ | |
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", | |
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\"\n", | |
" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n", | |
"<!-- Generated by dot version 2.2.1 (Wed Jan 25 18:54:27 UTC 2012)\n", | |
" For user: (dinu) Dinu Gherman Title: G Pages: 1 -->\n", | |
"<svg width=\"460pt\" height=\"298pt\"\n", | |
" viewBox = \"-1 -1 459 297\"\n", | |
" xmlns=\"http://www.w3.org/2000/svg\">\n", | |
"<g id=\"graph0\" class=\"graph\" style=\"font-family:Times-Roman;font-size:14.00;\">\n", | |
"<title>G</title>\n", | |
"<g id=\"node1\" class=\"node\"><title>name4367705552</title>\n", | |
"<ellipse cx=\"179\" cy=\"22\" rx=\"33\" ry=\"18\" style=\"fill:none;stroke:black;\"/>\n", | |
"<text text-anchor=\"middle\" x=\"179\" y=\"27\">myList</text>\n", | |
"</g>\n", | |
"<g id=\"node2\" class=\"node\"><title>list4367703360</title>\n", | |
"<polygon style=\"fill:none;stroke:black;\" points=\"100,128 258,128 258,92 100,92 100,128\"/>\n", | |
"<text text-anchor=\"middle\" x=\"119\" y=\"115\">list:</text>\n", | |
"<polyline style=\"fill:none;stroke:black;\" points=\"138,128 138,92 \"/>\n", | |
"<text text-anchor=\"middle\" x=\"150\" y=\"115\">0</text>\n", | |
"<polyline style=\"fill:none;stroke:black;\" points=\"162,128 162,92 \"/>\n", | |
"<text text-anchor=\"middle\" x=\"174\" y=\"115\">1</text>\n", | |
"<polyline style=\"fill:none;stroke:black;\" points=\"186,128 186,92 \"/>\n", | |
"<text text-anchor=\"middle\" x=\"198\" y=\"115\">2</text>\n", | |
"<polyline style=\"fill:none;stroke:black;\" points=\"210,128 210,92 \"/>\n", | |
"<text text-anchor=\"middle\" x=\"222\" y=\"115\">3</text>\n", | |
"<polyline style=\"fill:none;stroke:black;\" points=\"234,128 234,92 \"/>\n", | |
"<text text-anchor=\"middle\" x=\"246\" y=\"115\">4</text>\n", | |
"</g>\n", | |
"<g id=\"edge16\" class=\"edge\"><title>name4367705552->list4367703360</title>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M179,40C179,52 179,68 179,82\"/>\n", | |
"<polygon style=\"fill:black;stroke:black;\" points=\"183,82 179,92 176,82 183,82\"/>\n", | |
"<text text-anchor=\"middle\" x=\"187\" y=\"71\">ref</text>\n", | |
"</g>\n", | |
"<g id=\"node3\" class=\"node\"><title>int4298192568</title>\n", | |
"<polygon style=\"fill:none;stroke:black;\" points=\"59,180 5,180 5,216 59,216 59,180\"/>\n", | |
"<text text-anchor=\"middle\" x=\"32\" y=\"203\">int: 1</text>\n", | |
"</g>\n", | |
"<g id=\"edge2\" class=\"edge\"><title>list4367703360->int4298192568</title>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M138,128C117,148 90,166 68,179\"/>\n", | |
"<polygon style=\"fill:black;stroke:black;\" points=\"69,182 59,184 66,176 69,182\"/>\n", | |
"</g>\n", | |
"<g id=\"node4\" class=\"node\"><title>int4298192040</title>\n", | |
"<polygon style=\"fill:none;stroke:black;\" points=\"131,180 77,180 77,216 131,216 131,180\"/>\n", | |
"<text text-anchor=\"middle\" x=\"104\" y=\"203\">int: 23</text>\n", | |
"</g>\n", | |
"<g id=\"edge4\" class=\"edge\"><title>list4367703360->int4298192040</title>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M162,128C151,143 138,159 127,172\"/>\n", | |
"<polygon style=\"fill:black;stroke:black;\" points=\"129,175 120,180 124,170 129,175\"/>\n", | |
"</g>\n", | |
"<g id=\"node5\" class=\"node\"><title>tuple4366071424</title>\n", | |
"<polyline style=\"fill:none;stroke:black;\" points=\"161,216 235,216 \"/>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M235,216C241,216 247,210 247,204\"/>\n", | |
"<polyline style=\"fill:none;stroke:black;\" points=\"247,204 247,192 \"/>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M247,192C247,186 241,180 235,180\"/>\n", | |
"<polyline style=\"fill:none;stroke:black;\" points=\"235,180 161,180 \"/>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M161,180C155,180 149,186 149,192\"/>\n", | |
"<polyline style=\"fill:none;stroke:black;\" points=\"149,192 149,204 \"/>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M149,204C149,210 155,216 161,216\"/>\n", | |
"<text text-anchor=\"middle\" x=\"174\" y=\"203\">tuple:</text>\n", | |
"<polyline style=\"fill:none;stroke:black;\" points=\"199,216 199,180 \"/>\n", | |
"<text text-anchor=\"middle\" x=\"211\" y=\"203\">0</text>\n", | |
"<polyline style=\"fill:none;stroke:black;\" points=\"223,216 223,180 \"/>\n", | |
"<text text-anchor=\"middle\" x=\"235\" y=\"203\">1</text>\n", | |
"</g>\n", | |
"<g id=\"edge6\" class=\"edge\"><title>list4367703360->tuple4366071424</title>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M198,128C198,140 198,156 198,170\"/>\n", | |
"<polygon style=\"fill:black;stroke:black;\" points=\"202,170 198,180 195,170 202,170\"/>\n", | |
"</g>\n", | |
"<g id=\"node8\" class=\"node\"><title>none</title>\n", | |
"<polygon style=\"fill:none;stroke:black;\" points=\"319,180 265,180 265,216 319,216 319,180\"/>\n", | |
"<text text-anchor=\"middle\" x=\"292\" y=\"203\">None</text>\n", | |
"</g>\n", | |
"<g id=\"edge8\" class=\"edge\"><title>list4367703360->none</title>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M234,128C246,143 259,159 269,172\"/>\n", | |
"<polygon style=\"fill:black;stroke:black;\" points=\"272,170 276,180 267,175 272,170\"/>\n", | |
"</g>\n", | |
"<g id=\"node9\" class=\"node\"><title>type4368459968</title>\n", | |
"<polygon style=\"fill:none;stroke:black;\" points=\"453,180 337,180 337,216 453,216 453,180\"/>\n", | |
"<text text-anchor=\"middle\" x=\"395\" y=\"203\">new style class: C</text>\n", | |
"</g>\n", | |
"<g id=\"edge10\" class=\"edge\"><title>list4367703360->type4368459968</title>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M258,128C281,148 310,164 336,176\"/>\n", | |
"<polygon style=\"fill:black;stroke:black;\" points=\"337,173 345,180 334,179 337,173\"/>\n", | |
"</g>\n", | |
"<g id=\"node6\" class=\"node\"><title>int4298192544</title>\n", | |
"<polygon style=\"fill:none;stroke:black;\" points=\"214,254 160,254 160,290 214,290 214,254\"/>\n", | |
"<text text-anchor=\"middle\" x=\"187\" y=\"277\">int: 2</text>\n", | |
"</g>\n", | |
"<g id=\"edge12\" class=\"edge\"><title>tuple4366071424->int4298192544</title>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M205,216C202,225 199,235 196,244\"/>\n", | |
"<polygon style=\"fill:black;stroke:black;\" points=\"199,245 193,254 193,243 199,245\"/>\n", | |
"</g>\n", | |
"<g id=\"node7\" class=\"node\"><title>int4298192520</title>\n", | |
"<polygon style=\"fill:none;stroke:black;\" points=\"286,254 232,254 232,290 286,290 286,254\"/>\n", | |
"<text text-anchor=\"middle\" x=\"259\" y=\"277\">int: 3</text>\n", | |
"</g>\n", | |
"<g id=\"edge14\" class=\"edge\"><title>tuple4366071424->int4298192520</title>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M241,216C244,225 247,235 250,244\"/>\n", | |
"<polygon style=\"fill:black;stroke:black;\" points=\"253,243 253,254 247,245 253,243\"/>\n", | |
"</g>\n", | |
"<g id=\"node10\" class=\"node\"><title>name4367706896</title>\n", | |
"<ellipse cx=\"38\" cy=\"110\" rx=\"30\" ry=\"18\" style=\"fill:none;stroke:black;\"/>\n", | |
"<text text-anchor=\"middle\" x=\"38\" y=\"115\">myInt</text>\n", | |
"</g>\n", | |
"<g id=\"edge18\" class=\"edge\"><title>name4367706896->int4298192040</title>\n", | |
"<path style=\"fill:none;stroke:black;\" d=\"M50,127C60,140 74,157 84,172\"/>\n", | |
"<polygon style=\"fill:black;stroke:black;\" points=\"87,170 90,180 81,174 87,170\"/>\n", | |
"<text text-anchor=\"middle\" x=\"84\" y=\"159\">ref</text>\n", | |
"</g>\n", | |
"</g>\n", | |
"</svg>\n" | |
] | |
} | |
], | |
"prompt_number": 9 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Neat! " | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [] | |
} | |
], | |
"metadata": {} | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment