##// END OF EJS Templates
A LOT OF CLEANUP IN examples/Notebook
Jonathan Frederic -
Show More
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
@@ -1,379 +1,295 b''
1 1 {
2 2 "cells": [
3 3 {
4 4 "cell_type": "markdown",
5 5 "metadata": {},
6 6 "source": [
7 "# Running the Notebook Server"
8 ]
9 },
10 {
11 "cell_type": "markdown",
12 "metadata": {},
13 "source": [
14 "The IPython notebook server is a custom web server that runs the notebook web application. Most of the time, users run the notebook server on their local computer using IPython's command line interface."
15 ]
16 },
17 {
18 "cell_type": "markdown",
19 "metadata": {},
20 "source": [
21 "## Starting the notebook server using the command line"
22 ]
23 },
24 {
25 "cell_type": "markdown",
26 "metadata": {},
27 "source": [
28 "You can start the notebook server from the command line (Terminal on Mac/Linux, CMD prompt on Windows) by running the following command: \n",
29 "\n",
30 " ipython notebook\n",
31 "\n",
32 "This will print some information about the notebook server in your terminal, including the URL of the web application (by default, `http://127.0.0.1:8888`). It will then open your default web browser to this URL.\n",
33 "\n",
34 "When the notebook opens, you will see the **notebook dashboard**, which will show a list of the notebooks and subdirectories in the directory where the notebook server was started. As of IPython 2.0, the dashboard allows you to navigate to different subdirectories. Because of this, it is no longer necessary to start a separate notebook server for each subdirectory. Most of the time, you will want to start a notebook server in the highest directory in your filesystem where notebooks can be found. Often this will be your home directory.\n",
35 "\n",
36 "You can start more than one notebook server at the same time. By default, the first notebook server starts on port 8888 and later notebook servers search for open ports near that one.\n",
37 "\n",
38 "You can also specify the port manually:\n",
39 "\n",
40 " ipython notebook --port 9999\n",
41 "\n",
42 "Or start notebook server without opening a web browser.\n",
43 "\n",
44 " ipython notebook --no-browser\n",
45 "\n",
46 "The notebook server has a number of other command line arguments that can be displayed with the `--help` flag: \n",
47 "\n",
48 " ipython notebook --help\n",
49 "\n",
50 "<div class=\"alert alert-failure\">\n",
51 "It used to be possible to specify kernel options, such as <code>--pylab inline</code> from the command line. This is deprecated in IPython 2.0 and will be removed in IPython 3.0. To enable matplotlib based plotting for the Python kernel use the <code>%matplotlib</code> magic command.\n",
52 "</div>\n",
53 "\n"
7 "# Configuring the Notebook and Server"
54 8 ]
55 9 },
56 10 {
57 11 "cell_type": "markdown",
58 12 "metadata": {},
59 13 "source": [
60 14 "## Configuring the IPython Notebook"
61 15 ]
62 16 },
63 17 {
64 18 "cell_type": "markdown",
65 19 "metadata": {},
66 20 "source": [
67 21 "The notebook web server can also be configured using IPython profiles and configuration files. The Notebook web server configuration options are set in a file named `ipython_notebook_config.py` in your IPython *profile directory*. The profile directory is a subfolder of your IPython directory, which itself is usually `.ipython` in your home directory.\n",
68 22 "\n",
69 23 "You can display the location of your default profile directory by running the command:"
70 24 ]
71 25 },
72 26 {
73 27 "cell_type": "code",
74 "execution_count": 7,
28 "execution_count": null,
75 29 "metadata": {
76 30 "collapsed": false
77 31 },
78 "outputs": [
79 {
80 "name": "stdout",
81 "output_type": "stream",
82 "text": [
83 "/Users/bgranger/.ipython/profile_default\r\n"
84 ]
85 }
86 ],
32 "outputs": [],
87 33 "source": [
88 34 "!ipython profile locate default"
89 35 ]
90 36 },
91 37 {
92 38 "cell_type": "markdown",
93 39 "metadata": {},
94 40 "source": [
95 41 "The default version of `ipython_notebook_config.py` lists all of the options available along with documentation for each. Changes made to that file will affect all notebook servers run under that profile. Command line options always override those set in configuration files.\n",
96 42 "\n",
97 43 "You can create a new profile:"
98 44 ]
99 45 },
100 46 {
101 47 "cell_type": "code",
102 "execution_count": 3,
48 "execution_count": null,
103 49 "metadata": {
104 50 "collapsed": false
105 51 },
106 "outputs": [
107 {
108 "name": "stdout",
109 "output_type": "stream",
110 "text": [
111 "[ProfileCreate] Generating default config file: u'/Users/bgranger/.ipython/profile_my_profile/ipython_config.py'\r\n",
112 "[ProfileCreate] Generating default config file: u'/Users/bgranger/.ipython/profile_my_profile/ipython_qtconsole_config.py'\r\n",
113 "[ProfileCreate] Generating default config file: u'/Users/bgranger/.ipython/profile_my_profile/ipython_notebook_config.py'\r\n",
114 "[ProfileCreate] Generating default config file: u'/Users/bgranger/.ipython/profile_my_profile/ipython_nbconvert_config.py'\r\n"
115 ]
116 }
117 ],
52 "outputs": [],
118 53 "source": [
119 54 "!ipython profile create my_profile"
120 55 ]
121 56 },
122 57 {
123 58 "cell_type": "markdown",
124 59 "metadata": {},
125 60 "source": [
126 61 "And then view its location:"
127 62 ]
128 63 },
129 64 {
130 65 "cell_type": "code",
131 "execution_count": 5,
66 "execution_count": null,
132 67 "metadata": {
133 68 "collapsed": false
134 69 },
135 "outputs": [
136 {
137 "name": "stdout",
138 "output_type": "stream",
139 "text": [
140 "/Users/bgranger/.ipython/profile_my_profile\r\n"
141 ]
142 }
143 ],
70 "outputs": [],
144 71 "source": [
145 72 "!ipython profile locate my_profile"
146 73 ]
147 74 },
148 75 {
149 76 "cell_type": "markdown",
150 77 "metadata": {},
151 78 "source": [
152 79 "To start the notebook server using a given profile, run the following:\n",
153 80 "\n",
154 81 " ipython notebook --profile=my_profile"
155 82 ]
156 83 },
157 84 {
158 85 "cell_type": "markdown",
159 86 "metadata": {},
160 87 "source": [
161 88 "More details about IPython configuration files and profiles can be found [here](http://ipython.org/ipython-doc/dev/config/intro.html)."
162 89 ]
163 90 },
164 91 {
165 92 "cell_type": "markdown",
166 93 "metadata": {},
167 94 "source": [
168 95 "## Securing the notebook server"
169 96 ]
170 97 },
171 98 {
172 99 "cell_type": "markdown",
173 100 "metadata": {},
174 101 "source": [
175 102 "The IPython Notebook allows arbitrary code execution on the computer running it. Thus, the notebook web server should never be run on the open internet without first securing it. By default, the notebook server only listens on local network interface (`127.0.0.1`) There are two steps required to secure the notebook server:\n",
176 103 "\n",
177 104 "1. Setting a password\n",
178 105 "2. Encrypt network traffic using SSL"
179 106 ]
180 107 },
181 108 {
182 109 "cell_type": "markdown",
183 110 "metadata": {},
184 111 "source": [
185 112 "### Setting a password"
186 113 ]
187 114 },
188 115 {
189 116 "cell_type": "markdown",
190 117 "metadata": {},
191 118 "source": [
192 119 "You can protect your notebook server with a simple single password by setting the `NotebookApp.password` configurable. You can prepare a hashed password using the function `IPython.lib.passwd`:"
193 120 ]
194 121 },
195 122 {
196 123 "cell_type": "code",
197 "execution_count": 1,
124 "execution_count": null,
198 125 "metadata": {
199 126 "collapsed": false
200 127 },
201 "outputs": [
202 {
203 "data": {
204 "text/plain": [
205 "'sha1:6c2164fc2b22:ed55ecf07fc0f985ab46561483c0e888e8964ae6'"
206 ]
207 },
208 "execution_count": 1,
209 "metadata": {},
210 "output_type": "execute_result"
211 }
212 ],
128 "outputs": [],
213 129 "source": [
214 130 "from IPython.lib import passwd\n",
215 131 "password = passwd(\"secret\")\n",
216 132 "password"
217 133 ]
218 134 },
219 135 {
220 136 "cell_type": "markdown",
221 137 "metadata": {},
222 138 "source": [
223 139 "You can then add this to your `ipython_notebook_config.py`:\n",
224 140 "\n",
225 141 "```python\n",
226 142 "# Password to use for web authentication\n",
227 143 "c = get_config()\n",
228 144 "c.NotebookApp.password = \n",
229 145 "u'sha1:6c2164fc2b22:ed55ecf07fc0f985ab46561483c0e888e8964ae6'\n",
230 146 "```"
231 147 ]
232 148 },
233 149 {
234 150 "cell_type": "markdown",
235 151 "metadata": {},
236 152 "source": [
237 153 "### Using SSL/HTTPS"
238 154 ]
239 155 },
240 156 {
241 157 "cell_type": "markdown",
242 158 "metadata": {},
243 159 "source": [
244 160 "When using a password, it is a good idea to also use SSL, so that your \n",
245 161 "password is not sent unencrypted by your browser to the web server. When running the notebook on the public internet this is absolutely required.\n",
246 162 "\n",
247 163 "The first step is to generate an SSL certificate. A self-signed certificate can be generated with ``openssl``. For example, the following command will create a certificate valid for 365 days with both the key and certificate data written to the same file:\n",
248 164 "\n",
249 165 " openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mycert.pem -out mycert.pem\n",
250 166 "\n",
251 167 "In most cases, you should run this command in your profile directory, which will make it easy to use the generated key and certificate.\n",
252 168 "\n",
253 169 "When you connect to a notebook server over HTTPS using a self-signed certificate, your browser will warn you of a dangerous certificate because it is self-signed. If you want to have a fully compliant certificate that will not raise warnings, it is possible (but rather involved) to obtain one,\n",
254 170 "as explained in detail in [this tutorial](http://arstechnica.com/security/news/2009/12/how-to-get-set-with-a-secure-sertificate-for-free.ars)\n",
255 171 "\t\n",
256 172 "When you enable SSL support, you will need to access the notebook server over ``https://``, rather than plain ``http://``. The startup message from the notebook server prints the correct URL, but it is easy to overlook and think the server is for some reason non-responsive.\n",
257 173 "\n",
258 174 "Once you have generated the key and certificate, you can configure the notebook server to use them, by adding the following to `ipython_notebook_config.py`:\n",
259 175 "\n",
260 176 "```python\n",
261 177 "# The full path to an SSL/TLS certificate file.\n",
262 178 "c.NotebookApp.certfile = u'/Users/bgranger/.ipython/profile_my_profile/mycert.crt'\n",
263 179 "\n",
264 180 "# The full path to a private key file for usage with SSL/TLS.\n",
265 181 "c.NotebookApp.keyfile = u'/Users/bgranger/.ipython/profile_my_profile/mycert.key'\n",
266 182 "```"
267 183 ]
268 184 },
269 185 {
270 186 "cell_type": "markdown",
271 187 "metadata": {},
272 188 "source": [
273 189 "## Running a public notebook server"
274 190 ]
275 191 },
276 192 {
277 193 "cell_type": "markdown",
278 194 "metadata": {},
279 195 "source": [
280 196 "<div class=\"alert alert-error\">\n",
281 197 "Don't run a public notebook server unless you first secure it with a password and SSL/HTTPS as described above\n",
282 198 "</div>\n",
283 199 "\n",
284 200 "By default the notebook server only listens on the `localhost/127.0.0.1` network interface. If you want to connect to the notebook from another computers, or over the internet, you need to configure the notebook server to listen on all network interfaces and not open the browser. You will often also want to disable the automatic launching of the web browser.\n",
285 201 "\n",
286 202 "This can be accomplished by passing a command line options.\n",
287 203 "\n",
288 204 " ipython notebook --ip=* --no-browser\n",
289 205 "\n",
290 206 "You can also add the following to your`ipython_notebook_config.py` file:\n",
291 207 "\n",
292 208 "```python\n",
293 209 "c.NotebookApp.ip = '*'\n",
294 210 "c.NotebookApp.open_browser = False\n",
295 211 "```"
296 212 ]
297 213 },
298 214 {
299 215 "cell_type": "markdown",
300 216 "metadata": {},
301 217 "source": [
302 218 "## Running with a different URL prefix"
303 219 ]
304 220 },
305 221 {
306 222 "cell_type": "markdown",
307 223 "metadata": {},
308 224 "source": [
309 225 "The notebook dashboard typically lives at the URL `http://localhost:8888/tree`. If you prefer that it lives, together with the \n",
310 226 "rest of the notebook web application, under a base URL prefix, such as `http://localhost:8888/ipython/tree`, you can do so by adding the following lines to your `ipython_notebook_config.py` file.\n",
311 227 "\n",
312 228 "```python\n",
313 229 "c.NotebookApp.base_url = '/ipython/'\n",
314 230 "c.NotebookApp.webapp_settings = {'static_url_prefix':'/ipython/static/'}\n",
315 231 "```"
316 232 ]
317 233 },
318 234 {
319 235 "cell_type": "markdown",
320 236 "metadata": {},
321 237 "source": [
322 238 "## Using a different notebook store"
323 239 ]
324 240 },
325 241 {
326 242 "cell_type": "markdown",
327 243 "metadata": {},
328 244 "source": [
329 245 "By default, the notebook server stores the notebook documents that it saves as files in the working directory of the notebook server, also known as the\n",
330 246 "`notebook_dir`. This logic is implemented in the `FileNotebookManager` class. However, the server can be configured to use a different notebook manager class, which can store the notebooks in a different format. \n",
331 247 "\n",
332 248 "The [bookstore](https://github.com/rgbkrk/bookstore) package currently allows users to store notebooks on Rackspace CloudFiles or OpenStack Swift based object stores.\n",
333 249 "\n",
334 250 "Writing a notebook manager is as simple as extending the base class `NotebookManager`. The [simple_notebook_manager](https://github.com/khinsen/simple_notebook_manager) provides a great example\n",
335 251 "of an in memory notebook manager, created solely for the purpose of\n",
336 252 "illustrating the notebook manager API."
337 253 ]
338 254 },
339 255 {
340 256 "cell_type": "markdown",
341 257 "metadata": {},
342 258 "source": [
343 259 "## Known issues"
344 260 ]
345 261 },
346 262 {
347 263 "cell_type": "markdown",
348 264 "metadata": {},
349 265 "source": [
350 266 "When behind a proxy, especially if your system or browser is set to autodetect the proxy, the notebook web application might fail to connect to the server's websockets, and present you with a warning at startup. In this case, you need to configure your system not to use the proxy for the server's address.\n",
351 267 "\n",
352 268 "For example, in Firefox, go to the Preferences panel, Advanced section,\n",
353 269 "Network tab, click 'Settings...', and add the address of the notebook server\n",
354 270 "to the 'No proxy for' field."
355 271 ]
356 272 }
357 273 ],
358 274 "metadata": {
359 275 "kernelspec": {
360 276 "display_name": "Python 3",
361 277 "language": "python",
362 278 "name": "python3"
363 279 },
364 280 "language_info": {
365 281 "codemirror_mode": {
366 282 "name": "ipython",
367 283 "version": 3
368 284 },
369 285 "file_extension": ".py",
370 286 "mimetype": "text/x-python",
371 287 "name": "python",
372 288 "nbconvert_exporter": "python",
373 289 "pygments_lexer": "ipython3",
374 "version": "3.4.2"
290 "version": "3.4.3"
375 291 }
376 292 },
377 293 "nbformat": 4,
378 294 "nbformat_minor": 0
379 295 }
@@ -1,155 +1,132 b''
1 1 {
2 2 "cells": [
3 3 {
4 4 "cell_type": "markdown",
5 5 "metadata": {},
6 6 "source": [
7 7 "# Connecting to an existing IPython kernel using the Qt Console"
8 8 ]
9 9 },
10 10 {
11 11 "cell_type": "markdown",
12 12 "metadata": {},
13 13 "source": [
14 14 "## The Frontend/Kernel Model"
15 15 ]
16 16 },
17 17 {
18 18 "cell_type": "markdown",
19 19 "metadata": {},
20 20 "source": [
21 21 "The traditional IPython (`ipython`) consists of a single process that combines a terminal based UI with the process that runs the users code.\n",
22 22 "\n",
23 23 "While this traditional application still exists, the modern IPython consists of two processes:\n",
24 24 "\n",
25 25 "* Kernel: this is the process that runs the users code.\n",
26 26 "* Frontend: this is the process that provides the user interface where the user types code and sees results.\n",
27 27 "\n",
28 28 "IPython currently has 3 frontends:\n",
29 29 "\n",
30 30 "* Terminal Console (`ipython console`)\n",
31 31 "* Qt Console (`ipython qtconsole`)\n",
32 32 "* Notebook (`ipython notebook`)\n",
33 33 "\n",
34 34 "The Kernel and Frontend communicate over a ZeroMQ/JSON based messaging protocol, which allows multiple Frontends (even of different types) to communicate with a single Kernel. This opens the door for all sorts of interesting things, such as connecting a Console or Qt Console to a Notebook's Kernel. For example, you may want to connect a Qt console to your Notebook's Kernel and use it as a help\n",
35 35 "browser, calling `??` on objects in the Qt console (whose pager is more flexible than the\n",
36 36 "one in the notebook). \n",
37 37 "\n",
38 38 "This Notebook describes how you would connect another Frontend to a Kernel that is associated with a Notebook."
39 39 ]
40 40 },
41 41 {
42 42 "cell_type": "markdown",
43 43 "metadata": {},
44 44 "source": [
45 45 "## Manual connection"
46 46 ]
47 47 },
48 48 {
49 49 "cell_type": "markdown",
50 50 "metadata": {},
51 51 "source": [
52 52 "To connect another Frontend to a Kernel manually, you first need to find out the connection information for the Kernel using the `%connect_info` magic:"
53 53 ]
54 54 },
55 55 {
56 56 "cell_type": "code",
57 "execution_count": 6,
57 "execution_count": null,
58 58 "metadata": {
59 59 "collapsed": false
60 60 },
61 "outputs": [
62 {
63 "name": "stdout",
64 "output_type": "stream",
65 "text": [
66 "{\n",
67 " \"stdin_port\": 52858, \n",
68 " \"ip\": \"127.0.0.1\", \n",
69 " \"hb_port\": 52859, \n",
70 " \"key\": \"7efd45ca-d8a2-41b0-9cea-d9116d0fb883\", \n",
71 " \"shell_port\": 52856, \n",
72 " \"iopub_port\": 52857\n",
73 "}\n",
74 "\n",
75 "Paste the above JSON into a file, and connect with:\n",
76 " $> ipython <app> --existing <file>\n",
77 "or, if you are local, you can connect with just:\n",
78 " $> ipython <app> --existing kernel-b3bac7c1-8b2c-4536-8082-8d1df24f99ac.json \n",
79 "or even just:\n",
80 " $> ipython <app> --existing \n",
81 "if this is the most recent IPython session you have started.\n"
82 ]
83 }
84 ],
61 "outputs": [],
85 62 "source": [
86 63 "%connect_info"
87 64 ]
88 65 },
89 66 {
90 67 "cell_type": "markdown",
91 68 "metadata": {},
92 69 "source": [
93 70 "You can see that this magic displays everything you need to connect to this Notebook's Kernel."
94 71 ]
95 72 },
96 73 {
97 74 "cell_type": "markdown",
98 75 "metadata": {},
99 76 "source": [
100 77 "## Automatic connection using a new Qt Console"
101 78 ]
102 79 },
103 80 {
104 81 "cell_type": "markdown",
105 82 "metadata": {},
106 83 "source": [
107 84 "You can also start a new Qt Console connected to your current Kernel by using the `%qtconsole` magic. This will detect the necessary connection\n",
108 85 "information and start the Qt Console for you automatically."
109 86 ]
110 87 },
111 88 {
112 89 "cell_type": "code",
113 "execution_count": 1,
90 "execution_count": null,
114 91 "metadata": {
115 92 "collapsed": false
116 93 },
117 94 "outputs": [],
118 95 "source": [
119 96 "a = 10"
120 97 ]
121 98 },
122 99 {
123 100 "cell_type": "code",
124 "execution_count": 2,
101 "execution_count": null,
125 102 "metadata": {
126 103 "collapsed": false
127 104 },
128 105 "outputs": [],
129 106 "source": [
130 107 "%qtconsole"
131 108 ]
132 109 }
133 110 ],
134 111 "metadata": {
135 112 "kernelspec": {
136 113 "display_name": "Python 3",
137 114 "language": "python",
138 115 "name": "python3"
139 116 },
140 117 "language_info": {
141 118 "codemirror_mode": {
142 119 "name": "ipython",
143 120 "version": 3
144 121 },
145 122 "file_extension": ".py",
146 123 "mimetype": "text/x-python",
147 124 "name": "python",
148 125 "nbconvert_exporter": "python",
149 126 "pygments_lexer": "ipython3",
150 "version": "3.4.2"
127 "version": "3.4.3"
151 128 }
152 129 },
153 130 "nbformat": 4,
154 131 "nbformat_minor": 0
155 132 }
@@ -1,503 +1,317 b''
1 1 {
2 2 "cells": [
3 3 {
4 4 "cell_type": "markdown",
5 5 "metadata": {},
6 6 "source": [
7 7 "# NbConvert"
8 8 ]
9 9 },
10 10 {
11 11 "cell_type": "markdown",
12 12 "metadata": {},
13 13 "source": [
14 14 "## Command line usage"
15 15 ]
16 16 },
17 17 {
18 18 "cell_type": "markdown",
19 19 "metadata": {},
20 20 "source": [
21 "`NbConvert` is the library, and the command line tool that allow to convert from notebook to other formats.\n",
22 "It is a technological preview in 1.0 but is already usable and highly configurable.\n",
23 "It ships already with many default available formats : `html`, `latex`, `markdown`, `python`, `rst` and `slides`\n",
24 "which are fully base on Jinja templating engine, so writing a converter for your custom format or tweeking the existing \n",
25 "one should be extra simple."
21 "`NbConvert` is both a library and command line tool that allows you to convert notebooks to other formats. It ships with many common formats: `html`, `latex`, `markdown`, `python`, `rst`, and `slides`\n",
22 "NbConvert relys on the Jinja templating engine, so implementing a new format or tweeking an existing one is easy."
26 23 ]
27 24 },
28 25 {
29 26 "cell_type": "markdown",
30 27 "metadata": {},
31 28 "source": [
32 "You can invoke nbconvert by doing\n",
29 "You can invoke nbconvert by running\n",
33 30 "\n",
34 31 "```bash\n",
35 32 "$ ipython nbconvert <options and arguments>\n",
36 33 "```\n",
37 34 "\n",
38 "Call `ipython nbconvert` with the `--help` flag or no aruments to get basic help on how to use it.\n",
39 "For more information about configuration use the `--help-all` flag"
35 "Call `ipython nbconvert` with the `--help` flag or without any aruments to display the basic help. For detailed configuration help, use the `--help-all` flag."
40 36 ]
41 37 },
42 38 {
43 39 "cell_type": "markdown",
44 40 "metadata": {},
45 41 "source": [
46 42 "### Basic export"
47 43 ]
48 44 },
49 45 {
50 46 "cell_type": "markdown",
51 47 "metadata": {},
52 48 "source": [
53 "We will be converting `Custom Display Logic.ipynb`. \n",
54 "Be sure to have runed some of the cells in it to have output otherwise you will only see input in nbconvert.\n",
55 "Nbconvert **do not execute the code** in the notebook files, it only converts what is inside."
49 "As a test, the `Index.ipynb` notebook in the directory will be convert. \n",
50 "\n",
51 "If you're converting a notebook with code in it, make sure to run the code cells that you're interested in before attempting to convert the notebook. Nbconvert **does not execute the code cell** of the notebooks that it converts."
56 52 ]
57 53 },
58 54 {
59 55 "cell_type": "code",
60 "execution_count": 1,
56 "execution_count": null,
61 57 "metadata": {
62 58 "collapsed": false
63 59 },
64 "outputs": [
65 {
66 "name": "stderr",
67 "output_type": "stream",
68 "text": [
69 "[NbConvertApp] Using existing profile dir: u'/Users/bussonniermatthias/.ipython/profile_default'\n",
70 "[NbConvertApp] Converting notebook 04 - Custom Display Logic.ipynb to html\n",
71 "[NbConvertApp] Support files will be in 04 - Custom Display Logic_files/\n",
72 "[NbConvertApp] Loaded template html_full.tpl\n",
73 "[NbConvertApp] Writing 221081 bytes to 04 - Custom Display Logic.html\n"
74 ]
75 }
76 ],
60 "outputs": [],
77 61 "source": [
78 62 "%%bash\n",
79 "ipython nbconvert '04 - Custom Display Logic.ipynb'"
63 "ipython nbconvert 'Index.ipynb'"
80 64 ]
81 65 },
82 66 {
83 67 "cell_type": "markdown",
84 68 "metadata": {},
85 69 "source": [
86 "Html is the default value (that can be configured) , so the verbose form would be "
70 "Html is the (configurable) default value. The verbose form of the same command as above is "
87 71 ]
88 72 },
89 73 {
90 74 "cell_type": "code",
91 "execution_count": 2,
75 "execution_count": null,
92 76 "metadata": {
93 77 "collapsed": false
94 78 },
95 "outputs": [
96 {
97 "name": "stderr",
98 "output_type": "stream",
99 "text": [
100 "[NbConvertApp] Using existing profile dir: u'/Users/bussonniermatthias/.ipython/profile_default'\n",
101 "[NbConvertApp] Converting notebook 04 - Custom Display Logic.ipynb to html\n",
102 "[NbConvertApp] Support files will be in 04 - Custom Display Logic_files/\n",
103 "[NbConvertApp] Loaded template html_full.tpl\n",
104 "[NbConvertApp] Writing 221081 bytes to 04 - Custom Display Logic.html\n"
105 ]
106 }
107 ],
79 "outputs": [],
108 80 "source": [
109 81 "%%bash\n",
110 "ipython nbconvert --to=html '04 - Custom Display Logic.ipynb'"
82 "ipython nbconvert --to=html 'Index.ipynb'"
111 83 ]
112 84 },
113 85 {
114 86 "cell_type": "markdown",
115 87 "metadata": {},
116 88 "source": [
117 "You can also convert to latex, which will take care of extractin the embeded base64 encoded png, or the svg and call inkscape to convert those svg to pdf if necessary :"
89 "You can also convert to latex, which will extract the embeded images. If the embeded images are SVGs, inkscape is used to convert them to pdf:"
118 90 ]
119 91 },
120 92 {
121 93 "cell_type": "code",
122 "execution_count": 3,
94 "execution_count": null,
123 95 "metadata": {
124 96 "collapsed": false
125 97 },
126 "outputs": [
127 {
128 "name": "stderr",
129 "output_type": "stream",
130 "text": [
131 "[NbConvertApp] Using existing profile dir: u'/Users/bussonniermatthias/.ipython/profile_default'\n",
132 "[NbConvertApp] Converting notebook 04 - Custom Display Logic.ipynb to latex\n",
133 "[NbConvertApp] Support files will be in 04 - Custom Display Logic_files/\n",
134 "Setting Language: .UTF-8\n",
135 "\n",
136 "(process:26432): Gtk-WARNING **: Locale not supported by C library.\n",
137 "\tUsing the fallback 'C' locale.\n",
138 "Setting Language: .UTF-8\n",
139 "\n",
140 "(process:26472): Gtk-WARNING **: Locale not supported by C library.\n",
141 "\tUsing the fallback 'C' locale.\n",
142 "Setting Language: .UTF-8\n",
143 "\n",
144 "(process:26512): Gtk-WARNING **: Locale not supported by C library.\n",
145 "\tUsing the fallback 'C' locale.\n",
146 "Setting Language: .UTF-8\n",
147 "\n",
148 "(process:26552): Gtk-WARNING **: Locale not supported by C library.\n",
149 "\tUsing the fallback 'C' locale.\n",
150 "Setting Language: .UTF-8\n",
151 "\n",
152 "(process:26592): Gtk-WARNING **: Locale not supported by C library.\n",
153 "\tUsing the fallback 'C' locale.\n",
154 "[NbConvertApp] Loaded template latex_article.tplx\n",
155 "[NbConvertApp] Writing 41196 bytes to 04 - Custom Display Logic.tex\n"
156 ]
157 }
158 ],
98 "outputs": [],
159 99 "source": [
160 100 "%%bash\n",
161 "ipython nbconvert --to=latex '04 - Custom Display Logic.ipynb'"
101 "ipython nbconvert --to=latex 'Index.ipynb'"
162 102 ]
163 103 },
164 104 {
165 105 "cell_type": "markdown",
166 106 "metadata": {},
167 107 "source": [
168 "You should just have to compile the generated `.tex` file. If you get the required packages installed, if should compile out of the box.\n",
108 "Note that the latex conversion creates latex, not a PDF. To create a PDF you need the required third party packages to compile the latex.\n",
169 109 "\n",
170 "For convenience we allow to run extra action after the conversion has been done, in particular for `latex` we have a `pdf` post-processor. \n",
171 "You can define the postprocessor tu run with the `--post` flag."
110 "A `--post` flag is provided for convinience which allows you to have nbconvert automatically compile a PDF for you from your output."
172 111 ]
173 112 },
174 113 {
175 114 "cell_type": "code",
176 "execution_count": 4,
115 "execution_count": null,
177 116 "metadata": {
178 117 "collapsed": false
179 118 },
180 "outputs": [
181 {
182 "name": "stderr",
183 "output_type": "stream",
184 "text": [
185 "[NbConvertApp] Using existing profile dir: u'/Users/bussonniermatthias/.ipython/profile_default'\n",
186 "[NbConvertApp] Converting notebook 04 - Custom Display Logic.ipynb to latex\n",
187 "[NbConvertApp] Support files will be in 04 - Custom Display Logic_files/\n",
188 "Setting Language: .UTF-8\n",
189 "\n",
190 "(process:26658): Gtk-WARNING **: Locale not supported by C library.\n",
191 "\tUsing the fallback 'C' locale.\n",
192 "Setting Language: .UTF-8\n",
193 "\n",
194 "(process:26698): Gtk-WARNING **: Locale not supported by C library.\n",
195 "\tUsing the fallback 'C' locale.\n",
196 "Setting Language: .UTF-8\n",
197 "\n",
198 "(process:26738): Gtk-WARNING **: Locale not supported by C library.\n",
199 "\tUsing the fallback 'C' locale.\n",
200 "Setting Language: .UTF-8\n",
201 "\n",
202 "(process:26778): Gtk-WARNING **: Locale not supported by C library.\n",
203 "\tUsing the fallback 'C' locale.\n",
204 "Setting Language: .UTF-8\n",
205 "\n",
206 "(process:26818): Gtk-WARNING **: Locale not supported by C library.\n",
207 "\tUsing the fallback 'C' locale.\n",
208 "[NbConvertApp] Loaded template latex_article.tplx\n",
209 "[NbConvertApp] Writing 41196 bytes to 04 - Custom Display Logic.tex\n",
210 "[NbConvertApp] Building PDF: ['pdflatex', '04 - Custom Display Logic.tex']\n"
211 ]
212 }
213 ],
119 "outputs": [],
214 120 "source": [
215 121 "%%bash\n",
216 "ipython nbconvert --to=latex '04 - Custom Display Logic.ipynb' --post=pdf"
122 "ipython nbconvert --to=latex 'Index.ipynb' --post=pdf"
217 123 ]
218 124 },
219 125 {
220 126 "cell_type": "markdown",
221 127 "metadata": {},
222 128 "source": [
223 "Have a look at `04 - Custom Display Logic.pdf`, toward the end, where we compared `display()` vs `display_html()` and returning the object.\n",
224 "See how the cell where we use `display_html` was not able to display the circle, whereas the two other ones were able to select one of the oher representation they know how to display."
129 "## Custom templates"
225 130 ]
226 131 },
227 132 {
228 133 "cell_type": "markdown",
229 134 "metadata": {},
230 135 "source": [
231 "### Customizing template"
232 ]
233 },
234 {
235 "cell_type": "markdown",
236 "metadata": {},
237 "source": [
238 "let's look at the first 20 lines of the `python` exporter"
136 "Look at the first 20 lines of the `python` exporter"
239 137 ]
240 138 },
241 139 {
242 140 "cell_type": "code",
243 "execution_count": 5,
141 "execution_count": null,
244 142 "metadata": {
245 143 "collapsed": false
246 144 },
247 "outputs": [
248 {
249 "name": "stdout",
250 "output_type": "stream",
251 "text": [
252 "# 1. Implementing special display methods such as `_repr_html_`.\n",
253 "# 2. Registering a display function for a particular type.\n",
254 "# \n",
255 "# In this Notebook we show how both approaches work.\n",
256 "\n",
257 "# Before we get started, we will import the various display functions for displaying the different formats we will create.\n",
258 "\n",
259 "# In[54]:\n",
260 "\n",
261 "from IPython.display import display\n",
262 "from IPython.display import (\n",
263 " display_html, display_jpeg, display_png,\n",
264 " display_javascript, display_svg, display_latex\n",
265 ")\n",
266 "\n",
267 "\n",
268 "### Implementing special display methods\n",
269 "\n",
270 "# The main idea of the first approach is that you have to implement special display methods, one for each representation you want to use. Here is a list of the names of the special methods and the values they must return:\n",
271 "# \n"
272 ]
273 }
274 ],
145 "outputs": [],
275 146 "source": [
276 "pyfile = !ipython nbconvert --to python '04 - Custom Display Logic.ipynb' --stdout\n",
147 "pyfile = !ipython nbconvert --to python 'Index.ipynb' --stdout\n",
277 148 "for l in pyfile[20:40]:\n",
278 149 " print l"
279 150 ]
280 151 },
281 152 {
282 153 "cell_type": "markdown",
283 154 "metadata": {},
284 155 "source": [
285 "We see that the non-code cell are exported to the file. To have a cleaner script, we will export only the code contained in the code cells.\n",
286 "\n",
287 "To do so, we will inherit the python template, and overwrite the markdown blocks to be empty."
156 "From the code, you can see that non-code cells are also exported. If you want to change this behavior, you can use a custom template. The custom template inherits from the Python template and overwrites the markdown blocks so that they are empty."
288 157 ]
289 158 },
290 159 {
291 160 "cell_type": "code",
292 "execution_count": 6,
161 "execution_count": null,
293 162 "metadata": {
294 163 "collapsed": false
295 164 },
296 "outputs": [
297 {
298 "name": "stdout",
299 "output_type": "stream",
300 "text": [
301 "Overwriting simplepython.tpl\n"
302 ]
303 }
304 ],
165 "outputs": [],
305 166 "source": [
306 167 "%%writefile simplepython.tpl\n",
307 168 "{% extends 'python.tpl'%}\n",
308 169 "\n",
309 170 "{% block markdowncell -%}\n",
310 171 "{% endblock markdowncell %}\n",
311 172 "\n",
312 173 "## we also want to get rig of header cell\n",
313 174 "{% block headingcell -%}\n",
314 175 "{% endblock headingcell %}\n",
315 176 "\n",
316 177 "## and let's change the appearance of input prompt\n",
317 178 "{% block in_prompt %}\n",
318 179 "# This was input cell with prompt number : {{ cell.prompt_number if cell.prompt_number else ' ' }}\n",
319 180 "{%- endblock in_prompt %}"
320 181 ]
321 182 },
322 183 {
323 184 "cell_type": "code",
324 "execution_count": 7,
185 "execution_count": null,
325 186 "metadata": {
326 187 "collapsed": false
327 188 },
328 "outputs": [
329 {
330 "name": "stdout",
331 "output_type": "stream",
332 "text": [
333 "\n",
334 "# This was input cell with prompt number : 54\n",
335 "from IPython.display import display\n",
336 "from IPython.display import (\n",
337 " display_html, display_jpeg, display_png,\n",
338 " display_javascript, display_svg, display_latex\n",
339 ")\n",
340 "\n",
341 "\n",
342 "# This was input cell with prompt number : 55\n",
343 "get_ipython().magic(u'load soln/mycircle.py')\n",
344 "\n",
345 "\n",
346 "# This was input cell with prompt number : 56\n",
347 "class MyCircle(object):\n",
348 " \n",
349 " def _repr_html_(self):\n",
350 " return \"&#x25CB; (<b>html</b>)\"\n",
351 "\n",
352 " def _repr_svg_(self):\n",
353 " return \"\"\"<svg width='100px' height='100px'>\n",
354 " <circle cx=\"50\" cy=\"50\" r=\"20\" stroke=\"black\" stroke-width=\"1\" fill=\"blue\"/>\n",
355 " </svg>\"\"\"\n",
356 " \n",
357 " def _repr_latex_(self):\n",
358 " return r\"$\\bigcirc \\LaTeX$\"\n",
359 "\n",
360 " def _repr_javascript_(self):\n",
361 " return \"alert('I am a circle!');\"\n",
362 "\n",
363 "\n",
364 "# This was input cell with prompt number : 57\n",
365 "c = MyCircle()\n",
366 "\n",
367 "\n",
368 "# This was input cell with prompt number : 58\n",
369 "...\n"
370 ]
371 }
372 ],
189 "outputs": [],
373 190 "source": [
374 "pyfile = !ipython nbconvert --to python '04 - Custom Display Logic.ipynb' --stdout --template=simplepython.tpl\n",
191 "pyfile = !ipython nbconvert --to python 'Index.ipynb' --stdout --template=simplepython.tpl\n",
375 192 "\n",
376 193 "for l in pyfile[4:40]:\n",
377 194 " print l\n",
378 195 "print '...'"
379 196 ]
380 197 },
381 198 {
382 199 "cell_type": "markdown",
383 200 "metadata": {},
384 201 "source": [
385 "I'll let you read Jinja manual for the exact syntax of the template."
202 "For details about the template syntax, refer to [Jinja's manual](http://jinja.pocoo.org/docs/dev/)."
386 203 ]
387 204 },
388 205 {
389 206 "cell_type": "markdown",
390 207 "metadata": {},
391 208 "source": [
392 209 "## Template that use cells metadata"
393 210 ]
394 211 },
395 212 {
396 213 "cell_type": "markdown",
397 214 "metadata": {},
398 215 "source": [
399 "Notebook fileformat support attaching arbitrary JSON metadata to each cell of a notebook. In this part we will use those metadata."
216 "The notebook file format supports attaching arbitrary JSON metadata to each cell. Here, as an exercise, you will use the metadata to tags cells."
400 217 ]
401 218 },
402 219 {
403 220 "cell_type": "markdown",
404 221 "metadata": {},
405 222 "source": [
406 "First you need to choose another notebook you want to convert to html, and tag some of the cell with metadata.\n",
407 "You can see the file `soln/celldiff.js` for a solution on how to tag, or follow the javascript tutorial to see how to do that. Use what we have written there to tag cells of some notebooks to `Easy`|`Medium`|`Hard`|`<None>`, and convert this notebook using your template."
223 "First you need to choose another notebook you want to convert to html, and tag some of the cell with metadata. You can refere to the file `soln/celldiff.js` as an example or follow the Javascript tutorial to figure out how do change cell metadata. Assuming you have a notebook with some of the cells tagged as `Easy`|`Medium`|`Hard`|`<None>`, the notebook can be converted specially using a custom template. Design your remplate in the cells provided below.\n",
224 "\n",
225 "The following, unorganized lines of code, may be of help:"
408 226 ]
409 227 },
410 228 {
411 229 "cell_type": "markdown",
412 230 "metadata": {},
413 231 "source": [
414 "you might need the following : \n",
415 232 "```\n",
416 233 "{% extends 'html_full.tpl'%}\n",
417 234 "{% block any_cell %}\n",
418 235 "{{ super() }}\n",
419 236 "<div style=\"background-color:red\">\n",
420 237 "<div style='background-color:orange'>\n",
421 238 "```\n",
422 239 "\n",
423 "`metadata` might not exist, be sure to :\n",
240 "If your key name under `cell.metadata.example.difficulty`, the following code would get the value of it:\n",
424 241 "\n",
425 242 "`cell['metadata'].get('example',{}).get('difficulty','')`\n",
426 243 "\n",
427 "tip: use `%%writefile` to edit the template in the notebook :-)"
244 "Tip: Use `%%writefile` to edit the template in the notebook."
428 245 ]
429 246 },
430 247 {
431 248 "cell_type": "code",
432 "execution_count": 8,
249 "execution_count": null,
433 250 "metadata": {
434 251 "collapsed": false
435 252 },
436 253 "outputs": [],
437 254 "source": [
438 255 "%%bash\n",
439 256 "# ipython nbconvert --to html <your chosen notebook.ipynb> --template=<your template file>"
440 257 ]
441 258 },
442 259 {
443 260 "cell_type": "code",
444 261 "execution_count": null,
445 262 "metadata": {
446 263 "collapsed": false
447 264 },
448 265 "outputs": [],
449 266 "source": [
450 267 "%loadpy soln/coloreddiff.tpl"
451 268 ]
452 269 },
453 270 {
454 271 "cell_type": "code",
455 272 "execution_count": null,
456 273 "metadata": {
457 274 "collapsed": false
458 275 },
459 276 "outputs": [],
460 277 "source": [
461 278 "# ipython nbconvert --to html '04 - Custom Display Logic.ipynb' --template=soln/coloreddiff.tpl"
462 279 ]
463 280 },
464 281 {
465 282 "cell_type": "markdown",
466 283 "metadata": {},
467 284 "source": [
468 285 "### Get rid of all command line flags."
469 286 ]
470 287 },
471 288 {
472 289 "cell_type": "markdown",
473 290 "metadata": {},
474 291 "source": [
475 "As of all of IPython nbconvert can be configured using profiles and passing the `--profile` flag. \n",
476 "Moreover if a `config.py` file exist in current working directory nbconvert will use that, or read the config file you give to it with the `--config=<file>` flag. \n",
477 "\n",
478 "In the end, if you are often running nbconvert on the sam project, `$ ipython nbconvert` should be enough to get you up and ready."
292 "IPython nbconvert can be configured using the default profile and by selecting a non-default a profile via `--profile` flag. Additionally, if a `config.py` file exist in current working directory, nbconvert will use that as config."
479 293 ]
480 294 }
481 295 ],
482 296 "metadata": {
483 297 "kernelspec": {
484 298 "display_name": "Python 3",
485 299 "language": "python",
486 300 "name": "python3"
487 301 },
488 302 "language_info": {
489 303 "codemirror_mode": {
490 304 "name": "ipython",
491 305 "version": 3
492 306 },
493 307 "file_extension": ".py",
494 308 "mimetype": "text/x-python",
495 309 "name": "python",
496 310 "nbconvert_exporter": "python",
497 311 "pygments_lexer": "ipython3",
498 "version": "3.4.2"
312 "version": "3.4.3"
499 313 }
500 314 },
501 315 "nbformat": 4,
502 316 "nbformat_minor": 0
503 317 }
@@ -1,165 +1,113 b''
1 1 {
2 2 "cells": [
3 3 {
4 4 "cell_type": "markdown",
5 5 "metadata": {},
6 6 "source": [
7 7 "# Keyboard Shortcut Customization"
8 8 ]
9 9 },
10 10 {
11 11 "cell_type": "markdown",
12 12 "metadata": {},
13 13 "source": [
14 14 "Starting with IPython 2.0 keyboard shortcuts in command and edit mode are fully customizable. These customizations are made using the IPython JavaScript API. Here is an example that makes the `r` key available for running a cell:"
15 15 ]
16 16 },
17 17 {
18 18 "cell_type": "code",
19 "execution_count": 7,
19 "execution_count": null,
20 20 "metadata": {
21 21 "collapsed": false
22 22 },
23 "outputs": [
24 {
25 "data": {
26 "application/javascript": [
27 "\n",
28 "IPython.keyboard_manager.command_shortcuts.add_shortcut('r', {\n",
29 " help : 'run cell',\n",
30 " help_index : 'zz',\n",
31 " handler : function (event) {\n",
32 " IPython.notebook.execute_cell();\n",
33 " return false;\n",
34 " }}\n",
35 ");"
36 ],
37 "text/plain": [
38 "<IPython.core.display.Javascript at 0x10e8d1890>"
39 ]
40 },
41 "metadata": {},
42 "output_type": "display_data"
43 }
44 ],
23 "outputs": [],
45 24 "source": [
46 25 "%%javascript\n",
47 26 "\n",
48 27 "IPython.keyboard_manager.command_shortcuts.add_shortcut('r', {\n",
49 28 " help : 'run cell',\n",
50 29 " help_index : 'zz',\n",
51 30 " handler : function (event) {\n",
52 31 " IPython.notebook.execute_cell();\n",
53 32 " return false;\n",
54 33 " }}\n",
55 34 ");"
56 35 ]
57 36 },
58 37 {
59 38 "cell_type": "markdown",
60 39 "metadata": {},
61 40 "source": [
62 41 "There are a couple of points to mention about this API:\n",
63 42 "\n",
64 43 "* The `help_index` field is used to sort the shortcuts in the Keyboard Shortcuts help dialog. It defaults to `zz`.\n",
65 44 "* When a handler returns `false` it indicates that the event should stop propagating and the default action should not be performed. For further details about the `event` object or event handling, see the jQuery docs.\n",
66 45 "* If you don't need a `help` or `help_index` field, you can simply pass a function as the second argument to `add_shortcut`."
67 46 ]
68 47 },
69 48 {
70 49 "cell_type": "code",
71 "execution_count": 11,
50 "execution_count": null,
72 51 "metadata": {
73 52 "collapsed": false
74 53 },
75 "outputs": [
76 {
77 "data": {
78 "application/javascript": [
79 "\n",
80 "IPython.keyboard_manager.command_shortcuts.add_shortcut('r', function (event) {\n",
81 " IPython.notebook.execute_cell();\n",
82 " return false;\n",
83 "});"
84 ],
85 "text/plain": [
86 "<IPython.core.display.Javascript at 0x1019baf90>"
87 ]
88 },
89 "metadata": {},
90 "output_type": "display_data"
91 }
92 ],
54 "outputs": [],
93 55 "source": [
94 56 "%%javascript\n",
95 57 "\n",
96 58 "IPython.keyboard_manager.command_shortcuts.add_shortcut('r', function (event) {\n",
97 59 " IPython.notebook.execute_cell();\n",
98 60 " return false;\n",
99 61 "});"
100 62 ]
101 63 },
102 64 {
103 65 "cell_type": "markdown",
104 66 "metadata": {},
105 67 "source": [
106 68 "Likewise, to remove a shortcut, use `remove_shortcut`:"
107 69 ]
108 70 },
109 71 {
110 72 "cell_type": "code",
111 "execution_count": 8,
73 "execution_count": null,
112 74 "metadata": {
113 75 "collapsed": false
114 76 },
115 "outputs": [
116 {
117 "data": {
118 "application/javascript": [
119 "\n",
120 "IPython.keyboard_manager.command_shortcuts.remove_shortcut('r');"
121 ],
122 "text/plain": [
123 "<IPython.core.display.Javascript at 0x10e8d1950>"
124 ]
125 },
126 "metadata": {},
127 "output_type": "display_data"
128 }
129 ],
77 "outputs": [],
130 78 "source": [
131 79 "%%javascript\n",
132 80 "\n",
133 81 "IPython.keyboard_manager.command_shortcuts.remove_shortcut('r');"
134 82 ]
135 83 },
136 84 {
137 85 "cell_type": "markdown",
138 86 "metadata": {},
139 87 "source": [
140 88 "If you want your keyboard shortcuts to be active for all of your notebooks, put the above API calls into your `<profile>/static/custom/custom.js` file."
141 89 ]
142 90 }
143 91 ],
144 92 "metadata": {
145 93 "kernelspec": {
146 94 "display_name": "Python 3",
147 95 "language": "python",
148 96 "name": "python3"
149 97 },
150 98 "language_info": {
151 99 "codemirror_mode": {
152 100 "name": "ipython",
153 101 "version": 3
154 102 },
155 103 "file_extension": ".py",
156 104 "mimetype": "text/x-python",
157 105 "name": "python",
158 106 "nbconvert_exporter": "python",
159 107 "pygments_lexer": "ipython3",
160 "version": "3.4.2"
108 "version": "3.4.3"
161 109 }
162 110 },
163 111 "nbformat": 4,
164 112 "nbformat_minor": 0
165 113 }
@@ -1,733 +1,521 b''
1 1 {
2 2 "cells": [
3 3 {
4 4 "cell_type": "markdown",
5 5 "metadata": {},
6 6 "source": [
7 7 "# Importing IPython Notebooks as Modules"
8 8 ]
9 9 },
10 10 {
11 11 "cell_type": "markdown",
12 12 "metadata": {},
13 13 "source": [
14 14 "It is a common problem that people want to import code from IPython Notebooks.\n",
15 15 "This is made difficult by the fact that Notebooks are not plain Python files,\n",
16 16 "and thus cannot be imported by the regular Python machinery.\n",
17 17 "\n",
18 18 "Fortunately, Python provides some fairly sophisticated [hooks](http://www.python.org/dev/peps/pep-0302/) into the import machinery,\n",
19 19 "so we can actually make IPython notebooks importable without much difficulty,\n",
20 20 "and only using public APIs."
21 21 ]
22 22 },
23 23 {
24 24 "cell_type": "code",
25 "execution_count": 1,
25 "execution_count": null,
26 26 "metadata": {
27 27 "collapsed": false
28 28 },
29 29 "outputs": [],
30 30 "source": [
31 31 "import io, os, sys, types"
32 32 ]
33 33 },
34 34 {
35 35 "cell_type": "code",
36 "execution_count": 2,
36 "execution_count": null,
37 37 "metadata": {
38 38 "collapsed": false
39 39 },
40 40 "outputs": [],
41 41 "source": [
42 42 "from IPython.nbformat import current\n",
43 43 "from IPython.core.interactiveshell import InteractiveShell"
44 44 ]
45 45 },
46 46 {
47 47 "cell_type": "markdown",
48 48 "metadata": {},
49 49 "source": [
50 50 "Import hooks typically take the form of two objects:\n",
51 51 "\n",
52 52 "1. a Module **Loader**, which takes a module name (e.g. `'IPython.display'`), and returns a Module\n",
53 53 "2. a Module **Finder**, which figures out whether a module might exist, and tells Python what **Loader** to use"
54 54 ]
55 55 },
56 56 {
57 57 "cell_type": "code",
58 "execution_count": 3,
58 "execution_count": null,
59 59 "metadata": {
60 60 "collapsed": false
61 61 },
62 62 "outputs": [],
63 63 "source": [
64 64 "def find_notebook(fullname, path=None):\n",
65 65 " \"\"\"find a notebook, given its fully qualified name and an optional path\n",
66 66 " \n",
67 67 " This turns \"foo.bar\" into \"foo/bar.ipynb\"\n",
68 68 " and tries turning \"Foo_Bar\" into \"Foo Bar\" if Foo_Bar\n",
69 69 " does not exist.\n",
70 70 " \"\"\"\n",
71 71 " name = fullname.rsplit('.', 1)[-1]\n",
72 72 " if not path:\n",
73 73 " path = ['']\n",
74 74 " for d in path:\n",
75 75 " nb_path = os.path.join(d, name + \".ipynb\")\n",
76 76 " if os.path.isfile(nb_path):\n",
77 77 " return nb_path\n",
78 78 " # let import Notebook_Name find \"Notebook Name.ipynb\"\n",
79 79 " nb_path = nb_path.replace(\"_\", \" \")\n",
80 80 " if os.path.isfile(nb_path):\n",
81 81 " return nb_path\n",
82 82 " "
83 83 ]
84 84 },
85 85 {
86 86 "cell_type": "markdown",
87 87 "metadata": {},
88 88 "source": [
89 89 "## Notebook Loader"
90 90 ]
91 91 },
92 92 {
93 93 "cell_type": "markdown",
94 94 "metadata": {},
95 95 "source": [
96 96 "Here we have our Notebook Loader.\n",
97 97 "It's actually quite simple - once we figure out the filename of the module,\n",
98 98 "all it does is:\n",
99 99 "\n",
100 100 "1. load the notebook document into memory\n",
101 101 "2. create an empty Module\n",
102 102 "3. execute every cell in the Module namespace\n",
103 103 "\n",
104 104 "Since IPython cells can have extended syntax,\n",
105 105 "the IPython transform is applied to turn each of these cells into their pure-Python counterparts before executing them.\n",
106 106 "If all of your notebook cells are pure-Python,\n",
107 107 "this step is unnecessary."
108 108 ]
109 109 },
110 110 {
111 111 "cell_type": "code",
112 "execution_count": 4,
112 "execution_count": null,
113 113 "metadata": {
114 114 "collapsed": false
115 115 },
116 116 "outputs": [],
117 117 "source": [
118 118 "class NotebookLoader(object):\n",
119 119 " \"\"\"Module Loader for IPython Notebooks\"\"\"\n",
120 120 " def __init__(self, path=None):\n",
121 121 " self.shell = InteractiveShell.instance()\n",
122 122 " self.path = path\n",
123 123 " \n",
124 124 " def load_module(self, fullname):\n",
125 125 " \"\"\"import a notebook as a module\"\"\"\n",
126 126 " path = find_notebook(fullname, self.path)\n",
127 127 " \n",
128 128 " print (\"importing IPython notebook from %s\" % path)\n",
129 129 " \n",
130 130 " # load the notebook object\n",
131 131 " with io.open(path, 'r', encoding='utf-8') as f:\n",
132 132 " nb = current.read(f, 'json')\n",
133 133 " \n",
134 134 " \n",
135 135 " # create the module and add it to sys.modules\n",
136 136 " # if name in sys.modules:\n",
137 137 " # return sys.modules[name]\n",
138 138 " mod = types.ModuleType(fullname)\n",
139 139 " mod.__file__ = path\n",
140 140 " mod.__loader__ = self\n",
141 141 " sys.modules[fullname] = mod\n",
142 142 " \n",
143 143 " # extra work to ensure that magics that would affect the user_ns\n",
144 144 " # actually affect the notebook module's ns\n",
145 145 " save_user_ns = self.shell.user_ns\n",
146 146 " self.shell.user_ns = mod.__dict__\n",
147 147 " \n",
148 148 " try:\n",
149 149 " for cell in nb.worksheets[0].cells:\n",
150 150 " if cell.cell_type == 'code' and cell.language == 'python':\n",
151 151 " # transform the input to executable Python\n",
152 152 " code = self.shell.input_transformer_manager.transform_cell(cell.input)\n",
153 153 " # run the code in themodule\n",
154 154 " exec(code, mod.__dict__)\n",
155 155 " finally:\n",
156 156 " self.shell.user_ns = save_user_ns\n",
157 157 " return mod\n"
158 158 ]
159 159 },
160 160 {
161 161 "cell_type": "markdown",
162 162 "metadata": {},
163 163 "source": [
164 164 "## The Module Finder"
165 165 ]
166 166 },
167 167 {
168 168 "cell_type": "markdown",
169 169 "metadata": {},
170 170 "source": [
171 171 "The finder is a simple object that tells you whether a name can be imported,\n",
172 172 "and returns the appropriate loader.\n",
173 173 "All this one does is check, when you do:\n",
174 174 "\n",
175 175 "```python\n",
176 176 "import mynotebook\n",
177 177 "```\n",
178 178 "\n",
179 179 "it checks whether `mynotebook.ipynb` exists.\n",
180 180 "If a notebook is found, then it returns a NotebookLoader.\n",
181 181 "\n",
182 182 "Any extra logic is just for resolving paths within packages."
183 183 ]
184 184 },
185 185 {
186 186 "cell_type": "code",
187 "execution_count": 5,
187 "execution_count": null,
188 188 "metadata": {
189 189 "collapsed": false
190 190 },
191 191 "outputs": [],
192 192 "source": [
193 193 "class NotebookFinder(object):\n",
194 194 " \"\"\"Module finder that locates IPython Notebooks\"\"\"\n",
195 195 " def __init__(self):\n",
196 196 " self.loaders = {}\n",
197 197 " \n",
198 198 " def find_module(self, fullname, path=None):\n",
199 199 " nb_path = find_notebook(fullname, path)\n",
200 200 " if not nb_path:\n",
201 201 " return\n",
202 202 " \n",
203 203 " key = path\n",
204 204 " if path:\n",
205 205 " # lists aren't hashable\n",
206 206 " key = os.path.sep.join(path)\n",
207 207 " \n",
208 208 " if key not in self.loaders:\n",
209 209 " self.loaders[key] = NotebookLoader(path)\n",
210 210 " return self.loaders[key]\n"
211 211 ]
212 212 },
213 213 {
214 214 "cell_type": "markdown",
215 215 "metadata": {},
216 216 "source": [
217 217 "## Register the hook"
218 218 ]
219 219 },
220 220 {
221 221 "cell_type": "markdown",
222 222 "metadata": {},
223 223 "source": [
224 224 "Now we register the `NotebookFinder` with `sys.meta_path`"
225 225 ]
226 226 },
227 227 {
228 228 "cell_type": "code",
229 "execution_count": 6,
229 "execution_count": null,
230 230 "metadata": {
231 231 "collapsed": false
232 232 },
233 233 "outputs": [],
234 234 "source": [
235 235 "sys.meta_path.append(NotebookFinder())"
236 236 ]
237 237 },
238 238 {
239 239 "cell_type": "markdown",
240 240 "metadata": {},
241 241 "source": [
242 242 "After this point, my notebooks should be importable.\n",
243 243 "\n",
244 244 "Let's look at what we have in the CWD:"
245 245 ]
246 246 },
247 247 {
248 248 "cell_type": "code",
249 "execution_count": 7,
249 "execution_count": null,
250 250 "metadata": {
251 251 "collapsed": false
252 252 },
253 "outputs": [
254 {
255 "name": "stdout",
256 "output_type": "stream",
257 "text": [
258 "__init__.py mynotebook.ipynb \u001b[34mnbs\u001b[m\u001b[m/\r\n"
259 ]
260 }
261 ],
253 "outputs": [],
262 254 "source": [
263 255 "ls nbpackage"
264 256 ]
265 257 },
266 258 {
267 259 "cell_type": "markdown",
268 260 "metadata": {},
269 261 "source": [
270 262 "So I should be able to `import nbimp.mynotebook`.\n"
271 263 ]
272 264 },
273 265 {
274 266 "cell_type": "markdown",
275 267 "metadata": {},
276 268 "source": [
277 269 "### Aside: displaying notebooks"
278 270 ]
279 271 },
280 272 {
281 273 "cell_type": "markdown",
282 274 "metadata": {},
283 275 "source": [
284 276 "Here is some simple code to display the contents of a notebook\n",
285 277 "with syntax highlighting, etc."
286 278 ]
287 279 },
288 280 {
289 281 "cell_type": "code",
290 "execution_count": 8,
282 "execution_count": null,
291 283 "metadata": {
292 284 "collapsed": false
293 285 },
294 "outputs": [
295 {
296 "data": {
297 "text/html": [
298 "\n",
299 "<style type='text/css'>\n",
300 ".hll { background-color: #ffffcc }\n",
301 ".c { color: #408080; font-style: italic } /* Comment */\n",
302 ".err { border: 1px solid #FF0000 } /* Error */\n",
303 ".k { color: #008000; font-weight: bold } /* Keyword */\n",
304 ".o { color: #666666 } /* Operator */\n",
305 ".cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
306 ".cp { color: #BC7A00 } /* Comment.Preproc */\n",
307 ".c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
308 ".cs { color: #408080; font-style: italic } /* Comment.Special */\n",
309 ".gd { color: #A00000 } /* Generic.Deleted */\n",
310 ".ge { font-style: italic } /* Generic.Emph */\n",
311 ".gr { color: #FF0000 } /* Generic.Error */\n",
312 ".gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
313 ".gi { color: #00A000 } /* Generic.Inserted */\n",
314 ".go { color: #888888 } /* Generic.Output */\n",
315 ".gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
316 ".gs { font-weight: bold } /* Generic.Strong */\n",
317 ".gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
318 ".gt { color: #0044DD } /* Generic.Traceback */\n",
319 ".kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
320 ".kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
321 ".kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
322 ".kp { color: #008000 } /* Keyword.Pseudo */\n",
323 ".kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
324 ".kt { color: #B00040 } /* Keyword.Type */\n",
325 ".m { color: #666666 } /* Literal.Number */\n",
326 ".s { color: #BA2121 } /* Literal.String */\n",
327 ".na { color: #7D9029 } /* Name.Attribute */\n",
328 ".nb { color: #008000 } /* Name.Builtin */\n",
329 ".nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
330 ".no { color: #880000 } /* Name.Constant */\n",
331 ".nd { color: #AA22FF } /* Name.Decorator */\n",
332 ".ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
333 ".ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
334 ".nf { color: #0000FF } /* Name.Function */\n",
335 ".nl { color: #A0A000 } /* Name.Label */\n",
336 ".nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
337 ".nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
338 ".nv { color: #19177C } /* Name.Variable */\n",
339 ".ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
340 ".w { color: #bbbbbb } /* Text.Whitespace */\n",
341 ".mf { color: #666666 } /* Literal.Number.Float */\n",
342 ".mh { color: #666666 } /* Literal.Number.Hex */\n",
343 ".mi { color: #666666 } /* Literal.Number.Integer */\n",
344 ".mo { color: #666666 } /* Literal.Number.Oct */\n",
345 ".sb { color: #BA2121 } /* Literal.String.Backtick */\n",
346 ".sc { color: #BA2121 } /* Literal.String.Char */\n",
347 ".sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
348 ".s2 { color: #BA2121 } /* Literal.String.Double */\n",
349 ".se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
350 ".sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
351 ".si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
352 ".sx { color: #008000 } /* Literal.String.Other */\n",
353 ".sr { color: #BB6688 } /* Literal.String.Regex */\n",
354 ".s1 { color: #BA2121 } /* Literal.String.Single */\n",
355 ".ss { color: #19177C } /* Literal.String.Symbol */\n",
356 ".bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
357 ".vc { color: #19177C } /* Name.Variable.Class */\n",
358 ".vg { color: #19177C } /* Name.Variable.Global */\n",
359 ".vi { color: #19177C } /* Name.Variable.Instance */\n",
360 ".il { color: #666666 } /* Literal.Number.Integer.Long */\n",
361 "</style>\n"
362 ],
363 "text/plain": [
364 "<IPython.core.display.HTML at 0x1072303d0>"
365 ]
366 },
367 "metadata": {},
368 "output_type": "display_data"
369 }
370 ],
286 "outputs": [],
371 287 "source": [
372 288 "from pygments import highlight\n",
373 289 "from pygments.lexers import PythonLexer\n",
374 290 "from pygments.formatters import HtmlFormatter\n",
375 291 "\n",
376 292 "from IPython.display import display, HTML\n",
377 293 "\n",
378 294 "formatter = HtmlFormatter()\n",
379 295 "lexer = PythonLexer()\n",
380 296 "\n",
381 297 "# publish the CSS for pygments highlighting\n",
382 298 "display(HTML(\"\"\"\n",
383 299 "<style type='text/css'>\n",
384 300 "%s\n",
385 301 "</style>\n",
386 302 "\"\"\" % formatter.get_style_defs()\n",
387 303 "))"
388 304 ]
389 305 },
390 306 {
391 307 "cell_type": "code",
392 "execution_count": 10,
308 "execution_count": null,
393 309 "metadata": {
394 310 "collapsed": false
395 311 },
396 "outputs": [
397 {
398 "data": {
399 "text/html": [
400 "<h4>heading cell</h4>\n",
401 "<pre>My Notebook</pre>\n",
402 "<h4>code cell</h4>\n",
403 "<div class=\"highlight\"><pre><span class=\"k\">def</span> <span class=\"nf\">foo</span><span class=\"p\">():</span>\n",
404 " <span class=\"k\">return</span> <span class=\"s\">&quot;foo&quot;</span>\n",
405 "</pre></div>\n",
406 "\n",
407 "<h4>code cell</h4>\n",
408 "<div class=\"highlight\"><pre><span class=\"k\">def</span> <span class=\"nf\">has_ip_syntax</span><span class=\"p\">():</span>\n",
409 " <span class=\"n\">listing</span> <span class=\"o\">=</span> <span class=\"err\">!</span><span class=\"n\">ls</span>\n",
410 " <span class=\"k\">return</span> <span class=\"n\">listing</span>\n",
411 "</pre></div>\n",
412 "\n",
413 "<h4>code cell</h4>\n",
414 "<div class=\"highlight\"><pre><span class=\"k\">def</span> <span class=\"nf\">whatsmyname</span><span class=\"p\">():</span>\n",
415 " <span class=\"k\">return</span> <span class=\"n\">__name__</span>\n",
416 "</pre></div>\n"
417 ],
418 "text/plain": [
419 "<IPython.core.display.HTML at 0x10775a150>"
420 ]
421 },
422 "metadata": {},
423 "output_type": "display_data"
424 }
425 ],
312 "outputs": [],
426 313 "source": [
427 314 "def show_notebook(fname):\n",
428 315 " \"\"\"display a short summary of the cells of a notebook\"\"\"\n",
429 316 " with io.open(fname, 'r', encoding='utf-8') as f:\n",
430 317 " nb = current.read(f, 'json')\n",
431 318 " html = []\n",
432 319 " for cell in nb.worksheets[0].cells:\n",
433 320 " html.append(\"<h4>%s cell</h4>\" % cell.cell_type)\n",
434 321 " if cell.cell_type == 'code':\n",
435 322 " html.append(highlight(cell.input, lexer, formatter))\n",
436 323 " else:\n",
437 324 " html.append(\"<pre>%s</pre>\" % cell.source)\n",
438 325 " display(HTML('\\n'.join(html)))\n",
439 326 "\n",
440 327 "show_notebook(os.path.join(\"nbpackage\", \"mynotebook.ipynb\"))"
441 328 ]
442 329 },
443 330 {
444 331 "cell_type": "markdown",
445 332 "metadata": {},
446 333 "source": [
447 334 "So my notebook has a heading cell and some code cells,\n",
448 335 "one of which contains some IPython syntax.\n",
449 336 "\n",
450 337 "Let's see what happens when we import it"
451 338 ]
452 339 },
453 340 {
454 341 "cell_type": "code",
455 "execution_count": 11,
342 "execution_count": null,
456 343 "metadata": {
457 344 "collapsed": false
458 345 },
459 "outputs": [
460 {
461 "name": "stdout",
462 "output_type": "stream",
463 "text": [
464 "importing IPython notebook from nbpackage/mynotebook.ipynb\n"
465 ]
466 }
467 ],
346 "outputs": [],
468 347 "source": [
469 348 "from nbpackage import mynotebook"
470 349 ]
471 350 },
472 351 {
473 352 "cell_type": "markdown",
474 353 "metadata": {},
475 354 "source": [
476 355 "Hooray, it imported! Does it work?"
477 356 ]
478 357 },
479 358 {
480 359 "cell_type": "code",
481 "execution_count": 12,
360 "execution_count": null,
482 361 "metadata": {
483 362 "collapsed": false
484 363 },
485 "outputs": [
486 {
487 "data": {
488 "text/plain": [
489 "'foo'"
490 ]
491 },
492 "execution_count": 12,
493 "metadata": {},
494 "output_type": "execute_result"
495 }
496 ],
364 "outputs": [],
497 365 "source": [
498 366 "mynotebook.foo()"
499 367 ]
500 368 },
501 369 {
502 370 "cell_type": "markdown",
503 371 "metadata": {},
504 372 "source": [
505 373 "Hooray again!\n",
506 374 "\n",
507 375 "Even the function that contains IPython syntax works:"
508 376 ]
509 377 },
510 378 {
511 379 "cell_type": "code",
512 "execution_count": 13,
380 "execution_count": null,
513 381 "metadata": {
514 382 "collapsed": false
515 383 },
516 "outputs": [
517 {
518 "data": {
519 "text/plain": [
520 "['Animations Using clear_output.ipynb',\n",
521 " 'Connecting with the Qt Console.ipynb',\n",
522 " 'Importing Notebooks.ipynb',\n",
523 " 'Progress Bars.ipynb',\n",
524 " 'Raw Input.ipynb',\n",
525 " 'SymPy.ipynb',\n",
526 " 'Trapezoid Rule.ipynb',\n",
527 " 'nbpackage']"
528 ]
529 },
530 "execution_count": 13,
531 "metadata": {},
532 "output_type": "execute_result"
533 }
534 ],
384 "outputs": [],
535 385 "source": [
536 386 "mynotebook.has_ip_syntax()"
537 387 ]
538 388 },
539 389 {
540 390 "cell_type": "markdown",
541 391 "metadata": {},
542 392 "source": [
543 393 "## Notebooks in packages"
544 394 ]
545 395 },
546 396 {
547 397 "cell_type": "markdown",
548 398 "metadata": {},
549 399 "source": [
550 400 "We also have a notebook inside the `nb` package,\n",
551 401 "so let's make sure that works as well."
552 402 ]
553 403 },
554 404 {
555 405 "cell_type": "code",
556 "execution_count": 14,
406 "execution_count": null,
557 407 "metadata": {
558 408 "collapsed": false
559 409 },
560 "outputs": [
561 {
562 "name": "stdout",
563 "output_type": "stream",
564 "text": [
565 "__init__.py other.ipynb\r\n"
566 ]
567 }
568 ],
410 "outputs": [],
569 411 "source": [
570 412 "ls nbpackage/nbs"
571 413 ]
572 414 },
573 415 {
574 416 "cell_type": "markdown",
575 417 "metadata": {},
576 418 "source": [
577 419 "Note that the `__init__.py` is necessary for `nb` to be considered a package,\n",
578 420 "just like usual."
579 421 ]
580 422 },
581 423 {
582 424 "cell_type": "code",
583 "execution_count": 15,
425 "execution_count": null,
584 426 "metadata": {
585 427 "collapsed": false
586 428 },
587 "outputs": [
588 {
589 "data": {
590 "text/html": [
591 "<h4>markdown cell</h4>\n",
592 "<pre>This notebook just defines `bar`</pre>\n",
593 "<h4>code cell</h4>\n",
594 "<div class=\"highlight\"><pre><span class=\"k\">def</span> <span class=\"nf\">bar</span><span class=\"p\">(</span><span class=\"n\">x</span><span class=\"p\">):</span>\n",
595 " <span class=\"k\">return</span> <span class=\"s\">&quot;bar&quot;</span> <span class=\"o\">*</span> <span class=\"n\">x</span>\n",
596 "</pre></div>\n"
597 ],
598 "text/plain": [
599 "<IPython.core.display.HTML at 0x10775a250>"
600 ]
601 },
602 "metadata": {},
603 "output_type": "display_data"
604 }
605 ],
429 "outputs": [],
606 430 "source": [
607 431 "show_notebook(os.path.join(\"nbpackage\", \"nbs\", \"other.ipynb\"))"
608 432 ]
609 433 },
610 434 {
611 435 "cell_type": "code",
612 "execution_count": 16,
436 "execution_count": null,
613 437 "metadata": {
614 438 "collapsed": false
615 439 },
616 "outputs": [
617 {
618 "name": "stdout",
619 "output_type": "stream",
620 "text": [
621 "importing IPython notebook from nbpackage/nbs/other.ipynb\n"
622 ]
623 },
624 {
625 "data": {
626 "text/plain": [
627 "'barbarbarbarbar'"
628 ]
629 },
630 "execution_count": 16,
631 "metadata": {},
632 "output_type": "execute_result"
633 }
634 ],
440 "outputs": [],
635 441 "source": [
636 442 "from nbpackage.nbs import other\n",
637 443 "other.bar(5)"
638 444 ]
639 445 },
640 446 {
641 447 "cell_type": "markdown",
642 448 "metadata": {},
643 449 "source": [
644 450 "So now we have importable notebooks, from both the local directory and inside packages.\n",
645 451 "\n",
646 452 "I can even put a notebook inside IPython, to further demonstrate that this is working properly:"
647 453 ]
648 454 },
649 455 {
650 456 "cell_type": "code",
651 "execution_count": 17,
457 "execution_count": null,
652 458 "metadata": {
653 459 "collapsed": false
654 460 },
655 461 "outputs": [],
656 462 "source": [
657 463 "import shutil\n",
658 464 "from IPython.utils.path import get_ipython_package_dir\n",
659 465 "\n",
660 466 "utils = os.path.join(get_ipython_package_dir(), 'utils')\n",
661 467 "shutil.copy(os.path.join(\"nbpackage\", \"mynotebook.ipynb\"),\n",
662 468 " os.path.join(utils, \"inside_ipython.ipynb\")\n",
663 469 ")"
664 470 ]
665 471 },
666 472 {
667 473 "cell_type": "markdown",
668 474 "metadata": {},
669 475 "source": [
670 476 "and import the notebook from `IPython.utils`"
671 477 ]
672 478 },
673 479 {
674 480 "cell_type": "code",
675 "execution_count": 18,
481 "execution_count": null,
676 482 "metadata": {
677 483 "collapsed": false
678 484 },
679 "outputs": [
680 {
681 "name": "stdout",
682 "output_type": "stream",
683 "text": [
684 "importing IPython notebook from /Users/bgranger/Documents/Computing/IPython/code/ipython/IPython/utils/inside_ipython.ipynb\n"
685 ]
686 },
687 {
688 "data": {
689 "text/plain": [
690 "'IPython.utils.inside_ipython'"
691 ]
692 },
693 "execution_count": 18,
694 "metadata": {},
695 "output_type": "execute_result"
696 }
697 ],
485 "outputs": [],
698 486 "source": [
699 487 "from IPython.utils import inside_ipython\n",
700 488 "inside_ipython.whatsmyname()"
701 489 ]
702 490 },
703 491 {
704 492 "cell_type": "markdown",
705 493 "metadata": {},
706 494 "source": [
707 495 "This approach can even import functions and classes that are defined in a notebook using the `%%cython` magic."
708 496 ]
709 497 }
710 498 ],
711 499 "metadata": {
712 500 "gist_id": "6011986",
713 501 "kernelspec": {
714 502 "display_name": "Python 3",
715 503 "language": "python",
716 504 "name": "python3"
717 505 },
718 506 "language_info": {
719 507 "codemirror_mode": {
720 508 "name": "ipython",
721 509 "version": 3
722 510 },
723 511 "file_extension": ".py",
724 512 "mimetype": "text/x-python",
725 513 "name": "python",
726 514 "nbconvert_exporter": "python",
727 515 "pygments_lexer": "ipython3",
728 "version": "3.4.2"
516 "version": "3.4.3"
729 517 }
730 518 },
731 519 "nbformat": 4,
732 520 "nbformat_minor": 0
733 521 }
@@ -1,92 +1,91 b''
1 1 {
2 2 "cells": [
3 3 {
4 4 "cell_type": "markdown",
5 5 "metadata": {},
6 6 "source": [
7 7 "<img src=\"../images/ipython_logo.png\">"
8 8 ]
9 9 },
10 10 {
11 11 "cell_type": "markdown",
12 12 "metadata": {},
13 13 "source": [
14 14 "Back to the main [Index](../Index.ipynb)"
15 15 ]
16 16 },
17 17 {
18 18 "cell_type": "markdown",
19 19 "metadata": {},
20 20 "source": [
21 21 "# Notebook"
22 22 ]
23 23 },
24 24 {
25 25 "cell_type": "markdown",
26 26 "metadata": {},
27 27 "source": [
28 28 "The IPython Notebook is a web-based interactive computing system that enables users to author documents that include live code, narrative text, LaTeX equations, HTML, images and video. These documents contain a full record of a computation and its results and can be shared on email, [Dropbox](http://dropbox.com), version control systems (like git/[GitHub](http://github.com)) or [nbviewer.ipython.org](http://nbviewer.ipython.org)."
29 29 ]
30 30 },
31 31 {
32 32 "cell_type": "markdown",
33 33 "metadata": {},
34 34 "source": [
35 35 "## Tutorials"
36 36 ]
37 37 },
38 38 {
39 39 "cell_type": "markdown",
40 40 "metadata": {},
41 41 "source": [
42 42 "* [What is the IPython Notebook](What is the IPython Notebook.ipynb)\n",
43 "* [Running the Notebook Server](Running the Notebook Server.ipynb)\n",
44 43 "* [Notebook Basics](Notebook Basics.ipynb)\n",
45 44 "* [Running Code](Running Code.ipynb)\n",
46 45 "* [Working With Markdown Cells](Working With Markdown Cells.ipynb)\n",
46 "* [Configuring the Notebook and Server](Configuring the Notebook and Server.ipynb)\n",
47 47 "* [Custom Keyboard Shortcuts](Custom Keyboard Shortcuts.ipynb)\n",
48 48 "* [JavaScript Notebook Extensions](JavaScript Notebook Extensions.ipynb)\n",
49 "* [Notebook Security](Notebook Security.ipynb)\n",
50 49 "* [Converting Notebooks With nbconvert](Converting Notebooks With nbconvert.ipynb)\n",
51 50 "* [Using nbconvert as a Library](Using nbconvert as a Library.ipynb)"
52 51 ]
53 52 },
54 53 {
55 54 "cell_type": "markdown",
56 55 "metadata": {},
57 56 "source": [
58 57 "## Examples"
59 58 ]
60 59 },
61 60 {
62 61 "cell_type": "markdown",
63 62 "metadata": {},
64 63 "source": [
65 64 "* [Importing Notebooks](Importing Notebooks.ipynb)\n",
66 65 "* [Connecting with the Qt Console](Connecting with the Qt Console.ipynb)\n",
67 66 "* [Typesetting Equations](Typesetting Equations.ipynb)"
68 67 ]
69 68 }
70 69 ],
71 70 "metadata": {
72 71 "kernelspec": {
73 72 "display_name": "Python 3",
74 73 "language": "python",
75 74 "name": "python3"
76 75 },
77 76 "language_info": {
78 77 "codemirror_mode": {
79 78 "name": "ipython",
80 79 "version": 3
81 80 },
82 81 "file_extension": ".py",
83 82 "mimetype": "text/x-python",
84 83 "name": "python",
85 84 "nbconvert_exporter": "python",
86 85 "pygments_lexer": "ipython3",
87 "version": "3.4.2"
86 "version": "3.4.3"
88 87 }
89 88 },
90 89 "nbformat": 4,
91 90 "nbformat_minor": 0
92 91 }
@@ -1,773 +1,612 b''
1 1 {
2 2 "cells": [
3 3 {
4 4 "cell_type": "markdown",
5 5 "metadata": {},
6 6 "source": [
7 7 "# Embrasing web standards"
8 8 ]
9 9 },
10 10 {
11 11 "cell_type": "markdown",
12 12 "metadata": {},
13 13 "source": [
14 14 "One of the main reason that allowed us to developp the current notebook web application \n",
15 15 "was to embrase the web technology. \n",
16 16 "\n",
17 17 "By beeing a pure web application using HTML, Javascript and CSS, the Notebook can get \n",
18 18 "all the web technology improvement for free. Thus, as browsers support for different \n",
19 19 "media extend, The notebook web app should be able to be compatible without modification. \n",
20 20 "\n",
21 21 "This is also true with performance of the User Interface as the speed of javascript VM increase. "
22 22 ]
23 23 },
24 24 {
25 25 "cell_type": "markdown",
26 26 "metadata": {},
27 27 "source": [
28 28 "The other advantage of using only web technology is that the code of the interface is fully accessible to the end user, and modifiable live.\n",
29 29 "Even if this task is not always easy, we strive to keep our code as accessible and reusable as possible.\n",
30 30 "This should allow with minimum effort to develop small extensions that customize the behavior of the web interface. "
31 31 ]
32 32 },
33 33 {
34 34 "cell_type": "markdown",
35 35 "metadata": {},
36 36 "source": [
37 37 "## Tempering with Notebook app"
38 38 ]
39 39 },
40 40 {
41 41 "cell_type": "markdown",
42 42 "metadata": {},
43 43 "source": [
44 44 "The first tool that is availlable to you and that you shoudl be aware of are browser \"developpers tool\". The exact naming can change across browser, and might require the installation of extensions. But basically they can allow you to inspect/modify the DOM, and interact with the javascript code that run the frontend.\n",
45 45 "\n",
46 46 " - In Chrome and safari Developper tools are in the menu [Put mmenu name in english here] \n",
47 47 " - In firefox you might need to install [Firebug](http://getfirebug.com/)\n",
48 48 " - others ?\n",
49 49 " \n",
50 50 "Those will be your best friends to debug and try different approach for your extensions."
51 51 ]
52 52 },
53 53 {
54 54 "cell_type": "markdown",
55 55 "metadata": {},
56 56 "source": [
57 57 "### Injecting JS"
58 58 ]
59 59 },
60 60 {
61 61 "cell_type": "markdown",
62 62 "metadata": {},
63 63 "source": [
64 64 "#### using magics"
65 65 ]
66 66 },
67 67 {
68 68 "cell_type": "markdown",
69 69 "metadata": {},
70 70 "source": [
71 71 "Above tools can be tedious to edit long javascipt files. Hopefully we provide the `%%javascript` magic. This allows you to quickly inject javascript into the notebook. Still the javascript injected this way will not survive reloading. Hence it is a good tool for testing an refinig a script.\n",
72 72 "\n",
73 73 "You might see here and there people modifying css and injecting js into notebook by reading file and publishing them into the notebook.\n",
74 74 "Not only this often break the flow of the notebook and make the re-execution of the notebook broken, but it also mean that you need to execute those cells on all the notebook every time you need to update the code.\n",
75 75 "\n",
76 76 "This can still be usefull in some cases, like the `%autosave` magic that allows to control the time between each save. But this can be replaced by a Javascript dropdown menu to select save interval."
77 77 ]
78 78 },
79 79 {
80 80 "cell_type": "code",
81 81 "execution_count": null,
82 82 "metadata": {
83 83 "collapsed": false
84 84 },
85 85 "outputs": [],
86 86 "source": [
87 87 "## you can inspect the autosave code to see what it does.\n",
88 88 "%autosave??"
89 89 ]
90 90 },
91 91 {
92 92 "cell_type": "markdown",
93 93 "metadata": {},
94 94 "source": [
95 95 "#### custom.js"
96 96 ]
97 97 },
98 98 {
99 99 "cell_type": "markdown",
100 100 "metadata": {},
101 101 "source": [
102 102 "To inject Javascript we provide an entry point: `custom.js` that allow teh user to execute and load other resources into the notebook.\n",
103 103 "Javascript code in `custom.js` will be executed when the notebook app start and can then be used to customise almost anything in the UI and in the behavior of the notebook.\n",
104 104 "\n",
105 105 "`custom.js` can be found in IPython profile dir, and so you can have different UI modification on a per profile basis, as well as share your modfication with others."
106 106 ]
107 107 },
108 108 {
109 109 "cell_type": "markdown",
110 110 "metadata": {},
111 111 "source": [
112 112 "##### Because we like you...."
113 113 ]
114 114 },
115 115 {
116 116 "cell_type": "markdown",
117 117 "metadata": {},
118 118 "source": [
119 119 "You have been provided with an already existing profile folder with this tutorial...\n",
120 120 "start the notebook from the root of the tutorial directory with :\n",
121 121 "\n",
122 122 "```bash\n",
123 123 "$ ipython notebook --ProfileDir.location=./profile_euroscipy\n",
124 124 "```"
125 125 ]
126 126 },
127 127 {
128 128 "cell_type": "markdown",
129 129 "metadata": {},
130 130 "source": [
131 131 "##### but back to theory"
132 132 ]
133 133 },
134 134 {
135 135 "cell_type": "code",
136 136 "execution_count": null,
137 137 "metadata": {
138 138 "collapsed": false
139 139 },
140 "outputs": [
141 {
142 "data": {
143 "text/plain": [
144 "'/Users/bussonniermatthias/.ipython'"
145 ]
146 },
147 "execution_count": 1,
148 "metadata": {},
149 "output_type": "execute_result"
150 }
151 ],
140 "outputs": [],
152 141 "source": [
153 142 "profile_dir = ! ipython locate\n",
154 143 "profile_dir = profile_dir[0]\n",
155 144 "profile_dir"
156 145 ]
157 146 },
158 147 {
159 148 "cell_type": "markdown",
160 149 "metadata": {},
161 150 "source": [
162 151 "and custom js is in "
163 152 ]
164 153 },
165 154 {
166 155 "cell_type": "code",
167 156 "execution_count": null,
168 157 "metadata": {
169 158 "collapsed": false
170 159 },
171 160 "outputs": [],
172 161 "source": [
173 162 "import os.path\n",
174 163 "custom_js_path = os.path.join(profile_dir,'profile_default','static','custom','custom.js')"
175 164 ]
176 165 },
177 166 {
178 167 "cell_type": "code",
179 168 "execution_count": null,
180 169 "metadata": {
181 170 "collapsed": false
182 171 },
183 "outputs": [
184 {
185 "name": "stdout",
186 "output_type": "stream",
187 "text": [
188 "// we want strict javascript that fails\n",
189 "// on ambiguous syntax\n",
190 "\"using strict\";\n",
191 "\n",
192 "// notebook loaded is not perfect as it is re-triggerd on\n",
193 "// revert to checkpoint but this allow extesnsion to be loaded\n",
194 "// late enough to work.\n",
195 "$([IPython.events]).on('notebook_loaded.Notebook', function(){\n",
196 "\n",
197 "\n",
198 " /** Use path to js file relative to /static/ dir without leading slash, or\n",
199 " * js extension.\n",
200 " * Link directly to file is js extension isa simple file\n",
201 " *\n",
202 " * first argument of require is a **list** that can contains several modules if needed.\n",
203 " **/\n",
204 "\n",
205 " //require(['custom/noscroll']);\n",
206 " // require(['custom/clean_start'])\n",
207 " // require(['custom/toggle_all_line_number'])\n",
208 " // require(['custom/gist_it']);\n",
209 " // require(['custom/autosavetime']);\n",
210 "\n",
211 " /**\n",
212 " * Link to entrypoint if extesnsion is a folder.\n",
213 " * to be consistent with commonjs module, the entrypoint is main.js\n",
214 " * here youcan also trigger a custom function on load that will do extra\n",
215 " * action with the module if needed\n",
216 " **/\n",
217 " require(['custom/slidemode/main'])\n",
218 "\n",
219 " // require(['custom/autoscroll']);\n",
220 "\n",
221 " //require(['custom/css_selector/main'])\n",
222 " require(['custom/pre_exec_strip']);\n",
223 " // require(['custom/no_exec_dunder']);\n",
224 " // load_ext('nbviewer_theme')\n",
225 "\n",
226 "\n",
227 " require(['custom/clippytip/main']);\n",
228 "\n",
229 " IPython.toolbar.add_buttons_group([\n",
230 " {\n",
231 " 'label' : 'run qtconsole',\n",
232 " 'icon' : 'icon-paper-clip', // select your icon from http://jqueryui.com/themeroller/\n",
233 " 'callback': function(){\n",
234 " IPython.tooltip.remove_and_cancel_tooltip(true)\n",
235 " $('#tooltip').empty() \n",
236 " $('#tooltip').attr('style','') \n",
237 " IPython.tooltip = new IPython.ClippyTip()\n",
238 " }\n",
239 " },\n",
240 " {\n",
241 " 'label' : 'run qtconsole',\n",
242 " 'icon' : 'icon-th-large', // select your icon from http://jqueryui.com/themeroller/\n",
243 " 'callback': function(){\n",
244 " IPython.tooltip.remove_and_cancel_tooltip(true)\n",
245 " $('#tooltip').empty() \n",
246 " $('#tooltip').attr('style','')\n",
247 " IPython.tooltip = new IPython.Tooltip()\n",
248 " }\n",
249 " }\n",
250 " // add more button here if needed.\n",
251 " ]);\n",
252 " //\n",
253 "\n",
254 "});\n",
255 "\n",
256 "/*\n",
257 "$([IPython.events]).on('notebook_loaded.Notebook', function(){\n",
258 " IPython.toolbar.add_buttons_group([\n",
259 " {\n",
260 " 'label' : 'run qtconsole',\n",
261 " 'icon' : 'ui-icon-calculator',\n",
262 " 'callback': function(){IPython.notebook.kernel.execute('%qtconsole')}\n",
263 " }\n",
264 " ]);\n",
265 "});\n",
266 "*/\n",
267 "\n",
268 "//$([IPython.events]).on('notebook_loaded.Notebook', function(){\n",
269 "// mobile_preset = []\n",
270 "// var edit = function(div, cell) {\n",
271 "// var button_container = $(div);\n",
272 "// var button = $('<div/>').button({icons:{primary:'ui-icon-pencil'}});\n",
273 "// button.click(function(){\n",
274 "// cell.edit()\n",
275 "// })\n",
276 "// button_container.append(button);\n",
277 "// }\n",
278 "//\n",
279 "// IPython.CellToolbar.register_callback('mobile.edit',edit);\n",
280 "// mobile_preset.push('mobile.edit');\n",
281 "//\n",
282 "// IPython.CellToolbar.register_preset('Mobile',mobile_preset);\n",
283 "//});\n"
284 ]
285 }
286 ],
172 "outputs": [],
287 173 "source": [
288 174 "# my custom js\n",
289 175 "with open(custom_js_path) as f:\n",
290 176 " for l in f: \n",
291 177 " print l,"
292 178 ]
293 179 },
294 180 {
295 181 "cell_type": "markdown",
296 182 "metadata": {},
297 183 "source": [
298 184 "Note that `custom.js` is ment to be modified by user, when writing a script, you can define it in a separate file and add a line of configuration into `custom.js` that will fetch and execute the file."
299 185 ]
300 186 },
301 187 {
302 188 "cell_type": "markdown",
303 189 "metadata": {},
304 190 "source": [
305 191 "**Warning** : even if modification of `custom.js` take effect immediately after browser refresh (except if browser cache is aggressive), *creating* a file in `static/` directory need a **server restart**."
306 192 ]
307 193 },
308 194 {
309 195 "cell_type": "markdown",
310 196 "metadata": {},
311 197 "source": [
312 198 "## Exercise :"
313 199 ]
314 200 },
315 201 {
316 202 "cell_type": "markdown",
317 203 "metadata": {},
318 204 "source": [
319 205 " - Create a `custom.js` in the right location with the following content:\n",
320 206 "```javascript\n",
321 207 "alert(\"hello world from custom.js\")\n",
322 208 "```\n",
323 209 "\n",
324 210 " - Restart your server and open any notebook.\n",
325 211 " - Be greeted by custom.js"
326 212 ]
327 213 },
328 214 {
329 215 "cell_type": "markdown",
330 216 "metadata": {},
331 217 "source": [
332 218 "Have a look at [default custom.js](https://github.com/ipython/ipython/blob/1.x/IPython/html/static/custom/custom.js), to see it's content and some more explanation."
333 219 ]
334 220 },
335 221 {
336 222 "cell_type": "markdown",
337 223 "metadata": {},
338 224 "source": [
339 225 "#### For the quick ones : "
340 226 ]
341 227 },
342 228 {
343 229 "cell_type": "markdown",
344 230 "metadata": {},
345 231 "source": [
346 232 "We've seen above that you can change the autosave rate by using a magic. This is typically something I don't want to type everytime, and that I don't like to embed into my workwlow and documents. (reader don't care what my autosave time is), let's build an extension that allow to do it. "
347 233 ]
348 234 },
349 235 {
350 236 "cell_type": "markdown",
351 237 "metadata": {
352 238 "foo": true
353 239 },
354 240 "source": [
355 241 "Create a dropdow elemement in the toolbar (DOM `IPython.toolbar.element`), you will need \n",
356 242 "\n",
357 243 "- `IPython.notebook.set_autosave_interval(miliseconds)`\n",
358 244 "- know that 1min = 60 sec, and 1 sec = 1000 ms"
359 245 ]
360 246 },
361 247 {
362 248 "cell_type": "markdown",
363 249 "metadata": {},
364 250 "source": [
365 251 "```javascript\n",
366 252 "\n",
367 253 "var label = jQuery('<label/>').text('AutoScroll Limit:');\n",
368 254 "var select = jQuery('<select/>')\n",
369 255 " //.append(jQuery('<option/>').attr('value', '2').text('2min (default)'))\n",
370 256 " .append(jQuery('<option/>').attr('value', undefined).text('disabled'))\n",
371 257 "\n",
372 258 " // TODO:\n",
373 259 " //the_toolbar_element.append(label)\n",
374 260 " //the_toolbar_element.append(select);\n",
375 261 " \n",
376 262 "select.change(function() {\n",
377 263 " var val = jQuery(this).val() // val will be the value in [2]\n",
378 264 " // TODO\n",
379 265 " // this will be called when dropdown changes\n",
380 266 "\n",
381 267 "});\n",
382 268 "\n",
383 269 "var time_m = [1,5,10,15,30];\n",
384 270 "for (var i=0; i < time_m.length; i++) {\n",
385 271 " var ts = time_m[i];\n",
386 272 " //[2] ____ this will be `val` on [1] \n",
387 273 " // | \n",
388 274 " // v \n",
389 275 " select.append($('<option/>').attr('value', ts).text(thr+'min'));\n",
390 276 " // this will fill up the dropdown `select` with\n",
391 277 " // 1 min\n",
392 278 " // 5 min\n",
393 279 " // 10 min\n",
394 280 " // 10 min\n",
395 281 " // ...\n",
396 282 "}\n",
397 283 "```"
398 284 ]
399 285 },
400 286 {
401 287 "cell_type": "markdown",
402 288 "metadata": {},
403 289 "source": [
404 290 "#### A non interactive example first"
405 291 ]
406 292 },
407 293 {
408 294 "cell_type": "markdown",
409 295 "metadata": {},
410 296 "source": [
411 297 "I like my cython to be nicely highlighted\n",
412 298 "\n",
413 299 "```javascript\n",
414 300 "IPython.config.cell_magic_highlight['magic_text/x-cython'] = {}\n",
415 301 "IPython.config.cell_magic_highlight['magic_text/x-cython'].reg = [/^%%cython/]\n",
416 302 "```\n",
417 303 "\n",
418 304 "`text/x-cython` is the name of CodeMirror mode name, `magic_` prefix will just patch the mode so that the first line that contains a magic does not screw up the highlighting. `reg`is a list or regular expression that will trigger the change of mode."
419 305 ]
420 306 },
421 307 {
422 308 "cell_type": "markdown",
423 309 "metadata": {},
424 310 "source": [
425 311 "#### Get more docs"
426 312 ]
427 313 },
428 314 {
429 315 "cell_type": "markdown",
430 316 "metadata": {},
431 317 "source": [
432 318 "Sadly you will have to read the js source file (but there are lots of comments) an/or build the javascript documentation using yuidoc.\n",
433 319 "If you have `node` and `yui-doc` installed:"
434 320 ]
435 321 },
436 322 {
437 323 "cell_type": "markdown",
438 324 "metadata": {},
439 325 "source": [
440 326 "```bash\n",
441 327 "$ cd ~/ipython/IPython/html/static/notebook/js/\n",
442 328 "$ yuidoc . --server\n",
443 329 "warn: (yuidoc): Failed to extract port, setting to the default :3000\n",
444 330 "info: (yuidoc): Starting YUIDoc@0.3.45 using YUI@3.9.1 with NodeJS@0.10.15\n",
445 331 "info: (yuidoc): Scanning for yuidoc.json file.\n",
446 332 "info: (yuidoc): Starting YUIDoc with the following options:\n",
447 333 "info: (yuidoc):\n",
448 334 "{ port: 3000,\n",
449 335 " nocode: false,\n",
450 336 " paths: [ '.' ],\n",
451 337 " server: true,\n",
452 338 " outdir: './out' }\n",
453 339 "info: (yuidoc): Scanning for yuidoc.json file.\n",
454 340 "info: (server): Starting server: http://127.0.0.1:3000\n",
455 341 "```\n",
456 342 "\n",
457 343 "and browse http://127.0.0.1:3000 to get docs"
458 344 ]
459 345 },
460 346 {
461 347 "cell_type": "markdown",
462 348 "metadata": {
463 349 "foo": true
464 350 },
465 351 "source": [
466 352 "#### Some convenience methods"
467 353 ]
468 354 },
469 355 {
470 356 "cell_type": "markdown",
471 357 "metadata": {},
472 358 "source": [
473 359 "By browsing the doc you will see that we have soem convenience methods that avoid to re-invent the UI everytime :\n",
474 360 "```javascript\n",
475 361 "IPython.toolbar.add_buttons_group([\n",
476 362 " {\n",
477 363 " 'label' : 'run qtconsole',\n",
478 364 " 'icon' : 'icon-terminal', // select your icon from \n",
479 365 " // http://fortawesome.github.io/Font-Awesome/icons/\n",
480 366 " 'callback': function(){IPython.notebook.kernel.execute('%qtconsole')}\n",
481 367 " }\n",
482 368 " // add more button here if needed.\n",
483 369 " ]);\n",
484 370 "```\n",
485 371 "with a [lot of icons] you can select from. \n",
486 372 "\n",
487 373 "[lot of icons]: http://fortawesome.github.io/Font-Awesome/icons/"
488 374 ]
489 375 },
490 376 {
491 377 "cell_type": "markdown",
492 378 "metadata": {
493 379 "foo": true
494 380 },
495 381 "source": [
496 382 "## Cell Metadata"
497 383 ]
498 384 },
499 385 {
500 386 "cell_type": "markdown",
501 387 "metadata": {
502 388 "foo": true
503 389 },
504 390 "source": [
505 391 "The most requested feature is generaly to be able to distinguish individual cell in th enotebook, or run specific action with them.\n",
506 392 "To do so, you can either use `IPython.notebook.get_selected_cell()`, or rely on `CellToolbar`. This allow you to register aset of action and graphical element that will be attached on individual cells."
507 393 ]
508 394 },
509 395 {
510 396 "cell_type": "markdown",
511 397 "metadata": {},
512 398 "source": [
513 399 "### Cell Toolbar"
514 400 ]
515 401 },
516 402 {
517 403 "cell_type": "markdown",
518 404 "metadata": {},
519 405 "source": [
520 406 "You can see some example of what can be done by toggling the `Cell Toolbar` selector in the toolbar on top of the notebook. It provide two default `presets` that are `Default` and `slideshow`. Default allow edit the metadata attached to each cell manually."
521 407 ]
522 408 },
523 409 {
524 410 "cell_type": "markdown",
525 411 "metadata": {},
526 412 "source": [
527 413 "First we define a function that takes at first parameter an element on the DOM in which to inject UI element. Second element will be the cell this element will be registerd with. Then we will need to register that function ad give it a name.\n"
528 414 ]
529 415 },
530 416 {
531 417 "cell_type": "markdown",
532 418 "metadata": {},
533 419 "source": [
534 420 "#### Register a callback"
535 421 ]
536 422 },
537 423 {
538 424 "cell_type": "code",
539 "execution_count": 51,
425 "execution_count": null,
540 426 "metadata": {
541 427 "collapsed": false
542 428 },
543 "outputs": [
544 {
545 "data": {
546 "application/javascript": [
547 "var CellToolbar = IPython.CellToolbar\n",
548 "var toggle = function(div, cell) {\n",
549 " var button_container = $(div)\n",
550 "\n",
551 " // let's create a button that show the current value of the metadata\n",
552 " var button = $('<button/>').addClass('btn btn-mini').text(String(cell.metadata.foo));\n",
553 "\n",
554 " // On click, change the metadata value and update the button label\n",
555 " button.click(function(){\n",
556 " var v = cell.metadata.foo;\n",
557 " cell.metadata.foo = !v;\n",
558 " button.text(String(!v));\n",
559 " })\n",
560 "\n",
561 " // add the button to the DOM div.\n",
562 " button_container.append(button);\n",
563 "}\n",
564 "\n",
565 " // now we register the callback under the name foo to give the\n",
566 " // user the ability to use it later\n",
567 " CellToolbar.register_callback('tuto.foo', toggle);"
568 ],
569 "text/plain": [
570 "<IPython.core.display.Javascript at 0x10c94a590>"
571 ]
572 },
573 "metadata": {},
574 "output_type": "display_data"
575 }
576 ],
429 "outputs": [],
577 430 "source": [
578 431 "%%javascript\n",
579 432 "var CellToolbar = IPython.CellToolbar\n",
580 433 "var toggle = function(div, cell) {\n",
581 434 " var button_container = $(div)\n",
582 435 "\n",
583 436 " // let's create a button that show the current value of the metadata\n",
584 437 " var button = $('<button/>').addClass('btn btn-mini').text(String(cell.metadata.foo));\n",
585 438 "\n",
586 439 " // On click, change the metadata value and update the button label\n",
587 440 " button.click(function(){\n",
588 441 " var v = cell.metadata.foo;\n",
589 442 " cell.metadata.foo = !v;\n",
590 443 " button.text(String(!v));\n",
591 444 " })\n",
592 445 "\n",
593 446 " // add the button to the DOM div.\n",
594 447 " button_container.append(button);\n",
595 448 "}\n",
596 449 "\n",
597 450 " // now we register the callback under the name foo to give the\n",
598 451 " // user the ability to use it later\n",
599 452 " CellToolbar.register_callback('tuto.foo', toggle);"
600 453 ]
601 454 },
602 455 {
603 456 "cell_type": "markdown",
604 457 "metadata": {},
605 458 "source": [
606 459 "#### Registering a preset"
607 460 ]
608 461 },
609 462 {
610 463 "cell_type": "markdown",
611 464 "metadata": {},
612 465 "source": [
613 466 "This function can now be part of many `preset` of the CellToolBar."
614 467 ]
615 468 },
616 469 {
617 470 "cell_type": "code",
618 "execution_count": 54,
471 "execution_count": null,
619 472 "metadata": {
620 473 "collapsed": false,
621 474 "foo": true,
622 475 "slideshow": {
623 476 "slide_type": "subslide"
624 477 }
625 478 },
626 "outputs": [
627 {
628 "data": {
629 "application/javascript": [
630 "IPython.CellToolbar.register_preset('Tutorial 1',['tuto.foo','default.rawedit'])\n",
631 "IPython.CellToolbar.register_preset('Tutorial 2',['slideshow.select','tuto.foo'])"
632 ],
633 "text/plain": [
634 "<IPython.core.display.Javascript at 0x10c94a510>"
635 ]
636 },
637 "metadata": {},
638 "output_type": "display_data"
639 }
640 ],
479 "outputs": [],
641 480 "source": [
642 481 "%%javascript\n",
643 482 "IPython.CellToolbar.register_preset('Tutorial 1',['tuto.foo','default.rawedit'])\n",
644 483 "IPython.CellToolbar.register_preset('Tutorial 2',['slideshow.select','tuto.foo'])"
645 484 ]
646 485 },
647 486 {
648 487 "cell_type": "markdown",
649 488 "metadata": {},
650 489 "source": [
651 490 "You should now have access to two presets :\n",
652 491 "\n",
653 492 " - Tutorial 1\n",
654 493 " - Tutorial 2\n",
655 494 " \n",
656 495 "And check that the buttons you defin share state when you toggle preset. \n",
657 496 "Check moreover that the metadata of the cell is modified when you clisk the button, and that when saved on reloaded the metadata is still availlable."
658 497 ]
659 498 },
660 499 {
661 500 "cell_type": "markdown",
662 501 "metadata": {},
663 502 "source": [
664 503 "#### Exercise:"
665 504 ]
666 505 },
667 506 {
668 507 "cell_type": "markdown",
669 508 "metadata": {},
670 509 "source": [
671 510 "Try to wrap the all code in a file, put this file in `{profile}/static/custom/<a-name>.js`, and add \n",
672 511 "\n",
673 512 "```\n",
674 513 "require(['custom/<a-name>']);\n",
675 514 "```\n",
676 515 "\n",
677 516 "in `custom.js` to have this script automatically loaded in all your notebooks.\n",
678 517 "\n"
679 518 ]
680 519 },
681 520 {
682 521 "cell_type": "markdown",
683 522 "metadata": {},
684 523 "source": [
685 524 "`require` is provided by a [javascript library](http://requirejs.org/) that allow to express dependency. For simple extension like the previous one we directly mute the global namespace, but for more complexe extension you could pass acallback to `require([...], <callback>)` call, to allow the user to pass configuration information to your plugin.\n",
686 525 "\n",
687 526 "In Python lang, \n",
688 527 "\n",
689 528 "```javascript\n",
690 529 "require(['a/b', 'c/d'], function( e, f){\n",
691 530 " e.something()\n",
692 531 " f.something()\n",
693 532 "})\n",
694 533 "```\n",
695 534 "\n",
696 535 "could be read as\n",
697 536 "```python\n",
698 537 "import a.b as e\n",
699 538 "import c.d as f\n",
700 539 "e.something()\n",
701 540 "f.something()\n",
702 541 "```\n",
703 542 "\n",
704 543 "\n",
705 544 "See for example @damianavila [\"ZenMode\" plugin](https://github.com/ipython-contrib/IPython-notebook-extensions/blob/master/custom.example.js#L34) :\n",
706 545 "\n",
707 546 "```javascript\n",
708 547 "\n",
709 548 "// read that as\n",
710 549 "// import custom.zenmode.main as zenmode\n",
711 550 "require(['custom/zenmode/main'],function(zenmode){\n",
712 551 " zenmode.background('images/back12.jpg');\n",
713 552 "})\n",
714 553 "```\n"
715 554 ]
716 555 },
717 556 {
718 557 "cell_type": "markdown",
719 558 "metadata": {},
720 559 "source": [
721 560 "#### For the quickest"
722 561 ]
723 562 },
724 563 {
725 564 "cell_type": "markdown",
726 565 "metadata": {},
727 566 "source": [
728 567 "Try to use [the following](https://github.com/ipython/ipython/blob/1.x/IPython/html/static/notebook/js/celltoolbar.js#L367) to bind a dropdown list to `cell.metadata.difficulty.select`. \n",
729 568 "\n",
730 569 "It should be able to take the 4 following values :\n",
731 570 "\n",
732 571 " - `<None>`\n",
733 572 " - `Easy`\n",
734 573 " - `Medium`\n",
735 574 " - `Hard`\n",
736 575 " \n",
737 576 "We will use it to customise the output of the converted notebook depending of the tag on each cell"
738 577 ]
739 578 },
740 579 {
741 580 "cell_type": "code",
742 581 "execution_count": null,
743 582 "metadata": {
744 583 "collapsed": false
745 584 },
746 585 "outputs": [],
747 586 "source": [
748 587 "%load soln/celldiff.js"
749 588 ]
750 589 }
751 590 ],
752 591 "metadata": {
753 592 "kernelspec": {
754 593 "display_name": "Python 3",
755 594 "language": "python",
756 595 "name": "python3"
757 596 },
758 597 "language_info": {
759 598 "codemirror_mode": {
760 599 "name": "ipython",
761 600 "version": 3
762 601 },
763 602 "file_extension": ".py",
764 603 "mimetype": "text/x-python",
765 604 "name": "python",
766 605 "nbconvert_exporter": "python",
767 606 "pygments_lexer": "ipython3",
768 "version": "3.4.2"
607 "version": "3.4.3"
769 608 }
770 609 },
771 610 "nbformat": 4,
772 611 "nbformat_minor": 0
773 612 }
@@ -1,256 +1,313 b''
1 1 {
2 2 "cells": [
3 3 {
4 4 "cell_type": "markdown",
5 5 "metadata": {},
6 6 "source": [
7 7 "# Notebook Basics"
8 8 ]
9 9 },
10 10 {
11 11 "cell_type": "markdown",
12 12 "metadata": {},
13 13 "source": [
14 "This notebook assumes that you already have IPython [installed](http://ipython.org/install.html) and are able to start the notebook server by running:\n",
14 "## Running the Notebook Server"
15 ]
16 },
17 {
18 "cell_type": "markdown",
19 "metadata": {},
20 "source": [
21 "The IPython notebook server is a custom web server that runs the notebook web application. Most of the time, users run the notebook server on their local computer using IPython's command line interface."
22 ]
23 },
24 {
25 "cell_type": "markdown",
26 "metadata": {},
27 "source": [
28 "### Starting the notebook server using the command line"
29 ]
30 },
31 {
32 "cell_type": "markdown",
33 "metadata": {},
34 "source": [
35 "You can start the notebook server from the command line (Terminal on Mac/Linux, CMD prompt on Windows) by running the following command: \n",
15 36 "\n",
16 37 " ipython notebook\n",
17 38 "\n",
18 "For more details on how to run the notebook server, see [Running the Notebook Server](Running the Notebook Server.ipynb)."
39 "This will print some information about the notebook server in your terminal, including the URL of the web application (by default, `http://127.0.0.1:8888`). It will then open your default web browser to this URL.\n",
40 "\n",
41 "When the notebook opens, you will see the **notebook dashboard**, which will show a list of the notebooks and subdirectories in the directory where the notebook server was started (as seen in the next section, below). Most of the time, you will want to start a notebook server in the highest directory in your filesystem where notebooks can be found. Often this will be your home directory."
19 42 ]
20 43 },
21 44 {
22 45 "cell_type": "markdown",
23 46 "metadata": {},
24 47 "source": [
25 "## The Notebook dashboard"
48 "### Additional options"
26 49 ]
27 50 },
28 51 {
29 52 "cell_type": "markdown",
30 53 "metadata": {},
31 54 "source": [
32 "When you first start the notebook server, your browser will open to the notebook dashboard. The dashboard serves as a home page for the notebook. Its main purpose is to display the notebooks in the current directory. For example, here is a screenshot of the dashboard page for the `examples` directory in the IPython repository:\n",
55 "You can start more than one notebook server at the same time. By default, the first notebook server starts on port 8888 and later notebook servers search for open ports near that one.\n",
33 56 "\n",
34 "<img src=\"images/dashboard_notebooks_tab.png\" />\n",
57 "You can also specify the port manually:\n",
35 58 "\n",
36 "The top of the notebook list displays clickable breadcrumbs of the current directory. By clicking on these breadcrumbs or on sub-directories in the notebook list, you can navigate your file system.\n",
59 " ipython notebook --port 9999\n",
37 60 "\n",
38 "To create a new notebook, click on the \"New Notebook\" button at the top of the list.\n",
61 "Or start notebook server without opening a web browser.\n",
39 62 "\n",
40 "Notebooks can be uploaded to the current directory by dragging a notebook file onto the notebook list or by the \"click here\" text above the list.\n",
63 " ipython notebook --no-browser\n",
41 64 "\n",
42 "The notebook list shows a red \"Shutdown\" button for running notebooks and a \"Delete\" button for stopped notebooks. Notebook remain running until you explicitly click the \"Shutdown\" button; closing the notebook's page is not sufficient.\n",
65 "The notebook server has a number of other command line arguments that can be displayed with the `--help` flag: \n",
43 66 "\n",
44 "To see all of your running notebooks along with their directories, click on the \"Running\" tab:\n",
67 " ipython notebook --help"
68 ]
69 },
70 {
71 "cell_type": "markdown",
72 "metadata": {},
73 "source": [
74 "## The Notebook dashboard"
75 ]
76 },
77 {
78 "cell_type": "markdown",
79 "metadata": {},
80 "source": [
81 "When you first start the notebook server, your browser will open to the notebook dashboard. The dashboard serves as a home page for the notebook. Its main purpose is to display the notebooks and files in the current directory. For example, here is a screenshot of the dashboard page for the `examples` directory in the IPython repository:\n",
82 "\n",
83 "<img src=\"images/dashboard_files_tab.png\" width=\"791px\"/>"
84 ]
85 },
86 {
87 "cell_type": "markdown",
88 "metadata": {},
89 "source": [
90 "The top of the notebook list displays clickable breadcrumbs of the current directory. By clicking on these breadcrumbs or on sub-directories in the notebook list, you can navigate your file system.\n",
45 91 "\n",
46 "<img src=\"images/dashboard_running_tab.png\" />\n",
92 "To create a new notebook, click on the \"New\" button at the top of the list and select a kernel from the dropdown (as seen below). Which kernels are listed depend on what's installed on the server. Some of the kernels in the screenshot below may not exist as an option to you.\n",
47 93 "\n",
48 "This view provides a convenient way to track notebooks that you start as you navigate the file system in a long running notebook server."
94 "<img src=\"images/dashboard_files_tab_new.png\" width=\"202px\" />"
49 95 ]
50 96 },
51 97 {
52 98 "cell_type": "markdown",
53 99 "metadata": {},
54 100 "source": [
55 "## Overview of the Notebook UI"
101 "Notebooks and files can be uploaded to the current directory by dragging a notebook file onto the notebook list or by the \"click here\" text above the list.\n",
102 "\n",
103 "The notebook list shows green \"Running\" text and a green notebook icon next to running notebooks (as seen below). Notebooks remain running until you explicitly shut them down; closing the notebook's page is not sufficient.\n",
104 "\n",
105 "<img src=\"images/dashboard_files_tab_run.png\" width=\"777px\"/>"
56 106 ]
57 107 },
58 108 {
59 109 "cell_type": "markdown",
60 110 "metadata": {},
61 111 "source": [
62 "<div class=\"alert\">\n",
63 "As of IPython 2.0, the user interface has changed significantly. Because of this we highly recommend existing users to review this information after upgrading to IPython 2.0. All new users of IPython should review this information as well.\n",
64 "</div>"
112 "To shutdown, delete, duplicate, or rename a notebook check the checkbox next to it and an array of controls will appear at the top of the notebook list (as seen below). You can also use the same operations on directories and files when applicable.\n",
113 "\n",
114 "<img src=\"images/dashboard_files_tab_btns.png\" width=\"301px\" />"
115 ]
116 },
117 {
118 "cell_type": "markdown",
119 "metadata": {},
120 "source": [
121 "To see all of your running notebooks along with their directories, click on the \"Running\" tab:\n",
122 "\n",
123 "<img src=\"images/dashboard_running_tab.png\" width=\"786px\" />\n",
124 "\n",
125 "This view provides a convenient way to track notebooks that you start as you navigate the file system in a long running notebook server."
126 ]
127 },
128 {
129 "cell_type": "markdown",
130 "metadata": {},
131 "source": [
132 "## Overview of the Notebook UI"
65 133 ]
66 134 },
67 135 {
68 136 "cell_type": "markdown",
69 137 "metadata": {},
70 138 "source": [
71 139 "If you create a new notebook or open an existing one, you will be taken to the notebook user interface (UI). This UI allows you to run code and author notebook documents interactively. The notebook UI has the following main areas:\n",
72 140 "\n",
73 141 "* Menu\n",
74 142 "* Toolbar\n",
75 143 "* Notebook area and cells\n",
76 144 "\n",
77 "IPython 2.0 has an interactive tour of these elements that can be started in the \"Help:User Interface Tour\" menu item."
145 "The notebook has an interactive tour of these elements that can be started in the \"Help:User Interface Tour\" menu item."
78 146 ]
79 147 },
80 148 {
81 149 "cell_type": "markdown",
82 150 "metadata": {},
83 151 "source": [
84 152 "## Modal editor"
85 153 ]
86 154 },
87 155 {
88 156 "cell_type": "markdown",
89 157 "metadata": {},
90 158 "source": [
91 159 "Starting with IPython 2.0, the IPython Notebook has a modal user interface. This means that the keyboard does different things depending on which mode the Notebook is in. There are two modes: edit mode and command mode."
92 160 ]
93 161 },
94 162 {
95 163 "cell_type": "markdown",
96 164 "metadata": {},
97 165 "source": [
98 166 "### Edit mode"
99 167 ]
100 168 },
101 169 {
102 170 "cell_type": "markdown",
103 171 "metadata": {},
104 172 "source": [
105 173 "Edit mode is indicated by a green cell border and a prompt showing in the editor area:\n",
106 174 "\n",
107 175 "<img src=\"images/edit_mode.png\">\n",
108 176 "\n",
109 177 "When a cell is in edit mode, you can type into the cell, like a normal text editor."
110 178 ]
111 179 },
112 180 {
113 181 "cell_type": "markdown",
114 182 "metadata": {},
115 183 "source": [
116 184 "<div class=\"alert alert-success\">\n",
117 185 "Enter edit mode by pressing `Enter` or using the mouse to click on a cell's editor area.\n",
118 186 "</div>"
119 187 ]
120 188 },
121 189 {
122 190 "cell_type": "markdown",
123 191 "metadata": {},
124 192 "source": [
125 193 "### Command mode"
126 194 ]
127 195 },
128 196 {
129 197 "cell_type": "markdown",
130 198 "metadata": {},
131 199 "source": [
132 200 "Command mode is indicated by a grey cell border:\n",
133 201 "\n",
134 202 "<img src=\"images/command_mode.png\">\n",
135 203 "\n",
136 204 "When you are in command mode, you are able to edit the notebook as a whole, but not type into individual cells. Most importantly, in command mode, the keyboard is mapped to a set of shortcuts that let you perform notebook and cell actions efficiently. For example, if you are in command mode and you press `c`, you will copy the current cell - no modifier is needed."
137 205 ]
138 206 },
139 207 {
140 208 "cell_type": "markdown",
141 209 "metadata": {},
142 210 "source": [
143 211 "<div class=\"alert alert-error\">\n",
144 212 "Don't try to type into a cell in command mode; unexpected things will happen!\n",
145 213 "</div>"
146 214 ]
147 215 },
148 216 {
149 217 "cell_type": "markdown",
150 218 "metadata": {},
151 219 "source": [
152 220 "<div class=\"alert alert-success\">\n",
153 221 "Enter command mode by pressing `Esc` or using the mouse to click *outside* a cell's editor area.\n",
154 222 "</div>"
155 223 ]
156 224 },
157 225 {
158 226 "cell_type": "markdown",
159 227 "metadata": {},
160 228 "source": [
161 229 "## Mouse navigation"
162 230 ]
163 231 },
164 232 {
165 233 "cell_type": "markdown",
166 234 "metadata": {},
167 235 "source": [
168 236 "All navigation and actions in the Notebook are available using the mouse through the menubar and toolbar, which are both above the main Notebook area:\n",
169 237 "\n",
170 "<img src=\"images/menubar_toolbar.png\">"
238 "<img src=\"images/menubar_toolbar.png\" width=\"786px\" />"
171 239 ]
172 240 },
173 241 {
174 242 "cell_type": "markdown",
175 243 "metadata": {},
176 244 "source": [
177 245 "The first idea of mouse based navigation is that **cells can be selected by clicking on them.** The currently selected cell gets a grey or green border depending on whether the notebook is in edit or command mode. If you click inside a cell's editor area, you will enter edit mode. If you click on the prompt or output area of a cell you will enter command mode.\n",
178 246 "\n",
179 247 "If you are running this notebook in a live session (not on http://nbviewer.ipython.org) try selecting different cells and going between edit and command mode. Try typing into a cell."
180 248 ]
181 249 },
182 250 {
183 251 "cell_type": "markdown",
184 252 "metadata": {},
185 253 "source": [
186 254 "The second idea of mouse based navigation is that **cell actions usually apply to the currently selected cell**. Thus if you want to run the code in a cell, you would select it and click the <button class='btn btn-default btn-xs'><i class=\"fa fa-play icon-play\"></i></button> button in the toolbar or the \"Cell:Run\" menu item. Similarly, to copy a cell you would select it and click the <button class='btn btn-default btn-xs'><i class=\"fa fa-copy icon-copy\"></i></button> button in the toolbar or the \"Edit:Copy\" menu item. With this simple pattern, you should be able to do most everything you need with the mouse.\n",
187 255 "\n",
188 256 "Markdown and heading cells have one other state that can be modified with the mouse. These cells can either be rendered or unrendered. When they are rendered, you will see a nice formatted representation of the cell's contents. When they are unrendered, you will see the raw text source of the cell. To render the selected cell with the mouse, click the <button class='btn btn-default btn-xs'><i class=\"fa fa-play icon-play\"></i></button> button in the toolbar or the \"Cell:Run\" menu item. To unrender the selected cell, double click on the cell."
189 257 ]
190 258 },
191 259 {
192 260 "cell_type": "markdown",
193 261 "metadata": {},
194 262 "source": [
195 263 "## Keyboard Navigation"
196 264 ]
197 265 },
198 266 {
199 267 "cell_type": "markdown",
200 268 "metadata": {},
201 269 "source": [
202 270 "The modal user interface of the IPython Notebook has been optimized for efficient keyboard usage. This is made possible by having two different sets of keyboard shortcuts: one set that is active in edit mode and another in command mode.\n",
203 271 "\n",
204 272 "The most important keyboard shortcuts are `Enter`, which enters edit mode, and `Esc`, which enters command mode.\n",
205 273 "\n",
206 "In edit mode, most of the keyboard is dedicated to typing into the cell's editor. Thus, in edit mode there are relatively few shortcuts:\n",
207 "\n",
208 "<img src=\"images/edit_shortcuts.png\">"
209 ]
210 },
211 {
212 "cell_type": "markdown",
213 "metadata": {},
214 "source": [
215 "In command mode, the entire keyboard is available for shortcuts, so there are many more:\n",
216 "\n",
217 "<img src=\"images/command_shortcuts.png\">"
274 "In edit mode, most of the keyboard is dedicated to typing into the cell's editor. Thus, in edit mode there are relatively few shortcuts. In command mode, the entire keyboard is available for shortcuts, so there are many more. The `Help`->`Keyboard Shortcuts` dialog lists the available shortcuts."
218 275 ]
219 276 },
220 277 {
221 278 "cell_type": "markdown",
222 279 "metadata": {},
223 280 "source": [
224 281 "We recommend learning the command mode shortcuts in the following rough order:\n",
225 282 "\n",
226 283 "1. Basic navigation: `enter`, `shift-enter`, `up/k`, `down/j`\n",
227 284 "2. Saving the notebook: `s`\n",
228 285 "2. Cell types: `y`, `m`, `1-6`, `t`\n",
229 286 "3. Cell creation: `a`, `b`\n",
230 287 "4. Cell editing: `x`, `c`, `v`, `d`, `z`, `shift+=`\n",
231 288 "5. Kernel operations: `i`, `.`"
232 289 ]
233 290 }
234 291 ],
235 292 "metadata": {
236 293 "kernelspec": {
237 294 "display_name": "Python 3",
238 295 "language": "python",
239 296 "name": "python3"
240 297 },
241 298 "language_info": {
242 299 "codemirror_mode": {
243 300 "name": "ipython",
244 301 "version": 3
245 302 },
246 303 "file_extension": ".py",
247 304 "mimetype": "text/x-python",
248 305 "name": "python",
249 306 "nbconvert_exporter": "python",
250 307 "pygments_lexer": "ipython3",
251 "version": "3.4.2"
308 "version": "3.4.3"
252 309 }
253 310 },
254 311 "nbformat": 4,
255 312 "nbformat_minor": 0
256 313 }
This diff has been collapsed as it changes many lines, (631 lines changed) Show them Hide them
@@ -1,892 +1,289 b''
1 1 {
2 2 "cells": [
3 3 {
4 4 "cell_type": "markdown",
5 5 "metadata": {},
6 6 "source": [
7 7 "# Running Code"
8 8 ]
9 9 },
10 10 {
11 11 "cell_type": "markdown",
12 12 "metadata": {},
13 13 "source": [
14 14 "First and foremost, the IPython Notebook is an interactive environment for writing and running code. IPython is capable of running code in a wide range of languages. However, this notebook, and the default kernel in IPython 2.0, runs Python code."
15 15 ]
16 16 },
17 17 {
18 18 "cell_type": "markdown",
19 19 "metadata": {},
20 20 "source": [
21 21 "## Code cells allow you to enter and run Python code"
22 22 ]
23 23 },
24 24 {
25 25 "cell_type": "markdown",
26 26 "metadata": {},
27 27 "source": [
28 28 "Run a code cell using `Shift-Enter` or pressing the <button class='btn btn-default btn-xs'><i class=\"icon-play fa fa-play\"></i></button> button in the toolbar above:"
29 29 ]
30 30 },
31 31 {
32 32 "cell_type": "code",
33 "execution_count": 1,
33 "execution_count": null,
34 34 "metadata": {
35 35 "collapsed": false
36 36 },
37 37 "outputs": [],
38 38 "source": [
39 39 "a = 10"
40 40 ]
41 41 },
42 42 {
43 43 "cell_type": "code",
44 "execution_count": 2,
44 "execution_count": null,
45 45 "metadata": {
46 46 "collapsed": false
47 47 },
48 "outputs": [
49 {
50 "name": "stdout",
51 "output_type": "stream",
52 "text": [
53 "10\n"
54 ]
55 }
56 ],
48 "outputs": [],
57 49 "source": [
58 50 "print(a)"
59 51 ]
60 52 },
61 53 {
62 54 "cell_type": "markdown",
63 55 "metadata": {},
64 56 "source": [
65 57 "There are two other keyboard shortcuts for running code:\n",
66 58 "\n",
67 59 "* `Alt-Enter` runs the current cell and inserts a new one below.\n",
68 60 "* `Ctrl-Enter` run the current cell and enters command mode."
69 61 ]
70 62 },
71 63 {
72 64 "cell_type": "markdown",
73 65 "metadata": {},
74 66 "source": [
75 67 "## Managing the IPython Kernel"
76 68 ]
77 69 },
78 70 {
79 71 "cell_type": "markdown",
80 72 "metadata": {},
81 73 "source": [
82 74 "Code is run in a separate process called the IPython Kernel. The Kernel can be interrupted or restarted. Try running the following cell and then hit the <button class='btn btn-default btn-xs'><i class='icon-stop fa fa-stop'></i></button> button in the toolbar above."
83 75 ]
84 76 },
85 77 {
86 78 "cell_type": "code",
87 79 "execution_count": null,
88 80 "metadata": {
89 81 "collapsed": false
90 82 },
91 83 "outputs": [],
92 84 "source": [
93 85 "import time\n",
94 86 "time.sleep(10)"
95 87 ]
96 88 },
97 89 {
98 90 "cell_type": "markdown",
99 91 "metadata": {},
100 92 "source": [
101 93 "If the Kernel dies you will be prompted to restart it. Here we call the low-level system libc.time routine with the wrong argument via\n",
102 94 "ctypes to segfault the Python interpreter:"
103 95 ]
104 96 },
105 97 {
106 98 "cell_type": "code",
107 99 "execution_count": null,
108 100 "metadata": {
109 101 "collapsed": false
110 102 },
111 103 "outputs": [],
112 104 "source": [
113 105 "import sys\n",
114 106 "from ctypes import CDLL\n",
115 107 "# This will crash a Linux or Mac system\n",
116 108 "# equivalent calls can be made on Windows\n",
117 109 "dll = 'dylib' if sys.platform == 'darwin' else 'so.6'\n",
118 110 "libc = CDLL(\"libc.%s\" % dll) \n",
119 111 "libc.time(-1) # BOOM!!"
120 112 ]
121 113 },
122 114 {
123 115 "cell_type": "markdown",
124 116 "metadata": {},
125 117 "source": [
126 118 "## Cell menu"
127 119 ]
128 120 },
129 121 {
130 122 "cell_type": "markdown",
131 123 "metadata": {},
132 124 "source": [
133 125 "The \"Cell\" menu has a number of menu items for running code in different ways. These includes:\n",
134 126 "\n",
135 127 "* Run and Select Below\n",
136 128 "* Run and Insert Below\n",
137 129 "* Run All\n",
138 130 "* Run All Above\n",
139 131 "* Run All Below"
140 132 ]
141 133 },
142 134 {
143 135 "cell_type": "markdown",
144 136 "metadata": {},
145 137 "source": [
146 138 "## Restarting the kernels"
147 139 ]
148 140 },
149 141 {
150 142 "cell_type": "markdown",
151 143 "metadata": {},
152 144 "source": [
153 145 "The kernel maintains the state of a notebook's computations. You can reset this state by restarting the kernel. This is done by clicking on the <button class='btn btn-default btn-xs'><i class='fa fa-repeat icon-repeat'></i></button> in the toolbar above."
154 146 ]
155 147 },
156 148 {
157 149 "cell_type": "markdown",
158 150 "metadata": {},
159 151 "source": [
160 152 "## sys.stdout and sys.stderr"
161 153 ]
162 154 },
163 155 {
164 156 "cell_type": "markdown",
165 157 "metadata": {},
166 158 "source": [
167 159 "The stdout and stderr streams are displayed as text in the output area."
168 160 ]
169 161 },
170 162 {
171 163 "cell_type": "code",
172 "execution_count": 2,
164 "execution_count": null,
173 165 "metadata": {
174 166 "collapsed": false
175 167 },
176 "outputs": [
177 {
178 "name": "stdout",
179 "output_type": "stream",
180 "text": [
181 "hi, stdout\n"
182 ]
183 }
184 ],
168 "outputs": [],
185 169 "source": [
186 170 "print(\"hi, stdout\")"
187 171 ]
188 172 },
189 173 {
190 174 "cell_type": "code",
191 "execution_count": 3,
175 "execution_count": null,
192 176 "metadata": {
193 177 "collapsed": false
194 178 },
195 "outputs": [
196 {
197 "name": "stderr",
198 "output_type": "stream",
199 "text": [
200 "hi, stderr\n"
201 ]
202 }
203 ],
179 "outputs": [],
204 180 "source": [
205 181 "from __future__ import print_function\n",
206 182 "print('hi, stderr', file=sys.stderr)"
207 183 ]
208 184 },
209 185 {
210 186 "cell_type": "markdown",
211 187 "metadata": {},
212 188 "source": [
213 189 "## Output is asynchronous"
214 190 ]
215 191 },
216 192 {
217 193 "cell_type": "markdown",
218 194 "metadata": {},
219 195 "source": [
220 196 "All output is displayed asynchronously as it is generated in the Kernel. If you execute the next cell, you will see the output one piece at a time, not all at the end."
221 197 ]
222 198 },
223 199 {
224 200 "cell_type": "code",
225 "execution_count": 4,
201 "execution_count": null,
226 202 "metadata": {
227 203 "collapsed": false
228 204 },
229 "outputs": [
230 {
231 "name": "stdout",
232 "output_type": "stream",
233 "text": [
234 "0\n",
235 "1\n",
236 "2\n",
237 "3\n",
238 "4\n",
239 "5\n",
240 "6\n",
241 "7\n"
242 ]
243 }
244 ],
205 "outputs": [],
245 206 "source": [
246 207 "import time, sys\n",
247 208 "for i in range(8):\n",
248 209 " print(i)\n",
249 210 " time.sleep(0.5)"
250 211 ]
251 212 },
252 213 {
253 214 "cell_type": "markdown",
254 215 "metadata": {},
255 216 "source": [
256 217 "## Large outputs"
257 218 ]
258 219 },
259 220 {
260 221 "cell_type": "markdown",
261 222 "metadata": {},
262 223 "source": [
263 224 "To better handle large outputs, the output area can be collapsed. Run the following cell and then single- or double- click on the active area to the left of the output:"
264 225 ]
265 226 },
266 227 {
267 228 "cell_type": "code",
268 "execution_count": 5,
229 "execution_count": null,
269 230 "metadata": {
270 231 "collapsed": false
271 232 },
272 "outputs": [
273 {
274 "name": "stdout",
275 "output_type": "stream",
276 "text": [
277 "0\n",
278 "1\n",
279 "2\n",
280 "3\n",
281 "4\n",
282 "5\n",
283 "6\n",
284 "7\n",
285 "8\n",
286 "9\n",
287 "10\n",
288 "11\n",
289 "12\n",
290 "13\n",
291 "14\n",
292 "15\n",
293 "16\n",
294 "17\n",
295 "18\n",
296 "19\n",
297 "20\n",
298 "21\n",
299 "22\n",
300 "23\n",
301 "24\n",
302 "25\n",
303 "26\n",
304 "27\n",
305 "28\n",
306 "29\n",
307 "30\n",
308 "31\n",
309 "32\n",
310 "33\n",
311 "34\n",
312 "35\n",
313 "36\n",
314 "37\n",
315 "38\n",
316 "39\n",
317 "40\n",
318 "41\n",
319 "42\n",
320 "43\n",
321 "44\n",
322 "45\n",
323 "46\n",
324 "47\n",
325 "48\n",
326 "49\n"
327 ]
328 }
329 ],
233 "outputs": [],
330 234 "source": [
331 235 "for i in range(50):\n",
332 236 " print(i)"
333 237 ]
334 238 },
335 239 {
336 240 "cell_type": "markdown",
337 241 "metadata": {},
338 242 "source": [
339 243 "Beyond a certain point, output will scroll automatically:"
340 244 ]
341 245 },
342 246 {
343 247 "cell_type": "code",
344 "execution_count": 6,
248 "execution_count": null,
345 249 "metadata": {
346 250 "collapsed": false
347 251 },
348 "outputs": [
349 {
350 "name": "stdout",
351 "output_type": "stream",
352 "text": [
353 "0\n",
354 "1\n",
355 "3\n",
356 "7\n",
357 "15\n",
358 "31\n",
359 "63\n",
360 "127\n",
361 "255\n",
362 "511\n",
363 "1023\n",
364 "2047\n",
365 "4095\n",
366 "8191\n",
367 "16383\n",
368 "32767\n",
369 "65535\n",
370 "131071\n",
371 "262143\n",
372 "524287\n",
373 "1048575\n",
374 "2097151\n",
375 "4194303\n",
376 "8388607\n",
377 "16777215\n",
378 "33554431\n",
379 "67108863\n",
380 "134217727\n",
381 "268435455\n",
382 "536870911\n",
383 "1073741823\n",
384 "2147483647\n",
385 "4294967295\n",
386 "8589934591\n",
387 "17179869183\n",
388 "34359738367\n",
389 "68719476735\n",
390 "137438953471\n",
391 "274877906943\n",
392 "549755813887\n",
393 "1099511627775\n",
394 "2199023255551\n",
395 "4398046511103\n",
396 "8796093022207\n",
397 "17592186044415\n",
398 "35184372088831\n",
399 "70368744177663\n",
400 "140737488355327\n",
401 "281474976710655\n",
402 "562949953421311\n",
403 "1125899906842623\n",
404 "2251799813685247\n",
405 "4503599627370495\n",
406 "9007199254740991\n",
407 "18014398509481983\n",
408 "36028797018963967\n",
409 "72057594037927935\n",
410 "144115188075855871\n",
411 "288230376151711743\n",
412 "576460752303423487\n",
413 "1152921504606846975\n",
414 "2305843009213693951\n",
415 "4611686018427387903\n",
416 "9223372036854775807\n",
417 "18446744073709551615\n",
418 "36893488147419103231\n",
419 "73786976294838206463\n",
420 "147573952589676412927\n",
421 "295147905179352825855\n",
422 "590295810358705651711\n",
423 "1180591620717411303423\n",
424 "2361183241434822606847\n",
425 "4722366482869645213695\n",
426 "9444732965739290427391\n",
427 "18889465931478580854783\n",
428 "37778931862957161709567\n",
429 "75557863725914323419135\n",
430 "151115727451828646838271\n",
431 "302231454903657293676543\n",
432 "604462909807314587353087\n",
433 "1208925819614629174706175\n",
434 "2417851639229258349412351\n",
435 "4835703278458516698824703\n",
436 "9671406556917033397649407\n",
437 "19342813113834066795298815\n",
438 "38685626227668133590597631\n",
439 "77371252455336267181195263\n",
440 "154742504910672534362390527\n",
441 "309485009821345068724781055\n",
442 "618970019642690137449562111\n",
443 "1237940039285380274899124223\n",
444 "2475880078570760549798248447\n",
445 "4951760157141521099596496895\n",
446 "9903520314283042199192993791\n",
447 "19807040628566084398385987583\n",
448 "39614081257132168796771975167\n",
449 "79228162514264337593543950335\n",
450 "158456325028528675187087900671\n",
451 "316912650057057350374175801343\n",
452 "633825300114114700748351602687\n",
453 "1267650600228229401496703205375\n",
454 "2535301200456458802993406410751\n",
455 "5070602400912917605986812821503\n",
456 "10141204801825835211973625643007\n",
457 "20282409603651670423947251286015\n",
458 "40564819207303340847894502572031\n",
459 "81129638414606681695789005144063\n",
460 "162259276829213363391578010288127\n",
461 "324518553658426726783156020576255\n",
462 "649037107316853453566312041152511\n",
463 "1298074214633706907132624082305023\n",
464 "2596148429267413814265248164610047\n",
465 "5192296858534827628530496329220095\n",
466 "10384593717069655257060992658440191\n",
467 "20769187434139310514121985316880383\n",
468 "41538374868278621028243970633760767\n",
469 "83076749736557242056487941267521535\n",
470 "166153499473114484112975882535043071\n",
471 "332306998946228968225951765070086143\n",
472 "664613997892457936451903530140172287\n",
473 "1329227995784915872903807060280344575\n",
474 "2658455991569831745807614120560689151\n",
475 "5316911983139663491615228241121378303\n",
476 "10633823966279326983230456482242756607\n",
477 "21267647932558653966460912964485513215\n",
478 "42535295865117307932921825928971026431\n",
479 "85070591730234615865843651857942052863\n",
480 "170141183460469231731687303715884105727\n",
481 "340282366920938463463374607431768211455\n",
482 "680564733841876926926749214863536422911\n",
483 "1361129467683753853853498429727072845823\n",
484 "2722258935367507707706996859454145691647\n",
485 "5444517870735015415413993718908291383295\n",
486 "10889035741470030830827987437816582766591\n",
487 "21778071482940061661655974875633165533183\n",
488 "43556142965880123323311949751266331066367\n",
489 "87112285931760246646623899502532662132735\n",
490 "174224571863520493293247799005065324265471\n",
491 "348449143727040986586495598010130648530943\n",
492 "696898287454081973172991196020261297061887\n",
493 "1393796574908163946345982392040522594123775\n",
494 "2787593149816327892691964784081045188247551\n",
495 "5575186299632655785383929568162090376495103\n",
496 "11150372599265311570767859136324180752990207\n",
497 "22300745198530623141535718272648361505980415\n",
498 "44601490397061246283071436545296723011960831\n",
499 "89202980794122492566142873090593446023921663\n",
500 "178405961588244985132285746181186892047843327\n",
501 "356811923176489970264571492362373784095686655\n",
502 "713623846352979940529142984724747568191373311\n",
503 "1427247692705959881058285969449495136382746623\n",
504 "2854495385411919762116571938898990272765493247\n",
505 "5708990770823839524233143877797980545530986495\n",
506 "11417981541647679048466287755595961091061972991\n",
507 "22835963083295358096932575511191922182123945983\n",
508 "45671926166590716193865151022383844364247891967\n",
509 "91343852333181432387730302044767688728495783935\n",
510 "182687704666362864775460604089535377456991567871\n",
511 "365375409332725729550921208179070754913983135743\n",
512 "730750818665451459101842416358141509827966271487\n",
513 "1461501637330902918203684832716283019655932542975\n",
514 "2923003274661805836407369665432566039311865085951\n",
515 "5846006549323611672814739330865132078623730171903\n",
516 "11692013098647223345629478661730264157247460343807\n",
517 "23384026197294446691258957323460528314494920687615\n",
518 "46768052394588893382517914646921056628989841375231\n",
519 "93536104789177786765035829293842113257979682750463\n",
520 "187072209578355573530071658587684226515959365500927\n",
521 "374144419156711147060143317175368453031918731001855\n",
522 "748288838313422294120286634350736906063837462003711\n",
523 "1496577676626844588240573268701473812127674924007423\n",
524 "2993155353253689176481146537402947624255349848014847\n",
525 "5986310706507378352962293074805895248510699696029695\n",
526 "11972621413014756705924586149611790497021399392059391\n",
527 "23945242826029513411849172299223580994042798784118783\n",
528 "47890485652059026823698344598447161988085597568237567\n",
529 "95780971304118053647396689196894323976171195136475135\n",
530 "191561942608236107294793378393788647952342390272950271\n",
531 "383123885216472214589586756787577295904684780545900543\n",
532 "766247770432944429179173513575154591809369561091801087\n",
533 "1532495540865888858358347027150309183618739122183602175\n",
534 "3064991081731777716716694054300618367237478244367204351\n",
535 "6129982163463555433433388108601236734474956488734408703\n",
536 "12259964326927110866866776217202473468949912977468817407\n",
537 "24519928653854221733733552434404946937899825954937634815\n",
538 "49039857307708443467467104868809893875799651909875269631\n",
539 "98079714615416886934934209737619787751599303819750539263\n",
540 "196159429230833773869868419475239575503198607639501078527\n",
541 "392318858461667547739736838950479151006397215279002157055\n",
542 "784637716923335095479473677900958302012794430558004314111\n",
543 "1569275433846670190958947355801916604025588861116008628223\n",
544 "3138550867693340381917894711603833208051177722232017256447\n",
545 "6277101735386680763835789423207666416102355444464034512895\n",
546 "12554203470773361527671578846415332832204710888928069025791\n",
547 "25108406941546723055343157692830665664409421777856138051583\n",
548 "50216813883093446110686315385661331328818843555712276103167\n",
549 "100433627766186892221372630771322662657637687111424552206335\n",
550 "200867255532373784442745261542645325315275374222849104412671\n",
551 "401734511064747568885490523085290650630550748445698208825343\n",
552 "803469022129495137770981046170581301261101496891396417650687\n",
553 "1606938044258990275541962092341162602522202993782792835301375\n",
554 "3213876088517980551083924184682325205044405987565585670602751\n",
555 "6427752177035961102167848369364650410088811975131171341205503\n",
556 "12855504354071922204335696738729300820177623950262342682411007\n",
557 "25711008708143844408671393477458601640355247900524685364822015\n",
558 "51422017416287688817342786954917203280710495801049370729644031\n",
559 "102844034832575377634685573909834406561420991602098741459288063\n",
560 "205688069665150755269371147819668813122841983204197482918576127\n",
561 "411376139330301510538742295639337626245683966408394965837152255\n",
562 "822752278660603021077484591278675252491367932816789931674304511\n",
563 "1645504557321206042154969182557350504982735865633579863348609023\n",
564 "3291009114642412084309938365114701009965471731267159726697218047\n",
565 "6582018229284824168619876730229402019930943462534319453394436095\n",
566 "13164036458569648337239753460458804039861886925068638906788872191\n",
567 "26328072917139296674479506920917608079723773850137277813577744383\n",
568 "52656145834278593348959013841835216159447547700274555627155488767\n",
569 "105312291668557186697918027683670432318895095400549111254310977535\n",
570 "210624583337114373395836055367340864637790190801098222508621955071\n",
571 "421249166674228746791672110734681729275580381602196445017243910143\n",
572 "842498333348457493583344221469363458551160763204392890034487820287\n",
573 "1684996666696914987166688442938726917102321526408785780068975640575\n",
574 "3369993333393829974333376885877453834204643052817571560137951281151\n",
575 "6739986666787659948666753771754907668409286105635143120275902562303\n",
576 "13479973333575319897333507543509815336818572211270286240551805124607\n",
577 "26959946667150639794667015087019630673637144422540572481103610249215\n",
578 "53919893334301279589334030174039261347274288845081144962207220498431\n",
579 "107839786668602559178668060348078522694548577690162289924414440996863\n",
580 "215679573337205118357336120696157045389097155380324579848828881993727\n",
581 "431359146674410236714672241392314090778194310760649159697657763987455\n",
582 "862718293348820473429344482784628181556388621521298319395315527974911\n",
583 "1725436586697640946858688965569256363112777243042596638790631055949823\n",
584 "3450873173395281893717377931138512726225554486085193277581262111899647\n",
585 "6901746346790563787434755862277025452451108972170386555162524223799295\n",
586 "13803492693581127574869511724554050904902217944340773110325048447598591\n",
587 "27606985387162255149739023449108101809804435888681546220650096895197183\n",
588 "55213970774324510299478046898216203619608871777363092441300193790394367\n",
589 "110427941548649020598956093796432407239217743554726184882600387580788735\n",
590 "220855883097298041197912187592864814478435487109452369765200775161577471\n",
591 "441711766194596082395824375185729628956870974218904739530401550323154943\n",
592 "883423532389192164791648750371459257913741948437809479060803100646309887\n",
593 "1766847064778384329583297500742918515827483896875618958121606201292619775\n",
594 "3533694129556768659166595001485837031654967793751237916243212402585239551\n",
595 "7067388259113537318333190002971674063309935587502475832486424805170479103\n",
596 "14134776518227074636666380005943348126619871175004951664972849610340958207\n",
597 "28269553036454149273332760011886696253239742350009903329945699220681916415\n",
598 "56539106072908298546665520023773392506479484700019806659891398441363832831\n",
599 "113078212145816597093331040047546785012958969400039613319782796882727665663\n",
600 "226156424291633194186662080095093570025917938800079226639565593765455331327\n",
601 "452312848583266388373324160190187140051835877600158453279131187530910662655\n",
602 "904625697166532776746648320380374280103671755200316906558262375061821325311\n",
603 "1809251394333065553493296640760748560207343510400633813116524750123642650623\n",
604 "3618502788666131106986593281521497120414687020801267626233049500247285301247\n",
605 "7237005577332262213973186563042994240829374041602535252466099000494570602495\n",
606 "14474011154664524427946373126085988481658748083205070504932198000989141204991\n",
607 "28948022309329048855892746252171976963317496166410141009864396001978282409983\n",
608 "57896044618658097711785492504343953926634992332820282019728792003956564819967\n",
609 "115792089237316195423570985008687907853269984665640564039457584007913129639935\n",
610 "231584178474632390847141970017375815706539969331281128078915168015826259279871\n",
611 "463168356949264781694283940034751631413079938662562256157830336031652518559743\n",
612 "926336713898529563388567880069503262826159877325124512315660672063305037119487\n",
613 "1852673427797059126777135760139006525652319754650249024631321344126610074238975\n",
614 "3705346855594118253554271520278013051304639509300498049262642688253220148477951\n",
615 "7410693711188236507108543040556026102609279018600996098525285376506440296955903\n",
616 "14821387422376473014217086081112052205218558037201992197050570753012880593911807\n",
617 "29642774844752946028434172162224104410437116074403984394101141506025761187823615\n",
618 "59285549689505892056868344324448208820874232148807968788202283012051522375647231\n",
619 "118571099379011784113736688648896417641748464297615937576404566024103044751294463\n",
620 "237142198758023568227473377297792835283496928595231875152809132048206089502588927\n",
621 "474284397516047136454946754595585670566993857190463750305618264096412179005177855\n",
622 "948568795032094272909893509191171341133987714380927500611236528192824358010355711\n",
623 "1897137590064188545819787018382342682267975428761855001222473056385648716020711423\n",
624 "3794275180128377091639574036764685364535950857523710002444946112771297432041422847\n",
625 "7588550360256754183279148073529370729071901715047420004889892225542594864082845695\n",
626 "15177100720513508366558296147058741458143803430094840009779784451085189728165691391\n",
627 "30354201441027016733116592294117482916287606860189680019559568902170379456331382783\n",
628 "60708402882054033466233184588234965832575213720379360039119137804340758912662765567\n",
629 "121416805764108066932466369176469931665150427440758720078238275608681517825325531135\n",
630 "242833611528216133864932738352939863330300854881517440156476551217363035650651062271\n",
631 "485667223056432267729865476705879726660601709763034880312953102434726071301302124543\n",
632 "971334446112864535459730953411759453321203419526069760625906204869452142602604249087\n",
633 "1942668892225729070919461906823518906642406839052139521251812409738904285205208498175\n",
634 "3885337784451458141838923813647037813284813678104279042503624819477808570410416996351\n",
635 "7770675568902916283677847627294075626569627356208558085007249638955617140820833992703\n",
636 "15541351137805832567355695254588151253139254712417116170014499277911234281641667985407\n",
637 "31082702275611665134711390509176302506278509424834232340028998555822468563283335970815\n",
638 "62165404551223330269422781018352605012557018849668464680057997111644937126566671941631\n",
639 "124330809102446660538845562036705210025114037699336929360115994223289874253133343883263\n",
640 "248661618204893321077691124073410420050228075398673858720231988446579748506266687766527\n",
641 "497323236409786642155382248146820840100456150797347717440463976893159497012533375533055\n",
642 "994646472819573284310764496293641680200912301594695434880927953786318994025066751066111\n",
643 "1989292945639146568621528992587283360401824603189390869761855907572637988050133502132223\n",
644 "3978585891278293137243057985174566720803649206378781739523711815145275976100267004264447\n",
645 "7957171782556586274486115970349133441607298412757563479047423630290551952200534008528895\n",
646 "15914343565113172548972231940698266883214596825515126958094847260581103904401068017057791\n",
647 "31828687130226345097944463881396533766429193651030253916189694521162207808802136034115583\n",
648 "63657374260452690195888927762793067532858387302060507832379389042324415617604272068231167\n",
649 "127314748520905380391777855525586135065716774604121015664758778084648831235208544136462335\n",
650 "254629497041810760783555711051172270131433549208242031329517556169297662470417088272924671\n",
651 "509258994083621521567111422102344540262867098416484062659035112338595324940834176545849343\n",
652 "1018517988167243043134222844204689080525734196832968125318070224677190649881668353091698687\n",
653 "2037035976334486086268445688409378161051468393665936250636140449354381299763336706183397375\n",
654 "4074071952668972172536891376818756322102936787331872501272280898708762599526673412366794751\n",
655 "8148143905337944345073782753637512644205873574663745002544561797417525199053346824733589503\n",
656 "16296287810675888690147565507275025288411747149327490005089123594835050398106693649467179007\n",
657 "32592575621351777380295131014550050576823494298654980010178247189670100796213387298934358015\n",
658 "65185151242703554760590262029100101153646988597309960020356494379340201592426774597868716031\n",
659 "130370302485407109521180524058200202307293977194619920040712988758680403184853549195737432063\n",
660 "260740604970814219042361048116400404614587954389239840081425977517360806369707098391474864127\n",
661 "521481209941628438084722096232800809229175908778479680162851955034721612739414196782949728255\n",
662 "1042962419883256876169444192465601618458351817556959360325703910069443225478828393565899456511\n",
663 "2085924839766513752338888384931203236916703635113918720651407820138886450957656787131798913023\n",
664 "4171849679533027504677776769862406473833407270227837441302815640277772901915313574263597826047\n",
665 "8343699359066055009355553539724812947666814540455674882605631280555545803830627148527195652095\n",
666 "16687398718132110018711107079449625895333629080911349765211262561111091607661254297054391304191\n",
667 "33374797436264220037422214158899251790667258161822699530422525122222183215322508594108782608383\n",
668 "66749594872528440074844428317798503581334516323645399060845050244444366430645017188217565216767\n",
669 "133499189745056880149688856635597007162669032647290798121690100488888732861290034376435130433535\n",
670 "266998379490113760299377713271194014325338065294581596243380200977777465722580068752870260867071\n",
671 "533996758980227520598755426542388028650676130589163192486760401955554931445160137505740521734143\n",
672 "1067993517960455041197510853084776057301352261178326384973520803911109862890320275011481043468287\n",
673 "2135987035920910082395021706169552114602704522356652769947041607822219725780640550022962086936575\n",
674 "4271974071841820164790043412339104229205409044713305539894083215644439451561281100045924173873151\n",
675 "8543948143683640329580086824678208458410818089426611079788166431288878903122562200091848347746303\n",
676 "17087896287367280659160173649356416916821636178853222159576332862577757806245124400183696695492607\n",
677 "34175792574734561318320347298712833833643272357706444319152665725155515612490248800367393390985215\n",
678 "68351585149469122636640694597425667667286544715412888638305331450311031224980497600734786781970431\n",
679 "136703170298938245273281389194851335334573089430825777276610662900622062449960995201469573563940863\n",
680 "273406340597876490546562778389702670669146178861651554553221325801244124899921990402939147127881727\n",
681 "546812681195752981093125556779405341338292357723303109106442651602488249799843980805878294255763455\n",
682 "1093625362391505962186251113558810682676584715446606218212885303204976499599687961611756588511526911\n",
683 "2187250724783011924372502227117621365353169430893212436425770606409952999199375923223513177023053823\n",
684 "4374501449566023848745004454235242730706338861786424872851541212819905998398751846447026354046107647\n",
685 "8749002899132047697490008908470485461412677723572849745703082425639811996797503692894052708092215295\n",
686 "17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430591\n",
687 "34996011596528190789960035633881941845650710894291398982812329702559247987190014771576210832368861183\n",
688 "69992023193056381579920071267763883691301421788582797965624659405118495974380029543152421664737722367\n",
689 "139984046386112763159840142535527767382602843577165595931249318810236991948760059086304843329475444735\n",
690 "279968092772225526319680285071055534765205687154331191862498637620473983897520118172609686658950889471\n",
691 "559936185544451052639360570142111069530411374308662383724997275240947967795040236345219373317901778943\n",
692 "1119872371088902105278721140284222139060822748617324767449994550481895935590080472690438746635803557887\n",
693 "2239744742177804210557442280568444278121645497234649534899989100963791871180160945380877493271607115775\n",
694 "4479489484355608421114884561136888556243290994469299069799978201927583742360321890761754986543214231551\n",
695 "8958978968711216842229769122273777112486581988938598139599956403855167484720643781523509973086428463103\n",
696 "17917957937422433684459538244547554224973163977877196279199912807710334969441287563047019946172856926207\n",
697 "35835915874844867368919076489095108449946327955754392558399825615420669938882575126094039892345713852415\n",
698 "71671831749689734737838152978190216899892655911508785116799651230841339877765150252188079784691427704831\n",
699 "143343663499379469475676305956380433799785311823017570233599302461682679755530300504376159569382855409663\n",
700 "286687326998758938951352611912760867599570623646035140467198604923365359511060601008752319138765710819327\n",
701 "573374653997517877902705223825521735199141247292070280934397209846730719022121202017504638277531421638655\n",
702 "1146749307995035755805410447651043470398282494584140561868794419693461438044242404035009276555062843277311\n",
703 "2293498615990071511610820895302086940796564989168281123737588839386922876088484808070018553110125686554623\n",
704 "4586997231980143023221641790604173881593129978336562247475177678773845752176969616140037106220251373109247\n",
705 "9173994463960286046443283581208347763186259956673124494950355357547691504353939232280074212440502746218495\n",
706 "18347988927920572092886567162416695526372519913346248989900710715095383008707878464560148424881005492436991\n",
707 "36695977855841144185773134324833391052745039826692497979801421430190766017415756929120296849762010984873983\n",
708 "73391955711682288371546268649666782105490079653384995959602842860381532034831513858240593699524021969747967\n",
709 "146783911423364576743092537299333564210980159306769991919205685720763064069663027716481187399048043939495935\n",
710 "293567822846729153486185074598667128421960318613539983838411371441526128139326055432962374798096087878991871\n",
711 "587135645693458306972370149197334256843920637227079967676822742883052256278652110865924749596192175757983743\n",
712 "1174271291386916613944740298394668513687841274454159935353645485766104512557304221731849499192384351515967487\n",
713 "2348542582773833227889480596789337027375682548908319870707290971532209025114608443463698998384768703031934975\n",
714 "4697085165547666455778961193578674054751365097816639741414581943064418050229216886927397996769537406063869951\n",
715 "9394170331095332911557922387157348109502730195633279482829163886128836100458433773854795993539074812127739903\n",
716 "18788340662190665823115844774314696219005460391266558965658327772257672200916867547709591987078149624255479807\n",
717 "37576681324381331646231689548629392438010920782533117931316655544515344401833735095419183974156299248510959615\n",
718 "75153362648762663292463379097258784876021841565066235862633311089030688803667470190838367948312598497021919231\n",
719 "150306725297525326584926758194517569752043683130132471725266622178061377607334940381676735896625196994043838463\n",
720 "300613450595050653169853516389035139504087366260264943450533244356122755214669880763353471793250393988087676927\n",
721 "601226901190101306339707032778070279008174732520529886901066488712245510429339761526706943586500787976175353855\n",
722 "1202453802380202612679414065556140558016349465041059773802132977424491020858679523053413887173001575952350707711\n",
723 "2404907604760405225358828131112281116032698930082119547604265954848982041717359046106827774346003151904701415423\n",
724 "4809815209520810450717656262224562232065397860164239095208531909697964083434718092213655548692006303809402830847\n",
725 "9619630419041620901435312524449124464130795720328478190417063819395928166869436184427311097384012607618805661695\n",
726 "19239260838083241802870625048898248928261591440656956380834127638791856333738872368854622194768025215237611323391\n",
727 "38478521676166483605741250097796497856523182881313912761668255277583712667477744737709244389536050430475222646783\n",
728 "76957043352332967211482500195592995713046365762627825523336510555167425334955489475418488779072100860950445293567\n",
729 "153914086704665934422965000391185991426092731525255651046673021110334850669910978950836977558144201721900890587135\n",
730 "307828173409331868845930000782371982852185463050511302093346042220669701339821957901673955116288403443801781174271\n",
731 "615656346818663737691860001564743965704370926101022604186692084441339402679643915803347910232576806887603562348543\n",
732 "1231312693637327475383720003129487931408741852202045208373384168882678805359287831606695820465153613775207124697087\n",
733 "2462625387274654950767440006258975862817483704404090416746768337765357610718575663213391640930307227550414249394175\n",
734 "4925250774549309901534880012517951725634967408808180833493536675530715221437151326426783281860614455100828498788351\n",
735 "9850501549098619803069760025035903451269934817616361666987073351061430442874302652853566563721228910201656997576703\n",
736 "19701003098197239606139520050071806902539869635232723333974146702122860885748605305707133127442457820403313995153407\n",
737 "39402006196394479212279040100143613805079739270465446667948293404245721771497210611414266254884915640806627990306815\n",
738 "78804012392788958424558080200287227610159478540930893335896586808491443542994421222828532509769831281613255980613631\n",
739 "157608024785577916849116160400574455220318957081861786671793173616982887085988842445657065019539662563226511961227263\n",
740 "315216049571155833698232320801148910440637914163723573343586347233965774171977684891314130039079325126453023922454527\n",
741 "630432099142311667396464641602297820881275828327447146687172694467931548343955369782628260078158650252906047844909055\n",
742 "1260864198284623334792929283204595641762551656654894293374345388935863096687910739565256520156317300505812095689818111\n",
743 "2521728396569246669585858566409191283525103313309788586748690777871726193375821479130513040312634601011624191379636223\n",
744 "5043456793138493339171717132818382567050206626619577173497381555743452386751642958261026080625269202023248382759272447\n",
745 "10086913586276986678343434265636765134100413253239154346994763111486904773503285916522052161250538404046496765518544895\n",
746 "20173827172553973356686868531273530268200826506478308693989526222973809547006571833044104322501076808092993531037089791\n",
747 "40347654345107946713373737062547060536401653012956617387979052445947619094013143666088208645002153616185987062074179583\n",
748 "80695308690215893426747474125094121072803306025913234775958104891895238188026287332176417290004307232371974124148359167\n",
749 "161390617380431786853494948250188242145606612051826469551916209783790476376052574664352834580008614464743948248296718335\n",
750 "322781234760863573706989896500376484291213224103652939103832419567580952752105149328705669160017228929487896496593436671\n",
751 "645562469521727147413979793000752968582426448207305878207664839135161905504210298657411338320034457858975792993186873343\n",
752 "1291124939043454294827959586001505937164852896414611756415329678270323811008420597314822676640068915717951585986373746687\n",
753 "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629645353280137831435903171972747493375\n",
754 "5164499756173817179311838344006023748659411585658447025661318713081295244033682389259290706560275662871806343945494986751\n",
755 "10328999512347634358623676688012047497318823171316894051322637426162590488067364778518581413120551325743612687890989973503\n",
756 "20657999024695268717247353376024094994637646342633788102645274852325180976134729557037162826241102651487225375781979947007\n",
757 "41315998049390537434494706752048189989275292685267576205290549704650361952269459114074325652482205302974450751563959894015\n",
758 "82631996098781074868989413504096379978550585370535152410581099409300723904538918228148651304964410605948901503127919788031\n",
759 "165263992197562149737978827008192759957101170741070304821162198818601447809077836456297302609928821211897803006255839576063\n",
760 "330527984395124299475957654016385519914202341482140609642324397637202895618155672912594605219857642423795606012511679152127\n",
761 "661055968790248598951915308032771039828404682964281219284648795274405791236311345825189210439715284847591212025023358304255\n",
762 "1322111937580497197903830616065542079656809365928562438569297590548811582472622691650378420879430569695182424050046716608511\n",
763 "2644223875160994395807661232131084159313618731857124877138595181097623164945245383300756841758861139390364848100093433217023\n",
764 "5288447750321988791615322464262168318627237463714249754277190362195246329890490766601513683517722278780729696200186866434047\n",
765 "10576895500643977583230644928524336637254474927428499508554380724390492659780981533203027367035444557561459392400373732868095\n",
766 "21153791001287955166461289857048673274508949854856999017108761448780985319561963066406054734070889115122918784800747465736191\n",
767 "42307582002575910332922579714097346549017899709713998034217522897561970639123926132812109468141778230245837569601494931472383\n",
768 "84615164005151820665845159428194693098035799419427996068435045795123941278247852265624218936283556460491675139202989862944767\n",
769 "169230328010303641331690318856389386196071598838855992136870091590247882556495704531248437872567112920983350278405979725889535\n",
770 "338460656020607282663380637712778772392143197677711984273740183180495765112991409062496875745134225841966700556811959451779071\n",
771 "676921312041214565326761275425557544784286395355423968547480366360991530225982818124993751490268451683933401113623918903558143\n",
772 "1353842624082429130653522550851115089568572790710847937094960732721983060451965636249987502980536903367866802227247837807116287\n",
773 "2707685248164858261307045101702230179137145581421695874189921465443966120903931272499975005961073806735733604454495675614232575\n",
774 "5415370496329716522614090203404460358274291162843391748379842930887932241807862544999950011922147613471467208908991351228465151\n",
775 "10830740992659433045228180406808920716548582325686783496759685861775864483615725089999900023844295226942934417817982702456930303\n",
776 "21661481985318866090456360813617841433097164651373566993519371723551728967231450179999800047688590453885868835635965404913860607\n",
777 "43322963970637732180912721627235682866194329302747133987038743447103457934462900359999600095377180907771737671271930809827721215\n",
778 "86645927941275464361825443254471365732388658605494267974077486894206915868925800719999200190754361815543475342543861619655442431\n",
779 "173291855882550928723650886508942731464777317210988535948154973788413831737851601439998400381508723631086950685087723239310884863\n",
780 "346583711765101857447301773017885462929554634421977071896309947576827663475703202879996800763017447262173901370175446478621769727\n",
781 "693167423530203714894603546035770925859109268843954143792619895153655326951406405759993601526034894524347802740350892957243539455\n",
782 "1386334847060407429789207092071541851718218537687908287585239790307310653902812811519987203052069789048695605480701785914487078911\n",
783 "2772669694120814859578414184143083703436437075375816575170479580614621307805625623039974406104139578097391210961403571828974157823\n",
784 "5545339388241629719156828368286167406872874150751633150340959161229242615611251246079948812208279156194782421922807143657948315647\n",
785 "11090678776483259438313656736572334813745748301503266300681918322458485231222502492159897624416558312389564843845614287315896631295\n",
786 "22181357552966518876627313473144669627491496603006532601363836644916970462445004984319795248833116624779129687691228574631793262591\n",
787 "44362715105933037753254626946289339254982993206013065202727673289833940924890009968639590497666233249558259375382457149263586525183\n",
788 "88725430211866075506509253892578678509965986412026130405455346579667881849780019937279180995332466499116518750764914298527173050367\n",
789 "177450860423732151013018507785157357019931972824052260810910693159335763699560039874558361990664932998233037501529828597054346100735\n",
790 "354901720847464302026037015570314714039863945648104521621821386318671527399120079749116723981329865996466075003059657194108692201471\n",
791 "709803441694928604052074031140629428079727891296209043243642772637343054798240159498233447962659731992932150006119314388217384402943\n",
792 "1419606883389857208104148062281258856159455782592418086487285545274686109596480318996466895925319463985864300012238628776434768805887\n",
793 "2839213766779714416208296124562517712318911565184836172974571090549372219192960637992933791850638927971728600024477257552869537611775\n",
794 "5678427533559428832416592249125035424637823130369672345949142181098744438385921275985867583701277855943457200048954515105739075223551\n",
795 "11356855067118857664833184498250070849275646260739344691898284362197488876771842551971735167402555711886914400097909030211478150447103\n",
796 "22713710134237715329666368996500141698551292521478689383796568724394977753543685103943470334805111423773828800195818060422956300894207\n",
797 "45427420268475430659332737993000283397102585042957378767593137448789955507087370207886940669610222847547657600391636120845912601788415\n",
798 "90854840536950861318665475986000566794205170085914757535186274897579911014174740415773881339220445695095315200783272241691825203576831\n",
799 "181709681073901722637330951972001133588410340171829515070372549795159822028349480831547762678440891390190630401566544483383650407153663\n",
800 "363419362147803445274661903944002267176820680343659030140745099590319644056698961663095525356881782780381260803133088966767300814307327\n",
801 "726838724295606890549323807888004534353641360687318060281490199180639288113397923326191050713763565560762521606266177933534601628614655\n",
802 "1453677448591213781098647615776009068707282721374636120562980398361278576226795846652382101427527131121525043212532355867069203257229311\n",
803 "2907354897182427562197295231552018137414565442749272241125960796722557152453591693304764202855054262243050086425064711734138406514458623\n",
804 "5814709794364855124394590463104036274829130885498544482251921593445114304907183386609528405710108524486100172850129423468276813028917247\n",
805 "11629419588729710248789180926208072549658261770997088964503843186890228609814366773219056811420217048972200345700258846936553626057834495\n",
806 "23258839177459420497578361852416145099316523541994177929007686373780457219628733546438113622840434097944400691400517693873107252115668991\n",
807 "46517678354918840995156723704832290198633047083988355858015372747560914439257467092876227245680868195888801382801035387746214504231337983\n",
808 "93035356709837681990313447409664580397266094167976711716030745495121828878514934185752454491361736391777602765602070775492429008462675967\n",
809 "186070713419675363980626894819329160794532188335953423432061490990243657757029868371504908982723472783555205531204141550984858016925351935\n",
810 "372141426839350727961253789638658321589064376671906846864122981980487315514059736743009817965446945567110411062408283101969716033850703871\n",
811 "744282853678701455922507579277316643178128753343813693728245963960974631028119473486019635930893891134220822124816566203939432067701407743\n",
812 "1488565707357402911845015158554633286356257506687627387456491927921949262056238946972039271861787782268441644249633132407878864135402815487\n",
813 "2977131414714805823690030317109266572712515013375254774912983855843898524112477893944078543723575564536883288499266264815757728270805630975\n",
814 "5954262829429611647380060634218533145425030026750509549825967711687797048224955787888157087447151129073766576998532529631515456541611261951\n",
815 "11908525658859223294760121268437066290850060053501019099651935423375594096449911575776314174894302258147533153997065059263030913083222523903\n",
816 "23817051317718446589520242536874132581700120107002038199303870846751188192899823151552628349788604516295066307994130118526061826166445047807\n",
817 "47634102635436893179040485073748265163400240214004076398607741693502376385799646303105256699577209032590132615988260237052123652332890095615\n",
818 "95268205270873786358080970147496530326800480428008152797215483387004752771599292606210513399154418065180265231976520474104247304665780191231\n",
819 "190536410541747572716161940294993060653600960856016305594430966774009505543198585212421026798308836130360530463953040948208494609331560382463\n",
820 "381072821083495145432323880589986121307201921712032611188861933548019011086397170424842053596617672260721060927906081896416989218663120764927\n",
821 "762145642166990290864647761179972242614403843424065222377723867096038022172794340849684107193235344521442121855812163792833978437326241529855\n",
822 "1524291284333980581729295522359944485228807686848130444755447734192076044345588681699368214386470689042884243711624327585667956874652483059711\n",
823 "3048582568667961163458591044719888970457615373696260889510895468384152088691177363398736428772941378085768487423248655171335913749304966119423\n",
824 "6097165137335922326917182089439777940915230747392521779021790936768304177382354726797472857545882756171536974846497310342671827498609932238847\n",
825 "12194330274671844653834364178879555881830461494785043558043581873536608354764709453594945715091765512343073949692994620685343654997219864477695\n",
826 "24388660549343689307668728357759111763660922989570087116087163747073216709529418907189891430183531024686147899385989241370687309994439728955391\n",
827 "48777321098687378615337456715518223527321845979140174232174327494146433419058837814379782860367062049372295798771978482741374619988879457910783\n",
828 "97554642197374757230674913431036447054643691958280348464348654988292866838117675628759565720734124098744591597543956965482749239977758915821567\n",
829 "195109284394749514461349826862072894109287383916560696928697309976585733676235351257519131441468248197489183195087913930965498479955517831643135\n",
830 "390218568789499028922699653724145788218574767833121393857394619953171467352470702515038262882936496394978366390175827861930996959911035663286271\n",
831 "780437137578998057845399307448291576437149535666242787714789239906342934704941405030076525765872992789956732780351655723861993919822071326572543\n",
832 "1560874275157996115690798614896583152874299071332485575429578479812685869409882810060153051531745985579913465560703311447723987839644142653145087\n",
833 "3121748550315992231381597229793166305748598142664971150859156959625371738819765620120306103063491971159826931121406622895447975679288285306290175\n",
834 "6243497100631984462763194459586332611497196285329942301718313919250743477639531240240612206126983942319653862242813245790895951358576570612580351\n",
835 "12486994201263968925526388919172665222994392570659884603436627838501486955279062480481224412253967884639307724485626491581791902717153141225160703\n",
836 "24973988402527937851052777838345330445988785141319769206873255677002973910558124960962448824507935769278615448971252983163583805434306282450321407\n",
837 "49947976805055875702105555676690660891977570282639538413746511354005947821116249921924897649015871538557230897942505966327167610868612564900642815\n",
838 "99895953610111751404211111353381321783955140565279076827493022708011895642232499843849795298031743077114461795885011932654335221737225129801285631\n",
839 "199791907220223502808422222706762643567910281130558153654986045416023791284464999687699590596063486154228923591770023865308670443474450259602571263\n",
840 "399583814440447005616844445413525287135820562261116307309972090832047582568929999375399181192126972308457847183540047730617340886948900519205142527\n",
841 "799167628880894011233688890827050574271641124522232614619944181664095165137859998750798362384253944616915694367080095461234681773897801038410285055\n",
842 "1598335257761788022467377781654101148543282249044465229239888363328190330275719997501596724768507889233831388734160190922469363547795602076820570111\n",
843 "3196670515523576044934755563308202297086564498088930458479776726656380660551439995003193449537015778467662777468320381844938727095591204153641140223\n",
844 "6393341031047152089869511126616404594173128996177860916959553453312761321102879990006386899074031556935325554936640763689877454191182408307282280447\n",
845 "12786682062094304179739022253232809188346257992355721833919106906625522642205759980012773798148063113870651109873281527379754908382364816614564560895\n",
846 "25573364124188608359478044506465618376692515984711443667838213813251045284411519960025547596296126227741302219746563054759509816764729633229129121791\n",
847 "51146728248377216718956089012931236753385031969422887335676427626502090568823039920051095192592252455482604439493126109519019633529459266458258243583\n",
848 "102293456496754433437912178025862473506770063938845774671352855253004181137646079840102190385184504910965208878986252219038039267058918532916516487167\n",
849 "204586912993508866875824356051724947013540127877691549342705710506008362275292159680204380770369009821930417757972504438076078534117837065833032974335\n",
850 "409173825987017733751648712103449894027080255755383098685411421012016724550584319360408761540738019643860835515945008876152157068235674131666065948671\n",
851 "818347651974035467503297424206899788054160511510766197370822842024033449101168638720817523081476039287721671031890017752304314136471348263332131897343\n",
852 "1636695303948070935006594848413799576108321023021532394741645684048066898202337277441635046162952078575443342063780035504608628272942696526664263794687\n"
853 ]
854 }
855 ],
252 "outputs": [],
856 253 "source": [
857 254 "for i in range(500):\n",
858 255 " print(2**i - 1)"
859 256 ]
860 257 },
861 258 {
862 259 "cell_type": "code",
863 260 "execution_count": null,
864 261 "metadata": {
865 262 "collapsed": false
866 263 },
867 264 "outputs": [],
868 265 "source": []
869 266 }
870 267 ],
871 268 "metadata": {
872 269 "kernelspec": {
873 270 "display_name": "Python 3",
874 271 "language": "python",
875 272 "name": "python3"
876 273 },
877 274 "language_info": {
878 275 "codemirror_mode": {
879 276 "name": "ipython",
880 277 "version": 3
881 278 },
882 279 "file_extension": ".py",
883 280 "mimetype": "text/x-python",
884 281 "name": "python",
885 282 "nbconvert_exporter": "python",
886 283 "pygments_lexer": "ipython3",
887 "version": "3.4.2"
284 "version": "3.4.3"
888 285 }
889 286 },
890 287 "nbformat": 4,
891 288 "nbformat_minor": 0
892 289 }
@@ -1,271 +1,271 b''
1 1 {
2 2 "cells": [
3 3 {
4 4 "cell_type": "markdown",
5 5 "metadata": {},
6 6 "source": [
7 7 "The Markdown parser included in IPython is MathJax-aware. This means that you can freely mix in mathematical expressions using the [MathJax subset of Tex and LaTeX](http://docs.mathjax.org/en/latest/tex.html#tex-support). [Some examples from the MathJax site](http://www.mathjax.org/demos/tex-samples/) are reproduced below, as well as the Markdown+TeX source."
8 8 ]
9 9 },
10 10 {
11 11 "cell_type": "markdown",
12 12 "metadata": {},
13 13 "source": [
14 14 "# Motivating Examples\n",
15 15 "\n",
16 16 "---\n",
17 17 "\n",
18 18 "## The Lorenz Equations\n",
19 19 "### Source\n",
20 20 "```\\begin{align}\n",
21 21 "\\dot{x} & = \\sigma(y-x) \\\\\n",
22 22 "\\dot{y} & = \\rho x - y - xz \\\\\n",
23 23 "\\dot{z} & = -\\beta z + xy\n",
24 24 "\\end{align}\n",
25 25 "```\n",
26 26 "### Display\n",
27 27 "\\begin{align}\n",
28 28 "\\dot{x} & = \\sigma(y-x) \\\\\n",
29 29 "\\dot{y} & = \\rho x - y - xz \\\\\n",
30 30 "\\dot{z} & = -\\beta z + xy\n",
31 31 "\\end{align}"
32 32 ]
33 33 },
34 34 {
35 35 "cell_type": "markdown",
36 36 "metadata": {},
37 37 "source": [
38 38 "## The Cauchy-Schwarz Inequality\n",
39 39 "### Source\n",
40 40 "```\\begin{equation*}\n",
41 41 "\\left( \\sum_{k=1}^n a_k b_k \\right)^2 \\leq \\left( \\sum_{k=1}^n a_k^2 \\right) \\left( \\sum_{k=1}^n b_k^2 \\right)\n",
42 42 "\\end{equation*}\n",
43 43 "```\n",
44 44 "### Display\n",
45 45 "\\begin{equation*}\n",
46 46 "\\left( \\sum_{k=1}^n a_k b_k \\right)^2 \\leq \\left( \\sum_{k=1}^n a_k^2 \\right) \\left( \\sum_{k=1}^n b_k^2 \\right)\n",
47 47 "\\end{equation*}"
48 48 ]
49 49 },
50 50 {
51 51 "cell_type": "markdown",
52 52 "metadata": {},
53 53 "source": [
54 54 "## A Cross Product Formula\n",
55 55 "### Source\n",
56 56 "```\\begin{equation*}\n",
57 57 "\\mathbf{V}_1 \\times \\mathbf{V}_2 = \\begin{vmatrix}\n",
58 58 "\\mathbf{i} & \\mathbf{j} & \\mathbf{k} \\\\\n",
59 59 "\\frac{\\partial X}{\\partial u} & \\frac{\\partial Y}{\\partial u} & 0 \\\\\n",
60 60 "\\frac{\\partial X}{\\partial v} & \\frac{\\partial Y}{\\partial v} & 0\n",
61 61 "\\end{vmatrix} \n",
62 62 "\\end{equation*}\n",
63 63 "```\n",
64 64 "### Display\n",
65 65 "\\begin{equation*}\n",
66 66 "\\mathbf{V}_1 \\times \\mathbf{V}_2 = \\begin{vmatrix}\n",
67 67 "\\mathbf{i} & \\mathbf{j} & \\mathbf{k} \\\\\n",
68 68 "\\frac{\\partial X}{\\partial u} & \\frac{\\partial Y}{\\partial u} & 0 \\\\\n",
69 69 "\\frac{\\partial X}{\\partial v} & \\frac{\\partial Y}{\\partial v} & 0\n",
70 70 "\\end{vmatrix} \n",
71 71 "\\end{equation*}"
72 72 ]
73 73 },
74 74 {
75 75 "cell_type": "markdown",
76 76 "metadata": {},
77 77 "source": [
78 78 "## The probability of getting \\(k\\) heads when flipping \\(n\\) coins is\n",
79 79 "### Source\n",
80 80 "```\\begin{equation*}\n",
81 81 "P(E) = {n \\choose k} p^k (1-p)^{ n-k} \n",
82 82 "\\end{equation*}\n",
83 83 "```\n",
84 84 "### Display\n",
85 85 "\\begin{equation*}\n",
86 86 "P(E) = {n \\choose k} p^k (1-p)^{ n-k} \n",
87 87 "\\end{equation*}"
88 88 ]
89 89 },
90 90 {
91 91 "cell_type": "markdown",
92 92 "metadata": {},
93 93 "source": [
94 94 "## An Identity of Ramanujan\n",
95 95 "### Source\n",
96 96 "```\\begin{equation*}\n",
97 97 "\\frac{1}{\\Bigl(\\sqrt{\\phi \\sqrt{5}}-\\phi\\Bigr) e^{\\frac25 \\pi}} =\n",
98 98 "1+\\frac{e^{-2\\pi}} {1+\\frac{e^{-4\\pi}} {1+\\frac{e^{-6\\pi}}\n",
99 99 "{1+\\frac{e^{-8\\pi}} {1+\\ldots} } } } \n",
100 100 "\\end{equation*}\n",
101 101 "```\n",
102 102 "### Display\n",
103 103 "\\begin{equation*}\n",
104 104 "\\frac{1}{\\Bigl(\\sqrt{\\phi \\sqrt{5}}-\\phi\\Bigr) e^{\\frac25 \\pi}} =\n",
105 105 "1+\\frac{e^{-2\\pi}} {1+\\frac{e^{-4\\pi}} {1+\\frac{e^{-6\\pi}}\n",
106 106 "{1+\\frac{e^{-8\\pi}} {1+\\ldots} } } } \n",
107 107 "\\end{equation*}"
108 108 ]
109 109 },
110 110 {
111 111 "cell_type": "markdown",
112 112 "metadata": {},
113 113 "source": [
114 114 "## A Rogers-Ramanujan Identity\n",
115 115 "### Source\n",
116 116 "```\\begin{equation*}\n",
117 117 "1 + \\frac{q^2}{(1-q)}+\\frac{q^6}{(1-q)(1-q^2)}+\\cdots =\n",
118 118 "\\prod_{j=0}^{\\infty}\\frac{1}{(1-q^{5j+2})(1-q^{5j+3})},\n",
119 119 "\\quad\\quad \\text{for $|q|<1$}. \n",
120 120 "\\end{equation*}\n",
121 121 "```\n",
122 122 "### Display\n",
123 123 "\\begin{equation*}\n",
124 124 "1 + \\frac{q^2}{(1-q)}+\\frac{q^6}{(1-q)(1-q^2)}+\\cdots =\n",
125 125 "\\prod_{j=0}^{\\infty}\\frac{1}{(1-q^{5j+2})(1-q^{5j+3})},\n",
126 126 "\\quad\\quad \\text{for $|q|<1$}. \n",
127 127 "\\end{equation*}"
128 128 ]
129 129 },
130 130 {
131 131 "cell_type": "markdown",
132 132 "metadata": {},
133 133 "source": [
134 134 "## Maxwell's Equations\n",
135 135 "### Source\n",
136 136 "```\\begin{align}\n",
137 137 "\\nabla \\times \\vec{\\mathbf{B}} -\\, \\frac1c\\, \\frac{\\partial\\vec{\\mathbf{E}}}{\\partial t} & = \\frac{4\\pi}{c}\\vec{\\mathbf{j}} \\\\ \\nabla \\cdot \\vec{\\mathbf{E}} & = 4 \\pi \\rho \\\\\n",
138 138 "\\nabla \\times \\vec{\\mathbf{E}}\\, +\\, \\frac1c\\, \\frac{\\partial\\vec{\\mathbf{B}}}{\\partial t} & = \\vec{\\mathbf{0}} \\\\\n",
139 139 "\\nabla \\cdot \\vec{\\mathbf{B}} & = 0 \n",
140 140 "\\end{align}\n",
141 141 "```\n",
142 142 "### Display\n",
143 143 "\\begin{align}\n",
144 144 "\\nabla \\times \\vec{\\mathbf{B}} -\\, \\frac1c\\, \\frac{\\partial\\vec{\\mathbf{E}}}{\\partial t} & = \\frac{4\\pi}{c}\\vec{\\mathbf{j}} \\\\ \\nabla \\cdot \\vec{\\mathbf{E}} & = 4 \\pi \\rho \\\\\n",
145 145 "\\nabla \\times \\vec{\\mathbf{E}}\\, +\\, \\frac1c\\, \\frac{\\partial\\vec{\\mathbf{B}}}{\\partial t} & = \\vec{\\mathbf{0}} \\\\\n",
146 146 "\\nabla \\cdot \\vec{\\mathbf{B}} & = 0 \n",
147 147 "\\end{align}"
148 148 ]
149 149 },
150 150 {
151 151 "cell_type": "markdown",
152 152 "metadata": {},
153 153 "source": [
154 154 "# Equation Numbering and References\n",
155 155 "\n",
156 156 "---\n",
157 157 "\n",
158 158 "Equation numbering and referencing will be available in a future version of IPython."
159 159 ]
160 160 },
161 161 {
162 162 "cell_type": "markdown",
163 163 "metadata": {},
164 164 "source": [
165 165 "# Inline Typesetting (Mixing Markdown and TeX)\n",
166 166 "\n",
167 167 "---\n",
168 168 "\n",
169 169 "While display equations look good for a page of samples, the ability to mix math and *formatted* **text** in a paragraph is also important.\n",
170 170 "\n",
171 171 "## Source\n",
172 172 "``` This expression $\\sqrt{3x-1}+(1+x)^2$ is an example of a TeX inline equation in a **[Markdown-formatted](http://daringfireball.net/projects/markdown/)** sentence. \n",
173 173 "```\n",
174 174 "## Display\n",
175 175 "This expression $\\sqrt{3x-1}+(1+x)^2$ is an example of a TeX inline equation in a **[Markdown-formatted](http://daringfireball.net/projects/markdown/)** sentence. "
176 176 ]
177 177 },
178 178 {
179 179 "cell_type": "markdown",
180 180 "metadata": {},
181 181 "source": [
182 182 "# Other Syntax\n",
183 183 "\n",
184 184 "---\n",
185 185 "\n",
186 186 "You will notice in other places on the web that `$$` are needed explicitly to begin and end MathJax typesetting. This is **not** required if you will be using TeX environments, but the IPython notebook will accept this syntax on legacy notebooks. \n",
187 187 "\n",
188 188 "### Source\n",
189 189 "```\n",
190 190 "$$\n",
191 191 "\\begin{array}{c}\n",
192 192 "y_1 \\\\\\\n",
193 193 "y_2 \\mathtt{t}_i \\\\\\\n",
194 194 "z_{3,4}\n",
195 195 "\\end{array}\n",
196 196 "$$\n",
197 197 "```\n",
198 198 "\n",
199 199 "```\n",
200 200 "$$\n",
201 201 "\\begin{array}{c}\n",
202 202 "y_1 \\cr\n",
203 203 "y_2 \\mathtt{t}_i \\cr\n",
204 204 "y_{3}\n",
205 205 "\\end{array}\n",
206 206 "$$\n",
207 207 "```\n",
208 208 "\n",
209 209 "```\n",
210 210 "$$\\begin{eqnarray} \n",
211 211 "x' &=& &x \\sin\\phi &+& z \\cos\\phi \\\\\n",
212 212 "z' &=& - &x \\cos\\phi &+& z \\sin\\phi \\\\\n",
213 213 "\\end{eqnarray}$$\n",
214 214 "```\n",
215 215 "\n",
216 216 "```\n",
217 217 "$$\n",
218 218 "x=4\n",
219 219 "$$\n",
220 220 "```\n",
221 221 "\n",
222 222 "### Display\n",
223 223 "$$\n",
224 224 "\\begin{array}{c}\n",
225 225 "y_1 \\\\\\\n",
226 226 "y_2 \\mathtt{t}_i \\\\\\\n",
227 227 "z_{3,4}\n",
228 228 "\\end{array}\n",
229 229 "$$\n",
230 230 "\n",
231 231 "$$\n",
232 232 "\\begin{array}{c}\n",
233 233 "y_1 \\cr\n",
234 234 "y_2 \\mathtt{t}_i \\cr\n",
235 235 "y_{3}\n",
236 236 "\\end{array}\n",
237 237 "$$\n",
238 238 "\n",
239 239 "$$\\begin{eqnarray} \n",
240 240 "x' &=& &x \\sin\\phi &+& z \\cos\\phi \\\\\n",
241 241 "z' &=& - &x \\cos\\phi &+& z \\sin\\phi \\\\\n",
242 242 "\\end{eqnarray}$$\n",
243 243 "\n",
244 244 "$$\n",
245 245 "x=4\n",
246 246 "$$"
247 247 ]
248 248 }
249 249 ],
250 250 "metadata": {
251 251 "kernelspec": {
252 252 "display_name": "Python 3",
253 253 "language": "python",
254 254 "name": "python3"
255 255 },
256 256 "language_info": {
257 257 "codemirror_mode": {
258 258 "name": "ipython",
259 259 "version": 3
260 260 },
261 261 "file_extension": ".py",
262 262 "mimetype": "text/x-python",
263 263 "name": "python",
264 264 "nbconvert_exporter": "python",
265 265 "pygments_lexer": "ipython3",
266 "version": "3.4.2"
266 "version": "3.4.3"
267 267 }
268 268 },
269 269 "nbformat": 4,
270 270 "nbformat_minor": 0
271 271 }
This diff has been collapsed as it changes many lines, (1004 lines changed) Show them Hide them
@@ -1,1449 +1,619 b''
1 1 {
2 2 "cells": [
3 3 {
4 4 "cell_type": "markdown",
5 5 "metadata": {},
6 6 "source": [
7 "# NbConvert, Python library"
7 "# Using nbconvert as a Library"
8 8 ]
9 9 },
10 10 {
11 11 "cell_type": "markdown",
12 12 "metadata": {},
13 13 "source": [
14 "In this Notebook, I will introduce you to the programatic API of nbconvert to show you how to use it in various context. \n",
14 "In this Notebook, you will be introduced to the programatic API of nbconvert and how it can be used in various contexts. \n",
15 15 "\n",
16 "For this I will use one of [@jakevdp](https://github.com/jakevdp) great [blog post](http://jakevdp.github.io/blog/2013/04/15/code-golf-in-python-sudoku/).\n",
17 "I've explicitely chosen a post with no javascript tricks as Jake seem to be found of right now, for the reason that the becommings of embeding javascript in nbviewer, which is based on nbconvert is not fully decided yet. \n",
18 "\n",
19 "\n",
20 "This will not focus on using the command line tool to convert file. The attentive reader will point-out that no data are read from, or written to disk during the conversion process. Indeed, nbconvert as been though as much as\n",
21 "possible to avoid IO operation and work as well in a database, or web-based environement."
16 "One of [@jakevdp](https://github.com/jakevdp)'s great [blog posts](http://jakevdp.github.io/blog/2013/04/15/code-golf-in-python-sudoku/) will be used to demonstrate. This notebook will not focus on using the command line tool. The attentive reader will point-out that no data is read from or written to disk during the conversion process. Nbconvert has been designed to work in memory so that it works well in a database or web-based environement too."
22 17 ]
23 18 },
24 19 {
25 20 "cell_type": "markdown",
26 21 "metadata": {},
27 22 "source": [
28 "#### Quick overview"
23 "## Quick overview"
29 24 ]
30 25 },
31 26 {
32 27 "cell_type": "markdown",
33 28 "metadata": {},
34 29 "source": [
35 "Credit, Jonathan Freder (@jdfreder on github)\n",
30 "Credit, Jonathan Frederic (@jdfreder on github)\n",
36 31 "\n",
37 32 "<center>\n",
38 33 " ![nbca](images/nbconvert_arch.png)\n",
39 34 "</center>"
40 35 ]
41 36 },
42 37 {
43 38 "cell_type": "markdown",
44 39 "metadata": {},
45 40 "source": [
46 "The main principle of nbconvert is to instanciate a `Exporter` that controle\n",
47 "a pipeline through which each notebook you want to export with go through."
41 "The main principle of nbconvert is to instantiate an `Exporter` that controls\n",
42 "the pipeline through which notebooks are converted."
48 43 ]
49 44 },
50 45 {
51 46 "cell_type": "markdown",
52 47 "metadata": {},
53 48 "source": [
54 "Let's start by importing what we need from the API, and download @jakevdp's notebook."
49 "First, download @jakevdp's notebook."
55 50 ]
56 51 },
57 52 {
58 53 "cell_type": "code",
59 "execution_count": 1,
54 "execution_count": null,
60 55 "metadata": {
61 56 "collapsed": false
62 57 },
63 "outputs": [
64 {
65 "data": {
66 "text/plain": [
67 "'{\\n \"metadata\": {\\n \"name\": \"XKCD_plots\"\\n },\\n \"nbformat\": 3,\\n...'"
68 ]
69 },
70 "execution_count": 1,
71 "metadata": {},
72 "output_type": "execute_result"
73 }
74 ],
58 "outputs": [],
75 59 "source": [
76 60 "import requests\n",
77 61 "response = requests.get('http://jakevdp.github.com/downloads/notebooks/XKCD_plots.ipynb')\n",
78 62 "response.text[0:60]+'...'"
79 63 ]
80 64 },
81 65 {
82 66 "cell_type": "markdown",
83 67 "metadata": {},
84 68 "source": [
85 "If you do not have request install downlad by hand, and read the file as usual."
69 "If you do not have `requests`, install it by running `pip install requests` (or if you don't have pip installed, you can find it on PYPI)."
86 70 ]
87 71 },
88 72 {
89 73 "cell_type": "markdown",
90 74 "metadata": {},
91 75 "source": [
92 "We read the response into a slightly more convenient format which represent IPython notebook. \n",
93 "There are not real advantages for now, except some convenient methods, but with time this structure should be able to\n",
94 "guarantee that the notebook structure is valid. Note also that the in-memory format and on disk format can be slightly different. In particual, on disk, multiline strings might be spitted into list of string to be more version control friendly."
76 "The response is a JSON string which represents an IPython notebook. Next, read the response using nbformat.\n",
77 "\n",
78 "Doing this will guarantee that the notebook structure is valid. Note that the in-memory format and on disk format are slightly different. In particual, on disk, multiline strings might be splitted into a list of strings."
95 79 ]
96 80 },
97 81 {
98 82 "cell_type": "code",
99 "execution_count": 2,
83 "execution_count": null,
100 84 "metadata": {
101 85 "collapsed": false
102 86 },
103 "outputs": [
104 {
105 "data": {
106 "text/plain": [
107 "{'cell_type': 'markdown',\n",
108 " 'metadata': {},\n",
109 " 'source': '# XKCD plots in Matplotlib'}"
110 ]
111 },
112 "execution_count": 2,
113 "metadata": {},
114 "output_type": "execute_result"
115 }
116 ],
87 "outputs": [],
117 88 "source": [
118 89 "from IPython import nbformat\n",
119 90 "jake_notebook = nbformat.reads(response.text, as_version=4)\n",
120 91 "jake_notebook.cells[0]"
121 92 ]
122 93 },
123 94 {
124 95 "cell_type": "markdown",
125 96 "metadata": {},
126 97 "source": [
127 "So we have here Jake's notebook in a convenient form, which is mainly a Super-Powered dict and list nested.\n",
128 "You don't need to worry about the exact structure."
98 "The nbformat API returns a special dict. You don't need to worry about the details of the structure."
129 99 ]
130 100 },
131 101 {
132 102 "cell_type": "markdown",
133 103 "metadata": {},
134 104 "source": [
135 "The nbconvert API exposes some basic exporter for common format and default options. We will start\n",
136 "by using one of them. First we import it, instanciate an instance with most of the default parameters and fed it\n",
137 "the downloaded notebook. "
105 "The nbconvert API exposes some basic exporters for common formats and defaults. You will start\n",
106 "by using one of them. First you will import it, then instantiate it using most of the defaults, and finally you will process notebook downloaded early."
138 107 ]
139 108 },
140 109 {
141 110 "cell_type": "code",
142 "execution_count": 3,
111 "execution_count": null,
143 112 "metadata": {
144 113 "collapsed": false
145 114 },
146 115 "outputs": [],
147 116 "source": [
148 117 "from IPython.config import Config\n",
149 118 "from IPython.nbconvert import HTMLExporter\n",
150 119 "\n",
151 "## I use `basic` here to have less boilerplate and headers in the HTML.\n",
152 "## we'll see later how to pass config to exporters.\n",
120 "# The `basic` template is used here.\n",
121 "# Later you'll learn how to configure the exporter.\n",
153 122 "html_exporter = HTMLExporter(config=Config({'HTMLExporter':{'default_template':'basic'}}))"
154 123 ]
155 124 },
156 125 {
157 126 "cell_type": "code",
158 "execution_count": 4,
127 "execution_count": null,
159 128 "metadata": {
160 129 "collapsed": false
161 130 },
162 131 "outputs": [],
163 132 "source": [
164 133 "(body, resources) = html_exporter.from_notebook_node(jake_notebook)"
165 134 ]
166 135 },
167 136 {
168 137 "cell_type": "markdown",
169 138 "metadata": {},
170 139 "source": [
171 "The exporter returns a tuple containing the body of the converted notebook, here raw HTML, as well as a resources dict.\n",
172 "The resource dict contains (among many things) the extracted PNG, JPG [...etc] from the notebook when applicable.\n",
173 "The basic HTML exporter does keep them as embeded base64 into the notebook, but one can do ask the figures to be extracted. Cf advance use. So for now the resource dict **should** be mostly empty, except for 1 key containing some css, and 2 others whose content will be obvious.\n",
140 "The exporter returns a tuple containing the body of the converted notebook, raw HTML in this case, as well as a resources dict. The resource dict contains (among many things) the extracted PNG, JPG [...etc] from the notebook when applicable. The basic HTML exporter leaves the figures as embeded base64, but you can configure it to extract the figures. So for now, the resource dict **should** be mostly empty, except for a key containing CSS and a few others whose content will be obvious.\n",
174 141 "\n",
175 "Exporter are stateless, you won't be able to extract any usefull information (except their configuration) from them.\n",
176 "You can directly re-use the instance to convert another notebook. Each exporter expose for convenience a `from_file` and `from_filename` methods if you need."
142 "`Exporter`s are stateless, so you won't be able to extract any usefull information beyond their configuration from them. You can re-use an exporter instance to convert another notebook. Each exporter exposes, for convenience, a `from_file` and `from_filename` method."
177 143 ]
178 144 },
179 145 {
180 146 "cell_type": "code",
181 "execution_count": 5,
147 "execution_count": null,
182 148 "metadata": {
183 149 "collapsed": false
184 150 },
185 "outputs": [
186 {
187 "name": "stdout",
188 "output_type": "stream",
189 "text": [
190 "['raw_mimetypes', 'inlining', 'metadata', 'output_extension']\n",
191 "defaultdict(None, {'name': 'Notebook'})\n",
192 ".html\n"
193 ]
194 }
195 ],
151 "outputs": [],
196 152 "source": [
197 153 "print([key for key in resources ])\n",
198 154 "print(resources['metadata'])\n",
199 155 "print(resources['output_extension'])\n",
200 "# print resources['inlining'] # too lng to be shown"
156 "# print resources['inlining'] # Too long to be shown"
201 157 ]
202 158 },
203 159 {
204 160 "cell_type": "code",
205 "execution_count": 6,
161 "execution_count": null,
206 162 "metadata": {
207 163 "collapsed": false
208 164 },
209 "outputs": [
210 {
211 "name": "stdout",
212 "output_type": "stream",
213 "text": [
214 "<!DOCTYPE html>\n",
215 "<html>\n",
216 "<head>\n",
217 "\n",
218 "<meta charset=\"utf-8\" />\n",
219 "<title>Notebook</title>\n",
220 "\n",
221 "<script src=\"https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js\"></script>\n",
222 "<script src=\"https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js\"></script>\n",
223 "\n",
224 "<style type=\"text/css\">\n",
225 " /*!\n",
226 "*\n",
227 "* Twitter Bootstrap\n",
228 "*\n",
229 "*/\n",
230 "/*! normalize.css v3.0.2 | MIT License | git.io/normalize */\n",
231 "html {\n",
232 " fon...\n"
233 ]
234 }
235 ],
165 "outputs": [],
236 166 "source": [
237 167 "# Part of the body, here the first Heading\n",
238 168 "start = body.index('<h1 id', )\n",
239 169 "print(body[:400]+'...')"
240 170 ]
241 171 },
242 172 {
243 173 "cell_type": "markdown",
244 174 "metadata": {},
245 175 "source": [
246 "You can directly write the body into an HTML file if you wish, as you see it does not contains any body tag, or style declaration, but thoses are included in the default HtmlExporter if you do not pass it a config object as I did."
176 "If you understand HTML, you'll notice that some common tags are ommited, like the `body` tag. Those tags are included in the default `HtmlExporter`, which is what would have been constructed if no Config object was passed into it."
247 177 ]
248 178 },
249 179 {
250 180 "cell_type": "markdown",
251 181 "metadata": {},
252 182 "source": [
253 183 "#### Extracting Figures"
254 184 ]
255 185 },
256 186 {
257 187 "cell_type": "markdown",
258 188 "metadata": {},
259 189 "source": [
260 "When exporting one might want to extract the base64 encoded figures to separate files, this is by default what does the RstExporter does, let see how to use it. "
190 "When exporting you may want to extract the base64 encoded figures as files, this is by default what the `RstExporter` does (as seen below)."
261 191 ]
262 192 },
263 193 {
264 194 "cell_type": "code",
265 "execution_count": 7,
195 "execution_count": null,
266 196 "metadata": {
267 197 "collapsed": false
268 198 },
269 199 "outputs": [],
270 200 "source": [
271 201 "from IPython.nbconvert import RSTExporter\n",
272 202 "\n",
273 203 "rst_exporter = RSTExporter()\n",
274 204 "\n",
275 205 "(body,resources) = rst_exporter.from_notebook_node(jake_notebook)"
276 206 ]
277 207 },
278 208 {
279 209 "cell_type": "code",
280 "execution_count": 8,
210 "execution_count": null,
281 211 "metadata": {
282 212 "collapsed": false
283 213 },
284 "outputs": [
285 {
286 "name": "stdout",
287 "output_type": "stream",
288 "text": [
289 "\n",
290 "XKCD plots in Matplotlib\n",
291 "========================\n",
292 "\n",
293 "This notebook originally appeared as a blog post at `Pythonic\n",
294 "Perambulations <http://jakevdp.github.com/blog/2012/10/07/xkcd-style-plots-in-matplotlib/>`__\n",
295 "by Jake Vanderplas.\n",
296 "\n",
297 ".. raw:: html\n",
298 "\n",
299 " <!-- PELICAN_BEGIN_SUMMARY -->\n",
300 "\n",
301 "*Update: the matplotlib pull request has been merged! See* `*This\n",
302 "post* <http://jakevdp.github.io/blog/2013/07/10/XKCD-plots-in-matplotlib/>`__\n",
303 "*for a description of the XKCD functionality now built-in to\n",
304 "matplotlib!*\n",
305 "\n",
306 "One of the problems I've had with typical matplotlib figures is that\n",
307 "everything in them is so precise, so perfect. For an example of what I\n",
308 "mean, take a look at this figure:\n",
309 "\n",
310 ".. code:: python\n",
311 "\n",
312 " from IPython.display import Image\n",
313 " Image('http://jakevdp.github.com/figures/xkcd_version.png')\n",
314 "\n",
315 "\n",
316 "\n",
317 ".. image:: output_3_0.png\n",
318 "\n",
319 "\n",
320 "\n",
321 "Sometimes when showing schematic plots, this is the type of figure I\n",
322 "want to display. But drawing it by hand is a pain: I'd rather just use\n",
323 "matpl...\n",
324 "[.....]\n",
325 "mage:: output_3_0.png\n",
326 "\n",
327 "\n",
328 "\n",
329 "Sometimes when showing schematic plots, this is the type of figure I\n",
330 "want to display. But drawing it by hand is a pain: I'd rather just use\n",
331 "matplotlib. The problem is, matplotlib is a bit too precise. Attempting\n",
332 "to duplicate this figure in matplotlib leads to something like this:\n",
333 "\n",
334 ".. code:: python\n",
335 "\n",
336 " Image('http://jakevdp.github.com/figures/mpl_version.png')\n",
337 "\n",
338 "\n",
339 "\n",
340 ".. image:...\n"
341 ]
342 }
343 ],
214 "outputs": [],
344 215 "source": [
345 216 "print(body[:970]+'...')\n",
346 217 "print('[.....]')\n",
347 218 "print(body[800:1200]+'...')"
348 219 ]
349 220 },
350 221 {
351 222 "cell_type": "markdown",
352 223 "metadata": {},
353 224 "source": [
354 "Here we see that base64 images are not embeded, but we get what look like file name. Actually those are (Configurable) keys to get back the binary data from the resources dict we havent inspected earlier.\n"
225 "Notice that base64 images are not embeded, but instead there are file name like strings. The strings actually are (configurable) keys that map to the binary data in the resources dict.\n"
355 226 ]
356 227 },
357 228 {
358 229 "cell_type": "markdown",
359 230 "metadata": {},
360 231 "source": [
361 "So when writing a Rst Plugin for any blogengine, Sphinx or anything else, you will be responsible for writing all those data to disk, in the right place. \n",
362 "Of course to help you in this task all those naming are configurable in the right place."
232 "Note, if you write an RST Plugin, you are responsible for writing all the files to the disk (or uploading, etc...) in the right location. Of course, the naming scheme is configurable."
363 233 ]
364 234 },
365 235 {
366 236 "cell_type": "markdown",
367 237 "metadata": {},
368 238 "source": [
369 "let's try to see how to get one of these images"
239 "As an exercise, this notebook will show you how to get one of those images."
370 240 ]
371 241 },
372 242 {
373 243 "cell_type": "code",
374 "execution_count": 9,
244 "execution_count": null,
375 245 "metadata": {
376 246 "collapsed": false
377 247 },
378 "outputs": [
379 {
380 "data": {
381 "text/plain": [
382 "['output_5_0.png',\n",
383 " 'output_16_0.png',\n",
384 " 'output_13_1.png',\n",
385 " 'output_18_1.png',\n",
386 " 'output_3_0.png']"
387 ]
388 },
389 "execution_count": 9,
390 "metadata": {},
391 "output_type": "execute_result"
392 }
393 ],
248 "outputs": [],
394 249 "source": [
395 250 "list(resources['outputs'])"
396 251 ]
397 252 },
398 253 {
399 254 "cell_type": "markdown",
400 255 "metadata": {},
401 256 "source": [
402 "We have extracted 5 binary figures, here `png`s, but they could have been svg, and then wouldn't appear in the binary sub dict.\n",
403 "keep in mind that a object having multiple _repr_ will store all it's repr in the notebook. \n",
257 "There are 5 extracted binary figures, all `png`s, but they could have been `svg`s which then wouldn't appear in the binary sub dict. Keep in mind that objects with multiple reprs will have every repr stored in the notebook avaliable for conversion. \n",
404 258 "\n",
405 "Hence if you provide `_repr_javascript_`,`_repr_latex_` and `_repr_png_`to an object, you will be able to determine at conversion time which representaition is the more appropriate. You could even decide to show all the representaition of an object, it's up to you. But this will require beeing a little more involve and write a few line of Jinja template. This will probably be the subject of another tutorial.\n",
259 "Hence if the object provides `_repr_javascript_`, `_repr_latex_`, and `_repr_png_`, you will be able to determine, at conversion time, which representaition is most appropriate. You could even show all of the representaitions of an object in a single export, it's up to you. Doing so would require a little more involvement on your part and a custom Jinja template.\n",
406 260 "\n",
407 "Back to our images,\n",
408 "\n"
261 "Back to the task of extracting an image, the Image display object can be used to display one of the images (as seen below)."
409 262 ]
410 263 },
411 264 {
412 265 "cell_type": "code",
413 "execution_count": 10,
266 "execution_count": null,
414 267 "metadata": {
415 268 "collapsed": false
416 269 },
417 "outputs": [
418 {
419 "data": {
420 "image/png": [
421 "iVBORw0KGgoAAAANSUhEUgAAAbAAAAEgCAYAAADVKCZpAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\n",
422 "AAALEgAACxIB0t1+/AAAIABJREFUeJzsnXd4FGXXxu/ZTYP0RkvoJKH3IvAivQsiINIEgUAsgPIJ\n",
423 "Cq8IAgroqxRRUJpSpCO9ifQSpEgNvYYSCJDek93z/XEyuwkkIWV3Zjd5fte11yxbZu5ZsnvPc57z\n",
424 "nAMSCCyApUuXUqlSpUiSJKpfvz4dPnzY8Fy1atUoLCwsy/edPXuWiIjS0tLo008/JVtbW5Ik6aVb\n",
425 "mTJlKDEx0fA++fX29vak1Wqpe/fu9ODBAyIiWrFiBbm5udHx48fzfT6ffPIJOTo60u3bt/O9j5zY\n",
426 "vn07VaxY0XB+JUuWpBs3brzyfSdOnCAfHx+Kjo7O8zHv379PDg4O5OTkRFFRUfmRLRCYFBsIBCoz\n",
427 "e/ZsfPrppyhZsiSmTp2K5ORkrFmzBi1atAAAJCYmIiUlJcv3NmnSBMnJydi4cSNmzZoFLy8vTJky\n",
428 "Bfb29ple16hRIzg4OAAAUlNT0b9/f2zcuBG1atVCUFAQjhw5giNHjqBv3764efMmoqOjsWnTJjRt\n",
429 "2hSjR4/G77//jlu3bsHb2ztX57R//34kJibi/v378PT0REJCQo6v9/DwgJ2dXa72/ejRI/Tq1Qup\n",
430 "qamYNWsWrl69it9++w0dO3bE8ePHUbJkScNrY2Nj4ezsbPi3JEl49OgRlixZgjFjxgAAYmJicqXP\n",
431 "19cX77zzDpYvX47z58/j9ddfz5VegcBsqO2ggqLNypUrSZIk8vPzo9DQ0Jeef/78Obm6umb5HBGR\n",
432 "JElERBQeHk6SJNHSpUtfeczAwECSJIm6d+9OKSkpLz0/efJkkiSJ/vrrL7py5QppNBoqX758lq/N\n",
433 "js8++4wkSaKDBw9Sv379SJIk0mg0ZG9vn+UI8fvvv8/1vtu2bUtubm40d+5cw2ObNm0iOzs7atGi\n",
434 "heGxzZs3k1arpdOnT2d6f5MmTahcuXKG8+nbt2+u9cmfzaFDh3KtVyAwF8LABKrx6NEjcnNzI3d3\n",
435 "d3r8+HGWrzlw4ABVq1aN9Hp9ls/LBpaYmEiSJNHYsWMpLCzMcHsxVLZjxw6SJIlatGhBaWlpWe5T\n",
436 "/pGeMWMG1alTh3x8fOjWrVt5Ojd/f/9MP/SnTp2iq1ev0v3790mSJOrRowft2bOH9uzZQydOnMj1\n",
437 "fo8dO0aSJNG2bdteek6+GDh//jwREU2ZMiXL1x46dIgkSaL58+cbHsutvh9++IE0Go0hdCsQqIkw\n",
438 "MIFqTJ8+nSRJom+//Tbb1xw4cCDTqCI2NpbCwsLozp07NGbMGJIkiR48eEDR0dEkSRLZ29uTg4MD\n",
439 "SZJEtra21Llz50zm16FDB9JoNPTPP/9ke0zZwOTb4MGD83xu5cuXz/aHXpIkWrZsWZ73SUTUvn17\n",
440 "GjhwYJbP6fV6qly5Mk2ePJmIiJo2bUqurq4UHx+f6XUpKSnk5eVFNjY2dPfu3TzpS0lJoa1bt+ZL\n",
441 "u0BgasQcmEA1kpOTodFoMHjw4Bxfd+7cOVy+fBlubm5o06YNrl+/bnhOkiT4+Phg5cqVAIC///4b\n",
442 "tWrVwsmTJ1GzZk2ULl36pWNWrVoVjRs3zrXOVatWoWzZspg2bVoezg4oW7Ys6tatm6f35MSDBw+w\n",
443 "f/9+XLlyJcvnJUmCk5MTQkJCEB0djQsXLqBXr14oXrx4ptfZ2tqiTZs2WL9+PaKjo/OkwdbWFt26\n",
444 "dcv3OQgEpkSjtgBB0aVChQrQ6/XYu3dvjq+Li4tDzZo14evri+vXr6Nt27bYvXs3Bg4caHhNWloa\n",
445 "AOA///kPXF1d0b59+5fMSz7mtWvXcO/evVfqGz9+PHbs2AF7e3t88803GDduXK7OKyUlBbGxsdBo\n",
446 "TPv1WrduHd544w34+fll+fyWLVtw5coVjBo1CpGRkUhISIBWq83ytRcvXkSJEiVQuXJlk2oUCJRE\n",
447 "GJhANfr374/y5ctj1KhRePLkSabnTp06halTp0KSJGi1Wnz88cfYvXs3du/ejRUrVqBDhw5o3bo1\n",
448 "iAgAcOPGDQBAREQEEhMT8fjxY8MtJibGsN/x48eDiDBw4EDodLpMx1y6dCk2bdqEevXqAeDRWufO\n",
449 "nbF79244Ozvjhx9+wKZNm155XpcvX0ZkZGSBPpus2LFjB9zd3V96PCkpCd9//z369OmDb7755pXZ\n",
450 "gRcuXMC1a9cwd+5cODo65kkDEeH69esvfXYCgRoIAxOohp2dHdavXw+NRoMGDRpgxowZCAkJwcyZ\n",
451 "M9G8eXNDWnmzZs0we/ZsdOjQAR06dECpUqUAcMhMJiQkBABQpUoVlC1bFmXKlDHc3n//fcPrqlat\n",
452 "il9//RXHjx9H48aNsWjRIly9ehWDBw9GYGAgSpcuje7du2PkyJEoX748AKB58+ZYtGgRAGDjxo2v\n",
453 "PK/jx48D4HCbKfH398fmzZsxbtw4LF68GIsXL8b06dNRqVIlzJw5E7Nnz8bYsWMBwDDy0uv1L+0n\n",
454 "KCgI9erVwzvvvJNnDXPmzEHVqlXh7++PO3fuFOyEBIICIubABKrSsGFDnDp1CtOnT8eXX36JL774\n",
455 "Ara2thg5ciQ+++wzHD58ONtQXKNGjVCnTh0AgJ+fHypUqIBWrVoB4B/wLl26wNnZ+aURSWBgIKpW\n",
456 "rYovv/wSQUFBAAAvLy8sWrQIr732GgDgxx9/zPSePn36IDk5GQEBAa88p/DwcAC8Ru1F7t+//8r3\n",
457 "Z8fMmTPh7e2NX3/9FU+fPoWtrS2CgoIwf/589OjRI9Nry5Yti5o1a2Lbtm1ITExEsWLFALABnTp1\n",
458 "CpcuXcryGK/S5+7uDkmSYGdnBycnp3yfi0BgElROIilSJCcnZ5sOLsiaI0eO0Mcff6y2jDwhZzEO\n",
459 "HTr0peeOHTtGTk5OdOfOHbPrWL58OUmSREFBQbRo0SKaNGkS2djY0PLly7N9j5L6BIKCIhGlTyII\n",
460 "zMr9+/fRsGFDhIeHY968eRg5cqTakgRmYubMmZg5cyZ27tyJZs2aqarlrbfewpYtWwBwKHb69Omi\n",
461 "goag0CAMzMzo9XosWLAA48ePR1xcHAAOw5w+fRqVKlVSWZ1AIBBYLyKJw0Q8ffoUqampmR67fPky\n",
462 "WrRogZEjRyIuLg5ubm4AgMjISHTq1AnPnj1TQ6pAIBAUCoSBmYCIiAh8/PHHOHfuHABeBzR16lTU\n",
463 "q1cPx48fR+nSpbFx40aULVsWABAQEIAbN26ge/fuSExMVFO6QCAQWC3CwEzA/v37sWbNGsTGxiIt\n",
464 "LQ1NmjTB5MmTkZKSguHDh+Py5cvo2bOnoaL6okWLUK5cOQQHB6N///5ZpjoLBAKBIGeEgb2ClJSU\n",
465 "TAthdToddDodiOtIAuBFt9WqVUPNmjVhY2ODbt26wc/PDwcOHMDChQsNoUPZwHx9fbFr1y54eHig\n",
466 "VatWJq/YIBAIBEUBkcTxClavXo2tW7fivffeQ9u2bWFjY1w6p9frodFo0Lp1azx//hybNm1C5cqV\n",
467 "kZycDL1eb1h7I+Pr64uHDx/i/v378PX1RWRkZJaVFQQCgUDwasSlfw7o9Xrcvn0ba9euxVtvvYXX\n",
468 "X38ds2fPxvHjxxEdHW0YOV27dg16vd5gRvb29i+ZF2CsHCGX4RHmJRAIBPlHVOLIAY1Gg+HDh+Pu\n",
469 "3bv4448/cOLECZw4cQIAULNmTQQGBuKff/4x1Nzz8PDIcX9y5YL4+HizaxcIBILCjggh5pLIyEic\n",
470 "PXsW27Ztw/79+3H16lUQkaEKepcuXbB9+3bodLpsK4A3bNgQZ86cwcmTJ9GoUSMl5QsEAkGhQ4zA\n",
471 "skGe31qzZg2aN2+OsmXLok2bNmjTpg0ePXqEQ4cOYdOmTXjy5AkaNmyIYcOGAUCOCRnyCCw2NlaR\n",
472 "cxAIBILCjDCwbJCNqH///pg/fz6CgoKg1+uh1WpRpkwZ9OvXz7AYuUqVKob5rYwV0l9E7k/16NEj\n",
473 "85+AQCAQFHKEgeVAWFgYAMDT09PQlwrgnkiSJMHd3T1PiRjyQuaCVCQXCAQCASOyELNAnhY8evQo\n",
474 "ihcvbugLdfbsWaxZs8YwygoJCclTm3lhYAKBQGA6hIFlgWxg+/fvR5UqVVCiRAkAwMKFC7FmzRrD\n",
475 "67Zv346lS5cit3kwsoGFhoaaWLFAIBAUPYSB5cDx48dRq1YtQ5jw1KlTKFmypMGw/vnnH1SuXBnR\n",
476 "0dG52p8YgQkEAoHpEAaWBXICx9WrV2FrawsXFxcAwN27d9G1a1dDCPHff/81tL3PDcLABAKBwHSI\n",
477 "JI5siIiIgK+vL37//Xc4OTkhOjoaKSkpaNeuHQBOs9fpdChevHiuW6t7eXnBxsYGkZGRSEpKgoOD\n",
478 "gzlPQSAQCAo1YgSWDW5ubhgzZgy8vLxw4MAB/PXXX0hJSUFgYCD++usv/P7774iIiECjRo0y1UfM\n",
479 "CY1Gg1KlSgEAHj9+bE75AoFAUOgRI7Bs0Gg0GDlypKEZ5ZUrV7BlyxasXLkS69atA8CjsOTkZADG\n",
480 "1PpXUapUKTx48ABhYWGoUKGCOU9BIBAICjViBJYFcpLGhQsXMGPGDKSlpaFRo0b4+uuvcffuXZw7\n",
481 "dw6ff/453njjDTRo0CBP+/b29gYAPH/+3OS6BQKBoCghRmDZsG7dOowaNQpPnz5Fq1at0LRpU9y+\n",
482 "fRvR0dGoW7cuvvrqK8TExBh6feVm9AXAkPSRmppqNu0CgUBQFBAGlgVnzpxBYGAgunbtioCAACxc\n",
483 "uBAxMTGYMGEC7t69Cy8vL+zevRuVKlXK875tbW0BGJtbCgQCgSB/iBBiBvR6PQBgx44d8Pb2xs8/\n",
484 "/4y33noLmzdvxldffYXmzZvj9u3baN26NYKCggAg14uYZWQDEyMwgUAgKBjCwLJg3759aNiwIezt\n",
485 "7VGnTh1UrFgRvr6++N///gc3Nzf4+flh37592LVrV65DhzKJiYkAIFLoBQKBoIAIA8uAvIC5ePHi\n",
486 "uHLlisFsEhISUL16dYNZyYkYcgWOvIzCIiMjAYhuzAKBQFBQhIFlwYgRI2BrawsvLy8QEVasWIHB\n",
487 "gwcb1nvJC5ebNm0KIPcJHIDRwF7VvVkgEAgEOSOSODIgN7GsUqUK/P39ER0dDVdX15e6J1+9ejVT\n",
488 "lfq8IEZgAoFAYBqEgWVAHkmFhYUhODgYHh4esLW1hZ+fH1q2bIlu3bohICAAly5dQq1atQAAOp3O\n",
489 "0CcsN4gRmEAgEJgGifKaRlcECA8PR1JSEsqVK4cHDx5g9+7dOHDgAE6cOIFHjx4hOTkZn3zyCWbN\n",
490 "mmUYteWG1NRU2NnZQavVIjU1Nc8JIAKBQCAwIgwsAxnLQSUlJUGSJNjb27/0utDQUJQsWTLL53Ii\n",
491 "PDwcJUuWhKenJ549e2YSzQKBQFBUESHEDEiShAMHDuDo0aO4du0aQkNDkZqaiqpVq8Le3h4pKSlw\n",
492 "c3NDjRo1ULZsWbRt2zZP4cO4uDgAgLOzs7lOQSAQCIoMwsDSOXDgACZMmIDr168jKioK5cuXR8WK\n",
493 "FSFJEpYtWwZnZ2fY29sjOjoaNWvWxLBhw9ChQ4c8HSMtLQ2AcTGzQCAQCPKPMLB01q1bh5MnT2LU\n",
494 "qFEYNGgQ/Pz84OLigpEjR+LBgwdYunQp6tati+TkZMTFxeW6B1hG5OobwsAEAoGg4AgDS0euKu/v\n",
495 "75+pwny7du1w5MgRlCpVCq6urgCAEiVK5OsY8ggst/3DBAKBQJA9YiFzOoGBgXj//fcxfvx4fPbZ\n",
496 "Zzh79iwAoEePHrh48aKhAaVer89z/UMZMQITCAQC0yGGAhmYOHEibG1tsWLFCnz//fdo3bo17O3t\n",
497 "4eDggPv37xtS5vV6fb5S4IWBCQQCgekQBpaBMmXKYO7cuRgwYAB+++03rF+/HhEREQCAmTNnQqfT\n",
498 "YcCAAfkOAYoQokAgEJgOEULMgBwabNy4MRYsWIBr165h+/btGDduHJycnPDhhx/Czs4O3377bb72\n",
499 "L0ZgAoFAYDrEUCADclhQDhF6enqiS5cu6NKlCwAgJiYGixcvRv369fO1f5FGLxAIBKZDGFgWyKWh\n",
500 "iAg6nQ4Az4/17NkTH3/8ca5LR72IPAITIUSBQCAoOCKEmE5WmYWSJMHGxgaXLl3Cd999h5s3b0Kr\n",
501 "1ea7hqEIIQoEAoHpKPJDAb1eD8A46pLDh5IkGWojnj59Gt7e3mjWrFmBjiWSOF6BXg8cPgxs3Aic\n",
502 "Pg08fMiPV6gANG4M9O0LNGgAiCLIAoEAYgSG4OBgTJgwAYcOHQLARiaPsOTw4YkTJ6DVag2tUPKL\n",
503 "GIFlAxGwaRNQqxbQujXw00/AiRPA/ft8O3IE+OEHoFEjoGVLNjeBQFDkKfIGdvToUcyZMwcDBw7E\n",
504 "wIEDsWXLFjxMv/KXR0oXL16Eg4MD3NzcCnSslJQUAMLAMhERAfTsybfLlwFfX+C//wX+/hu4cwe4\n",
505 "dQvYtQv4+GPA3Z3N7LXXgGnT2PgEAkGRpcjHsoYOHYozZ85gw4YNWLVqFVatWgVbW1s0adIEo0aN\n",
506 "ws2bN3H58mXEx8cX2MDi4+MBAI6OjqaQbv1cuQJ07w7cvAk4OwPTpwMjRgB2dplfV6kS0KkTMGUK\n",
507 "3+bMASZNYnNbtAgQFwQCQZGkyBuYt7c3Vq9ejYkTJ+LQoUPYu3cvgoODcfToUVy4cAExMTEAgPLl\n",
508 "y8Pd3b1AxxIGloFjx4AuXYCYGKBuXWDzZqB8+Zzf4+oKzJoFtGsHvP02sGwZ8OwZ8OefL5ueQCAo\n",
509 "9BT5ECIAaLVa1K5dG6NGjcLWrVtx6NAh/Pzzz6hXrx4CAgLQvn17/PzzzwCMSR/5QRhYOidPAp07\n",
510 "s3n17AkcPfpq88pIly7A/v2ApyewYwcQGCjCiQJBEaTIj8Bk9Ho99Ho9bGxsUL16dfj7+6NDhw54\n",
511 "+vQpqlataggf5ncNGABDF+aCjuSsmqtXgY4dgdhYzipcuRLIQ1NQA02aAHv2cFLHihUcZvzqK5PL\n",
512 "FQgElosYgaWj0Wgypbfb2NigcuXKeO211wo89yUjJ4f4+PiYZH9WR0QE0K0bEBXFc1/Ll+fPvGQa\n",
513 "NADWrQM0Gp4b273bdFoFAoHFIwwsB4go361TsuLRo0cAiqiB6fVA//6csFG3LrBqlWmSL7p0AaZO\n",
514 "5fvvvgukf8YCgaDwIwwsB+QFzaZCHoGVKVPGZPu0GmbP5pCfpyewZQtgynnACROA9u05oeP998V8\n",
515 "mEBQRJDIlEMMQbbodDrY29tDp9MhOTkZdkUpa+7sWZ6zSk1l8+re3fTHePgQqF6dE0PWrgX69DH9\n",
516 "MQQCgUUhRmAoWJfl3PLkyRPodDp4e3sXLfNKSuLQYWoq8MEH5jEvAPDxAb77ju+PGgU8f26e4wgE\n",
517 "AotBGBiM5aMKkiL/KuT5ryIXPvzmG848rFoV+P578x5r+HDg9deB8HDgiy/MeyyBQKA6RdrA4uLi\n",
518 "MGfOHPzwww+Ij48vUIr8qyiSGYiXLgEzZ/L9RYuA4sXNezyNBvjlF85sXLQICAkx7/EEAoGqFGkD\n",
519 "c3R0RPHixfH1119j+PDhCA0NBWDMPjRHBmKRGYHp9VwWKi0NCAoC/vMfZY5brRofT68Hxo5V5pgC\n",
520 "gUAVirSBAcCIESPwv//9D0ePHsXEiRPx+PFjQ/ahKTMQw8PDAQClSpUy2T4tml9/BYKDgVKljKMw\n",
521 "pfjqK8DFhdeF7d2r7LEFAoFiFFkDk3t9AUBgYCCWLl2KlStXomHDhli4cCFCQkLw+PFjJCQkmOR4\n",
522 "soGVKFHCJPuzaJ4944ryAPDjj4CJFoLnGm9vYPx4vj9likirFwgKKUXWwCRJMvTnunDhgsFgwsLC\n",
523 "8MEHH6Bjx44YMmQIJk2aZCjoWxCKlIFNmsTVNtq1A3r3VkfDyJHcfuXYMSC915tAIChcFMlaiBER\n",
524 "Edi1axfWrl2LkJAQxMTEoGTJkmjbti26dOmCcuXK4dixY9ixYwdOnDgBHx8fjBkzpkDHjI6OBgCT\n",
525 "laWyWC5c4PChVsttT9TqnuzsDHzyCTB5MvcOa9VKHR0CgcBsFEkDO3HiBKZNmwZJktC2bVvUqFED\n",
526 "LVq0QP369Q2v6d69O4YMGYLk5GQEBAQU+JjJyckAAHt7+wLvy2Ih4saTej2vxapRQ109o0dz6v7+\n",
527 "/cD580CdOurqEQgEJqVIGljLli0RHBwMFxcX6PV6Q4dknU4HbXpxWVtbW9SqVctkxywSBvbnn8DB\n",
528 "g1wuasoUtdXw3NvgwcBPP/GocP58tRUJBAITUiTnwBwdHeHu7g6tVmswLwAG8wJMX8hXnm/LWPG+\n",
529 "UJGSAowbx/enTeP5J0sgKIi3K1ZwCxeBQFBoKJIGlhtMnUYvN7GUm1oWOhYvBu7c4XqEw4errcZI\n",
530 "zZq8Bi0ujmskCgSCQoMwMIWQkzciIyNVVmIGEhKAr7/m+1OnApY2ynzvPd6uW6eqDIFAYFqEgSmE\n",
531 "3IW5UBrY/PlAWBhQrx7Qs6faal6mRw821f37eY2aQCAoFAgDUwjZwKKiolRWYmJiY42VNr7+Wr20\n",
532 "+Zzw9ATatgV0OmDzZrXVCAQCEyEMTCEK7Qhs8WJuXdK0KdC5s9pqskdeUL1li7o6BAKByRAGphCF\n",
533 "0sDS0oC5c/n+559b5uhLpmtX3v79N8/ZCQQCq0cYmEIUyiSOTZuAe/eAKlWAN95QW03OlC4NNGzI\n",
534 "DTb371dbjUAgMAEWli5WeCmUI7BZs3g7ZgyXjrJ0unUDTp8Gtm+3fMMt5EREALt2ccOCe/d4KtXF\n",
535 "BahY0RiNdnVVW6XA0hEGphCFLokjOBg4cYIXLA8erLaa3PHGG1wbcft2LntlySHPQsrFi9yke9Mm\n",
536 "XvueFT/+CNjZ8bTlZ5+JCmCC7BEGphCFbgT2ww+8ff99IH2RtsVTrx5Qpgzw8CFw7hz/W6AIkZE8\n",
537 "TbpoEf9bo+HE0LZtuQepiws3MLhyhacpDx0CVq0CVq/mvqjTpwMeHuqeg8DykMiU9ZIE2fLw4UP4\n",
538 "+vqiZMmSePz4sdpyCsbdu0Dlyhw2vHuXTcFaCAoCFi7kWo2TJqmtpkhw+jSPpu7dA2xt+Zpn3Dig\n",
539 "bNns33PvHkeo58/nXCFPT0547dFDOd0Cy0ckcShEoRqB/fQTV5x/5x3rMi+A58EADiMKzM6iRUDz\n",
540 "5mxIjRpxU4Aff8zZvACgfHlOcD1/njvhPH8OvPUWMHYskF5WVCAQIzClICLY2tpCp9MhKSnJeqvS\n",
541 "x8YCvr5ATAxfWjdooLaivJGQwJfzSUnAo0ecnSgwCzNmGBtzf/ghj6jy82dPxGY2bhyPxtq04cYH\n",
542 "IslDIEZgCiFJElxcXAAAsdZcFf3339m8/vMf6zMvAChenDtFA8DOnepqKcRMmsTmJUncyebnn/Nn\n",
543 "XgDv45NPeF6sVCleBfH66zyVKSjaCANTEGdnZwBWbGA6nXHhcgE7VKuKnEK/bZu6OgopP/7IHXW0\n",
544 "Wu5iM2KEafbbrBlw/Djg78+Nv1u2FCZW1BEGpiBWb2AbNwK3bgEVKgBvvqm2mvwjV+X46y9usyIw\n",
545 "GZs28WgJAJYuBQYMMO3+K1ZkE6tfn/8UW7fmSLCgaCIMTEGs2sD0er6sBoDx461j4XJ2+Pry5Xxi\n",
546 "IrB1q9pqCg3XrgGDBvGc1ddf831z4OkJ7N0L1K0L3LjBc2LWntgryB/CwBTEqg1syxbg0iX+8Zf7\n",
547 "a1kz/fvzdtUqdXUUEhITgbff5gHtO+8YkzfMhYcHrxerXZuNs2tX0XC7KCIMTEHs7OwAAKnWlgdM\n",
548 "ZBx9ff55/mfjLYm33+ZR5J49okeYCZg0iats+Ptz6rwSRU48PdnEqlQB/v0X6NNHpNgXNYSBKYg2\n",
549 "Peym0+lUVpJHduwAzp7llPPAQLXVmIYSJYD27Tkve8MGtdVYNf/+yynyGg2wciWQHmhQBG9vrqno\n",
550 "5QXs3g188AFfbwmKBsLAFESj4Y9br9errCQPEAFTp/L9zz4DHBzU1WNK5DDi6tXq6rBi0tL4mkav\n",
551 "B0aP5sXKSlOlCieUFisGLFkCzJunvAaBOggDUxCrHIH99Rdw6hSPWEyVD20p9OjBhnz4MHD/vtpq\n",
552 "rJIFC3hwXr68McqsBq+9xksUAeDTT/m/VFD4EQamIJYwAiPiYhSRkbys65V88w1vP/2UFwEXJpyd\n",
553 "ge7d+f6aNepqsUJiYoyD89mzAScndfX06cOlptLSeIpTrBEr/AgDU5DExEQAQLFixRQ7JhEPoP77\n",
554 "X84cd3Xl4vEeHtyywt+fu6Fs3gwkJ7/w5iNH+ObuzpMLhZF+/XgrshHzzA8/cP5Ls2aWU2R3xgxO\n",
555 "qw8PB3r1yuJvWlCoEAamIAnpreyLKzCSSUjgousNGgCNG/MXOziYU43t7bl9hV7P62iWL+dCqQ0a\n",
556 "vJDFNX06b0ePVnZmXknkzonnzgGXL6utxmoIDzd21PnuO8tprWZjw4PpcuWAf/7hEZmg8CIMTEHi\n",
557 "4+MBAI5m7J+l0/FEtr8/dw45e5bTjUeP5myt8HCuYxsdzVenZ84AM2cCNWvyYMTWNn1H//7LaV2O\n",
558 "jsCoUWbTqzr29tzrAxDJHHnghx+A+HiuytW8udpqMuPtzYmldnbcOGHtWrUVCcwGCRSjZs2aBIDO\n",
559 "nz9vlv2fOEFUqxYRBw6J6tYlWrmSKDHx1e/V64lSUjI80KsX72TsWLNotSj27eNzrVSJPwhBjjx9\n",
560 "SuToyB/ZqVNqq8men35ijU5ORFevqq1GYA7ECExBzBVCTEriVhPNmvFi0goVgD/+4NHVgAG5y3yX\n",
561 "pAyjrytXuF+FnR3wf/9nUq0WScuWvMbt9m3g5Em11Vg8s2fz6KtLF6BhQ7XVZM+HHwJ9+3J1kN69\n",
562 "OawuKFwIA1MQc4QQb94EmjYFvv+e/z1uHE/l9O/PC0vzxcyZPIgbOtTQLyspyTR6LRKtln/pAJHM\n",
563 "8QoiIozrrL78Ul0tr0KSeB44IICroH34oVjkXNgQBqYgsoGZagT255+ceHHuHFC5MidpfPcdL+jM\n",
564 "N3fv8vBNq+WFy+l88QWwfn2BJVsu8qLmtWs5D1uQJXPnciJQ+/a89srScXbm+bBixYBly7hCvqDw\n",
565 "IAxMIYjIZCFEvZ5LEvbqxWtxevbkcGHjxiYQ+t13nAnSvz/3rgCHYH75hYu0/vGHCY5hiTRoAPj5\n",
566 "AU+eAAdPcYCBAAAgAElEQVQOqK3GIomKMraDmzRJXS15oWZN/vsFgI8+4gs+QeFAGJhCpKSkQK/X\n",
567 "w9bWFraGyaa8k5DAizS/+45ThmfP5itMk7RXDwvjS1RJAiZMMDzs6MgdVIh4zdj27SY4lqUhSaJC\n",
568 "/SuYN4+zV1u14obc1sSgQVzyKjmZ58Oio9VWJDAJameRFBUiIiIIALm5ueV7H48fEzVuzJlVrq6c\n",
569 "PGdSxo7lnffsmeXT48fz0w4OnPFY6Lh6lU/Q2ZkoIUFtNRZFbCyRhwd/PPv3q60mfyQkcGau/Ccu\n",
570 "Ek6tHzECU4iCzn9dvsxzDidPcpbh8eNcccBkRERwYTsg22ZO06cDw4dzQkfPnjxgK1QEBHAoMTYW\n",
571 "2LlTbTUWxW+/8Z/Ia6/xCMwaKVaM53FdXHj+WA6HCqwXYWAKUZD5r2PHeLHo3bs8z3XiBFC9uokF\n",
572 "zpvHudEdO/KPeBZIEvDzz8Drr3Mb9969C2G+gxxGFLURDeh0HKoGOMvVUqpu5IcqVdiMAT6X4GB1\n",
573 "9QgKhjAwhcivge3YAbRrxxPoPXpwfkHJkiYWFxtrvBx9RStdW1u+ivXx4VGgXG2q0CBX5di5kw1d\n",
574 "gE2bgDt3ONP1zTfVVlNwevYExozhi68+fUQ/U2tGGJhCyBXo5ZYquWHFCv7BSEriCegNG8xUEP7X\n",
575 "X7k8ffPmQIsWr3x5iRJcPxHgauSnTplBk1qUKwc0acLZMrt3q63GIpBrHn7yCa+uKAx8+y2vn3zw\n",
576 "ABg4kDN7BdaHMDCFyGsrldmzOXNKp+OEwIULzfTjkZRk/IX64otcx4fatOGrWJ2OC9VbU4uzVyKP\n",
577 "wkSnZpw5wyFrd3dgyBC11ZgOW1te8ufpCezZY+waJLAuhIEpRG4NjIijeHIFp1mzOExntnmHpUuB\n",
578 "x4+BevWATp3y9NapUwFfX/6RW7jQTPrUoFcv3m7fDqS3wCmqyAt/Bw3i5RSFibJleV2jJAGTJwN/\n",
579 "/622IkFeEQamEFK6A1EOtWzS0rjp8YwZPNpatoxHOWYjKck4iZWH0ZeMkxMwZw7f/+9/gadPTaxP\n",
580 "LSpW5ESWuDi+PC+iJCYaF64PHaquFnPRsSMwcSJfOPbvL5pgWhvCwBTiVSOw1FT+Ai1ezMV3N2/m\n",
581 "q16zsmgRf2Pr1OGGYPmgZ0+gQwdOMilUCR1vv83bIhxG3LyZF/w2bAjUrq22GvMxeTLQti1fgL3z\n",
582 "DpCSorYiQW4RBqYQORmYXB1AXqOydy/3WTIrCQlGx5kyJd+VfyWJq4IAwPz5QGioifSpjRxG3Lq1\n",
583 "yLb1lb373XfV1WFutFouvlKmDC9ZCQwURX+tBWFgCiEbWMX0+oIyiYmcabh1K0+U79unUJmeX37h\n",
584 "ua8GDYDu3Qu0qzp1uJh7SgowbZqJ9KlNlSpA3bq8xGDvXrXVKE5iojEJM5+Dc6uiRAlg2zbO8l2x\n",
585 "ohD9HRdyhIEphEajQZ06dbBy5UrDY3FxQNeuPM3i7c1rvBTpr/TsGfD113x/yhSTZIhMncpXsr/9\n",
586 "Bly/XuDdWQZyNmKhLsOfNX/9xYP0hg052aEoUL8+m9jAgWxkha7STCFEGJhCFCtWDAcOHICHhwcA\n",
587 "nlvo1IlNq3Rp4OBBHskowoQJvO6rfXvuSmgC/Px4ol+nA776yiS7VB95HmzLliI3MfLnn7zt2VNd\n",
588 "HUrTpg2PwMaONbTCE1gwEuWUFicwGXq93hBGjIhg8zp1iq9u9+1jA1CEf/7hFZw2Nty+OSDAZLsO\n",
589 "DeXIm07HtRtNuGv1qF2bP6edO4HOndVWowipqVztJTKSm3NXraq2IguAiMPJAA/PbGzU1SMAIEZg\n",
590 "iiGb19OnfJV36hRnax8+rKB56XTcEImIF5qZ2GHKlePFrnp9IcpILIKLmg8fZvOqWrUImldcHE9I\n",
591 "T5nCw8+AAF7tbGPDPYtcXXkVtK0tT5w1aQL068ftqbdtK0RrSawDMQJTkLAwrmt4+TLg788jL19f\n",
592 "BQX8+ivw/vt80CtXeCGXibl7lw2ZCLh6lUdkVs3ly0CNGoCHBye9FKCXm7UwciQXbf7vf4tIhYq0\n",
593 "NI6ZrlkD7NrF6yOzwtGR54sTEnKuPeXnx6H5bt248nUR+JtRC2FgChEaymtNbt7k38O//wZKlVJQ\n",
594 "wPPn7JoREcC6dcb5HTMwbBhXcBg6FFiyxGyHUY4aNdjI9uzhRW+FGL2ew9qPHnGUQJGkIrXQ6Th/\n",
595 "fto04MYN4+NNm3Jd0Lp1OYRcurRx5AXw1VlqKo+27tzhW0gIh+dPnmSDk3Fz4wWew4ZxtRtrLuVv\n",
596 "iajYi6zIcPMmUbly3EivXj2ip09VEDFiBAto29bsnfxu3iTSaolsbIhu3zbroZRh0iT+7IYPV1uJ\n",
597 "2Tlxgk+1bNlC3vDx8mWiRo34ZAGiKlWI5swhevCgYPtNTSU6fpxowgSiGjWM+weI6tQhmjuXKCrK\n",
598 "NOcgIGFgZubyZaLSpfnv97XXiCIjVRBx8iSRJLGjXL6syCEHDeJzHjFCkcOZl7Nn+WRKly7kv+pE\n",
599 "n3/OpzpqlNpKzIReT/Tjj0T29kan/v13Np5XEBfHnal1ujwc7/x5oo8/Nrazljt+jx1LFBqa//MQ\n",
600 "EJEwMLNy+jSRtzf/zbZsSRQTo4IInc54pfnZZ4od9upVIo2GyNaW6N49xQ5rHvR6Ih8f/gzPnFFb\n",
601 "jdnQ64n8/Pg0DxxQW40ZSEnhUbRsJMOGEUVH5/rthw4ZfW/GjDweOymJaN06/iGQj29jQzRwIF8g\n",
602 "CfKFMDAzsWsXkaMj/5127EgUH6+SkIULWYSPD18+Kkj//nzoDz9U9LDmQQ7BTp2qthKzcekSn6Kn\n",
603 "Z64GJNZFQgJRhw58gg4ORGvW5Gs3GzZwMAMgWrIkn1pOnSLq25fj7LKZtW9PtG9foR/hmxphYGbg\n",
604 "t9+Mf5sDBxIlJxufe1DQGHteePbMGLrI5xe2IISE8Jfdzo4oLEzxw5uWLVv4c2zcWG0lZmPaND7F\n",
605 "IUPUVmJiEhKI2rXjkytRguiffwq0u59/5l1ptUTbtxdgR3fvEo0ZQ+TkZDSyxo2J/vwzj3HKoosw\n",
606 "MBOi1xt/BACi8eMzX1Ddvn2bateurZygoCAW0qaNald2PXuyhC++UOXwpiMujuNHkkT05InaasxC\n",
607 "vXr8f7Vtm9pKTEhCAo9uZPMy0RzwF1/wLosV48SXAhERQfT118b5BoAoIIBo6dLMV7+ClxAGZiIS\n",
608 "EowhM0kimjcv8/NpaWlUpkwZcnZ2VkbQqVPGxI2QEGWOmQXHjvFn4u7OHmDVdOrEJ/P772orMTl3\n",
609 "7vCpOTkRJSaqrcZEpKURdetmNC8Tfg/0eqKhQ40h16tXTbDT+Hiin34iKl/eaGS+vkSzZike/rcW\n",
610 "hIGZgNBQovr1jT8Amza9/JrY2FgCQI6OjuYXpNNxKALgbCeVee01lvLTT2orKSDz5vGJ9O6tthKT\n",
611 "M3s2n9rbb6utxISMHs0n5eHBE3wmJiWFqEsXPkT58kQPH5pwxytWZE7D9/AgmjxZpTU4loswsALy\n",
612 "9998cQcQVapEdPFi1q+Lj48nAFSsWDHzi1q0iAWVKaNS6mNmNmwwfj5paWqrKQC3b/OJuLgUutDO\n",
613 "66/zqa1apbYSEzF3Lp+QnR3R4cNmO0xcnPFasU4dEy/x0uk4ntusmdHIihfntHyrT+01DcLA8klq\n",
614 "KtHEicaMpLZtOWciOxITEwkA2dvbm1fY8+cc0wCIVq8277FySVoaUcWKLKlAk96WQPXqfCL79qmt\n",
615 "xGQ8eWJMtslDVrnlsnu38Yu5cqXZD/f0KZG/v3G6OSnJDAc5fNg43JNT8N97T7F1nZaKKOabD0JD\n",
616 "uSDv119zZZivvuIqQ56e2b9HSi8hQ+au3PXf/3LZqNatuT+6BaDVcglGgPtoWjVdu/J21y51dZiQ\n",
617 "rVv5V7FtW+4IbtXcvw8MGMAnNHky3zczXl7c/LNUKWD/fmDw4JxLJeaLFi2AHTuAc+e4NJVeD/z+\n",
618 "O1C9OnfEPXy4aLaRVttBrQm9nuiXX3ghvVyYIbcLPlNSUggA2djYmE/ggQMszNbWLDH/ghAezrI0\n",
619 "GiuPfvz9N3/GSmaTmpmOHfmUFi5UW0kBSU42Trh27qx4KvrZs8bfhv79zRxlvnWL6IMPjCurAZ7I\n",
620 "LGIIA8slt29zeED+W+nZk3+Uc0taWhoBII1GYx6B8fFElSuzuK++Ms8xCki/fizvyy/VVlIAkpI4\n",
621 "dxogevRIbTUF5skTY93KnELgVsH//Z+xPJRKJ3PwoHFZV6dOCmTePn7MX6jSpYnu3zfzwSwPYWCv\n",
622 "ID6ek3/k3ywvL6K1a/O+rEqv1xMAMtug95NPWGCtWhabYHDwoHHkatWVHjp35hNZtkxtJQXmp5/4\n",
623 "VLp2VVtJATl0yDg3VOCFWQXj1Cn+nZDrnyqyiN+qv1D5R8yBZQMRsHo1N/SbMgVITAT69uWuGn36\n",
624 "5L0rgpThDWTqWPWWLcCcOTzZtGQJYGdn2v2biNdf51ZJYWHcTsZq6diRt3v2qKvDBKxaxdv+/dXV\n",
625 "USDi47mTKsBzwE2aqCqnYUPg2DFu8HriBNCgARAcbOaDFtUO0Wo76Itcu3aNBgwYQI9UCs/o9Vw1\n",
626 "qGFDY7iwXj2+wCsoGo2GAFCqKa+Wbt0icnVlod9/b7r9mompU41zBFbL5ct8Et7eVl3yR168XLy4\n",
627 "la+THTXKmMduQdGHsDCiFi2M09ILFohSh6bGYgzswYMHNGLECNJqtQSARo4cqejx09K4WHTt2kbj\n",
628 "KlGCaPFi06xdyhhC1JnqRy8hgahBAxb75ptW8e2Ql1IVK2YRS9Tyh17P8ywA0b//qq0m38yYwafQ\n",
629 "t6/aSgrA2bPGijMWWNU9JYWXbeV37twSiI2NpfsWOr+m+rgzIiICM2fOxLx585CUlASNRoPAwEB8\n",
630 "9tlnihz/6VPuHvzrr9xYFQDKlAE++wwYPhwoXtz4Wr1ej7t37+Lu3bvQaDSwtbWFjY0NbG1tUbx4\n",
631 "cTg7O8PFxQWOjo7QaDJHZ/XpebWSJL30XL7Q6ThF+MwZoEIF4LffrKLba8WKwH/+Axw9yl3cBw9W\n",
632 "W1E+kCTuzLxkCbBvH3faBZCWloakpCTo9XoQkWGb8X5+n0tNTc10S0lJMdxPS0uDVquFnZ0dbG1t\n",
633 "M20dHBxQvHhxFCtWzPA3KoezrT58SAR8/DFvR43iDsoWhq0tR/cbNQI++ID/5o8eBRYu5Ox3a2Dr\n",
634 "1q0YMGAA6tWrh27duqFbt26oX7++aX7HCohEpM7igbi4OMydOxf/+9//EB0dDQDo2bMnJk2aBH9/\n",
635 "/0xf4he/zNn9OyUlBQkJCUhMTERCQgISEhKQnJyMzp07wyZDjDgxkZfx/PEHsH07kJLCj1eowMY1\n",
636 "ZAjg4JBZ77Zt2/Dpp5/iRsbW49kgSRKcnJwMhiab2oEDBwwG7ejoCCcnJzg6Ohpu9vb20Gq1Wd5q\n",
637 "1aoFHx8f40HGjOFvhqsrB9xr1AAA6HQ6pKSkwMHBIdO8myWxcCEQFMTrjtScC0tNTUVUVBQiIyMz\n",
638 "3eTHoqOjERMTg+joaERHR6Nz584YOXIkv/n33/kPpVcvYMMGAMD+/fvRtm1b9U7oFfTt2xerV68G\n",
639 "AFy6BNSqBbi7A48fG6dNhwwZgpiYGIPhZTS/rB6T79vZ2UGSJMMFmnxfvmX1vc3KqOX7kiTBwcHh\n",
640 "pZubmxu0Wi2LXbeO1zp6ewPXrwNubip9srnj7l3+kzl4kP89YADw/fe8fiw/xMXF4dGjRwgLC8Oj\n",
641 "R4/w+PFjREdHIz4+HnFxcYiPj0diYiIAZPq/sLGxgb29PRwcHLLdZry/c+dOrFy5EklJSYZjlyhR\n",
642 "Au3atUOnTp3Qvn17lChRQhVDU8XALl68iNq1ayt2vPXr16N3794A+G9+6FCe9wX4YrpLF7466tSJ\n",
643 "8yAycuHCBcyfPx+XLl2Ck5MTNBrNS1fDqampSExMRExMDGJjYxEXF2dS/b/88guCgoKMD8ydC3zy\n",
644 "CV/e7dnDi5YBJCcno0WLFjh16hQ0Go3BRJ2cnF66n91NNlYnJyfY2dlBq9XCxsbmpZtWq830owTg\n",
645 "pQuOjI/b29ujXLlyAIDISKB0ab5wePCAR7wAcOvWLcTFxeW4vxcvUvK6TUhIQExMDCIjI/P8/9Ss\n",
646 "WTMcO3aM/3H1KlCtGuDjwycB/kEpXbo0AGT6EZfvv7jN7XOSJMHW1tZwk0dY8n0bGxukpaVlGpml\n",
647 "pKQgJSUFSUlJhvP/7bff0KVLFwDAF18A06dzlGHhQj6l4OBgNGvWLE+fiZK0bNkSB+Vf/9RUzrC6\n",
648 "fZvDJyNGAOC/oZ49e4KIoNVqodPpoNPpkJaWluVWp9NlebEs3yRJQrFixV66ZYy4ZLd1dXVFzZo1\n",
649 "UaJECcM56PXAvHnA+PFAUhIvHJ8yBfjoI/46ZyQqKgohISE4c+YMQkNDM5lVWFgYYmNjFfrkX835\n",
650 "8+cV/U2XUSWEmJ1Ty19aGxubl67iXvVv+Uvu6Oj40lXiw4cPDceoVo3Nq1Ejzibs149/g7Kjdu3a\n",
651 "+CWP5SN0Oh3i4uIQGxtrMLXHjx+jR48esLe3x5w5cwxXSBlvycnJhi+V/MUKDAxE9+7djTtfvJjN\n",
652 "C+DYZ7p5AcD//d//4fbt27C3t0dycjJiYmIQExOTJ+3m5Pr16/Dz84O7O18sbNkCbNrEX14A2Llz\n",
653 "J0aPHq2YHo1GAzc3N7i7u2e6yY+5uroabi4uLnB3dzf8qMHfn6/4Hz5kA/P1hZOTk0X9qGSHnGEL\n",
654 "ZA4fenl5YceOHZnM/lX35W1KSkq2kRH5M8uNUcv39Xo9kpOTkZSUZLhNnz7dKHbZMjavgABg2DDD\n",
655 "wyNHjsSFCxdM+nnFy1e7+aR3795YsGABvLy8oNFw1PONN3i7YwcHU+bNA6ZO5Uxn+SLazc0NzZs3\n",
656 "R+3atbFp0ybcvXsX58+fR2RkJADAwcEBpUuXRpkyZVCmTBmUKlUK7u7umaI7xYoVA5D5YjAtLc3w\n",
657 "2eZn++zZMzx8+BA6nQ4Af4/s7e0L9BnlF1VGYEQEnU6H4OBgbNu2Ddu2bcPVq1cNz2u1WkybNg0T\n",
658 "Jkwww7G52kz6YEAxIiMj4eHhAVdXV0RFReVvJ8uWcQyCCJg1i//ysyE1NRVxcXGGmzwyjI2NRWxs\n",
659 "rME0M75GNlX5vjy/It/kK1f59uIFBICXHsv4+JgxY/Dhhx8CAFauBN59F2jVCjhwgDWHh4ejffv2\n",
660 "htdntT87O7tsw1mv2sr3XVxc4ObmBmdn54KFPTp14hHwunXA22/nfz8Kc+IE0LQpX7jdu/dy1MHi\n",
661 "SUnh9RihoezEffsCABISEvDgwQPDaFSn0xkiCFlt5VtWF8PyTa/XIykpCYmJiZluCQkJhu+SfKGY\n",
662 "1X15a29vj5kzZxpGwDLbtgHjxgHXrvG/q1UDPv2Uw4svTmMA/Nsp5wrIYVulOHXqFCZMmIB9+/YB\n",
663 "AEqVKoVJkyZh2LBhsFNr6U5BMkBMyY0bN2jWrFnUunVrsrGxoXXr1qktyaQ8ffqUAJCHh0f+drBq\n",
664 "FddhAohmzjStOBWIijKWlnr8WG01+WTiRP7/mDBBbSV5Qs46/7//U1tJPlmwgE+gRg2ra2+Qlpb2\n",
665 "UhZyair3rixXLnMG9IQJllGr98qVK9SrVy9DFrWrqyvNmDGD4iygwZ/FGFhGIiMjKbHQdNVjwsLC\n",
666 "CACVKFEi729euNBYXXvqVNOLU4muXfmUfvlFbSX5ZM0aPoHu3dVWkmtSU43tf06fVltNPkhM5CaP\n",
667 "ANH69WqrMSnJydwGrG5do5EB3GtwyhSi4GDzFNzQ6/Wk0+leMtbo6GgaP348DRw4kACQg4MDff75\n",
668 "5/T8+XPTi8gnFmlghZHQ0FACQD4+Prl/k15vXKxTyMyLiOi33/i02rVTW0k+uXiRT6ByZbWV5Jq/\n",
669 "/mLJ/v5WsWzwZWbNMi5atuJF5Dmh13P3lMBAY40C+ebqStS6NdGYMTxq27ePu0HnZSG6Xq+ntGxG\n",
670 "rjqdjmLSF2jOnj2bJEmi0aNH0wcffEAPTdax03QIA1OIW7duEQCqUKFC7t6g03E3ZYBHX/Pnm1eg\n",
671 "Cjx/zutPtVorbTSbnMwnIElcNNMKeO89/pOaPFltJfkgJsZYZHDHDrXVKEJiItHmzUQffkhUpUpm\n",
672 "M3vx9vPPL79fp9ORPocrlevXr9OSJUtowIAB5OfnR5Ik0S/pIZFx48aRJEn0VXpxcJNWEDIRqi9k\n",
673 "LiqkpqYCAGxfzJXNirg4znDYvJlrnK1YYZioLkx4ePBasD17OCMxQzKZdWBnx8kEV67wrUEDtRXl\n",
674 "SFISL6QFOPvW6pg9G3j2DGjeHOjcWW01iuDgwAue5UXPDx4A589zW7DLl/nfciJsyZIvvz+rJKVn\n",
675 "z55h8uTJWLRoEdLS0uDq6oqAgAC0bNkSkydPRq9evQBwkgbASxOy25faCANTiFwb2PXrQO/ewMWL\n",
676 "nKa9bh2QnplXGOnd25jIZ3UGBvAC8itXgJAQizewnTuBmBiWGRCgtpo88uwZr/oFgBkzrKLqjDnw\n",
677 "9eWb3FdVhghIS9NDr2ejSUlJQXBwMPbt24eIiAgMGDAATZs2BcBFGRYsWICAgADMnj0b3t7eKFmy\n",
678 "JNzc3ODo6GjIbKxSpQoAGFLkLdHALE+RudHpuG1quqEoRVpaGgBe25ElRLyuq149Nq+AAOCffwq1\n",
679 "eQFAjx6cxr1vHzeStjrSK6AgJERdHbkgvWCIpTTqzhszZwKxsbx0oUULtdWoAqWveHr48CEOHjyI\n",
680 "x48fA0B65RLA1lYDjUaD06dPo1KlSmjbti02bNiAvXv34u2338aoUaOQnJwMR0dHAMDnn3+OTp06\n",
681 "oUGDBvBNX8eYMS1froYSGhqKiIiITBosBrVjmIpz7JhxNvSdd4j++IMoIsLsh719+zZt2bKFkrOq\n",
682 "ln3jhjElD+DOj1FRZtdkKXTowKe9eLHaSvLB+vVk6ABswSQmGhst3r6ttpo8cv++sfPwmTNqq1EF\n",
683 "OUPwxo0bZG9vT5Ik0bvvvpvp+X///ZfWr19P1atXpxo1atC2bdsoOjqaIiMjqV27dqTVaunIkSNE\n",
684 "ROTh4UFBQUH077//0ooVK2jQoEHUsWNHunbtmmGfu3fvJh8fH6pfvz7dvHmTiHgZQE5zakpT9Axs\n",
685 "925eP5Jx9lOrJWrVijOc0v+jFOHJE6Lx44ns7FiHiwvR8uVWmh6WfxYv5tPv0EFtJfng+nUWn5fs\n",
686 "UhXYutWYkm11jBjB4t9+W20lqtOnTx9ycXGhLl26kCRJ9NFHHxmSKz799FNq06YN7d27N9N7li9f\n",
687 "Tj169KD9+/cbHnvjjTdIkiRyc3OjUqVKUevWrWnNmjWUnJxsyFA8fPgwOTs7U8eOHenZCx2uIyMj\n",
688 "KSQkRHUzK3oGJnPrFtGcOURt2rCBZTQ0Pz/+0qxebfpVtno9X0UGBRE5OBiPOXiwQq1bLY9nz6w4\n",
689 "GzEtjRtqAaq1sc8NgwezxG++UVtJHrlxg/8wNBrOFy+k3Lhxg4YNG2YY6WTFtWvXyNHR0ZAlOGLE\n",
690 "CJIkiZYvX05ERMePH6dWrVrRsWPHiIgzDL/88kuSJIlGjBhBqampBsPp27cv1a1blxITEykhIYFi\n",
691 "s8jDv3TpEjk7O5OzszMFBQXRhg0b6L333qPq1auTJEnk7OxMoaGhpv4o8kTRNbCMRERwpYu+fV9e\n",
692 "eAEQVa1KNGgQ0dy5REeOcEOfvFx5PHzIubCffkpUsWLmfXfvrnoLdEugUyf+OBYuVFtJPmjShMVn\n",
693 "uMK1JFJTidzdWaLVeUC/fix86FC1lZiVQYMGGVLYXxzVyP/eu3cveXt70x9//EFERCEhIdSoUSOq\n",
694 "X78+XU4v2TFy5EiaPn06ERF988035O7uTm+++Sa1bduW6tatSxcvXiSdTkdDhw4lPz+/l3To9Xp6\n",
695 "mn4VmZSURE2aNCFJkgw3T09PevPNN2n16tX0559/UpTKUx0iCxHgnhL9+vEtNZV7bB04wLejR7ny\n",
696 "+NWrwPLlxve4ugKVKgElSgCenrwPSeJy06mpQHg48OgRF15Mn2w1UKoUt+EYOZIragvQpw+wezdn\n",
697 "Iw4frraaPFKnDifcnD+fqbiypXD6NHcA8POzsuzD8+e51qGdHTB5stpq8gSl13vVarU51iuUXyMX\n",
698 "6PX09IQkSYbH5X1JkoT4+HhERkYiLCwMAFC9enVMmzYN77//Pg4ePIhq1aqhYsWKOHfuHADgww8/\n",
699 "xLvvvgs3Nzc8efIE3377LaZMmYL169ejSpUqWL58OaKjo3Hv3j3s2LEDBw4cwJkzZ9C4cWOsW7cO\n",
700 "zs7OWLFiBcaNG4fDhw+jfv36GDt2LBo0aAAvLy+LaNckDOxFbG2B117j24QJXDj07Fk2tdOngQsX\n",
701 "gBs3gOhofjw3uLgADRtyCfyuXYFmzaywgqp56dGDe4Tt389NRr291VaUB+Q2Eiaugm4q/vqLtx06\n",
702 "qKsjz0ycyNsPP1S++nYBkftuvQqtVovU1FSULVsWAHLsNyhnMLu4uAAAjhw5gokTJyI8PByHDx/G\n",
703 "Bx98gGrVqmH79u2G18vvcXZ2RunSpZGUlGQoCAwA5cuXN7SDatWqFcaOHYv33nsPzs7OSEtLg5+f\n",
704 "H1atWoXiGTv7WhDCwF6FnR3QpAnfZIh4hHX3Lud+P38OyBXmNRq+lSjBTa/KlOEvnwWuobAk3N2B\n",
705 "du240eiff7KZWQ116vD2/Hl1dWSDVRrYsWPcbdbRkS8krYyoqCisXbsWOp0OgYGBOVZr12q1qJoe\n",
706 "icnYokRGvm9nZwedTodNmzbB19cXEyZMQEBAgOFYM2fOROXKlSFJEu7du4fy5csjNjYWFy9exC+/\n",
707 "/IKVK1di48aNkCQJpUqVgouLC/z9/fHGG2+gTJkyaN26NcqVKweNRgMigo2NDYjIYF46nc5Qud9i\n",
708 "UDWAKRBkQK6N2Lq12krySFQUC7e3N0+11QIQFcU5EDY2RNHRaqvJJXo90euv82f65Zdqq3klGZMj\n",
709 "5H9/9dVXhkSHyMjIHN+v1+tp3rx5htT4F4vqyvu+dOkS+fj4kCRJVLx4cerWrRtFR0fT2rVrqVix\n",
710 "Yt33RU8AACAASURBVPTll1/SvXv3qHfv3jRu3DhasmQJjRgxgsqVK0eSJNHYsWMN+wwPD6fz589T\n",
711 "vJWUQMsOYWAKkZiYSAsWLKBx48apLcViiYw0tlh58kRtNXmkfHn+wbWE/hcZ2LSJZbVoobaSPLB3\n",
712 "L4t2d7f49ZCRkZE0depUWrZsGRHxOqnjx48bkh6CgoJyrCEom9Py5cupePHi1LNnT4PhvWhkz549\n",
713 "oxYtWlDNmjUNmYZERPfv36fWrVtT48aN6fbt2/T++++TJElkb29P1apVo2HDhtHGjRuzzDR8UYe1\n",
714 "IQxMIR48eEAAqHTp0mpLsWi6dOHfrgUL1FaSR7p3Z+Fr1qitJBMffMCypk1TW0ku0euJmjdn0TNm\n",
715 "qK3mlYSHhxvMavPmzURE1LRpU5IkiVq3bk23bt3K8f2ySS1fvtyQ7p7RaJKSkuj8+fMUHBxMaWlp\n",
716 "NGTIEGrSpAkRsVnKa7b+/PNP8vLyosuXL9OdO3fo3Llz5jhdi0NMzCiEHEdOSEhQWYll06cPb9ev\n",
717 "V1dHnrHQRA6rm//at4/nvzw9gY8+UlvNK/H29kZQUBC0Wi3ee+89tG7dGmfPnoWtrS2++OILVKpU\n",
718 "Kcf3U3ppJg8PD0iShPXr12P8+PGYOXMmWrRogTJlyqBu3br46KOPEBMTg8qVK2d6v5yp2KVLF4wY\n",
719 "MQKOjo6oUKEC6qTPy+r1euj1essrAWUiRBKHQsj1x+Lj41VWYtm8+SYngh48yHkyJUqorSiXWKCB\n",
720 "3brFN3d3i68zbGTqVN6OHQs4O6urJZf89NNPKF68OGbPno1Dhw4BAPr27Yu2bdtCr9fnWARXfq5W\n",
721 "rVqoXr06QkJCMH/+fABA7dq1MWjQILz11lvQaDRwdHREVFQUwsPDkZSUBAcHB8N+7O3t8c0332S7\n",
722 "/0KL2kPAooJeryetVksAKCUlRW05Fo1cFtKqwohXr7LocuXUVmJgwQIrq8B06hQLdnPj3l9WxJMn\n",
723 "T2j06NGGcGLVqlUpODiYiCjb5pEvcvv2berYsSPVqlWLPv74Y7p06RIlJCS89JrHpq4OZMUUcnu2\n",
724 "HCRJEqOwXPL227y1qjBilSrcvCk01LikQmWsLnw4dy5vAwOtZvQl4+rqisTERMO/r127hoEDB+KP\n",
725 "P/4whPlygohQsWJF7Ny5ExcuXMCcOXNQo0YNFCtW7KXXlMyq8VcRRRiYgjg5OQEA4uLiVFZi2bwY\n",
726 "RrQKtFqgZk2+bwFhxLQ0nk4CrKQjT1gYsHYtr5e0grmvF9m/fz8WL14MHx8fnD9/Ht26dcPt27fx\n",
727 "7rvv4vvvv0dMTAyA7NuRSJIEIjKswdLr9Vm+RpAZYWAK4unpCYA7ogqyx82NRw16vbGDsFVgQfNg\n",
728 "J09y80p/f6B8ebXV5IKVK7kEW/fuQIUKaqvJMxPTq4ZMnDgRtWrVwpYtWzA5vfzVrFmzcqywISMb\n",
729 "lCRJhX/uykSIJA4F8fLyAgA8ffpUZSWWT+/ewI4dwNatwPvvq60ml8gVOdJr0amJ1YUP167l7aBB\n",
730 "6urIB4mJiahevTpq1KiBgQMHGh7/4osvUL9+fSQlJaFatWoAxCjK1AgDUxDv9AJ/wsBeTefOvD1w\n",
731 "AEhIACy0FFtm6tfn7Zkz6uqAlRnYzZv8mTk5Gf/jrYhixYphyZIl0Ov1cHBwMBTftbGxQbdu3dSW\n",
732 "V6gR41QFEQaWe0qW5PrHSUk8F2YV1K3LHQkuXWLhKhEVxcXxbWyAVq1Uk5F75GydN9/kRBgrxM7O\n",
733 "zpDWLkZZyiEMTEGEgeWNLl14u3OnujpyjZMTUK0aZ1CoOA+2fz/PHzZrZiXJfHL48J131NUhsDqE\n",
734 "gSmIMLC8kdHArKaQgLxi+PRp1SQcOMDbdu1Uk5B7rl3jKv6urlYS7xRYEsLAFEQkceSNhg25otCd\n",
735 "O8D162qrySWvvcbbw4dVkyAfumVL1STkHnn09dZbgL29uloEVocwMAUpkV4XSRhY7tBqgU6d+P6O\n",
736 "HepqyTVt2/J23z6O4ylMRARw8SK3sWvcWPHD551163grF8EUCPKAMDAFkQ0s3GpW56qPHEZMbzJr\n",
737 "+fj7A2XLAs+eqdLg8tgxDrc2aWIF+RAhIXzz8LCSeKfA0hAGpiDCwPJO5848Ejt8GIiMVFtNLpAk\n",
738 "Y+mLXbsUP/yRI7x9/XXFD5135PBhz55cekUgyCPCwBTEw8MDWq0WUVFRSElJUVuOVeDuzj/GOh2w\n",
739 "e7faanLJm2/ydsMGxQ8tL0GTp+IsFiJg1Sq+L7IPBflEGJiCaDQaQyaiKCeVe+S1oFu3qqsj13To\n",
740 "ALi4AGfP8iJdhSAyFgGpW1exw+aPQ4e414uvL9C6tdpqBFaKMDCFEWHEvNO9O2937eJyeRaPg4Nx\n",
741 "FCYnKSjAgwecxOHlBfj4KHbY/LF4MW+HDOEYsUCQD4SBKYwwsLxTuTJQvToQHa1qdnrekMNiK1Yo\n",
742 "tojt7FneygVBLJaoKGDjRr4/ZIi6WgRWjTAwhXF3dwcARFlIzyhroUcP3q5Zo66OXNOxI1C6NHD1\n",
743 "KnD8uCKHtJrw4apVXGqrXTugYkW11QisGGFgCiP3BIuNjVVZiXUxYABvN2wAkpPV1ZIrbGyAwYP5\n",
744 "/pIlihxSHoHVq6fI4fKPHD4cNkxdHQKrRxiYwjinF6cTTS3zRvXqPLKIirKi2ohDh/J23TpAgQuW\n",
745 "jCFEi+Xff1moh4dxWC0Q5BNhYAojRmD5Rx6F/fGHujpyjZ8frwGIjzeueTITz58D9+5x25mAALMe\n",
746 "qmDIo9GBA61gpbXA0hEGpjDCwPJPv36cnLB9Oyd0WAVymMzMYUR5/Vfduhac1JeYaLz6EOFDgQkQ\n",
747 "BqYwNjbcQ1SvQp08a8fHh/tbJScbk9gsnt69uafJiRPAlStmO4xsYHIxfIvkzz/5yqNRI6B2bbXV\n",
748 "CAoBwsAEVoXcsX3lSnV15JrixY0p9cuWme0wcveWhg3NdoiCI5I3BCZGGJjAqujVi6dODh4E7t9X\n",
749 "W00ukdc6rVjBNbFMDBEQHMz3LdbAbt7k/7RixYC+fdVWIygkCAMTWBWurlyZI2MpPYunaVNO6Hj0\n",
750 "CPjrL5Pv/soVICwMKFmSG0JbJEuX8rZPH/5PFAhMgDAwhZHnviSLLpVg2chhRAWLXBQMSQLee4/v\n",
751 "//67yXf/99+8bdfOQitwpKUZz1uEDwUmRBiYwkSm9wRxc3NTWYn10qkTd2oOCTFWn7B4ZNfdvh1I\n",
752 "SDDprvfs4a3cxcXi2L2bh4j+/sB//qO2GkEhQhiYwshV6L28vFRWYr3Y2hqnUawmmaNcOW6RnJBg\n",
753 "dBwT8Pw5sHcvoNEYu1dbHBmTNyxyiCiwVoSBKYxsYHJbFUH+ePdd3q5axREqq6BXL96asE/Y+vVc\n",
754 "ob99e54DszgeP+ZRp1YLDBqkthpBIUMYmMKIEZhpaNyY8yIePwb27VNbTS6RDWz7dpMVdJRHoHKV\n",
755 "Eotj+XLOvHzjDaBUKbXVCAoZwsAURhiYaZAk44/2+vXqask1lSsDdeoAMTEmcd07d4Bjx3ip2Vtv\n",
756 "mUCfqSEyViAJDFRXi6BQIgxMYYSBmY6ePXm7ZYtZlleZB9lpTNBeWl5G8OabQHqFMsvi6FHg+nVu\n",
757 "K2OxE3QCa0YYmILodDpERERAkiRDXzBB/qlZE6hSBXj2jH8rrYJu3Xi7fXuB1gAQGcOHcoKjxZGx\n",
758 "63J6CTWBwJQIA1OQyMhIEBHc3d0NNREF+UeSjAOaTZvU1ZJr6tXjoo4PHxr7n+SDs2e5V6aXl4Wm\n",
759 "z0dHG2O7clsZgcDECANTEBE+ND0ZDcxqFjXLo7AChBHlou7vvMPLCiyONWu4+nyrVjz3JxCYAWFg\n",
760 "CiIMzPQ0acJTLKGh3CvRKpANbNu2fL1dpwNWr+b7Fh8+FMkbAjMiDExBhIGZHo3G2Nh382Z1teSa\n",
761 "Nm04dfDff4EHD/L89sOHubBFpUps4BbH+fNcHt/V1ZhpIxCYAWFgCiIMzDxY3TyYgwPQoQPf3749\n",
762 "z2+Xp5b69LHQwhZy6vyAAVx9XiAwE8LAFOTp06cAhIGZmpYt+WI/JAS4cUNtNbkkn2FEnY77QgLA\n",
763 "22+bWJMpSEzkKsuACB8KzI4wMAURIzDzYGfHhR4AKxqFde3Kw6d9+4D4+Fy/7ehR4MkTDh/Wq2dG\n",
764 "ffll40YgKoobk1mkQEFhQhiYgggDMx9yGNFq5sFKluQJrORkrsabS+Qyir17W2j4cNEi3g4frq4O\n",
765 "QZFAGJiCCAMzH5068dRScDAnOFgF+Qgj7tjBW4vMjbh6lTNMHB2Bfv3UViMoAggDUxBRid58ODoa\n",
766 "F/Ru2aKullyTsSpHeqPTnLh1i+sfurtzhM7ikFPn+/UDnJ3V1SIoEggDUxAxAjMvVhdGrFkTqFAB\n",
767 "CA8HTp585cvlzstt2nB3EosiORlYtozvi/ChQCGEgSmIMDDz0q0brwvbv58rGVk8eazKIU+VWWTp\n",
768 "qC1buChl7dpAo0ZqqxEUEYSBKURKSgpiYmKg1Wrh6uqqtpxCiZcX8Prr3ODRBMXelSGX82A6HRsz\n",
769 "YKEGtnAhb0eMsNDsEkFhRBiYQkRERAAAPDw8IIkvuNno04e3a9eqqyPXtGzJ80WXLvEEVzacOQNE\n",
770 "RnL6fKVKCurLDbdu8XKAYsUsuLOmoDAiDEwhnj9/DgDw9PRUWUnhplcvDiPu2QOkXzNYNnZ2xl5Z\n",
771 "OYzC5Pmvdu0U0JRXfvyRt337Am5u6mr5//bOPS7Kauvjv/0MV+UqIDZeEgVN8M4RMAWviaNg2pt5\n",
772 "T+3NUsvrqY9ancC3TLDQMLWL4iW1g2bmDdTykimK+cpLmsqBBPWAiiIEKDdh1vvHdh4YAUGF5xkO\n",
773 "+/v5zGce5tmz99qjzI+199prCRoVQsAUoqIHJqg/mjfnQQ6lpQ3oUHMtlhENBZwHDVLAnschNxdY\n",
774 "v55fz5mjri2CRocQMIUwCJjwwOqfsWP5c4NZRhw2jLuNx45VGX1SWAjExfHrgQMVtq0moqKAu3e5\n",
775 "Yd26qW2NoJEhBEwhDEuIwgOrf0aN4gWADx/mEeomj5MT0KcPjz45eLDS7ZMneZR69+48UMVkKC0t\n",
776 "Xz6cN09dWwSNEiFgCiGWEJWjWTOe7F2v56n5GgSPWEY07H+Z3PLhtm3A1auAhwf3IgUChRECphD5\n",
777 "+fkAAFuRoUARDMuI0dHq2lFrRozgzzEx3LOpgOH8l0kJWGkpsHgxv160iC+BCgQKI/7XKURJSQkA\n",
778 "wNLSUmVLGgcvvghYWgLHjwPXr6ttTS3o2JF7Mjk5fM3wAXfu8BD6Jk14xL3JsHUrr13Tvj0waZLa\n",
779 "1ggaKULAFEIImLLY2QE6HUBUXgDS5KliGTEnhz8PG8ZFzCS4fx/4n//h1yEhfMNRIFABIWAKYRAw\n",
780 "CwsLlS1pPDTYZcQKaURatuSepElln9+0CUhN5V7j+PFqWyNoxAgBUwiDgJmbm6tsSeMhKIh7LfHx\n",
781 "wJUraltTC/r04anmk5OBf/0LAE9u8cILJhQjUVICfPQRvw4NNcGswoLGhBAwhZAebHLra1E2Q1A3\n",
782 "NG1aXql5+3Z1bakVZmZ83RMwWkacMwcwmfSZ69YB164Bnp7A6NFqWyNo5AgBU4gmDzYwCgoKVLak\n",
783 "cdHgDjUblhErCJi/v0q2PExBQbn39dFHwvsSqI4QMIUwCFhhYaHKljQudDqeKzchgQfNmTxDh3JP\n",
784 "7MQJIDMTAN8DMwlWrwZu3gS8vcuLrwkEKiIETCGsra0BCA9MaayseEg90EAONdvbcxHT603LbczL\n",
785 "A8LC+PWSJaJkisAkEAKmEMIDUw/DqtyBA+raUWsmTuTPW7aoa0dFVqzg6f39/XmaE4HABBACphDC\n",
786 "A1OPwYN5ooi4OO5ImDwjRvCDbGfOAJcuqW0NP00dEcGvhfclMCGEgCmECOJQD0dHwM+PZz8yVDU2\n",
787 "aayty6NP1qxR1xYACA8H8vOBwEATiigRCISAKYbBAxNLiOpgqBnZYJYR336bP2/cWGWJFcXIzARW\n",
788 "reLXH3+snh0CQRUIAVMI4YGpS0UBI1LXluq4fZs7OgCALl2AAQN4ra0NG9QzKjycFyR78UXgb39T\n",
789 "zw6BoAqEgCmEIQdicXGxypY0Try9eS2tq1d5ogtTZNUq7nDJGCocf/opFxGluXED+PJLfh0aqvz4\n",
790 "AkENCAFTCCFg6iJJ5cFzpriMWFICfP11+WodAJ7ct3t3nk7fICRKEhYGFBXxM1/duys/vkBQA0LA\n",
791 "FEIImPqY8j7YDz/w7SYLiwpLnJJUvu+0dClfTlSKjAyuqIDwvgQmixAwhRACpj4GD+yXX9RZkXsU\n",
792 "q1fz57feeihKfdgwHkKZlcVFTClCQ4HiYuDll4GuXZUbVyB4DISAKYQQMPVxdQV69uSrYocPq21N\n",
793 "Ob//zs+o2dmVn2GWYQxYvpxff/qpMufCzp4FoqJ4SisReSgwYYSAKYQQMNPgv/6LP2/erK4dFTF4\n",
794 "X5MnAzY2VTTo3RuYNo0Xkpwxo37DKIl48IjhuWPH+htLIHhKGJGpBhX/Z3Hjxg1otVq4urri5s2b\n",
795 "apvTaPn3v4FnnwXMzXleWkdHde3JyeFFKwsLuXP13HPVNMzO5mKSlQWsXQu8/nr9GLRhA/Daa0Dz\n",
796 "5jxc02TquAgElREemEIID8w0aN2aF4gsKQG++05ta3jYfGEhT3dVrXgBQLNmwOef8+s5c+SCl3XK\n",
797 "1avlofsREUK8BCaPEDCFMAiYoTKzQD1ee40/r1mj7qFmvb48U9Rbb9XiDePH80dBAU81VZeH4u/f\n",
798 "ByZN4iepR40CJkyou74FgnpCLCEqRGlpKczNzaHRaFBaWqq2OY2a+/eBtm358aqffuIemRocPMhD\n",
799 "+1u3BlJTecxEjeTm8kiU1FReETk6mofbPy1z5gArVwLPPAMkJvIlRIHAxBEemEJoNBowxlBWVoay\n",
800 "sjK1zWnUmJuXezyGVTk1MBxanjGjluIF8GW9vXt5yOL33wMLFz69G/nll1y8zM35gTQhXoIGgvDA\n",
801 "FMTKygrFxcUoLCyElZWV2uY0arKyuOdTVAQkJSkfbJeWBrRvzzUjPR1wcXnMDvbv55k6ysqA+fOB\n",
802 "zz57sjInmzYBU6bw6/oMDhEI6gHhgSmIhYUFABHIYQo4O/MtH4DXalSar77ijtMrrzyBeAGATsc9\n",
803 "MHNzfk7sv/+bq3FtIeIHo6dO5T9/+mmjEC+9Xo/x48dDkiS8Xov5ZmZm4oUXXkBKSooC1tUNCQkJ\n",
804 "WLx4MTaomQRaKUigGM7OzgSAbt26pbYpAiK6dImIMSILC6L0dOXGLSggcnIiAoji45+ys337iKys\n",
805 "eGedOxOdOFHze27dInrpJf4egCgs7CmNUJedO3eSk5MTMcbkR9euXenPP/+s1HbmzJnEGCN7e3ti\n",
806 "jNGRI0fke9u3b6d33nlH/lmv11Pfvn2JMUaffPIJERF5eHgYjWN4TJgwgdLS0oiIKDk5mZ5//vkq\n",
807 "2zHGaO7cuURElJGRQf7+/kb3LC0tacuWLU/0ORQVFdG4ceNIkiTS6XSUmJhIREQJCQkkSRKFhYXR\n",
808 "/fv3ydzcnN57771K7w8JCSHGGH377bdERLR+/Xpq3rx5lXPQaDSUkJDwRHbWJULAFESr1RIA+ve/\n",
809 "/622KYIHjB7Nv8MffKcowvr1fExvbyK9vg46/L//I3J3LxekgQOJNm4kysgoH6C4mOjMGaJ33yWy\n",
810 "t+ft7OyI9uypAwPU48yZM2RpaUmtWrWi2bNnU1RUFC1atIjs7e3Jzs6OLl26JLeNj48nxhhFRkbS\n",
811 "7du3yc3NjTw9PUn/4DOaM2cOMcZowYIFRET0xRdfkIWFBWk0GvL29iYiIsYYSZJEY8eOpaioKIqK\n",
812 "iqJp06YRY4z8/PyIiEin0xFjjIYOHSq3MTw2bNhA9+7do9LSUvL19SUzMzMaMWIErV27llavXk1d\n",
813 "unQhxhgtWbLksT6HwsJC8vLyIltbW1q7dq08JyKi5cuXE2OMpk6dSkVFRcQYoyZNmtCJh/7YMQjY\n",
814 "sWPH6ObNm8QYIzMzMwoNDa00j4MHDz7+P1Y9IARMQdq2bUsA6PLly2qbInhAYiL/Lre2JsrMrP/x\n",
815 "9Hqibt34mBs21GHHBQVEH3xAZGtbLmQAUdOmRI6ORGZmxq8HBhIlJ9ehAepw8eJFsrS0pMWLFxu9\n",
816 "np2dTS4uLhQUFCS/tmLFCrK0tKScnBwi4gLFGKPY2FgiKhcwV1dXSkhIIK1WS8uXL6ewsDBijBER\n",
817 "FzCdTlfJDk9PT3J1dSUiomXLlpG5uTkVFxc/0vaAgAByc3Mzek2v19O0adPIwcGhSg+yKoqKikin\n",
818 "05GFhQWlpqZWun/x4sVKAsYYo86dOxu1MwjYb7/9RkREnTt3pldffbVWNqiF2ANTEMNZsKLH2asQ\n",
819 "1CvduvFYiMJCZfbCfv2V5z5s3hwYN64OO7a2Bj76CLh2jeemGjKEH36+d4+n+ygt5ZEq06YBp07x\n",
820 "lPweHnVoAIeI5wDOyOBJk7dtA37+uf6KSnfq1AmzZs0CPRSL5ujoiE2bNiEmJga5DwaPiYmBjY0N\n",
821 "HBwcAABBQUFwdHTE3r17AQBt2rQBANy6dQve3t5o0aIFpk+fjhYtWoBVCJAJDg42Gmv//v24dOkS\n",
822 "/v73vwMAbG1tUVZWhsTERNy8eVN+PHx8Zs2aNZXsZoxh1apVsLW1le2qidWrV+PAgQOYP38+3Nzc\n",
823 "Kt3ftWuXfF3RhgsXLhjtk5WWlqJly5bo1asXAKBp06ZIS0vD9evX5TlkZWXVyibFUFtBGxPdu3cn\n",
824 "AHT27Fm1TRFUID6eOyU2NkR37tTvWCNH8rFCQup3HJmcHKKsLKLCwnobIi/P2Lmr6mFmRjRoEN+y\n",
825 "q2tCQ0MpNDS0ynstWrSg6OhoKigoIK1WS6+88op8Lzs7m4KDg6l///5ERHT06FF5j8rKykr2RFJS\n",
826 "Uow8sI4dO1J8fDxdv36dIiMjycrKivz9/eV+IyMjiTFGtra2JEmSfL3hIZc7LS2N2rZtW6XdCxcu\n",
827 "pMDAwFrN//Tp09S6dWtijNGwYcMo+SHP2uBZzZkzh/75z38SY4zi4+Np6NCh1KJFC8rIyCAiok6d\n",
828 "Ohl5hD169CCNRkM2Njay19axY0e5vSkgPDAFMYTOF5paLY9Gjq8vP8x89y6wbFn9jZOaCuzezWt+\n",
829 "TZ9ef+MY4eAAODkBCh7bMDPjHmbv3rwaS+/eXMYOHwbu3Kn78fR6fbX3fH190aZNG2RmZuLGjRtI\n",
830 "SkpCRkYGli1bBhcXF+zbt6+SVzFv3jzExcXJnoj00EHx5ORk9O7dGy1btsTcuXPh4+OD2NhY+f6e\n",
831 "PXvg7u6OvLw8nDt3DocOHcJff/2FKYbjCg+gR5xg8vHxkT3CmvDx8cG1a9dw+PBh3LlzB15eXthc\n",
832 "RbbqkSNHyqs/vr6++OKLL1BQUIDAwED88ccfuHPnjuxppqenIzExEaGhocjLy8OhQ4dw/vx5JCUl\n",
833 "QavV1souJajt8UlBHWBtbQ1ACJgpsmQJX+qKjOSHnFu3rvsxwsL4F/m4cUCLFnXfv1rY2tZ8lvrO\n",
834 "HeDQIWDAgLof/6effoJOp6v0ekFBAfbv34/NmzfjzgPlPH/+PFq3bg0bGxts374dK1asQFxcHG7d\n",
835 "umX03p49e8rXx48fN7onSRLeeustDB8+HJIkwd/fX94eAPhSXN++fQEAXl5e8PLyqtbu6tixYwf8\n",
836 "/PxqmLkxAwYMwMmTJ7Fu3TrMnDkTXl5e6Nmzpzz3h4XY3d0de/fuhU6nQ9cHNd9GjBghzwEAAgIC\n",
837 "wBjDwIEDH8sWpRAemIIYBEzsgZkevXrxM1lFRfVTgPjKFZ7oXZKARYvqvn9Tx8kJGDOmfpJ8NK+m\n",
838 "0127dsHX1xe2trbya6+++iqOHDmC3NxcvPTSS3jzzTcBACdPnqy2/4c9pcDAQERGRmLIkCEYPHiw\n",
839 "kXiVlZUhNTUVOTk5ICJkZ2cb7YPdv39fbutSzQHAkpIS7Nu3r0pRrglJkjBx4kSYm5vjm2++AVBZ\n",
840 "gCsSEBCAhQsXAuD7b6NHjwYA+dxbVlYWysrKjOZw+/btx7arvhAemIIID8y0+fhjYOdOLjQzZgB/\n",
841 "+1vd9b10KY+jmDhRlNiqa3r27FlJZAoLCxEREYGlD1WxnjJlCvr37y//3KFDBwDAtWvXqgyAMFDR\n",
842 "exk1alS17fLz85Geno709HR4eHggNTVVvscYQ2xsLAIDA2W7q2L58uUYPnw43N3dqx3HQEZGBvbv\n",
843 "34/AwEAcP34cd+/exZo1a5CXl4fg4GBkZ2cjKSkJjDGYm5tX2cf777+P9PR0ODk5YciDsuUXLlwA\n",
844 "AIwZMwatW7fGlStX5PbPPvssUlJSYFbr/Gf1h/oWNCKEgJk2Hh48p21EBN+jOn0a0Gievt+LF3mB\n",
845 "Y0kCPvjg6fsTGENERlGC+fn5eOONN+Dg4CB/IScnJ8PKygq9e/c2eq+Pj4/swXXr1g3u7u7y76kB\n",
846 "Pz8/oz0lQ0adqmjSpAm0Wi08PT3RqlUrBAQE4JlnnkG/fv3g7OxcrWgBPEPPgQMHEBYWhri4uFrN\n",
847 "/ejRo3jjjTcgSZK8F+jn54djx46hT58+uHLlCkpKSsAYg6+vL/5VRRkeSZLw9ddfG73Wvn172NjY\n",
848 "YNSoUdA8+CV4/vnn0aZNG3Tr1s0kxAsQAqYoQsBMn9BQHvp99ixPL7hgwdP1RwTMns1TFs6YIbyv\n",
849 "uqaoqAh79uyBq6sr1q1bh5iYGOzevRu9evXCkSNH5HaXL1+GtbW10XKfgenTp8sBE8nJyZXuP/fc\n",
850 "c3juQbG2KVOmwNfXt1p7LCwskJ6eXivbt23bhpycHKxbtw6pqan46quvUFxcjNjY2Gr3zR6mb9++\n",
851 "sLS0RElJCXQ6HWJiYqptK0mSkdA/iuDgYOTl5dWqraqoGgPZyJg1axYBoBUrVqhtiuARxMaWh36f\n",
852 "Pv10fUVF8b6aNePR7IK6JTEx0SjFkY2NDYWGhlJeXp7aptVI9+7dZbsN6Z/OnTtXp2NkZGSQJEk0\n",
853 "f/58IiJKTU2lnj171ukYaiI8MAURHljDQKfjS4mRkTwM/ORJoFWrx+/nzz+59wXwsi1OTnVrSCc+\n",
854 "OgAADbxJREFUpwBwc3PD4sWLERAQgH79+qltzmMxf/585Obm4u233663MbRarVH5Jjc3N5w9e7be\n",
855 "xlMaIWAKYthEFQUtTZ/wcODMGS5eQ4cCx48Djo61f//t28Dw4TwRxpgxPHhDUPfY2dnhH//4h9pm\n",
856 "PBGTDOUQBE+MCKNXEMP6M4kSbCaPpSWvG9mpE3DhAtCvH8/SVBtycoBhw4DkZJ6q6uuvn6xUl0Ag\n",
857 "eDRCwBRECFjDolkz4OBBHnhx/jzQvTsPsX9UQe3TpwE/P+B//xdo146nHLS3V85mgaAxIQRMQQxn\n",
858 "SYSANRxatwbi4vhyYE4O8NprQIcOPFrx5595iHxCArBxI08K3Ls397y6dgWOHv3PyrghEJgaYg9M\n",
859 "QQwe2KNytwlMDycnvpz43Xf8HFdqKrB4cdVtLSyAuXOBkBCgSRNl7RQIGhtCwBRELCE2XBgDJkzg\n",
860 "ARmHDwN79vCyKFlZXLQ6dAD69OHBGtVkCBIIBHWMWEJUECFgDR8zMyAwkJfcOnECSEoCzp0DduwA\n",
861 "5s0T4mXq6PV6jB8/HpIk4fXXX6+xfWZmJl544QU5N2Bj5ejRowgNDcWPP/6otilGCAFTELEHJhDU\n",
862 "PT/++COcnZ0hSZL86NatGy5fvlyp7axZsxAdHQ07OzusX78eR48ele99//33ePfdd+WfiQgvv/wy\n",
863 "Dh8+jB07dgDguRMrjmN4TJw4Uc4XmJKSgj59+lTZTpIkzJs3DwBw/fp1BAQEGN2zsrLC1q1bn+hz\n",
864 "2LdvH9q3bw9JkvDcc89h586dldro9Xq88847sLCwkMccPXp0td9JOTk5GDJkCAYNGoSUlBR0794d\n",
865 "ALB7925IkoTo6GikpaVBo9HIyYMrMmXKFEiSJCcUDg8Ph52dXZWfi42NDa5fv/54k1bvDHXjY8mS\n",
866 "JQSAFi5cqLYpAsF/BGfOnCFLS0tq1aoVzZ49m6KiomjRokVkb29PdnZ2dOnSJbltfHw8McYoMjKS\n",
867 "bt++TW5ubuTp6Ul6vZ6IiObMmUOMMVqwYAEREX3xxRdkYWFBGo2GvL29iYjkrBljx46lqKgoioqK\n",
868 "omnTphFjjPz8/IiISKfTEWOMhg4dKrcxPDZs2ED37t2j0tJS8vX1JTMzMxoxYgStXbuWVq9eTV26\n",
869 "dCHGGC1ZsuSxPoft27eTmZkZOTg40MKFCyk8PJxGjhxZqV1ERAQxxqhr1670zTffkI+PDzHGaObM\n",
870 "mZXaXr9+nVq1akUuLi60e/duo3uzZ88mxhgtXryYkpKSiDFGLi4ulJSUZNRu8uTJxBijq1ev0unT\n",
871 "p4kxRk2bNqWIiIhKn01cXNxjzZmISAiYgnzyyScEQP4FEQgET8fFixfJ0tKSFi9ebPR6dnY2ubi4\n",
872 "UFBQkPzaihUryNLSknJycoiICxRjjGJjY4moXMBcXV0pISGBtFotLV++nMLCwowqMut0ukp2eHp6\n",
873 "kqurKxERLVu2jMzNzam4uPiRtgcEBBhVQCYi0uv1NG3aNHJwcKA///yzVp/BsWPHSKPRkKurK/3+\n",
874 "++/VtktNTSUzMzPq0qUL/fHHH0REVFZWRmPHjiXGGEVFRclts7Ozydvbm5ycnCg3N7dSX7GxsZUE\n",
875 "zFARuiKTJ08mjUZDmZmZVFJSQg4ODvThhx/Wal61QQRxKIjYAxP8R1JczOvFADx7sV7Po14YA/Lz\n",
876 "gYICwNmZh3MOHgx06VJnQ3fq1AmzZs2q9Dvl6OiITZs2Yfjw4cjNzYW9vT1iYmJgY2MDBwcHAEBQ\n",
877 "UBBCQkLkoo6GhL63bt2Ct7c3evTogenTp2P79u1GSXCDg4ONxtq/fz8uXbqE8PBwAICtrS3KysqQ\n",
878 "mJhoVFXZ2dnZKIv7mjVrEBQUZNQXYwyrVq3CgQMHsHfvXsydO/eR8y8uLsakSZPAGMORI0fg6elZ\n",
879 "bdulS5eiefPmOHv2rJwVSJIkbN26FTk5OVi1ahVee+01AEBISAgSEhLw5Zdfws7OrlJfu3btkq8r\n",
880 "1jg7cOAADh8+jEGDBgHgWYeef/55OeO/lZUVkpOTcfPmTfk9lpaWcHycNDcVqTMpFNRIeHg4AaB3\n",
881 "331XbVMEgrojL49nLK7N45tv6nz40NBQCg0NrfJeixYtKDo6mgoKCkir1dIrr7wi38vOzqbg4GDq\n",
882 "378/EREdPXqUGGM0d+5csrKyot9++42IiFJSUow8sI4dO1J8fDxdv36dIiMjycrKivz9/eV+IyMj\n",
883 "iTFGtra2JEmSfL1hwwYj29LS0qht27ZV2r1w4UIKDAysce7fffcdMcZoxowZj2yXlpZGFhYWdOjQ\n",
884 "oSrvG7y4y5cvExHR3r17ycnJiTQaDU2cOJEyMjKM2huWBlesWEFLly4lOzs7OnfuHPXo0YO8vLwo\n",
885 "Pz+fiIisra1pwIABRMS9y2bNmpG5uTk1adKEGGOk0WioV69edPfu3RrnWhXCA6tniAh//fUXHB0d\n",
886 "H3kOLDc3F3Z2drUudyAQmAwWFvzgmwFJKvfEbG35gbjMTCA3t069LwN6vd6o4GRFfH190aZNG2Rm\n",
887 "ZuLGjRtISkpCRkYGtm7divfeew96vb5S6ZJ58+Zh0qRJcu2uh/tOTk42qivm7+9vVMZkz549cHd3\n",
888 "R3JyMi5cuIDMzEz079+/Uj/0iJUYHx8f3Llzp8a5FxcXAwCmTp36yHZbtmyBr6+v7Bk9jJ2dHfR6\n",
889 "PS5duoR27dohKCgIWVlZ2LlzJ95//305KGTw4MFG7xs5ciQ2btyIZs2aoUuXLli5ciUGDhyIF198\n",
890 "EStXrkRRUZH8nRYXF4ecnBx8++23GD16NI4fP4527dqhXbt2Nc6zWp5I9gS1orS0lGbMmEEeHh50\n",
891 "+/Zt+vTTTwmAXNqAiP9VsnXrVnJ2dqZt27apaK1A0DDx8/OrtAdGRHTv3j2ysLCgvLw8SktLMyq7\n",
892 "YmtrSz/88AP17duXGGOUmZkpe2BXr1416mfjxo1GHphGo6HZs2fTwYMH6eeff6aioiKj9v369aOp\n",
893 "U6fWaPdXX31VrQc2fvx4WrlyZY19GGz+6KOPHtmua9eu9OOPP1Z5r7S0lMaNG0cdOnSg0tLSSvdL\n",
894 "Skrogw8+IK1WS2lpaUREFBQURJIk0ZUrVygkJMRoHtHR0aTRaOTP+uOPPzay9eHP92kQYfT1SGFh\n",
895 "IU6dOoWUlBQEBwfLa8X04C+vq1evYvjw4ZgwYQKysrJM7oyFQNAQMOyvPMyuXbvg6+sLW1tb+bVX\n",
896 "X30VR44cQW5uLl566SW8+eabAICTJ09W2z895CkFBgYiMjISQ4YMweDBg42KZJaVlSE1NRU5OTkg\n",
897 "ImRnZ+PmzZvyo+J+kUs1hwZLSkqwb98+6HS6Gufev39/+Pn5ITQ0FBcvXjS6d+XKFcyaNQvp6ek4\n",
898 "f/58lftMKSkpGDVqFI4cOYJdu3bJ1ZcrYm5ujrfeegs3btxAdHQ0AMhh8VUxZswYTJ48GQDf03v5\n",
899 "5ZflsQAgKysLJSUlRp9LdnZ2jXOtCrGEWI/Y2NggJiYGvXv3Rnx8PO7evQuA/ydfuXIl3nvvPdy7\n",
900 "dw8ODg5Yvnw5pkyZoq7BAkEDpGfPnpVEprCwEBEREVhqCC55wJQpU9C/f3/55w4dOgAArl27Bjc3\n",
901 "t2rHqLj8N2rUqGrb5efnIz09Henp6fDw8EBqaqp8jzGG2NhYBAYGynZXxfLlyzF8+HC4u7tXO05F\n",
902 "tmzZgkGDBsHf3x8zZ87EqFGjkJCQgLlz52LixIlwcHCAi4sL5s+fj/Hjx8P+QXbpU6dO4dtvv0WP\n",
903 "Hj1w6NAhdOrUCQCQlJSEkydPYtiwYThw4AAKCwsRHh4OKysrBAYG4uLFi8jLywNjTA4GeZhVq1Yh\n",
904 "Ly8PAQEB6PigDPmFCxcA8CVXR0dHozNffn5+j/wjojqEgNUzWq0W+/fvR58+ffDHH38AALZv3y5H\n",
905 "4YwePRorV65EC5H1VSB4IojIaO84Pz8fb7zxBhwcHDBkyBAAfN/KysrKaO8K4HtNBg+uW7ducHd3\n",
906 "lwvPGvDz88PmzZvlny0sLKq1pUmTJtBqtfD09ESrVq0QEBCAZ555Bv369YOzs3O1ogXw/awDBw4g\n",
907 "LCwMcXFxtZ5/u3btcOrUKUREROCzzz7DkiVLwBjD+PHjERERgaZNmyImJgbLli3DggULoNfr0aFD\n",
908 "B4wePRrJycmVhHvHjh348MMPIUmSvF8/dOhQxMTEwMvLC7/88gsAoGXLltBqtVXaZG1tje+//97o\n",
909 "NQ8PD7i4uGD48OEAuKAPGjQILi4u8PX1rfV8jaizxUjBI/n1119Jo9EQAAJAWq2Wdu3apbZZAkGD\n",
910 "prCwkHr06EFDhw6ltWvX0siRI4kxRj4+PkaRbWvWrKFmzZpV2UdISEi1+0MPM3Xq1EqHdZ+UsLAw\n",
911 "sre3p7Vr19KiRYvI0dGRmjRpQr/88kud9P+knDhxgjQaDUmSVGV0o2Evq127dkTEo0Cr28urb4SA\n",
912 "KcjUqVMJAHXu3Jn++usvtc0RCBo8iYmJRsEZNjY2FBoaSnl5eWqbViPdu3eX7ZYkiXQ6HZ07d05t\n",
913 "s2rk5MmTpNFo6PPPPyciotOnT9cq5L8+YETiVK1S0ENLHQKB4OnIy8tDZGQkAgIC0K9fP7XNeSw2\n",
914 "b96M3NxcvP3222qb0mARAiYQCASCBokIoxcIBAJBg0QImEAgEAgaJELABAKBQNAgEQImEAgEggaJ\n",
915 "EDCBQCAQNEiEgAkEAoGgQSIETCAQCAQNEiFgAoFAIGiQCAETCAQCQYPk/wEPvRJNIO9OCwAAAABJ\n",
916 "RU5ErkJggg==\n"
917 ],
918 "text/plain": [
919 "<IPython.core.display.Image object>"
920 ]
921 },
922 "execution_count": 10,
923 "metadata": {},
924 "output_type": "execute_result"
925 }
926 ],
270 "outputs": [],
927 271 "source": [
928 272 "from IPython.display import Image\n",
929 273 "Image(data=resources['outputs']['output_3_0.png'],format='png')"
930 274 ]
931 275 },
932 276 {
933 277 "cell_type": "markdown",
934 278 "metadata": {},
935 279 "source": [
936 "Yep, this is indeed the image we were expecting, and I was able to see it without ever writing or reading it from disk. I don't think I'll have to show to you what to do with those data, as if you are here you are most probably familiar with IO."
280 "This image is being rendered without reading or writing to the disk."
937 281 ]
938 282 },
939 283 {
940 284 "cell_type": "markdown",
941 285 "metadata": {},
942 286 "source": [
943 287 "## Extracting figures with HTML Exporter ?"
944 288 ]
945 289 },
946 290 {
947 291 "cell_type": "markdown",
948 292 "metadata": {},
949 293 "source": [
950 294 "Use case:\n",
951 295 "\n",
952 "> I write an [awesome blog](http://jakevdp.github.io/) in HTML, and I want all but having base64 embeded images. \n",
953 "Having one html file with all inside is nice to send to coworker, but I definitively want resources to be cached !\n",
954 "So I need an HTML exporter, and I want it to extract the figures !"
296 "> I write an [awesome blog](http://jakevdp.github.io/) using IPython notebooks converted to HTML, and I want the images to be cached. Having one html file with all of the images base64 encoded inside it is nice when sharing with a coworker, but for a website, not so much. I need an HTML exporter, and I want it to extract the figures!"
955 297 ]
956 298 },
957 299 {
958 300 "cell_type": "markdown",
959 301 "metadata": {},
960 302 "source": [
961 303 "### Some theory"
962 304 ]
963 305 },
964 306 {
965 307 "cell_type": "markdown",
966 308 "metadata": {},
967 309 "source": [
968 "The process of converting a notebook to a another format with the nbconvert Exporters happend in a few steps:\n",
310 "The process of converting a notebook to a another format with happens in a few steps:\n",
969 311 "\n",
970 " - Get the notebook data and other required files. (you are responsible for that)\n",
971 " - Feed them to the exporter that will\n",
972 " - sequentially feed the data to a number of `Preprocessors`. Preprocessor only act on the **structure**\n",
973 " of the notebook, and have access to it all. \n",
974 " - feed the notebook through the jinja templating engine\n",
975 " - the use templates are configurable.\n",
976 " - templates make use of configurable macros called filters.\n",
977 " - The exporter return the converted notebook as well as other relevant resources as a tuple.\n",
978 " - Write what you need to disk, or elsewhere. (You are responsible for it)"
312 " - Retrieve the notebook and it's accompanying resource (you are responsible for this).\n",
313 " - Feed them into the exporter, which:\n",
314 " - Sequentially feeds them into an array of `Preprocessors`. Preprocessors only act on the **structure** of the notebook, and have unrestricted access to it. \n",
315 " - Feeds the notebook into the Jinja templating engine.\n",
316 " - The template is configured (you can change which one is used).\n",
317 " - Templates make use of configurable macros called `filters`.\n",
318 " - The exporter returns the converted notebook and other relevant resources as a tuple.\n",
319 " - You write the data to the disk, or elsewhere (you are responsible for this too)."
979 320 ]
980 321 },
981 322 {
982 323 "cell_type": "markdown",
983 324 "metadata": {},
984 325 "source": [
985 "Here we'll be interested in the `Preprocessors`. Each `Preprocessor` is applied successively and in order on the notebook before going through the conversion process.\n",
986 "\n",
987 "We provide some preprocessor that do some modification on the notebook structure by default.\n",
988 "One of them, the `ExtractOutputPreprocessor` is responsible for crawling notebook,\n",
989 "finding all the figures, and put them into the resources directory, as well as choosing the key\n",
990 "(`filename_xx_y.extension`) that can replace the figure in the template.\n",
991 "\n",
326 "You can use `Preprocessors` to accomplish the task at hand. IPython has preprocessors built in which you can use. One of them, the `ExtractOutputPreprocessor` is responsible for crawling the notebook, finding all of the figures, and putting them into the resources directory, as well as choosing the key (i.e. `filename_xx_y.extension`) that can replace the figure inside the template.\n",
992 327 "\n",
993 "The `ExtractOutputPreprocessor` is special in the fact that it **should** be availlable on all `Exporter`s, but is just inactive by default on some exporter."
328 "The `ExtractOutputPreprocessor` is special because it's available in all of the `Exporter`s, and is just disabled in some by default."
994 329 ]
995 330 },
996 331 {
997 332 "cell_type": "code",
998 "execution_count": 11,
333 "execution_count": null,
999 334 "metadata": {
1000 335 "collapsed": false
1001 336 },
1002 "outputs": [
1003 {
1004 "data": {
1005 "text/plain": [
1006 "[<function IPython.nbconvert.preprocessors.coalescestreams.cell_preprocessor.<locals>.wrappedfunc>,\n",
1007 " <IPython.nbconvert.preprocessors.svg2pdf.SVG2PDFPreprocessor at 0x107d1a630>,\n",
1008 " <IPython.nbconvert.preprocessors.extractoutput.ExtractOutputPreprocessor at 0x107d1a748>,\n",
1009 " <IPython.nbconvert.preprocessors.csshtmlheader.CSSHTMLHeaderPreprocessor at 0x107d1aba8>,\n",
1010 " <IPython.nbconvert.preprocessors.revealhelp.RevealHelpPreprocessor at 0x107d1a710>,\n",
1011 " <IPython.nbconvert.preprocessors.latex.LatexPreprocessor at 0x107daa860>,\n",
1012 " <IPython.nbconvert.preprocessors.clearoutput.ClearOutputPreprocessor at 0x107db7080>,\n",
1013 " <IPython.nbconvert.preprocessors.execute.ExecutePreprocessor at 0x107db7160>,\n",
1014 " <IPython.nbconvert.preprocessors.highlightmagics.HighlightMagicsPreprocessor at 0x107db7048>]"
1015 ]
1016 },
1017 "execution_count": 11,
1018 "metadata": {},
1019 "output_type": "execute_result"
1020 }
1021 ],
337 "outputs": [],
1022 338 "source": [
1023 339 "# 3rd one should be <ExtractOutputPreprocessor>\n",
1024 340 "html_exporter._preprocessors"
1025 341 ]
1026 342 },
1027 343 {
1028 344 "cell_type": "markdown",
1029 345 "metadata": {},
1030 346 "source": [
1031 "To enable it we will use IPython configuration/Traitlets system. If you are have already set some IPython configuration options, \n",
1032 "this will look pretty familiar to you. Configuration option are always of the form:\n",
347 "Use the IPython configuration/Traitlets system to enable it. If you have already set IPython configuration options, this system is familiar to you. Configuration options will always of the form:\n",
1033 348 "\n",
1034 349 " ClassName.attribute_name = value\n",
1035 350 " \n",
1036 "A few ways exist to create such config, like reading a config file in your profile, but you can also do it programatically usign a dictionary. Let's create such a config object, and see the difference if we pass it to our `HTMLExporter`"
351 "You can create a configuration object a couple of different ways. Everytime you launch IPython, configuration objects are created from reading config files in your profile directory. Instead of writing a config file, you can also do it programatically using a dictionary. The following creates a config object, that enables the figure extracter, and passes it to an `HTMLExporter`. The output is compared to an `HTMLExporter` without the config object."
1037 352 ]
1038 353 },
1039 354 {
1040 355 "cell_type": "code",
1041 "execution_count": 12,
356 "execution_count": null,
1042 357 "metadata": {
1043 358 "collapsed": false
1044 359 },
1045 "outputs": [
1046 {
1047 "name": "stdout",
1048 "output_type": "stream",
1049 "text": [
1050 "resources without the \"figures\" key :\n",
1051 "['raw_mimetypes', 'inlining', 'metadata', 'output_extension']\n",
1052 "\n",
1053 "Here we have one more field\n",
1054 "['outputs', 'raw_mimetypes', 'inlining', 'metadata', 'output_extension']\n"
1055 ]
1056 },
1057 {
1058 "data": {
1059 "text/plain": [
1060 "['output_5_0.png',\n",
1061 " 'output_16_0.png',\n",
1062 " 'output_13_1.png',\n",
1063 " 'output_18_1.png',\n",
1064 " 'output_3_0.png']"
1065 ]
1066 },
1067 "execution_count": 12,
1068 "metadata": {},
1069 "output_type": "execute_result"
1070 }
1071 ],
360 "outputs": [],
1072 361 "source": [
1073 362 "from IPython.config import Config\n",
1074 363 "\n",
1075 364 "c = Config({\n",
1076 365 " 'ExtractOutputPreprocessor':{'enabled':True}\n",
1077 366 " })\n",
1078 367 "\n",
1079 368 "exportHTML = HTMLExporter()\n",
1080 369 "exportHTML_and_figs = HTMLExporter(config=c)\n",
1081 370 "\n",
1082 371 "(_, resources) = exportHTML.from_notebook_node(jake_notebook)\n",
1083 372 "(_, resources_with_fig) = exportHTML_and_figs.from_notebook_node(jake_notebook)\n",
1084 373 "\n",
1085 "print('resources without the \"figures\" key :')\n",
374 "print('resources without the \"figures\" key:')\n",
1086 375 "print(list(resources))\n",
1087 376 "\n",
1088 377 "print('')\n",
1089 "print('Here we have one more field')\n",
378 "print('ditto, notice that there\\'s one more field:')\n",
1090 379 "print(list(resources_with_fig))\n",
1091 380 "list(resources_with_fig['outputs'])"
1092 381 ]
1093 382 },
1094 383 {
1095 384 "cell_type": "markdown",
1096 385 "metadata": {},
1097 386 "source": [
1098 "So now you can loop through the dict and write all those figures to disk in the right place... "
1099 ]
1100 },
1101 {
1102 "cell_type": "markdown",
1103 "metadata": {},
1104 "source": [
1105 387 "#### Custom Preprocessor"
1106 388 ]
1107 389 },
1108 390 {
1109 391 "cell_type": "markdown",
1110 392 "metadata": {},
1111 393 "source": [
1112 "Of course you can imagine many transformation that you would like to apply to a notebook. This is one of the reason we provide a way to register your own preprocessors that will be applied to the notebook after the default ones.\n",
394 "There are an endless number of transformations that you may want to apply to a notebook. This is why we provide a way to register your own preprocessors that will be applied to the notebook after the default ones.\n",
1113 395 "\n",
1114 "To do so you'll have to pass an ordered list of `Preprocessor`s to the Exporter constructor. \n",
396 "To do so, you'll have to pass an ordered list of `Preprocessor`s to the `Exporter`'s constructor. \n",
1115 397 "\n",
1116 "But what is an preprocessor ? Preprocessor can be either *decorated function* for dead-simple `Preprocessor`s that apply\n",
1117 "independently to each cell, for more advance transformation that support configurability You have to inherit from\n",
1118 "`Preprocessor` and define a `call` method as we'll see below.\n",
398 "For simple cell-by-cell transformations, `Preprocessor` can be created using a decorator. For more complex operations, you need to subclass `Preprocessor` and define a `call` method (as seen below).\n",
1119 399 "\n",
1120 "All transforers have a magic attribute that allows it to be activated/disactivate from the config dict."
400 "All transforers have a flag that allows you to enable and disable them via a configuration object."
1121 401 ]
1122 402 },
1123 403 {
1124 404 "cell_type": "code",
1125 "execution_count": 13,
405 "execution_count": null,
1126 406 "metadata": {
1127 407 "collapsed": false
1128 408 },
1129 "outputs": [
1130 {
1131 "name": "stdout",
1132 "output_type": "stream",
1133 "text": [
1134 "Four relevant docstring\n",
1135 "=============================\n",
1136 " A configurable preprocessor\n",
1137 "\n",
1138 " Inherit from this class if you wish to have configurability for your\n",
1139 " preprocessor.\n",
1140 "\n",
1141 " Any configurable traitlets this class exposed will be configurable in\n",
1142 " profiles using c.SubClassName.attribute = value\n",
1143 "\n",
1144 " you can overwrite :meth:`preprocess_cell` to apply a transformation\n",
1145 " independently on each cell or :meth:`preprocess` if you prefer your own\n",
1146 " logic. See corresponding docstring for informations.\n",
1147 "\n",
1148 " Disabled by default and can be enabled via the config by\n",
1149 " 'c.YourPreprocessorName.enabled = True'\n",
1150 " \n",
1151 "=============================\n",
1152 "\n",
1153 " Preprocessing to apply on each notebook.\n",
1154 " \n",
1155 " Must return modified nb, resources.\n",
1156 " \n",
1157 " If you wish to apply your preprocessing to each cell, you might want\n",
1158 " to override preprocess_cell method instead.\n",
1159 " \n",
1160 " Parameters\n",
1161 " ----------\n",
1162 " nb : NotebookNode\n",
1163 " Notebook being converted\n",
1164 " resources : dictionary\n",
1165 " Additional resources used in the conversion process. Allows\n",
1166 " preprocessors to pass variables into the Jinja engine.\n",
1167 " \n",
1168 "=============================\n",
1169 "\n",
1170 " Override if you want to apply some preprocessing to each cell.\n",
1171 " Must return modified cell and resource dictionary.\n",
1172 " \n",
1173 " Parameters\n",
1174 " ----------\n",
1175 " cell : NotebookNode cell\n",
1176 " Notebook cell being processed\n",
1177 " resources : dictionary\n",
1178 " Additional resources used in the conversion process. Allows\n",
1179 " preprocessors to pass variables into the Jinja engine.\n",
1180 " index : int\n",
1181 " Index of the cell being processed\n",
1182 " \n",
1183 "=============================\n"
1184 ]
1185 }
1186 ],
409 "outputs": [],
1187 410 "source": [
1188 411 "from IPython.nbconvert.preprocessors import Preprocessor\n",
1189 412 "import IPython.config\n",
1190 413 "print(\"Four relevant docstring\")\n",
1191 414 "print('=============================')\n",
1192 415 "print(Preprocessor.__doc__)\n",
1193 416 "print('=============================')\n",
1194 417 "print(Preprocessor.preprocess.__doc__)\n",
1195 418 "print('=============================')\n",
1196 419 "print(Preprocessor.preprocess_cell.__doc__)\n",
1197 420 "print('=============================')"
1198 421 ]
1199 422 },
1200 423 {
1201 424 "cell_type": "markdown",
1202 425 "metadata": {},
1203 426 "source": [
1204 "***\n",
1205 "We don't provide convenient method to be aplied on each worksheet as the **data structure** for worksheet will be removed. (not the worksheet functionality, which is still on it's way)\n",
1206 "***"
1207 ]
1208 },
1209 {
1210 "cell_type": "markdown",
1211 "metadata": {},
1212 "source": [
1213 427 "### Example"
1214 428 ]
1215 429 },
1216 430 {
1217 431 "cell_type": "markdown",
1218 432 "metadata": {},
1219 433 "source": [
1220 "I'll now demonstrate a specific example [requested](https://github.com/ipython/nbconvert/pull/137#issuecomment-18658235) while nbconvert 2 was being developed. The ability to exclude cell from the conversion process based on their index. \n",
434 "The following demonstration was requested in [an IPython GitHub issue](https://github.com/ipython/nbconvert/pull/137#issuecomment-18658235), the ability to exclude a cell by index. \n",
1221 435 "\n",
1222 "I'll let you imagin how to inject cell, if what you just want is to happend static content at the beginning/end of a notebook, plese refer to templating section, it will be much easier and cleaner."
436 "Inject cells is similar, and won't be covered here. If you want to inject static content at the beginning/end of a notebook, use a custom template."
1223 437 ]
1224 438 },
1225 439 {
1226 440 "cell_type": "code",
1227 "execution_count": 14,
441 "execution_count": null,
1228 442 "metadata": {
1229 443 "collapsed": false
1230 444 },
1231 445 "outputs": [],
1232 446 "source": [
1233 447 "from IPython.utils.traitlets import Integer"
1234 448 ]
1235 449 },
1236 450 {
1237 451 "cell_type": "code",
1238 "execution_count": 15,
452 "execution_count": null,
1239 453 "metadata": {
1240 454 "collapsed": false
1241 455 },
1242 456 "outputs": [],
1243 457 "source": [
1244 458 "class PelicanSubCell(Preprocessor):\n",
1245 " \"\"\"A Pelican specific preprocessor to remove somme of the cells of a notebook\"\"\"\n",
459 " \"\"\"A Pelican specific preprocessor to remove some of the cells of a notebook\"\"\"\n",
1246 460 " \n",
1247 461 " # I could also read the cells from nbc.metadata.pelican is someone wrote a JS extension\n",
1248 462 " # But I'll stay with configurable value. \n",
1249 463 " start = Integer(0, config=True, help=\"first cell of notebook to be converted\")\n",
1250 464 " end = Integer(-1, config=True, help=\"last cell of notebook to be converted\")\n",
1251 465 " \n",
1252 466 " def preprocess(self, nb, resources):\n",
1253 467 "\n",
1254 468 " #nbc = deepcopy(nb)\n",
1255 469 " nbc = nb\n",
1256 470 " # don't print in real preprocessor !!!\n",
1257 471 " print(\"I'll keep only cells from \", self.start, \"to \", self.end, \"\\n\\n\")\n",
1258 472 " nbc.cells = nb.cells[self.start:self.end] \n",
1259 473 " return nbc, resources"
1260 474 ]
1261 475 },
1262 476 {
1263 477 "cell_type": "code",
1264 "execution_count": 16,
478 "execution_count": null,
1265 479 "metadata": {
1266 480 "collapsed": false
1267 481 },
1268 482 "outputs": [],
1269 483 "source": [
1270 484 "# I create this on the fly, but this could be loaded from a DB, and config object support merging...\n",
1271 485 "c = Config()\n",
1272 486 "c.PelicanSubCell.enabled = True\n",
1273 487 "c.PelicanSubCell.start = 4\n",
1274 488 "c.PelicanSubCell.end = 6"
1275 489 ]
1276 490 },
1277 491 {
1278 492 "cell_type": "markdown",
1279 493 "metadata": {},
1280 494 "source": [
1281 "I'm creating a pelican exporter that take `PelicanSubCell` extra preprocessors and a `config` object as parameter. This might seem redundant, but with configuration system you'll see that one can register an inactive preprocessor on all exporters and activate it at will form its config files and command line. "
495 "Here a Pelican exporter is created that takes `PelicanSubCell` preprocessors and a `config` object as parameters. This may seem redundant, but with the configuration system you can register an inactive preprocessor on all of the exporters and activate it from config files or the command line. "
1282 496 ]
1283 497 },
1284 498 {
1285 499 "cell_type": "code",
1286 "execution_count": 17,
500 "execution_count": null,
1287 501 "metadata": {
1288 502 "collapsed": false
1289 503 },
1290 504 "outputs": [],
1291 505 "source": [
1292 506 "pelican = RSTExporter(preprocessors=[PelicanSubCell], config=c)"
1293 507 ]
1294 508 },
1295 509 {
1296 510 "cell_type": "code",
1297 "execution_count": 18,
511 "execution_count": null,
1298 512 "metadata": {
1299 513 "collapsed": false
1300 514 },
1301 "outputs": [
1302 {
1303 "name": "stdout",
1304 "output_type": "stream",
1305 "text": [
1306 "I'll keep only cells from 4 to 6 \n",
1307 "\n",
1308 "\n",
1309 "\n",
1310 "Sometimes when showing schematic plots, this is the type of figure I\n",
1311 "want to display. But drawing it by hand is a pain: I'd rather just use\n",
1312 "matplotlib. The problem is, matplotlib is a bit too precise. Attempting\n",
1313 "to duplicate this figure in matplotlib leads to something like this:\n",
1314 "\n",
1315 ".. code:: python\n",
1316 "\n",
1317 " Image('http://jakevdp.github.com/figures/mpl_version.png')\n",
1318 "\n",
1319 "\n",
1320 "\n",
1321 ".. image:: output_5_0.png\n",
1322 "\n",
1323 "\n",
1324 "\n"
1325 ]
1326 }
1327 ],
515 "outputs": [],
1328 516 "source": [
1329 517 "print(pelican.from_notebook_node(jake_notebook)[0])"
1330 518 ]
1331 519 },
1332 520 {
1333 521 "cell_type": "markdown",
1334 522 "metadata": {},
1335 523 "source": [
1336 524 "### Programatically make templates"
1337 525 ]
1338 526 },
1339 527 {
1340 528 "cell_type": "code",
1341 "execution_count": 19,
529 "execution_count": null,
1342 530 "metadata": {
1343 531 "collapsed": false
1344 532 },
1345 "outputs": [
1346 {
1347 "name": "stdout",
1348 "output_type": "stream",
1349 "text": [
1350 "</div>\n",
1351 "</div>\n",
1352 "FOOOOOOOOTEEEEER\n",
1353 "\n"
1354 ]
1355 }
1356 ],
533 "outputs": [],
1357 534 "source": [
1358 535 "from jinja2 import DictLoader\n",
1359 536 "\n",
1360 537 "dl = DictLoader({'full.tpl': \n",
1361 538 "\"\"\"\n",
1362 539 "{%- extends 'basic.tpl' -%} \n",
1363 540 "\n",
1364 541 "{% block footer %}\n",
1365 542 "FOOOOOOOOTEEEEER\n",
1366 543 "{% endblock footer %}\n",
1367 544 "\"\"\"})\n",
1368 545 "\n",
1369 546 "\n",
1370 547 "exportHTML = HTMLExporter(extra_loaders=[dl])\n",
1371 548 "(body,resources) = exportHTML.from_notebook_node(jake_notebook)\n",
1372 549 "for l in body.split('\\n')[-4:]:\n",
1373 550 " print(l)"
1374 551 ]
1375 552 },
1376 553 {
1377 554 "cell_type": "markdown",
1378 555 "metadata": {},
1379 556 "source": [
1380 557 "### Real World Use"
1381 558 ]
1382 559 },
1383 560 {
1384 561 "cell_type": "markdown",
1385 562 "metadata": {},
1386 563 "source": [
1387 "@jakevdp use Pelican and IPython Notebook to blog. Pelican [Will use](https://github.com/getpelican/pelican-plugins/pull/21) nbconvert programatically to generate blog post. Have a look a [Pythonic Preambulations](http://jakevdp.github.io/) for Jake blog post."
564 "@jakevdp uses Pelican and IPython Notebook to blog. Pelican [will use](https://github.com/getpelican/pelican-plugins/pull/21) nbconvert programatically to generate blog post. Have a look a [Pythonic Preambulations](http://jakevdp.github.io/) for Jake's blog post."
1388 565 ]
1389 566 },
1390 567 {
1391 568 "cell_type": "markdown",
1392 569 "metadata": {},
1393 570 "source": [
1394 "@damianavila Wrote a Nicholas Plugin to [Write blog post as Notebook](http://www.damian.oquanta.info/posts/one-line-deployment-of-your-site-to-gh-pages.html) and is developping a js-extension to publish notebooks in one click from the web app."
571 "@damianavila wrote the Nicholas Plugin to [write blog post as Notebooks](http://www.damian.oquanta.info/posts/one-line-deployment-of-your-site-to-gh-pages.html) and is developping a js-extension to publish notebooks via one click from the web app."
1395 572 ]
1396 573 },
1397 574 {
1398 575 "cell_type": "markdown",
1399 576 "metadata": {},
1400 577 "source": [
1401 578 "<center>\n",
1402 579 "<blockquote class=\"twitter-tweet\"><p>As <a href=\"https://twitter.com/Mbussonn\">@Mbussonn</a> requested... easieeeeer! Deploy your Nikola site with just a click in the IPython notebook! <a href=\"http://t.co/860sJunZvj\">http://t.co/860sJunZvj</a> cc <a href=\"https://twitter.com/ralsina\">@ralsina</a></p>&mdash; Damián Avila (@damian_avila) <a href=\"https://twitter.com/damian_avila/statuses/370306057828335616\">August 21, 2013</a></blockquote>\n",
1403 580 "</center>"
1404 581 ]
1405 582 },
1406 583 {
1407 584 "cell_type": "markdown",
1408 585 "metadata": {},
1409 586 "source": [
1410 "And finaly, what you just did, is replicate what [nbviewer](http://nbviewer.ipython.org) does. WHich to fetch a notebook from url, convert it and send in back to you as a static html."
1411 ]
1412 },
1413 {
1414 "cell_type": "markdown",
1415 "metadata": {},
1416 "source": [
1417 587 "##### A few gotchas"
1418 588 ]
1419 589 },
1420 590 {
1421 591 "cell_type": "markdown",
1422 592 "metadata": {},
1423 593 "source": [
1424 594 "Jinja blocks use `{% %}`by default which does not play nicely with $\\LaTeX$, hence thoses are replaced by `((* *))` in latex templates."
1425 595 ]
1426 596 }
1427 597 ],
1428 598 "metadata": {
1429 599 "kernelspec": {
1430 600 "display_name": "Python 3",
1431 601 "language": "python",
1432 602 "name": "python3"
1433 603 },
1434 604 "language_info": {
1435 605 "codemirror_mode": {
1436 606 "name": "ipython",
1437 607 "version": 3
1438 608 },
1439 609 "file_extension": ".py",
1440 610 "mimetype": "text/x-python",
1441 611 "name": "python",
1442 612 "nbconvert_exporter": "python",
1443 613 "pygments_lexer": "ipython3",
1444 "version": "3.4.2"
614 "version": "3.4.3"
1445 615 }
1446 616 },
1447 617 "nbformat": 4,
1448 618 "nbformat_minor": 0
1449 619 }
@@ -1,184 +1,183 b''
1 1 {
2 2 "cells": [
3 3 {
4 4 "cell_type": "markdown",
5 5 "metadata": {
6 6 "slideshow": {
7 7 "slide_type": "slide"
8 8 }
9 9 },
10 10 "source": [
11 11 "# What is the IPython Notebook?"
12 12 ]
13 13 },
14 14 {
15 15 "cell_type": "markdown",
16 16 "metadata": {},
17 17 "source": [
18 18 "## Introduction"
19 19 ]
20 20 },
21 21 {
22 22 "cell_type": "markdown",
23 23 "metadata": {},
24 24 "source": [
25 25 "The IPython Notebook is an **interactive computing environment** that enables users to author notebook documents that include: \n",
26 26 "- Live code\n",
27 27 "- Interactive widgets\n",
28 28 "- Plots\n",
29 29 "- Narrative text\n",
30 30 "- Equations\n",
31 31 "- Images\n",
32 32 "- Video\n",
33 33 "\n",
34 34 "These documents provide a **complete and self-contained record of a computation** that can be converted to various formats and shared with others using email, [Dropbox](http://dropbox.com), version control systems (like git/[GitHub](http://github.com)) or [nbviewer.ipython.org](http://nbviewer.ipython.org)."
35 35 ]
36 36 },
37 37 {
38 38 "cell_type": "markdown",
39 39 "metadata": {
40 40 "slideshow": {
41 41 "slide_type": "slide"
42 42 }
43 43 },
44 44 "source": [
45 45 "### Components"
46 46 ]
47 47 },
48 48 {
49 49 "cell_type": "markdown",
50 50 "metadata": {},
51 51 "source": [
52 52 "The IPython Notebook combines three components:\n",
53 53 "\n",
54 54 "* **The notebook web application**: An interactive web application for writing and running code interactively and authoring notebook documents.\n",
55 55 "* **Kernels**: Separate processes started by the notebook web application that runs users' code in a given language and returns output back to the notebook web application. The kernel also handles things like computations for interactive widgets, tab completion and introspection. \n",
56 56 "* **Notebook documents**: Self-contained documents that contain a representation of all content visible in the notebook web application, including inputs and outputs of the computations, narrative\n",
57 57 "text, equations, images, and rich media representations of objects. Each notebook document has its own kernel."
58 58 ]
59 59 },
60 60 {
61 61 "cell_type": "markdown",
62 62 "metadata": {
63 63 "slideshow": {
64 64 "slide_type": "slide"
65 65 }
66 66 },
67 67 "source": [
68 68 "## Notebook web application"
69 69 ]
70 70 },
71 71 {
72 72 "cell_type": "markdown",
73 73 "metadata": {},
74 74 "source": [
75 75 "The notebook web application enables users to:\n",
76 76 "\n",
77 77 "* **Edit code in the browser**, with automatic syntax highlighting, indentation, and tab completion/introspection.\n",
78 78 "* **Run code from the browser**, with the results of computations attached to the code which generated them.\n",
79 79 "* See the results of computations with **rich media representations**, such as HTML, LaTeX, PNG, SVG, PDF, etc.\n",
80 80 "* Create and use **interactive JavaScript wigets**, which bind interactive user interface controls and visualizations to reactive kernel side computations.\n",
81 81 "* Author **narrative text** using the [Markdown](https://daringfireball.net/projects/markdown/) markup language.\n",
82 82 "* Build **hierarchical documents** that are organized into sections with different levels of headings.\n",
83 83 "* Include mathematical equations using **LaTeX syntax in Markdown**, which are rendered in-browser by [MathJax](http://www.mathjax.org/).\n",
84 84 "* Start **parallel computing** clusters that work with IPython's interactive parallel computing libraries `IPython.parallel`."
85 85 ]
86 86 },
87 87 {
88 88 "cell_type": "markdown",
89 89 "metadata": {
90 90 "slideshow": {
91 91 "slide_type": "slide"
92 92 }
93 93 },
94 94 "source": [
95 95 "## Kernels"
96 96 ]
97 97 },
98 98 {
99 99 "cell_type": "markdown",
100 100 "metadata": {},
101 101 "source": [
102 102 "Through IPython's kernel and messaging architecture, the Notebook allows code to be run in a range of different programming languages. For each notebook document that a user opens, the web application starts a kernel that runs the code for that notebook. Each kernel is capable of running code in a single programming language and there are kernels available in the following languages:\n",
103 103 "\n",
104 104 "* Python(https://github.com/ipython/ipython)\n",
105 105 "* Julia (https://github.com/JuliaLang/IJulia.jl)\n",
106 106 "* R (https://github.com/takluyver/IRkernel)\n",
107 107 "* Ruby (https://github.com/minrk/iruby)\n",
108 108 "* Haskell (https://github.com/gibiansky/IHaskell)\n",
109 109 "* Scala (https://github.com/Bridgewater/scala-notebook)\n",
110 110 "* node.js (https://gist.github.com/Carreau/4279371)\n",
111 111 "* Go (https://github.com/takluyver/igo)\n",
112 112 "\n",
113 "The default kernel runs Python code. When it is released in the Summer/Fall of 2014, IPython 3.0 will provide a simple way for users to pick which of these kernels is used for a given notebook. \n",
113 "The default kernel runs Python code. IPython 3.0 provides a simple way for users to pick which of these kernels is used for a given notebook. \n",
114 114 "\n",
115 115 "Each of these kernels communicate with the notebook web application and web browser using a JSON over ZeroMQ/WebSockets message protocol that is described [here](http://ipython.org/ipython-doc/dev/development/messaging.html). Most users don't need to know about these details, but it helps to understand that \"kernels run code.\""
116 116 ]
117 117 },
118 118 {
119 119 "cell_type": "markdown",
120 120 "metadata": {
121 121 "slideshow": {
122 122 "slide_type": "slide"
123 123 }
124 124 },
125 125 "source": [
126 126 "## Notebook documents"
127 127 ]
128 128 },
129 129 {
130 130 "cell_type": "markdown",
131 131 "metadata": {},
132 132 "source": [
133 133 "Notebook documents contain the **inputs and outputs** of an interactive session as well as **narrative text** that accompanies the code but is not meant for execution. **Rich output** generated by running code, including HTML, images, video, and plots, is embeddeed in the notebook, which makes it a complete and self-contained record of a computation. "
134 134 ]
135 135 },
136 136 {
137 137 "cell_type": "markdown",
138 138 "metadata": {},
139 139 "source": [
140 "When you run the notebook web application on your computer, notebook documents are just **files on your local filesystem with a `.ipynb` extension**. This allows you to use familiar workflows for organizing your notebooks into folders and sharing them with others using email, Dropbox and version control systems."
140 "When you run the notebook web application on your computer, notebook documents are just **files on your local filesystem with a `.ipynb` extension**. This allows you to use familiar workflows for organizing your notebooks into folders and sharing them with others."
141 141 ]
142 142 },
143 143 {
144 144 "cell_type": "markdown",
145 145 "metadata": {},
146 146 "source": [
147 147 "Notebooks consist of a **linear sequence of cells**. There are four basic cell types:\n",
148 148 "\n",
149 149 "* **Code cells:** Input and output of live code that is run in the kernel\n",
150 150 "* **Markdown cells:** Narrative text with embedded LaTeX equations\n",
151 151 "* **Heading cells:** 6 levels of hierarchical organization and formatting\n",
152 152 "* **Raw cells:** Unformatted text that is included, without modification, when notebooks are converted to different formats using nbconvert\n",
153 153 "\n",
154 154 "Internally, notebook documents are **[JSON](http://en.wikipedia.org/wiki/JSON) data** with **binary values [base64](http://en.wikipedia.org/wiki/Base64)** encoded. This allows them to be **read and manipulated programmatically** by any programming language. Because JSON is a text format, notebook documents are version control friendly.\n",
155 155 "\n",
156 156 "**Notebooks can be exported** to different static formats including HTML, reStructeredText, LaTeX, PDF, and slide shows ([reveal.js](http://lab.hakim.se/reveal-js/#/)) using IPython's `nbconvert` utility.\n",
157 157 "\n",
158 158 "Furthermore, any notebook document available from a **public URL on or GitHub can be shared** via [nbviewer](http://nbviewer.ipython.org). This service loads the notebook document from the URL and renders it as a static web page. The resulting web page may thus be shared with others **without their needing to install IPython**."
159 159 ]
160 160 }
161 161 ],
162 162 "metadata": {
163 "celltoolbar": "Slideshow",
164 163 "kernelspec": {
165 164 "display_name": "Python 3",
166 165 "language": "python",
167 166 "name": "python3"
168 167 },
169 168 "language_info": {
170 169 "codemirror_mode": {
171 170 "name": "ipython",
172 171 "version": 3
173 172 },
174 173 "file_extension": ".py",
175 174 "mimetype": "text/x-python",
176 175 "name": "python",
177 176 "nbconvert_exporter": "python",
178 177 "pygments_lexer": "ipython3",
179 "version": "3.4.2"
178 "version": "3.4.3"
180 179 }
181 180 },
182 181 "nbformat": 4,
183 182 "nbformat_minor": 0
184 183 }
@@ -1,320 +1,320 b''
1 1 {
2 2 "cells": [
3 3 {
4 4 "cell_type": "markdown",
5 5 "metadata": {},
6 6 "source": [
7 7 "# Markdown Cells"
8 8 ]
9 9 },
10 10 {
11 11 "cell_type": "markdown",
12 12 "metadata": {},
13 13 "source": [
14 14 "Text can be added to IPython Notebooks using Markdown cells. Markdown is a popular markup language that is a superset of HTML. Its specification can be found here:\n",
15 15 "\n",
16 16 "<http://daringfireball.net/projects/markdown/>"
17 17 ]
18 18 },
19 19 {
20 20 "cell_type": "markdown",
21 21 "metadata": {},
22 22 "source": [
23 23 "## Markdown basics"
24 24 ]
25 25 },
26 26 {
27 27 "cell_type": "markdown",
28 28 "metadata": {},
29 29 "source": [
30 30 "You can make text *italic* or **bold**."
31 31 ]
32 32 },
33 33 {
34 34 "cell_type": "markdown",
35 35 "metadata": {},
36 36 "source": [
37 37 "You can build nested itemized or enumerated lists:\n",
38 38 "\n",
39 39 "* One\n",
40 40 " - Sublist\n",
41 41 " - This\n",
42 42 " - Sublist\n",
43 43 " - That\n",
44 44 " - The other thing\n",
45 45 "* Two\n",
46 46 " - Sublist\n",
47 47 "* Three\n",
48 48 " - Sublist\n",
49 49 "\n",
50 50 "Now another list:\n",
51 51 "\n",
52 52 "1. Here we go\n",
53 53 " 1. Sublist\n",
54 54 " 2. Sublist\n",
55 55 "2. There we go\n",
56 56 "3. Now this"
57 57 ]
58 58 },
59 59 {
60 60 "cell_type": "markdown",
61 61 "metadata": {},
62 62 "source": [
63 63 "You can add horizontal rules:\n",
64 64 "\n",
65 65 "---"
66 66 ]
67 67 },
68 68 {
69 69 "cell_type": "markdown",
70 70 "metadata": {},
71 71 "source": [
72 72 "Here is a blockquote:\n",
73 73 "\n",
74 74 "> Beautiful is better than ugly.\n",
75 75 "> Explicit is better than implicit.\n",
76 76 "> Simple is better than complex.\n",
77 77 "> Complex is better than complicated.\n",
78 78 "> Flat is better than nested.\n",
79 79 "> Sparse is better than dense.\n",
80 80 "> Readability counts.\n",
81 81 "> Special cases aren't special enough to break the rules.\n",
82 82 "> Although practicality beats purity.\n",
83 83 "> Errors should never pass silently.\n",
84 84 "> Unless explicitly silenced.\n",
85 85 "> In the face of ambiguity, refuse the temptation to guess.\n",
86 86 "> There should be one-- and preferably only one --obvious way to do it.\n",
87 87 "> Although that way may not be obvious at first unless you're Dutch.\n",
88 88 "> Now is better than never.\n",
89 89 "> Although never is often better than *right* now.\n",
90 90 "> If the implementation is hard to explain, it's a bad idea.\n",
91 91 "> If the implementation is easy to explain, it may be a good idea.\n",
92 92 "> Namespaces are one honking great idea -- let's do more of those!"
93 93 ]
94 94 },
95 95 {
96 96 "cell_type": "markdown",
97 97 "metadata": {},
98 98 "source": [
99 99 "And shorthand for links:\n",
100 100 "\n",
101 101 "[IPython's website](http://ipython.org)"
102 102 ]
103 103 },
104 104 {
105 105 "cell_type": "markdown",
106 106 "metadata": {},
107 107 "source": [
108 108 "## Headings"
109 109 ]
110 110 },
111 111 {
112 112 "cell_type": "markdown",
113 113 "metadata": {},
114 114 "source": [
115 115 "If you want, you can add headings using Markdown's syntax:\n",
116 116 "\n",
117 117 "# Heading 1\n",
118 118 "# Heading 2\n",
119 119 "## Heading 2.1\n",
120 120 "## Heading 2.2"
121 121 ]
122 122 },
123 123 {
124 124 "cell_type": "markdown",
125 125 "metadata": {},
126 126 "source": [
127 127 "**BUT most of the time you should use the Notebook's Heading Cells to organize your Notebook content**, as they provide meaningful structure that can be interpreted by other tools, not just large bold fonts."
128 128 ]
129 129 },
130 130 {
131 131 "cell_type": "markdown",
132 132 "metadata": {},
133 133 "source": [
134 134 "## Embedded code"
135 135 ]
136 136 },
137 137 {
138 138 "cell_type": "markdown",
139 139 "metadata": {},
140 140 "source": [
141 141 "You can embed code meant for illustration instead of execution in Python:\n",
142 142 "\n",
143 143 " def f(x):\n",
144 144 " \"\"\"a docstring\"\"\"\n",
145 145 " return x**2\n",
146 146 "\n",
147 147 "or other languages:\n",
148 148 "\n",
149 149 " if (i=0; i<n; i++) {\n",
150 150 " printf(\"hello %d\\n\", i);\n",
151 151 " x += 4;\n",
152 152 " }"
153 153 ]
154 154 },
155 155 {
156 156 "cell_type": "markdown",
157 157 "metadata": {},
158 158 "source": [
159 159 "## LaTeX equations"
160 160 ]
161 161 },
162 162 {
163 163 "cell_type": "markdown",
164 164 "metadata": {},
165 165 "source": [
166 166 "Courtesy of MathJax, you can include mathematical expressions both inline: \n",
167 167 "$e^{i\\pi} + 1 = 0$ and displayed:\n",
168 168 "\n",
169 169 "$$e^x=\\sum_{i=0}^\\infty \\frac{1}{i!}x^i$$"
170 170 ]
171 171 },
172 172 {
173 173 "cell_type": "markdown",
174 174 "metadata": {},
175 175 "source": [
176 176 "## Github flavored markdown (GFM)"
177 177 ]
178 178 },
179 179 {
180 180 "cell_type": "markdown",
181 181 "metadata": {},
182 182 "source": [
183 183 "The Notebook webapp support Github flavored markdown meaning that you can use triple backticks for code blocks \n",
184 184 "<pre>\n",
185 185 "```python\n",
186 186 "print \"Hello World\"\n",
187 187 "```\n",
188 188 "\n",
189 189 "```javascript\n",
190 190 "console.log(\"Hello World\")\n",
191 191 "```\n",
192 192 "</pre>\n",
193 193 "\n",
194 194 "Gives \n",
195 195 "```python\n",
196 196 "print \"Hello World\"\n",
197 197 "```\n",
198 198 "\n",
199 199 "```javascript\n",
200 200 "console.log(\"Hello World\")\n",
201 201 "```\n",
202 202 "\n",
203 203 "And a table like this : \n",
204 204 "\n",
205 205 "<pre>\n",
206 206 "| This | is |\n",
207 207 "|------|------|\n",
208 208 "| a | table| \n",
209 209 "</pre>\n",
210 210 "\n",
211 211 "A nice Html Table\n",
212 212 "\n",
213 213 "| This | is |\n",
214 214 "|------|------|\n",
215 215 "| a | table| "
216 216 ]
217 217 },
218 218 {
219 219 "cell_type": "markdown",
220 220 "metadata": {},
221 221 "source": [
222 222 "## General HTML"
223 223 ]
224 224 },
225 225 {
226 226 "cell_type": "markdown",
227 227 "metadata": {},
228 228 "source": [
229 229 "Because Markdown is a superset of HTML you can even add things like HTML tables:\n",
230 230 "\n",
231 231 "<table>\n",
232 232 "<tr>\n",
233 233 "<th>Header 1</th>\n",
234 234 "<th>Header 2</th>\n",
235 235 "</tr>\n",
236 236 "<tr>\n",
237 237 "<td>row 1, cell 1</td>\n",
238 238 "<td>row 1, cell 2</td>\n",
239 239 "</tr>\n",
240 240 "<tr>\n",
241 241 "<td>row 2, cell 1</td>\n",
242 242 "<td>row 2, cell 2</td>\n",
243 243 "</tr>\n",
244 244 "</table>"
245 245 ]
246 246 },
247 247 {
248 248 "cell_type": "markdown",
249 249 "metadata": {},
250 250 "source": [
251 251 "## Local files"
252 252 ]
253 253 },
254 254 {
255 255 "cell_type": "markdown",
256 256 "metadata": {},
257 257 "source": [
258 258 "If you have local files in your Notebook directory, you can refer to these files in Markdown cells directly:\n",
259 259 "\n",
260 260 " [subdirectory/]<filename>\n",
261 261 "\n",
262 262 "For example, in the images folder, we have the Python logo:\n",
263 263 "\n",
264 264 " <img src=\"../images/python_logo.svg\" />\n",
265 265 "\n",
266 266 "<img src=\"../images/python_logo.svg\" />\n",
267 267 "\n",
268 268 "and a video with the HTML5 video tag:\n",
269 269 "\n",
270 270 " <video controls src=\"images/animation.m4v\" />\n",
271 271 "\n",
272 272 "<video controls src=\"images/animation.m4v\" />\n",
273 273 "\n",
274 274 "These do not embed the data into the notebook file, and require that the files exist when you are viewing the notebook."
275 275 ]
276 276 },
277 277 {
278 278 "cell_type": "markdown",
279 279 "metadata": {},
280 280 "source": [
281 281 "### Security of local files"
282 282 ]
283 283 },
284 284 {
285 285 "cell_type": "markdown",
286 286 "metadata": {},
287 287 "source": [
288 288 "Note that this means that the IPython notebook server also acts as a generic file server\n",
289 289 "for files inside the same tree as your notebooks. Access is not granted outside the\n",
290 290 "notebook folder so you have strict control over what files are visible, but for this\n",
291 291 "reason it is highly recommended that you do not run the notebook server with a notebook\n",
292 292 "directory at a high level in your filesystem (e.g. your home directory).\n",
293 293 "\n",
294 294 "When you run the notebook in a password-protected manner, local file access is restricted\n",
295 295 "to authenticated users unless read-only views are active."
296 296 ]
297 297 }
298 298 ],
299 299 "metadata": {
300 300 "kernelspec": {
301 301 "display_name": "Python 3",
302 302 "language": "python",
303 303 "name": "python3"
304 304 },
305 305 "language_info": {
306 306 "codemirror_mode": {
307 307 "name": "ipython",
308 308 "version": 3
309 309 },
310 310 "file_extension": ".py",
311 311 "mimetype": "text/x-python",
312 312 "name": "python",
313 313 "nbconvert_exporter": "python",
314 314 "pygments_lexer": "ipython3",
315 "version": "3.4.2"
315 "version": "3.4.3"
316 316 }
317 317 },
318 318 "nbformat": 4,
319 319 "nbformat_minor": 0
320 320 }
1 NO CONTENT: modified file, binary diff hidden
1 NO CONTENT: modified file, binary diff hidden
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
General Comments 0
You need to be logged in to leave comments. Login now