Show More
@@ -1,131 +1,131 b'' | |||
|
1 | 1 | # coding: utf-8 |
|
2 | 2 | import base64 |
|
3 | 3 | import io |
|
4 | 4 | import json |
|
5 | 5 | import os |
|
6 | 6 | from os.path import join as pjoin |
|
7 | 7 | import shutil |
|
8 | 8 | |
|
9 | 9 | import requests |
|
10 | 10 | |
|
11 | 11 | from IPython.html.utils import url_path_join |
|
12 | 12 | from IPython.html.tests.launchnotebook import NotebookTestBase, assert_http_error |
|
13 | 13 | from IPython.nbformat.current import (new_notebook, write, |
|
14 |
new_ |
|
|
14 | new_markdown_cell, new_code_cell, | |
|
15 | 15 | new_output) |
|
16 | 16 | |
|
17 | 17 | from IPython.testing.decorators import onlyif_cmds_exist |
|
18 | 18 | |
|
19 | 19 | |
|
20 | 20 | class NbconvertAPI(object): |
|
21 | 21 | """Wrapper for nbconvert API calls.""" |
|
22 | 22 | def __init__(self, base_url): |
|
23 | 23 | self.base_url = base_url |
|
24 | 24 | |
|
25 | 25 | def _req(self, verb, path, body=None, params=None): |
|
26 | 26 | response = requests.request(verb, |
|
27 | 27 | url_path_join(self.base_url, 'nbconvert', path), |
|
28 | 28 | data=body, params=params, |
|
29 | 29 | ) |
|
30 | 30 | response.raise_for_status() |
|
31 | 31 | return response |
|
32 | 32 | |
|
33 | 33 | def from_file(self, format, path, name, download=False): |
|
34 | 34 | return self._req('GET', url_path_join(format, path, name), |
|
35 | 35 | params={'download':download}) |
|
36 | 36 | |
|
37 | 37 | def from_post(self, format, nbmodel): |
|
38 | 38 | body = json.dumps(nbmodel) |
|
39 | 39 | return self._req('POST', format, body) |
|
40 | 40 | |
|
41 | 41 | def list_formats(self): |
|
42 | 42 | return self._req('GET', '') |
|
43 | 43 | |
|
44 | 44 | png_green_pixel = base64.encodestring(b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00' |
|
45 | 45 | b'\x00\x00\x01\x00\x00x00\x01\x08\x02\x00\x00\x00\x90wS\xde\x00\x00\x00\x0cIDAT' |
|
46 | 46 | b'\x08\xd7c\x90\xfb\xcf\x00\x00\x02\\\x01\x1e.~d\x87\x00\x00\x00\x00IEND\xaeB`\x82' |
|
47 | 47 | ).decode('ascii') |
|
48 | 48 | |
|
49 | 49 | class APITest(NotebookTestBase): |
|
50 | 50 | def setUp(self): |
|
51 | 51 | nbdir = self.notebook_dir.name |
|
52 | 52 | |
|
53 | 53 | if not os.path.isdir(pjoin(nbdir, 'foo')): |
|
54 | 54 | os.mkdir(pjoin(nbdir, 'foo')) |
|
55 | 55 | |
|
56 | 56 | nb = new_notebook() |
|
57 | 57 | |
|
58 |
nb.cells.append(new_ |
|
|
58 | nb.cells.append(new_markdown_cell(u'Created by test ³')) | |
|
59 | 59 | cc1 = new_code_cell(source=u'print(2*6)') |
|
60 | 60 | cc1.outputs.append(new_output(output_type="stream", text=u'12')) |
|
61 | 61 | cc1.outputs.append(new_output(output_type="execute_result", |
|
62 | 62 | data={'image/png' : png_green_pixel}, |
|
63 | 63 | execution_count=1, |
|
64 | 64 | )) |
|
65 | 65 | nb.cells.append(cc1) |
|
66 | 66 | |
|
67 | 67 | with io.open(pjoin(nbdir, 'foo', 'testnb.ipynb'), 'w', |
|
68 | 68 | encoding='utf-8') as f: |
|
69 | 69 | write(nb, f) |
|
70 | 70 | |
|
71 | 71 | self.nbconvert_api = NbconvertAPI(self.base_url()) |
|
72 | 72 | |
|
73 | 73 | def tearDown(self): |
|
74 | 74 | nbdir = self.notebook_dir.name |
|
75 | 75 | |
|
76 | 76 | for dname in ['foo']: |
|
77 | 77 | shutil.rmtree(pjoin(nbdir, dname), ignore_errors=True) |
|
78 | 78 | |
|
79 | 79 | @onlyif_cmds_exist('pandoc') |
|
80 | 80 | def test_from_file(self): |
|
81 | 81 | r = self.nbconvert_api.from_file('html', 'foo', 'testnb.ipynb') |
|
82 | 82 | self.assertEqual(r.status_code, 200) |
|
83 | 83 | self.assertIn(u'text/html', r.headers['Content-Type']) |
|
84 | 84 | self.assertIn(u'Created by test', r.text) |
|
85 | 85 | self.assertIn(u'print', r.text) |
|
86 | 86 | |
|
87 | 87 | r = self.nbconvert_api.from_file('python', 'foo', 'testnb.ipynb') |
|
88 | 88 | self.assertIn(u'text/x-python', r.headers['Content-Type']) |
|
89 | 89 | self.assertIn(u'print(2*6)', r.text) |
|
90 | 90 | |
|
91 | 91 | @onlyif_cmds_exist('pandoc') |
|
92 | 92 | def test_from_file_404(self): |
|
93 | 93 | with assert_http_error(404): |
|
94 | 94 | self.nbconvert_api.from_file('html', 'foo', 'thisdoesntexist.ipynb') |
|
95 | 95 | |
|
96 | 96 | @onlyif_cmds_exist('pandoc') |
|
97 | 97 | def test_from_file_download(self): |
|
98 | 98 | r = self.nbconvert_api.from_file('python', 'foo', 'testnb.ipynb', download=True) |
|
99 | 99 | content_disposition = r.headers['Content-Disposition'] |
|
100 | 100 | self.assertIn('attachment', content_disposition) |
|
101 | 101 | self.assertIn('testnb.py', content_disposition) |
|
102 | 102 | |
|
103 | 103 | @onlyif_cmds_exist('pandoc') |
|
104 | 104 | def test_from_file_zip(self): |
|
105 | 105 | r = self.nbconvert_api.from_file('latex', 'foo', 'testnb.ipynb', download=True) |
|
106 | 106 | self.assertIn(u'application/zip', r.headers['Content-Type']) |
|
107 | 107 | self.assertIn(u'.zip', r.headers['Content-Disposition']) |
|
108 | 108 | |
|
109 | 109 | @onlyif_cmds_exist('pandoc') |
|
110 | 110 | def test_from_post(self): |
|
111 | 111 | nbmodel_url = url_path_join(self.base_url(), 'api/contents/foo/testnb.ipynb') |
|
112 | 112 | nbmodel = requests.get(nbmodel_url).json() |
|
113 | 113 | |
|
114 | 114 | r = self.nbconvert_api.from_post(format='html', nbmodel=nbmodel) |
|
115 | 115 | self.assertEqual(r.status_code, 200) |
|
116 | 116 | self.assertIn(u'text/html', r.headers['Content-Type']) |
|
117 | 117 | self.assertIn(u'Created by test', r.text) |
|
118 | 118 | self.assertIn(u'print', r.text) |
|
119 | 119 | |
|
120 | 120 | r = self.nbconvert_api.from_post(format='python', nbmodel=nbmodel) |
|
121 | 121 | self.assertIn(u'text/x-python', r.headers['Content-Type']) |
|
122 | 122 | self.assertIn(u'print(2*6)', r.text) |
|
123 | 123 | |
|
124 | 124 | @onlyif_cmds_exist('pandoc') |
|
125 | 125 | def test_from_post_zip(self): |
|
126 | 126 | nbmodel_url = url_path_join(self.base_url(), 'api/contents/foo/testnb.ipynb') |
|
127 | 127 | nbmodel = requests.get(nbmodel_url).json() |
|
128 | 128 | |
|
129 | 129 | r = self.nbconvert_api.from_post(format='latex', nbmodel=nbmodel) |
|
130 | 130 | self.assertIn(u'application/zip', r.headers['Content-Type']) |
|
131 | 131 | self.assertIn(u'.zip', r.headers['Content-Disposition']) |
@@ -1,545 +1,545 b'' | |||
|
1 | 1 | """A contents manager that uses the local file system for storage.""" |
|
2 | 2 | |
|
3 | 3 | # Copyright (c) IPython Development Team. |
|
4 | 4 | # Distributed under the terms of the Modified BSD License. |
|
5 | 5 | |
|
6 | 6 | import base64 |
|
7 | 7 | import io |
|
8 | 8 | import os |
|
9 | 9 | import glob |
|
10 | 10 | import shutil |
|
11 | 11 | |
|
12 | 12 | from tornado import web |
|
13 | 13 | |
|
14 | 14 | from .manager import ContentsManager |
|
15 | 15 | from IPython.nbformat import current |
|
16 | 16 | from IPython.utils.io import atomic_writing |
|
17 | 17 | from IPython.utils.path import ensure_dir_exists |
|
18 | 18 | from IPython.utils.traitlets import Unicode, Bool, TraitError |
|
19 | 19 | from IPython.utils.py3compat import getcwd |
|
20 | 20 | from IPython.utils import tz |
|
21 | 21 | from IPython.html.utils import is_hidden, to_os_path, url_path_join |
|
22 | 22 | |
|
23 | 23 | |
|
24 | 24 | class FileContentsManager(ContentsManager): |
|
25 | 25 | |
|
26 | 26 | root_dir = Unicode(getcwd(), config=True) |
|
27 | 27 | |
|
28 | 28 | save_script = Bool(False, config=True, help='DEPRECATED, IGNORED') |
|
29 | 29 | def _save_script_changed(self): |
|
30 | 30 | self.log.warn(""" |
|
31 | 31 | Automatically saving notebooks as scripts has been removed. |
|
32 | 32 | Use `ipython nbconvert --to python [notebook]` instead. |
|
33 | 33 | """) |
|
34 | 34 | |
|
35 | 35 | def _root_dir_changed(self, name, old, new): |
|
36 | 36 | """Do a bit of validation of the root_dir.""" |
|
37 | 37 | if not os.path.isabs(new): |
|
38 | 38 | # If we receive a non-absolute path, make it absolute. |
|
39 | 39 | self.root_dir = os.path.abspath(new) |
|
40 | 40 | return |
|
41 | 41 | if not os.path.isdir(new): |
|
42 | 42 | raise TraitError("%r is not a directory" % new) |
|
43 | 43 | |
|
44 | 44 | checkpoint_dir = Unicode('.ipynb_checkpoints', config=True, |
|
45 | 45 | help="""The directory name in which to keep file checkpoints |
|
46 | 46 | |
|
47 | 47 | This is a path relative to the file's own directory. |
|
48 | 48 | |
|
49 | 49 | By default, it is .ipynb_checkpoints |
|
50 | 50 | """ |
|
51 | 51 | ) |
|
52 | 52 | |
|
53 | 53 | def _copy(self, src, dest): |
|
54 | 54 | """copy src to dest |
|
55 | 55 | |
|
56 | 56 | like shutil.copy2, but log errors in copystat |
|
57 | 57 | """ |
|
58 | 58 | shutil.copyfile(src, dest) |
|
59 | 59 | try: |
|
60 | 60 | shutil.copystat(src, dest) |
|
61 | 61 | except OSError as e: |
|
62 | 62 | self.log.debug("copystat on %s failed", dest, exc_info=True) |
|
63 | 63 | |
|
64 | 64 | def _get_os_path(self, name=None, path=''): |
|
65 | 65 | """Given a filename and API path, return its file system |
|
66 | 66 | path. |
|
67 | 67 | |
|
68 | 68 | Parameters |
|
69 | 69 | ---------- |
|
70 | 70 | name : string |
|
71 | 71 | A filename |
|
72 | 72 | path : string |
|
73 | 73 | The relative API path to the named file. |
|
74 | 74 | |
|
75 | 75 | Returns |
|
76 | 76 | ------- |
|
77 | 77 | path : string |
|
78 | 78 | API path to be evaluated relative to root_dir. |
|
79 | 79 | """ |
|
80 | 80 | if name is not None: |
|
81 | 81 | path = url_path_join(path, name) |
|
82 | 82 | return to_os_path(path, self.root_dir) |
|
83 | 83 | |
|
84 | 84 | def path_exists(self, path): |
|
85 | 85 | """Does the API-style path refer to an extant directory? |
|
86 | 86 | |
|
87 | 87 | API-style wrapper for os.path.isdir |
|
88 | 88 | |
|
89 | 89 | Parameters |
|
90 | 90 | ---------- |
|
91 | 91 | path : string |
|
92 | 92 | The path to check. This is an API path (`/` separated, |
|
93 | 93 | relative to root_dir). |
|
94 | 94 | |
|
95 | 95 | Returns |
|
96 | 96 | ------- |
|
97 | 97 | exists : bool |
|
98 | 98 | Whether the path is indeed a directory. |
|
99 | 99 | """ |
|
100 | 100 | path = path.strip('/') |
|
101 | 101 | os_path = self._get_os_path(path=path) |
|
102 | 102 | return os.path.isdir(os_path) |
|
103 | 103 | |
|
104 | 104 | def is_hidden(self, path): |
|
105 | 105 | """Does the API style path correspond to a hidden directory or file? |
|
106 | 106 | |
|
107 | 107 | Parameters |
|
108 | 108 | ---------- |
|
109 | 109 | path : string |
|
110 | 110 | The path to check. This is an API path (`/` separated, |
|
111 | 111 | relative to root_dir). |
|
112 | 112 | |
|
113 | 113 | Returns |
|
114 | 114 | ------- |
|
115 | 115 | exists : bool |
|
116 | 116 | Whether the path is hidden. |
|
117 | 117 | |
|
118 | 118 | """ |
|
119 | 119 | path = path.strip('/') |
|
120 | 120 | os_path = self._get_os_path(path=path) |
|
121 | 121 | return is_hidden(os_path, self.root_dir) |
|
122 | 122 | |
|
123 | 123 | def file_exists(self, name, path=''): |
|
124 | 124 | """Returns True if the file exists, else returns False. |
|
125 | 125 | |
|
126 | 126 | API-style wrapper for os.path.isfile |
|
127 | 127 | |
|
128 | 128 | Parameters |
|
129 | 129 | ---------- |
|
130 | 130 | name : string |
|
131 | 131 | The name of the file you are checking. |
|
132 | 132 | path : string |
|
133 | 133 | The relative path to the file's directory (with '/' as separator) |
|
134 | 134 | |
|
135 | 135 | Returns |
|
136 | 136 | ------- |
|
137 | 137 | exists : bool |
|
138 | 138 | Whether the file exists. |
|
139 | 139 | """ |
|
140 | 140 | path = path.strip('/') |
|
141 | 141 | nbpath = self._get_os_path(name, path=path) |
|
142 | 142 | return os.path.isfile(nbpath) |
|
143 | 143 | |
|
144 | 144 | def exists(self, name=None, path=''): |
|
145 | 145 | """Returns True if the path [and name] exists, else returns False. |
|
146 | 146 | |
|
147 | 147 | API-style wrapper for os.path.exists |
|
148 | 148 | |
|
149 | 149 | Parameters |
|
150 | 150 | ---------- |
|
151 | 151 | name : string |
|
152 | 152 | The name of the file you are checking. |
|
153 | 153 | path : string |
|
154 | 154 | The relative path to the file's directory (with '/' as separator) |
|
155 | 155 | |
|
156 | 156 | Returns |
|
157 | 157 | ------- |
|
158 | 158 | exists : bool |
|
159 | 159 | Whether the target exists. |
|
160 | 160 | """ |
|
161 | 161 | path = path.strip('/') |
|
162 | 162 | os_path = self._get_os_path(name, path=path) |
|
163 | 163 | return os.path.exists(os_path) |
|
164 | 164 | |
|
165 | 165 | def _base_model(self, name, path=''): |
|
166 | 166 | """Build the common base of a contents model""" |
|
167 | 167 | os_path = self._get_os_path(name, path) |
|
168 | 168 | info = os.stat(os_path) |
|
169 | 169 | last_modified = tz.utcfromtimestamp(info.st_mtime) |
|
170 | 170 | created = tz.utcfromtimestamp(info.st_ctime) |
|
171 | 171 | # Create the base model. |
|
172 | 172 | model = {} |
|
173 | 173 | model['name'] = name |
|
174 | 174 | model['path'] = path |
|
175 | 175 | model['last_modified'] = last_modified |
|
176 | 176 | model['created'] = created |
|
177 | 177 | model['content'] = None |
|
178 | 178 | model['format'] = None |
|
179 | 179 | model['message'] = None |
|
180 | 180 | return model |
|
181 | 181 | |
|
182 | 182 | def _dir_model(self, name, path='', content=True): |
|
183 | 183 | """Build a model for a directory |
|
184 | 184 | |
|
185 | 185 | if content is requested, will include a listing of the directory |
|
186 | 186 | """ |
|
187 | 187 | os_path = self._get_os_path(name, path) |
|
188 | 188 | |
|
189 | 189 | four_o_four = u'directory does not exist: %r' % os_path |
|
190 | 190 | |
|
191 | 191 | if not os.path.isdir(os_path): |
|
192 | 192 | raise web.HTTPError(404, four_o_four) |
|
193 | 193 | elif is_hidden(os_path, self.root_dir): |
|
194 | 194 | self.log.info("Refusing to serve hidden directory %r, via 404 Error", |
|
195 | 195 | os_path |
|
196 | 196 | ) |
|
197 | 197 | raise web.HTTPError(404, four_o_four) |
|
198 | 198 | |
|
199 | 199 | if name is None: |
|
200 | 200 | if '/' in path: |
|
201 | 201 | path, name = path.rsplit('/', 1) |
|
202 | 202 | else: |
|
203 | 203 | name = '' |
|
204 | 204 | model = self._base_model(name, path) |
|
205 | 205 | model['type'] = 'directory' |
|
206 | 206 | dir_path = u'{}/{}'.format(path, name) |
|
207 | 207 | if content: |
|
208 | 208 | model['content'] = contents = [] |
|
209 | 209 | for os_path in glob.glob(self._get_os_path('*', dir_path)): |
|
210 | 210 | name = os.path.basename(os_path) |
|
211 | 211 | # skip over broken symlinks in listing |
|
212 | 212 | if not os.path.exists(os_path): |
|
213 | 213 | self.log.warn("%s doesn't exist", os_path) |
|
214 | 214 | continue |
|
215 | 215 | if self.should_list(name) and not is_hidden(os_path, self.root_dir): |
|
216 | 216 | contents.append(self.get_model(name=name, path=dir_path, content=False)) |
|
217 | 217 | |
|
218 | 218 | model['format'] = 'json' |
|
219 | 219 | |
|
220 | 220 | return model |
|
221 | 221 | |
|
222 | 222 | def _file_model(self, name, path='', content=True): |
|
223 | 223 | """Build a model for a file |
|
224 | 224 | |
|
225 | 225 | if content is requested, include the file contents. |
|
226 | 226 | UTF-8 text files will be unicode, binary files will be base64-encoded. |
|
227 | 227 | """ |
|
228 | 228 | model = self._base_model(name, path) |
|
229 | 229 | model['type'] = 'file' |
|
230 | 230 | if content: |
|
231 | 231 | os_path = self._get_os_path(name, path) |
|
232 | 232 | with io.open(os_path, 'rb') as f: |
|
233 | 233 | bcontent = f.read() |
|
234 | 234 | try: |
|
235 | 235 | model['content'] = bcontent.decode('utf8') |
|
236 | 236 | except UnicodeError as e: |
|
237 | 237 | model['content'] = base64.encodestring(bcontent).decode('ascii') |
|
238 | 238 | model['format'] = 'base64' |
|
239 | 239 | else: |
|
240 | 240 | model['format'] = 'text' |
|
241 | 241 | return model |
|
242 | 242 | |
|
243 | 243 | |
|
244 | 244 | def _notebook_model(self, name, path='', content=True): |
|
245 | 245 | """Build a notebook model |
|
246 | 246 | |
|
247 | 247 | if content is requested, the notebook content will be populated |
|
248 | 248 | as a JSON structure (not double-serialized) |
|
249 | 249 | """ |
|
250 | 250 | model = self._base_model(name, path) |
|
251 | 251 | model['type'] = 'notebook' |
|
252 | 252 | if content: |
|
253 | 253 | os_path = self._get_os_path(name, path) |
|
254 | 254 | with io.open(os_path, 'r', encoding='utf-8') as f: |
|
255 | 255 | try: |
|
256 | 256 | nb = current.read(f, u'json') |
|
257 | 257 | except Exception as e: |
|
258 |
raise web.HTTPError(400, u"Unreadable Notebook: %s % |
|
|
258 | raise web.HTTPError(400, u"Unreadable Notebook: %s %r" % (os_path, e)) | |
|
259 | 259 | self.mark_trusted_cells(nb, name, path) |
|
260 | 260 | model['content'] = nb |
|
261 | 261 | model['format'] = 'json' |
|
262 | 262 | self.validate_notebook_model(model) |
|
263 | 263 | return model |
|
264 | 264 | |
|
265 | 265 | def get_model(self, name, path='', content=True): |
|
266 | 266 | """ Takes a path and name for an entity and returns its model |
|
267 | 267 | |
|
268 | 268 | Parameters |
|
269 | 269 | ---------- |
|
270 | 270 | name : str |
|
271 | 271 | the name of the target |
|
272 | 272 | path : str |
|
273 | 273 | the API path that describes the relative path for the target |
|
274 | 274 | |
|
275 | 275 | Returns |
|
276 | 276 | ------- |
|
277 | 277 | model : dict |
|
278 | 278 | the contents model. If content=True, returns the contents |
|
279 | 279 | of the file or directory as well. |
|
280 | 280 | """ |
|
281 | 281 | path = path.strip('/') |
|
282 | 282 | |
|
283 | 283 | if not self.exists(name=name, path=path): |
|
284 | 284 | raise web.HTTPError(404, u'No such file or directory: %s/%s' % (path, name)) |
|
285 | 285 | |
|
286 | 286 | os_path = self._get_os_path(name, path) |
|
287 | 287 | if os.path.isdir(os_path): |
|
288 | 288 | model = self._dir_model(name, path, content) |
|
289 | 289 | elif name.endswith('.ipynb'): |
|
290 | 290 | model = self._notebook_model(name, path, content) |
|
291 | 291 | else: |
|
292 | 292 | model = self._file_model(name, path, content) |
|
293 | 293 | return model |
|
294 | 294 | |
|
295 | 295 | def _save_notebook(self, os_path, model, name='', path=''): |
|
296 | 296 | """save a notebook file""" |
|
297 | 297 | # Save the notebook file |
|
298 | 298 | nb = current.to_notebook_json(model['content']) |
|
299 | 299 | |
|
300 | 300 | self.check_and_sign(nb, name, path) |
|
301 | 301 | |
|
302 | 302 | if 'name' in nb['metadata']: |
|
303 | 303 | nb['metadata']['name'] = u'' |
|
304 | 304 | |
|
305 | 305 | with atomic_writing(os_path, encoding='utf-8') as f: |
|
306 | 306 | current.write(nb, f, version=nb.nbformat) |
|
307 | 307 | |
|
308 | 308 | def _save_file(self, os_path, model, name='', path=''): |
|
309 | 309 | """save a non-notebook file""" |
|
310 | 310 | fmt = model.get('format', None) |
|
311 | 311 | if fmt not in {'text', 'base64'}: |
|
312 | 312 | raise web.HTTPError(400, "Must specify format of file contents as 'text' or 'base64'") |
|
313 | 313 | try: |
|
314 | 314 | content = model['content'] |
|
315 | 315 | if fmt == 'text': |
|
316 | 316 | bcontent = content.encode('utf8') |
|
317 | 317 | else: |
|
318 | 318 | b64_bytes = content.encode('ascii') |
|
319 | 319 | bcontent = base64.decodestring(b64_bytes) |
|
320 | 320 | except Exception as e: |
|
321 | 321 | raise web.HTTPError(400, u'Encoding error saving %s: %s' % (os_path, e)) |
|
322 | 322 | with atomic_writing(os_path, text=False) as f: |
|
323 | 323 | f.write(bcontent) |
|
324 | 324 | |
|
325 | 325 | def _save_directory(self, os_path, model, name='', path=''): |
|
326 | 326 | """create a directory""" |
|
327 | 327 | if is_hidden(os_path, self.root_dir): |
|
328 | 328 | raise web.HTTPError(400, u'Cannot create hidden directory %r' % os_path) |
|
329 | 329 | if not os.path.exists(os_path): |
|
330 | 330 | os.mkdir(os_path) |
|
331 | 331 | elif not os.path.isdir(os_path): |
|
332 | 332 | raise web.HTTPError(400, u'Not a directory: %s' % (os_path)) |
|
333 | 333 | else: |
|
334 | 334 | self.log.debug("Directory %r already exists", os_path) |
|
335 | 335 | |
|
336 | 336 | def save(self, model, name='', path=''): |
|
337 | 337 | """Save the file model and return the model with no content.""" |
|
338 | 338 | path = path.strip('/') |
|
339 | 339 | |
|
340 | 340 | if 'type' not in model: |
|
341 | 341 | raise web.HTTPError(400, u'No file type provided') |
|
342 | 342 | if 'content' not in model and model['type'] != 'directory': |
|
343 | 343 | raise web.HTTPError(400, u'No file content provided') |
|
344 | 344 | |
|
345 | 345 | # One checkpoint should always exist |
|
346 | 346 | if self.file_exists(name, path) and not self.list_checkpoints(name, path): |
|
347 | 347 | self.create_checkpoint(name, path) |
|
348 | 348 | |
|
349 | 349 | new_path = model.get('path', path).strip('/') |
|
350 | 350 | new_name = model.get('name', name) |
|
351 | 351 | |
|
352 | 352 | if path != new_path or name != new_name: |
|
353 | 353 | self.rename(name, path, new_name, new_path) |
|
354 | 354 | |
|
355 | 355 | os_path = self._get_os_path(new_name, new_path) |
|
356 | 356 | self.log.debug("Saving %s", os_path) |
|
357 | 357 | try: |
|
358 | 358 | if model['type'] == 'notebook': |
|
359 | 359 | self._save_notebook(os_path, model, new_name, new_path) |
|
360 | 360 | elif model['type'] == 'file': |
|
361 | 361 | self._save_file(os_path, model, new_name, new_path) |
|
362 | 362 | elif model['type'] == 'directory': |
|
363 | 363 | self._save_directory(os_path, model, new_name, new_path) |
|
364 | 364 | else: |
|
365 | 365 | raise web.HTTPError(400, "Unhandled contents type: %s" % model['type']) |
|
366 | 366 | except web.HTTPError: |
|
367 | 367 | raise |
|
368 | 368 | except Exception as e: |
|
369 | 369 | raise web.HTTPError(400, u'Unexpected error while saving file: %s %s' % (os_path, e)) |
|
370 | 370 | |
|
371 | 371 | validation_message = None |
|
372 | 372 | if model['type'] == 'notebook': |
|
373 | 373 | self.validate_notebook_model(model) |
|
374 | 374 | validation_message = model.get('message', None) |
|
375 | 375 | |
|
376 | 376 | model = self.get_model(new_name, new_path, content=False) |
|
377 | 377 | if validation_message: |
|
378 | 378 | model['message'] = validation_message |
|
379 | 379 | return model |
|
380 | 380 | |
|
381 | 381 | def update(self, model, name, path=''): |
|
382 | 382 | """Update the file's path and/or name |
|
383 | 383 | |
|
384 | 384 | For use in PATCH requests, to enable renaming a file without |
|
385 | 385 | re-uploading its contents. Only used for renaming at the moment. |
|
386 | 386 | """ |
|
387 | 387 | path = path.strip('/') |
|
388 | 388 | new_name = model.get('name', name) |
|
389 | 389 | new_path = model.get('path', path).strip('/') |
|
390 | 390 | if path != new_path or name != new_name: |
|
391 | 391 | self.rename(name, path, new_name, new_path) |
|
392 | 392 | model = self.get_model(new_name, new_path, content=False) |
|
393 | 393 | return model |
|
394 | 394 | |
|
395 | 395 | def delete(self, name, path=''): |
|
396 | 396 | """Delete file by name and path.""" |
|
397 | 397 | path = path.strip('/') |
|
398 | 398 | os_path = self._get_os_path(name, path) |
|
399 | 399 | rm = os.unlink |
|
400 | 400 | if os.path.isdir(os_path): |
|
401 | 401 | listing = os.listdir(os_path) |
|
402 | 402 | # don't delete non-empty directories (checkpoints dir doesn't count) |
|
403 | 403 | if listing and listing != [self.checkpoint_dir]: |
|
404 | 404 | raise web.HTTPError(400, u'Directory %s not empty' % os_path) |
|
405 | 405 | elif not os.path.isfile(os_path): |
|
406 | 406 | raise web.HTTPError(404, u'File does not exist: %s' % os_path) |
|
407 | 407 | |
|
408 | 408 | # clear checkpoints |
|
409 | 409 | for checkpoint in self.list_checkpoints(name, path): |
|
410 | 410 | checkpoint_id = checkpoint['id'] |
|
411 | 411 | cp_path = self.get_checkpoint_path(checkpoint_id, name, path) |
|
412 | 412 | if os.path.isfile(cp_path): |
|
413 | 413 | self.log.debug("Unlinking checkpoint %s", cp_path) |
|
414 | 414 | os.unlink(cp_path) |
|
415 | 415 | |
|
416 | 416 | if os.path.isdir(os_path): |
|
417 | 417 | self.log.debug("Removing directory %s", os_path) |
|
418 | 418 | shutil.rmtree(os_path) |
|
419 | 419 | else: |
|
420 | 420 | self.log.debug("Unlinking file %s", os_path) |
|
421 | 421 | rm(os_path) |
|
422 | 422 | |
|
423 | 423 | def rename(self, old_name, old_path, new_name, new_path): |
|
424 | 424 | """Rename a file.""" |
|
425 | 425 | old_path = old_path.strip('/') |
|
426 | 426 | new_path = new_path.strip('/') |
|
427 | 427 | if new_name == old_name and new_path == old_path: |
|
428 | 428 | return |
|
429 | 429 | |
|
430 | 430 | new_os_path = self._get_os_path(new_name, new_path) |
|
431 | 431 | old_os_path = self._get_os_path(old_name, old_path) |
|
432 | 432 | |
|
433 | 433 | # Should we proceed with the move? |
|
434 | 434 | if os.path.isfile(new_os_path): |
|
435 | 435 | raise web.HTTPError(409, u'File with name already exists: %s' % new_os_path) |
|
436 | 436 | |
|
437 | 437 | # Move the file |
|
438 | 438 | try: |
|
439 | 439 | shutil.move(old_os_path, new_os_path) |
|
440 | 440 | except Exception as e: |
|
441 | 441 | raise web.HTTPError(500, u'Unknown error renaming file: %s %s' % (old_os_path, e)) |
|
442 | 442 | |
|
443 | 443 | # Move the checkpoints |
|
444 | 444 | old_checkpoints = self.list_checkpoints(old_name, old_path) |
|
445 | 445 | for cp in old_checkpoints: |
|
446 | 446 | checkpoint_id = cp['id'] |
|
447 | 447 | old_cp_path = self.get_checkpoint_path(checkpoint_id, old_name, old_path) |
|
448 | 448 | new_cp_path = self.get_checkpoint_path(checkpoint_id, new_name, new_path) |
|
449 | 449 | if os.path.isfile(old_cp_path): |
|
450 | 450 | self.log.debug("Renaming checkpoint %s -> %s", old_cp_path, new_cp_path) |
|
451 | 451 | shutil.move(old_cp_path, new_cp_path) |
|
452 | 452 | |
|
453 | 453 | # Checkpoint-related utilities |
|
454 | 454 | |
|
455 | 455 | def get_checkpoint_path(self, checkpoint_id, name, path=''): |
|
456 | 456 | """find the path to a checkpoint""" |
|
457 | 457 | path = path.strip('/') |
|
458 | 458 | basename, ext = os.path.splitext(name) |
|
459 | 459 | filename = u"{name}-{checkpoint_id}{ext}".format( |
|
460 | 460 | name=basename, |
|
461 | 461 | checkpoint_id=checkpoint_id, |
|
462 | 462 | ext=ext, |
|
463 | 463 | ) |
|
464 | 464 | os_path = self._get_os_path(path=path) |
|
465 | 465 | cp_dir = os.path.join(os_path, self.checkpoint_dir) |
|
466 | 466 | ensure_dir_exists(cp_dir) |
|
467 | 467 | cp_path = os.path.join(cp_dir, filename) |
|
468 | 468 | return cp_path |
|
469 | 469 | |
|
470 | 470 | def get_checkpoint_model(self, checkpoint_id, name, path=''): |
|
471 | 471 | """construct the info dict for a given checkpoint""" |
|
472 | 472 | path = path.strip('/') |
|
473 | 473 | cp_path = self.get_checkpoint_path(checkpoint_id, name, path) |
|
474 | 474 | stats = os.stat(cp_path) |
|
475 | 475 | last_modified = tz.utcfromtimestamp(stats.st_mtime) |
|
476 | 476 | info = dict( |
|
477 | 477 | id = checkpoint_id, |
|
478 | 478 | last_modified = last_modified, |
|
479 | 479 | ) |
|
480 | 480 | return info |
|
481 | 481 | |
|
482 | 482 | # public checkpoint API |
|
483 | 483 | |
|
484 | 484 | def create_checkpoint(self, name, path=''): |
|
485 | 485 | """Create a checkpoint from the current state of a file""" |
|
486 | 486 | path = path.strip('/') |
|
487 | 487 | src_path = self._get_os_path(name, path) |
|
488 | 488 | # only the one checkpoint ID: |
|
489 | 489 | checkpoint_id = u"checkpoint" |
|
490 | 490 | cp_path = self.get_checkpoint_path(checkpoint_id, name, path) |
|
491 | 491 | self.log.debug("creating checkpoint for %s", name) |
|
492 | 492 | self._copy(src_path, cp_path) |
|
493 | 493 | |
|
494 | 494 | # return the checkpoint info |
|
495 | 495 | return self.get_checkpoint_model(checkpoint_id, name, path) |
|
496 | 496 | |
|
497 | 497 | def list_checkpoints(self, name, path=''): |
|
498 | 498 | """list the checkpoints for a given file |
|
499 | 499 | |
|
500 | 500 | This contents manager currently only supports one checkpoint per file. |
|
501 | 501 | """ |
|
502 | 502 | path = path.strip('/') |
|
503 | 503 | checkpoint_id = "checkpoint" |
|
504 | 504 | os_path = self.get_checkpoint_path(checkpoint_id, name, path) |
|
505 | 505 | if not os.path.exists(os_path): |
|
506 | 506 | return [] |
|
507 | 507 | else: |
|
508 | 508 | return [self.get_checkpoint_model(checkpoint_id, name, path)] |
|
509 | 509 | |
|
510 | 510 | |
|
511 | 511 | def restore_checkpoint(self, checkpoint_id, name, path=''): |
|
512 | 512 | """restore a file to a checkpointed state""" |
|
513 | 513 | path = path.strip('/') |
|
514 | 514 | self.log.info("restoring %s from checkpoint %s", name, checkpoint_id) |
|
515 | 515 | nb_path = self._get_os_path(name, path) |
|
516 | 516 | cp_path = self.get_checkpoint_path(checkpoint_id, name, path) |
|
517 | 517 | if not os.path.isfile(cp_path): |
|
518 | 518 | self.log.debug("checkpoint file does not exist: %s", cp_path) |
|
519 | 519 | raise web.HTTPError(404, |
|
520 | 520 | u'checkpoint does not exist: %s-%s' % (name, checkpoint_id) |
|
521 | 521 | ) |
|
522 | 522 | # ensure notebook is readable (never restore from an unreadable notebook) |
|
523 | 523 | if cp_path.endswith('.ipynb'): |
|
524 | 524 | with io.open(cp_path, 'r', encoding='utf-8') as f: |
|
525 | 525 | current.read(f, u'json') |
|
526 | 526 | self._copy(cp_path, nb_path) |
|
527 | 527 | self.log.debug("copying %s -> %s", cp_path, nb_path) |
|
528 | 528 | |
|
529 | 529 | def delete_checkpoint(self, checkpoint_id, name, path=''): |
|
530 | 530 | """delete a file's checkpoint""" |
|
531 | 531 | path = path.strip('/') |
|
532 | 532 | cp_path = self.get_checkpoint_path(checkpoint_id, name, path) |
|
533 | 533 | if not os.path.isfile(cp_path): |
|
534 | 534 | raise web.HTTPError(404, |
|
535 | 535 | u'Checkpoint does not exist: %s%s-%s' % (path, name, checkpoint_id) |
|
536 | 536 | ) |
|
537 | 537 | self.log.debug("unlinking %s", cp_path) |
|
538 | 538 | os.unlink(cp_path) |
|
539 | 539 | |
|
540 | 540 | def info_string(self): |
|
541 | 541 | return "Serving notebooks from local directory: %s" % self.root_dir |
|
542 | 542 | |
|
543 | 543 | def get_kernel_path(self, name, path='', model=None): |
|
544 | 544 | """Return the initial working dir a kernel associated with a given notebook""" |
|
545 | 545 | return os.path.join(self.root_dir, path) |
@@ -1,480 +1,480 b'' | |||
|
1 | 1 | # coding: utf-8 |
|
2 | 2 | """Test the contents webservice API.""" |
|
3 | 3 | |
|
4 | 4 | import base64 |
|
5 | 5 | import io |
|
6 | 6 | import json |
|
7 | 7 | import os |
|
8 | 8 | import shutil |
|
9 | 9 | from unicodedata import normalize |
|
10 | 10 | |
|
11 | 11 | pjoin = os.path.join |
|
12 | 12 | |
|
13 | 13 | import requests |
|
14 | 14 | |
|
15 | 15 | from IPython.html.utils import url_path_join, url_escape |
|
16 | 16 | from IPython.html.tests.launchnotebook import NotebookTestBase, assert_http_error |
|
17 | 17 | from IPython.nbformat import current |
|
18 | 18 | from IPython.nbformat.current import (new_notebook, write, read, |
|
19 |
new_ |
|
|
19 | new_markdown_cell, to_notebook_json) | |
|
20 | 20 | from IPython.nbformat import v2 |
|
21 | 21 | from IPython.utils import py3compat |
|
22 | 22 | from IPython.utils.data import uniq_stable |
|
23 | 23 | |
|
24 | 24 | |
|
25 | 25 | def notebooks_only(dir_model): |
|
26 | 26 | return [nb for nb in dir_model['content'] if nb['type']=='notebook'] |
|
27 | 27 | |
|
28 | 28 | def dirs_only(dir_model): |
|
29 | 29 | return [x for x in dir_model['content'] if x['type']=='directory'] |
|
30 | 30 | |
|
31 | 31 | |
|
32 | 32 | class API(object): |
|
33 | 33 | """Wrapper for contents API calls.""" |
|
34 | 34 | def __init__(self, base_url): |
|
35 | 35 | self.base_url = base_url |
|
36 | 36 | |
|
37 | 37 | def _req(self, verb, path, body=None): |
|
38 | 38 | response = requests.request(verb, |
|
39 | 39 | url_path_join(self.base_url, 'api/contents', path), |
|
40 | 40 | data=body, |
|
41 | 41 | ) |
|
42 | 42 | response.raise_for_status() |
|
43 | 43 | return response |
|
44 | 44 | |
|
45 | 45 | def list(self, path='/'): |
|
46 | 46 | return self._req('GET', path) |
|
47 | 47 | |
|
48 | 48 | def read(self, name, path='/'): |
|
49 | 49 | return self._req('GET', url_path_join(path, name)) |
|
50 | 50 | |
|
51 | 51 | def create_untitled(self, path='/', ext=None): |
|
52 | 52 | body = None |
|
53 | 53 | if ext: |
|
54 | 54 | body = json.dumps({'ext': ext}) |
|
55 | 55 | return self._req('POST', path, body) |
|
56 | 56 | |
|
57 | 57 | def upload_untitled(self, body, path='/'): |
|
58 | 58 | return self._req('POST', path, body) |
|
59 | 59 | |
|
60 | 60 | def copy_untitled(self, copy_from, path='/'): |
|
61 | 61 | body = json.dumps({'copy_from':copy_from}) |
|
62 | 62 | return self._req('POST', path, body) |
|
63 | 63 | |
|
64 | 64 | def create(self, name, path='/'): |
|
65 | 65 | return self._req('PUT', url_path_join(path, name)) |
|
66 | 66 | |
|
67 | 67 | def upload(self, name, body, path='/'): |
|
68 | 68 | return self._req('PUT', url_path_join(path, name), body) |
|
69 | 69 | |
|
70 | 70 | def mkdir(self, name, path='/'): |
|
71 | 71 | return self._req('PUT', url_path_join(path, name), json.dumps({'type': 'directory'})) |
|
72 | 72 | |
|
73 | 73 | def copy(self, copy_from, copy_to, path='/'): |
|
74 | 74 | body = json.dumps({'copy_from':copy_from}) |
|
75 | 75 | return self._req('PUT', url_path_join(path, copy_to), body) |
|
76 | 76 | |
|
77 | 77 | def save(self, name, body, path='/'): |
|
78 | 78 | return self._req('PUT', url_path_join(path, name), body) |
|
79 | 79 | |
|
80 | 80 | def delete(self, name, path='/'): |
|
81 | 81 | return self._req('DELETE', url_path_join(path, name)) |
|
82 | 82 | |
|
83 | 83 | def rename(self, name, path, new_name): |
|
84 | 84 | body = json.dumps({'name': new_name}) |
|
85 | 85 | return self._req('PATCH', url_path_join(path, name), body) |
|
86 | 86 | |
|
87 | 87 | def get_checkpoints(self, name, path): |
|
88 | 88 | return self._req('GET', url_path_join(path, name, 'checkpoints')) |
|
89 | 89 | |
|
90 | 90 | def new_checkpoint(self, name, path): |
|
91 | 91 | return self._req('POST', url_path_join(path, name, 'checkpoints')) |
|
92 | 92 | |
|
93 | 93 | def restore_checkpoint(self, name, path, checkpoint_id): |
|
94 | 94 | return self._req('POST', url_path_join(path, name, 'checkpoints', checkpoint_id)) |
|
95 | 95 | |
|
96 | 96 | def delete_checkpoint(self, name, path, checkpoint_id): |
|
97 | 97 | return self._req('DELETE', url_path_join(path, name, 'checkpoints', checkpoint_id)) |
|
98 | 98 | |
|
99 | 99 | class APITest(NotebookTestBase): |
|
100 | 100 | """Test the kernels web service API""" |
|
101 | 101 | dirs_nbs = [('', 'inroot'), |
|
102 | 102 | ('Directory with spaces in', 'inspace'), |
|
103 | 103 | (u'unicodé', 'innonascii'), |
|
104 | 104 | ('foo', 'a'), |
|
105 | 105 | ('foo', 'b'), |
|
106 | 106 | ('foo', 'name with spaces'), |
|
107 | 107 | ('foo', u'unicodé'), |
|
108 | 108 | ('foo/bar', 'baz'), |
|
109 | 109 | ('ordering', 'A'), |
|
110 | 110 | ('ordering', 'b'), |
|
111 | 111 | ('ordering', 'C'), |
|
112 | 112 | (u'å b', u'ç d'), |
|
113 | 113 | ] |
|
114 | 114 | hidden_dirs = ['.hidden', '__pycache__'] |
|
115 | 115 | |
|
116 | 116 | dirs = uniq_stable([py3compat.cast_unicode(d) for (d,n) in dirs_nbs]) |
|
117 | 117 | del dirs[0] # remove '' |
|
118 | 118 | top_level_dirs = {normalize('NFC', d.split('/')[0]) for d in dirs} |
|
119 | 119 | |
|
120 | 120 | @staticmethod |
|
121 | 121 | def _blob_for_name(name): |
|
122 | 122 | return name.encode('utf-8') + b'\xFF' |
|
123 | 123 | |
|
124 | 124 | @staticmethod |
|
125 | 125 | def _txt_for_name(name): |
|
126 | 126 | return u'%s text file' % name |
|
127 | 127 | |
|
128 | 128 | def setUp(self): |
|
129 | 129 | nbdir = self.notebook_dir.name |
|
130 | 130 | self.blob = os.urandom(100) |
|
131 | 131 | self.b64_blob = base64.encodestring(self.blob).decode('ascii') |
|
132 | 132 | |
|
133 | 133 | |
|
134 | 134 | |
|
135 | 135 | for d in (self.dirs + self.hidden_dirs): |
|
136 | 136 | d.replace('/', os.sep) |
|
137 | 137 | if not os.path.isdir(pjoin(nbdir, d)): |
|
138 | 138 | os.mkdir(pjoin(nbdir, d)) |
|
139 | 139 | |
|
140 | 140 | for d, name in self.dirs_nbs: |
|
141 | 141 | d = d.replace('/', os.sep) |
|
142 | 142 | # create a notebook |
|
143 | 143 | with io.open(pjoin(nbdir, d, '%s.ipynb' % name), 'w', |
|
144 | 144 | encoding='utf-8') as f: |
|
145 | 145 | nb = new_notebook() |
|
146 | 146 | write(nb, f, format='ipynb') |
|
147 | 147 | |
|
148 | 148 | # create a text file |
|
149 | 149 | with io.open(pjoin(nbdir, d, '%s.txt' % name), 'w', |
|
150 | 150 | encoding='utf-8') as f: |
|
151 | 151 | f.write(self._txt_for_name(name)) |
|
152 | 152 | |
|
153 | 153 | # create a binary file |
|
154 | 154 | with io.open(pjoin(nbdir, d, '%s.blob' % name), 'wb') as f: |
|
155 | 155 | f.write(self._blob_for_name(name)) |
|
156 | 156 | |
|
157 | 157 | self.api = API(self.base_url()) |
|
158 | 158 | |
|
159 | 159 | def tearDown(self): |
|
160 | 160 | nbdir = self.notebook_dir.name |
|
161 | 161 | |
|
162 | 162 | for dname in (list(self.top_level_dirs) + self.hidden_dirs): |
|
163 | 163 | shutil.rmtree(pjoin(nbdir, dname), ignore_errors=True) |
|
164 | 164 | |
|
165 | 165 | if os.path.isfile(pjoin(nbdir, 'inroot.ipynb')): |
|
166 | 166 | os.unlink(pjoin(nbdir, 'inroot.ipynb')) |
|
167 | 167 | |
|
168 | 168 | def test_list_notebooks(self): |
|
169 | 169 | nbs = notebooks_only(self.api.list().json()) |
|
170 | 170 | self.assertEqual(len(nbs), 1) |
|
171 | 171 | self.assertEqual(nbs[0]['name'], 'inroot.ipynb') |
|
172 | 172 | |
|
173 | 173 | nbs = notebooks_only(self.api.list('/Directory with spaces in/').json()) |
|
174 | 174 | self.assertEqual(len(nbs), 1) |
|
175 | 175 | self.assertEqual(nbs[0]['name'], 'inspace.ipynb') |
|
176 | 176 | |
|
177 | 177 | nbs = notebooks_only(self.api.list(u'/unicodé/').json()) |
|
178 | 178 | self.assertEqual(len(nbs), 1) |
|
179 | 179 | self.assertEqual(nbs[0]['name'], 'innonascii.ipynb') |
|
180 | 180 | self.assertEqual(nbs[0]['path'], u'unicodé') |
|
181 | 181 | |
|
182 | 182 | nbs = notebooks_only(self.api.list('/foo/bar/').json()) |
|
183 | 183 | self.assertEqual(len(nbs), 1) |
|
184 | 184 | self.assertEqual(nbs[0]['name'], 'baz.ipynb') |
|
185 | 185 | self.assertEqual(nbs[0]['path'], 'foo/bar') |
|
186 | 186 | |
|
187 | 187 | nbs = notebooks_only(self.api.list('foo').json()) |
|
188 | 188 | self.assertEqual(len(nbs), 4) |
|
189 | 189 | nbnames = { normalize('NFC', n['name']) for n in nbs } |
|
190 | 190 | expected = [ u'a.ipynb', u'b.ipynb', u'name with spaces.ipynb', u'unicodé.ipynb'] |
|
191 | 191 | expected = { normalize('NFC', name) for name in expected } |
|
192 | 192 | self.assertEqual(nbnames, expected) |
|
193 | 193 | |
|
194 | 194 | nbs = notebooks_only(self.api.list('ordering').json()) |
|
195 | 195 | nbnames = [n['name'] for n in nbs] |
|
196 | 196 | expected = ['A.ipynb', 'b.ipynb', 'C.ipynb'] |
|
197 | 197 | self.assertEqual(nbnames, expected) |
|
198 | 198 | |
|
199 | 199 | def test_list_dirs(self): |
|
200 | 200 | dirs = dirs_only(self.api.list().json()) |
|
201 | 201 | dir_names = {normalize('NFC', d['name']) for d in dirs} |
|
202 | 202 | self.assertEqual(dir_names, self.top_level_dirs) # Excluding hidden dirs |
|
203 | 203 | |
|
204 | 204 | def test_list_nonexistant_dir(self): |
|
205 | 205 | with assert_http_error(404): |
|
206 | 206 | self.api.list('nonexistant') |
|
207 | 207 | |
|
208 | 208 | def test_get_nb_contents(self): |
|
209 | 209 | for d, name in self.dirs_nbs: |
|
210 | 210 | nb = self.api.read('%s.ipynb' % name, d+'/').json() |
|
211 | 211 | self.assertEqual(nb['name'], u'%s.ipynb' % name) |
|
212 | 212 | self.assertEqual(nb['type'], 'notebook') |
|
213 | 213 | self.assertIn('content', nb) |
|
214 | 214 | self.assertEqual(nb['format'], 'json') |
|
215 | 215 | self.assertIn('content', nb) |
|
216 | 216 | self.assertIn('metadata', nb['content']) |
|
217 | 217 | self.assertIsInstance(nb['content']['metadata'], dict) |
|
218 | 218 | |
|
219 | 219 | def test_get_contents_no_such_file(self): |
|
220 | 220 | # Name that doesn't exist - should be a 404 |
|
221 | 221 | with assert_http_error(404): |
|
222 | 222 | self.api.read('q.ipynb', 'foo') |
|
223 | 223 | |
|
224 | 224 | def test_get_text_file_contents(self): |
|
225 | 225 | for d, name in self.dirs_nbs: |
|
226 | 226 | model = self.api.read(u'%s.txt' % name, d+'/').json() |
|
227 | 227 | self.assertEqual(model['name'], u'%s.txt' % name) |
|
228 | 228 | self.assertIn('content', model) |
|
229 | 229 | self.assertEqual(model['format'], 'text') |
|
230 | 230 | self.assertEqual(model['type'], 'file') |
|
231 | 231 | self.assertEqual(model['content'], self._txt_for_name(name)) |
|
232 | 232 | |
|
233 | 233 | # Name that doesn't exist - should be a 404 |
|
234 | 234 | with assert_http_error(404): |
|
235 | 235 | self.api.read('q.txt', 'foo') |
|
236 | 236 | |
|
237 | 237 | def test_get_binary_file_contents(self): |
|
238 | 238 | for d, name in self.dirs_nbs: |
|
239 | 239 | model = self.api.read(u'%s.blob' % name, d+'/').json() |
|
240 | 240 | self.assertEqual(model['name'], u'%s.blob' % name) |
|
241 | 241 | self.assertIn('content', model) |
|
242 | 242 | self.assertEqual(model['format'], 'base64') |
|
243 | 243 | self.assertEqual(model['type'], 'file') |
|
244 | 244 | b64_data = base64.encodestring(self._blob_for_name(name)).decode('ascii') |
|
245 | 245 | self.assertEqual(model['content'], b64_data) |
|
246 | 246 | |
|
247 | 247 | # Name that doesn't exist - should be a 404 |
|
248 | 248 | with assert_http_error(404): |
|
249 | 249 | self.api.read('q.txt', 'foo') |
|
250 | 250 | |
|
251 | 251 | def _check_created(self, resp, name, path, type='notebook'): |
|
252 | 252 | self.assertEqual(resp.status_code, 201) |
|
253 | 253 | location_header = py3compat.str_to_unicode(resp.headers['Location']) |
|
254 | 254 | self.assertEqual(location_header, url_escape(url_path_join(u'/api/contents', path, name))) |
|
255 | 255 | rjson = resp.json() |
|
256 | 256 | self.assertEqual(rjson['name'], name) |
|
257 | 257 | self.assertEqual(rjson['path'], path) |
|
258 | 258 | self.assertEqual(rjson['type'], type) |
|
259 | 259 | isright = os.path.isdir if type == 'directory' else os.path.isfile |
|
260 | 260 | assert isright(pjoin( |
|
261 | 261 | self.notebook_dir.name, |
|
262 | 262 | path.replace('/', os.sep), |
|
263 | 263 | name, |
|
264 | 264 | )) |
|
265 | 265 | |
|
266 | 266 | def test_create_untitled(self): |
|
267 | 267 | resp = self.api.create_untitled(path=u'Ã¥ b') |
|
268 | 268 | self._check_created(resp, 'Untitled0.ipynb', u'Ã¥ b') |
|
269 | 269 | |
|
270 | 270 | # Second time |
|
271 | 271 | resp = self.api.create_untitled(path=u'Ã¥ b') |
|
272 | 272 | self._check_created(resp, 'Untitled1.ipynb', u'Ã¥ b') |
|
273 | 273 | |
|
274 | 274 | # And two directories down |
|
275 | 275 | resp = self.api.create_untitled(path='foo/bar') |
|
276 | 276 | self._check_created(resp, 'Untitled0.ipynb', 'foo/bar') |
|
277 | 277 | |
|
278 | 278 | def test_create_untitled_txt(self): |
|
279 | 279 | resp = self.api.create_untitled(path='foo/bar', ext='.txt') |
|
280 | 280 | self._check_created(resp, 'untitled0.txt', 'foo/bar', type='file') |
|
281 | 281 | |
|
282 | 282 | resp = self.api.read(path='foo/bar', name='untitled0.txt') |
|
283 | 283 | model = resp.json() |
|
284 | 284 | self.assertEqual(model['type'], 'file') |
|
285 | 285 | self.assertEqual(model['format'], 'text') |
|
286 | 286 | self.assertEqual(model['content'], '') |
|
287 | 287 | |
|
288 | 288 | def test_upload_untitled(self): |
|
289 | 289 | nb = new_notebook() |
|
290 | 290 | nbmodel = {'content': nb, 'type': 'notebook'} |
|
291 | 291 | resp = self.api.upload_untitled(path=u'Ã¥ b', |
|
292 | 292 | body=json.dumps(nbmodel)) |
|
293 | 293 | self._check_created(resp, 'Untitled0.ipynb', u'Ã¥ b') |
|
294 | 294 | |
|
295 | 295 | def test_upload(self): |
|
296 | 296 | nb = new_notebook() |
|
297 | 297 | nbmodel = {'content': nb, 'type': 'notebook'} |
|
298 | 298 | resp = self.api.upload(u'Upload tést.ipynb', path=u'å b', |
|
299 | 299 | body=json.dumps(nbmodel)) |
|
300 | 300 | self._check_created(resp, u'Upload tést.ipynb', u'å b') |
|
301 | 301 | |
|
302 | 302 | def test_mkdir(self): |
|
303 | 303 | resp = self.api.mkdir(u'New ∂ir', path=u'å b') |
|
304 | 304 | self._check_created(resp, u'New ∂ir', u'å b', type='directory') |
|
305 | 305 | |
|
306 | 306 | def test_mkdir_hidden_400(self): |
|
307 | 307 | with assert_http_error(400): |
|
308 | 308 | resp = self.api.mkdir(u'.hidden', path=u'Ã¥ b') |
|
309 | 309 | |
|
310 | 310 | def test_upload_txt(self): |
|
311 | 311 | body = u'ünicode téxt' |
|
312 | 312 | model = { |
|
313 | 313 | 'content' : body, |
|
314 | 314 | 'format' : 'text', |
|
315 | 315 | 'type' : 'file', |
|
316 | 316 | } |
|
317 | 317 | resp = self.api.upload(u'Upload tést.txt', path=u'å b', |
|
318 | 318 | body=json.dumps(model)) |
|
319 | 319 | |
|
320 | 320 | # check roundtrip |
|
321 | 321 | resp = self.api.read(path=u'å b', name=u'Upload tést.txt') |
|
322 | 322 | model = resp.json() |
|
323 | 323 | self.assertEqual(model['type'], 'file') |
|
324 | 324 | self.assertEqual(model['format'], 'text') |
|
325 | 325 | self.assertEqual(model['content'], body) |
|
326 | 326 | |
|
327 | 327 | def test_upload_b64(self): |
|
328 | 328 | body = b'\xFFblob' |
|
329 | 329 | b64body = base64.encodestring(body).decode('ascii') |
|
330 | 330 | model = { |
|
331 | 331 | 'content' : b64body, |
|
332 | 332 | 'format' : 'base64', |
|
333 | 333 | 'type' : 'file', |
|
334 | 334 | } |
|
335 | 335 | resp = self.api.upload(u'Upload tést.blob', path=u'å b', |
|
336 | 336 | body=json.dumps(model)) |
|
337 | 337 | |
|
338 | 338 | # check roundtrip |
|
339 | 339 | resp = self.api.read(path=u'å b', name=u'Upload tést.blob') |
|
340 | 340 | model = resp.json() |
|
341 | 341 | self.assertEqual(model['type'], 'file') |
|
342 | 342 | self.assertEqual(model['format'], 'base64') |
|
343 | 343 | decoded = base64.decodestring(model['content'].encode('ascii')) |
|
344 | 344 | self.assertEqual(decoded, body) |
|
345 | 345 | |
|
346 | 346 | def test_upload_v2(self): |
|
347 | 347 | nb = v2.new_notebook() |
|
348 | 348 | ws = v2.new_worksheet() |
|
349 | 349 | nb.worksheets.append(ws) |
|
350 | 350 | ws.cells.append(v2.new_code_cell(input='print("hi")')) |
|
351 | 351 | nbmodel = {'content': nb, 'type': 'notebook'} |
|
352 | 352 | resp = self.api.upload(u'Upload tést.ipynb', path=u'å b', |
|
353 | 353 | body=json.dumps(nbmodel)) |
|
354 | 354 | self._check_created(resp, u'Upload tést.ipynb', u'å b') |
|
355 | 355 | resp = self.api.read(u'Upload tést.ipynb', u'å b') |
|
356 | 356 | data = resp.json() |
|
357 | 357 | self.assertEqual(data['content']['nbformat'], current.nbformat) |
|
358 | 358 | |
|
359 | 359 | def test_copy_untitled(self): |
|
360 | 360 | resp = self.api.copy_untitled(u'ç d.ipynb', path=u'å b') |
|
361 | 361 | self._check_created(resp, u'ç d-Copy0.ipynb', u'å b') |
|
362 | 362 | |
|
363 | 363 | def test_copy(self): |
|
364 | 364 | resp = self.api.copy(u'ç d.ipynb', u'cøpy.ipynb', path=u'å b') |
|
365 | 365 | self._check_created(resp, u'cøpy.ipynb', u'å b') |
|
366 | 366 | |
|
367 | 367 | def test_copy_path(self): |
|
368 | 368 | resp = self.api.copy(u'foo/a.ipynb', u'cøpyfoo.ipynb', path=u'å b') |
|
369 | 369 | self._check_created(resp, u'cøpyfoo.ipynb', u'å b') |
|
370 | 370 | |
|
371 | 371 | def test_copy_dir_400(self): |
|
372 | 372 | # can't copy directories |
|
373 | 373 | with assert_http_error(400): |
|
374 | 374 | resp = self.api.copy(u'Ã¥ b', u'Ã¥ c') |
|
375 | 375 | |
|
376 | 376 | def test_delete(self): |
|
377 | 377 | for d, name in self.dirs_nbs: |
|
378 | 378 | resp = self.api.delete('%s.ipynb' % name, d) |
|
379 | 379 | self.assertEqual(resp.status_code, 204) |
|
380 | 380 | |
|
381 | 381 | for d in self.dirs + ['/']: |
|
382 | 382 | nbs = notebooks_only(self.api.list(d).json()) |
|
383 | 383 | self.assertEqual(len(nbs), 0) |
|
384 | 384 | |
|
385 | 385 | def test_delete_dirs(self): |
|
386 | 386 | # depth-first delete everything, so we don't try to delete empty directories |
|
387 | 387 | for name in sorted(self.dirs + ['/'], key=len, reverse=True): |
|
388 | 388 | listing = self.api.list(name).json()['content'] |
|
389 | 389 | for model in listing: |
|
390 | 390 | self.api.delete(model['name'], model['path']) |
|
391 | 391 | listing = self.api.list('/').json()['content'] |
|
392 | 392 | self.assertEqual(listing, []) |
|
393 | 393 | |
|
394 | 394 | def test_delete_non_empty_dir(self): |
|
395 | 395 | """delete non-empty dir raises 400""" |
|
396 | 396 | with assert_http_error(400): |
|
397 | 397 | self.api.delete(u'Ã¥ b') |
|
398 | 398 | |
|
399 | 399 | def test_rename(self): |
|
400 | 400 | resp = self.api.rename('a.ipynb', 'foo', 'z.ipynb') |
|
401 | 401 | self.assertEqual(resp.headers['Location'].split('/')[-1], 'z.ipynb') |
|
402 | 402 | self.assertEqual(resp.json()['name'], 'z.ipynb') |
|
403 | 403 | assert os.path.isfile(pjoin(self.notebook_dir.name, 'foo', 'z.ipynb')) |
|
404 | 404 | |
|
405 | 405 | nbs = notebooks_only(self.api.list('foo').json()) |
|
406 | 406 | nbnames = set(n['name'] for n in nbs) |
|
407 | 407 | self.assertIn('z.ipynb', nbnames) |
|
408 | 408 | self.assertNotIn('a.ipynb', nbnames) |
|
409 | 409 | |
|
410 | 410 | def test_rename_existing(self): |
|
411 | 411 | with assert_http_error(409): |
|
412 | 412 | self.api.rename('a.ipynb', 'foo', 'b.ipynb') |
|
413 | 413 | |
|
414 | 414 | def test_save(self): |
|
415 | 415 | resp = self.api.read('a.ipynb', 'foo') |
|
416 | 416 | nbcontent = json.loads(resp.text)['content'] |
|
417 | 417 | nb = to_notebook_json(nbcontent) |
|
418 |
nb.cells.append(new_ |
|
|
418 | nb.cells.append(new_markdown_cell(u'Created by test ³')) | |
|
419 | 419 | |
|
420 | 420 | nbmodel= {'name': 'a.ipynb', 'path':'foo', 'content': nb, 'type': 'notebook'} |
|
421 | 421 | resp = self.api.save('a.ipynb', path='foo', body=json.dumps(nbmodel)) |
|
422 | 422 | |
|
423 | 423 | nbfile = pjoin(self.notebook_dir.name, 'foo', 'a.ipynb') |
|
424 | 424 | with io.open(nbfile, 'r', encoding='utf-8') as f: |
|
425 | 425 | newnb = read(f, format='ipynb') |
|
426 | 426 | self.assertEqual(newnb.cells[0].source, |
|
427 | 427 | u'Created by test ³') |
|
428 | 428 | nbcontent = self.api.read('a.ipynb', 'foo').json()['content'] |
|
429 | 429 | newnb = to_notebook_json(nbcontent) |
|
430 | 430 | self.assertEqual(newnb.cells[0].source, |
|
431 | 431 | u'Created by test ³') |
|
432 | 432 | |
|
433 | 433 | # Save and rename |
|
434 | 434 | nbmodel= {'name': 'a2.ipynb', 'path':'foo/bar', 'content': nb, 'type': 'notebook'} |
|
435 | 435 | resp = self.api.save('a.ipynb', path='foo', body=json.dumps(nbmodel)) |
|
436 | 436 | saved = resp.json() |
|
437 | 437 | self.assertEqual(saved['name'], 'a2.ipynb') |
|
438 | 438 | self.assertEqual(saved['path'], 'foo/bar') |
|
439 | 439 | assert os.path.isfile(pjoin(self.notebook_dir.name,'foo','bar','a2.ipynb')) |
|
440 | 440 | assert not os.path.isfile(pjoin(self.notebook_dir.name, 'foo', 'a.ipynb')) |
|
441 | 441 | with assert_http_error(404): |
|
442 | 442 | self.api.read('a.ipynb', 'foo') |
|
443 | 443 | |
|
444 | 444 | def test_checkpoints(self): |
|
445 | 445 | resp = self.api.read('a.ipynb', 'foo') |
|
446 | 446 | r = self.api.new_checkpoint('a.ipynb', 'foo') |
|
447 | 447 | self.assertEqual(r.status_code, 201) |
|
448 | 448 | cp1 = r.json() |
|
449 | 449 | self.assertEqual(set(cp1), {'id', 'last_modified'}) |
|
450 | 450 | self.assertEqual(r.headers['Location'].split('/')[-1], cp1['id']) |
|
451 | 451 | |
|
452 | 452 | # Modify it |
|
453 | 453 | nbcontent = json.loads(resp.text)['content'] |
|
454 | 454 | nb = to_notebook_json(nbcontent) |
|
455 |
hcell = new_ |
|
|
455 | hcell = new_markdown_cell('Created by test') | |
|
456 | 456 | nb.cells.append(hcell) |
|
457 | 457 | # Save |
|
458 | 458 | nbmodel= {'name': 'a.ipynb', 'path':'foo', 'content': nb, 'type': 'notebook'} |
|
459 | 459 | resp = self.api.save('a.ipynb', path='foo', body=json.dumps(nbmodel)) |
|
460 | 460 | |
|
461 | 461 | # List checkpoints |
|
462 | 462 | cps = self.api.get_checkpoints('a.ipynb', 'foo').json() |
|
463 | 463 | self.assertEqual(cps, [cp1]) |
|
464 | 464 | |
|
465 | 465 | nbcontent = self.api.read('a.ipynb', 'foo').json()['content'] |
|
466 | 466 | nb = to_notebook_json(nbcontent) |
|
467 | 467 | self.assertEqual(nb.cells[0].source, 'Created by test') |
|
468 | 468 | |
|
469 | 469 | # Restore cp1 |
|
470 | 470 | r = self.api.restore_checkpoint('a.ipynb', 'foo', cp1['id']) |
|
471 | 471 | self.assertEqual(r.status_code, 204) |
|
472 | 472 | nbcontent = self.api.read('a.ipynb', 'foo').json()['content'] |
|
473 | 473 | nb = to_notebook_json(nbcontent) |
|
474 | 474 | self.assertEqual(nb.cells, []) |
|
475 | 475 | |
|
476 | 476 | # Delete cp1 |
|
477 | 477 | r = self.api.delete_checkpoint('a.ipynb', 'foo', cp1['id']) |
|
478 | 478 | self.assertEqual(r.status_code, 204) |
|
479 | 479 | cps = self.api.get_checkpoints('a.ipynb', 'foo').json() |
|
480 | 480 | self.assertEqual(cps, []) |
@@ -1,226 +1,214 b'' | |||
|
1 | 1 | // Copyright (c) IPython Development Team. |
|
2 | 2 | // Distributed under the terms of the Modified BSD License. |
|
3 | 3 | |
|
4 | 4 | define([ |
|
5 | 5 | 'base/js/namespace', |
|
6 | 6 | 'jquery', |
|
7 | 7 | 'notebook/js/toolbar', |
|
8 | 8 | 'notebook/js/celltoolbar', |
|
9 | 9 | ], function(IPython, $, toolbar, celltoolbar) { |
|
10 | 10 | "use strict"; |
|
11 | 11 | |
|
12 | 12 | var MainToolBar = function (selector, options) { |
|
13 | 13 | // Constructor |
|
14 | 14 | // |
|
15 | 15 | // Parameters: |
|
16 | 16 | // selector: string |
|
17 | 17 | // options: dictionary |
|
18 | 18 | // Dictionary of keyword arguments. |
|
19 | 19 | // events: $(Events) instance |
|
20 | 20 | // notebook: Notebook instance |
|
21 | 21 | toolbar.ToolBar.apply(this, arguments); |
|
22 | 22 | this.events = options.events; |
|
23 | 23 | this.notebook = options.notebook; |
|
24 | 24 | this.construct(); |
|
25 | 25 | this.add_celltype_list(); |
|
26 | 26 | this.add_celltoolbar_list(); |
|
27 | 27 | this.bind_events(); |
|
28 | 28 | }; |
|
29 | 29 | |
|
30 | 30 | MainToolBar.prototype = Object.create(toolbar.ToolBar.prototype); |
|
31 | 31 | |
|
32 | 32 | MainToolBar.prototype.construct = function () { |
|
33 | 33 | var that = this; |
|
34 | 34 | this.add_buttons_group([ |
|
35 | 35 | { |
|
36 | 36 | id : 'save_b', |
|
37 | 37 | label : 'Save and Checkpoint', |
|
38 | 38 | icon : 'fa-save', |
|
39 | 39 | callback : function () { |
|
40 | 40 | that.notebook.save_checkpoint(); |
|
41 | 41 | } |
|
42 | 42 | } |
|
43 | 43 | ]); |
|
44 | 44 | |
|
45 | 45 | this.add_buttons_group([ |
|
46 | 46 | { |
|
47 | 47 | id : 'insert_below_b', |
|
48 | 48 | label : 'Insert Cell Below', |
|
49 | 49 | icon : 'fa-plus', |
|
50 | 50 | callback : function () { |
|
51 | 51 | that.notebook.insert_cell_below('code'); |
|
52 | 52 | that.notebook.select_next(); |
|
53 | 53 | that.notebook.focus_cell(); |
|
54 | 54 | } |
|
55 | 55 | } |
|
56 | 56 | ],'insert_above_below'); |
|
57 | 57 | |
|
58 | 58 | this.add_buttons_group([ |
|
59 | 59 | { |
|
60 | 60 | id : 'cut_b', |
|
61 | 61 | label : 'Cut Cell', |
|
62 | 62 | icon : 'fa-cut', |
|
63 | 63 | callback : function () { |
|
64 | 64 | that.notebook.cut_cell(); |
|
65 | 65 | } |
|
66 | 66 | }, |
|
67 | 67 | { |
|
68 | 68 | id : 'copy_b', |
|
69 | 69 | label : 'Copy Cell', |
|
70 | 70 | icon : 'fa-copy', |
|
71 | 71 | callback : function () { |
|
72 | 72 | that.notebook.copy_cell(); |
|
73 | 73 | } |
|
74 | 74 | }, |
|
75 | 75 | { |
|
76 | 76 | id : 'paste_b', |
|
77 | 77 | label : 'Paste Cell Below', |
|
78 | 78 | icon : 'fa-paste', |
|
79 | 79 | callback : function () { |
|
80 | 80 | that.notebook.paste_cell_below(); |
|
81 | 81 | } |
|
82 | 82 | } |
|
83 | 83 | ],'cut_copy_paste'); |
|
84 | 84 | |
|
85 | 85 | this.add_buttons_group([ |
|
86 | 86 | { |
|
87 | 87 | id : 'move_up_b', |
|
88 | 88 | label : 'Move Cell Up', |
|
89 | 89 | icon : 'fa-arrow-up', |
|
90 | 90 | callback : function () { |
|
91 | 91 | that.notebook.move_cell_up(); |
|
92 | 92 | } |
|
93 | 93 | }, |
|
94 | 94 | { |
|
95 | 95 | id : 'move_down_b', |
|
96 | 96 | label : 'Move Cell Down', |
|
97 | 97 | icon : 'fa-arrow-down', |
|
98 | 98 | callback : function () { |
|
99 | 99 | that.notebook.move_cell_down(); |
|
100 | 100 | } |
|
101 | 101 | } |
|
102 | 102 | ],'move_up_down'); |
|
103 | 103 | |
|
104 | 104 | |
|
105 | 105 | this.add_buttons_group([ |
|
106 | 106 | { |
|
107 | 107 | id : 'run_b', |
|
108 | 108 | label : 'Run Cell', |
|
109 | 109 | icon : 'fa-play', |
|
110 | 110 | callback : function () { |
|
111 | 111 | // emulate default shift-enter behavior |
|
112 | 112 | that.notebook.execute_cell_and_select_below(); |
|
113 | 113 | } |
|
114 | 114 | }, |
|
115 | 115 | { |
|
116 | 116 | id : 'interrupt_b', |
|
117 | 117 | label : 'Interrupt', |
|
118 | 118 | icon : 'fa-stop', |
|
119 | 119 | callback : function () { |
|
120 | 120 | that.notebook.kernel.interrupt(); |
|
121 | 121 | } |
|
122 | 122 | }, |
|
123 | 123 | { |
|
124 | 124 | id : 'repeat_b', |
|
125 | 125 | label : 'Restart Kernel', |
|
126 | 126 | icon : 'fa-repeat', |
|
127 | 127 | callback : function () { |
|
128 | 128 | that.notebook.restart_kernel(); |
|
129 | 129 | } |
|
130 | 130 | } |
|
131 | 131 | ],'run_int'); |
|
132 | 132 | }; |
|
133 | 133 | |
|
134 | 134 | MainToolBar.prototype.add_celltype_list = function () { |
|
135 | 135 | this.element |
|
136 | 136 | .append($('<select/>') |
|
137 | 137 | .attr('id','cell_type') |
|
138 | 138 | .addClass('form-control select-xs') |
|
139 | 139 | .append($('<option/>').attr('value','code').text('Code')) |
|
140 | 140 | .append($('<option/>').attr('value','markdown').text('Markdown')) |
|
141 | 141 | .append($('<option/>').attr('value','raw').text('Raw NBConvert')) |
|
142 | .append($('<option/>').attr('value','heading1').text('Heading 1')) | |
|
143 | .append($('<option/>').attr('value','heading2').text('Heading 2')) | |
|
144 | .append($('<option/>').attr('value','heading3').text('Heading 3')) | |
|
145 | .append($('<option/>').attr('value','heading4').text('Heading 4')) | |
|
146 | .append($('<option/>').attr('value','heading5').text('Heading 5')) | |
|
147 | .append($('<option/>').attr('value','heading6').text('Heading 6')) | |
|
148 | 142 | ); |
|
149 | 143 | }; |
|
150 | 144 | |
|
151 | 145 | MainToolBar.prototype.add_celltoolbar_list = function () { |
|
152 | 146 | var label = $('<span/>').addClass("navbar-text").text('Cell Toolbar:'); |
|
153 | 147 | var select = $('<select/>') |
|
154 | 148 | .attr('id', 'ctb_select') |
|
155 | 149 | .addClass('form-control select-xs') |
|
156 | 150 | .append($('<option/>').attr('value', '').text('None')); |
|
157 | 151 | this.element.append(label).append(select); |
|
158 | 152 | var that = this; |
|
159 | 153 | select.change(function() { |
|
160 | 154 | var val = $(this).val(); |
|
161 | 155 | if (val ==='') { |
|
162 | 156 | celltoolbar.CellToolbar.global_hide(); |
|
163 | 157 | delete that.notebook.metadata.celltoolbar; |
|
164 | 158 | } else { |
|
165 | 159 | celltoolbar.CellToolbar.global_show(); |
|
166 | 160 | celltoolbar.CellToolbar.activate_preset(val, that.events); |
|
167 | 161 | that.notebook.metadata.celltoolbar = val; |
|
168 | 162 | } |
|
169 | 163 | }); |
|
170 | 164 | // Setup the currently registered presets. |
|
171 | 165 | var presets = celltoolbar.CellToolbar.list_presets(); |
|
172 | 166 | for (var i=0; i<presets.length; i++) { |
|
173 | 167 | var name = presets[i]; |
|
174 | 168 | select.append($('<option/>').attr('value', name).text(name)); |
|
175 | 169 | } |
|
176 | 170 | // Setup future preset registrations. |
|
177 | 171 | this.events.on('preset_added.CellToolbar', function (event, data) { |
|
178 | 172 | var name = data.name; |
|
179 | 173 | select.append($('<option/>').attr('value', name).text(name)); |
|
180 | 174 | }); |
|
181 | 175 | // Update select value when a preset is activated. |
|
182 | 176 | this.events.on('preset_activated.CellToolbar', function (event, data) { |
|
183 | 177 | if (select.val() !== data.name) |
|
184 | 178 | select.val(data.name); |
|
185 | 179 | }); |
|
186 | 180 | }; |
|
187 | 181 | |
|
188 | 182 | MainToolBar.prototype.bind_events = function () { |
|
189 | 183 | var that = this; |
|
190 | 184 | |
|
191 | 185 | this.element.find('#cell_type').change(function () { |
|
192 | 186 | var cell_type = $(this).val(); |
|
193 |
|
|
|
187 | switch (cell_type) { | |
|
188 | case 'code': | |
|
194 | 189 | that.notebook.to_code(); |
|
195 | } else if (cell_type === 'markdown') { | |
|
190 | break; | |
|
191 | case 'markdown': | |
|
196 | 192 | that.notebook.to_markdown(); |
|
197 | } else if (cell_type === 'raw') { | |
|
193 | break; | |
|
194 | case 'raw': | |
|
198 | 195 | that.notebook.to_raw(); |
|
199 | } else if (cell_type === 'heading1') { | |
|
200 | that.notebook.to_heading(undefined, 1); | |
|
201 | } else if (cell_type === 'heading2') { | |
|
202 | that.notebook.to_heading(undefined, 2); | |
|
203 | } else if (cell_type === 'heading3') { | |
|
204 | that.notebook.to_heading(undefined, 3); | |
|
205 | } else if (cell_type === 'heading4') { | |
|
206 | that.notebook.to_heading(undefined, 4); | |
|
207 | } else if (cell_type === 'heading5') { | |
|
208 | that.notebook.to_heading(undefined, 5); | |
|
209 | } else if (cell_type === 'heading6') { | |
|
210 | that.notebook.to_heading(undefined, 6); | |
|
196 | break; | |
|
197 | default: | |
|
198 | console.log("unrecognized cell type:", cell_type); | |
|
211 | 199 | } |
|
212 | 200 | }); |
|
213 | 201 | this.events.on('selected_cell_type_changed.Notebook', function (event, data) { |
|
214 | 202 | if (data.cell_type === 'heading') { |
|
215 | 203 | that.element.find('#cell_type').val(data.cell_type+data.level); |
|
216 | 204 | } else { |
|
217 | 205 | that.element.find('#cell_type').val(data.cell_type); |
|
218 | 206 | } |
|
219 | 207 | }); |
|
220 | 208 | }; |
|
221 | 209 | |
|
222 | 210 | // Backwards compatability. |
|
223 | 211 | IPython.MainToolBar = MainToolBar; |
|
224 | 212 | |
|
225 | 213 | return {'MainToolBar': MainToolBar}; |
|
226 | 214 | }); |
@@ -1,2678 +1,2682 b'' | |||
|
1 | 1 | // Copyright (c) IPython Development Team. |
|
2 | 2 | // Distributed under the terms of the Modified BSD License. |
|
3 | 3 | |
|
4 | 4 | define([ |
|
5 | 5 | 'base/js/namespace', |
|
6 | 6 | 'jquery', |
|
7 | 7 | 'base/js/utils', |
|
8 | 8 | 'base/js/dialog', |
|
9 | 9 | 'notebook/js/textcell', |
|
10 | 10 | 'notebook/js/codecell', |
|
11 | 11 | 'services/sessions/session', |
|
12 | 12 | 'notebook/js/celltoolbar', |
|
13 | 13 | 'components/marked/lib/marked', |
|
14 | 14 | 'highlight', |
|
15 | 15 | 'notebook/js/mathjaxutils', |
|
16 | 16 | 'base/js/keyboard', |
|
17 | 17 | 'notebook/js/tooltip', |
|
18 | 18 | 'notebook/js/celltoolbarpresets/default', |
|
19 | 19 | 'notebook/js/celltoolbarpresets/rawcell', |
|
20 | 20 | 'notebook/js/celltoolbarpresets/slideshow', |
|
21 | 21 | 'notebook/js/scrollmanager' |
|
22 | 22 | ], function ( |
|
23 | 23 | IPython, |
|
24 | 24 | $, |
|
25 | 25 | utils, |
|
26 | 26 | dialog, |
|
27 | 27 | textcell, |
|
28 | 28 | codecell, |
|
29 | 29 | session, |
|
30 | 30 | celltoolbar, |
|
31 | 31 | marked, |
|
32 | 32 | hljs, |
|
33 | 33 | mathjaxutils, |
|
34 | 34 | keyboard, |
|
35 | 35 | tooltip, |
|
36 | 36 | default_celltoolbar, |
|
37 | 37 | rawcell_celltoolbar, |
|
38 | 38 | slideshow_celltoolbar, |
|
39 | 39 | scrollmanager |
|
40 | 40 | ) { |
|
41 | 41 | |
|
42 | 42 | var Notebook = function (selector, options) { |
|
43 | 43 | // Constructor |
|
44 | 44 | // |
|
45 | 45 | // A notebook contains and manages cells. |
|
46 | 46 | // |
|
47 | 47 | // Parameters: |
|
48 | 48 | // selector: string |
|
49 | 49 | // options: dictionary |
|
50 | 50 | // Dictionary of keyword arguments. |
|
51 | 51 | // events: $(Events) instance |
|
52 | 52 | // keyboard_manager: KeyboardManager instance |
|
53 | 53 | // save_widget: SaveWidget instance |
|
54 | 54 | // config: dictionary |
|
55 | 55 | // base_url : string |
|
56 | 56 | // notebook_path : string |
|
57 | 57 | // notebook_name : string |
|
58 | 58 | this.config = utils.mergeopt(Notebook, options.config); |
|
59 | 59 | this.base_url = options.base_url; |
|
60 | 60 | this.notebook_path = options.notebook_path; |
|
61 | 61 | this.notebook_name = options.notebook_name; |
|
62 | 62 | this.events = options.events; |
|
63 | 63 | this.keyboard_manager = options.keyboard_manager; |
|
64 | 64 | this.save_widget = options.save_widget; |
|
65 | 65 | this.tooltip = new tooltip.Tooltip(this.events); |
|
66 | 66 | this.ws_url = options.ws_url; |
|
67 | 67 | this._session_starting = false; |
|
68 | 68 | this.default_cell_type = this.config.default_cell_type || 'code'; |
|
69 | 69 | |
|
70 | 70 | // Create default scroll manager. |
|
71 | 71 | this.scroll_manager = new scrollmanager.ScrollManager(this); |
|
72 | 72 | |
|
73 | 73 | // TODO: This code smells (and the other `= this` line a couple lines down) |
|
74 | 74 | // We need a better way to deal with circular instance references. |
|
75 | 75 | this.keyboard_manager.notebook = this; |
|
76 | 76 | this.save_widget.notebook = this; |
|
77 | 77 | |
|
78 | 78 | mathjaxutils.init(); |
|
79 | 79 | |
|
80 | 80 | if (marked) { |
|
81 | 81 | marked.setOptions({ |
|
82 | 82 | gfm : true, |
|
83 | 83 | tables: true, |
|
84 | 84 | langPrefix: "language-", |
|
85 | 85 | highlight: function(code, lang) { |
|
86 | 86 | if (!lang) { |
|
87 | 87 | // no language, no highlight |
|
88 | 88 | return code; |
|
89 | 89 | } |
|
90 | 90 | var highlighted; |
|
91 | 91 | try { |
|
92 | 92 | highlighted = hljs.highlight(lang, code, false); |
|
93 | 93 | } catch(err) { |
|
94 | 94 | highlighted = hljs.highlightAuto(code); |
|
95 | 95 | } |
|
96 | 96 | return highlighted.value; |
|
97 | 97 | } |
|
98 | 98 | }); |
|
99 | 99 | } |
|
100 | 100 | |
|
101 | 101 | this.element = $(selector); |
|
102 | 102 | this.element.scroll(); |
|
103 | 103 | this.element.data("notebook", this); |
|
104 | 104 | this.next_prompt_number = 1; |
|
105 | 105 | this.session = null; |
|
106 | 106 | this.kernel = null; |
|
107 | 107 | this.clipboard = null; |
|
108 | 108 | this.undelete_backup = null; |
|
109 | 109 | this.undelete_index = null; |
|
110 | 110 | this.undelete_below = false; |
|
111 | 111 | this.paste_enabled = false; |
|
112 | 112 | // It is important to start out in command mode to match the intial mode |
|
113 | 113 | // of the KeyboardManager. |
|
114 | 114 | this.mode = 'command'; |
|
115 | 115 | this.set_dirty(false); |
|
116 | 116 | this.metadata = {}; |
|
117 | 117 | this._checkpoint_after_save = false; |
|
118 | 118 | this.last_checkpoint = null; |
|
119 | 119 | this.checkpoints = []; |
|
120 | 120 | this.autosave_interval = 0; |
|
121 | 121 | this.autosave_timer = null; |
|
122 | 122 | // autosave *at most* every two minutes |
|
123 | 123 | this.minimum_autosave_interval = 120000; |
|
124 | 124 | this.notebook_name_blacklist_re = /[\/\\:]/; |
|
125 | 125 | this.nbformat = 4; // Increment this when changing the nbformat |
|
126 | 126 | this.nbformat_minor = 0; // Increment this when changing the nbformat |
|
127 | 127 | this.codemirror_mode = 'ipython'; |
|
128 | 128 | this.create_elements(); |
|
129 | 129 | this.bind_events(); |
|
130 | 130 | this.save_notebook = function() { // don't allow save until notebook_loaded |
|
131 | 131 | this.save_notebook_error(null, null, "Load failed, save is disabled"); |
|
132 | 132 | }; |
|
133 | 133 | |
|
134 | 134 | // Trigger cell toolbar registration. |
|
135 | 135 | default_celltoolbar.register(this); |
|
136 | 136 | rawcell_celltoolbar.register(this); |
|
137 | 137 | slideshow_celltoolbar.register(this); |
|
138 | 138 | }; |
|
139 | 139 | |
|
140 | 140 | Notebook.options_default = { |
|
141 | 141 | // can be any cell type, or the special values of |
|
142 | 142 | // 'above', 'below', or 'selected' to get the value from another cell. |
|
143 | 143 | Notebook: { |
|
144 | 144 | default_cell_type: 'code', |
|
145 | 145 | } |
|
146 | 146 | }; |
|
147 | 147 | |
|
148 | 148 | |
|
149 | 149 | /** |
|
150 | 150 | * Create an HTML and CSS representation of the notebook. |
|
151 | 151 | * |
|
152 | 152 | * @method create_elements |
|
153 | 153 | */ |
|
154 | 154 | Notebook.prototype.create_elements = function () { |
|
155 | 155 | var that = this; |
|
156 | 156 | this.element.attr('tabindex','-1'); |
|
157 | 157 | this.container = $("<div/>").addClass("container").attr("id", "notebook-container"); |
|
158 | 158 | // We add this end_space div to the end of the notebook div to: |
|
159 | 159 | // i) provide a margin between the last cell and the end of the notebook |
|
160 | 160 | // ii) to prevent the div from scrolling up when the last cell is being |
|
161 | 161 | // edited, but is too low on the page, which browsers will do automatically. |
|
162 | 162 | var end_space = $('<div/>').addClass('end_space'); |
|
163 | 163 | end_space.dblclick(function (e) { |
|
164 | 164 | var ncells = that.ncells(); |
|
165 | 165 | that.insert_cell_below('code',ncells-1); |
|
166 | 166 | }); |
|
167 | 167 | this.element.append(this.container); |
|
168 | 168 | this.container.append(end_space); |
|
169 | 169 | }; |
|
170 | 170 | |
|
171 | 171 | /** |
|
172 | 172 | * Bind JavaScript events: key presses and custom IPython events. |
|
173 | 173 | * |
|
174 | 174 | * @method bind_events |
|
175 | 175 | */ |
|
176 | 176 | Notebook.prototype.bind_events = function () { |
|
177 | 177 | var that = this; |
|
178 | 178 | |
|
179 | 179 | this.events.on('set_next_input.Notebook', function (event, data) { |
|
180 | 180 | var index = that.find_cell_index(data.cell); |
|
181 | 181 | var new_cell = that.insert_cell_below('code',index); |
|
182 | 182 | new_cell.set_text(data.text); |
|
183 | 183 | that.dirty = true; |
|
184 | 184 | }); |
|
185 | 185 | |
|
186 | 186 | this.events.on('set_dirty.Notebook', function (event, data) { |
|
187 | 187 | that.dirty = data.value; |
|
188 | 188 | }); |
|
189 | 189 | |
|
190 | 190 | this.events.on('trust_changed.Notebook', function (event, trusted) { |
|
191 | 191 | that.trusted = trusted; |
|
192 | 192 | }); |
|
193 | 193 | |
|
194 | 194 | this.events.on('select.Cell', function (event, data) { |
|
195 | 195 | var index = that.find_cell_index(data.cell); |
|
196 | 196 | that.select(index); |
|
197 | 197 | }); |
|
198 | 198 | |
|
199 | 199 | this.events.on('edit_mode.Cell', function (event, data) { |
|
200 | 200 | that.handle_edit_mode(data.cell); |
|
201 | 201 | }); |
|
202 | 202 | |
|
203 | 203 | this.events.on('command_mode.Cell', function (event, data) { |
|
204 | 204 | that.handle_command_mode(data.cell); |
|
205 | 205 | }); |
|
206 | 206 | |
|
207 | 207 | this.events.on('spec_changed.Kernel', function(event, data) { |
|
208 | 208 | that.metadata.kernelspec = |
|
209 | 209 | {name: data.name, display_name: data.display_name}; |
|
210 | 210 | }); |
|
211 | 211 | |
|
212 | 212 | this.events.on('kernel_ready.Kernel', function(event, data) { |
|
213 | 213 | var kinfo = data.kernel.info_reply |
|
214 | 214 | var langinfo = kinfo.language_info || {}; |
|
215 | 215 | if (!langinfo.name) langinfo.name = kinfo.language; |
|
216 | 216 | |
|
217 | 217 | that.metadata.language_info = langinfo; |
|
218 | 218 | // Mode 'null' should be plain, unhighlighted text. |
|
219 | 219 | var cm_mode = langinfo.codemirror_mode || langinfo.language || 'null' |
|
220 | 220 | that.set_codemirror_mode(cm_mode); |
|
221 | 221 | }); |
|
222 | 222 | |
|
223 | 223 | var collapse_time = function (time) { |
|
224 | 224 | var app_height = $('#ipython-main-app').height(); // content height |
|
225 | 225 | var splitter_height = $('div#pager_splitter').outerHeight(true); |
|
226 | 226 | var new_height = app_height - splitter_height; |
|
227 | 227 | that.element.animate({height : new_height + 'px'}, time); |
|
228 | 228 | }; |
|
229 | 229 | |
|
230 | 230 | this.element.bind('collapse_pager', function (event, extrap) { |
|
231 | 231 | var time = (extrap !== undefined) ? ((extrap.duration !== undefined ) ? extrap.duration : 'fast') : 'fast'; |
|
232 | 232 | collapse_time(time); |
|
233 | 233 | }); |
|
234 | 234 | |
|
235 | 235 | var expand_time = function (time) { |
|
236 | 236 | var app_height = $('#ipython-main-app').height(); // content height |
|
237 | 237 | var splitter_height = $('div#pager_splitter').outerHeight(true); |
|
238 | 238 | var pager_height = $('div#pager').outerHeight(true); |
|
239 | 239 | var new_height = app_height - pager_height - splitter_height; |
|
240 | 240 | that.element.animate({height : new_height + 'px'}, time); |
|
241 | 241 | }; |
|
242 | 242 | |
|
243 | 243 | this.element.bind('expand_pager', function (event, extrap) { |
|
244 | 244 | var time = (extrap !== undefined) ? ((extrap.duration !== undefined ) ? extrap.duration : 'fast') : 'fast'; |
|
245 | 245 | expand_time(time); |
|
246 | 246 | }); |
|
247 | 247 | |
|
248 | 248 | // Firefox 22 broke $(window).on("beforeunload") |
|
249 | 249 | // I'm not sure why or how. |
|
250 | 250 | window.onbeforeunload = function (e) { |
|
251 | 251 | // TODO: Make killing the kernel configurable. |
|
252 | 252 | var kill_kernel = false; |
|
253 | 253 | if (kill_kernel) { |
|
254 | 254 | that.session.delete(); |
|
255 | 255 | } |
|
256 | 256 | // if we are autosaving, trigger an autosave on nav-away. |
|
257 | 257 | // still warn, because if we don't the autosave may fail. |
|
258 | 258 | if (that.dirty) { |
|
259 | 259 | if ( that.autosave_interval ) { |
|
260 | 260 | // schedule autosave in a timeout |
|
261 | 261 | // this gives you a chance to forcefully discard changes |
|
262 | 262 | // by reloading the page if you *really* want to. |
|
263 | 263 | // the timer doesn't start until you *dismiss* the dialog. |
|
264 | 264 | setTimeout(function () { |
|
265 | 265 | if (that.dirty) { |
|
266 | 266 | that.save_notebook(); |
|
267 | 267 | } |
|
268 | 268 | }, 1000); |
|
269 | 269 | return "Autosave in progress, latest changes may be lost."; |
|
270 | 270 | } else { |
|
271 | 271 | return "Unsaved changes will be lost."; |
|
272 | 272 | } |
|
273 | 273 | } |
|
274 | 274 | // Null is the *only* return value that will make the browser not |
|
275 | 275 | // pop up the "don't leave" dialog. |
|
276 | 276 | return null; |
|
277 | 277 | }; |
|
278 | 278 | }; |
|
279 | 279 | |
|
280 | 280 | /** |
|
281 | 281 | * Set the dirty flag, and trigger the set_dirty.Notebook event |
|
282 | 282 | * |
|
283 | 283 | * @method set_dirty |
|
284 | 284 | */ |
|
285 | 285 | Notebook.prototype.set_dirty = function (value) { |
|
286 | 286 | if (value === undefined) { |
|
287 | 287 | value = true; |
|
288 | 288 | } |
|
289 | 289 | if (this.dirty == value) { |
|
290 | 290 | return; |
|
291 | 291 | } |
|
292 | 292 | this.events.trigger('set_dirty.Notebook', {value: value}); |
|
293 | 293 | }; |
|
294 | 294 | |
|
295 | 295 | /** |
|
296 | 296 | * Scroll the top of the page to a given cell. |
|
297 | 297 | * |
|
298 | 298 | * @method scroll_to_cell |
|
299 | 299 | * @param {Number} cell_number An index of the cell to view |
|
300 | 300 | * @param {Number} time Animation time in milliseconds |
|
301 | 301 | * @return {Number} Pixel offset from the top of the container |
|
302 | 302 | */ |
|
303 | 303 | Notebook.prototype.scroll_to_cell = function (cell_number, time) { |
|
304 | 304 | var cells = this.get_cells(); |
|
305 | 305 | time = time || 0; |
|
306 | 306 | cell_number = Math.min(cells.length-1,cell_number); |
|
307 | 307 | cell_number = Math.max(0 ,cell_number); |
|
308 | 308 | var scroll_value = cells[cell_number].element.position().top-cells[0].element.position().top ; |
|
309 | 309 | this.element.animate({scrollTop:scroll_value}, time); |
|
310 | 310 | return scroll_value; |
|
311 | 311 | }; |
|
312 | 312 | |
|
313 | 313 | /** |
|
314 | 314 | * Scroll to the bottom of the page. |
|
315 | 315 | * |
|
316 | 316 | * @method scroll_to_bottom |
|
317 | 317 | */ |
|
318 | 318 | Notebook.prototype.scroll_to_bottom = function () { |
|
319 | 319 | this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0); |
|
320 | 320 | }; |
|
321 | 321 | |
|
322 | 322 | /** |
|
323 | 323 | * Scroll to the top of the page. |
|
324 | 324 | * |
|
325 | 325 | * @method scroll_to_top |
|
326 | 326 | */ |
|
327 | 327 | Notebook.prototype.scroll_to_top = function () { |
|
328 | 328 | this.element.animate({scrollTop:0}, 0); |
|
329 | 329 | }; |
|
330 | 330 | |
|
331 | 331 | // Edit Notebook metadata |
|
332 | 332 | |
|
333 | 333 | Notebook.prototype.edit_metadata = function () { |
|
334 | 334 | var that = this; |
|
335 | 335 | dialog.edit_metadata({ |
|
336 | 336 | md: this.metadata, |
|
337 | 337 | callback: function (md) { |
|
338 | 338 | that.metadata = md; |
|
339 | 339 | }, |
|
340 | 340 | name: 'Notebook', |
|
341 | 341 | notebook: this, |
|
342 | 342 | keyboard_manager: this.keyboard_manager}); |
|
343 | 343 | }; |
|
344 | 344 | |
|
345 | 345 | // Cell indexing, retrieval, etc. |
|
346 | 346 | |
|
347 | 347 | /** |
|
348 | 348 | * Get all cell elements in the notebook. |
|
349 | 349 | * |
|
350 | 350 | * @method get_cell_elements |
|
351 | 351 | * @return {jQuery} A selector of all cell elements |
|
352 | 352 | */ |
|
353 | 353 | Notebook.prototype.get_cell_elements = function () { |
|
354 | 354 | return this.container.children("div.cell"); |
|
355 | 355 | }; |
|
356 | 356 | |
|
357 | 357 | /** |
|
358 | 358 | * Get a particular cell element. |
|
359 | 359 | * |
|
360 | 360 | * @method get_cell_element |
|
361 | 361 | * @param {Number} index An index of a cell to select |
|
362 | 362 | * @return {jQuery} A selector of the given cell. |
|
363 | 363 | */ |
|
364 | 364 | Notebook.prototype.get_cell_element = function (index) { |
|
365 | 365 | var result = null; |
|
366 | 366 | var e = this.get_cell_elements().eq(index); |
|
367 | 367 | if (e.length !== 0) { |
|
368 | 368 | result = e; |
|
369 | 369 | } |
|
370 | 370 | return result; |
|
371 | 371 | }; |
|
372 | 372 | |
|
373 | 373 | /** |
|
374 | 374 | * Try to get a particular cell by msg_id. |
|
375 | 375 | * |
|
376 | 376 | * @method get_msg_cell |
|
377 | 377 | * @param {String} msg_id A message UUID |
|
378 | 378 | * @return {Cell} Cell or null if no cell was found. |
|
379 | 379 | */ |
|
380 | 380 | Notebook.prototype.get_msg_cell = function (msg_id) { |
|
381 | 381 | return codecell.CodeCell.msg_cells[msg_id] || null; |
|
382 | 382 | }; |
|
383 | 383 | |
|
384 | 384 | /** |
|
385 | 385 | * Count the cells in this notebook. |
|
386 | 386 | * |
|
387 | 387 | * @method ncells |
|
388 | 388 | * @return {Number} The number of cells in this notebook |
|
389 | 389 | */ |
|
390 | 390 | Notebook.prototype.ncells = function () { |
|
391 | 391 | return this.get_cell_elements().length; |
|
392 | 392 | }; |
|
393 | 393 | |
|
394 | 394 | /** |
|
395 | 395 | * Get all Cell objects in this notebook. |
|
396 | 396 | * |
|
397 | 397 | * @method get_cells |
|
398 | 398 | * @return {Array} This notebook's Cell objects |
|
399 | 399 | */ |
|
400 | 400 | // TODO: we are often calling cells as cells()[i], which we should optimize |
|
401 | 401 | // to cells(i) or a new method. |
|
402 | 402 | Notebook.prototype.get_cells = function () { |
|
403 | 403 | return this.get_cell_elements().toArray().map(function (e) { |
|
404 | 404 | return $(e).data("cell"); |
|
405 | 405 | }); |
|
406 | 406 | }; |
|
407 | 407 | |
|
408 | 408 | /** |
|
409 | 409 | * Get a Cell object from this notebook. |
|
410 | 410 | * |
|
411 | 411 | * @method get_cell |
|
412 | 412 | * @param {Number} index An index of a cell to retrieve |
|
413 | 413 | * @return {Cell} Cell or null if no cell was found. |
|
414 | 414 | */ |
|
415 | 415 | Notebook.prototype.get_cell = function (index) { |
|
416 | 416 | var result = null; |
|
417 | 417 | var ce = this.get_cell_element(index); |
|
418 | 418 | if (ce !== null) { |
|
419 | 419 | result = ce.data('cell'); |
|
420 | 420 | } |
|
421 | 421 | return result; |
|
422 | 422 | }; |
|
423 | 423 | |
|
424 | 424 | /** |
|
425 | 425 | * Get the cell below a given cell. |
|
426 | 426 | * |
|
427 | 427 | * @method get_next_cell |
|
428 | 428 | * @param {Cell} cell The provided cell |
|
429 | 429 | * @return {Cell} the next cell or null if no cell was found. |
|
430 | 430 | */ |
|
431 | 431 | Notebook.prototype.get_next_cell = function (cell) { |
|
432 | 432 | var result = null; |
|
433 | 433 | var index = this.find_cell_index(cell); |
|
434 | 434 | if (this.is_valid_cell_index(index+1)) { |
|
435 | 435 | result = this.get_cell(index+1); |
|
436 | 436 | } |
|
437 | 437 | return result; |
|
438 | 438 | }; |
|
439 | 439 | |
|
440 | 440 | /** |
|
441 | 441 | * Get the cell above a given cell. |
|
442 | 442 | * |
|
443 | 443 | * @method get_prev_cell |
|
444 | 444 | * @param {Cell} cell The provided cell |
|
445 | 445 | * @return {Cell} The previous cell or null if no cell was found. |
|
446 | 446 | */ |
|
447 | 447 | Notebook.prototype.get_prev_cell = function (cell) { |
|
448 | 448 | var result = null; |
|
449 | 449 | var index = this.find_cell_index(cell); |
|
450 | 450 | if (index !== null && index > 0) { |
|
451 | 451 | result = this.get_cell(index-1); |
|
452 | 452 | } |
|
453 | 453 | return result; |
|
454 | 454 | }; |
|
455 | 455 | |
|
456 | 456 | /** |
|
457 | 457 | * Get the numeric index of a given cell. |
|
458 | 458 | * |
|
459 | 459 | * @method find_cell_index |
|
460 | 460 | * @param {Cell} cell The provided cell |
|
461 | 461 | * @return {Number} The cell's numeric index or null if no cell was found. |
|
462 | 462 | */ |
|
463 | 463 | Notebook.prototype.find_cell_index = function (cell) { |
|
464 | 464 | var result = null; |
|
465 | 465 | this.get_cell_elements().filter(function (index) { |
|
466 | 466 | if ($(this).data("cell") === cell) { |
|
467 | 467 | result = index; |
|
468 | 468 | } |
|
469 | 469 | }); |
|
470 | 470 | return result; |
|
471 | 471 | }; |
|
472 | 472 | |
|
473 | 473 | /** |
|
474 | 474 | * Get a given index , or the selected index if none is provided. |
|
475 | 475 | * |
|
476 | 476 | * @method index_or_selected |
|
477 | 477 | * @param {Number} index A cell's index |
|
478 | 478 | * @return {Number} The given index, or selected index if none is provided. |
|
479 | 479 | */ |
|
480 | 480 | Notebook.prototype.index_or_selected = function (index) { |
|
481 | 481 | var i; |
|
482 | 482 | if (index === undefined || index === null) { |
|
483 | 483 | i = this.get_selected_index(); |
|
484 | 484 | if (i === null) { |
|
485 | 485 | i = 0; |
|
486 | 486 | } |
|
487 | 487 | } else { |
|
488 | 488 | i = index; |
|
489 | 489 | } |
|
490 | 490 | return i; |
|
491 | 491 | }; |
|
492 | 492 | |
|
493 | 493 | /** |
|
494 | 494 | * Get the currently selected cell. |
|
495 | 495 | * @method get_selected_cell |
|
496 | 496 | * @return {Cell} The selected cell |
|
497 | 497 | */ |
|
498 | 498 | Notebook.prototype.get_selected_cell = function () { |
|
499 | 499 | var index = this.get_selected_index(); |
|
500 | 500 | return this.get_cell(index); |
|
501 | 501 | }; |
|
502 | 502 | |
|
503 | 503 | /** |
|
504 | 504 | * Check whether a cell index is valid. |
|
505 | 505 | * |
|
506 | 506 | * @method is_valid_cell_index |
|
507 | 507 | * @param {Number} index A cell index |
|
508 | 508 | * @return True if the index is valid, false otherwise |
|
509 | 509 | */ |
|
510 | 510 | Notebook.prototype.is_valid_cell_index = function (index) { |
|
511 | 511 | if (index !== null && index >= 0 && index < this.ncells()) { |
|
512 | 512 | return true; |
|
513 | 513 | } else { |
|
514 | 514 | return false; |
|
515 | 515 | } |
|
516 | 516 | }; |
|
517 | 517 | |
|
518 | 518 | /** |
|
519 | 519 | * Get the index of the currently selected cell. |
|
520 | 520 | |
|
521 | 521 | * @method get_selected_index |
|
522 | 522 | * @return {Number} The selected cell's numeric index |
|
523 | 523 | */ |
|
524 | 524 | Notebook.prototype.get_selected_index = function () { |
|
525 | 525 | var result = null; |
|
526 | 526 | this.get_cell_elements().filter(function (index) { |
|
527 | 527 | if ($(this).data("cell").selected === true) { |
|
528 | 528 | result = index; |
|
529 | 529 | } |
|
530 | 530 | }); |
|
531 | 531 | return result; |
|
532 | 532 | }; |
|
533 | 533 | |
|
534 | 534 | |
|
535 | 535 | // Cell selection. |
|
536 | 536 | |
|
537 | 537 | /** |
|
538 | 538 | * Programmatically select a cell. |
|
539 | 539 | * |
|
540 | 540 | * @method select |
|
541 | 541 | * @param {Number} index A cell's index |
|
542 | 542 | * @return {Notebook} This notebook |
|
543 | 543 | */ |
|
544 | 544 | Notebook.prototype.select = function (index) { |
|
545 | 545 | if (this.is_valid_cell_index(index)) { |
|
546 | 546 | var sindex = this.get_selected_index(); |
|
547 | 547 | if (sindex !== null && index !== sindex) { |
|
548 | 548 | // If we are about to select a different cell, make sure we are |
|
549 | 549 | // first in command mode. |
|
550 | 550 | if (this.mode !== 'command') { |
|
551 | 551 | this.command_mode(); |
|
552 | 552 | } |
|
553 | 553 | this.get_cell(sindex).unselect(); |
|
554 | 554 | } |
|
555 | 555 | var cell = this.get_cell(index); |
|
556 | 556 | cell.select(); |
|
557 | 557 | if (cell.cell_type === 'heading') { |
|
558 | 558 | this.events.trigger('selected_cell_type_changed.Notebook', |
|
559 | 559 | {'cell_type':cell.cell_type,level:cell.level} |
|
560 | 560 | ); |
|
561 | 561 | } else { |
|
562 | 562 | this.events.trigger('selected_cell_type_changed.Notebook', |
|
563 | 563 | {'cell_type':cell.cell_type} |
|
564 | 564 | ); |
|
565 | 565 | } |
|
566 | 566 | } |
|
567 | 567 | return this; |
|
568 | 568 | }; |
|
569 | 569 | |
|
570 | 570 | /** |
|
571 | 571 | * Programmatically select the next cell. |
|
572 | 572 | * |
|
573 | 573 | * @method select_next |
|
574 | 574 | * @return {Notebook} This notebook |
|
575 | 575 | */ |
|
576 | 576 | Notebook.prototype.select_next = function () { |
|
577 | 577 | var index = this.get_selected_index(); |
|
578 | 578 | this.select(index+1); |
|
579 | 579 | return this; |
|
580 | 580 | }; |
|
581 | 581 | |
|
582 | 582 | /** |
|
583 | 583 | * Programmatically select the previous cell. |
|
584 | 584 | * |
|
585 | 585 | * @method select_prev |
|
586 | 586 | * @return {Notebook} This notebook |
|
587 | 587 | */ |
|
588 | 588 | Notebook.prototype.select_prev = function () { |
|
589 | 589 | var index = this.get_selected_index(); |
|
590 | 590 | this.select(index-1); |
|
591 | 591 | return this; |
|
592 | 592 | }; |
|
593 | 593 | |
|
594 | 594 | |
|
595 | 595 | // Edit/Command mode |
|
596 | 596 | |
|
597 | 597 | /** |
|
598 | 598 | * Gets the index of the cell that is in edit mode. |
|
599 | 599 | * |
|
600 | 600 | * @method get_edit_index |
|
601 | 601 | * |
|
602 | 602 | * @return index {int} |
|
603 | 603 | **/ |
|
604 | 604 | Notebook.prototype.get_edit_index = function () { |
|
605 | 605 | var result = null; |
|
606 | 606 | this.get_cell_elements().filter(function (index) { |
|
607 | 607 | if ($(this).data("cell").mode === 'edit') { |
|
608 | 608 | result = index; |
|
609 | 609 | } |
|
610 | 610 | }); |
|
611 | 611 | return result; |
|
612 | 612 | }; |
|
613 | 613 | |
|
614 | 614 | /** |
|
615 | 615 | * Handle when a a cell blurs and the notebook should enter command mode. |
|
616 | 616 | * |
|
617 | 617 | * @method handle_command_mode |
|
618 | 618 | * @param [cell] {Cell} Cell to enter command mode on. |
|
619 | 619 | **/ |
|
620 | 620 | Notebook.prototype.handle_command_mode = function (cell) { |
|
621 | 621 | if (this.mode !== 'command') { |
|
622 | 622 | cell.command_mode(); |
|
623 | 623 | this.mode = 'command'; |
|
624 | 624 | this.events.trigger('command_mode.Notebook'); |
|
625 | 625 | this.keyboard_manager.command_mode(); |
|
626 | 626 | } |
|
627 | 627 | }; |
|
628 | 628 | |
|
629 | 629 | /** |
|
630 | 630 | * Make the notebook enter command mode. |
|
631 | 631 | * |
|
632 | 632 | * @method command_mode |
|
633 | 633 | **/ |
|
634 | 634 | Notebook.prototype.command_mode = function () { |
|
635 | 635 | var cell = this.get_cell(this.get_edit_index()); |
|
636 | 636 | if (cell && this.mode !== 'command') { |
|
637 | 637 | // We don't call cell.command_mode, but rather call cell.focus_cell() |
|
638 | 638 | // which will blur and CM editor and trigger the call to |
|
639 | 639 | // handle_command_mode. |
|
640 | 640 | cell.focus_cell(); |
|
641 | 641 | } |
|
642 | 642 | }; |
|
643 | 643 | |
|
644 | 644 | /** |
|
645 | 645 | * Handle when a cell fires it's edit_mode event. |
|
646 | 646 | * |
|
647 | 647 | * @method handle_edit_mode |
|
648 | 648 | * @param [cell] {Cell} Cell to enter edit mode on. |
|
649 | 649 | **/ |
|
650 | 650 | Notebook.prototype.handle_edit_mode = function (cell) { |
|
651 | 651 | if (cell && this.mode !== 'edit') { |
|
652 | 652 | cell.edit_mode(); |
|
653 | 653 | this.mode = 'edit'; |
|
654 | 654 | this.events.trigger('edit_mode.Notebook'); |
|
655 | 655 | this.keyboard_manager.edit_mode(); |
|
656 | 656 | } |
|
657 | 657 | }; |
|
658 | 658 | |
|
659 | 659 | /** |
|
660 | 660 | * Make a cell enter edit mode. |
|
661 | 661 | * |
|
662 | 662 | * @method edit_mode |
|
663 | 663 | **/ |
|
664 | 664 | Notebook.prototype.edit_mode = function () { |
|
665 | 665 | var cell = this.get_selected_cell(); |
|
666 | 666 | if (cell && this.mode !== 'edit') { |
|
667 | 667 | cell.unrender(); |
|
668 | 668 | cell.focus_editor(); |
|
669 | 669 | } |
|
670 | 670 | }; |
|
671 | 671 | |
|
672 | 672 | /** |
|
673 | 673 | * Focus the currently selected cell. |
|
674 | 674 | * |
|
675 | 675 | * @method focus_cell |
|
676 | 676 | **/ |
|
677 | 677 | Notebook.prototype.focus_cell = function () { |
|
678 | 678 | var cell = this.get_selected_cell(); |
|
679 | 679 | if (cell === null) {return;} // No cell is selected |
|
680 | 680 | cell.focus_cell(); |
|
681 | 681 | }; |
|
682 | 682 | |
|
683 | 683 | // Cell movement |
|
684 | 684 | |
|
685 | 685 | /** |
|
686 | 686 | * Move given (or selected) cell up and select it. |
|
687 | 687 | * |
|
688 | 688 | * @method move_cell_up |
|
689 | 689 | * @param [index] {integer} cell index |
|
690 | 690 | * @return {Notebook} This notebook |
|
691 | 691 | **/ |
|
692 | 692 | Notebook.prototype.move_cell_up = function (index) { |
|
693 | 693 | var i = this.index_or_selected(index); |
|
694 | 694 | if (this.is_valid_cell_index(i) && i > 0) { |
|
695 | 695 | var pivot = this.get_cell_element(i-1); |
|
696 | 696 | var tomove = this.get_cell_element(i); |
|
697 | 697 | if (pivot !== null && tomove !== null) { |
|
698 | 698 | tomove.detach(); |
|
699 | 699 | pivot.before(tomove); |
|
700 | 700 | this.select(i-1); |
|
701 | 701 | var cell = this.get_selected_cell(); |
|
702 | 702 | cell.focus_cell(); |
|
703 | 703 | } |
|
704 | 704 | this.set_dirty(true); |
|
705 | 705 | } |
|
706 | 706 | return this; |
|
707 | 707 | }; |
|
708 | 708 | |
|
709 | 709 | |
|
710 | 710 | /** |
|
711 | 711 | * Move given (or selected) cell down and select it |
|
712 | 712 | * |
|
713 | 713 | * @method move_cell_down |
|
714 | 714 | * @param [index] {integer} cell index |
|
715 | 715 | * @return {Notebook} This notebook |
|
716 | 716 | **/ |
|
717 | 717 | Notebook.prototype.move_cell_down = function (index) { |
|
718 | 718 | var i = this.index_or_selected(index); |
|
719 | 719 | if (this.is_valid_cell_index(i) && this.is_valid_cell_index(i+1)) { |
|
720 | 720 | var pivot = this.get_cell_element(i+1); |
|
721 | 721 | var tomove = this.get_cell_element(i); |
|
722 | 722 | if (pivot !== null && tomove !== null) { |
|
723 | 723 | tomove.detach(); |
|
724 | 724 | pivot.after(tomove); |
|
725 | 725 | this.select(i+1); |
|
726 | 726 | var cell = this.get_selected_cell(); |
|
727 | 727 | cell.focus_cell(); |
|
728 | 728 | } |
|
729 | 729 | } |
|
730 | 730 | this.set_dirty(); |
|
731 | 731 | return this; |
|
732 | 732 | }; |
|
733 | 733 | |
|
734 | 734 | |
|
735 | 735 | // Insertion, deletion. |
|
736 | 736 | |
|
737 | 737 | /** |
|
738 | 738 | * Delete a cell from the notebook. |
|
739 | 739 | * |
|
740 | 740 | * @method delete_cell |
|
741 | 741 | * @param [index] A cell's numeric index |
|
742 | 742 | * @return {Notebook} This notebook |
|
743 | 743 | */ |
|
744 | 744 | Notebook.prototype.delete_cell = function (index) { |
|
745 | 745 | var i = this.index_or_selected(index); |
|
746 | 746 | var cell = this.get_cell(i); |
|
747 | 747 | if (!cell.is_deletable()) { |
|
748 | 748 | return this; |
|
749 | 749 | } |
|
750 | 750 | |
|
751 | 751 | this.undelete_backup = cell.toJSON(); |
|
752 | 752 | $('#undelete_cell').removeClass('disabled'); |
|
753 | 753 | if (this.is_valid_cell_index(i)) { |
|
754 | 754 | var old_ncells = this.ncells(); |
|
755 | 755 | var ce = this.get_cell_element(i); |
|
756 | 756 | ce.remove(); |
|
757 | 757 | if (i === 0) { |
|
758 | 758 | // Always make sure we have at least one cell. |
|
759 | 759 | if (old_ncells === 1) { |
|
760 | 760 | this.insert_cell_below('code'); |
|
761 | 761 | } |
|
762 | 762 | this.select(0); |
|
763 | 763 | this.undelete_index = 0; |
|
764 | 764 | this.undelete_below = false; |
|
765 | 765 | } else if (i === old_ncells-1 && i !== 0) { |
|
766 | 766 | this.select(i-1); |
|
767 | 767 | this.undelete_index = i - 1; |
|
768 | 768 | this.undelete_below = true; |
|
769 | 769 | } else { |
|
770 | 770 | this.select(i); |
|
771 | 771 | this.undelete_index = i; |
|
772 | 772 | this.undelete_below = false; |
|
773 | 773 | } |
|
774 | 774 | this.events.trigger('delete.Cell', {'cell': cell, 'index': i}); |
|
775 | 775 | this.set_dirty(true); |
|
776 | 776 | } |
|
777 | 777 | return this; |
|
778 | 778 | }; |
|
779 | 779 | |
|
780 | 780 | /** |
|
781 | 781 | * Restore the most recently deleted cell. |
|
782 | 782 | * |
|
783 | 783 | * @method undelete |
|
784 | 784 | */ |
|
785 | 785 | Notebook.prototype.undelete_cell = function() { |
|
786 | 786 | if (this.undelete_backup !== null && this.undelete_index !== null) { |
|
787 | 787 | var current_index = this.get_selected_index(); |
|
788 | 788 | if (this.undelete_index < current_index) { |
|
789 | 789 | current_index = current_index + 1; |
|
790 | 790 | } |
|
791 | 791 | if (this.undelete_index >= this.ncells()) { |
|
792 | 792 | this.select(this.ncells() - 1); |
|
793 | 793 | } |
|
794 | 794 | else { |
|
795 | 795 | this.select(this.undelete_index); |
|
796 | 796 | } |
|
797 | 797 | var cell_data = this.undelete_backup; |
|
798 | 798 | var new_cell = null; |
|
799 | 799 | if (this.undelete_below) { |
|
800 | 800 | new_cell = this.insert_cell_below(cell_data.cell_type); |
|
801 | 801 | } else { |
|
802 | 802 | new_cell = this.insert_cell_above(cell_data.cell_type); |
|
803 | 803 | } |
|
804 | 804 | new_cell.fromJSON(cell_data); |
|
805 | 805 | if (this.undelete_below) { |
|
806 | 806 | this.select(current_index+1); |
|
807 | 807 | } else { |
|
808 | 808 | this.select(current_index); |
|
809 | 809 | } |
|
810 | 810 | this.undelete_backup = null; |
|
811 | 811 | this.undelete_index = null; |
|
812 | 812 | } |
|
813 | 813 | $('#undelete_cell').addClass('disabled'); |
|
814 | 814 | }; |
|
815 | 815 | |
|
816 | 816 | /** |
|
817 | 817 | * Insert a cell so that after insertion the cell is at given index. |
|
818 | 818 | * |
|
819 | 819 | * If cell type is not provided, it will default to the type of the |
|
820 | 820 | * currently active cell. |
|
821 | 821 | * |
|
822 | 822 | * Similar to insert_above, but index parameter is mandatory |
|
823 | 823 | * |
|
824 | 824 | * Index will be brought back into the accessible range [0,n] |
|
825 | 825 | * |
|
826 | 826 | * @method insert_cell_at_index |
|
827 |
* @param [type] {string} in ['code','markdown', |
|
|
827 | * @param [type] {string} in ['code','markdown', 'raw'], defaults to 'code' | |
|
828 | 828 | * @param [index] {int} a valid index where to insert cell |
|
829 | 829 | * |
|
830 | 830 | * @return cell {cell|null} created cell or null |
|
831 | 831 | **/ |
|
832 | 832 | Notebook.prototype.insert_cell_at_index = function(type, index){ |
|
833 | 833 | |
|
834 | 834 | var ncells = this.ncells(); |
|
835 | 835 | index = Math.min(index, ncells); |
|
836 | 836 | index = Math.max(index, 0); |
|
837 | 837 | var cell = null; |
|
838 | 838 | type = type || this.default_cell_type; |
|
839 | 839 | if (type === 'above') { |
|
840 | 840 | if (index > 0) { |
|
841 | 841 | type = this.get_cell(index-1).cell_type; |
|
842 | 842 | } else { |
|
843 | 843 | type = 'code'; |
|
844 | 844 | } |
|
845 | 845 | } else if (type === 'below') { |
|
846 | 846 | if (index < ncells) { |
|
847 | 847 | type = this.get_cell(index).cell_type; |
|
848 | 848 | } else { |
|
849 | 849 | type = 'code'; |
|
850 | 850 | } |
|
851 | 851 | } else if (type === 'selected') { |
|
852 | 852 | type = this.get_selected_cell().cell_type; |
|
853 | 853 | } |
|
854 | 854 | |
|
855 | 855 | if (ncells === 0 || this.is_valid_cell_index(index) || index === ncells) { |
|
856 | 856 | var cell_options = { |
|
857 | 857 | events: this.events, |
|
858 | 858 | config: this.config, |
|
859 | 859 | keyboard_manager: this.keyboard_manager, |
|
860 | 860 | notebook: this, |
|
861 | 861 | tooltip: this.tooltip, |
|
862 | 862 | }; |
|
863 |
|
|
|
863 | switch(type) { | |
|
864 | case 'code': | |
|
864 | 865 | cell = new codecell.CodeCell(this.kernel, cell_options); |
|
865 | 866 | cell.set_input_prompt(); |
|
866 | } else if (type === 'markdown') { | |
|
867 | break; | |
|
868 | case 'markdown': | |
|
867 | 869 | cell = new textcell.MarkdownCell(cell_options); |
|
868 | } else if (type === 'raw') { | |
|
870 | break; | |
|
871 | case 'raw': | |
|
869 | 872 | cell = new textcell.RawCell(cell_options); |
|
870 | } else if (type === 'heading') { | |
|
871 | cell = new textcell.HeadingCell(cell_options); | |
|
873 | break; | |
|
874 | default: | |
|
875 | console.log("invalid cell type: ", type); | |
|
872 | 876 | } |
|
873 | 877 | |
|
874 | 878 | if(this._insert_element_at_index(cell.element,index)) { |
|
875 | 879 | cell.render(); |
|
876 | 880 | this.events.trigger('create.Cell', {'cell': cell, 'index': index}); |
|
877 | 881 | cell.refresh(); |
|
878 | 882 | // We used to select the cell after we refresh it, but there |
|
879 | 883 | // are now cases were this method is called where select is |
|
880 | 884 | // not appropriate. The selection logic should be handled by the |
|
881 | 885 | // caller of the the top level insert_cell methods. |
|
882 | 886 | this.set_dirty(true); |
|
883 | 887 | } |
|
884 | 888 | } |
|
885 | 889 | return cell; |
|
886 | 890 | |
|
887 | 891 | }; |
|
888 | 892 | |
|
889 | 893 | /** |
|
890 | 894 | * Insert an element at given cell index. |
|
891 | 895 | * |
|
892 | 896 | * @method _insert_element_at_index |
|
893 | 897 | * @param element {dom_element} a cell element |
|
894 | 898 | * @param [index] {int} a valid index where to inser cell |
|
895 | 899 | * @private |
|
896 | 900 | * |
|
897 | 901 | * return true if everything whent fine. |
|
898 | 902 | **/ |
|
899 | 903 | Notebook.prototype._insert_element_at_index = function(element, index){ |
|
900 | 904 | if (element === undefined){ |
|
901 | 905 | return false; |
|
902 | 906 | } |
|
903 | 907 | |
|
904 | 908 | var ncells = this.ncells(); |
|
905 | 909 | |
|
906 | 910 | if (ncells === 0) { |
|
907 | 911 | // special case append if empty |
|
908 | 912 | this.element.find('div.end_space').before(element); |
|
909 | 913 | } else if ( ncells === index ) { |
|
910 | 914 | // special case append it the end, but not empty |
|
911 | 915 | this.get_cell_element(index-1).after(element); |
|
912 | 916 | } else if (this.is_valid_cell_index(index)) { |
|
913 | 917 | // otherwise always somewhere to append to |
|
914 | 918 | this.get_cell_element(index).before(element); |
|
915 | 919 | } else { |
|
916 | 920 | return false; |
|
917 | 921 | } |
|
918 | 922 | |
|
919 | 923 | if (this.undelete_index !== null && index <= this.undelete_index) { |
|
920 | 924 | this.undelete_index = this.undelete_index + 1; |
|
921 | 925 | this.set_dirty(true); |
|
922 | 926 | } |
|
923 | 927 | return true; |
|
924 | 928 | }; |
|
925 | 929 | |
|
926 | 930 | /** |
|
927 | 931 | * Insert a cell of given type above given index, or at top |
|
928 | 932 | * of notebook if index smaller than 0. |
|
929 | 933 | * |
|
930 | 934 | * default index value is the one of currently selected cell |
|
931 | 935 | * |
|
932 | 936 | * @method insert_cell_above |
|
933 | 937 | * @param [type] {string} cell type |
|
934 | 938 | * @param [index] {integer} |
|
935 | 939 | * |
|
936 | 940 | * @return handle to created cell or null |
|
937 | 941 | **/ |
|
938 | 942 | Notebook.prototype.insert_cell_above = function (type, index) { |
|
939 | 943 | index = this.index_or_selected(index); |
|
940 | 944 | return this.insert_cell_at_index(type, index); |
|
941 | 945 | }; |
|
942 | 946 | |
|
943 | 947 | /** |
|
944 | 948 | * Insert a cell of given type below given index, or at bottom |
|
945 | 949 | * of notebook if index greater than number of cells |
|
946 | 950 | * |
|
947 | 951 | * default index value is the one of currently selected cell |
|
948 | 952 | * |
|
949 | 953 | * @method insert_cell_below |
|
950 | 954 | * @param [type] {string} cell type |
|
951 | 955 | * @param [index] {integer} |
|
952 | 956 | * |
|
953 | 957 | * @return handle to created cell or null |
|
954 | 958 | * |
|
955 | 959 | **/ |
|
956 | 960 | Notebook.prototype.insert_cell_below = function (type, index) { |
|
957 | 961 | index = this.index_or_selected(index); |
|
958 | 962 | return this.insert_cell_at_index(type, index+1); |
|
959 | 963 | }; |
|
960 | 964 | |
|
961 | 965 | |
|
962 | 966 | /** |
|
963 | 967 | * Insert cell at end of notebook |
|
964 | 968 | * |
|
965 | 969 | * @method insert_cell_at_bottom |
|
966 | 970 | * @param {String} type cell type |
|
967 | 971 | * |
|
968 | 972 | * @return the added cell; or null |
|
969 | 973 | **/ |
|
970 | 974 | Notebook.prototype.insert_cell_at_bottom = function (type){ |
|
971 | 975 | var len = this.ncells(); |
|
972 | 976 | return this.insert_cell_below(type,len-1); |
|
973 | 977 | }; |
|
974 | 978 | |
|
975 | 979 | /** |
|
976 | 980 | * Turn a cell into a code cell. |
|
977 | 981 | * |
|
978 | 982 | * @method to_code |
|
979 | 983 | * @param {Number} [index] A cell's index |
|
980 | 984 | */ |
|
981 | 985 | Notebook.prototype.to_code = function (index) { |
|
982 | 986 | var i = this.index_or_selected(index); |
|
983 | 987 | if (this.is_valid_cell_index(i)) { |
|
984 | 988 | var source_cell = this.get_cell(i); |
|
985 | 989 | if (!(source_cell instanceof codecell.CodeCell)) { |
|
986 | 990 | var target_cell = this.insert_cell_below('code',i); |
|
987 | 991 | var text = source_cell.get_text(); |
|
988 | 992 | if (text === source_cell.placeholder) { |
|
989 | 993 | text = ''; |
|
990 | 994 | } |
|
991 | 995 | //metadata |
|
992 | 996 | target_cell.metadata = source_cell.metadata; |
|
993 | 997 | |
|
994 | 998 | target_cell.set_text(text); |
|
995 | 999 | // make this value the starting point, so that we can only undo |
|
996 | 1000 | // to this state, instead of a blank cell |
|
997 | 1001 | target_cell.code_mirror.clearHistory(); |
|
998 | 1002 | source_cell.element.remove(); |
|
999 | 1003 | this.select(i); |
|
1000 | 1004 | var cursor = source_cell.code_mirror.getCursor(); |
|
1001 | 1005 | target_cell.code_mirror.setCursor(cursor); |
|
1002 | 1006 | this.set_dirty(true); |
|
1003 | 1007 | } |
|
1004 | 1008 | } |
|
1005 | 1009 | }; |
|
1006 | 1010 | |
|
1007 | 1011 | /** |
|
1008 | 1012 | * Turn a cell into a Markdown cell. |
|
1009 | 1013 | * |
|
1010 | 1014 | * @method to_markdown |
|
1011 | 1015 | * @param {Number} [index] A cell's index |
|
1012 | 1016 | */ |
|
1013 | 1017 | Notebook.prototype.to_markdown = function (index) { |
|
1014 | 1018 | var i = this.index_or_selected(index); |
|
1015 | 1019 | if (this.is_valid_cell_index(i)) { |
|
1016 | 1020 | var source_cell = this.get_cell(i); |
|
1017 | 1021 | |
|
1018 | 1022 | if (!(source_cell instanceof textcell.MarkdownCell)) { |
|
1019 | 1023 | var target_cell = this.insert_cell_below('markdown',i); |
|
1020 | 1024 | var text = source_cell.get_text(); |
|
1021 | 1025 | |
|
1022 | 1026 | if (text === source_cell.placeholder) { |
|
1023 | 1027 | text = ''; |
|
1024 | 1028 | } |
|
1025 | 1029 | // metadata |
|
1026 | 1030 | target_cell.metadata = source_cell.metadata |
|
1027 | 1031 | // We must show the editor before setting its contents |
|
1028 | 1032 | target_cell.unrender(); |
|
1029 | 1033 | target_cell.set_text(text); |
|
1030 | 1034 | // make this value the starting point, so that we can only undo |
|
1031 | 1035 | // to this state, instead of a blank cell |
|
1032 | 1036 | target_cell.code_mirror.clearHistory(); |
|
1033 | 1037 | source_cell.element.remove(); |
|
1034 | 1038 | this.select(i); |
|
1035 | 1039 | if ((source_cell instanceof textcell.TextCell) && source_cell.rendered) { |
|
1036 | 1040 | target_cell.render(); |
|
1037 | 1041 | } |
|
1038 | 1042 | var cursor = source_cell.code_mirror.getCursor(); |
|
1039 | 1043 | target_cell.code_mirror.setCursor(cursor); |
|
1040 | 1044 | this.set_dirty(true); |
|
1041 | 1045 | } |
|
1042 | 1046 | } |
|
1043 | 1047 | }; |
|
1044 | 1048 | |
|
1045 | 1049 | /** |
|
1046 | 1050 | * Turn a cell into a raw text cell. |
|
1047 | 1051 | * |
|
1048 | 1052 | * @method to_raw |
|
1049 | 1053 | * @param {Number} [index] A cell's index |
|
1050 | 1054 | */ |
|
1051 | 1055 | Notebook.prototype.to_raw = function (index) { |
|
1052 | 1056 | var i = this.index_or_selected(index); |
|
1053 | 1057 | if (this.is_valid_cell_index(i)) { |
|
1054 | 1058 | var target_cell = null; |
|
1055 | 1059 | var source_cell = this.get_cell(i); |
|
1056 | 1060 | |
|
1057 | 1061 | if (!(source_cell instanceof textcell.RawCell)) { |
|
1058 | 1062 | target_cell = this.insert_cell_below('raw',i); |
|
1059 | 1063 | var text = source_cell.get_text(); |
|
1060 | 1064 | if (text === source_cell.placeholder) { |
|
1061 | 1065 | text = ''; |
|
1062 | 1066 | } |
|
1063 | 1067 | //metadata |
|
1064 | 1068 | target_cell.metadata = source_cell.metadata; |
|
1065 | 1069 | // We must show the editor before setting its contents |
|
1066 | 1070 | target_cell.unrender(); |
|
1067 | 1071 | target_cell.set_text(text); |
|
1068 | 1072 | // make this value the starting point, so that we can only undo |
|
1069 | 1073 | // to this state, instead of a blank cell |
|
1070 | 1074 | target_cell.code_mirror.clearHistory(); |
|
1071 | 1075 | source_cell.element.remove(); |
|
1072 | 1076 | this.select(i); |
|
1073 | 1077 | var cursor = source_cell.code_mirror.getCursor(); |
|
1074 | 1078 | target_cell.code_mirror.setCursor(cursor); |
|
1075 | 1079 | this.set_dirty(true); |
|
1076 | 1080 | } |
|
1077 | 1081 | } |
|
1078 | 1082 | }; |
|
1079 | 1083 | |
|
1080 | 1084 | /** |
|
1081 | 1085 | * Turn a cell into a heading cell. |
|
1082 | 1086 | * |
|
1083 | 1087 | * @method to_heading |
|
1084 | 1088 | * @param {Number} [index] A cell's index |
|
1085 | 1089 | * @param {Number} [level] A heading level (e.g., 1 becomes <h1>) |
|
1086 | 1090 | */ |
|
1087 | 1091 | Notebook.prototype.to_heading = function (index, level) { |
|
1088 | 1092 | level = level || 1; |
|
1089 | 1093 | var i = this.index_or_selected(index); |
|
1090 | 1094 | if (this.is_valid_cell_index(i)) { |
|
1091 | 1095 | var source_cell = this.get_cell(i); |
|
1092 | 1096 | var target_cell = null; |
|
1093 |
if (source_cell instanceof textcell. |
|
|
1094 | source_cell.set_level(level); | |
|
1097 | if (source_cell instanceof textcell.MarkdownCell) { | |
|
1098 | source_cell.set_heading_level(level); | |
|
1095 | 1099 | } else { |
|
1096 |
target_cell = this.insert_cell_below(' |
|
|
1100 | target_cell = this.insert_cell_below('markdown',i); | |
|
1097 | 1101 | var text = source_cell.get_text(); |
|
1098 | 1102 | if (text === source_cell.placeholder) { |
|
1099 | 1103 | text = ''; |
|
1100 | 1104 | } |
|
1101 | 1105 | //metadata |
|
1102 | 1106 | target_cell.metadata = source_cell.metadata; |
|
1103 | 1107 | // We must show the editor before setting its contents |
|
1104 | target_cell.set_level(level); | |
|
1105 | 1108 | target_cell.unrender(); |
|
1106 | 1109 | target_cell.set_text(text); |
|
1110 | target_cell.set_heading_level(level); | |
|
1107 | 1111 | // make this value the starting point, so that we can only undo |
|
1108 | 1112 | // to this state, instead of a blank cell |
|
1109 | 1113 | target_cell.code_mirror.clearHistory(); |
|
1110 | 1114 | source_cell.element.remove(); |
|
1111 | 1115 | this.select(i); |
|
1112 | 1116 | var cursor = source_cell.code_mirror.getCursor(); |
|
1113 | 1117 | target_cell.code_mirror.setCursor(cursor); |
|
1114 | 1118 | if ((source_cell instanceof textcell.TextCell) && source_cell.rendered) { |
|
1115 | 1119 | target_cell.render(); |
|
1116 | 1120 | } |
|
1117 | 1121 | } |
|
1118 | 1122 | this.set_dirty(true); |
|
1119 | 1123 | this.events.trigger('selected_cell_type_changed.Notebook', |
|
1120 |
{'cell_type':' |
|
|
1124 | {'cell_type':'markdown',level:level} | |
|
1121 | 1125 | ); |
|
1122 | 1126 | } |
|
1123 | 1127 | }; |
|
1124 | 1128 | |
|
1125 | 1129 | |
|
1126 | 1130 | // Cut/Copy/Paste |
|
1127 | 1131 | |
|
1128 | 1132 | /** |
|
1129 | 1133 | * Enable UI elements for pasting cells. |
|
1130 | 1134 | * |
|
1131 | 1135 | * @method enable_paste |
|
1132 | 1136 | */ |
|
1133 | 1137 | Notebook.prototype.enable_paste = function () { |
|
1134 | 1138 | var that = this; |
|
1135 | 1139 | if (!this.paste_enabled) { |
|
1136 | 1140 | $('#paste_cell_replace').removeClass('disabled') |
|
1137 | 1141 | .on('click', function () {that.paste_cell_replace();}); |
|
1138 | 1142 | $('#paste_cell_above').removeClass('disabled') |
|
1139 | 1143 | .on('click', function () {that.paste_cell_above();}); |
|
1140 | 1144 | $('#paste_cell_below').removeClass('disabled') |
|
1141 | 1145 | .on('click', function () {that.paste_cell_below();}); |
|
1142 | 1146 | this.paste_enabled = true; |
|
1143 | 1147 | } |
|
1144 | 1148 | }; |
|
1145 | 1149 | |
|
1146 | 1150 | /** |
|
1147 | 1151 | * Disable UI elements for pasting cells. |
|
1148 | 1152 | * |
|
1149 | 1153 | * @method disable_paste |
|
1150 | 1154 | */ |
|
1151 | 1155 | Notebook.prototype.disable_paste = function () { |
|
1152 | 1156 | if (this.paste_enabled) { |
|
1153 | 1157 | $('#paste_cell_replace').addClass('disabled').off('click'); |
|
1154 | 1158 | $('#paste_cell_above').addClass('disabled').off('click'); |
|
1155 | 1159 | $('#paste_cell_below').addClass('disabled').off('click'); |
|
1156 | 1160 | this.paste_enabled = false; |
|
1157 | 1161 | } |
|
1158 | 1162 | }; |
|
1159 | 1163 | |
|
1160 | 1164 | /** |
|
1161 | 1165 | * Cut a cell. |
|
1162 | 1166 | * |
|
1163 | 1167 | * @method cut_cell |
|
1164 | 1168 | */ |
|
1165 | 1169 | Notebook.prototype.cut_cell = function () { |
|
1166 | 1170 | this.copy_cell(); |
|
1167 | 1171 | this.delete_cell(); |
|
1168 | 1172 | }; |
|
1169 | 1173 | |
|
1170 | 1174 | /** |
|
1171 | 1175 | * Copy a cell. |
|
1172 | 1176 | * |
|
1173 | 1177 | * @method copy_cell |
|
1174 | 1178 | */ |
|
1175 | 1179 | Notebook.prototype.copy_cell = function () { |
|
1176 | 1180 | var cell = this.get_selected_cell(); |
|
1177 | 1181 | this.clipboard = cell.toJSON(); |
|
1178 | 1182 | // remove undeletable status from the copied cell |
|
1179 | 1183 | if (this.clipboard.metadata.deletable !== undefined) { |
|
1180 | 1184 | delete this.clipboard.metadata.deletable; |
|
1181 | 1185 | } |
|
1182 | 1186 | this.enable_paste(); |
|
1183 | 1187 | }; |
|
1184 | 1188 | |
|
1185 | 1189 | /** |
|
1186 | 1190 | * Replace the selected cell with a cell in the clipboard. |
|
1187 | 1191 | * |
|
1188 | 1192 | * @method paste_cell_replace |
|
1189 | 1193 | */ |
|
1190 | 1194 | Notebook.prototype.paste_cell_replace = function () { |
|
1191 | 1195 | if (this.clipboard !== null && this.paste_enabled) { |
|
1192 | 1196 | var cell_data = this.clipboard; |
|
1193 | 1197 | var new_cell = this.insert_cell_above(cell_data.cell_type); |
|
1194 | 1198 | new_cell.fromJSON(cell_data); |
|
1195 | 1199 | var old_cell = this.get_next_cell(new_cell); |
|
1196 | 1200 | this.delete_cell(this.find_cell_index(old_cell)); |
|
1197 | 1201 | this.select(this.find_cell_index(new_cell)); |
|
1198 | 1202 | } |
|
1199 | 1203 | }; |
|
1200 | 1204 | |
|
1201 | 1205 | /** |
|
1202 | 1206 | * Paste a cell from the clipboard above the selected cell. |
|
1203 | 1207 | * |
|
1204 | 1208 | * @method paste_cell_above |
|
1205 | 1209 | */ |
|
1206 | 1210 | Notebook.prototype.paste_cell_above = function () { |
|
1207 | 1211 | if (this.clipboard !== null && this.paste_enabled) { |
|
1208 | 1212 | var cell_data = this.clipboard; |
|
1209 | 1213 | var new_cell = this.insert_cell_above(cell_data.cell_type); |
|
1210 | 1214 | new_cell.fromJSON(cell_data); |
|
1211 | 1215 | new_cell.focus_cell(); |
|
1212 | 1216 | } |
|
1213 | 1217 | }; |
|
1214 | 1218 | |
|
1215 | 1219 | /** |
|
1216 | 1220 | * Paste a cell from the clipboard below the selected cell. |
|
1217 | 1221 | * |
|
1218 | 1222 | * @method paste_cell_below |
|
1219 | 1223 | */ |
|
1220 | 1224 | Notebook.prototype.paste_cell_below = function () { |
|
1221 | 1225 | if (this.clipboard !== null && this.paste_enabled) { |
|
1222 | 1226 | var cell_data = this.clipboard; |
|
1223 | 1227 | var new_cell = this.insert_cell_below(cell_data.cell_type); |
|
1224 | 1228 | new_cell.fromJSON(cell_data); |
|
1225 | 1229 | new_cell.focus_cell(); |
|
1226 | 1230 | } |
|
1227 | 1231 | }; |
|
1228 | 1232 | |
|
1229 | 1233 | // Split/merge |
|
1230 | 1234 | |
|
1231 | 1235 | /** |
|
1232 | 1236 | * Split the selected cell into two, at the cursor. |
|
1233 | 1237 | * |
|
1234 | 1238 | * @method split_cell |
|
1235 | 1239 | */ |
|
1236 | 1240 | Notebook.prototype.split_cell = function () { |
|
1237 | 1241 | var mdc = textcell.MarkdownCell; |
|
1238 | 1242 | var rc = textcell.RawCell; |
|
1239 | 1243 | var cell = this.get_selected_cell(); |
|
1240 | 1244 | if (cell.is_splittable()) { |
|
1241 | 1245 | var texta = cell.get_pre_cursor(); |
|
1242 | 1246 | var textb = cell.get_post_cursor(); |
|
1243 | 1247 | cell.set_text(textb); |
|
1244 | 1248 | var new_cell = this.insert_cell_above(cell.cell_type); |
|
1245 | 1249 | // Unrender the new cell so we can call set_text. |
|
1246 | 1250 | new_cell.unrender(); |
|
1247 | 1251 | new_cell.set_text(texta); |
|
1248 | 1252 | } |
|
1249 | 1253 | }; |
|
1250 | 1254 | |
|
1251 | 1255 | /** |
|
1252 | 1256 | * Combine the selected cell into the cell above it. |
|
1253 | 1257 | * |
|
1254 | 1258 | * @method merge_cell_above |
|
1255 | 1259 | */ |
|
1256 | 1260 | Notebook.prototype.merge_cell_above = function () { |
|
1257 | 1261 | var mdc = textcell.MarkdownCell; |
|
1258 | 1262 | var rc = textcell.RawCell; |
|
1259 | 1263 | var index = this.get_selected_index(); |
|
1260 | 1264 | var cell = this.get_cell(index); |
|
1261 | 1265 | var render = cell.rendered; |
|
1262 | 1266 | if (!cell.is_mergeable()) { |
|
1263 | 1267 | return; |
|
1264 | 1268 | } |
|
1265 | 1269 | if (index > 0) { |
|
1266 | 1270 | var upper_cell = this.get_cell(index-1); |
|
1267 | 1271 | if (!upper_cell.is_mergeable()) { |
|
1268 | 1272 | return; |
|
1269 | 1273 | } |
|
1270 | 1274 | var upper_text = upper_cell.get_text(); |
|
1271 | 1275 | var text = cell.get_text(); |
|
1272 | 1276 | if (cell instanceof codecell.CodeCell) { |
|
1273 | 1277 | cell.set_text(upper_text+'\n'+text); |
|
1274 | 1278 | } else { |
|
1275 | 1279 | cell.unrender(); // Must unrender before we set_text. |
|
1276 | 1280 | cell.set_text(upper_text+'\n\n'+text); |
|
1277 | 1281 | if (render) { |
|
1278 | 1282 | // The rendered state of the final cell should match |
|
1279 | 1283 | // that of the original selected cell; |
|
1280 | 1284 | cell.render(); |
|
1281 | 1285 | } |
|
1282 | 1286 | } |
|
1283 | 1287 | this.delete_cell(index-1); |
|
1284 | 1288 | this.select(this.find_cell_index(cell)); |
|
1285 | 1289 | } |
|
1286 | 1290 | }; |
|
1287 | 1291 | |
|
1288 | 1292 | /** |
|
1289 | 1293 | * Combine the selected cell into the cell below it. |
|
1290 | 1294 | * |
|
1291 | 1295 | * @method merge_cell_below |
|
1292 | 1296 | */ |
|
1293 | 1297 | Notebook.prototype.merge_cell_below = function () { |
|
1294 | 1298 | var mdc = textcell.MarkdownCell; |
|
1295 | 1299 | var rc = textcell.RawCell; |
|
1296 | 1300 | var index = this.get_selected_index(); |
|
1297 | 1301 | var cell = this.get_cell(index); |
|
1298 | 1302 | var render = cell.rendered; |
|
1299 | 1303 | if (!cell.is_mergeable()) { |
|
1300 | 1304 | return; |
|
1301 | 1305 | } |
|
1302 | 1306 | if (index < this.ncells()-1) { |
|
1303 | 1307 | var lower_cell = this.get_cell(index+1); |
|
1304 | 1308 | if (!lower_cell.is_mergeable()) { |
|
1305 | 1309 | return; |
|
1306 | 1310 | } |
|
1307 | 1311 | var lower_text = lower_cell.get_text(); |
|
1308 | 1312 | var text = cell.get_text(); |
|
1309 | 1313 | if (cell instanceof codecell.CodeCell) { |
|
1310 | 1314 | cell.set_text(text+'\n'+lower_text); |
|
1311 | 1315 | } else { |
|
1312 | 1316 | cell.unrender(); // Must unrender before we set_text. |
|
1313 | 1317 | cell.set_text(text+'\n\n'+lower_text); |
|
1314 | 1318 | if (render) { |
|
1315 | 1319 | // The rendered state of the final cell should match |
|
1316 | 1320 | // that of the original selected cell; |
|
1317 | 1321 | cell.render(); |
|
1318 | 1322 | } |
|
1319 | 1323 | } |
|
1320 | 1324 | this.delete_cell(index+1); |
|
1321 | 1325 | this.select(this.find_cell_index(cell)); |
|
1322 | 1326 | } |
|
1323 | 1327 | }; |
|
1324 | 1328 | |
|
1325 | 1329 | |
|
1326 | 1330 | // Cell collapsing and output clearing |
|
1327 | 1331 | |
|
1328 | 1332 | /** |
|
1329 | 1333 | * Hide a cell's output. |
|
1330 | 1334 | * |
|
1331 | 1335 | * @method collapse_output |
|
1332 | 1336 | * @param {Number} index A cell's numeric index |
|
1333 | 1337 | */ |
|
1334 | 1338 | Notebook.prototype.collapse_output = function (index) { |
|
1335 | 1339 | var i = this.index_or_selected(index); |
|
1336 | 1340 | var cell = this.get_cell(i); |
|
1337 | 1341 | if (cell !== null && (cell instanceof codecell.CodeCell)) { |
|
1338 | 1342 | cell.collapse_output(); |
|
1339 | 1343 | this.set_dirty(true); |
|
1340 | 1344 | } |
|
1341 | 1345 | }; |
|
1342 | 1346 | |
|
1343 | 1347 | /** |
|
1344 | 1348 | * Hide each code cell's output area. |
|
1345 | 1349 | * |
|
1346 | 1350 | * @method collapse_all_output |
|
1347 | 1351 | */ |
|
1348 | 1352 | Notebook.prototype.collapse_all_output = function () { |
|
1349 | 1353 | $.map(this.get_cells(), function (cell, i) { |
|
1350 | 1354 | if (cell instanceof codecell.CodeCell) { |
|
1351 | 1355 | cell.collapse_output(); |
|
1352 | 1356 | } |
|
1353 | 1357 | }); |
|
1354 | 1358 | // this should not be set if the `collapse` key is removed from nbformat |
|
1355 | 1359 | this.set_dirty(true); |
|
1356 | 1360 | }; |
|
1357 | 1361 | |
|
1358 | 1362 | /** |
|
1359 | 1363 | * Show a cell's output. |
|
1360 | 1364 | * |
|
1361 | 1365 | * @method expand_output |
|
1362 | 1366 | * @param {Number} index A cell's numeric index |
|
1363 | 1367 | */ |
|
1364 | 1368 | Notebook.prototype.expand_output = function (index) { |
|
1365 | 1369 | var i = this.index_or_selected(index); |
|
1366 | 1370 | var cell = this.get_cell(i); |
|
1367 | 1371 | if (cell !== null && (cell instanceof codecell.CodeCell)) { |
|
1368 | 1372 | cell.expand_output(); |
|
1369 | 1373 | this.set_dirty(true); |
|
1370 | 1374 | } |
|
1371 | 1375 | }; |
|
1372 | 1376 | |
|
1373 | 1377 | /** |
|
1374 | 1378 | * Expand each code cell's output area, and remove scrollbars. |
|
1375 | 1379 | * |
|
1376 | 1380 | * @method expand_all_output |
|
1377 | 1381 | */ |
|
1378 | 1382 | Notebook.prototype.expand_all_output = function () { |
|
1379 | 1383 | $.map(this.get_cells(), function (cell, i) { |
|
1380 | 1384 | if (cell instanceof codecell.CodeCell) { |
|
1381 | 1385 | cell.expand_output(); |
|
1382 | 1386 | } |
|
1383 | 1387 | }); |
|
1384 | 1388 | // this should not be set if the `collapse` key is removed from nbformat |
|
1385 | 1389 | this.set_dirty(true); |
|
1386 | 1390 | }; |
|
1387 | 1391 | |
|
1388 | 1392 | /** |
|
1389 | 1393 | * Clear the selected CodeCell's output area. |
|
1390 | 1394 | * |
|
1391 | 1395 | * @method clear_output |
|
1392 | 1396 | * @param {Number} index A cell's numeric index |
|
1393 | 1397 | */ |
|
1394 | 1398 | Notebook.prototype.clear_output = function (index) { |
|
1395 | 1399 | var i = this.index_or_selected(index); |
|
1396 | 1400 | var cell = this.get_cell(i); |
|
1397 | 1401 | if (cell !== null && (cell instanceof codecell.CodeCell)) { |
|
1398 | 1402 | cell.clear_output(); |
|
1399 | 1403 | this.set_dirty(true); |
|
1400 | 1404 | } |
|
1401 | 1405 | }; |
|
1402 | 1406 | |
|
1403 | 1407 | /** |
|
1404 | 1408 | * Clear each code cell's output area. |
|
1405 | 1409 | * |
|
1406 | 1410 | * @method clear_all_output |
|
1407 | 1411 | */ |
|
1408 | 1412 | Notebook.prototype.clear_all_output = function () { |
|
1409 | 1413 | $.map(this.get_cells(), function (cell, i) { |
|
1410 | 1414 | if (cell instanceof codecell.CodeCell) { |
|
1411 | 1415 | cell.clear_output(); |
|
1412 | 1416 | } |
|
1413 | 1417 | }); |
|
1414 | 1418 | this.set_dirty(true); |
|
1415 | 1419 | }; |
|
1416 | 1420 | |
|
1417 | 1421 | /** |
|
1418 | 1422 | * Scroll the selected CodeCell's output area. |
|
1419 | 1423 | * |
|
1420 | 1424 | * @method scroll_output |
|
1421 | 1425 | * @param {Number} index A cell's numeric index |
|
1422 | 1426 | */ |
|
1423 | 1427 | Notebook.prototype.scroll_output = function (index) { |
|
1424 | 1428 | var i = this.index_or_selected(index); |
|
1425 | 1429 | var cell = this.get_cell(i); |
|
1426 | 1430 | if (cell !== null && (cell instanceof codecell.CodeCell)) { |
|
1427 | 1431 | cell.scroll_output(); |
|
1428 | 1432 | this.set_dirty(true); |
|
1429 | 1433 | } |
|
1430 | 1434 | }; |
|
1431 | 1435 | |
|
1432 | 1436 | /** |
|
1433 | 1437 | * Expand each code cell's output area, and add a scrollbar for long output. |
|
1434 | 1438 | * |
|
1435 | 1439 | * @method scroll_all_output |
|
1436 | 1440 | */ |
|
1437 | 1441 | Notebook.prototype.scroll_all_output = function () { |
|
1438 | 1442 | $.map(this.get_cells(), function (cell, i) { |
|
1439 | 1443 | if (cell instanceof codecell.CodeCell) { |
|
1440 | 1444 | cell.scroll_output(); |
|
1441 | 1445 | } |
|
1442 | 1446 | }); |
|
1443 | 1447 | // this should not be set if the `collapse` key is removed from nbformat |
|
1444 | 1448 | this.set_dirty(true); |
|
1445 | 1449 | }; |
|
1446 | 1450 | |
|
1447 | 1451 | /** Toggle whether a cell's output is collapsed or expanded. |
|
1448 | 1452 | * |
|
1449 | 1453 | * @method toggle_output |
|
1450 | 1454 | * @param {Number} index A cell's numeric index |
|
1451 | 1455 | */ |
|
1452 | 1456 | Notebook.prototype.toggle_output = function (index) { |
|
1453 | 1457 | var i = this.index_or_selected(index); |
|
1454 | 1458 | var cell = this.get_cell(i); |
|
1455 | 1459 | if (cell !== null && (cell instanceof codecell.CodeCell)) { |
|
1456 | 1460 | cell.toggle_output(); |
|
1457 | 1461 | this.set_dirty(true); |
|
1458 | 1462 | } |
|
1459 | 1463 | }; |
|
1460 | 1464 | |
|
1461 | 1465 | /** |
|
1462 | 1466 | * Hide/show the output of all cells. |
|
1463 | 1467 | * |
|
1464 | 1468 | * @method toggle_all_output |
|
1465 | 1469 | */ |
|
1466 | 1470 | Notebook.prototype.toggle_all_output = function () { |
|
1467 | 1471 | $.map(this.get_cells(), function (cell, i) { |
|
1468 | 1472 | if (cell instanceof codecell.CodeCell) { |
|
1469 | 1473 | cell.toggle_output(); |
|
1470 | 1474 | } |
|
1471 | 1475 | }); |
|
1472 | 1476 | // this should not be set if the `collapse` key is removed from nbformat |
|
1473 | 1477 | this.set_dirty(true); |
|
1474 | 1478 | }; |
|
1475 | 1479 | |
|
1476 | 1480 | /** |
|
1477 | 1481 | * Toggle a scrollbar for long cell outputs. |
|
1478 | 1482 | * |
|
1479 | 1483 | * @method toggle_output_scroll |
|
1480 | 1484 | * @param {Number} index A cell's numeric index |
|
1481 | 1485 | */ |
|
1482 | 1486 | Notebook.prototype.toggle_output_scroll = function (index) { |
|
1483 | 1487 | var i = this.index_or_selected(index); |
|
1484 | 1488 | var cell = this.get_cell(i); |
|
1485 | 1489 | if (cell !== null && (cell instanceof codecell.CodeCell)) { |
|
1486 | 1490 | cell.toggle_output_scroll(); |
|
1487 | 1491 | this.set_dirty(true); |
|
1488 | 1492 | } |
|
1489 | 1493 | }; |
|
1490 | 1494 | |
|
1491 | 1495 | /** |
|
1492 | 1496 | * Toggle the scrolling of long output on all cells. |
|
1493 | 1497 | * |
|
1494 | 1498 | * @method toggle_all_output_scrolling |
|
1495 | 1499 | */ |
|
1496 | 1500 | Notebook.prototype.toggle_all_output_scroll = function () { |
|
1497 | 1501 | $.map(this.get_cells(), function (cell, i) { |
|
1498 | 1502 | if (cell instanceof codecell.CodeCell) { |
|
1499 | 1503 | cell.toggle_output_scroll(); |
|
1500 | 1504 | } |
|
1501 | 1505 | }); |
|
1502 | 1506 | // this should not be set if the `collapse` key is removed from nbformat |
|
1503 | 1507 | this.set_dirty(true); |
|
1504 | 1508 | }; |
|
1505 | 1509 | |
|
1506 | 1510 | // Other cell functions: line numbers, ... |
|
1507 | 1511 | |
|
1508 | 1512 | /** |
|
1509 | 1513 | * Toggle line numbers in the selected cell's input area. |
|
1510 | 1514 | * |
|
1511 | 1515 | * @method cell_toggle_line_numbers |
|
1512 | 1516 | */ |
|
1513 | 1517 | Notebook.prototype.cell_toggle_line_numbers = function() { |
|
1514 | 1518 | this.get_selected_cell().toggle_line_numbers(); |
|
1515 | 1519 | }; |
|
1516 | 1520 | |
|
1517 | 1521 | /** |
|
1518 | 1522 | * Set the codemirror mode for all code cells, including the default for |
|
1519 | 1523 | * new code cells. |
|
1520 | 1524 | * |
|
1521 | 1525 | * @method set_codemirror_mode |
|
1522 | 1526 | */ |
|
1523 | 1527 | Notebook.prototype.set_codemirror_mode = function(newmode){ |
|
1524 | 1528 | if (newmode === this.codemirror_mode) { |
|
1525 | 1529 | return; |
|
1526 | 1530 | } |
|
1527 | 1531 | this.codemirror_mode = newmode; |
|
1528 | 1532 | codecell.CodeCell.options_default.cm_config.mode = newmode; |
|
1529 | modename = newmode.mode || newmode.name || newmode | |
|
1530 | ||
|
1533 | modename = newmode.mode || newmode.name || newmode; | |
|
1534 | ||
|
1531 | 1535 | that = this; |
|
1532 | 1536 | utils.requireCodeMirrorMode(modename, function () { |
|
1533 | 1537 | $.map(that.get_cells(), function(cell, i) { |
|
1534 | 1538 | if (cell.cell_type === 'code'){ |
|
1535 | 1539 | cell.code_mirror.setOption('mode', newmode); |
|
1536 | 1540 | // This is currently redundant, because cm_config ends up as |
|
1537 | 1541 | // codemirror's own .options object, but I don't want to |
|
1538 | 1542 | // rely on that. |
|
1539 | 1543 | cell.cm_config.mode = newmode; |
|
1540 | 1544 | } |
|
1541 | 1545 | }); |
|
1542 | }) | |
|
1546 | }); | |
|
1543 | 1547 | }; |
|
1544 | 1548 | |
|
1545 | 1549 | // Session related things |
|
1546 | 1550 | |
|
1547 | 1551 | /** |
|
1548 | 1552 | * Start a new session and set it on each code cell. |
|
1549 | 1553 | * |
|
1550 | 1554 | * @method start_session |
|
1551 | 1555 | */ |
|
1552 | 1556 | Notebook.prototype.start_session = function (kernel_name) { |
|
1553 | 1557 | var that = this; |
|
1554 | 1558 | if (this._session_starting) { |
|
1555 | 1559 | throw new session.SessionAlreadyStarting(); |
|
1556 | 1560 | } |
|
1557 | 1561 | this._session_starting = true; |
|
1558 | 1562 | |
|
1559 | 1563 | var options = { |
|
1560 | 1564 | base_url: this.base_url, |
|
1561 | 1565 | ws_url: this.ws_url, |
|
1562 | 1566 | notebook_path: this.notebook_path, |
|
1563 | 1567 | notebook_name: this.notebook_name, |
|
1564 | 1568 | kernel_name: kernel_name, |
|
1565 | 1569 | notebook: this |
|
1566 | 1570 | }; |
|
1567 | 1571 | |
|
1568 | 1572 | var success = $.proxy(this._session_started, this); |
|
1569 | 1573 | var failure = $.proxy(this._session_start_failed, this); |
|
1570 | 1574 | |
|
1571 | 1575 | if (this.session !== null) { |
|
1572 | 1576 | this.session.restart(options, success, failure); |
|
1573 | 1577 | } else { |
|
1574 | 1578 | this.session = new session.Session(options); |
|
1575 | 1579 | this.session.start(success, failure); |
|
1576 | 1580 | } |
|
1577 | 1581 | }; |
|
1578 | 1582 | |
|
1579 | 1583 | |
|
1580 | 1584 | /** |
|
1581 | 1585 | * Once a session is started, link the code cells to the kernel and pass the |
|
1582 | 1586 | * comm manager to the widget manager |
|
1583 | 1587 | * |
|
1584 | 1588 | */ |
|
1585 | 1589 | Notebook.prototype._session_started = function (){ |
|
1586 | 1590 | this._session_starting = false; |
|
1587 | 1591 | this.kernel = this.session.kernel; |
|
1588 | 1592 | var ncells = this.ncells(); |
|
1589 | 1593 | for (var i=0; i<ncells; i++) { |
|
1590 | 1594 | var cell = this.get_cell(i); |
|
1591 | 1595 | if (cell instanceof codecell.CodeCell) { |
|
1592 | 1596 | cell.set_kernel(this.session.kernel); |
|
1593 | 1597 | } |
|
1594 | 1598 | } |
|
1595 | 1599 | }; |
|
1596 | 1600 | Notebook.prototype._session_start_failed = function (jqxhr, status, error){ |
|
1597 | 1601 | this._session_starting = false; |
|
1598 | 1602 | utils.log_ajax_error(jqxhr, status, error); |
|
1599 | 1603 | }; |
|
1600 | 1604 | |
|
1601 | 1605 | /** |
|
1602 | 1606 | * Prompt the user to restart the IPython kernel. |
|
1603 | 1607 | * |
|
1604 | 1608 | * @method restart_kernel |
|
1605 | 1609 | */ |
|
1606 | 1610 | Notebook.prototype.restart_kernel = function () { |
|
1607 | 1611 | var that = this; |
|
1608 | 1612 | dialog.modal({ |
|
1609 | 1613 | notebook: this, |
|
1610 | 1614 | keyboard_manager: this.keyboard_manager, |
|
1611 | 1615 | title : "Restart kernel or continue running?", |
|
1612 | 1616 | body : $("<p/>").text( |
|
1613 | 1617 | 'Do you want to restart the current kernel? You will lose all variables defined in it.' |
|
1614 | 1618 | ), |
|
1615 | 1619 | buttons : { |
|
1616 | 1620 | "Continue running" : {}, |
|
1617 | 1621 | "Restart" : { |
|
1618 | 1622 | "class" : "btn-danger", |
|
1619 | 1623 | "click" : function() { |
|
1620 | 1624 | that.kernel.restart(); |
|
1621 | 1625 | } |
|
1622 | 1626 | } |
|
1623 | 1627 | } |
|
1624 | 1628 | }); |
|
1625 | 1629 | }; |
|
1626 | 1630 | |
|
1627 | 1631 | /** |
|
1628 | 1632 | * Execute or render cell outputs and go into command mode. |
|
1629 | 1633 | * |
|
1630 | 1634 | * @method execute_cell |
|
1631 | 1635 | */ |
|
1632 | 1636 | Notebook.prototype.execute_cell = function () { |
|
1633 | 1637 | // mode = shift, ctrl, alt |
|
1634 | 1638 | var cell = this.get_selected_cell(); |
|
1635 | 1639 | var cell_index = this.find_cell_index(cell); |
|
1636 | 1640 | |
|
1637 | 1641 | cell.execute(); |
|
1638 | 1642 | this.command_mode(); |
|
1639 | 1643 | this.set_dirty(true); |
|
1640 | 1644 | }; |
|
1641 | 1645 | |
|
1642 | 1646 | /** |
|
1643 | 1647 | * Execute or render cell outputs and insert a new cell below. |
|
1644 | 1648 | * |
|
1645 | 1649 | * @method execute_cell_and_insert_below |
|
1646 | 1650 | */ |
|
1647 | 1651 | Notebook.prototype.execute_cell_and_insert_below = function () { |
|
1648 | 1652 | var cell = this.get_selected_cell(); |
|
1649 | 1653 | var cell_index = this.find_cell_index(cell); |
|
1650 | 1654 | |
|
1651 | 1655 | cell.execute(); |
|
1652 | 1656 | |
|
1653 | 1657 | // If we are at the end always insert a new cell and return |
|
1654 | 1658 | if (cell_index === (this.ncells()-1)) { |
|
1655 | 1659 | this.command_mode(); |
|
1656 | 1660 | this.insert_cell_below(); |
|
1657 | 1661 | this.select(cell_index+1); |
|
1658 | 1662 | this.edit_mode(); |
|
1659 | 1663 | this.scroll_to_bottom(); |
|
1660 | 1664 | this.set_dirty(true); |
|
1661 | 1665 | return; |
|
1662 | 1666 | } |
|
1663 | 1667 | |
|
1664 | 1668 | this.command_mode(); |
|
1665 | 1669 | this.insert_cell_below(); |
|
1666 | 1670 | this.select(cell_index+1); |
|
1667 | 1671 | this.edit_mode(); |
|
1668 | 1672 | this.set_dirty(true); |
|
1669 | 1673 | }; |
|
1670 | 1674 | |
|
1671 | 1675 | /** |
|
1672 | 1676 | * Execute or render cell outputs and select the next cell. |
|
1673 | 1677 | * |
|
1674 | 1678 | * @method execute_cell_and_select_below |
|
1675 | 1679 | */ |
|
1676 | 1680 | Notebook.prototype.execute_cell_and_select_below = function () { |
|
1677 | 1681 | |
|
1678 | 1682 | var cell = this.get_selected_cell(); |
|
1679 | 1683 | var cell_index = this.find_cell_index(cell); |
|
1680 | 1684 | |
|
1681 | 1685 | cell.execute(); |
|
1682 | 1686 | |
|
1683 | 1687 | // If we are at the end always insert a new cell and return |
|
1684 | 1688 | if (cell_index === (this.ncells()-1)) { |
|
1685 | 1689 | this.command_mode(); |
|
1686 | 1690 | this.insert_cell_below(); |
|
1687 | 1691 | this.select(cell_index+1); |
|
1688 | 1692 | this.edit_mode(); |
|
1689 | 1693 | this.scroll_to_bottom(); |
|
1690 | 1694 | this.set_dirty(true); |
|
1691 | 1695 | return; |
|
1692 | 1696 | } |
|
1693 | 1697 | |
|
1694 | 1698 | this.command_mode(); |
|
1695 | 1699 | this.select(cell_index+1); |
|
1696 | 1700 | this.focus_cell(); |
|
1697 | 1701 | this.set_dirty(true); |
|
1698 | 1702 | }; |
|
1699 | 1703 | |
|
1700 | 1704 | /** |
|
1701 | 1705 | * Execute all cells below the selected cell. |
|
1702 | 1706 | * |
|
1703 | 1707 | * @method execute_cells_below |
|
1704 | 1708 | */ |
|
1705 | 1709 | Notebook.prototype.execute_cells_below = function () { |
|
1706 | 1710 | this.execute_cell_range(this.get_selected_index(), this.ncells()); |
|
1707 | 1711 | this.scroll_to_bottom(); |
|
1708 | 1712 | }; |
|
1709 | 1713 | |
|
1710 | 1714 | /** |
|
1711 | 1715 | * Execute all cells above the selected cell. |
|
1712 | 1716 | * |
|
1713 | 1717 | * @method execute_cells_above |
|
1714 | 1718 | */ |
|
1715 | 1719 | Notebook.prototype.execute_cells_above = function () { |
|
1716 | 1720 | this.execute_cell_range(0, this.get_selected_index()); |
|
1717 | 1721 | }; |
|
1718 | 1722 | |
|
1719 | 1723 | /** |
|
1720 | 1724 | * Execute all cells. |
|
1721 | 1725 | * |
|
1722 | 1726 | * @method execute_all_cells |
|
1723 | 1727 | */ |
|
1724 | 1728 | Notebook.prototype.execute_all_cells = function () { |
|
1725 | 1729 | this.execute_cell_range(0, this.ncells()); |
|
1726 | 1730 | this.scroll_to_bottom(); |
|
1727 | 1731 | }; |
|
1728 | 1732 | |
|
1729 | 1733 | /** |
|
1730 | 1734 | * Execute a contiguous range of cells. |
|
1731 | 1735 | * |
|
1732 | 1736 | * @method execute_cell_range |
|
1733 | 1737 | * @param {Number} start Index of the first cell to execute (inclusive) |
|
1734 | 1738 | * @param {Number} end Index of the last cell to execute (exclusive) |
|
1735 | 1739 | */ |
|
1736 | 1740 | Notebook.prototype.execute_cell_range = function (start, end) { |
|
1737 | 1741 | this.command_mode(); |
|
1738 | 1742 | for (var i=start; i<end; i++) { |
|
1739 | 1743 | this.select(i); |
|
1740 | 1744 | this.execute_cell(); |
|
1741 | 1745 | } |
|
1742 | 1746 | }; |
|
1743 | 1747 | |
|
1744 | 1748 | // Persistance and loading |
|
1745 | 1749 | |
|
1746 | 1750 | /** |
|
1747 | 1751 | * Getter method for this notebook's name. |
|
1748 | 1752 | * |
|
1749 | 1753 | * @method get_notebook_name |
|
1750 | 1754 | * @return {String} This notebook's name (excluding file extension) |
|
1751 | 1755 | */ |
|
1752 | 1756 | Notebook.prototype.get_notebook_name = function () { |
|
1753 | 1757 | var nbname = this.notebook_name.substring(0,this.notebook_name.length-6); |
|
1754 | 1758 | return nbname; |
|
1755 | 1759 | }; |
|
1756 | 1760 | |
|
1757 | 1761 | /** |
|
1758 | 1762 | * Setter method for this notebook's name. |
|
1759 | 1763 | * |
|
1760 | 1764 | * @method set_notebook_name |
|
1761 | 1765 | * @param {String} name A new name for this notebook |
|
1762 | 1766 | */ |
|
1763 | 1767 | Notebook.prototype.set_notebook_name = function (name) { |
|
1764 | 1768 | this.notebook_name = name; |
|
1765 | 1769 | }; |
|
1766 | 1770 | |
|
1767 | 1771 | /** |
|
1768 | 1772 | * Check that a notebook's name is valid. |
|
1769 | 1773 | * |
|
1770 | 1774 | * @method test_notebook_name |
|
1771 | 1775 | * @param {String} nbname A name for this notebook |
|
1772 | 1776 | * @return {Boolean} True if the name is valid, false if invalid |
|
1773 | 1777 | */ |
|
1774 | 1778 | Notebook.prototype.test_notebook_name = function (nbname) { |
|
1775 | 1779 | nbname = nbname || ''; |
|
1776 | 1780 | if (nbname.length>0 && !this.notebook_name_blacklist_re.test(nbname)) { |
|
1777 | 1781 | return true; |
|
1778 | 1782 | } else { |
|
1779 | 1783 | return false; |
|
1780 | 1784 | } |
|
1781 | 1785 | }; |
|
1782 | 1786 | |
|
1783 | 1787 | /** |
|
1784 | 1788 | * Load a notebook from JSON (.ipynb). |
|
1785 | 1789 | * |
|
1786 | 1790 | * @method fromJSON |
|
1787 | 1791 | * @param {Object} data JSON representation of a notebook |
|
1788 | 1792 | */ |
|
1789 | 1793 | Notebook.prototype.fromJSON = function (data) { |
|
1790 | 1794 | |
|
1791 | 1795 | var content = data.content; |
|
1792 | 1796 | var ncells = this.ncells(); |
|
1793 | 1797 | var i; |
|
1794 | 1798 | for (i=0; i<ncells; i++) { |
|
1795 | 1799 | // Always delete cell 0 as they get renumbered as they are deleted. |
|
1796 | 1800 | this.delete_cell(0); |
|
1797 | 1801 | } |
|
1798 | 1802 | // Save the metadata and name. |
|
1799 | 1803 | this.metadata = content.metadata; |
|
1800 | 1804 | this.notebook_name = data.name; |
|
1801 | 1805 | var trusted = true; |
|
1802 | 1806 | |
|
1803 | 1807 | // Trigger an event changing the kernel spec - this will set the default |
|
1804 | 1808 | // codemirror mode |
|
1805 | 1809 | if (this.metadata.kernelspec !== undefined) { |
|
1806 | 1810 | this.events.trigger('spec_changed.Kernel', this.metadata.kernelspec); |
|
1807 | 1811 | } |
|
1808 | 1812 | |
|
1809 | 1813 | // Set the codemirror mode from language_info metadata |
|
1810 | 1814 | if (this.metadata.language_info !== undefined) { |
|
1811 | 1815 | var langinfo = this.metadata.language_info; |
|
1812 | 1816 | // Mode 'null' should be plain, unhighlighted text. |
|
1813 | 1817 | var cm_mode = langinfo.codemirror_mode || langinfo.language || 'null' |
|
1814 | 1818 | this.set_codemirror_mode(cm_mode); |
|
1815 | 1819 | } |
|
1816 | 1820 | |
|
1817 | 1821 | var new_cells = content.cells; |
|
1818 | 1822 | ncells = new_cells.length; |
|
1819 | 1823 | var cell_data = null; |
|
1820 | 1824 | var new_cell = null; |
|
1821 | 1825 | for (i=0; i<ncells; i++) { |
|
1822 | 1826 | cell_data = new_cells[i]; |
|
1823 | 1827 | new_cell = this.insert_cell_at_index(cell_data.cell_type, i); |
|
1824 | 1828 | new_cell.fromJSON(cell_data); |
|
1825 | 1829 | if (new_cell.cell_type == 'code' && !new_cell.output_area.trusted) { |
|
1826 | 1830 | trusted = false; |
|
1827 | 1831 | } |
|
1828 | 1832 | } |
|
1829 | 1833 | if (trusted !== this.trusted) { |
|
1830 | 1834 | this.trusted = trusted; |
|
1831 | 1835 | this.events.trigger("trust_changed.Notebook", trusted); |
|
1832 | 1836 | } |
|
1833 | 1837 | }; |
|
1834 | 1838 | |
|
1835 | 1839 | /** |
|
1836 | 1840 | * Dump this notebook into a JSON-friendly object. |
|
1837 | 1841 | * |
|
1838 | 1842 | * @method toJSON |
|
1839 | 1843 | * @return {Object} A JSON-friendly representation of this notebook. |
|
1840 | 1844 | */ |
|
1841 | 1845 | Notebook.prototype.toJSON = function () { |
|
1842 | 1846 | // remove the conversion indicator, which only belongs in-memory |
|
1843 | 1847 | delete this.metadata.orig_nbformat; |
|
1844 | 1848 | delete this.metadata.orig_nbformat_minor; |
|
1845 | 1849 | |
|
1846 | 1850 | var cells = this.get_cells(); |
|
1847 | 1851 | var ncells = cells.length; |
|
1848 | 1852 | var cell_array = new Array(ncells); |
|
1849 | 1853 | var trusted = true; |
|
1850 | 1854 | for (var i=0; i<ncells; i++) { |
|
1851 | 1855 | var cell = cells[i]; |
|
1852 | 1856 | if (cell.cell_type == 'code' && !cell.output_area.trusted) { |
|
1853 | 1857 | trusted = false; |
|
1854 | 1858 | } |
|
1855 | 1859 | cell_array[i] = cell.toJSON(); |
|
1856 | 1860 | } |
|
1857 | 1861 | var data = { |
|
1858 | 1862 | cells: cell_array, |
|
1859 | 1863 | metadata : this.metadata |
|
1860 | 1864 | }; |
|
1861 | 1865 | if (trusted != this.trusted) { |
|
1862 | 1866 | this.trusted = trusted; |
|
1863 | 1867 | this.events.trigger("trust_changed.Notebook", trusted); |
|
1864 | 1868 | } |
|
1865 | 1869 | return data; |
|
1866 | 1870 | }; |
|
1867 | 1871 | |
|
1868 | 1872 | /** |
|
1869 | 1873 | * Start an autosave timer, for periodically saving the notebook. |
|
1870 | 1874 | * |
|
1871 | 1875 | * @method set_autosave_interval |
|
1872 | 1876 | * @param {Integer} interval the autosave interval in milliseconds |
|
1873 | 1877 | */ |
|
1874 | 1878 | Notebook.prototype.set_autosave_interval = function (interval) { |
|
1875 | 1879 | var that = this; |
|
1876 | 1880 | // clear previous interval, so we don't get simultaneous timers |
|
1877 | 1881 | if (this.autosave_timer) { |
|
1878 | 1882 | clearInterval(this.autosave_timer); |
|
1879 | 1883 | } |
|
1880 | 1884 | |
|
1881 | 1885 | this.autosave_interval = this.minimum_autosave_interval = interval; |
|
1882 | 1886 | if (interval) { |
|
1883 | 1887 | this.autosave_timer = setInterval(function() { |
|
1884 | 1888 | if (that.dirty) { |
|
1885 | 1889 | that.save_notebook(); |
|
1886 | 1890 | } |
|
1887 | 1891 | }, interval); |
|
1888 | 1892 | this.events.trigger("autosave_enabled.Notebook", interval); |
|
1889 | 1893 | } else { |
|
1890 | 1894 | this.autosave_timer = null; |
|
1891 | 1895 | this.events.trigger("autosave_disabled.Notebook"); |
|
1892 | 1896 | } |
|
1893 | 1897 | }; |
|
1894 | 1898 | |
|
1895 | 1899 | /** |
|
1896 | 1900 | * Save this notebook on the server. This becomes a notebook instance's |
|
1897 | 1901 | * .save_notebook method *after* the entire notebook has been loaded. |
|
1898 | 1902 | * |
|
1899 | 1903 | * @method save_notebook |
|
1900 | 1904 | */ |
|
1901 | 1905 | Notebook.prototype.save_notebook = function (extra_settings) { |
|
1902 | 1906 | // Create a JSON model to be sent to the server. |
|
1903 | 1907 | var model = {}; |
|
1904 | 1908 | model.name = this.notebook_name; |
|
1905 | 1909 | model.path = this.notebook_path; |
|
1906 | 1910 | model.type = 'notebook'; |
|
1907 | 1911 | model.format = 'json'; |
|
1908 | 1912 | model.content = this.toJSON(); |
|
1909 | 1913 | model.content.nbformat = this.nbformat; |
|
1910 | 1914 | model.content.nbformat_minor = this.nbformat_minor; |
|
1911 | 1915 | // time the ajax call for autosave tuning purposes. |
|
1912 | 1916 | var start = new Date().getTime(); |
|
1913 | 1917 | // We do the call with settings so we can set cache to false. |
|
1914 | 1918 | var settings = { |
|
1915 | 1919 | processData : false, |
|
1916 | 1920 | cache : false, |
|
1917 | 1921 | type : "PUT", |
|
1918 | 1922 | data : JSON.stringify(model), |
|
1919 | 1923 | contentType: 'application/json', |
|
1920 | 1924 | dataType : "json", |
|
1921 | 1925 | success : $.proxy(this.save_notebook_success, this, start), |
|
1922 | 1926 | error : $.proxy(this.save_notebook_error, this) |
|
1923 | 1927 | }; |
|
1924 | 1928 | if (extra_settings) { |
|
1925 | 1929 | for (var key in extra_settings) { |
|
1926 | 1930 | settings[key] = extra_settings[key]; |
|
1927 | 1931 | } |
|
1928 | 1932 | } |
|
1929 | 1933 | this.events.trigger('notebook_saving.Notebook'); |
|
1930 | 1934 | var url = utils.url_join_encode( |
|
1931 | 1935 | this.base_url, |
|
1932 | 1936 | 'api/contents', |
|
1933 | 1937 | this.notebook_path, |
|
1934 | 1938 | this.notebook_name |
|
1935 | 1939 | ); |
|
1936 | 1940 | $.ajax(url, settings); |
|
1937 | 1941 | }; |
|
1938 | 1942 | |
|
1939 | 1943 | /** |
|
1940 | 1944 | * Success callback for saving a notebook. |
|
1941 | 1945 | * |
|
1942 | 1946 | * @method save_notebook_success |
|
1943 | 1947 | * @param {Integer} start the time when the save request started |
|
1944 | 1948 | * @param {Object} data JSON representation of a notebook |
|
1945 | 1949 | * @param {String} status Description of response status |
|
1946 | 1950 | * @param {jqXHR} xhr jQuery Ajax object |
|
1947 | 1951 | */ |
|
1948 | 1952 | Notebook.prototype.save_notebook_success = function (start, data, status, xhr) { |
|
1949 | 1953 | this.set_dirty(false); |
|
1950 | 1954 | if (data.message) { |
|
1951 | 1955 | // save succeeded, but validation failed. |
|
1952 | 1956 | var body = $("<div>"); |
|
1953 | 1957 | var title = "Notebook validation failed"; |
|
1954 | 1958 | |
|
1955 | 1959 | body.append($("<p>").text( |
|
1956 | 1960 | "The save operation succeeded," + |
|
1957 | 1961 | " but the notebook does not appear to be valid." + |
|
1958 | 1962 | " The validation error was:" |
|
1959 | 1963 | )).append($("<div>").addClass("validation-error").append( |
|
1960 | 1964 | $("<pre>").text(data.message) |
|
1961 | 1965 | )); |
|
1962 | 1966 | dialog.modal({ |
|
1963 | 1967 | notebook: this, |
|
1964 | 1968 | keyboard_manager: this.keyboard_manager, |
|
1965 | 1969 | title: title, |
|
1966 | 1970 | body: body, |
|
1967 | 1971 | buttons : { |
|
1968 | 1972 | OK : { |
|
1969 | 1973 | "class" : "btn-primary" |
|
1970 | 1974 | } |
|
1971 | 1975 | } |
|
1972 | 1976 | }); |
|
1973 | 1977 | } |
|
1974 | 1978 | this.events.trigger('notebook_saved.Notebook'); |
|
1975 | 1979 | this._update_autosave_interval(start); |
|
1976 | 1980 | if (this._checkpoint_after_save) { |
|
1977 | 1981 | this.create_checkpoint(); |
|
1978 | 1982 | this._checkpoint_after_save = false; |
|
1979 | 1983 | } |
|
1980 | 1984 | }; |
|
1981 | 1985 | |
|
1982 | 1986 | /** |
|
1983 | 1987 | * update the autosave interval based on how long the last save took |
|
1984 | 1988 | * |
|
1985 | 1989 | * @method _update_autosave_interval |
|
1986 | 1990 | * @param {Integer} timestamp when the save request started |
|
1987 | 1991 | */ |
|
1988 | 1992 | Notebook.prototype._update_autosave_interval = function (start) { |
|
1989 | 1993 | var duration = (new Date().getTime() - start); |
|
1990 | 1994 | if (this.autosave_interval) { |
|
1991 | 1995 | // new save interval: higher of 10x save duration or parameter (default 30 seconds) |
|
1992 | 1996 | var interval = Math.max(10 * duration, this.minimum_autosave_interval); |
|
1993 | 1997 | // round to 10 seconds, otherwise we will be setting a new interval too often |
|
1994 | 1998 | interval = 10000 * Math.round(interval / 10000); |
|
1995 | 1999 | // set new interval, if it's changed |
|
1996 | 2000 | if (interval != this.autosave_interval) { |
|
1997 | 2001 | this.set_autosave_interval(interval); |
|
1998 | 2002 | } |
|
1999 | 2003 | } |
|
2000 | 2004 | }; |
|
2001 | 2005 | |
|
2002 | 2006 | /** |
|
2003 | 2007 | * Failure callback for saving a notebook. |
|
2004 | 2008 | * |
|
2005 | 2009 | * @method save_notebook_error |
|
2006 | 2010 | * @param {jqXHR} xhr jQuery Ajax object |
|
2007 | 2011 | * @param {String} status Description of response status |
|
2008 | 2012 | * @param {String} error HTTP error message |
|
2009 | 2013 | */ |
|
2010 | 2014 | Notebook.prototype.save_notebook_error = function (xhr, status, error) { |
|
2011 | 2015 | this.events.trigger('notebook_save_failed.Notebook', [xhr, status, error]); |
|
2012 | 2016 | }; |
|
2013 | 2017 | |
|
2014 | 2018 | /** |
|
2015 | 2019 | * Explicitly trust the output of this notebook. |
|
2016 | 2020 | * |
|
2017 | 2021 | * @method trust_notebook |
|
2018 | 2022 | */ |
|
2019 | 2023 | Notebook.prototype.trust_notebook = function (extra_settings) { |
|
2020 | 2024 | var body = $("<div>").append($("<p>") |
|
2021 | 2025 | .text("A trusted IPython notebook may execute hidden malicious code ") |
|
2022 | 2026 | .append($("<strong>") |
|
2023 | 2027 | .append( |
|
2024 | 2028 | $("<em>").text("when you open it") |
|
2025 | 2029 | ) |
|
2026 | 2030 | ).append(".").append( |
|
2027 | 2031 | " Selecting trust will immediately reload this notebook in a trusted state." |
|
2028 | 2032 | ).append( |
|
2029 | 2033 | " For more information, see the " |
|
2030 | 2034 | ).append($("<a>").attr("href", "http://ipython.org/ipython-doc/2/notebook/security.html") |
|
2031 | 2035 | .text("IPython security documentation") |
|
2032 | 2036 | ).append(".") |
|
2033 | 2037 | ); |
|
2034 | 2038 | |
|
2035 | 2039 | var nb = this; |
|
2036 | 2040 | dialog.modal({ |
|
2037 | 2041 | notebook: this, |
|
2038 | 2042 | keyboard_manager: this.keyboard_manager, |
|
2039 | 2043 | title: "Trust this notebook?", |
|
2040 | 2044 | body: body, |
|
2041 | 2045 | |
|
2042 | 2046 | buttons: { |
|
2043 | 2047 | Cancel : {}, |
|
2044 | 2048 | Trust : { |
|
2045 | 2049 | class : "btn-danger", |
|
2046 | 2050 | click : function () { |
|
2047 | 2051 | var cells = nb.get_cells(); |
|
2048 | 2052 | for (var i = 0; i < cells.length; i++) { |
|
2049 | 2053 | var cell = cells[i]; |
|
2050 | 2054 | if (cell.cell_type == 'code') { |
|
2051 | 2055 | cell.output_area.trusted = true; |
|
2052 | 2056 | } |
|
2053 | 2057 | } |
|
2054 | 2058 | nb.events.on('notebook_saved.Notebook', function () { |
|
2055 | 2059 | window.location.reload(); |
|
2056 | 2060 | }); |
|
2057 | 2061 | nb.save_notebook(); |
|
2058 | 2062 | } |
|
2059 | 2063 | } |
|
2060 | 2064 | } |
|
2061 | 2065 | }); |
|
2062 | 2066 | }; |
|
2063 | 2067 | |
|
2064 | 2068 | Notebook.prototype.new_notebook = function(){ |
|
2065 | 2069 | var path = this.notebook_path; |
|
2066 | 2070 | var base_url = this.base_url; |
|
2067 | 2071 | var settings = { |
|
2068 | 2072 | processData : false, |
|
2069 | 2073 | cache : false, |
|
2070 | 2074 | type : "POST", |
|
2071 | 2075 | dataType : "json", |
|
2072 | 2076 | async : false, |
|
2073 | 2077 | success : function (data, status, xhr){ |
|
2074 | 2078 | var notebook_name = data.name; |
|
2075 | 2079 | window.open( |
|
2076 | 2080 | utils.url_join_encode( |
|
2077 | 2081 | base_url, |
|
2078 | 2082 | 'notebooks', |
|
2079 | 2083 | path, |
|
2080 | 2084 | notebook_name |
|
2081 | 2085 | ), |
|
2082 | 2086 | '_blank' |
|
2083 | 2087 | ); |
|
2084 | 2088 | }, |
|
2085 | 2089 | error : utils.log_ajax_error, |
|
2086 | 2090 | }; |
|
2087 | 2091 | var url = utils.url_join_encode( |
|
2088 | 2092 | base_url, |
|
2089 | 2093 | 'api/contents', |
|
2090 | 2094 | path |
|
2091 | 2095 | ); |
|
2092 | 2096 | $.ajax(url,settings); |
|
2093 | 2097 | }; |
|
2094 | 2098 | |
|
2095 | 2099 | |
|
2096 | 2100 | Notebook.prototype.copy_notebook = function(){ |
|
2097 | 2101 | var path = this.notebook_path; |
|
2098 | 2102 | var base_url = this.base_url; |
|
2099 | 2103 | var settings = { |
|
2100 | 2104 | processData : false, |
|
2101 | 2105 | cache : false, |
|
2102 | 2106 | type : "POST", |
|
2103 | 2107 | dataType : "json", |
|
2104 | 2108 | data : JSON.stringify({copy_from : this.notebook_name}), |
|
2105 | 2109 | async : false, |
|
2106 | 2110 | success : function (data, status, xhr) { |
|
2107 | 2111 | window.open(utils.url_join_encode( |
|
2108 | 2112 | base_url, |
|
2109 | 2113 | 'notebooks', |
|
2110 | 2114 | data.path, |
|
2111 | 2115 | data.name |
|
2112 | 2116 | ), '_blank'); |
|
2113 | 2117 | }, |
|
2114 | 2118 | error : utils.log_ajax_error, |
|
2115 | 2119 | }; |
|
2116 | 2120 | var url = utils.url_join_encode( |
|
2117 | 2121 | base_url, |
|
2118 | 2122 | 'api/contents', |
|
2119 | 2123 | path |
|
2120 | 2124 | ); |
|
2121 | 2125 | $.ajax(url,settings); |
|
2122 | 2126 | }; |
|
2123 | 2127 | |
|
2124 | 2128 | Notebook.prototype.rename = function (nbname) { |
|
2125 | 2129 | var that = this; |
|
2126 | 2130 | if (!nbname.match(/\.ipynb$/)) { |
|
2127 | 2131 | nbname = nbname + ".ipynb"; |
|
2128 | 2132 | } |
|
2129 | 2133 | var data = {name: nbname}; |
|
2130 | 2134 | var settings = { |
|
2131 | 2135 | processData : false, |
|
2132 | 2136 | cache : false, |
|
2133 | 2137 | type : "PATCH", |
|
2134 | 2138 | data : JSON.stringify(data), |
|
2135 | 2139 | dataType: "json", |
|
2136 | 2140 | contentType: 'application/json', |
|
2137 | 2141 | success : $.proxy(that.rename_success, this), |
|
2138 | 2142 | error : $.proxy(that.rename_error, this) |
|
2139 | 2143 | }; |
|
2140 | 2144 | this.events.trigger('rename_notebook.Notebook', data); |
|
2141 | 2145 | var url = utils.url_join_encode( |
|
2142 | 2146 | this.base_url, |
|
2143 | 2147 | 'api/contents', |
|
2144 | 2148 | this.notebook_path, |
|
2145 | 2149 | this.notebook_name |
|
2146 | 2150 | ); |
|
2147 | 2151 | $.ajax(url, settings); |
|
2148 | 2152 | }; |
|
2149 | 2153 | |
|
2150 | 2154 | Notebook.prototype.delete = function () { |
|
2151 | 2155 | var that = this; |
|
2152 | 2156 | var settings = { |
|
2153 | 2157 | processData : false, |
|
2154 | 2158 | cache : false, |
|
2155 | 2159 | type : "DELETE", |
|
2156 | 2160 | dataType: "json", |
|
2157 | 2161 | error : utils.log_ajax_error, |
|
2158 | 2162 | }; |
|
2159 | 2163 | var url = utils.url_join_encode( |
|
2160 | 2164 | this.base_url, |
|
2161 | 2165 | 'api/contents', |
|
2162 | 2166 | this.notebook_path, |
|
2163 | 2167 | this.notebook_name |
|
2164 | 2168 | ); |
|
2165 | 2169 | $.ajax(url, settings); |
|
2166 | 2170 | }; |
|
2167 | 2171 | |
|
2168 | 2172 | |
|
2169 | 2173 | Notebook.prototype.rename_success = function (json, status, xhr) { |
|
2170 | 2174 | var name = this.notebook_name = json.name; |
|
2171 | 2175 | var path = json.path; |
|
2172 | 2176 | this.session.rename_notebook(name, path); |
|
2173 | 2177 | this.events.trigger('notebook_renamed.Notebook', json); |
|
2174 | 2178 | }; |
|
2175 | 2179 | |
|
2176 | 2180 | Notebook.prototype.rename_error = function (xhr, status, error) { |
|
2177 | 2181 | var that = this; |
|
2178 | 2182 | var dialog_body = $('<div/>').append( |
|
2179 | 2183 | $("<p/>").text('This notebook name already exists.') |
|
2180 | 2184 | ); |
|
2181 | 2185 | this.events.trigger('notebook_rename_failed.Notebook', [xhr, status, error]); |
|
2182 | 2186 | dialog.modal({ |
|
2183 | 2187 | notebook: this, |
|
2184 | 2188 | keyboard_manager: this.keyboard_manager, |
|
2185 | 2189 | title: "Notebook Rename Error!", |
|
2186 | 2190 | body: dialog_body, |
|
2187 | 2191 | buttons : { |
|
2188 | 2192 | "Cancel": {}, |
|
2189 | 2193 | "OK": { |
|
2190 | 2194 | class: "btn-primary", |
|
2191 | 2195 | click: function () { |
|
2192 | 2196 | this.save_widget.rename_notebook({notebook:that}); |
|
2193 | 2197 | }} |
|
2194 | 2198 | }, |
|
2195 | 2199 | open : function (event, ui) { |
|
2196 | 2200 | var that = $(this); |
|
2197 | 2201 | // Upon ENTER, click the OK button. |
|
2198 | 2202 | that.find('input[type="text"]').keydown(function (event, ui) { |
|
2199 | 2203 | if (event.which === this.keyboard.keycodes.enter) { |
|
2200 | 2204 | that.find('.btn-primary').first().click(); |
|
2201 | 2205 | } |
|
2202 | 2206 | }); |
|
2203 | 2207 | that.find('input[type="text"]').focus(); |
|
2204 | 2208 | } |
|
2205 | 2209 | }); |
|
2206 | 2210 | }; |
|
2207 | 2211 | |
|
2208 | 2212 | /** |
|
2209 | 2213 | * Request a notebook's data from the server. |
|
2210 | 2214 | * |
|
2211 | 2215 | * @method load_notebook |
|
2212 | 2216 | * @param {String} notebook_name and path A notebook to load |
|
2213 | 2217 | */ |
|
2214 | 2218 | Notebook.prototype.load_notebook = function (notebook_name, notebook_path) { |
|
2215 | 2219 | var that = this; |
|
2216 | 2220 | this.notebook_name = notebook_name; |
|
2217 | 2221 | this.notebook_path = notebook_path; |
|
2218 | 2222 | // We do the call with settings so we can set cache to false. |
|
2219 | 2223 | var settings = { |
|
2220 | 2224 | processData : false, |
|
2221 | 2225 | cache : false, |
|
2222 | 2226 | type : "GET", |
|
2223 | 2227 | dataType : "json", |
|
2224 | 2228 | success : $.proxy(this.load_notebook_success,this), |
|
2225 | 2229 | error : $.proxy(this.load_notebook_error,this), |
|
2226 | 2230 | }; |
|
2227 | 2231 | this.events.trigger('notebook_loading.Notebook'); |
|
2228 | 2232 | var url = utils.url_join_encode( |
|
2229 | 2233 | this.base_url, |
|
2230 | 2234 | 'api/contents', |
|
2231 | 2235 | this.notebook_path, |
|
2232 | 2236 | this.notebook_name |
|
2233 | 2237 | ); |
|
2234 | 2238 | $.ajax(url, settings); |
|
2235 | 2239 | }; |
|
2236 | 2240 | |
|
2237 | 2241 | /** |
|
2238 | 2242 | * Success callback for loading a notebook from the server. |
|
2239 | 2243 | * |
|
2240 | 2244 | * Load notebook data from the JSON response. |
|
2241 | 2245 | * |
|
2242 | 2246 | * @method load_notebook_success |
|
2243 | 2247 | * @param {Object} data JSON representation of a notebook |
|
2244 | 2248 | * @param {String} status Description of response status |
|
2245 | 2249 | * @param {jqXHR} xhr jQuery Ajax object |
|
2246 | 2250 | */ |
|
2247 | 2251 | Notebook.prototype.load_notebook_success = function (data, status, xhr) { |
|
2248 | 2252 | var failed; |
|
2249 | 2253 | try { |
|
2250 | 2254 | this.fromJSON(data); |
|
2251 | 2255 | } catch (e) { |
|
2252 | 2256 | failed = e; |
|
2253 | 2257 | console.log("Notebook failed to load from JSON:", e); |
|
2254 | 2258 | } |
|
2255 | 2259 | if (failed || data.message) { |
|
2256 | 2260 | // *either* fromJSON failed or validation failed |
|
2257 | 2261 | var body = $("<div>"); |
|
2258 | 2262 | var title; |
|
2259 | 2263 | if (failed) { |
|
2260 | 2264 | title = "Notebook failed to load"; |
|
2261 | 2265 | body.append($("<p>").text( |
|
2262 | 2266 | "The error was: " |
|
2263 | 2267 | )).append($("<div>").addClass("js-error").text( |
|
2264 | 2268 | failed.toString() |
|
2265 | 2269 | )).append($("<p>").text( |
|
2266 | 2270 | "See the error console for details." |
|
2267 | 2271 | )); |
|
2268 | 2272 | } else { |
|
2269 | 2273 | title = "Notebook validation failed"; |
|
2270 | 2274 | } |
|
2271 | 2275 | |
|
2272 | 2276 | if (data.message) { |
|
2273 | 2277 | var msg; |
|
2274 | 2278 | if (failed) { |
|
2275 | 2279 | msg = "The notebook also failed validation:" |
|
2276 | 2280 | } else { |
|
2277 | 2281 | msg = "An invalid notebook may not function properly." + |
|
2278 | 2282 | " The validation error was:" |
|
2279 | 2283 | } |
|
2280 | 2284 | body.append($("<p>").text( |
|
2281 | 2285 | msg |
|
2282 | 2286 | )).append($("<div>").addClass("validation-error").append( |
|
2283 | 2287 | $("<pre>").text(data.message) |
|
2284 | 2288 | )); |
|
2285 | 2289 | } |
|
2286 | 2290 | |
|
2287 | 2291 | dialog.modal({ |
|
2288 | 2292 | notebook: this, |
|
2289 | 2293 | keyboard_manager: this.keyboard_manager, |
|
2290 | 2294 | title: title, |
|
2291 | 2295 | body: body, |
|
2292 | 2296 | buttons : { |
|
2293 | 2297 | OK : { |
|
2294 | 2298 | "class" : "btn-primary" |
|
2295 | 2299 | } |
|
2296 | 2300 | } |
|
2297 | 2301 | }); |
|
2298 | 2302 | } |
|
2299 | 2303 | if (this.ncells() === 0) { |
|
2300 | 2304 | this.insert_cell_below('code'); |
|
2301 | 2305 | this.edit_mode(0); |
|
2302 | 2306 | } else { |
|
2303 | 2307 | this.select(0); |
|
2304 | 2308 | this.handle_command_mode(this.get_cell(0)); |
|
2305 | 2309 | } |
|
2306 | 2310 | this.set_dirty(false); |
|
2307 | 2311 | this.scroll_to_top(); |
|
2308 | 2312 | var nbmodel = data.content; |
|
2309 | 2313 | var orig_nbformat = nbmodel.metadata.orig_nbformat; |
|
2310 | 2314 | var orig_nbformat_minor = nbmodel.metadata.orig_nbformat_minor; |
|
2311 | 2315 | if (orig_nbformat !== undefined && nbmodel.nbformat !== orig_nbformat) { |
|
2312 | 2316 | var msg = "This notebook has been converted from an older " + |
|
2313 | 2317 | "notebook format (v"+orig_nbformat+") to the current notebook " + |
|
2314 | 2318 | "format (v"+nbmodel.nbformat+"). The next time you save this notebook, the " + |
|
2315 | 2319 | "newer notebook format will be used and older versions of IPython " + |
|
2316 | 2320 | "may not be able to read it. To keep the older version, close the " + |
|
2317 | 2321 | "notebook without saving it."; |
|
2318 | 2322 | dialog.modal({ |
|
2319 | 2323 | notebook: this, |
|
2320 | 2324 | keyboard_manager: this.keyboard_manager, |
|
2321 | 2325 | title : "Notebook converted", |
|
2322 | 2326 | body : msg, |
|
2323 | 2327 | buttons : { |
|
2324 | 2328 | OK : { |
|
2325 | 2329 | class : "btn-primary" |
|
2326 | 2330 | } |
|
2327 | 2331 | } |
|
2328 | 2332 | }); |
|
2329 | 2333 | } else if (orig_nbformat_minor !== undefined && nbmodel.nbformat_minor !== orig_nbformat_minor) { |
|
2330 | 2334 | var that = this; |
|
2331 | 2335 | var orig_vs = 'v' + nbmodel.nbformat + '.' + orig_nbformat_minor; |
|
2332 | 2336 | var this_vs = 'v' + nbmodel.nbformat + '.' + this.nbformat_minor; |
|
2333 | 2337 | var msg = "This notebook is version " + orig_vs + ", but we only fully support up to " + |
|
2334 | 2338 | this_vs + ". You can still work with this notebook, but some features " + |
|
2335 | 2339 | "introduced in later notebook versions may not be available."; |
|
2336 | 2340 | |
|
2337 | 2341 | dialog.modal({ |
|
2338 | 2342 | notebook: this, |
|
2339 | 2343 | keyboard_manager: this.keyboard_manager, |
|
2340 | 2344 | title : "Newer Notebook", |
|
2341 | 2345 | body : msg, |
|
2342 | 2346 | buttons : { |
|
2343 | 2347 | OK : { |
|
2344 | 2348 | class : "btn-danger" |
|
2345 | 2349 | } |
|
2346 | 2350 | } |
|
2347 | 2351 | }); |
|
2348 | 2352 | |
|
2349 | 2353 | } |
|
2350 | 2354 | |
|
2351 | 2355 | // Create the session after the notebook is completely loaded to prevent |
|
2352 | 2356 | // code execution upon loading, which is a security risk. |
|
2353 | 2357 | if (this.session === null) { |
|
2354 | 2358 | var kernelspec = this.metadata.kernelspec || {}; |
|
2355 | 2359 | var kernel_name = kernelspec.name; |
|
2356 | 2360 | |
|
2357 | 2361 | this.start_session(kernel_name); |
|
2358 | 2362 | } |
|
2359 | 2363 | // load our checkpoint list |
|
2360 | 2364 | this.list_checkpoints(); |
|
2361 | 2365 | |
|
2362 | 2366 | // load toolbar state |
|
2363 | 2367 | if (this.metadata.celltoolbar) { |
|
2364 | 2368 | celltoolbar.CellToolbar.global_show(); |
|
2365 | 2369 | celltoolbar.CellToolbar.activate_preset(this.metadata.celltoolbar); |
|
2366 | 2370 | } else { |
|
2367 | 2371 | celltoolbar.CellToolbar.global_hide(); |
|
2368 | 2372 | } |
|
2369 | 2373 | |
|
2370 | 2374 | // now that we're fully loaded, it is safe to restore save functionality |
|
2371 | 2375 | delete(this.save_notebook); |
|
2372 | 2376 | this.events.trigger('notebook_loaded.Notebook'); |
|
2373 | 2377 | }; |
|
2374 | 2378 | |
|
2375 | 2379 | /** |
|
2376 | 2380 | * Failure callback for loading a notebook from the server. |
|
2377 | 2381 | * |
|
2378 | 2382 | * @method load_notebook_error |
|
2379 | 2383 | * @param {jqXHR} xhr jQuery Ajax object |
|
2380 | 2384 | * @param {String} status Description of response status |
|
2381 | 2385 | * @param {String} error HTTP error message |
|
2382 | 2386 | */ |
|
2383 | 2387 | Notebook.prototype.load_notebook_error = function (xhr, status, error) { |
|
2384 | 2388 | this.events.trigger('notebook_load_failed.Notebook', [xhr, status, error]); |
|
2385 | 2389 | utils.log_ajax_error(xhr, status, error); |
|
2386 | var msg; | |
|
2390 | var msg = $("<div>"); | |
|
2387 | 2391 | if (xhr.status === 400) { |
|
2388 |
msg |
|
|
2392 | msg.text(utils.ajax_error_msg(xhr)); | |
|
2389 | 2393 | } else if (xhr.status === 500) { |
|
2390 |
msg |
|
|
2394 | msg.text("An unknown error occurred while loading this notebook. " + | |
|
2391 | 2395 | "This version can load notebook formats " + |
|
2392 | "v" + this.nbformat + " or earlier. See the server log for details."; | |
|
2396 | "v" + this.nbformat + " or earlier. See the server log for details."); | |
|
2393 | 2397 | } |
|
2394 | 2398 | dialog.modal({ |
|
2395 | 2399 | notebook: this, |
|
2396 | 2400 | keyboard_manager: this.keyboard_manager, |
|
2397 | 2401 | title: "Error loading notebook", |
|
2398 | 2402 | body : msg, |
|
2399 | 2403 | buttons : { |
|
2400 | 2404 | "OK": {} |
|
2401 | 2405 | } |
|
2402 | 2406 | }); |
|
2403 | 2407 | }; |
|
2404 | 2408 | |
|
2405 | 2409 | /********************* checkpoint-related *********************/ |
|
2406 | 2410 | |
|
2407 | 2411 | /** |
|
2408 | 2412 | * Save the notebook then immediately create a checkpoint. |
|
2409 | 2413 | * |
|
2410 | 2414 | * @method save_checkpoint |
|
2411 | 2415 | */ |
|
2412 | 2416 | Notebook.prototype.save_checkpoint = function () { |
|
2413 | 2417 | this._checkpoint_after_save = true; |
|
2414 | 2418 | this.save_notebook(); |
|
2415 | 2419 | }; |
|
2416 | 2420 | |
|
2417 | 2421 | /** |
|
2418 | 2422 | * Add a checkpoint for this notebook. |
|
2419 | 2423 | * for use as a callback from checkpoint creation. |
|
2420 | 2424 | * |
|
2421 | 2425 | * @method add_checkpoint |
|
2422 | 2426 | */ |
|
2423 | 2427 | Notebook.prototype.add_checkpoint = function (checkpoint) { |
|
2424 | 2428 | var found = false; |
|
2425 | 2429 | for (var i = 0; i < this.checkpoints.length; i++) { |
|
2426 | 2430 | var existing = this.checkpoints[i]; |
|
2427 | 2431 | if (existing.id == checkpoint.id) { |
|
2428 | 2432 | found = true; |
|
2429 | 2433 | this.checkpoints[i] = checkpoint; |
|
2430 | 2434 | break; |
|
2431 | 2435 | } |
|
2432 | 2436 | } |
|
2433 | 2437 | if (!found) { |
|
2434 | 2438 | this.checkpoints.push(checkpoint); |
|
2435 | 2439 | } |
|
2436 | 2440 | this.last_checkpoint = this.checkpoints[this.checkpoints.length - 1]; |
|
2437 | 2441 | }; |
|
2438 | 2442 | |
|
2439 | 2443 | /** |
|
2440 | 2444 | * List checkpoints for this notebook. |
|
2441 | 2445 | * |
|
2442 | 2446 | * @method list_checkpoints |
|
2443 | 2447 | */ |
|
2444 | 2448 | Notebook.prototype.list_checkpoints = function () { |
|
2445 | 2449 | var url = utils.url_join_encode( |
|
2446 | 2450 | this.base_url, |
|
2447 | 2451 | 'api/contents', |
|
2448 | 2452 | this.notebook_path, |
|
2449 | 2453 | this.notebook_name, |
|
2450 | 2454 | 'checkpoints' |
|
2451 | 2455 | ); |
|
2452 | 2456 | $.get(url).done( |
|
2453 | 2457 | $.proxy(this.list_checkpoints_success, this) |
|
2454 | 2458 | ).fail( |
|
2455 | 2459 | $.proxy(this.list_checkpoints_error, this) |
|
2456 | 2460 | ); |
|
2457 | 2461 | }; |
|
2458 | 2462 | |
|
2459 | 2463 | /** |
|
2460 | 2464 | * Success callback for listing checkpoints. |
|
2461 | 2465 | * |
|
2462 | 2466 | * @method list_checkpoint_success |
|
2463 | 2467 | * @param {Object} data JSON representation of a checkpoint |
|
2464 | 2468 | * @param {String} status Description of response status |
|
2465 | 2469 | * @param {jqXHR} xhr jQuery Ajax object |
|
2466 | 2470 | */ |
|
2467 | 2471 | Notebook.prototype.list_checkpoints_success = function (data, status, xhr) { |
|
2468 | 2472 | data = $.parseJSON(data); |
|
2469 | 2473 | this.checkpoints = data; |
|
2470 | 2474 | if (data.length) { |
|
2471 | 2475 | this.last_checkpoint = data[data.length - 1]; |
|
2472 | 2476 | } else { |
|
2473 | 2477 | this.last_checkpoint = null; |
|
2474 | 2478 | } |
|
2475 | 2479 | this.events.trigger('checkpoints_listed.Notebook', [data]); |
|
2476 | 2480 | }; |
|
2477 | 2481 | |
|
2478 | 2482 | /** |
|
2479 | 2483 | * Failure callback for listing a checkpoint. |
|
2480 | 2484 | * |
|
2481 | 2485 | * @method list_checkpoint_error |
|
2482 | 2486 | * @param {jqXHR} xhr jQuery Ajax object |
|
2483 | 2487 | * @param {String} status Description of response status |
|
2484 | 2488 | * @param {String} error_msg HTTP error message |
|
2485 | 2489 | */ |
|
2486 | 2490 | Notebook.prototype.list_checkpoints_error = function (xhr, status, error_msg) { |
|
2487 | 2491 | this.events.trigger('list_checkpoints_failed.Notebook'); |
|
2488 | 2492 | }; |
|
2489 | 2493 | |
|
2490 | 2494 | /** |
|
2491 | 2495 | * Create a checkpoint of this notebook on the server from the most recent save. |
|
2492 | 2496 | * |
|
2493 | 2497 | * @method create_checkpoint |
|
2494 | 2498 | */ |
|
2495 | 2499 | Notebook.prototype.create_checkpoint = function () { |
|
2496 | 2500 | var url = utils.url_join_encode( |
|
2497 | 2501 | this.base_url, |
|
2498 | 2502 | 'api/contents', |
|
2499 | 2503 | this.notebook_path, |
|
2500 | 2504 | this.notebook_name, |
|
2501 | 2505 | 'checkpoints' |
|
2502 | 2506 | ); |
|
2503 | 2507 | $.post(url).done( |
|
2504 | 2508 | $.proxy(this.create_checkpoint_success, this) |
|
2505 | 2509 | ).fail( |
|
2506 | 2510 | $.proxy(this.create_checkpoint_error, this) |
|
2507 | 2511 | ); |
|
2508 | 2512 | }; |
|
2509 | 2513 | |
|
2510 | 2514 | /** |
|
2511 | 2515 | * Success callback for creating a checkpoint. |
|
2512 | 2516 | * |
|
2513 | 2517 | * @method create_checkpoint_success |
|
2514 | 2518 | * @param {Object} data JSON representation of a checkpoint |
|
2515 | 2519 | * @param {String} status Description of response status |
|
2516 | 2520 | * @param {jqXHR} xhr jQuery Ajax object |
|
2517 | 2521 | */ |
|
2518 | 2522 | Notebook.prototype.create_checkpoint_success = function (data, status, xhr) { |
|
2519 | 2523 | data = $.parseJSON(data); |
|
2520 | 2524 | this.add_checkpoint(data); |
|
2521 | 2525 | this.events.trigger('checkpoint_created.Notebook', data); |
|
2522 | 2526 | }; |
|
2523 | 2527 | |
|
2524 | 2528 | /** |
|
2525 | 2529 | * Failure callback for creating a checkpoint. |
|
2526 | 2530 | * |
|
2527 | 2531 | * @method create_checkpoint_error |
|
2528 | 2532 | * @param {jqXHR} xhr jQuery Ajax object |
|
2529 | 2533 | * @param {String} status Description of response status |
|
2530 | 2534 | * @param {String} error_msg HTTP error message |
|
2531 | 2535 | */ |
|
2532 | 2536 | Notebook.prototype.create_checkpoint_error = function (xhr, status, error_msg) { |
|
2533 | 2537 | this.events.trigger('checkpoint_failed.Notebook'); |
|
2534 | 2538 | }; |
|
2535 | 2539 | |
|
2536 | 2540 | Notebook.prototype.restore_checkpoint_dialog = function (checkpoint) { |
|
2537 | 2541 | var that = this; |
|
2538 | 2542 | checkpoint = checkpoint || this.last_checkpoint; |
|
2539 | 2543 | if ( ! checkpoint ) { |
|
2540 | 2544 | console.log("restore dialog, but no checkpoint to restore to!"); |
|
2541 | 2545 | return; |
|
2542 | 2546 | } |
|
2543 | 2547 | var body = $('<div/>').append( |
|
2544 | 2548 | $('<p/>').addClass("p-space").text( |
|
2545 | 2549 | "Are you sure you want to revert the notebook to " + |
|
2546 | 2550 | "the latest checkpoint?" |
|
2547 | 2551 | ).append( |
|
2548 | 2552 | $("<strong/>").text( |
|
2549 | 2553 | " This cannot be undone." |
|
2550 | 2554 | ) |
|
2551 | 2555 | ) |
|
2552 | 2556 | ).append( |
|
2553 | 2557 | $('<p/>').addClass("p-space").text("The checkpoint was last updated at:") |
|
2554 | 2558 | ).append( |
|
2555 | 2559 | $('<p/>').addClass("p-space").text( |
|
2556 | 2560 | Date(checkpoint.last_modified) |
|
2557 | 2561 | ).css("text-align", "center") |
|
2558 | 2562 | ); |
|
2559 | 2563 | |
|
2560 | 2564 | dialog.modal({ |
|
2561 | 2565 | notebook: this, |
|
2562 | 2566 | keyboard_manager: this.keyboard_manager, |
|
2563 | 2567 | title : "Revert notebook to checkpoint", |
|
2564 | 2568 | body : body, |
|
2565 | 2569 | buttons : { |
|
2566 | 2570 | Revert : { |
|
2567 | 2571 | class : "btn-danger", |
|
2568 | 2572 | click : function () { |
|
2569 | 2573 | that.restore_checkpoint(checkpoint.id); |
|
2570 | 2574 | } |
|
2571 | 2575 | }, |
|
2572 | 2576 | Cancel : {} |
|
2573 | 2577 | } |
|
2574 | 2578 | }); |
|
2575 | 2579 | }; |
|
2576 | 2580 | |
|
2577 | 2581 | /** |
|
2578 | 2582 | * Restore the notebook to a checkpoint state. |
|
2579 | 2583 | * |
|
2580 | 2584 | * @method restore_checkpoint |
|
2581 | 2585 | * @param {String} checkpoint ID |
|
2582 | 2586 | */ |
|
2583 | 2587 | Notebook.prototype.restore_checkpoint = function (checkpoint) { |
|
2584 | 2588 | this.events.trigger('notebook_restoring.Notebook', checkpoint); |
|
2585 | 2589 | var url = utils.url_join_encode( |
|
2586 | 2590 | this.base_url, |
|
2587 | 2591 | 'api/contents', |
|
2588 | 2592 | this.notebook_path, |
|
2589 | 2593 | this.notebook_name, |
|
2590 | 2594 | 'checkpoints', |
|
2591 | 2595 | checkpoint |
|
2592 | 2596 | ); |
|
2593 | 2597 | $.post(url).done( |
|
2594 | 2598 | $.proxy(this.restore_checkpoint_success, this) |
|
2595 | 2599 | ).fail( |
|
2596 | 2600 | $.proxy(this.restore_checkpoint_error, this) |
|
2597 | 2601 | ); |
|
2598 | 2602 | }; |
|
2599 | 2603 | |
|
2600 | 2604 | /** |
|
2601 | 2605 | * Success callback for restoring a notebook to a checkpoint. |
|
2602 | 2606 | * |
|
2603 | 2607 | * @method restore_checkpoint_success |
|
2604 | 2608 | * @param {Object} data (ignored, should be empty) |
|
2605 | 2609 | * @param {String} status Description of response status |
|
2606 | 2610 | * @param {jqXHR} xhr jQuery Ajax object |
|
2607 | 2611 | */ |
|
2608 | 2612 | Notebook.prototype.restore_checkpoint_success = function (data, status, xhr) { |
|
2609 | 2613 | this.events.trigger('checkpoint_restored.Notebook'); |
|
2610 | 2614 | this.load_notebook(this.notebook_name, this.notebook_path); |
|
2611 | 2615 | }; |
|
2612 | 2616 | |
|
2613 | 2617 | /** |
|
2614 | 2618 | * Failure callback for restoring a notebook to a checkpoint. |
|
2615 | 2619 | * |
|
2616 | 2620 | * @method restore_checkpoint_error |
|
2617 | 2621 | * @param {jqXHR} xhr jQuery Ajax object |
|
2618 | 2622 | * @param {String} status Description of response status |
|
2619 | 2623 | * @param {String} error_msg HTTP error message |
|
2620 | 2624 | */ |
|
2621 | 2625 | Notebook.prototype.restore_checkpoint_error = function (xhr, status, error_msg) { |
|
2622 | 2626 | this.events.trigger('checkpoint_restore_failed.Notebook'); |
|
2623 | 2627 | }; |
|
2624 | 2628 | |
|
2625 | 2629 | /** |
|
2626 | 2630 | * Delete a notebook checkpoint. |
|
2627 | 2631 | * |
|
2628 | 2632 | * @method delete_checkpoint |
|
2629 | 2633 | * @param {String} checkpoint ID |
|
2630 | 2634 | */ |
|
2631 | 2635 | Notebook.prototype.delete_checkpoint = function (checkpoint) { |
|
2632 | 2636 | this.events.trigger('notebook_restoring.Notebook', checkpoint); |
|
2633 | 2637 | var url = utils.url_join_encode( |
|
2634 | 2638 | this.base_url, |
|
2635 | 2639 | 'api/contents', |
|
2636 | 2640 | this.notebook_path, |
|
2637 | 2641 | this.notebook_name, |
|
2638 | 2642 | 'checkpoints', |
|
2639 | 2643 | checkpoint |
|
2640 | 2644 | ); |
|
2641 | 2645 | $.ajax(url, { |
|
2642 | 2646 | type: 'DELETE', |
|
2643 | 2647 | success: $.proxy(this.delete_checkpoint_success, this), |
|
2644 | 2648 | error: $.proxy(this.delete_checkpoint_error, this) |
|
2645 | 2649 | }); |
|
2646 | 2650 | }; |
|
2647 | 2651 | |
|
2648 | 2652 | /** |
|
2649 | 2653 | * Success callback for deleting a notebook checkpoint |
|
2650 | 2654 | * |
|
2651 | 2655 | * @method delete_checkpoint_success |
|
2652 | 2656 | * @param {Object} data (ignored, should be empty) |
|
2653 | 2657 | * @param {String} status Description of response status |
|
2654 | 2658 | * @param {jqXHR} xhr jQuery Ajax object |
|
2655 | 2659 | */ |
|
2656 | 2660 | Notebook.prototype.delete_checkpoint_success = function (data, status, xhr) { |
|
2657 | 2661 | this.events.trigger('checkpoint_deleted.Notebook', data); |
|
2658 | 2662 | this.load_notebook(this.notebook_name, this.notebook_path); |
|
2659 | 2663 | }; |
|
2660 | 2664 | |
|
2661 | 2665 | /** |
|
2662 | 2666 | * Failure callback for deleting a notebook checkpoint. |
|
2663 | 2667 | * |
|
2664 | 2668 | * @method delete_checkpoint_error |
|
2665 | 2669 | * @param {jqXHR} xhr jQuery Ajax object |
|
2666 | 2670 | * @param {String} status Description of response status |
|
2667 | 2671 | * @param {String} error HTTP error message |
|
2668 | 2672 | */ |
|
2669 | 2673 | Notebook.prototype.delete_checkpoint_error = function (xhr, status, error) { |
|
2670 | 2674 | this.events.trigger('checkpoint_delete_failed.Notebook', [xhr, status, error]); |
|
2671 | 2675 | }; |
|
2672 | 2676 | |
|
2673 | 2677 | |
|
2674 | 2678 | // For backwards compatability. |
|
2675 | 2679 | IPython.Notebook = Notebook; |
|
2676 | 2680 | |
|
2677 | 2681 | return {'Notebook': Notebook}; |
|
2678 | 2682 | }); |
@@ -1,425 +1,352 b'' | |||
|
1 | 1 | // Copyright (c) IPython Development Team. |
|
2 | 2 | // Distributed under the terms of the Modified BSD License. |
|
3 | 3 | |
|
4 | 4 | define([ |
|
5 | 5 | 'base/js/namespace', |
|
6 | 6 | 'base/js/utils', |
|
7 | 7 | 'jquery', |
|
8 | 8 | 'notebook/js/cell', |
|
9 | 9 | 'base/js/security', |
|
10 | 10 | 'notebook/js/mathjaxutils', |
|
11 | 11 | 'notebook/js/celltoolbar', |
|
12 | 12 | 'components/marked/lib/marked', |
|
13 | 13 | 'codemirror/lib/codemirror', |
|
14 | 14 | 'codemirror/mode/gfm/gfm', |
|
15 | 15 | 'notebook/js/codemirror-ipythongfm' |
|
16 | 16 | ], function(IPython,utils , $, cell, security, mathjaxutils, celltoolbar, marked, CodeMirror, gfm, ipgfm) { |
|
17 | 17 | "use strict"; |
|
18 | 18 | var Cell = cell.Cell; |
|
19 | 19 | |
|
20 | 20 | var TextCell = function (options) { |
|
21 | 21 | // Constructor |
|
22 | 22 | // |
|
23 | 23 | // Construct a new TextCell, codemirror mode is by default 'htmlmixed', |
|
24 | 24 | // and cell type is 'text' cell start as not redered. |
|
25 | 25 | // |
|
26 | 26 | // Parameters: |
|
27 | 27 | // options: dictionary |
|
28 | 28 | // Dictionary of keyword arguments. |
|
29 | 29 | // events: $(Events) instance |
|
30 | 30 | // config: dictionary |
|
31 | 31 | // keyboard_manager: KeyboardManager instance |
|
32 | 32 | // notebook: Notebook instance |
|
33 | 33 | options = options || {}; |
|
34 | 34 | |
|
35 | 35 | // in all TextCell/Cell subclasses |
|
36 | 36 | // do not assign most of members here, just pass it down |
|
37 | 37 | // in the options dict potentially overwriting what you wish. |
|
38 | 38 | // they will be assigned in the base class. |
|
39 | 39 | this.notebook = options.notebook; |
|
40 | 40 | this.events = options.events; |
|
41 | 41 | this.config = options.config; |
|
42 | 42 | |
|
43 | 43 | // we cannot put this as a class key as it has handle to "this". |
|
44 | 44 | var cm_overwrite_options = { |
|
45 | 45 | onKeyEvent: $.proxy(this.handle_keyevent,this) |
|
46 | 46 | }; |
|
47 | 47 | var config = utils.mergeopt(TextCell, this.config, {cm_config:cm_overwrite_options}); |
|
48 | 48 | Cell.apply(this, [{ |
|
49 | 49 | config: config, |
|
50 | 50 | keyboard_manager: options.keyboard_manager, |
|
51 | 51 | events: this.events}]); |
|
52 | 52 | |
|
53 | 53 | this.cell_type = this.cell_type || 'text'; |
|
54 | 54 | mathjaxutils = mathjaxutils; |
|
55 | 55 | this.rendered = false; |
|
56 | 56 | }; |
|
57 | 57 | |
|
58 | 58 | TextCell.prototype = Object.create(Cell.prototype); |
|
59 | 59 | |
|
60 | 60 | TextCell.options_default = { |
|
61 | 61 | cm_config : { |
|
62 | 62 | extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess"}, |
|
63 | 63 | mode: 'htmlmixed', |
|
64 | 64 | lineWrapping : true, |
|
65 | 65 | } |
|
66 | 66 | }; |
|
67 | 67 | |
|
68 | 68 | |
|
69 | 69 | /** |
|
70 | 70 | * Create the DOM element of the TextCell |
|
71 | 71 | * @method create_element |
|
72 | 72 | * @private |
|
73 | 73 | */ |
|
74 | 74 | TextCell.prototype.create_element = function () { |
|
75 | 75 | Cell.prototype.create_element.apply(this, arguments); |
|
76 | 76 | |
|
77 | 77 | var cell = $("<div>").addClass('cell text_cell'); |
|
78 | 78 | cell.attr('tabindex','2'); |
|
79 | 79 | |
|
80 | 80 | var prompt = $('<div/>').addClass('prompt input_prompt'); |
|
81 | 81 | cell.append(prompt); |
|
82 | 82 | var inner_cell = $('<div/>').addClass('inner_cell'); |
|
83 | 83 | this.celltoolbar = new celltoolbar.CellToolbar({ |
|
84 | 84 | cell: this, |
|
85 | 85 | notebook: this.notebook}); |
|
86 | 86 | inner_cell.append(this.celltoolbar.element); |
|
87 | 87 | var input_area = $('<div/>').addClass('input_area'); |
|
88 | 88 | this.code_mirror = new CodeMirror(input_area.get(0), this.cm_config); |
|
89 | 89 | // The tabindex=-1 makes this div focusable. |
|
90 | 90 | var render_area = $('<div/>').addClass('text_cell_render rendered_html') |
|
91 | 91 | .attr('tabindex','-1'); |
|
92 | 92 | inner_cell.append(input_area).append(render_area); |
|
93 | 93 | cell.append(inner_cell); |
|
94 | 94 | this.element = cell; |
|
95 | 95 | }; |
|
96 | 96 | |
|
97 | 97 | |
|
98 | 98 | // Cell level actions |
|
99 | 99 | |
|
100 | 100 | TextCell.prototype.select = function () { |
|
101 | 101 | var cont = Cell.prototype.select.apply(this); |
|
102 | 102 | if (cont) { |
|
103 | 103 | if (this.mode === 'edit') { |
|
104 | 104 | this.code_mirror.refresh(); |
|
105 | 105 | } |
|
106 | 106 | } |
|
107 | 107 | return cont; |
|
108 | 108 | }; |
|
109 | 109 | |
|
110 | 110 | TextCell.prototype.unrender = function () { |
|
111 | 111 | if (this.read_only) return; |
|
112 | 112 | var cont = Cell.prototype.unrender.apply(this); |
|
113 | 113 | if (cont) { |
|
114 | 114 | var text_cell = this.element; |
|
115 | 115 | var output = text_cell.find("div.text_cell_render"); |
|
116 | 116 | if (this.get_text() === this.placeholder) { |
|
117 | 117 | this.set_text(''); |
|
118 | 118 | } |
|
119 | 119 | this.refresh(); |
|
120 | 120 | } |
|
121 | 121 | return cont; |
|
122 | 122 | }; |
|
123 | 123 | |
|
124 | 124 | TextCell.prototype.execute = function () { |
|
125 | 125 | this.render(); |
|
126 | 126 | }; |
|
127 | 127 | |
|
128 | 128 | /** |
|
129 | 129 | * setter: {{#crossLink "TextCell/set_text"}}{{/crossLink}} |
|
130 | 130 | * @method get_text |
|
131 | 131 | * @retrun {string} CodeMirror current text value |
|
132 | 132 | */ |
|
133 | 133 | TextCell.prototype.get_text = function() { |
|
134 | 134 | return this.code_mirror.getValue(); |
|
135 | 135 | }; |
|
136 | 136 | |
|
137 | 137 | /** |
|
138 | 138 | * @param {string} text - Codemiror text value |
|
139 | 139 | * @see TextCell#get_text |
|
140 | 140 | * @method set_text |
|
141 | 141 | * */ |
|
142 | 142 | TextCell.prototype.set_text = function(text) { |
|
143 | 143 | this.code_mirror.setValue(text); |
|
144 | 144 | this.unrender(); |
|
145 | 145 | this.code_mirror.refresh(); |
|
146 | 146 | }; |
|
147 | 147 | |
|
148 | 148 | /** |
|
149 | 149 | * setter :{{#crossLink "TextCell/set_rendered"}}{{/crossLink}} |
|
150 | 150 | * @method get_rendered |
|
151 | 151 | * */ |
|
152 | 152 | TextCell.prototype.get_rendered = function() { |
|
153 | 153 | return this.element.find('div.text_cell_render').html(); |
|
154 | 154 | }; |
|
155 | 155 | |
|
156 | 156 | /** |
|
157 | 157 | * @method set_rendered |
|
158 | 158 | */ |
|
159 | 159 | TextCell.prototype.set_rendered = function(text) { |
|
160 | 160 | this.element.find('div.text_cell_render').html(text); |
|
161 | 161 | }; |
|
162 | 162 | |
|
163 | 163 | |
|
164 | 164 | /** |
|
165 | 165 | * Create Text cell from JSON |
|
166 | 166 | * @param {json} data - JSON serialized text-cell |
|
167 | 167 | * @method fromJSON |
|
168 | 168 | */ |
|
169 | 169 | TextCell.prototype.fromJSON = function (data) { |
|
170 | 170 | Cell.prototype.fromJSON.apply(this, arguments); |
|
171 | 171 | if (data.cell_type === this.cell_type) { |
|
172 | 172 | if (data.source !== undefined) { |
|
173 | 173 | this.set_text(data.source); |
|
174 | 174 | // make this value the starting point, so that we can only undo |
|
175 | 175 | // to this state, instead of a blank cell |
|
176 | 176 | this.code_mirror.clearHistory(); |
|
177 | 177 | // TODO: This HTML needs to be treated as potentially dangerous |
|
178 | 178 | // user input and should be handled before set_rendered. |
|
179 | 179 | this.set_rendered(data.rendered || ''); |
|
180 | 180 | this.rendered = false; |
|
181 | 181 | this.render(); |
|
182 | 182 | } |
|
183 | 183 | } |
|
184 | 184 | }; |
|
185 | 185 | |
|
186 | 186 | /** Generate JSON from cell |
|
187 | 187 | * @return {object} cell data serialised to json |
|
188 | 188 | */ |
|
189 | 189 | TextCell.prototype.toJSON = function () { |
|
190 | 190 | var data = Cell.prototype.toJSON.apply(this); |
|
191 | 191 | data.source = this.get_text(); |
|
192 | 192 | if (data.source == this.placeholder) { |
|
193 | 193 | data.source = ""; |
|
194 | 194 | } |
|
195 | 195 | return data; |
|
196 | 196 | }; |
|
197 | 197 | |
|
198 | 198 | |
|
199 | 199 | var MarkdownCell = function (options) { |
|
200 | 200 | // Constructor |
|
201 | 201 | // |
|
202 | 202 | // Parameters: |
|
203 | 203 | // options: dictionary |
|
204 | 204 | // Dictionary of keyword arguments. |
|
205 | 205 | // events: $(Events) instance |
|
206 | 206 | // config: dictionary |
|
207 | 207 | // keyboard_manager: KeyboardManager instance |
|
208 | 208 | // notebook: Notebook instance |
|
209 | 209 | options = options || {}; |
|
210 | 210 | var config = utils.mergeopt(MarkdownCell, options.config); |
|
211 | 211 | TextCell.apply(this, [$.extend({}, options, {config: config})]); |
|
212 | 212 | |
|
213 | 213 | this.cell_type = 'markdown'; |
|
214 | 214 | }; |
|
215 | 215 | |
|
216 | 216 | MarkdownCell.options_default = { |
|
217 | 217 | cm_config: { |
|
218 | 218 | mode: 'ipythongfm' |
|
219 | 219 | }, |
|
220 | 220 | placeholder: "Type *Markdown* and LaTeX: $\\alpha^2$" |
|
221 | 221 | }; |
|
222 | 222 | |
|
223 | 223 | MarkdownCell.prototype = Object.create(TextCell.prototype); |
|
224 | 224 | |
|
225 | MarkdownCell.prototype.set_heading_level = function (level) { | |
|
226 | // make a markdown cell a heading | |
|
227 | level = level || 1; | |
|
228 | var source = this.get_text(); | |
|
229 | // \s\S appears to be the js version of multi-line dot-all | |
|
230 | var match = source.match(/(#*)\s*([\s\S]*)/); | |
|
231 | // strip the leading `#` if it's already there | |
|
232 | if (match) { | |
|
233 | source = match[2]; | |
|
234 | } | |
|
235 | // add `#` markdown heading prefix | |
|
236 | var new_text = new Array(level + 1).join('#') + ' ' + source; | |
|
237 | ||
|
238 | this.set_text(new_text); | |
|
239 | this.refresh(); | |
|
240 | if (this.rendered) { | |
|
241 | this.render(); | |
|
242 | } | |
|
243 | }; | |
|
244 | ||
|
225 | 245 | /** |
|
226 | 246 | * @method render |
|
227 | 247 | */ |
|
228 | 248 | MarkdownCell.prototype.render = function () { |
|
229 | 249 | var cont = TextCell.prototype.render.apply(this); |
|
230 | 250 | if (cont) { |
|
231 | 251 | var text = this.get_text(); |
|
232 | 252 | var math = null; |
|
233 | 253 | if (text === "") { text = this.placeholder; } |
|
234 | 254 | var text_and_math = mathjaxutils.remove_math(text); |
|
235 | 255 | text = text_and_math[0]; |
|
236 | 256 | math = text_and_math[1]; |
|
237 | 257 | var html = marked.parser(marked.lexer(text)); |
|
238 | 258 | html = mathjaxutils.replace_math(html, math); |
|
239 | 259 | html = security.sanitize_html(html); |
|
240 | 260 | html = $($.parseHTML(html)); |
|
261 | // add anchors to headings | |
|
262 | // console.log(html); | |
|
263 | html.find(":header").addBack(":header").each(function (i, h) { | |
|
264 | h = $(h); | |
|
265 | var hash = h.text().replace(/ /g, '-'); | |
|
266 | h.attr('id', hash); | |
|
267 | h.append( | |
|
268 | $('<a/>') | |
|
269 | .addClass('anchor-link') | |
|
270 | .attr('href', '#' + hash) | |
|
271 | .text('¶') | |
|
272 | ); | |
|
273 | }) | |
|
241 | 274 | // links in markdown cells should open in new tabs |
|
242 | 275 | html.find("a[href]").not('[href^="#"]').attr("target", "_blank"); |
|
243 | 276 | this.set_rendered(html); |
|
244 | 277 | this.typeset(); |
|
245 | 278 | this.events.trigger("rendered.MarkdownCell", {cell: this}) |
|
246 | 279 | } |
|
247 | 280 | return cont; |
|
248 | 281 | }; |
|
249 | 282 | |
|
250 | 283 | |
|
251 | 284 | var RawCell = function (options) { |
|
252 | 285 | // Constructor |
|
253 | 286 | // |
|
254 | 287 | // Parameters: |
|
255 | 288 | // options: dictionary |
|
256 | 289 | // Dictionary of keyword arguments. |
|
257 | 290 | // events: $(Events) instance |
|
258 | 291 | // config: dictionary |
|
259 | 292 | // keyboard_manager: KeyboardManager instance |
|
260 | 293 | // notebook: Notebook instance |
|
261 | 294 | options = options || {}; |
|
262 | 295 | var config = utils.mergeopt(RawCell, options.config); |
|
263 | 296 | TextCell.apply(this, [$.extend({}, options, {config: config})]); |
|
264 | 297 | |
|
265 | 298 | this.cell_type = 'raw'; |
|
266 | 299 | }; |
|
267 | 300 | |
|
268 | 301 | RawCell.options_default = { |
|
269 | 302 | placeholder : "Write raw LaTeX or other formats here, for use with nbconvert. " + |
|
270 | 303 | "It will not be rendered in the notebook. " + |
|
271 | 304 | "When passing through nbconvert, a Raw Cell's content is added to the output unmodified." |
|
272 | 305 | }; |
|
273 | 306 | |
|
274 | 307 | RawCell.prototype = Object.create(TextCell.prototype); |
|
275 | 308 | |
|
276 | 309 | /** @method bind_events **/ |
|
277 | 310 | RawCell.prototype.bind_events = function () { |
|
278 | 311 | TextCell.prototype.bind_events.apply(this); |
|
279 | 312 | var that = this; |
|
280 | 313 | this.element.focusout(function() { |
|
281 | 314 | that.auto_highlight(); |
|
282 | 315 | that.render(); |
|
283 | 316 | }); |
|
284 | 317 | |
|
285 | 318 | this.code_mirror.on('focus', function() { that.unrender(); }); |
|
286 | 319 | }; |
|
287 | 320 | |
|
288 | 321 | /** |
|
289 | 322 | * Trigger autodetection of highlight scheme for current cell |
|
290 | 323 | * @method auto_highlight |
|
291 | 324 | */ |
|
292 | 325 | RawCell.prototype.auto_highlight = function () { |
|
293 | 326 | this._auto_highlight(this.config.raw_cell_highlight); |
|
294 | 327 | }; |
|
295 | 328 | |
|
296 | 329 | /** @method render **/ |
|
297 | 330 | RawCell.prototype.render = function () { |
|
298 | 331 | var cont = TextCell.prototype.render.apply(this); |
|
299 | 332 | if (cont){ |
|
300 | 333 | var text = this.get_text(); |
|
301 | 334 | if (text === "") { text = this.placeholder; } |
|
302 | 335 | this.set_text(text); |
|
303 | 336 | this.element.removeClass('rendered'); |
|
304 | 337 | } |
|
305 | 338 | return cont; |
|
306 | 339 | }; |
|
307 | 340 | |
|
308 | ||
|
309 | var HeadingCell = function (options) { | |
|
310 | // Constructor | |
|
311 | // | |
|
312 | // Parameters: | |
|
313 | // options: dictionary | |
|
314 | // Dictionary of keyword arguments. | |
|
315 | // events: $(Events) instance | |
|
316 | // config: dictionary | |
|
317 | // keyboard_manager: KeyboardManager instance | |
|
318 | // notebook: Notebook instance | |
|
319 | options = options || {}; | |
|
320 | var config = utils.mergeopt(HeadingCell, options.config); | |
|
321 | TextCell.apply(this, [$.extend({}, options, {config: config})]); | |
|
322 | ||
|
323 | this.level = 1; | |
|
324 | this.cell_type = 'heading'; | |
|
325 | }; | |
|
326 | ||
|
327 | HeadingCell.options_default = { | |
|
328 | cm_config: { | |
|
329 | theme: 'heading-1' | |
|
330 | }, | |
|
331 | placeholder: "Type Heading Here" | |
|
332 | }; | |
|
333 | ||
|
334 | HeadingCell.prototype = Object.create(TextCell.prototype); | |
|
335 | ||
|
336 | /** @method fromJSON */ | |
|
337 | HeadingCell.prototype.fromJSON = function (data) { | |
|
338 | if (data.level !== undefined){ | |
|
339 | this.level = data.level; | |
|
340 | } | |
|
341 | TextCell.prototype.fromJSON.apply(this, arguments); | |
|
342 | this.code_mirror.setOption("theme", "heading-"+this.level); | |
|
343 | }; | |
|
344 | ||
|
345 | ||
|
346 | /** @method toJSON */ | |
|
347 | HeadingCell.prototype.toJSON = function () { | |
|
348 | var data = TextCell.prototype.toJSON.apply(this); | |
|
349 | data.level = this.get_level(); | |
|
350 | return data; | |
|
351 | }; | |
|
352 | ||
|
353 | /** | |
|
354 | * Change heading level of cell, and re-render | |
|
355 | * @method set_level | |
|
356 | */ | |
|
357 | HeadingCell.prototype.set_level = function (level) { | |
|
358 | this.level = level; | |
|
359 | this.code_mirror.setOption("theme", "heading-"+level); | |
|
360 | ||
|
361 | if (this.rendered) { | |
|
362 | this.rendered = false; | |
|
363 | this.render(); | |
|
364 | } | |
|
365 | }; | |
|
366 | ||
|
367 | /** The depth of header cell, based on html (h1 to h6) | |
|
368 | * @method get_level | |
|
369 | * @return {integer} level - for 1 to 6 | |
|
370 | */ | |
|
371 | HeadingCell.prototype.get_level = function () { | |
|
372 | return this.level; | |
|
373 | }; | |
|
374 | ||
|
375 | ||
|
376 | HeadingCell.prototype.get_rendered = function () { | |
|
377 | var r = this.element.find("div.text_cell_render"); | |
|
378 | return r.children().first().html(); | |
|
379 | }; | |
|
380 | ||
|
381 | HeadingCell.prototype.render = function () { | |
|
382 | var cont = TextCell.prototype.render.apply(this); | |
|
383 | if (cont) { | |
|
384 | var text = this.get_text(); | |
|
385 | var math = null; | |
|
386 | // Markdown headings must be a single line | |
|
387 | text = text.replace(/\n/g, ' '); | |
|
388 | if (text === "") { text = this.placeholder; } | |
|
389 | text = new Array(this.level + 1).join("#") + " " + text; | |
|
390 | var text_and_math = mathjaxutils.remove_math(text); | |
|
391 | text = text_and_math[0]; | |
|
392 | math = text_and_math[1]; | |
|
393 | var html = marked.parser(marked.lexer(text)); | |
|
394 | html = mathjaxutils.replace_math(html, math); | |
|
395 | html = security.sanitize_html(html); | |
|
396 | var h = $($.parseHTML(html)); | |
|
397 | // add id and linkback anchor | |
|
398 | var hash = h.text().trim().replace(/ /g, '-'); | |
|
399 | h.attr('id', hash); | |
|
400 | h.append( | |
|
401 | $('<a/>') | |
|
402 | .addClass('anchor-link') | |
|
403 | .attr('href', '#' + hash) | |
|
404 | .text('¶') | |
|
405 | ); | |
|
406 | this.set_rendered(h); | |
|
407 | this.typeset(); | |
|
408 | } | |
|
409 | return cont; | |
|
410 | }; | |
|
411 | ||
|
412 | 341 | // Backwards compatability. |
|
413 | 342 | IPython.TextCell = TextCell; |
|
414 | 343 | IPython.MarkdownCell = MarkdownCell; |
|
415 | 344 | IPython.RawCell = RawCell; |
|
416 | IPython.HeadingCell = HeadingCell; | |
|
417 | 345 | |
|
418 | 346 | var textcell = { |
|
419 |
|
|
|
420 |
|
|
|
421 |
|
|
|
422 | 'HeadingCell': HeadingCell, | |
|
347 | TextCell: TextCell, | |
|
348 | MarkdownCell: MarkdownCell, | |
|
349 | RawCell: RawCell, | |
|
423 | 350 | }; |
|
424 | 351 | return textcell; |
|
425 | 352 | }); |
@@ -1,328 +1,322 b'' | |||
|
1 | 1 | {% extends "page.html" %} |
|
2 | 2 | |
|
3 | 3 | {% block stylesheet %} |
|
4 | 4 | |
|
5 | 5 | {% if mathjax_url %} |
|
6 | 6 | <script type="text/javascript" src="{{mathjax_url}}?config=TeX-AMS_HTML-full&delayStartupUntil=configured" charset="utf-8"></script> |
|
7 | 7 | {% endif %} |
|
8 | 8 | <script type="text/javascript"> |
|
9 | 9 | // MathJax disabled, set as null to distingish from *missing* MathJax, |
|
10 | 10 | // where it will be undefined, and should prompt a dialog later. |
|
11 | 11 | window.mathjax_url = "{{mathjax_url}}"; |
|
12 | 12 | </script> |
|
13 | 13 | |
|
14 | 14 | <link rel="stylesheet" href="{{ static_url("components/bootstrap-tour/build/css/bootstrap-tour.min.css") }}" type="text/css" /> |
|
15 | 15 | <link rel="stylesheet" href="{{ static_url("components/codemirror/lib/codemirror.css") }}"> |
|
16 | 16 | |
|
17 | 17 | {{super()}} |
|
18 | 18 | |
|
19 | 19 | <link rel="stylesheet" href="{{ static_url("notebook/css/override.css") }}" type="text/css" /> |
|
20 | 20 | |
|
21 | 21 | {% endblock %} |
|
22 | 22 | |
|
23 | 23 | {% block params %} |
|
24 | 24 | |
|
25 | 25 | data-project="{{project}}" |
|
26 | 26 | data-base-url="{{base_url}}" |
|
27 | 27 | data-ws-url="{{ws_url}}" |
|
28 | 28 | data-notebook-name="{{notebook_name}}" |
|
29 | 29 | data-notebook-path="{{notebook_path}}" |
|
30 | 30 | class="notebook_app" |
|
31 | 31 | |
|
32 | 32 | {% endblock %} |
|
33 | 33 | |
|
34 | 34 | |
|
35 | 35 | {% block header %} |
|
36 | 36 | |
|
37 | 37 | |
|
38 | 38 | <span id="save_widget" class="nav pull-left"> |
|
39 | 39 | <span id="notebook_name"></span> |
|
40 | 40 | <span id="checkpoint_status"></span> |
|
41 | 41 | <span id="autosave_status"></span> |
|
42 | 42 | </span> |
|
43 | 43 | |
|
44 | 44 | <span id="kernel_selector_widget" class="pull-right dropdown"> |
|
45 | 45 | <button class="dropdown-toggle" data-toggle="dropdown" type='button' id="current_kernel_spec"> |
|
46 | 46 | <span class='kernel_name'>Python</span> |
|
47 | 47 | <span class="caret"></span> |
|
48 | 48 | </button> |
|
49 | 49 | <ul id="kernel_selector" class="dropdown-menu"> |
|
50 | 50 | </ul> |
|
51 | 51 | </span> |
|
52 | 52 | |
|
53 | 53 | {% endblock %} |
|
54 | 54 | |
|
55 | 55 | |
|
56 | 56 | {% block site %} |
|
57 | 57 | |
|
58 | 58 | <div id="menubar-container" class="container"> |
|
59 | 59 | <div id="menubar"> |
|
60 | 60 | <div id="menus" class="navbar navbar-default" role="navigation"> |
|
61 | 61 | <div class="container-fluid"> |
|
62 | 62 | <button type="button" class="btn btn-default navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> |
|
63 | 63 | <i class="fa fa-bars"></i> |
|
64 | 64 | <span class="navbar-text">Menu</span> |
|
65 | 65 | </button> |
|
66 | 66 | <ul class="nav navbar-nav navbar-right"> |
|
67 | 67 | <li id="kernel_indicator"> |
|
68 | 68 | <i id="kernel_indicator_icon"></i> |
|
69 | 69 | </li> |
|
70 | 70 | <li id="modal_indicator"> |
|
71 | 71 | <i id="modal_indicator_icon"></i> |
|
72 | 72 | </li> |
|
73 | 73 | <li id="notification_area"></li> |
|
74 | 74 | </ul> |
|
75 | 75 | <div class="navbar-collapse collapse"> |
|
76 | 76 | <ul class="nav navbar-nav"> |
|
77 | 77 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">File</a> |
|
78 | 78 | <ul id="file_menu" class="dropdown-menu"> |
|
79 | 79 | <li id="new_notebook" |
|
80 | 80 | title="Make a new notebook (Opens a new window)"> |
|
81 | 81 | <a href="#">New</a></li> |
|
82 | 82 | <li id="open_notebook" |
|
83 | 83 | title="Opens a new window with the Dashboard view"> |
|
84 | 84 | <a href="#">Open...</a></li> |
|
85 | 85 | <!-- <hr/> --> |
|
86 | 86 | <li class="divider"></li> |
|
87 | 87 | <li id="copy_notebook" |
|
88 | 88 | title="Open a copy of this notebook's contents and start a new kernel"> |
|
89 | 89 | <a href="#">Make a Copy...</a></li> |
|
90 | 90 | <li id="rename_notebook"><a href="#">Rename...</a></li> |
|
91 | 91 | <li id="save_checkpoint"><a href="#">Save and Checkpoint</a></li> |
|
92 | 92 | <!-- <hr/> --> |
|
93 | 93 | <li class="divider"></li> |
|
94 | 94 | <li id="restore_checkpoint" class="dropdown-submenu"><a href="#">Revert to Checkpoint</a> |
|
95 | 95 | <ul class="dropdown-menu"> |
|
96 | 96 | <li><a href="#"></a></li> |
|
97 | 97 | <li><a href="#"></a></li> |
|
98 | 98 | <li><a href="#"></a></li> |
|
99 | 99 | <li><a href="#"></a></li> |
|
100 | 100 | <li><a href="#"></a></li> |
|
101 | 101 | </ul> |
|
102 | 102 | </li> |
|
103 | 103 | <li class="divider"></li> |
|
104 | 104 | <li id="print_preview"><a href="#">Print Preview</a></li> |
|
105 | 105 | <li class="dropdown-submenu"><a href="#">Download as</a> |
|
106 | 106 | <ul class="dropdown-menu"> |
|
107 | 107 | <li id="download_ipynb"><a href="#">IPython Notebook (.ipynb)</a></li> |
|
108 | 108 | <li id="download_py"><a href="#">Python (.py)</a></li> |
|
109 | 109 | <li id="download_html"><a href="#">HTML (.html)</a></li> |
|
110 | 110 | <li id="download_rst"><a href="#">reST (.rst)</a></li> |
|
111 | 111 | <li id="download_pdf"><a href="#">PDF (.pdf)</a></li> |
|
112 | 112 | </ul> |
|
113 | 113 | </li> |
|
114 | 114 | <li class="divider"></li> |
|
115 | 115 | <li id="trust_notebook" |
|
116 | 116 | title="Trust the output of this notebook"> |
|
117 | 117 | <a href="#" >Trust Notebook</a></li> |
|
118 | 118 | <li class="divider"></li> |
|
119 | 119 | <li id="kill_and_exit" |
|
120 | 120 | title="Shutdown this notebook's kernel, and close this window"> |
|
121 | 121 | <a href="#" >Close and halt</a></li> |
|
122 | 122 | </ul> |
|
123 | 123 | </li> |
|
124 | 124 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Edit</a> |
|
125 | 125 | <ul id="edit_menu" class="dropdown-menu"> |
|
126 | 126 | <li id="cut_cell"><a href="#">Cut Cell</a></li> |
|
127 | 127 | <li id="copy_cell"><a href="#">Copy Cell</a></li> |
|
128 | 128 | <li id="paste_cell_above" class="disabled"><a href="#">Paste Cell Above</a></li> |
|
129 | 129 | <li id="paste_cell_below" class="disabled"><a href="#">Paste Cell Below</a></li> |
|
130 | 130 | <li id="paste_cell_replace" class="disabled"><a href="#">Paste Cell & Replace</a></li> |
|
131 | 131 | <li id="delete_cell"><a href="#">Delete Cell</a></li> |
|
132 | 132 | <li id="undelete_cell" class="disabled"><a href="#">Undo Delete Cell</a></li> |
|
133 | 133 | <li class="divider"></li> |
|
134 | 134 | <li id="split_cell"><a href="#">Split Cell</a></li> |
|
135 | 135 | <li id="merge_cell_above"><a href="#">Merge Cell Above</a></li> |
|
136 | 136 | <li id="merge_cell_below"><a href="#">Merge Cell Below</a></li> |
|
137 | 137 | <li class="divider"></li> |
|
138 | 138 | <li id="move_cell_up"><a href="#">Move Cell Up</a></li> |
|
139 | 139 | <li id="move_cell_down"><a href="#">Move Cell Down</a></li> |
|
140 | 140 | <li class="divider"></li> |
|
141 | 141 | <li id="edit_nb_metadata"><a href="#">Edit Notebook Metadata</a></li> |
|
142 | 142 | </ul> |
|
143 | 143 | </li> |
|
144 | 144 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">View</a> |
|
145 | 145 | <ul id="view_menu" class="dropdown-menu"> |
|
146 | 146 | <li id="toggle_header" |
|
147 | 147 | title="Show/Hide the IPython Notebook logo and notebook title (above menu bar)"> |
|
148 | 148 | <a href="#">Toggle Header</a></li> |
|
149 | 149 | <li id="toggle_toolbar" |
|
150 | 150 | title="Show/Hide the action icons (below menu bar)"> |
|
151 | 151 | <a href="#">Toggle Toolbar</a></li> |
|
152 | 152 | </ul> |
|
153 | 153 | </li> |
|
154 | 154 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Insert</a> |
|
155 | 155 | <ul id="insert_menu" class="dropdown-menu"> |
|
156 | 156 | <li id="insert_cell_above" |
|
157 | 157 | title="Insert an empty Code cell above the currently active cell"> |
|
158 | 158 | <a href="#">Insert Cell Above</a></li> |
|
159 | 159 | <li id="insert_cell_below" |
|
160 | 160 | title="Insert an empty Code cell below the currently active cell"> |
|
161 | 161 | <a href="#">Insert Cell Below</a></li> |
|
162 | 162 | </ul> |
|
163 | 163 | </li> |
|
164 | 164 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Cell</a> |
|
165 | 165 | <ul id="cell_menu" class="dropdown-menu"> |
|
166 | 166 | <li id="run_cell" title="Run this cell, and move cursor to the next one"> |
|
167 | 167 | <a href="#">Run</a></li> |
|
168 | 168 | <li id="run_cell_select_below" title="Run this cell, select below"> |
|
169 | 169 | <a href="#">Run and Select Below</a></li> |
|
170 | 170 | <li id="run_cell_insert_below" title="Run this cell, insert below"> |
|
171 | 171 | <a href="#">Run and Insert Below</a></li> |
|
172 | 172 | <li id="run_all_cells" title="Run all cells in the notebook"> |
|
173 | 173 | <a href="#">Run All</a></li> |
|
174 | 174 | <li id="run_all_cells_above" title="Run all cells above (but not including) this cell"> |
|
175 | 175 | <a href="#">Run All Above</a></li> |
|
176 | 176 | <li id="run_all_cells_below" title="Run this cell and all cells below it"> |
|
177 | 177 | <a href="#">Run All Below</a></li> |
|
178 | 178 | <li class="divider"></li> |
|
179 | 179 | <li id="change_cell_type" class="dropdown-submenu" |
|
180 | 180 | title="All cells in the notebook have a cell type. By default, new cells are created as 'Code' cells"> |
|
181 | 181 | <a href="#">Cell Type</a> |
|
182 | 182 | <ul class="dropdown-menu"> |
|
183 | 183 | <li id="to_code" |
|
184 | 184 | title="Contents will be sent to the kernel for execution, and output will display in the footer of cell"> |
|
185 | 185 | <a href="#">Code</a></li> |
|
186 | 186 | <li id="to_markdown" |
|
187 | 187 | title="Contents will be rendered as HTML and serve as explanatory text"> |
|
188 | 188 | <a href="#">Markdown</a></li> |
|
189 | 189 | <li id="to_raw" |
|
190 | 190 | title="Contents will pass through nbconvert unmodified"> |
|
191 | 191 | <a href="#">Raw NBConvert</a></li> |
|
192 | <li id="to_heading1"><a href="#">Heading 1</a></li> | |
|
193 | <li id="to_heading2"><a href="#">Heading 2</a></li> | |
|
194 | <li id="to_heading3"><a href="#">Heading 3</a></li> | |
|
195 | <li id="to_heading4"><a href="#">Heading 4</a></li> | |
|
196 | <li id="to_heading5"><a href="#">Heading 5</a></li> | |
|
197 | <li id="to_heading6"><a href="#">Heading 6</a></li> | |
|
198 | 192 | </ul> |
|
199 | 193 | </li> |
|
200 | 194 | <li class="divider"></li> |
|
201 | 195 | <li id="current_outputs" class="dropdown-submenu"><a href="#">Current Output</a> |
|
202 | 196 | <ul class="dropdown-menu"> |
|
203 | 197 | <li id="toggle_current_output" |
|
204 | 198 | title="Hide/Show the output of the current cell"> |
|
205 | 199 | <a href="#">Toggle</a> |
|
206 | 200 | </li> |
|
207 | 201 | <li id="toggle_current_output_scroll" |
|
208 | 202 | title="Scroll the output of the current cell"> |
|
209 | 203 | <a href="#">Toggle Scrolling</a> |
|
210 | 204 | </li> |
|
211 | 205 | <li id="clear_current_output" |
|
212 | 206 | title="Clear the output of the current cell"> |
|
213 | 207 | <a href="#">Clear</a> |
|
214 | 208 | </li> |
|
215 | 209 | </ul> |
|
216 | 210 | </li> |
|
217 | 211 | <li id="all_outputs" class="dropdown-submenu"><a href="#">All Output</a> |
|
218 | 212 | <ul class="dropdown-menu"> |
|
219 | 213 | <li id="toggle_all_output" |
|
220 | 214 | title="Hide/Show the output of all cells"> |
|
221 | 215 | <a href="#">Toggle</a> |
|
222 | 216 | </li> |
|
223 | 217 | <li id="toggle_all_output_scroll" |
|
224 | 218 | title="Scroll the output of all cells"> |
|
225 | 219 | <a href="#">Toggle Scrolling</a> |
|
226 | 220 | </li> |
|
227 | 221 | <li id="clear_all_output" |
|
228 | 222 | title="Clear the output of all cells"> |
|
229 | 223 | <a href="#">Clear</a> |
|
230 | 224 | </li> |
|
231 | 225 | </ul> |
|
232 | 226 | </li> |
|
233 | 227 | </ul> |
|
234 | 228 | </li> |
|
235 | 229 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Kernel</a> |
|
236 | 230 | <ul id="kernel_menu" class="dropdown-menu"> |
|
237 | 231 | <li id="int_kernel" |
|
238 | 232 | title="Send KeyboardInterrupt (CTRL-C) to the Kernel"> |
|
239 | 233 | <a href="#">Interrupt</a></li> |
|
240 | 234 | <li id="restart_kernel" |
|
241 | 235 | title="Restart the Kernel"> |
|
242 | 236 | <a href="#">Restart</a></li> |
|
243 | 237 | <li class="divider"></li> |
|
244 | 238 | <li id="menu-change-kernel" class="dropdown-submenu"> |
|
245 | 239 | <a href="#">Change kernel</a> |
|
246 | 240 | <ul class="dropdown-menu" id="menu-change-kernel-submenu"></ul> |
|
247 | 241 | </li> |
|
248 | 242 | </ul> |
|
249 | 243 | </li> |
|
250 | 244 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Help</a> |
|
251 | 245 | <ul id="help_menu" class="dropdown-menu"> |
|
252 | 246 | <li id="notebook_tour" title="A quick tour of the notebook user interface"><a href="#">User Interface Tour</a></li> |
|
253 | 247 | <li id="keyboard_shortcuts" title="Opens a tooltip with all keyboard shortcuts"><a href="#">Keyboard Shortcuts</a></li> |
|
254 | 248 | <li class="divider"></li> |
|
255 | 249 | {% set |
|
256 | 250 | sections = ( |
|
257 | 251 | ( |
|
258 | 252 | ("http://ipython.org/documentation.html","IPython Help",True), |
|
259 | 253 | ("http://nbviewer.ipython.org/github/ipython/ipython/tree/2.x/examples/Index.ipynb", "Notebook Help", True), |
|
260 | 254 | ),( |
|
261 | 255 | ("http://docs.python.org","Python",True), |
|
262 | 256 | ("http://help.github.com/articles/github-flavored-markdown","Markdown",True), |
|
263 | 257 | ("http://docs.scipy.org/doc/numpy/reference/","NumPy",True), |
|
264 | 258 | ("http://docs.scipy.org/doc/scipy/reference/","SciPy",True), |
|
265 | 259 | ("http://matplotlib.org/contents.html","Matplotlib",True), |
|
266 | 260 | ("http://docs.sympy.org/latest/index.html","SymPy",True), |
|
267 | 261 | ("http://pandas.pydata.org/pandas-docs/stable/","pandas", True) |
|
268 | 262 | ) |
|
269 | 263 | ) |
|
270 | 264 | %} |
|
271 | 265 | |
|
272 | 266 | {% for helplinks in sections %} |
|
273 | 267 | {% for link in helplinks %} |
|
274 | 268 | <li><a href="{{link[0]}}" {{'target="_blank" title="Opens in a new window"' if link[2]}}> |
|
275 | 269 | {{'<i class="fa fa-external-link menu-icon pull-right"></i>' if link[2]}} |
|
276 | 270 | {{link[1]}} |
|
277 | 271 | </a></li> |
|
278 | 272 | {% endfor %} |
|
279 | 273 | {% if not loop.last %} |
|
280 | 274 | <li class="divider"></li> |
|
281 | 275 | {% endif %} |
|
282 | 276 | {% endfor %} |
|
283 | 277 | <li class="divider"></li> |
|
284 | 278 | <li title="About IPython Notebook"><a id="notebook_about" href="#">About</a></li> |
|
285 | 279 | </ul> |
|
286 | 280 | </li> |
|
287 | 281 | </ul> |
|
288 | 282 | </div> |
|
289 | 283 | </div> |
|
290 | 284 | </div> |
|
291 | 285 | </div> |
|
292 | 286 | <div id="maintoolbar" class="navbar"> |
|
293 | 287 | <div class="toolbar-inner navbar-inner navbar-nobg"> |
|
294 | 288 | <div id="maintoolbar-container" class="container"></div> |
|
295 | 289 | </div> |
|
296 | 290 | </div> |
|
297 | 291 | </div> |
|
298 | 292 | |
|
299 | 293 | <div id="ipython-main-app"> |
|
300 | 294 | |
|
301 | 295 | <div id="notebook_panel"> |
|
302 | 296 | <div id="notebook"></div> |
|
303 | 297 | <div id="pager_splitter"></div> |
|
304 | 298 | <div id="pager"> |
|
305 | 299 | <div id='pager_button_area'> |
|
306 | 300 | </div> |
|
307 | 301 | <div id="pager-container" class="container"></div> |
|
308 | 302 | </div> |
|
309 | 303 | </div> |
|
310 | 304 | |
|
311 | 305 | </div> |
|
312 | 306 | <div id='tooltip' class='ipython_tooltip' style='display:none'></div> |
|
313 | 307 | |
|
314 | 308 | |
|
315 | 309 | {% endblock %} |
|
316 | 310 | |
|
317 | 311 | |
|
318 | 312 | {% block script %} |
|
319 | 313 | {{super()}} |
|
320 | 314 | <script type="text/javascript"> |
|
321 | 315 | sys_info = {{sys_info}}; |
|
322 | 316 | </script> |
|
323 | 317 | |
|
324 | 318 | <script src="{{ static_url("components/text-encoding/lib/encoding.js") }}" charset="utf-8"></script> |
|
325 | 319 | |
|
326 | 320 | <script src="{{ static_url("notebook/js/main.js") }}" charset="utf-8"></script> |
|
327 | 321 | |
|
328 | 322 | {% endblock %} |
@@ -1,77 +1,77 b'' | |||
|
1 | 1 | |
|
2 | 2 | // Test |
|
3 | 3 | casper.notebook_test(function () { |
|
4 | 4 | var a = 'print("a")'; |
|
5 | 5 | var index = this.append_cell(a); |
|
6 | 6 | this.execute_cell_then(index); |
|
7 | 7 | |
|
8 | 8 | var b = 'print("b")'; |
|
9 | 9 | index = this.append_cell(b); |
|
10 | 10 | this.execute_cell_then(index); |
|
11 | 11 | |
|
12 | 12 | var c = 'print("c")'; |
|
13 | 13 | index = this.append_cell(c); |
|
14 | 14 | this.execute_cell_then(index); |
|
15 | 15 | |
|
16 | 16 | this.thenEvaluate(function() { |
|
17 | 17 | IPython.notebook.default_cell_type = 'code'; |
|
18 | 18 | }); |
|
19 | 19 | |
|
20 | 20 | this.then(function () { |
|
21 | 21 | // Cell insertion |
|
22 | 22 | this.select_cell(2); |
|
23 | 23 | this.trigger_keydown('m'); // Make it markdown |
|
24 | 24 | this.trigger_keydown('a'); // Creates one cell |
|
25 | 25 | this.test.assertEquals(this.get_cell_text(2), '', 'a; New cell 2 text is empty'); |
|
26 | 26 | this.test.assertEquals(this.get_cell(2).cell_type, 'code', 'a; inserts a code cell'); |
|
27 | 27 | this.validate_notebook_state('a', 'command', 2); |
|
28 | 28 | this.trigger_keydown('b'); // Creates one cell |
|
29 | 29 | this.test.assertEquals(this.get_cell_text(2), '', 'b; Cell 2 text is still empty'); |
|
30 | 30 | this.test.assertEquals(this.get_cell_text(3), '', 'b; New cell 3 text is empty'); |
|
31 | 31 | this.test.assertEquals(this.get_cell(3).cell_type, 'code', 'b; inserts a code cell'); |
|
32 | 32 | this.validate_notebook_state('b', 'command', 3); |
|
33 | 33 | }); |
|
34 | 34 | |
|
35 | 35 | this.thenEvaluate(function() { |
|
36 | 36 | IPython.notebook.default_cell_type = 'selected'; |
|
37 | 37 | }); |
|
38 | 38 | |
|
39 | 39 | this.then(function () { |
|
40 | 40 | this.select_cell(2); |
|
41 | 41 | this.trigger_keydown('m'); // switch it to markdown for the next test |
|
42 | 42 | this.test.assertEquals(this.get_cell(2).cell_type, 'markdown', 'test cell is markdown'); |
|
43 | 43 | this.trigger_keydown('a'); // new cell above |
|
44 | 44 | this.test.assertEquals(this.get_cell(2).cell_type, 'markdown', 'a; inserts a markdown cell when markdown selected'); |
|
45 | 45 | this.trigger_keydown('b'); // new cell below |
|
46 | 46 | this.test.assertEquals(this.get_cell(3).cell_type, 'markdown', 'b; inserts a markdown cell when markdown selected'); |
|
47 | 47 | }); |
|
48 | 48 | |
|
49 | 49 | this.thenEvaluate(function() { |
|
50 | 50 | IPython.notebook.default_cell_type = 'above'; |
|
51 | 51 | }); |
|
52 | 52 | |
|
53 | 53 | this.then(function () { |
|
54 | 54 | this.select_cell(2); |
|
55 |
this.trigger_keydown(' |
|
|
56 |
this.test.assertEquals(this.get_cell(2).cell_type, ' |
|
|
55 | this.trigger_keydown('y'); // switch it to code for the next test | |
|
56 | this.test.assertEquals(this.get_cell(2).cell_type, 'code', 'test cell is code'); | |
|
57 | 57 | this.trigger_keydown('b'); // new cell below |
|
58 |
this.test.assertEquals(this.get_cell(3).cell_type, ' |
|
|
58 | this.test.assertEquals(this.get_cell(3).cell_type, 'code', 'b; inserts a code cell below code cell'); | |
|
59 | 59 | this.trigger_keydown('a'); // new cell above |
|
60 |
this.test.assertEquals(this.get_cell(3).cell_type, ' |
|
|
60 | this.test.assertEquals(this.get_cell(3).cell_type, 'code', 'a; inserts a code cell below code cell'); | |
|
61 | 61 | }); |
|
62 | 62 | |
|
63 | 63 | this.thenEvaluate(function() { |
|
64 | 64 | IPython.notebook.default_cell_type = 'below'; |
|
65 | 65 | }); |
|
66 | 66 | |
|
67 | 67 | this.then(function () { |
|
68 | 68 | this.select_cell(2); |
|
69 | 69 | this.trigger_keydown('r'); // switch it to markdown for the next test |
|
70 | 70 | this.test.assertEquals(this.get_cell(2).cell_type, 'raw', 'test cell is raw'); |
|
71 | 71 | this.trigger_keydown('a'); // new cell above |
|
72 | 72 | this.test.assertEquals(this.get_cell(2).cell_type, 'raw', 'a; inserts a raw cell above raw cell'); |
|
73 | 73 | this.trigger_keydown('y'); // switch it to code for the next test |
|
74 | 74 | this.trigger_keydown('b'); // new cell below |
|
75 | 75 | this.test.assertEquals(this.get_cell(3).cell_type, 'raw', 'b; inserts a raw cell above raw cell'); |
|
76 | 76 | }); |
|
77 | 77 | }); |
@@ -1,28 +1,41 b'' | |||
|
1 | 1 | // Test keyboard shortcuts that change the cell's mode. |
|
2 | 2 | |
|
3 | 3 | // Test |
|
4 | 4 | casper.notebook_test(function () { |
|
5 | 5 | this.then(function () { |
|
6 | 6 | // Cell mode change |
|
7 | this.select_cell(0); | |
|
7 | var index = 0; | |
|
8 | this.select_cell(index); | |
|
9 | var a = 'hello\nmulti\nline'; | |
|
10 | this.set_cell_text(index, a); | |
|
8 | 11 | this.trigger_keydown('esc','r'); |
|
9 |
this.test.assertEquals(this.get_cell( |
|
|
12 | this.test.assertEquals(this.get_cell(index).cell_type, 'raw', 'r; cell is raw'); | |
|
10 | 13 | this.trigger_keydown('1'); |
|
11 |
this.test.assertEquals(this.get_cell( |
|
|
12 |
this.test.assertEquals(this.get_cell( |
|
|
14 | this.test.assertEquals(this.get_cell(index).cell_type, 'markdown', '1; cell is markdown'); | |
|
15 | this.test.assertEquals(this.get_cell_text(index), '# ' + a, '1; markdown heading'); | |
|
13 | 16 | this.trigger_keydown('2'); |
|
14 |
this.test.assertEquals(this.get_cell( |
|
|
17 | this.test.assertEquals(this.get_cell(index).cell_type, 'markdown', '2; cell is markdown'); | |
|
18 | this.test.assertEquals(this.get_cell_text(index), '## ' + a, '2; markdown heading'); | |
|
15 | 19 | this.trigger_keydown('3'); |
|
16 |
this.test.assertEquals(this.get_cell( |
|
|
20 | this.test.assertEquals(this.get_cell(index).cell_type, 'markdown', '3; cell is markdown'); | |
|
21 | this.test.assertEquals(this.get_cell_text(index), '### ' + a, '3; markdown heading'); | |
|
17 | 22 | this.trigger_keydown('4'); |
|
18 |
this.test.assertEquals(this.get_cell( |
|
|
23 | this.test.assertEquals(this.get_cell(index).cell_type, 'markdown', '4; cell is markdown'); | |
|
24 | this.test.assertEquals(this.get_cell_text(index), '#### ' + a, '4; markdown heading'); | |
|
19 | 25 | this.trigger_keydown('5'); |
|
20 |
this.test.assertEquals(this.get_cell( |
|
|
26 | this.test.assertEquals(this.get_cell(index).cell_type, 'markdown', '5; cell is markdown'); | |
|
27 | this.test.assertEquals(this.get_cell_text(index), '##### ' + a, '5; markdown heading'); | |
|
21 | 28 | this.trigger_keydown('6'); |
|
22 |
this.test.assertEquals(this.get_cell( |
|
|
29 | this.test.assertEquals(this.get_cell(index).cell_type, 'markdown', '6; cell is markdown'); | |
|
30 | this.test.assertEquals(this.get_cell_text(index), '###### ' + a, '6; markdown heading'); | |
|
23 | 31 | this.trigger_keydown('m'); |
|
24 |
this.test.assertEquals(this.get_cell( |
|
|
32 | this.test.assertEquals(this.get_cell(index).cell_type, 'markdown', 'm; cell is markdown'); | |
|
33 | this.test.assertEquals(this.get_cell_text(index), '###### ' + a, 'm; still markdown heading'); | |
|
25 | 34 | this.trigger_keydown('y'); |
|
26 |
this.test.assertEquals(this.get_cell( |
|
|
35 | this.test.assertEquals(this.get_cell(index).cell_type, 'code', 'y; cell is code'); | |
|
36 | this.test.assertEquals(this.get_cell_text(index), '###### ' + a, 'y; still has hashes'); | |
|
37 | this.trigger_keydown('1'); | |
|
38 | this.test.assertEquals(this.get_cell(index).cell_type, 'markdown', '1; cell is markdown'); | |
|
39 | this.test.assertEquals(this.get_cell_text(index), '# ' + a, '1; markdown heading'); | |
|
27 | 40 | }); |
|
28 | 41 | }); No newline at end of file |
@@ -1,47 +1,62 b'' | |||
|
1 | 1 | // |
|
2 | 2 | // Test that a Markdown cell is rendered to HTML. |
|
3 | 3 | // |
|
4 | 4 | casper.notebook_test(function () { |
|
5 | 5 | // Test JavaScript models. |
|
6 | 6 | var output = this.evaluate(function () { |
|
7 | 7 | IPython.notebook.to_markdown(); |
|
8 | 8 | var cell = IPython.notebook.get_selected_cell(); |
|
9 | 9 | cell.set_text('# Foo'); |
|
10 | 10 | cell.render(); |
|
11 | 11 | return cell.get_rendered(); |
|
12 | 12 | }); |
|
13 |
this.test.assertEquals(output.trim(), '<h1 id=\" |
|
|
13 | this.test.assertEquals(output.trim(), '<h1 id=\"Foo\">Foo<a class=\"anchor-link\" href=\"#Foo\">¶</a></h1>', 'Markdown JS API works.'); | |
|
14 | 14 | |
|
15 | 15 | // Test menubar entries. |
|
16 | 16 | output = this.evaluate(function () { |
|
17 | 17 | $('#to_code').mouseenter().click(); |
|
18 | 18 | $('#to_markdown').mouseenter().click(); |
|
19 | 19 | var cell = IPython.notebook.get_selected_cell(); |
|
20 |
cell.set_text(' |
|
|
20 | cell.set_text('**Bar**'); | |
|
21 | 21 | $('#run_cell').mouseenter().click(); |
|
22 | 22 | return cell.get_rendered(); |
|
23 | 23 | }); |
|
24 |
this.test.assertEquals(output.trim(), '< |
|
|
24 | this.test.assertEquals(output.trim(), '<p><strong>Bar</strong></p>', 'Markdown menubar items work.'); | |
|
25 | 25 | |
|
26 | 26 | // Test toolbar buttons. |
|
27 | 27 | output = this.evaluate(function () { |
|
28 | 28 | $('#cell_type').val('code').change(); |
|
29 | 29 | $('#cell_type').val('markdown').change(); |
|
30 | 30 | var cell = IPython.notebook.get_selected_cell(); |
|
31 |
cell.set_text(' |
|
|
31 | cell.set_text('*Baz*'); | |
|
32 | 32 | $('#run_b').click(); |
|
33 | 33 | return cell.get_rendered(); |
|
34 | 34 | }); |
|
35 |
this.test.assertEquals(output.trim(), '< |
|
|
35 | this.test.assertEquals(output.trim(), '<p><em>Baz</em></p>', 'Markdown toolbar items work.'); | |
|
36 | 36 | |
|
37 | // Test JavaScript models. | |
|
38 | var output = this.evaluate(function () { | |
|
37 | // Test markdown headings | |
|
39 | 38 | |
|
39 | var text = 'multi\nline'; | |
|
40 | ||
|
41 | this.evaluate(function (text) { | |
|
40 | 42 | var cell = IPython.notebook.insert_cell_at_index('markdown', 0); |
|
41 |
cell.set_text( |
|
|
42 | cell.render(); | |
|
43 | return cell.get_rendered(); | |
|
44 | }); | |
|
45 | this.test.assertEquals(output.trim(), '<h1 id=\"qux\">Qux</h1>', 'Markdown JS API works.'); | |
|
43 | cell.set_text(text); | |
|
44 | }, {text: text}); | |
|
45 | ||
|
46 | var set_level = function (level) { | |
|
47 | return casper.evaluate(function (level) { | |
|
48 | var cell = IPython.notebook.get_cell(0); | |
|
49 | cell.set_heading_level(level); | |
|
50 | return cell.get_text(); | |
|
51 | }, {level: level}); | |
|
52 | }; | |
|
46 | 53 | |
|
54 | var level_text; | |
|
55 | var levels = [ 1, 2, 3, 4, 5, 6, 2, 1 ]; | |
|
56 | for (var idx=0; idx < levels.length; idx++) { | |
|
57 | var level = levels[idx]; | |
|
58 | level_text = set_level(level); | |
|
59 | hashes = new Array(level + 1).join('#'); | |
|
60 | this.test.assertEquals(level_text, hashes + ' ' + text, 'markdown set_heading_level ' + level); | |
|
61 | } | |
|
47 | 62 | }); |
@@ -1,263 +1,262 b'' | |||
|
1 | 1 | { |
|
2 | 2 | "cells": [ |
|
3 | 3 | { |
|
4 |
"cell_type": " |
|
|
5 | "level": 1, | |
|
4 | "cell_type": "markdown", | |
|
6 | 5 | "metadata": {}, |
|
7 | 6 | "source": [ |
|
8 | "NumPy and Matplotlib examples" | |
|
7 | "# NumPy and Matplotlib examples" | |
|
9 | 8 | ] |
|
10 | 9 | }, |
|
11 | 10 | { |
|
12 | 11 | "cell_type": "markdown", |
|
13 | 12 | "metadata": {}, |
|
14 | 13 | "source": [ |
|
15 | 14 | "First import NumPy and Matplotlib:" |
|
16 | 15 | ] |
|
17 | 16 | }, |
|
18 | 17 | { |
|
19 | 18 | "cell_type": "code", |
|
20 | 19 | "execution_count": 1, |
|
21 | 20 | "metadata": { |
|
22 | 21 | "collapsed": false |
|
23 | 22 | }, |
|
24 | 23 | "outputs": [ |
|
25 | 24 | { |
|
26 | 25 | "name": "stdout", |
|
27 | 26 | "output_type": "stream", |
|
28 | 27 | "text": [ |
|
29 | 28 | "\n", |
|
30 | 29 | "Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.kernel.zmq.pylab.backend_inline].\n", |
|
31 | 30 | "For more information, type 'help(pylab)'.\n" |
|
32 | 31 | ] |
|
33 | 32 | } |
|
34 | 33 | ], |
|
35 | 34 | "source": [ |
|
36 | 35 | "%pylab inline" |
|
37 | 36 | ] |
|
38 | 37 | }, |
|
39 | 38 | { |
|
40 | 39 | "cell_type": "code", |
|
41 | 40 | "execution_count": 2, |
|
42 | 41 | "metadata": { |
|
43 | 42 | "collapsed": false |
|
44 | 43 | }, |
|
45 | 44 | "outputs": [], |
|
46 | 45 | "source": [ |
|
47 | 46 | "import numpy as np" |
|
48 | 47 | ] |
|
49 | 48 | }, |
|
50 | 49 | { |
|
51 | 50 | "cell_type": "markdown", |
|
52 | 51 | "metadata": {}, |
|
53 | 52 | "source": [ |
|
54 | 53 | "Now we show some very basic examples of how they can be used." |
|
55 | 54 | ] |
|
56 | 55 | }, |
|
57 | 56 | { |
|
58 | 57 | "cell_type": "code", |
|
59 | 58 | "execution_count": 6, |
|
60 | 59 | "metadata": { |
|
61 | 60 | "collapsed": false |
|
62 | 61 | }, |
|
63 | 62 | "outputs": [], |
|
64 | 63 | "source": [ |
|
65 | 64 | "a = np.random.uniform(size=(100,100))" |
|
66 | 65 | ] |
|
67 | 66 | }, |
|
68 | 67 | { |
|
69 | 68 | "cell_type": "code", |
|
70 | 69 | "execution_count": 7, |
|
71 | 70 | "metadata": { |
|
72 | 71 | "collapsed": false |
|
73 | 72 | }, |
|
74 | 73 | "outputs": [ |
|
75 | 74 | { |
|
76 | 75 | "data": { |
|
77 | 76 | "text/plain": [ |
|
78 | 77 | "(100, 100)" |
|
79 | 78 | ] |
|
80 | 79 | }, |
|
81 | 80 | "execution_count": 7, |
|
82 | 81 | "metadata": {}, |
|
83 | 82 | "output_type": "execute_result" |
|
84 | 83 | } |
|
85 | 84 | ], |
|
86 | 85 | "source": [ |
|
87 | 86 | "a.shape" |
|
88 | 87 | ] |
|
89 | 88 | }, |
|
90 | 89 | { |
|
91 | 90 | "cell_type": "code", |
|
92 | 91 | "execution_count": 8, |
|
93 | 92 | "metadata": { |
|
94 | 93 | "collapsed": false |
|
95 | 94 | }, |
|
96 | 95 | "outputs": [], |
|
97 | 96 | "source": [ |
|
98 | 97 | "evs = np.linalg.eigvals(a)" |
|
99 | 98 | ] |
|
100 | 99 | }, |
|
101 | 100 | { |
|
102 | 101 | "cell_type": "code", |
|
103 | 102 | "execution_count": 10, |
|
104 | 103 | "metadata": { |
|
105 | 104 | "collapsed": false |
|
106 | 105 | }, |
|
107 | 106 | "outputs": [ |
|
108 | 107 | { |
|
109 | 108 | "data": { |
|
110 | 109 | "text/plain": [ |
|
111 | 110 | "(100,)" |
|
112 | 111 | ] |
|
113 | 112 | }, |
|
114 | 113 | "execution_count": 10, |
|
115 | 114 | "metadata": {}, |
|
116 | 115 | "output_type": "execute_result" |
|
117 | 116 | } |
|
118 | 117 | ], |
|
119 | 118 | "source": [ |
|
120 | 119 | "evs.shape" |
|
121 | 120 | ] |
|
122 | 121 | }, |
|
123 | 122 | { |
|
124 | 123 | "cell_type": "markdown", |
|
125 | 124 | "metadata": {}, |
|
126 | 125 | "source": [ |
|
127 | 126 | "Here is a cell that has both text and PNG output:" |
|
128 | 127 | ] |
|
129 | 128 | }, |
|
130 | 129 | { |
|
131 | 130 | "cell_type": "code", |
|
132 | 131 | "execution_count": 14, |
|
133 | 132 | "metadata": { |
|
134 | 133 | "collapsed": false |
|
135 | 134 | }, |
|
136 | 135 | "outputs": [ |
|
137 | 136 | { |
|
138 | 137 | "data": { |
|
139 | 138 | "text/plain": [ |
|
140 | 139 | "(array([95, 4, 0, 0, 0, 0, 0, 0, 0, 1]),\n", |
|
141 | 140 | " array([ -2.93566063, 2.35937011, 7.65440086, 12.9494316 ,\n", |
|
142 | 141 | " 18.24446235, 23.53949309, 28.83452384, 34.12955458,\n", |
|
143 | 142 | " 39.42458533, 44.71961607, 50.01464682]),\n", |
|
144 | 143 | " <a list of 10 Patch objects>)" |
|
145 | 144 | ] |
|
146 | 145 | }, |
|
147 | 146 | "execution_count": 14, |
|
148 | 147 | "metadata": {}, |
|
149 | 148 | "output_type": "execute_result" |
|
150 | 149 | }, |
|
151 | 150 | { |
|
152 | 151 | "data": { |
|
153 | 152 | "image/png": [ |
|
154 | 153 | "iVBORw0KGgoAAAANSUhEUgAAAXgAAAD9CAYAAAC2l2x5AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\n", |
|
155 | 154 | "AAALEgAACxIB0t1+/AAAEhdJREFUeJzt3X1olfX/x/HXtVbT8CZDmsK6KmrubEu3U2xnZOpxLBnG\n", |
|
156 | 155 | "OqsIE7RoE3QRZkT/yEAjcIh/LIs6i/BEGSU1CkxT0+pkFp1zMmsxZ5uUTIXoxm95lmdlef3+8Nep\n", |
|
157 | 156 | "dbtz7exs16fnAw7sXNs5n/c14nmurl3naDmO4wgAYJy8sR4AADA6CDwAGIrAA4ChCDwAGIrAA4Ch\n", |
|
158 | 157 | "CDwAGOofA9/U1KTCwkLNnj07vS2ZTCoUCsm2bTU2NmpgYCD9vccee0zFxcUqKyvTgQMHRm9qAMC/\n", |
|
159 | 158 | "+sfA33PPPdq9e/eQbeFwWLZtq6+vT0VFRero6JAkffXVV3ryySf15ptvKhwOa/Xq1aM3NQDgX/1j\n", |
|
160 | 159 | "4OfNm6dp06YN2RaPx9Xc3KyCggI1NTUpFotJkmKxmOrr62XbthYsWCDHcZRMJkdvcgDAP8r4HHwi\n", |
|
161 | 160 | "kZDP55Mk+Xw+xeNxSecDX1pamv65kpKS9PcAALmXn+kDMvlkA8uyhrUNAPDvMv1kmYyP4KuqqtTT\n", |
|
162 | 161 | "0yNJ6unpUVVVlSQpEAjo8OHD6Z87cuRI+nt/NaRXb+vWrRvzGZh/7Odgfu/dvDy747j7yLCMAx8I\n", |
|
163 | 162 | "BBSJRJRKpRSJRFRTUyNJqq6u1p49e9Tf369oNKq8vDxNnjzZ1VAAgJH7x8AvXbpUN9xwg3p7e3X5\n", |
|
164 | 163 | "5ZfrmWeeUUtLi/r7+1VSUqKTJ09q1apVkqTCwkK1tLSotrZW9957rzZv3pyTHQAA/DXLcXvs73ZB\n", |
|
165 | 164 | "y3L9vxvjQTQaVTAYHOsxXGP+scX8Y8fLs0vu2kngAcAD3LSTjyoAAEMReAAwFIEHAEMReAAwFIEH\n", |
|
166 | 165 | "AEP9ZwM/Zcqlsixr1G9Tplw61rsK4D/qP3uZ5PnPxMnFHONjfwF4G5dJAgDSCDwAGIrAA4ChCDwA\n", |
|
167 | 166 | "GIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrA\n", |
|
168 | 167 | "A4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChXAf+6aef1g03\n", |
|
169 | 168 | "3KDrr79ea9askSQlk0mFQiHZtq3GxkYNDAxkbVAAQGZcBf7UqVPasGGD9u7dq0Qiod7eXu3Zs0fh\n", |
|
170 | 169 | "cFi2bauvr09FRUXq6OjI9rwAgGFyFfiJEyfKcRx9//33SqVSOnPmjC655BLF43E1NzeroKBATU1N\n", |
|
171 | 170 | "isVi2Z4XADBMrgMfDod15ZVXasaMGZo7d64CgYASiYR8Pp8kyefzKR6PZ3VYAMDw5bt50Ndff62W\n", |
|
172 | 171 | "lhYdPnxY06ZN0x133KEdO3bIcZxhPX79+vXpr4PBoILBoJsxAMBY0WhU0Wh0RM9hOcOt8u/s3LlT\n", |
|
173 | 172 | "W7du1bZt2yRJ4XBYx44d09GjR9Xa2iq/36+DBw+qra1NnZ2dQxe0rGG/EIwmy7Ik5WKO8bG/ALzN\n", |
|
174 | 173 | "TTtdnaKZN2+ePvzwQ506dUo//vijdu3apUWLFikQCCgSiSiVSikSiaimpsbN0wMAssBV4KdMmaLW\n", |
|
175 | 174 | "1lbdeuutuvHGG1VRUaGFCxeqpaVF/f39Kikp0cmTJ7Vq1apszwsAGCZXp2hGtCCnaAAgYzk7RQMA\n", |
|
176 | 175 | "GP8IPAAYisADgKEIPAAYisADgKEIPAAYisADgKEIPAAYisADgKEIPAAYisADgKEIPAAYisADgKEI\n", |
|
177 | 176 | "PAAYisADgKEIPAAYisADgKEIPAAYisADgKEIPAAYisADgKEIPAAYisADgKEIPAAYisADgKEIPAAY\n", |
|
178 | 177 | "isADgKEIPAAYisADgKEIPAAYisADgKEIPAAYisADgKEIPAAYisADgKEIPAAYynXgf/jhB919992a\n", |
|
179 | 178 | "NWuWysrKFIvFlEwmFQqFZNu2GhsbNTAwkM1ZAQAZcB34devWybZtdXV1qaurSz6fT+FwWLZtq6+v\n", |
|
180 | 179 | "T0VFRero6MjmrACADLgO/L59+7R27VpNmDBB+fn5mjp1quLxuJqbm1VQUKCmpibFYrFszgoAyICr\n", |
|
181 | 180 | "wJ84cUKDg4NqaWlRIBDQxo0blUqllEgk5PP5JEk+n0/xeDyrwwIAhi/fzYMGBwfV29urTZs2qa6u\n", |
|
182 | 181 | "TitXrtRLL70kx3GG9fj169envw4GgwoGg27GAABjRaNRRaPRET2H5Qy3yn9QWlqqnp4eSdKuXbv0\n", |
|
183 | 182 | "3HPP6aefflJra6v8fr8OHjyotrY2dXZ2Dl3Qsob9QjCaLMuSlIs5xsf+AvA2N+10fQ6+uLhYsVhM\n", |
|
184 | 183 | "586d086dO1VXV6dAIKBIJKJUKqVIJKKamhq3Tw8AGCHXR/C9vb266667NDg4qLq6Oj388MM6d+6c\n", |
|
185 | 184 | "li1bpkOHDum6667T888/r0mTJg1dkCN4AMiYm3a6DrxbBB4AMpfTUzQAgPGNwAOAoQg8ABiKwAOA\n", |
|
186 | 185 | "oQg8ABiKwAOAoQg8ABiKwAOAoQg8ABiKwAOAoQg8ABiKwAOAoQg8ABiKwAOAoQg8ABiKwAOAoQg8\n", |
|
187 | 186 | "ABiKwAOAoQg8ABiKwAOAoQg8ABiKwAOAoQg8ABiKwAOAoQg8ABiKwAOAoQg8ABiKwAOAoQg8ABiK\n", |
|
188 | 187 | "wAOAoQg8ABiKwAOAoQg8ABiKwAOAoQg8ABiKwAOAoVwH/pdffpHf71dDQ4MkKZlMKhQKybZtNTY2\n", |
|
189 | 188 | "amBgIGtDAgAy5zrwmzdvVllZmSzLkiSFw2HZtq2+vj4VFRWpo6Mja0MCADLnKvAnTpzQ66+/rhUr\n", |
|
190 | 189 | "VshxHElSPB5Xc3OzCgoK1NTUpFgsltVBAQCZcRX4Bx54QJs2bVJe3m8PTyQS8vl8kiSfz6d4PJ6d\n", |
|
191 | 190 | "CQEAruRn+oAdO3bosssuk9/vVzQaTW//9Uh+ONavX5/+OhgMKhgMZjoGABgtGo0OaawblpNJmSWt\n", |
|
192 | 191 | "XbtWW7duVX5+vgYHB3X69GnddtttOnPmjFpbW+X3+3Xw4EG1tbWps7PzzwtaVkYvBqPl/N8OcjHH\n", |
|
193 | 192 | "+NhfAN7mpp0Zn6LZsGGDjh8/ri+++ELbtm1TbW2ttm7dqkAgoEgkolQqpUgkopqamkyfGgCQRSO+\n", |
|
194 | 193 | "Dv7Xq2haWlrU39+vkpISnTx5UqtWrRrxcAAA9zI+RTPiBTlFAwAZy8kpGgCANxB4ADAUgQcAQxF4\n", |
|
195 | 194 | "ADAUgQcAQxF4ADAUgQcAQxF4ADAUgQcAQxF4ADAUgQcAQxF4ADAUgQcAQxF4ADAUgQcAQxF4ADAU\n", |
|
196 | 195 | "gQcAQxF4ADAUgQcAQxF4ADAUgQcAQxF4ADAUgQcAQxF4ADAUgQcAQxF4ADAUgQcAQxF4ADAUgQcA\n", |
|
197 | 196 | "QxF4ADAUgQcAQxF4ADAUgQcAQxF4ADAUgQcAQ7kK/PHjx7Vw4UKVl5crGAzqhRdekCQlk0mFQiHZ\n", |
|
198 | 197 | "tq3GxkYNDAxkdVgAwPC5CvyFF16o9vZ2dXd3q7OzU62trUomkwqHw7JtW319fSoqKlJHR0e25wUA\n", |
|
199 | 198 | "DJOrwM+YMUOVlZWSpOnTp6u8vFyJRELxeFzNzc0qKChQU1OTYrFYVocFAAzfiM/BHz16VN3d3aqu\n", |
|
200 | 199 | "rlYikZDP55Mk+Xw+xePxEQ8IAHAnfyQPTiaTWrJkidrb2zVp0iQ5jjOsx61fvz79dTAYVDAYHMkY\n", |
|
201 | 200 | "AGCcaDSqaDQ6ouewnOFW+Q/Onj2rm2++WYsXL9aaNWskSbfffrtaW1vl9/t18OBBtbW1qbOzc+iC\n", |
|
202 | 201 | "ljXsF4LRZFmWpFzMMT72F4C3uWmnq1M0juOoublZ1157bTrukhQIBBSJRJRKpRSJRFRTU+Pm6QEA\n", |
|
203 | 202 | "WeDqCP7AgQOaP3++5syZ8/9HwlJbW5vmzp2rZcuW6dChQ7ruuuv0/PPPa9KkSUMX5AgeADLmpp2u\n", |
|
204 | 203 | "T9G4ReABIHM5O0UDABj/CDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrA\n", |
|
205 | 204 | "A4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4Ch\n", |
|
206 | 205 | "CDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4Ch8sd6APPly7KsUV1h8uRpOn361Kiu\n", |
|
207 | 206 | "AcB7LMdxnJwuaFnK8ZJ/O4eUizlysc74+J0CGD1u2skpGgAwFIEHAEMReAAwVNYDv3//fpWWlqq4\n", |
|
208 | 207 | "uFiPP/54tp9+HIiO9QAjEo1Gx3qEEWH+seXl+b08u1tZD/z999+vp556Svv27dMTTzyhb775JttL\n", |
|
209 | 208 | "jLHoWA8wIl7/j5z5x5aX5/fy7G5lNfDff/+9JGn+/Pm64oortGjRIsVisWwuAcBAU6ZcKsuyRvXW\n", |
|
210 | 209 | "1rZxrHcz57Ia+EQiIZ/Pl75fVlamDz74IJtLADBQMvk/nb+cePRuP/00mLsdGieyeh38vn37tGXL\n", |
|
211 | 210 | "Fr344ouSpI6ODp08eVKPPPLIbwuO8pt+AMBUmeY6q+9kraqq0kMPPZS+393drfr6+iE/wxtyACA3\n", |
|
212 | 211 | "snqKZurUqZLOX0lz7Ngx7d27V4FAIJtLAACGKeufRfPoo49q5cqVOnv2rFavXq3p06dnewkAwDBk\n", |
|
213 | 212 | "/TLJBQsWqKenR0ePHtXq1aslSS+//LLKy8t1wQUX6KOPPhry84899piKi4tVVlamAwcOZHucrPHa\n", |
|
214 | 213 | "9f1NTU0qLCzU7Nmz09uSyaRCoZBs21ZjY6MGBgbGcMJ/dvz4cS1cuFDl5eUKBoN64YUXJHlnHwYH\n", |
|
215 | 214 | "BxUIBFRZWamamhq1t7dL8s78kvTLL7/I7/eroaFBkrdmv/LKKzVnzhz5/X5VV1dL8tb8P/zwg+6+\n", |
|
216 | 215 | "+27NmjVLZWVlisVirubPyTtZZ8+erVdffVXz588fsv2rr77Sk08+qTfffFPhcDj9gjAeee36/nvu\n", |
|
217 | 216 | "uUe7d+8esi0cDsu2bfX19amoqEgdHR1jNN2/u/DCC9Xe3q7u7m51dnaqtbVVyWTSM/swYcIEvf32\n", |
|
218 | 217 | "2/r444/1zjvvaMuWLerr6/PM/JK0efNmlZWVpS+M8NLslmUpGo3q0KFDisfjkrw1/7p162Tbtrq6\n", |
|
219 | 218 | "utTV1SWfz+dq/pwE3ufzadasWX/aHovFVF9fL9u2tWDBAjmOo2QymYuRMuLF6/vnzZunadOmDdkW\n", |
|
220 | 219 | "j8fV3NysgoICNTU1jet9mDFjhiorKyVJ06dPV3l5uRKJhKf24eKLL5YkDQwM6Oeff1ZBQYFn5j9x\n", |
|
221 | 220 | "4oRef/11rVixIn1hhFdm/9UfL+jw0vz79u3T2rVrNWHCBOXn52vq1Kmu5h/Tz6KJx+MqLS1N3y8p\n", |
|
222 | 221 | "KUm/2o4nplzf//v98Pl84/J3/VeOHj2q7u5uVVdXe2ofzp07p4qKChUWFuq+++6Tbduemf+BBx7Q\n", |
|
223 | 222 | "pk2blJf3WyK8Mrt0/gi+trZWjY2N2r59uyTvzH/ixAkNDg6qpaVFgUBAGzduVCqVcjV/1v7IetNN\n", |
|
224 | 223 | "N+nLL7/80/YNGzakz+H90V9dMsl18qPHi5eoJpNJLVmyRO3t7Zo0aZKn9iEvL0+ffPKJjh07psWL\n", |
|
225 | 224 | "F2vu3LmemH/Hjh267LLL5Pf7h7y93wuz/+q9997TzJkz1dPTo4aGBlVXV3tm/sHBQfX29mrTpk2q\n", |
|
226 | 225 | "q6vTypUr9dJLL7maP2tH8Hv37tWnn376p9vfxV2SAoGADh8+nL5/5MgRVVVVZWukrKmqqtKRI0fS\n", |
|
227 | 226 | "97u7u1VTUzOGE7lTVVWlnp4eSVJPT8+4/F3/3tmzZ3X77bdr+fLlCoVCkry3D9L5P/gtXrxYsVjM\n", |
|
228 | 227 | "E/O///772r59u6666iotXbpUb731lpYvX+6J2X81c+ZMSVJpaaluueUWvfbaa56Z/5prrlFJSYka\n", |
|
229 | 228 | "Gho0ceJELV26VLt373Y1f85P0fz+Vai6ulp79uxRf3+/otGo8vLyNHny5FyP9K9Mub4/EAgoEoko\n", |
|
230 | 229 | "lUopEomM6xcpx3HU3Nysa6+9VmvWrElv98o+fPPNN/ruu+8kSd9++63eeOMNhUIhT8y/YcMGHT9+\n", |
|
231 | 230 | "XF988YW2bdum2tpabd261ROzS9KZM2fSf8v7+uuvtWfPHtXX13tmfkkqLi5WLBbTuXPntHPnTtXV\n", |
|
232 | 231 | "1bmb38mBV155xSkqKnImTJjgFBYWOvX19envPfroo87VV1/tlJaWOvv378/FOK5Eo1HH5/M5V199\n", |
|
233 | 232 | "tbN58+axHudf3Xnnnc7MmTOdiy66yCkqKnIikYhz+vRp55ZbbnEuv/xyJxQKOclkcqzH/Fvvvvuu\n", |
|
234 | 233 | "Y1mWU1FR4VRWVjqVlZXOrl27PLMPXV1djt/vd+bMmeMsWrTIefbZZx3HcTwz/6+i0ajT0NDgOI53\n", |
|
235 | 234 | "Zv/888+diooKp6KiwqmtrXW2bNniOI535nccx/nss8+cQCDgVFRUOA8++KAzMDDgav6c/5usAIDc\n", |
|
236 | 235 | "4F90AgBDEXgAMBSBBwBDEXgAMBSBBwBDEXgAMNT/AQKseNIf7mhWAAAAAElFTkSuQmCC\n" |
|
237 | 236 | ], |
|
238 | 237 | "text/plain": [ |
|
239 | 238 | "<matplotlib.figure.Figure at 0x108c8f1d0>" |
|
240 | 239 | ] |
|
241 | 240 | }, |
|
242 | 241 | "metadata": {}, |
|
243 | 242 | "output_type": "display_data" |
|
244 | 243 | } |
|
245 | 244 | ], |
|
246 | 245 | "source": [ |
|
247 | 246 | "hist(evs.real)" |
|
248 | 247 | ] |
|
249 | 248 | }, |
|
250 | 249 | { |
|
251 | 250 | "cell_type": "code", |
|
252 | 251 | "execution_count": null, |
|
253 | 252 | "metadata": { |
|
254 | 253 | "collapsed": false |
|
255 | 254 | }, |
|
256 | 255 | "outputs": [], |
|
257 | 256 | "source": [] |
|
258 | 257 | } |
|
259 | 258 | ], |
|
260 | 259 | "metadata": {}, |
|
261 | 260 | "nbformat": 4, |
|
262 | 261 | "nbformat_minor": 0 |
|
263 | 262 | } No newline at end of file |
@@ -1,38 +1,39 b'' | |||
|
1 | 1 | """Tests for notebook.py""" |
|
2 | 2 | |
|
3 | 3 | # Copyright (c) IPython Development Team. |
|
4 | 4 | # Distributed under the terms of the Modified BSD License. |
|
5 | 5 | |
|
6 | 6 | import json |
|
7 | 7 | |
|
8 | 8 | from .base import ExportersTestsBase |
|
9 | 9 | from ..notebook import NotebookExporter |
|
10 | 10 | |
|
11 | from IPython.nbformat.current import validate | |
|
11 | 12 | from IPython.testing.tools import assert_big_text_equal |
|
12 | 13 | |
|
13 | 14 | class TestNotebookExporter(ExportersTestsBase): |
|
14 | 15 | """Contains test functions for notebook.py""" |
|
15 | 16 | |
|
16 | 17 | exporter_class = NotebookExporter |
|
17 | 18 | |
|
18 | 19 | def test_export(self): |
|
19 | 20 | """ |
|
20 | 21 | Does the NotebookExporter return the file unchanged? |
|
21 | 22 | """ |
|
22 | 23 | with open(self._get_notebook()) as f: |
|
23 | 24 | file_contents = f.read() |
|
24 | 25 | (output, resources) = self.exporter_class().from_filename(self._get_notebook()) |
|
25 | 26 | assert len(output) > 0 |
|
26 | 27 | assert_big_text_equal(output, file_contents) |
|
27 | 28 | |
|
28 | 29 | def test_downgrade_3(self): |
|
29 | 30 | exporter = self.exporter_class(nbformat_version=3) |
|
30 | 31 | (output, resources) = exporter.from_filename(self._get_notebook()) |
|
31 | 32 | nb = json.loads(output) |
|
32 | self.assertEqual(nb['nbformat'], 3) | |
|
33 | validate(nb) | |
|
33 | 34 | |
|
34 | 35 | def test_downgrade_2(self): |
|
35 | 36 | exporter = self.exporter_class(nbformat_version=2) |
|
36 | 37 | (output, resources) = exporter.from_filename(self._get_notebook()) |
|
37 | 38 | nb = json.loads(output) |
|
38 | 39 | self.assertEqual(nb['nbformat'], 2) |
@@ -1,231 +1,236 b'' | |||
|
1 | 1 | """Markdown filters |
|
2 | 2 | |
|
3 | 3 | This file contains a collection of utility filters for dealing with |
|
4 | 4 | markdown within Jinja templates. |
|
5 | 5 | """ |
|
6 | 6 | # Copyright (c) IPython Development Team. |
|
7 | 7 | # Distributed under the terms of the Modified BSD License. |
|
8 | 8 | |
|
9 | 9 | from __future__ import print_function |
|
10 | 10 | |
|
11 | 11 | # Stdlib imports |
|
12 | 12 | import os |
|
13 | 13 | import subprocess |
|
14 | 14 | from io import TextIOWrapper, BytesIO |
|
15 | 15 | import re |
|
16 | 16 | |
|
17 | 17 | import mistune |
|
18 | 18 | from pygments import highlight |
|
19 | 19 | from pygments.lexers import get_lexer_by_name |
|
20 | 20 | from pygments.formatters import HtmlFormatter |
|
21 | 21 | from pygments.util import ClassNotFound |
|
22 | 22 | |
|
23 | 23 | # IPython imports |
|
24 | from IPython.nbconvert.filters.strings import add_anchor | |
|
24 | 25 | from IPython.nbconvert.utils.pandoc import pandoc |
|
25 | 26 | from IPython.nbconvert.utils.exceptions import ConversionException |
|
26 | 27 | from IPython.utils.decorators import undoc |
|
27 | 28 | from IPython.utils.process import get_output_error_code |
|
28 | 29 | from IPython.utils.py3compat import cast_bytes |
|
29 | 30 | from IPython.utils.version import check_version |
|
30 | 31 | |
|
31 | 32 | |
|
32 | 33 | marked = os.path.join(os.path.dirname(__file__), "marked.js") |
|
33 | 34 | _node = None |
|
34 | 35 | |
|
35 | 36 | __all__ = [ |
|
36 | 37 | 'markdown2html', |
|
37 | 38 | 'markdown2html_pandoc', |
|
38 | 39 | 'markdown2html_marked', |
|
39 | 40 | 'markdown2html_mistune', |
|
40 | 41 | 'markdown2latex', |
|
41 | 42 | 'markdown2rst', |
|
42 | 43 | ] |
|
43 | 44 | |
|
44 | 45 | class NodeJSMissing(ConversionException): |
|
45 | 46 | """Exception raised when node.js is missing.""" |
|
46 | 47 | pass |
|
47 | 48 | |
|
48 | 49 | def markdown2latex(source, markup='markdown', extra_args=None): |
|
49 | 50 | """Convert a markdown string to LaTeX via pandoc. |
|
50 | 51 | |
|
51 | 52 | This function will raise an error if pandoc is not installed. |
|
52 | 53 | Any error messages generated by pandoc are printed to stderr. |
|
53 | 54 | |
|
54 | 55 | Parameters |
|
55 | 56 | ---------- |
|
56 | 57 | source : string |
|
57 | 58 | Input string, assumed to be valid markdown. |
|
58 | 59 | markup : string |
|
59 | 60 | Markup used by pandoc's reader |
|
60 | 61 | default : pandoc extended markdown |
|
61 | 62 | (see http://johnmacfarlane.net/pandoc/README.html#pandocs-markdown) |
|
62 | 63 | |
|
63 | 64 | Returns |
|
64 | 65 | ------- |
|
65 | 66 | out : string |
|
66 | 67 | Output as returned by pandoc. |
|
67 | 68 | """ |
|
68 | 69 | return pandoc(source, markup, 'latex', extra_args=extra_args) |
|
69 | 70 | |
|
70 | 71 | |
|
71 | 72 | @undoc |
|
72 | 73 | class MathBlockGrammar(mistune.BlockGrammar): |
|
73 | 74 | block_math = re.compile("^\$\$(.*?)\$\$", re.DOTALL) |
|
74 | 75 | latex_environment = re.compile(r"^\\begin\{([a-z]*\*?)\}(.*?)\\end\{\1\}", |
|
75 | 76 | re.DOTALL) |
|
76 | 77 | |
|
77 | 78 | @undoc |
|
78 | 79 | class MathBlockLexer(mistune.BlockLexer): |
|
79 | 80 | default_features = ['block_math', 'latex_environment'] + mistune.BlockLexer.default_features |
|
80 | 81 | |
|
81 | 82 | def __init__(self, rules=None, **kwargs): |
|
82 | 83 | if rules is None: |
|
83 | 84 | rules = MathBlockGrammar() |
|
84 | 85 | super(MathBlockLexer, self).__init__(rules, **kwargs) |
|
85 | 86 | |
|
86 | 87 | def parse_block_math(self, m): |
|
87 | 88 | """Parse a $$math$$ block""" |
|
88 | 89 | self.tokens.append({ |
|
89 | 90 | 'type': 'block_math', |
|
90 | 91 | 'text': m.group(1) |
|
91 | 92 | }) |
|
92 | 93 | |
|
93 | 94 | def parse_latex_environment(self, m): |
|
94 | 95 | self.tokens.append({ |
|
95 | 96 | 'type': 'latex_environment', |
|
96 | 97 | 'name': m.group(1), |
|
97 | 98 | 'text': m.group(2) |
|
98 | 99 | }) |
|
99 | 100 | |
|
100 | 101 | @undoc |
|
101 | 102 | class MathInlineGrammar(mistune.InlineGrammar): |
|
102 | 103 | math = re.compile("^\$(.+?)\$") |
|
103 | 104 | text = re.compile(r'^[\s\S]+?(?=[\\<!\[_*`~$]|https?://| {2,}\n|$)') |
|
104 | 105 | |
|
105 | 106 | @undoc |
|
106 | 107 | class MathInlineLexer(mistune.InlineLexer): |
|
107 | 108 | default_features = ['math'] + mistune.InlineLexer.default_features |
|
108 | 109 | |
|
109 | 110 | def __init__(self, renderer, rules=None, **kwargs): |
|
110 | 111 | if rules is None: |
|
111 | 112 | rules = MathInlineGrammar() |
|
112 | 113 | super(MathInlineLexer, self).__init__(renderer, rules, **kwargs) |
|
113 | 114 | |
|
114 | 115 | def output_math(self, m): |
|
115 | 116 | return self.renderer.inline_math(m.group(1)) |
|
116 | 117 | |
|
117 | 118 | @undoc |
|
118 | 119 | class MarkdownWithMath(mistune.Markdown): |
|
119 | 120 | def __init__(self, renderer, **kwargs): |
|
120 | 121 | if 'inline' not in kwargs: |
|
121 | 122 | kwargs['inline'] = MathInlineLexer |
|
122 | 123 | if 'block' not in kwargs: |
|
123 | 124 | kwargs['block'] = MathBlockLexer |
|
124 | 125 | super(MarkdownWithMath, self).__init__(renderer, **kwargs) |
|
125 | 126 | |
|
126 | 127 | def parse_block_math(self): |
|
127 | 128 | return self.renderer.block_math(self.token['text']) |
|
128 | 129 | |
|
129 | 130 | def parse_latex_environment(self): |
|
130 | 131 | return self.renderer.latex_environment(self.token['name'], self.token['text']) |
|
131 | 132 | |
|
132 | 133 | @undoc |
|
133 | 134 | class IPythonRenderer(mistune.Renderer): |
|
134 | 135 | def block_code(self, code, lang): |
|
135 | 136 | if lang: |
|
136 | 137 | try: |
|
137 | 138 | lexer = get_lexer_by_name(lang, stripall=True) |
|
138 | 139 | except ClassNotFound: |
|
139 | 140 | code = lang + '\n' + code |
|
140 | 141 | lang = None |
|
141 | 142 | |
|
142 | 143 | if not lang: |
|
143 | 144 | return '\n<pre><code>%s</code></pre>\n' % \ |
|
144 | 145 | mistune.escape(code) |
|
145 | 146 | |
|
146 | 147 | formatter = HtmlFormatter() |
|
147 | 148 | return highlight(code, lexer, formatter) |
|
148 | 149 | |
|
150 | def header(self, text, level, raw=None): | |
|
151 | html = super(IPythonRenderer, self).header(text, level, raw=raw) | |
|
152 | return add_anchor(html) | |
|
153 | ||
|
149 | 154 | # Pass math through unaltered - mathjax does the rendering in the browser |
|
150 | 155 | def block_math(self, text): |
|
151 | 156 | return '$$%s$$' % text |
|
152 | 157 | |
|
153 | 158 | def latex_environment(self, name, text): |
|
154 | 159 | return r'\begin{%s}%s\end{%s}' % (name, text, name) |
|
155 | 160 | |
|
156 | 161 | def inline_math(self, text): |
|
157 | 162 | return '$%s$' % text |
|
158 | 163 | |
|
159 | 164 | def markdown2html_mistune(source): |
|
160 | 165 | """Convert a markdown string to HTML using mistune""" |
|
161 | 166 | return MarkdownWithMath(renderer=IPythonRenderer()).render(source) |
|
162 | 167 | |
|
163 | 168 | def markdown2html_pandoc(source, extra_args=None): |
|
164 | 169 | """Convert a markdown string to HTML via pandoc""" |
|
165 | 170 | extra_args = extra_args or ['--mathjax'] |
|
166 | 171 | return pandoc(source, 'markdown', 'html', extra_args=extra_args) |
|
167 | 172 | |
|
168 | 173 | def _find_nodejs(): |
|
169 | 174 | global _node |
|
170 | 175 | if _node is None: |
|
171 | 176 | # prefer md2html via marked if node.js >= 0.9.12 is available |
|
172 | 177 | # node is called nodejs on debian, so try that first |
|
173 | 178 | _node = 'nodejs' |
|
174 | 179 | if not _verify_node(_node): |
|
175 | 180 | _node = 'node' |
|
176 | 181 | return _node |
|
177 | 182 | |
|
178 | 183 | def markdown2html_marked(source, encoding='utf-8'): |
|
179 | 184 | """Convert a markdown string to HTML via marked""" |
|
180 | 185 | command = [_find_nodejs(), marked] |
|
181 | 186 | try: |
|
182 | 187 | p = subprocess.Popen(command, |
|
183 | 188 | stdin=subprocess.PIPE, stdout=subprocess.PIPE |
|
184 | 189 | ) |
|
185 | 190 | except OSError as e: |
|
186 | 191 | raise NodeJSMissing( |
|
187 | 192 | "The command '%s' returned an error: %s.\n" % (" ".join(command), e) + |
|
188 | 193 | "Please check that Node.js is installed." |
|
189 | 194 | ) |
|
190 | 195 | out, _ = p.communicate(cast_bytes(source, encoding)) |
|
191 | 196 | out = TextIOWrapper(BytesIO(out), encoding, 'replace').read() |
|
192 | 197 | return out.rstrip('\n') |
|
193 | 198 | |
|
194 | 199 | # The mistune renderer is the default, because it's simple to depend on it |
|
195 | 200 | markdown2html = markdown2html_mistune |
|
196 | 201 | |
|
197 | 202 | def markdown2rst(source, extra_args=None): |
|
198 | 203 | """Convert a markdown string to ReST via pandoc. |
|
199 | 204 | |
|
200 | 205 | This function will raise an error if pandoc is not installed. |
|
201 | 206 | Any error messages generated by pandoc are printed to stderr. |
|
202 | 207 | |
|
203 | 208 | Parameters |
|
204 | 209 | ---------- |
|
205 | 210 | source : string |
|
206 | 211 | Input string, assumed to be valid markdown. |
|
207 | 212 | |
|
208 | 213 | Returns |
|
209 | 214 | ------- |
|
210 | 215 | out : string |
|
211 | 216 | Output as returned by pandoc. |
|
212 | 217 | """ |
|
213 | 218 | return pandoc(source, 'markdown', 'rst', extra_args=extra_args) |
|
214 | 219 | |
|
215 | 220 | def _verify_node(cmd): |
|
216 | 221 | """Verify that the node command exists and is at least the minimum supported |
|
217 | 222 | version of node. |
|
218 | 223 | |
|
219 | 224 | Parameters |
|
220 | 225 | ---------- |
|
221 | 226 | cmd : string |
|
222 | 227 | Node command to verify (i.e 'node').""" |
|
223 | 228 | try: |
|
224 | 229 | out, err, return_code = get_output_error_code([cmd, '--version']) |
|
225 | 230 | except OSError: |
|
226 | 231 | # Command not found |
|
227 | 232 | return False |
|
228 | 233 | if return_code: |
|
229 | 234 | # Command error |
|
230 | 235 | return False |
|
231 | 236 | return check_version(out.lstrip('v'), '0.9.12') |
@@ -1,232 +1,221 b'' | |||
|
1 | 1 | # coding: utf-8 |
|
2 | 2 | """String filters. |
|
3 | 3 | |
|
4 | 4 | Contains a collection of useful string manipulation filters for use in Jinja |
|
5 | 5 | templates. |
|
6 | 6 | """ |
|
7 | #----------------------------------------------------------------------------- | |
|
8 | # Copyright (c) 2013, the IPython Development Team. | |
|
9 | # | |
|
10 | # Distributed under the terms of the Modified BSD License. | |
|
11 | # | |
|
12 | # The full license is in the file COPYING.txt, distributed with this software. | |
|
13 | #----------------------------------------------------------------------------- | |
|
14 | 7 | |
|
15 | #----------------------------------------------------------------------------- | |
|
16 | # Imports | |
|
17 | #----------------------------------------------------------------------------- | |
|
8 | # Copyright (c) IPython Development Team. | |
|
9 | # Distributed under the terms of the Modified BSD License. | |
|
18 | 10 | |
|
19 | 11 | import os |
|
20 | 12 | import re |
|
21 | 13 | import textwrap |
|
22 | 14 | try: |
|
23 | 15 | from urllib.parse import quote # Py 3 |
|
24 | 16 | except ImportError: |
|
25 | 17 | from urllib2 import quote # Py 2 |
|
26 | 18 | from xml.etree import ElementTree |
|
27 | 19 | |
|
28 | 20 | from IPython.core.interactiveshell import InteractiveShell |
|
29 | 21 | from IPython.utils import py3compat |
|
30 | 22 | |
|
31 | #----------------------------------------------------------------------------- | |
|
32 | # Functions | |
|
33 | #----------------------------------------------------------------------------- | |
|
34 | 23 | |
|
35 | 24 | __all__ = [ |
|
36 | 25 | 'wrap_text', |
|
37 | 26 | 'html2text', |
|
38 | 27 | 'add_anchor', |
|
39 | 28 | 'strip_dollars', |
|
40 | 29 | 'strip_files_prefix', |
|
41 | 30 | 'comment_lines', |
|
42 | 31 | 'get_lines', |
|
43 | 32 | 'ipython2python', |
|
44 | 33 | 'posix_path', |
|
45 | 34 | 'path2url', |
|
46 | 35 | 'add_prompts', |
|
47 | 36 | 'ascii_only', |
|
48 | 37 | 'prevent_list_blocks', |
|
49 | 38 | ] |
|
50 | 39 | |
|
51 | 40 | |
|
52 | 41 | def wrap_text(text, width=100): |
|
53 | 42 | """ |
|
54 | 43 | Intelligently wrap text. |
|
55 | 44 | Wrap text without breaking words if possible. |
|
56 | 45 | |
|
57 | 46 | Parameters |
|
58 | 47 | ---------- |
|
59 | 48 | text : str |
|
60 | 49 | Text to wrap. |
|
61 | 50 | width : int, optional |
|
62 | 51 | Number of characters to wrap to, default 100. |
|
63 | 52 | """ |
|
64 | 53 | |
|
65 | 54 | split_text = text.split('\n') |
|
66 | 55 | wrp = map(lambda x:textwrap.wrap(x,width), split_text) |
|
67 | 56 | wrpd = map('\n'.join, wrp) |
|
68 | 57 | return '\n'.join(wrpd) |
|
69 | 58 | |
|
70 | 59 | |
|
71 | 60 | def html2text(element): |
|
72 | 61 | """extract inner text from html |
|
73 | 62 | |
|
74 | 63 | Analog of jQuery's $(element).text() |
|
75 | 64 | """ |
|
76 | 65 | if isinstance(element, py3compat.string_types): |
|
77 | 66 | try: |
|
78 | 67 | element = ElementTree.fromstring(element) |
|
79 | 68 | except Exception: |
|
80 | 69 | # failed to parse, just return it unmodified |
|
81 | 70 | return element |
|
82 | 71 | |
|
83 | 72 | text = element.text or "" |
|
84 | 73 | for child in element: |
|
85 | 74 | text += html2text(child) |
|
86 | 75 | text += (element.tail or "") |
|
87 | 76 | return text |
|
88 | 77 | |
|
89 | 78 | |
|
90 | 79 | def add_anchor(html): |
|
91 |
"""Add an anchor-link to an html header |
|
|
80 | """Add an anchor-link to an html header | |
|
92 | 81 | |
|
93 |
For use |
|
|
82 | For use on markdown headings | |
|
94 | 83 | """ |
|
95 | 84 | try: |
|
96 | 85 | h = ElementTree.fromstring(py3compat.cast_bytes_py2(html, encoding='utf-8')) |
|
97 | 86 | except Exception: |
|
98 | 87 | # failed to parse, just return it unmodified |
|
99 | 88 | return html |
|
100 | 89 | link = html2text(h).replace(' ', '-') |
|
101 | 90 | h.set('id', link) |
|
102 | 91 | a = ElementTree.Element("a", {"class" : "anchor-link", "href" : "#" + link}) |
|
103 | 92 | a.text = u'¶' |
|
104 | 93 | h.append(a) |
|
105 | 94 | |
|
106 | 95 | # Known issue of Python3.x, ElementTree.tostring() returns a byte string |
|
107 | 96 | # instead of a text string. See issue http://bugs.python.org/issue10942 |
|
108 | 97 | # Workaround is to make sure the bytes are casted to a string. |
|
109 | 98 | return py3compat.decode(ElementTree.tostring(h), 'utf-8') |
|
110 | 99 | |
|
111 | 100 | |
|
112 | 101 | def add_prompts(code, first='>>> ', cont='... '): |
|
113 | 102 | """Add prompts to code snippets""" |
|
114 | 103 | new_code = [] |
|
115 | 104 | code_list = code.split('\n') |
|
116 | 105 | new_code.append(first + code_list[0]) |
|
117 | 106 | for line in code_list[1:]: |
|
118 | 107 | new_code.append(cont + line) |
|
119 | 108 | return '\n'.join(new_code) |
|
120 | 109 | |
|
121 | 110 | |
|
122 | 111 | def strip_dollars(text): |
|
123 | 112 | """ |
|
124 | 113 | Remove all dollar symbols from text |
|
125 | 114 | |
|
126 | 115 | Parameters |
|
127 | 116 | ---------- |
|
128 | 117 | text : str |
|
129 | 118 | Text to remove dollars from |
|
130 | 119 | """ |
|
131 | 120 | |
|
132 | 121 | return text.strip('$') |
|
133 | 122 | |
|
134 | 123 | |
|
135 | 124 | files_url_pattern = re.compile(r'(src|href)\=([\'"]?)/?files/') |
|
136 | 125 | markdown_url_pattern = re.compile(r'(!?)\[(?P<caption>.*?)\]\(/?files/(?P<location>.*?)\)') |
|
137 | 126 | |
|
138 | 127 | def strip_files_prefix(text): |
|
139 | 128 | """ |
|
140 | 129 | Fix all fake URLs that start with `files/`, stripping out the `files/` prefix. |
|
141 | 130 | Applies to both urls (for html) and relative paths (for markdown paths). |
|
142 | 131 | |
|
143 | 132 | Parameters |
|
144 | 133 | ---------- |
|
145 | 134 | text : str |
|
146 | 135 | Text in which to replace 'src="files/real...' with 'src="real...' |
|
147 | 136 | """ |
|
148 | 137 | cleaned_text = files_url_pattern.sub(r"\1=\2", text) |
|
149 | 138 | cleaned_text = markdown_url_pattern.sub(r'\1[\2](\3)', cleaned_text) |
|
150 | 139 | return cleaned_text |
|
151 | 140 | |
|
152 | 141 | |
|
153 | 142 | def comment_lines(text, prefix='# '): |
|
154 | 143 | """ |
|
155 | 144 | Build a Python comment line from input text. |
|
156 | 145 | |
|
157 | 146 | Parameters |
|
158 | 147 | ---------- |
|
159 | 148 | text : str |
|
160 | 149 | Text to comment out. |
|
161 | 150 | prefix : str |
|
162 | 151 | Character to append to the start of each line. |
|
163 | 152 | """ |
|
164 | 153 | |
|
165 | 154 | #Replace line breaks with line breaks and comment symbols. |
|
166 | 155 | #Also add a comment symbol at the beginning to comment out |
|
167 | 156 | #the first line. |
|
168 | 157 | return prefix + ('\n'+prefix).join(text.split('\n')) |
|
169 | 158 | |
|
170 | 159 | |
|
171 | 160 | def get_lines(text, start=None,end=None): |
|
172 | 161 | """ |
|
173 | 162 | Split the input text into separate lines and then return the |
|
174 | 163 | lines that the caller is interested in. |
|
175 | 164 | |
|
176 | 165 | Parameters |
|
177 | 166 | ---------- |
|
178 | 167 | text : str |
|
179 | 168 | Text to parse lines from. |
|
180 | 169 | start : int, optional |
|
181 | 170 | First line to grab from. |
|
182 | 171 | end : int, optional |
|
183 | 172 | Last line to grab from. |
|
184 | 173 | """ |
|
185 | 174 | |
|
186 | 175 | # Split the input into lines. |
|
187 | 176 | lines = text.split("\n") |
|
188 | 177 | |
|
189 | 178 | # Return the right lines. |
|
190 | 179 | return "\n".join(lines[start:end]) #re-join |
|
191 | 180 | |
|
192 | 181 | def ipython2python(code): |
|
193 | 182 | """Transform IPython syntax to pure Python syntax |
|
194 | 183 | |
|
195 | 184 | Parameters |
|
196 | 185 | ---------- |
|
197 | 186 | |
|
198 | 187 | code : str |
|
199 | 188 | IPython code, to be transformed to pure Python |
|
200 | 189 | """ |
|
201 | 190 | shell = InteractiveShell.instance() |
|
202 | 191 | return shell.input_transformer_manager.transform_cell(code) |
|
203 | 192 | |
|
204 | 193 | def posix_path(path): |
|
205 | 194 | """Turn a path into posix-style path/to/etc |
|
206 | 195 | |
|
207 | 196 | Mainly for use in latex on Windows, |
|
208 | 197 | where native Windows paths are not allowed. |
|
209 | 198 | """ |
|
210 | 199 | if os.path.sep != '/': |
|
211 | 200 | return path.replace(os.path.sep, '/') |
|
212 | 201 | return path |
|
213 | 202 | |
|
214 | 203 | def path2url(path): |
|
215 | 204 | """Turn a file path into a URL""" |
|
216 | 205 | parts = path.split(os.path.sep) |
|
217 | 206 | return '/'.join(quote(part) for part in parts) |
|
218 | 207 | |
|
219 | 208 | def ascii_only(s): |
|
220 | 209 | """ensure a string is ascii""" |
|
221 | 210 | s = py3compat.cast_unicode(s) |
|
222 | 211 | return s.encode('ascii', 'replace').decode('ascii') |
|
223 | 212 | |
|
224 | 213 | def prevent_list_blocks(s): |
|
225 | 214 | """ |
|
226 | 215 | Prevent presence of enumerate or itemize blocks in latex headings cells |
|
227 | 216 | """ |
|
228 | 217 | out = re.sub('(^\s*\d*)\.', '\\1\.', s) |
|
229 | 218 | out = re.sub('(^\s*)\-', '\\1\-', out) |
|
230 | 219 | out = re.sub('(^\s*)\+', '\\1\+', out) |
|
231 | 220 | out = re.sub('(^\s*)\*', '\\1\*', out) |
|
232 | 221 | return out |
@@ -1,129 +1,143 b'' | |||
|
1 | # coding: utf-8 | |
|
1 | 2 | """Tests for conversions from markdown to other formats""" |
|
2 | 3 | |
|
3 | 4 | # Copyright (c) IPython Development Team. |
|
4 | 5 | # Distributed under the terms of the Modified BSD License. |
|
5 | 6 | |
|
6 | 7 | from copy import copy |
|
7 | 8 | |
|
8 | 9 | from IPython.utils.py3compat import string_types |
|
9 | 10 | from IPython.testing import decorators as dec |
|
10 | 11 | |
|
11 | 12 | from ...tests.base import TestsBase |
|
12 | 13 | from ..markdown import markdown2latex, markdown2html, markdown2rst |
|
13 | 14 | |
|
14 | 15 | from jinja2 import Environment |
|
15 | 16 | |
|
16 | 17 | class TestMarkdown(TestsBase): |
|
17 | 18 | |
|
18 | 19 | tests = [ |
|
19 | 20 | '*test', |
|
20 | 21 | '**test', |
|
21 | 22 | '*test*', |
|
22 | 23 | '_test_', |
|
23 | 24 | '__test__', |
|
24 | 25 | '__*test*__', |
|
25 | 26 | '**test**', |
|
26 | 27 | '#test', |
|
27 | 28 | '##test', |
|
28 | 29 | 'test\n----', |
|
29 |
'test [link](https://google.com/)' |
|
|
30 | 'test [link](https://google.com/)', | |
|
31 | ] | |
|
30 | 32 | |
|
31 | 33 | tokens = [ |
|
32 | 34 | '*test', |
|
33 | 35 | '**test', |
|
34 | 36 | 'test', |
|
35 | 37 | 'test', |
|
36 | 38 | 'test', |
|
37 | 39 | 'test', |
|
38 | 40 | 'test', |
|
39 | 41 | 'test', |
|
40 | 42 | 'test', |
|
41 | 43 | 'test', |
|
42 |
('test', 'https://google.com/') |
|
|
44 | ('test', 'https://google.com/'), | |
|
45 | ] | |
|
43 | 46 | |
|
44 | 47 | |
|
45 | 48 | @dec.onlyif_cmds_exist('pandoc') |
|
46 | 49 | def test_markdown2latex(self): |
|
47 | 50 | """markdown2latex test""" |
|
48 | 51 | for index, test in enumerate(self.tests): |
|
49 | 52 | self._try_markdown(markdown2latex, test, self.tokens[index]) |
|
50 | 53 | |
|
51 | 54 | @dec.onlyif_cmds_exist('pandoc') |
|
52 | 55 | def test_markdown2latex_markup(self): |
|
53 | 56 | """markdown2latex with markup kwarg test""" |
|
54 | 57 | # This string should be passed through unaltered with pandoc's |
|
55 | 58 | # markdown_strict reader |
|
56 | 59 | s = '1) arabic number with parenthesis' |
|
57 | 60 | self.assertEqual(markdown2latex(s, markup='markdown_strict'), s) |
|
58 | 61 | # This string should be passed through unaltered with pandoc's |
|
59 | 62 | # markdown_strict+tex_math_dollars reader |
|
60 | 63 | s = '$\\alpha$ latex math' |
|
61 | 64 | self.assertEqual( |
|
62 | 65 | markdown2latex(s, markup='markdown_strict+tex_math_dollars'), |
|
63 | 66 | s) |
|
64 | 67 | |
|
65 | 68 | @dec.onlyif_cmds_exist('pandoc') |
|
66 | 69 | def test_pandoc_extra_args(self): |
|
67 | 70 | # pass --no-wrap |
|
68 | 71 | s = '\n'.join([ |
|
69 | 72 | "#latex {{long_line | md2l('markdown', ['--no-wrap'])}}", |
|
70 | 73 | "#rst {{long_line | md2r(['--columns', '5'])}}", |
|
71 | 74 | ]) |
|
72 | 75 | long_line = ' '.join(['long'] * 30) |
|
73 | 76 | env = Environment() |
|
74 | 77 | env.filters.update({ |
|
75 | 78 | 'md2l': markdown2latex, |
|
76 | 79 | 'md2r': markdown2rst, |
|
77 | 80 | }) |
|
78 | 81 | tpl = env.from_string(s) |
|
79 | 82 | rendered = tpl.render(long_line=long_line) |
|
80 | 83 | _, latex, rst = rendered.split('#') |
|
81 | 84 | |
|
82 | 85 | self.assertEqual(latex.strip(), 'latex %s' % long_line) |
|
83 | 86 | self.assertEqual(rst.strip(), 'rst %s' % long_line.replace(' ', '\n')) |
|
84 | 87 | |
|
85 | 88 | def test_markdown2html(self): |
|
86 | 89 | """markdown2html test""" |
|
87 | 90 | for index, test in enumerate(self.tests): |
|
88 | 91 | self._try_markdown(markdown2html, test, self.tokens[index]) |
|
89 | 92 | |
|
93 | def test_markdown2html_heading_anchors(self): | |
|
94 | for md, tokens in [ | |
|
95 | ('# test', | |
|
96 | ('<h1', '>test', 'id="test"', u'¶</a>', "anchor-link") | |
|
97 | ), | |
|
98 | ('###test head space', | |
|
99 | ('<h3', '>test head space', 'id="test-head-space"', u'¶</a>', "anchor-link") | |
|
100 | ) | |
|
101 | ]: | |
|
102 | self._try_markdown(markdown2html, md, tokens) | |
|
103 | ||
|
90 | 104 | def test_markdown2html_math(self): |
|
91 | 105 | # Mathematical expressions should be passed through unaltered |
|
92 | 106 | cases = [("\\begin{equation*}\n" |
|
93 | 107 | "\\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" |
|
94 | 108 | "\\end{equation*}"), |
|
95 | 109 | ("$$\n" |
|
96 | 110 | "a = 1 *3* 5\n" |
|
97 | 111 | "$$"), |
|
98 | 112 | "$ a = 1 *3* 5 $", |
|
99 | 113 | ] |
|
100 | 114 | for case in cases: |
|
101 | 115 | self.assertIn(case, markdown2html(case)) |
|
102 | 116 | |
|
103 | 117 | def test_markdown2html_math_paragraph(self): |
|
104 | 118 | # https://github.com/ipython/ipython/issues/6724 |
|
105 | 119 | a = """Water that is stored in $t$, $s_t$, must equal the storage content of the previous stage, |
|
106 | 120 | $s_{t-1}$, plus a stochastic inflow, $I_t$, minus what is being released in $t$, $r_t$. |
|
107 | 121 | With $s_0$ defined as the initial storage content in $t=1$, we have""" |
|
108 | 122 | self.assertIn(a, markdown2html(a)) |
|
109 | 123 | |
|
110 | 124 | @dec.onlyif_cmds_exist('pandoc') |
|
111 | 125 | def test_markdown2rst(self): |
|
112 | 126 | """markdown2rst test""" |
|
113 | 127 | |
|
114 | 128 | #Modify token array for rst, escape asterik |
|
115 | 129 | tokens = copy(self.tokens) |
|
116 | 130 | tokens[0] = r'\*test' |
|
117 | 131 | tokens[1] = r'\*\*test' |
|
118 | 132 | |
|
119 | 133 | for index, test in enumerate(self.tests): |
|
120 | 134 | self._try_markdown(markdown2rst, test, tokens[index]) |
|
121 | 135 | |
|
122 | 136 | |
|
123 | 137 | def _try_markdown(self, method, test, tokens): |
|
124 | 138 | results = method(test) |
|
125 | 139 | if isinstance(tokens, string_types): |
|
126 | 140 | assert tokens in results |
|
127 | 141 | else: |
|
128 | 142 | for token in tokens: |
|
129 | 143 | assert token in results |
@@ -1,203 +1,192 b'' | |||
|
1 | 1 | {%- extends 'display_priority.tpl' -%} |
|
2 | 2 | |
|
3 | 3 | |
|
4 | 4 | {% block codecell %} |
|
5 | 5 | <div class="cell border-box-sizing code_cell rendered"> |
|
6 | 6 | {{ super() }} |
|
7 | 7 | </div> |
|
8 | 8 | {%- endblock codecell %} |
|
9 | 9 | |
|
10 | 10 | {% block input_group -%} |
|
11 | 11 | <div class="input"> |
|
12 | 12 | {{ super() }} |
|
13 | 13 | </div> |
|
14 | 14 | {% endblock input_group %} |
|
15 | 15 | |
|
16 | 16 | {% block output_group %} |
|
17 | 17 | <div class="output_wrapper"> |
|
18 | 18 | <div class="output"> |
|
19 | 19 | {{ super() }} |
|
20 | 20 | </div> |
|
21 | 21 | </div> |
|
22 | 22 | {% endblock output_group %} |
|
23 | 23 | |
|
24 | 24 | {% block in_prompt -%} |
|
25 | 25 | <div class="prompt input_prompt"> |
|
26 | 26 | {%- if cell.execution_count is defined -%} |
|
27 | 27 | In [{{ cell.execution_count|replace(None, " ") }}]: |
|
28 | 28 | {%- else -%} |
|
29 | 29 | In [ ]: |
|
30 | 30 | {%- endif -%} |
|
31 | 31 | </div> |
|
32 | 32 | {%- endblock in_prompt %} |
|
33 | 33 | |
|
34 | 34 | {% block empty_in_prompt -%} |
|
35 | 35 | <div class="prompt input_prompt"> |
|
36 | 36 | </div> |
|
37 | 37 | {%- endblock empty_in_prompt %} |
|
38 | 38 | |
|
39 | 39 | {# |
|
40 | 40 | output_prompt doesn't do anything in HTML, |
|
41 | 41 | because there is a prompt div in each output area (see output block) |
|
42 | 42 | #} |
|
43 | 43 | {% block output_prompt %} |
|
44 | 44 | {% endblock output_prompt %} |
|
45 | 45 | |
|
46 | 46 | {% block input %} |
|
47 | 47 | <div class="inner_cell"> |
|
48 | 48 | <div class="input_area"> |
|
49 | 49 | {{ cell.source | highlight_code(metadata=cell.metadata) }} |
|
50 | 50 | </div> |
|
51 | 51 | </div> |
|
52 | 52 | {%- endblock input %} |
|
53 | 53 | |
|
54 | 54 | {% block output %} |
|
55 | 55 | <div class="output_area"> |
|
56 | 56 | {%- if output.output_type == 'execute_result' -%} |
|
57 | 57 | <div class="prompt output_prompt"> |
|
58 | 58 | {%- if cell.execution_count is defined -%} |
|
59 | 59 | Out[{{ cell.execution_count|replace(None, " ") }}]: |
|
60 | 60 | {%- else -%} |
|
61 | 61 | Out[ ]: |
|
62 | 62 | {%- endif -%} |
|
63 | 63 | {%- else -%} |
|
64 | 64 | <div class="prompt"> |
|
65 | 65 | {%- endif -%} |
|
66 | 66 | </div> |
|
67 | 67 | {{ super() }} |
|
68 | 68 | </div> |
|
69 | 69 | {% endblock output %} |
|
70 | 70 | |
|
71 | 71 | {% block markdowncell scoped %} |
|
72 | 72 | <div class="cell border-box-sizing text_cell rendered"> |
|
73 | 73 | {{ self.empty_in_prompt() }} |
|
74 | 74 | <div class="inner_cell"> |
|
75 | 75 | <div class="text_cell_render border-box-sizing rendered_html"> |
|
76 | 76 | {{ cell.source | markdown2html | strip_files_prefix }} |
|
77 | 77 | </div> |
|
78 | 78 | </div> |
|
79 | 79 | </div> |
|
80 | 80 | {%- endblock markdowncell %} |
|
81 | 81 | |
|
82 | {% block headingcell scoped %} | |
|
83 | <div class="cell border-box-sizing text_cell rendered"> | |
|
84 | {{ self.empty_in_prompt() }} | |
|
85 | <div class="inner_cell"> | |
|
86 | <div class="text_cell_render border-box-sizing rendered_html"> | |
|
87 | {{ ("#" * cell.level + cell.source) | replace('\n', ' ') | markdown2html | strip_files_prefix | add_anchor }} | |
|
88 | </div> | |
|
89 | </div> | |
|
90 | </div> | |
|
91 | {% endblock headingcell %} | |
|
92 | ||
|
93 | 82 | {% block unknowncell scoped %} |
|
94 | 83 | unknown type {{ cell.type }} |
|
95 | 84 | {% endblock unknowncell %} |
|
96 | 85 | |
|
97 | 86 | {% block execute_result -%} |
|
98 | 87 | {%- set extra_class="output_execute_result" -%} |
|
99 | 88 | {% block data_priority scoped %} |
|
100 | 89 | {{ super() }} |
|
101 | 90 | {% endblock %} |
|
102 | 91 | {%- set extra_class="" -%} |
|
103 | 92 | {%- endblock execute_result %} |
|
104 | 93 | |
|
105 | 94 | {% block stream_stdout -%} |
|
106 | 95 | <div class="output_subarea output_stream output_stdout output_text"> |
|
107 | 96 | <pre> |
|
108 | 97 | {{- output.text | ansi2html -}} |
|
109 | 98 | </pre> |
|
110 | 99 | </div> |
|
111 | 100 | {%- endblock stream_stdout %} |
|
112 | 101 | |
|
113 | 102 | {% block stream_stderr -%} |
|
114 | 103 | <div class="output_subarea output_stream output_stderr output_text"> |
|
115 | 104 | <pre> |
|
116 | 105 | {{- output.text | ansi2html -}} |
|
117 | 106 | </pre> |
|
118 | 107 | </div> |
|
119 | 108 | {%- endblock stream_stderr %} |
|
120 | 109 | |
|
121 | 110 | {% block data_svg scoped -%} |
|
122 | 111 | <div class="output_svg output_subarea {{extra_class}}"> |
|
123 | 112 | {%- if output.svg_filename %} |
|
124 | 113 | <img src="{{output.svg_filename | posix_path}}" |
|
125 | 114 | {%- else %} |
|
126 | 115 | {{ output.data['image/svg+xml'] }} |
|
127 | 116 | {%- endif %} |
|
128 | 117 | </div> |
|
129 | 118 | {%- endblock data_svg %} |
|
130 | 119 | |
|
131 | 120 | {% block data_html scoped -%} |
|
132 | 121 | <div class="output_html rendered_html output_subarea {{extra_class}}"> |
|
133 | 122 | {{ output.data['text/html'] }} |
|
134 | 123 | </div> |
|
135 | 124 | {%- endblock data_html %} |
|
136 | 125 | |
|
137 | 126 | {% block data_png scoped %} |
|
138 | 127 | <div class="output_png output_subarea {{extra_class}}"> |
|
139 | 128 | {%- if 'image/png' in output.metadata.get('filenames', {}) %} |
|
140 | 129 | <img src="{{output.metadata.filenames['image/png'] | posix_path}}" |
|
141 | 130 | {%- else %} |
|
142 | 131 | <img src="data:image/png;base64,{{ output.data['image/png'] }}" |
|
143 | 132 | {%- endif %} |
|
144 | 133 | {%- if 'width' in output.metadata.get('image/png', {}) %} |
|
145 | 134 | width={{output.metadata['png']['width']}} |
|
146 | 135 | {%- endif %} |
|
147 | 136 | {%- if 'height' in output.metadata.get('image/png', {}) %} |
|
148 | 137 | height={{output.metadata['png']['height']}} |
|
149 | 138 | {%- endif %} |
|
150 | 139 | > |
|
151 | 140 | </div> |
|
152 | 141 | {%- endblock data_png %} |
|
153 | 142 | |
|
154 | 143 | {% block data_jpg scoped %} |
|
155 | 144 | <div class="output_jpeg output_subarea {{extra_class}}"> |
|
156 | 145 | {%- if 'image/jpeg' in output.metadata.get('filenames', {}) %} |
|
157 | 146 | <img src="{{output.metadata.filenames['image/jpeg'] | posix_path}}" |
|
158 | 147 | {%- else %} |
|
159 | 148 | <img src="data:image/jpeg;base64,{{ output.data['image/jpeg'] }}" |
|
160 | 149 | {%- endif %} |
|
161 | 150 | {%- if 'width' in output.metadata.get('image/jpeg', {}) %} |
|
162 | 151 | width={{output.metadata['image/jpeg']['width']}} |
|
163 | 152 | {%- endif %} |
|
164 | 153 | {%- if 'height' in output.metadata.get('image/jpeg', {}) %} |
|
165 | 154 | height={{output.metadata['image/jpeg']['height']}} |
|
166 | 155 | {%- endif %} |
|
167 | 156 | > |
|
168 | 157 | </div> |
|
169 | 158 | {%- endblock data_jpg %} |
|
170 | 159 | |
|
171 | 160 | {% block data_latex scoped %} |
|
172 | 161 | <div class="output_latex output_subarea {{extra_class}}"> |
|
173 | 162 | {{ output.data['text/latex'] }} |
|
174 | 163 | </div> |
|
175 | 164 | {%- endblock data_latex %} |
|
176 | 165 | |
|
177 | 166 | {% block error -%} |
|
178 | 167 | <div class="output_subarea output_text output_error"> |
|
179 | 168 | <pre> |
|
180 | 169 | {{- super() -}} |
|
181 | 170 | </pre> |
|
182 | 171 | </div> |
|
183 | 172 | {%- endblock error %} |
|
184 | 173 | |
|
185 | 174 | {%- block traceback_line %} |
|
186 | 175 | {{ line | ansi2html }} |
|
187 | 176 | {%- endblock traceback_line %} |
|
188 | 177 | |
|
189 | 178 | {%- block data_text scoped %} |
|
190 | 179 | <div class="output_text output_subarea {{extra_class}}"> |
|
191 | 180 | <pre> |
|
192 | 181 | {{- output.data['text/plain'] | ansi2html -}} |
|
193 | 182 | </pre> |
|
194 | 183 | </div> |
|
195 | 184 | {%- endblock -%} |
|
196 | 185 | |
|
197 | 186 | {%- block data_javascript scoped %} |
|
198 | 187 | <div class="output_subarea output_javascript {{extra_class}}"> |
|
199 | 188 | <script type="text/javascript"> |
|
200 | 189 | {{ output.data['text/javascript'] }} |
|
201 | 190 | </script> |
|
202 | 191 | </div> |
|
203 | 192 | {%- endblock -%} |
@@ -1,223 +1,202 b'' | |||
|
1 | 1 | ((= Latex base template (must inherit) |
|
2 | 2 | This template builds upon the abstract template, adding common latex output |
|
3 | 3 | functions. Figures, data_text, |
|
4 | 4 | This template does not define a docclass, the inheriting class must define this.=)) |
|
5 | 5 | |
|
6 | 6 | ((*- extends 'display_priority.tplx' -*)) |
|
7 | 7 | |
|
8 | 8 | %=============================================================================== |
|
9 | 9 | % Abstract overrides |
|
10 | 10 | %=============================================================================== |
|
11 | 11 | |
|
12 | 12 | ((* block header *)) |
|
13 | 13 | ((* block docclass *))((* endblock docclass *)) |
|
14 | 14 | |
|
15 | 15 | ((* block packages *)) |
|
16 | 16 | \usepackage{graphicx} % Used to insert images |
|
17 | 17 | \usepackage{adjustbox} % Used to constrain images to a maximum size |
|
18 | 18 | \usepackage{color} % Allow colors to be defined |
|
19 | 19 | \usepackage{enumerate} % Needed for markdown enumerations to work |
|
20 | 20 | \usepackage{geometry} % Used to adjust the document margins |
|
21 | 21 | \usepackage{amsmath} % Equations |
|
22 | 22 | \usepackage{amssymb} % Equations |
|
23 | 23 | \usepackage[mathletters]{ucs} % Extended unicode (utf-8) support |
|
24 | 24 | \usepackage[utf8x]{inputenc} % Allow utf-8 characters in the tex document |
|
25 | 25 | \usepackage{fancyvrb} % verbatim replacement that allows latex |
|
26 | 26 | \usepackage{grffile} % extends the file name processing of package graphics |
|
27 | 27 | % to support a larger range |
|
28 | 28 | % The hyperref package gives us a pdf with properly built |
|
29 | 29 | % internal navigation ('pdf bookmarks' for the table of contents, |
|
30 | 30 | % internal cross-reference links, web links for URLs, etc.) |
|
31 | 31 | \usepackage{hyperref} |
|
32 | 32 | \usepackage{longtable} % longtable support required by pandoc >1.10 |
|
33 | 33 | \usepackage{booktabs} % table support for pandoc > 1.12.2 |
|
34 | 34 | ((* endblock packages *)) |
|
35 | 35 | |
|
36 | 36 | ((* block definitions *)) |
|
37 | 37 | \definecolor{orange}{cmyk}{0,0.4,0.8,0.2} |
|
38 | 38 | \definecolor{darkorange}{rgb}{.71,0.21,0.01} |
|
39 | 39 | \definecolor{darkgreen}{rgb}{.12,.54,.11} |
|
40 | 40 | \definecolor{myteal}{rgb}{.26, .44, .56} |
|
41 | 41 | \definecolor{gray}{gray}{0.45} |
|
42 | 42 | \definecolor{lightgray}{gray}{.95} |
|
43 | 43 | \definecolor{mediumgray}{gray}{.8} |
|
44 | 44 | \definecolor{inputbackground}{rgb}{.95, .95, .85} |
|
45 | 45 | \definecolor{outputbackground}{rgb}{.95, .95, .95} |
|
46 | 46 | \definecolor{traceback}{rgb}{1, .95, .95} |
|
47 | 47 | % ansi colors |
|
48 | 48 | \definecolor{red}{rgb}{.6,0,0} |
|
49 | 49 | \definecolor{green}{rgb}{0,.65,0} |
|
50 | 50 | \definecolor{brown}{rgb}{0.6,0.6,0} |
|
51 | 51 | \definecolor{blue}{rgb}{0,.145,.698} |
|
52 | 52 | \definecolor{purple}{rgb}{.698,.145,.698} |
|
53 | 53 | \definecolor{cyan}{rgb}{0,.698,.698} |
|
54 | 54 | \definecolor{lightgray}{gray}{0.5} |
|
55 | 55 | |
|
56 | 56 | % bright ansi colors |
|
57 | 57 | \definecolor{darkgray}{gray}{0.25} |
|
58 | 58 | \definecolor{lightred}{rgb}{1.0,0.39,0.28} |
|
59 | 59 | \definecolor{lightgreen}{rgb}{0.48,0.99,0.0} |
|
60 | 60 | \definecolor{lightblue}{rgb}{0.53,0.81,0.92} |
|
61 | 61 | \definecolor{lightpurple}{rgb}{0.87,0.63,0.87} |
|
62 | 62 | \definecolor{lightcyan}{rgb}{0.5,1.0,0.83} |
|
63 | 63 | |
|
64 | 64 | % commands and environments needed by pandoc snippets |
|
65 | 65 | % extracted from the output of `pandoc -s` |
|
66 | 66 | \DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}} |
|
67 | 67 | % Add ',fontsize=\small' for more characters per line |
|
68 | 68 | \newenvironment{Shaded}{}{} |
|
69 | 69 | \newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{{#1}}}} |
|
70 | 70 | \newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{{#1}}} |
|
71 | 71 | \newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} |
|
72 | 72 | \newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} |
|
73 | 73 | \newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} |
|
74 | 74 | \newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} |
|
75 | 75 | \newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} |
|
76 | 76 | \newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{{#1}}}} |
|
77 | 77 | \newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{{#1}}} |
|
78 | 78 | \newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}} |
|
79 | 79 | \newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{{#1}}} |
|
80 | 80 | \newcommand{\RegionMarkerTok}[1]{{#1}} |
|
81 | 81 | \newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}} |
|
82 | 82 | \newcommand{\NormalTok}[1]{{#1}} |
|
83 | 83 | |
|
84 | 84 | % Define a nice break command that doesn't care if a line doesn't already |
|
85 | 85 | % exist. |
|
86 | 86 | \def\br{\hspace*{\fill} \\* } |
|
87 | 87 | % Math Jax compatability definitions |
|
88 | 88 | \def\gt{>} |
|
89 | 89 | \def\lt{<} |
|
90 | 90 | % Document parameters |
|
91 | 91 | ((* block title *))\title{((( resources.metadata.name | ascii_only | escape_latex )))}((* endblock title *)) |
|
92 | 92 | ((* block date *))((* endblock date *)) |
|
93 | 93 | ((* block author *))((* endblock author *)) |
|
94 | 94 | ((* endblock definitions *)) |
|
95 | 95 | |
|
96 | 96 | ((* block commands *)) |
|
97 | 97 | % Prevent overflowing lines due to hard-to-break entities |
|
98 | 98 | \sloppy |
|
99 | 99 | % Setup hyperref package |
|
100 | 100 | \hypersetup{ |
|
101 | 101 | breaklinks=true, % so long urls are correctly broken across lines |
|
102 | 102 | colorlinks=true, |
|
103 | 103 | urlcolor=blue, |
|
104 | 104 | linkcolor=darkorange, |
|
105 | 105 | citecolor=darkgreen, |
|
106 | 106 | } |
|
107 | 107 | % Slightly bigger margins than the latex defaults |
|
108 | 108 | ((* block margins *)) |
|
109 | 109 | \geometry{verbose,tmargin=1in,bmargin=1in,lmargin=1in,rmargin=1in} |
|
110 | 110 | ((* endblock margins *)) |
|
111 | 111 | ((* endblock commands *)) |
|
112 | 112 | ((* endblock header *)) |
|
113 | 113 | |
|
114 | 114 | ((* block body *)) |
|
115 | 115 | \begin{document} |
|
116 | 116 | |
|
117 | 117 | ((* block predoc *)) |
|
118 | 118 | ((* block maketitle *))\maketitle((* endblock maketitle *)) |
|
119 | 119 | ((* block abstract *))((* endblock abstract *)) |
|
120 | 120 | ((* endblock predoc *)) |
|
121 | 121 | |
|
122 | 122 | ((( super() ))) |
|
123 | 123 | |
|
124 | 124 | % Add a bibliography block to the postdoc |
|
125 | 125 | ((* block postdoc *)) |
|
126 | 126 | ((* block bibliography *))((* endblock bibliography *)) |
|
127 | 127 | ((* endblock postdoc *)) |
|
128 | 128 | \end{document} |
|
129 | 129 | ((* endblock body *)) |
|
130 | 130 | |
|
131 | 131 | %=============================================================================== |
|
132 | 132 | % Support blocks |
|
133 | 133 | %=============================================================================== |
|
134 | 134 | |
|
135 | 135 | % Displaying simple data text |
|
136 | 136 | ((* block data_text *)) |
|
137 | 137 | \begin{verbatim} |
|
138 | 138 | ((( output.data['text/plain'] ))) |
|
139 | 139 | \end{verbatim} |
|
140 | 140 | ((* endblock data_text *)) |
|
141 | 141 | |
|
142 | 142 | % Display python error text as-is |
|
143 | 143 | ((* block error *)) |
|
144 | 144 | \begin{Verbatim}[commandchars=\\\{\}] |
|
145 | 145 | ((( super() ))) |
|
146 | 146 | \end{Verbatim} |
|
147 | 147 | ((* endblock error *)) |
|
148 | 148 | ((* block traceback_line *)) |
|
149 | 149 | ((( line | indent | strip_ansi | escape_latex ))) |
|
150 | 150 | ((* endblock traceback_line *)) |
|
151 | 151 | |
|
152 | 152 | % Display stream ouput with coloring |
|
153 | 153 | ((* block stream *)) |
|
154 | 154 | \begin{Verbatim}[commandchars=\\\{\}] |
|
155 | 155 | ((( output.text | escape_latex | ansi2latex ))) |
|
156 | 156 | \end{Verbatim} |
|
157 | 157 | ((* endblock stream *)) |
|
158 | 158 | |
|
159 | 159 | % Display latex |
|
160 | 160 | ((* block data_latex -*)) |
|
161 | 161 | ((*- if output.data['text/latex'].startswith('$'): -*)) |
|
162 | 162 | ((= Replace $ symbols with more explicit, equation block. =)) |
|
163 | 163 | \begin{equation*}\adjustbox{max width=\hsize}{$ |
|
164 | 164 | ((( output.data['text/latex'] | strip_dollars ))) |
|
165 | 165 | $}\end{equation*} |
|
166 | 166 | ((*- else -*)) |
|
167 | 167 | ((( output.data['text/latex'] ))) |
|
168 | 168 | ((*- endif *)) |
|
169 | 169 | ((* endblock data_latex *)) |
|
170 | 170 | |
|
171 | 171 | % Default mechanism for rendering figures |
|
172 | 172 | ((*- block data_png -*))((( draw_figure(output.metadata.filenames['image/png']) )))((*- endblock -*)) |
|
173 | 173 | ((*- block data_jpg -*))((( draw_figure(output.metadata.filenames['image/jpeg']) )))((*- endblock -*)) |
|
174 | 174 | ((*- block data_svg -*))((( draw_figure(output.metadata.filenames['image/svg+xml']) )))((*- endblock -*)) |
|
175 | 175 | ((*- block data_pdf -*))((( draw_figure(output.metadata.filenames['application/pdf']) )))((*- endblock -*)) |
|
176 | 176 | |
|
177 | 177 | % Draw a figure using the graphicx package. |
|
178 | 178 | ((* macro draw_figure(filename) -*)) |
|
179 | 179 | ((* set filename = filename | posix_path *)) |
|
180 | 180 | ((*- block figure scoped -*)) |
|
181 | 181 | \begin{center} |
|
182 | 182 | \adjustimage{max size={0.9\linewidth}{0.9\paperheight}}{((( filename )))} |
|
183 | 183 | \end{center} |
|
184 | 184 | { \hspace*{\fill} \\} |
|
185 | 185 | ((*- endblock figure -*)) |
|
186 | 186 | ((*- endmacro *)) |
|
187 | 187 | |
|
188 | % Draw heading cell. Explicitly map different cell levels. | |
|
189 | ((* block headingcell scoped *)) | |
|
190 | ||
|
191 | ((* if cell.level == 1 -*)) | |
|
192 | ((* block h1 -*))\section((* endblock h1 -*)) | |
|
193 | ((* elif cell.level == 2 -*)) | |
|
194 | ((* block h2 -*))\subsection((* endblock h2 -*)) | |
|
195 | ((* elif cell.level == 3 -*)) | |
|
196 | ((* block h3 -*))\subsubsection((* endblock h3 -*)) | |
|
197 | ((* elif cell.level == 4 -*)) | |
|
198 | ((* block h4 -*))\paragraph((* endblock h4 -*)) | |
|
199 | ((* elif cell.level == 5 -*)) | |
|
200 | ((* block h5 -*))\subparagraph((* endblock h5 -*)) | |
|
201 | ((* elif cell.level == 6 -*)) | |
|
202 | ((* block h6 -*))\\*\textit((* endblock h6 -*)) | |
|
203 | ((*- endif -*)) | |
|
204 | {((( cell.source | replace('\n', ' ') | citation2latex | strip_files_prefix | prevent_list_blocks | markdown2latex(markup='markdown_strict+tex_math_dollars') )))} | |
|
205 | ||
|
206 | ||
|
207 | ((* endblock headingcell *)) | |
|
208 | ||
|
209 | 188 | % Redirect execute_result to display data priority. |
|
210 | 189 | ((* block execute_result scoped *)) |
|
211 | 190 | ((* block data_priority scoped *)) |
|
212 | 191 | ((( super() ))) |
|
213 | 192 | ((* endblock *)) |
|
214 | 193 | ((* endblock execute_result *)) |
|
215 | 194 | |
|
216 | 195 | % Render markdown |
|
217 | 196 | ((* block markdowncell scoped *)) |
|
218 | 197 | ((( cell.source | citation2latex | strip_files_prefix | markdown2latex ))) |
|
219 | 198 | ((* endblock markdowncell *)) |
|
220 | 199 | |
|
221 | 200 | % Don't display unknown types |
|
222 | 201 | ((* block unknowncell scoped *)) |
|
223 | 202 | ((* endblock unknowncell *)) |
@@ -1,96 +1,93 b'' | |||
|
1 | 1 | ((= Auto-generated template file, DO NOT edit directly! |
|
2 | 2 | To edit this file, please refer to ../../skeleton/README.md =)) |
|
3 | 3 | |
|
4 | 4 | |
|
5 | 5 | ((= |
|
6 | 6 | |
|
7 | 7 | DO NOT USE THIS AS A BASE, |
|
8 | 8 | IF YOU ARE COPY AND PASTING THIS FILE |
|
9 | 9 | YOU ARE PROBABLY DOING THINGS INCORRECTLY. |
|
10 | 10 | |
|
11 | 11 | Null template, does nothing except defining a basic structure |
|
12 | 12 | To layout the different blocks of a notebook. |
|
13 | 13 | |
|
14 | 14 | Subtemplates can override blocks to define their custom representation. |
|
15 | 15 | |
|
16 | 16 | If one of the block you do overwrite is not a leave block, consider |
|
17 | 17 | calling super. |
|
18 | 18 | |
|
19 | 19 | ((*- block nonLeaveBlock -*)) |
|
20 | 20 | #add stuff at beginning |
|
21 | 21 | ((( super() ))) |
|
22 | 22 | #add stuff at end |
|
23 | 23 | ((*- endblock nonLeaveBlock -*)) |
|
24 | 24 | |
|
25 | 25 | consider calling super even if it is a leave block, we might insert more blocks later. |
|
26 | 26 | |
|
27 | 27 | =)) |
|
28 | 28 | ((*- block header -*)) |
|
29 | 29 | ((*- endblock header -*)) |
|
30 | 30 | ((*- block body -*)) |
|
31 | 31 | ((*- for cell in nb.cells -*)) |
|
32 | 32 | ((*- block any_cell scoped -*)) |
|
33 | 33 | ((*- if cell.cell_type == 'code' -*)) |
|
34 | 34 | ((*- block codecell scoped -*)) |
|
35 | 35 | ((*- block input_group -*)) |
|
36 | 36 | ((*- block in_prompt -*))((*- endblock in_prompt -*)) |
|
37 | 37 | ((*- block input -*))((*- endblock input -*)) |
|
38 | 38 | ((*- endblock input_group -*)) |
|
39 | 39 | ((*- if cell.outputs -*)) |
|
40 | 40 | ((*- block output_group -*)) |
|
41 | 41 | ((*- block output_prompt -*))((*- endblock output_prompt -*)) |
|
42 | 42 | ((*- block outputs scoped -*)) |
|
43 | 43 | ((*- for output in cell.outputs -*)) |
|
44 | 44 | ((*- block output scoped -*)) |
|
45 | 45 | ((*- if output.output_type == 'execute_result' -*)) |
|
46 | 46 | ((*- block execute_result scoped -*))((*- endblock execute_result -*)) |
|
47 | 47 | ((*- elif output.output_type == 'stream' -*)) |
|
48 | 48 | ((*- block stream scoped -*)) |
|
49 | 49 | ((*- if output.name == 'stdout' -*)) |
|
50 | 50 | ((*- block stream_stdout scoped -*)) |
|
51 | 51 | ((*- endblock stream_stdout -*)) |
|
52 | 52 | ((*- elif output.name == 'stderr' -*)) |
|
53 | 53 | ((*- block stream_stderr scoped -*)) |
|
54 | 54 | ((*- endblock stream_stderr -*)) |
|
55 | 55 | ((*- endif -*)) |
|
56 | 56 | ((*- endblock stream -*)) |
|
57 | 57 | ((*- elif output.output_type == 'display_data' -*)) |
|
58 | 58 | ((*- block display_data scoped -*)) |
|
59 | 59 | ((*- block data_priority scoped -*)) |
|
60 | 60 | ((*- endblock data_priority -*)) |
|
61 | 61 | ((*- endblock display_data -*)) |
|
62 | 62 | ((*- elif output.output_type == 'error' -*)) |
|
63 | 63 | ((*- block error scoped -*)) |
|
64 | 64 | ((*- for line in output.traceback -*)) |
|
65 | 65 | ((*- block traceback_line scoped -*))((*- endblock traceback_line -*)) |
|
66 | 66 | ((*- endfor -*)) |
|
67 | 67 | ((*- endblock error -*)) |
|
68 | 68 | ((*- endif -*)) |
|
69 | 69 | ((*- endblock output -*)) |
|
70 | 70 | ((*- endfor -*)) |
|
71 | 71 | ((*- endblock outputs -*)) |
|
72 | 72 | ((*- endblock output_group -*)) |
|
73 | 73 | ((*- endif -*)) |
|
74 | 74 | ((*- endblock codecell -*)) |
|
75 | 75 | ((*- elif cell.cell_type in ['markdown'] -*)) |
|
76 | 76 | ((*- block markdowncell scoped-*)) |
|
77 | 77 | ((*- endblock markdowncell -*)) |
|
78 | ((*- elif cell.cell_type in ['heading'] -*)) | |
|
79 | ((*- block headingcell scoped-*)) | |
|
80 | ((*- endblock headingcell -*)) | |
|
81 | 78 | ((*- elif cell.cell_type in ['raw'] -*)) |
|
82 | 79 | ((*- block rawcell scoped -*)) |
|
83 | 80 | ((* if cell.metadata.get('raw_mimetype', '').lower() in resources.get('raw_mimetypes', ['']) *)) |
|
84 | 81 | ((( cell.source ))) |
|
85 | 82 | ((* endif *)) |
|
86 | 83 | ((*- endblock rawcell -*)) |
|
87 | 84 | ((*- else -*)) |
|
88 | 85 | ((*- block unknowncell scoped-*)) |
|
89 | 86 | ((*- endblock unknowncell -*)) |
|
90 | 87 | ((*- endif -*)) |
|
91 | 88 | ((*- endblock any_cell -*)) |
|
92 | 89 | ((*- endfor -*)) |
|
93 | 90 | ((*- endblock body -*)) |
|
94 | 91 | |
|
95 | 92 | ((*- block footer -*)) |
|
96 | 93 | ((*- endblock footer -*)) |
@@ -1,68 +1,63 b'' | |||
|
1 | 1 | {% extends 'display_priority.tpl' %} |
|
2 | 2 | |
|
3 | 3 | |
|
4 | 4 | {% block in_prompt %} |
|
5 | 5 | {% endblock in_prompt %} |
|
6 | 6 | |
|
7 | 7 | {% block output_prompt %} |
|
8 | 8 | {%- endblock output_prompt %} |
|
9 | 9 | |
|
10 | 10 | {% block input %} |
|
11 | 11 | {{ cell.source | indent(4)}} |
|
12 | 12 | {% endblock input %} |
|
13 | 13 | |
|
14 | 14 | {% block error %} |
|
15 | 15 | {{ super() }} |
|
16 | 16 | {% endblock error %} |
|
17 | 17 | |
|
18 | 18 | {% block traceback_line %} |
|
19 | 19 | {{ line | indent | strip_ansi }} |
|
20 | 20 | {% endblock traceback_line %} |
|
21 | 21 | |
|
22 | 22 | {% block execute_result %} |
|
23 | 23 | |
|
24 | 24 | {% block data_priority scoped %} |
|
25 | 25 | {{ super() }} |
|
26 | 26 | {% endblock %} |
|
27 | 27 | {% endblock execute_result %} |
|
28 | 28 | |
|
29 | 29 | {% block stream %} |
|
30 | 30 | {{ output.text | indent }} |
|
31 | 31 | {% endblock stream %} |
|
32 | 32 | |
|
33 | 33 | {% block data_svg %} |
|
34 | 34 | ![svg]({{ output.svg_filename | path2url }}) |
|
35 | 35 | {% endblock data_svg %} |
|
36 | 36 | |
|
37 | 37 | {% block data_png %} |
|
38 | 38 | ![png]({{ output.metadata.filenames['image/png'] | path2url }}) |
|
39 | 39 | {% endblock data_png %} |
|
40 | 40 | |
|
41 | 41 | {% block data_jpg %} |
|
42 | 42 | ![jpeg]({{ output.metadata.filenames['image/jpeg'] | path2url }}) |
|
43 | 43 | {% endblock data_jpg %} |
|
44 | 44 | |
|
45 | 45 | {% block data_latex %} |
|
46 | 46 | {{ output.data['text/latex'] }} |
|
47 | 47 | {% endblock data_latex %} |
|
48 | 48 | |
|
49 | 49 | {% block data_html scoped %} |
|
50 | 50 | {{ output.data['text/html'] }} |
|
51 | 51 | {% endblock data_html %} |
|
52 | 52 | |
|
53 | 53 | {% block data_text scoped %} |
|
54 | 54 | {{ output.data['text/plain'] | indent }} |
|
55 | 55 | {% endblock data_text %} |
|
56 | 56 | |
|
57 | 57 | {% block markdowncell scoped %} |
|
58 | 58 | {{ cell.source }} |
|
59 | 59 | {% endblock markdowncell %} |
|
60 | 60 | |
|
61 | ||
|
62 | {% block headingcell scoped %} | |
|
63 | {{ '#' * cell.level }} {{ cell.source | replace('\n', ' ') }} | |
|
64 | {% endblock headingcell %} | |
|
65 | ||
|
66 | 61 | {% block unknowncell scoped %} |
|
67 | 62 | unknown type {{ cell.type }} |
|
68 | 63 | {% endblock unknowncell %} No newline at end of file |
@@ -1,21 +1,17 b'' | |||
|
1 | 1 | {%- extends 'null.tpl' -%} |
|
2 | 2 | |
|
3 | 3 | {% block header %} |
|
4 | 4 | # coding: utf-8 |
|
5 | 5 | {% endblock header %} |
|
6 | 6 | |
|
7 | 7 | {% block in_prompt %} |
|
8 | 8 | # In[{{ cell.execution_count if cell.execution_count else ' ' }}]: |
|
9 | 9 | {% endblock in_prompt %} |
|
10 | 10 | |
|
11 | 11 | {% block input %} |
|
12 | 12 | {{ cell.source | ipython2python }} |
|
13 | 13 | {% endblock input %} |
|
14 | 14 | |
|
15 | 15 | {% block markdowncell scoped %} |
|
16 | 16 | {{ cell.source | comment_lines }} |
|
17 | 17 | {% endblock markdowncell %} |
|
18 | ||
|
19 | {% block headingcell scoped %} | |
|
20 | {{ '#' * cell.level }}{{ cell.source | replace('\n', ' ') | comment_lines }} | |
|
21 | {% endblock headingcell %} |
@@ -1,92 +1,89 b'' | |||
|
1 | 1 | {# |
|
2 | 2 | |
|
3 | 3 | DO NOT USE THIS AS A BASE, |
|
4 | 4 | IF YOU ARE COPY AND PASTING THIS FILE |
|
5 | 5 | YOU ARE PROBABLY DOING THINGS INCORRECTLY. |
|
6 | 6 | |
|
7 | 7 | Null template, does nothing except defining a basic structure |
|
8 | 8 | To layout the different blocks of a notebook. |
|
9 | 9 | |
|
10 | 10 | Subtemplates can override blocks to define their custom representation. |
|
11 | 11 | |
|
12 | 12 | If one of the block you do overwrite is not a leave block, consider |
|
13 | 13 | calling super. |
|
14 | 14 | |
|
15 | 15 | {%- block nonLeaveBlock -%} |
|
16 | 16 | #add stuff at beginning |
|
17 | 17 | {{ super() }} |
|
18 | 18 | #add stuff at end |
|
19 | 19 | {%- endblock nonLeaveBlock -%} |
|
20 | 20 | |
|
21 | 21 | consider calling super even if it is a leave block, we might insert more blocks later. |
|
22 | 22 | |
|
23 | 23 | #} |
|
24 | 24 | {%- block header -%} |
|
25 | 25 | {%- endblock header -%} |
|
26 | 26 | {%- block body -%} |
|
27 | 27 | {%- for cell in nb.cells -%} |
|
28 | 28 | {%- block any_cell scoped -%} |
|
29 | 29 | {%- if cell.cell_type == 'code' -%} |
|
30 | 30 | {%- block codecell scoped -%} |
|
31 | 31 | {%- block input_group -%} |
|
32 | 32 | {%- block in_prompt -%}{%- endblock in_prompt -%} |
|
33 | 33 | {%- block input -%}{%- endblock input -%} |
|
34 | 34 | {%- endblock input_group -%} |
|
35 | 35 | {%- if cell.outputs -%} |
|
36 | 36 | {%- block output_group -%} |
|
37 | 37 | {%- block output_prompt -%}{%- endblock output_prompt -%} |
|
38 | 38 | {%- block outputs scoped -%} |
|
39 | 39 | {%- for output in cell.outputs -%} |
|
40 | 40 | {%- block output scoped -%} |
|
41 | 41 | {%- if output.output_type == 'execute_result' -%} |
|
42 | 42 | {%- block execute_result scoped -%}{%- endblock execute_result -%} |
|
43 | 43 | {%- elif output.output_type == 'stream' -%} |
|
44 | 44 | {%- block stream scoped -%} |
|
45 | 45 | {%- if output.name == 'stdout' -%} |
|
46 | 46 | {%- block stream_stdout scoped -%} |
|
47 | 47 | {%- endblock stream_stdout -%} |
|
48 | 48 | {%- elif output.name == 'stderr' -%} |
|
49 | 49 | {%- block stream_stderr scoped -%} |
|
50 | 50 | {%- endblock stream_stderr -%} |
|
51 | 51 | {%- endif -%} |
|
52 | 52 | {%- endblock stream -%} |
|
53 | 53 | {%- elif output.output_type == 'display_data' -%} |
|
54 | 54 | {%- block display_data scoped -%} |
|
55 | 55 | {%- block data_priority scoped -%} |
|
56 | 56 | {%- endblock data_priority -%} |
|
57 | 57 | {%- endblock display_data -%} |
|
58 | 58 | {%- elif output.output_type == 'error' -%} |
|
59 | 59 | {%- block error scoped -%} |
|
60 | 60 | {%- for line in output.traceback -%} |
|
61 | 61 | {%- block traceback_line scoped -%}{%- endblock traceback_line -%} |
|
62 | 62 | {%- endfor -%} |
|
63 | 63 | {%- endblock error -%} |
|
64 | 64 | {%- endif -%} |
|
65 | 65 | {%- endblock output -%} |
|
66 | 66 | {%- endfor -%} |
|
67 | 67 | {%- endblock outputs -%} |
|
68 | 68 | {%- endblock output_group -%} |
|
69 | 69 | {%- endif -%} |
|
70 | 70 | {%- endblock codecell -%} |
|
71 | 71 | {%- elif cell.cell_type in ['markdown'] -%} |
|
72 | 72 | {%- block markdowncell scoped-%} |
|
73 | 73 | {%- endblock markdowncell -%} |
|
74 | {%- elif cell.cell_type in ['heading'] -%} | |
|
75 | {%- block headingcell scoped-%} | |
|
76 | {%- endblock headingcell -%} | |
|
77 | 74 | {%- elif cell.cell_type in ['raw'] -%} |
|
78 | 75 | {%- block rawcell scoped -%} |
|
79 | 76 | {% if cell.metadata.get('raw_mimetype', '').lower() in resources.get('raw_mimetypes', ['']) %} |
|
80 | 77 | {{ cell.source }} |
|
81 | 78 | {% endif %} |
|
82 | 79 | {%- endblock rawcell -%} |
|
83 | 80 | {%- else -%} |
|
84 | 81 | {%- block unknowncell scoped-%} |
|
85 | 82 | {%- endblock unknowncell -%} |
|
86 | 83 | {%- endif -%} |
|
87 | 84 | {%- endblock any_cell -%} |
|
88 | 85 | {%- endfor -%} |
|
89 | 86 | {%- endblock body -%} |
|
90 | 87 | |
|
91 | 88 | {%- block footer -%} |
|
92 | 89 | {%- endblock footer -%} |
@@ -1,190 +1,189 b'' | |||
|
1 | 1 | { |
|
2 | 2 | "cells": [ |
|
3 | 3 | { |
|
4 |
"cell_type": " |
|
|
5 | "level": 1, | |
|
4 | "cell_type": "markdown", | |
|
6 | 5 | "metadata": {}, |
|
7 | 6 | "source": [ |
|
8 | "A simple SymPy example" | |
|
7 | "# A simple SymPy example" | |
|
9 | 8 | ] |
|
10 | 9 | }, |
|
11 | 10 | { |
|
12 | 11 | "cell_type": "markdown", |
|
13 | 12 | "metadata": {}, |
|
14 | 13 | "source": [ |
|
15 | 14 | "First we import SymPy and initialize printing:" |
|
16 | 15 | ] |
|
17 | 16 | }, |
|
18 | 17 | { |
|
19 | 18 | "cell_type": "code", |
|
20 | 19 | "execution_count": 2, |
|
21 | 20 | "metadata": { |
|
22 | 21 | "collapsed": false |
|
23 | 22 | }, |
|
24 | 23 | "outputs": [], |
|
25 | 24 | "source": [ |
|
26 | 25 | "from sympy import init_printing\n", |
|
27 | 26 | "from sympy import *\n", |
|
28 | 27 | " init_printing()" |
|
29 | 28 | ] |
|
30 | 29 | }, |
|
31 | 30 | { |
|
32 | 31 | "cell_type": "markdown", |
|
33 | 32 | "metadata": {}, |
|
34 | 33 | "source": [ |
|
35 | 34 | "Create a few symbols:" |
|
36 | 35 | ] |
|
37 | 36 | }, |
|
38 | 37 | { |
|
39 | 38 | "cell_type": "code", |
|
40 | 39 | "execution_count": 4, |
|
41 | 40 | "metadata": { |
|
42 | 41 | "collapsed": false |
|
43 | 42 | }, |
|
44 | 43 | "outputs": [], |
|
45 | 44 | "source": [ |
|
46 | 45 | "x,y,z = symbols('x y z')" |
|
47 | 46 | ] |
|
48 | 47 | }, |
|
49 | 48 | { |
|
50 | 49 | "cell_type": "markdown", |
|
51 | 50 | "metadata": {}, |
|
52 | 51 | "source": [ |
|
53 | 52 | "Here is a basic expression:" |
|
54 | 53 | ] |
|
55 | 54 | }, |
|
56 | 55 | { |
|
57 | 56 | "cell_type": "code", |
|
58 | 57 | "execution_count": 6, |
|
59 | 58 | "metadata": { |
|
60 | 59 | "collapsed": false |
|
61 | 60 | }, |
|
62 | 61 | "outputs": [ |
|
63 | 62 | { |
|
64 | 63 | "data": { |
|
65 | 64 | "image/png": [ |
|
66 | 65 | "iVBORw0KGgoAAAANSUhEUgAAAKMAAAAZBAMAAACvE4OgAAAAMFBMVEX///8AAAAAAAAAAAAAAAAA\n", |
|
67 | 66 | "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEHarIkSJZt3NVLsy\n", |
|
68 | 67 | "me8Q6PJIAAACz0lEQVRIDa1UTWjUQBT+ZpvdzW7TGlrxItjYSg/C6vbiDwjmoCgUpHioPYhdqig9\n", |
|
69 | 68 | "FJYiPYmW4klB14NgFGnw4EHpj7UgUtTFXhSEBgVBxIOFggWVrrUqiMY3mZkkLNIK7oN575vvvfky\n", |
|
70 | 69 | "8yYJIGzgkSlRrULKrivVSkvq6LbxtcaSjV3aSo0lgWyl5pK69V+SRlEsPxNTGYhhDrV3M2Ue2etc\n", |
|
71 | 70 | "EDmuMmM+IjolrCuHXNoLoQDNSAXdzbjsfFVKTY1vCgFXFIxenG4cFSSzRewAPnN0FugXjPDr45MQ\n", |
|
72 | 71 | "JwoKtitgXL9zT+CsJeIHYG+Z4H1gwhRU4G/FcAQbbYU3KdDo+0sCK8lRU0guA72uKqMYk9RehHxP\n", |
|
73 | 72 | "iDIu0NS2v90KGShJYi7T7tgvkrQ2vIT2XtRISWNra6lzGc8/PW3ji4PL7Vmge095YIX0iB71NCaZ\n", |
|
74 | 73 | "5N3XyM0VCuNIyFNIyY3AMG/KDUvjn90DGmwq9wpIl5AyU5WsTYy0aJf6JFGB5An3Der5jExKHjNR\n", |
|
75 | 74 | "4JKPge/EXqDBoOXpkxkmkJHFfAFRVhDIveWA0S57N2Me6yw+DSX1n1uCq3sIfCF2IcjNkjeWyKli\n", |
|
76 | 75 | "ginHubboOB4vSNAjyaiXE26ygrkyTfod55Lj3CTE+n2P73ImJpnk6wJJKjYJSwt3OQbNJu4icM5s\n", |
|
77 | 76 | "KGGbzMuD70N6JSbJD44x7pLDyJrbkfiLpOEhYVMJSVEj83x5YFLyNrAzJsmvJ+uhLrieXvcJDshy\n", |
|
78 | 77 | "HtQuD54c2IWWEnSXfUTDZJJfAjcpOW5imp9aHvw4ZZ4NDV4FGjw0tzadKgbFwinJUd//AT0P1tdW\n", |
|
79 | 78 | "BtuRU39oKdk9ONQ163fM+nvu/s4D/FX30otdQIZGlSnJKpq6KUxKVqV1WxGHFIhishjhEO1Gi3r4\n", |
|
80 | 79 | "kZCMg+hH1henV8EjmFoly1PTMs/Uadaox+FceY2STpmvt9co/Pe0Jvt1GvgDK/Osw/4jQ4wAAAAA\n", |
|
81 | 80 | "SUVORK5CYII=\n" |
|
82 | 81 | ], |
|
83 | 82 | "text/latex": [ |
|
84 | 83 | "$$x^{2} + 2.0 y + \\sin{\\left (z \\right )}$$" |
|
85 | 84 | ], |
|
86 | 85 | "text/plain": [ |
|
87 | 86 | " 2 \n", |
|
88 | 87 | "x + 2.0\u22c5y + sin(z)" |
|
89 | 88 | ] |
|
90 | 89 | }, |
|
91 | 90 | "execution_count": 6, |
|
92 | 91 | "metadata": {}, |
|
93 | 92 | "output_type": "execute_result" |
|
94 | 93 | } |
|
95 | 94 | ], |
|
96 | 95 | "source": [ |
|
97 | 96 | "e = x**2 + 2.0*y + sin(z); e" |
|
98 | 97 | ] |
|
99 | 98 | }, |
|
100 | 99 | { |
|
101 | 100 | "cell_type": "code", |
|
102 | 101 | "execution_count": 7, |
|
103 | 102 | "metadata": { |
|
104 | 103 | "collapsed": false |
|
105 | 104 | }, |
|
106 | 105 | "outputs": [ |
|
107 | 106 | { |
|
108 | 107 | "data": { |
|
109 | 108 | "image/png": [ |
|
110 | 109 | "iVBORw0KGgoAAAANSUhEUgAAABQAAAAOBAMAAADd6iHDAAAAMFBMVEX///8AAAAAAAAAAAAAAAAA\n", |
|
111 | 110 | "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAIpm7MhCriUTv3c12\n", |
|
112 | 111 | "VGZoascqAAAAgElEQVQIHWNgVDJ2YICAMAb2H1BmKgPDTChzFgNDvgOEvT8AzgQKrA9gPZPYUwNk\n", |
|
113 | 112 | "cXxnCGd4dWA1kMllwFDKUB9wEchUZmAIYNgMZDDwJIDIPyDiEgOjAAPLFwZWBhYFBh6BqzwfGI4y\n", |
|
114 | 113 | "SJUXZXH8Zf7A+IBh////v1hzjh5/xwAAW80hUDE8HYkAAAAASUVORK5CYII=\n" |
|
115 | 114 | ], |
|
116 | 115 | "text/latex": [ |
|
117 | 116 | "$$2 x$$" |
|
118 | 117 | ], |
|
119 | 118 | "text/plain": [ |
|
120 | 119 | "2\u22c5x" |
|
121 | 120 | ] |
|
122 | 121 | }, |
|
123 | 122 | "execution_count": 7, |
|
124 | 123 | "metadata": {}, |
|
125 | 124 | "output_type": "execute_result" |
|
126 | 125 | } |
|
127 | 126 | ], |
|
128 | 127 | "source": [ |
|
129 | 128 | "diff(e, x)" |
|
130 | 129 | ] |
|
131 | 130 | }, |
|
132 | 131 | { |
|
133 | 132 | "cell_type": "code", |
|
134 | 133 | "execution_count": 8, |
|
135 | 134 | "metadata": { |
|
136 | 135 | "collapsed": false |
|
137 | 136 | }, |
|
138 | 137 | "outputs": [ |
|
139 | 138 | { |
|
140 | 139 | "data": { |
|
141 | 140 | "image/png": [ |
|
142 | 141 | "iVBORw0KGgoAAAANSUhEUgAAALsAAAAZBAMAAACbakK8AAAAMFBMVEX///8AAAAAAAAAAAAAAAAA\n", |
|
143 | 142 | "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEHarIkSJZt3NVLsy\n", |
|
144 | 143 | "me8Q6PJIAAADAklEQVRIDbVVS2gTURQ90/wmk0k6tCJCsR1SKShIsxE3CgNWBKUxq9qFmqFqShfF\n", |
|
145 | 144 | "UKQrkaDiF0pcCKYgBBcuBLV+wIWKARe6kQ4UhNKKWdiF4KIptmA/xPvmzZuMxdYUzIPcd+655568\n", |
|
146 | 145 | "vLlJAL6G32oOasQWNHz5Rvg6nrKh/mygfSzlX2ygPaBUGmov6//NXs1yq4sex2EPrsHemTd2snNg\n", |
|
147 | 146 | "tkb+Cx1zBL6SqwxZLvQAKYHzKZaPY4fh4TeHd0S5Nox9OClItm/jiU9DrEwwVEawpiVis9VkimqX\n", |
|
148 | 147 | "AOr4o2cCs/0BT2I5+FYJRhJbePQxgzcD7QLEqtV5gdnu2Icr3L45gcCyt74Z7neL4SLQ0nm4S+dM\n", |
|
149 | 148 | "YCz1gSPHnhKZDWyHhcCCNKwjqaF/TkwGl0L6nClie/wc1D1xdoNsSLhT0IJkhi7Lzr22xb8keE/N\n", |
|
150 | 149 | "Pm0Sc9yEuhRUyuiG9HzvFNeImCyq39SriOhtQI7IV/TiTqE8glqwohjE0NJwiANxOZTdZoxtfzSa\n", |
|
151 | 150 | "x2tI8DtHcKQoQFmV6f1XT2swibxFL+6k5EgenhBCqKLTPX3ULnaYdDlaTMcCSd8zuXTvBq2bJUJr\n", |
|
152 | 151 | "lE4WgSV5ZRdBzLFgO6nzhJp1ltvrlB2HCoWxQuG+jTvt2GxBWUZaU2mMApZNuSHA3vJpCliRhqqs\n", |
|
153 | 152 | "ZtvbTrb9ZIk+i70Ut1OcnpgeKskTCFUwjaYy8Jhr3eiefq0HIfa7yC6HOwVyULRuNDn21JngbcL+\n", |
|
154 | 153 | "E8A+MNnSxb+w59+Cj2tELJBbjEZr8SGwn0j2aLkTPdp08R2OcKV6fXB3ikPH3n8tM5WTfrETtZcw\n", |
|
155 | 154 | "g3QWH0dH7nKNiMkszqo/EDafaHhJ5Bm6ee4UtdAabxnMcmUUl0SnYx+uVqs5XAGN9QGgdeCrASv0\n", |
|
156 | 155 | "3TmCsJcOdhnozexD38goK9HXynEKr1OKDs9guhQD039kGySyIQpJAdbvJ9YTlPvyUl3/aLUf34G/\n", |
|
157 | 156 | "uGxIyXpE37DoLbAHwJaU53t9MRCfrU8o/k4iRn36Lar8Wd5wAfgN4R6xelyy/ssAAAAASUVORK5C\n", |
|
158 | 157 | "YII=\n" |
|
159 | 158 | ], |
|
160 | 159 | "text/latex": [ |
|
161 | 160 | "$$x^{2} z + 2.0 y z - \\cos{\\left (z \\right )}$$" |
|
162 | 161 | ], |
|
163 | 162 | "text/plain": [ |
|
164 | 163 | " 2 \n", |
|
165 | 164 | "x \u22c5z + 2.0\u22c5y\u22c5z - cos(z)" |
|
166 | 165 | ] |
|
167 | 166 | }, |
|
168 | 167 | "execution_count": 8, |
|
169 | 168 | "metadata": {}, |
|
170 | 169 | "output_type": "execute_result" |
|
171 | 170 | } |
|
172 | 171 | ], |
|
173 | 172 | "source": [ |
|
174 | 173 | "integrate(e, z)" |
|
175 | 174 | ] |
|
176 | 175 | }, |
|
177 | 176 | { |
|
178 | 177 | "cell_type": "code", |
|
179 | 178 | "execution_count": null, |
|
180 | 179 | "metadata": { |
|
181 | 180 | "collapsed": false |
|
182 | 181 | }, |
|
183 | 182 | "outputs": [], |
|
184 | 183 | "source": [] |
|
185 | 184 | } |
|
186 | 185 | ], |
|
187 | 186 | "metadata": {}, |
|
188 | 187 | "nbformat": 4, |
|
189 | 188 | "nbformat_minor": 0 |
|
190 | 189 | } No newline at end of file |
@@ -1,1586 +1,1584 b'' | |||
|
1 | 1 | { |
|
2 | 2 | "cells": [ |
|
3 | 3 | { |
|
4 |
"cell_type": " |
|
|
5 | "level": 1, | |
|
4 | "cell_type": "markdown", | |
|
6 | 5 | "metadata": {}, |
|
7 | 6 | "source": [ |
|
8 | "NumPy and Matplotlib examples" | |
|
7 | "# NumPy and Matplotlib examples" | |
|
9 | 8 | ] |
|
10 | 9 | }, |
|
11 | 10 | { |
|
12 | 11 | "cell_type": "markdown", |
|
13 | 12 | "metadata": {}, |
|
14 | 13 | "source": [ |
|
15 | 14 | "First import NumPy and Matplotlib:" |
|
16 | 15 | ] |
|
17 | 16 | }, |
|
18 | 17 | { |
|
19 | 18 | "cell_type": "code", |
|
20 | 19 | "execution_count": 1, |
|
21 | 20 | "metadata": { |
|
22 | 21 | "collapsed": false |
|
23 | 22 | }, |
|
24 | 23 | "outputs": [ |
|
25 | 24 | { |
|
26 | 25 | "name": "stdout", |
|
27 | 26 | "output_type": "stream", |
|
28 | 27 | "text": [ |
|
29 | 28 | "module://IPython.kernel.zmq.pylab.backend_inline\n" |
|
30 | 29 | ] |
|
31 | 30 | } |
|
32 | 31 | ], |
|
33 | 32 | "source": [ |
|
34 | 33 | "%matplotlib inline\n", |
|
35 | 34 | "import matplotlib\n", |
|
36 | 35 | "import matplotlib.pyplot as plt\n", |
|
37 | 36 | "print(matplotlib.backends.backend)" |
|
38 | 37 | ] |
|
39 | 38 | }, |
|
40 | 39 | { |
|
41 | 40 | "cell_type": "code", |
|
42 | 41 | "execution_count": 2, |
|
43 | 42 | "metadata": { |
|
44 | 43 | "collapsed": false |
|
45 | 44 | }, |
|
46 | 45 | "outputs": [], |
|
47 | 46 | "source": [ |
|
48 | 47 | "from IPython.display import set_matplotlib_formats\n", |
|
49 | 48 | "set_matplotlib_formats('png', 'pdf')\n", |
|
50 | 49 | "matplotlib.rcParams['figure.figsize'] = (2,1)" |
|
51 | 50 | ] |
|
52 | 51 | }, |
|
53 | 52 | { |
|
54 | 53 | "cell_type": "code", |
|
55 | 54 | "execution_count": 3, |
|
56 | 55 | "metadata": { |
|
57 | 56 | "collapsed": false |
|
58 | 57 | }, |
|
59 | 58 | "outputs": [ |
|
60 | 59 | { |
|
61 | 60 | "data": { |
|
62 | 61 | "text/plain": [ |
|
63 | 62 | "{matplotlib.figure.Figure: <function IPython.core.pylabtools.<lambda>>}" |
|
64 | 63 | ] |
|
65 | 64 | }, |
|
66 | 65 | "execution_count": 3, |
|
67 | 66 | "metadata": {}, |
|
68 | 67 | "output_type": "execute_result" |
|
69 | 68 | } |
|
70 | 69 | ], |
|
71 | 70 | "source": [ |
|
72 | 71 | "ip.display_formatter.formatters['application/pdf'].type_printers" |
|
73 | 72 | ] |
|
74 | 73 | }, |
|
75 | 74 | { |
|
76 | 75 | "cell_type": "code", |
|
77 | 76 | "execution_count": 4, |
|
78 | 77 | "metadata": { |
|
79 | 78 | "collapsed": false |
|
80 | 79 | }, |
|
81 | 80 | "outputs": [], |
|
82 | 81 | "source": [ |
|
83 | 82 | "import numpy as np" |
|
84 | 83 | ] |
|
85 | 84 | }, |
|
86 | 85 | { |
|
87 | 86 | "cell_type": "markdown", |
|
88 | 87 | "metadata": {}, |
|
89 | 88 | "source": [ |
|
90 | 89 | "Now we show some very basic examples of how they can be used." |
|
91 | 90 | ] |
|
92 | 91 | }, |
|
93 | 92 | { |
|
94 | 93 | "cell_type": "code", |
|
95 | 94 | "execution_count": 5, |
|
96 | 95 | "metadata": { |
|
97 | 96 | "collapsed": false |
|
98 | 97 | }, |
|
99 | 98 | "outputs": [], |
|
100 | 99 | "source": [ |
|
101 | 100 | "a = np.random.uniform(size=(100,100))" |
|
102 | 101 | ] |
|
103 | 102 | }, |
|
104 | 103 | { |
|
105 | 104 | "cell_type": "code", |
|
106 | 105 | "execution_count": 6, |
|
107 | 106 | "metadata": { |
|
108 | 107 | "collapsed": false |
|
109 | 108 | }, |
|
110 | 109 | "outputs": [ |
|
111 | 110 | { |
|
112 | 111 | "data": { |
|
113 | 112 | "text/plain": [ |
|
114 | 113 | "(100, 100)" |
|
115 | 114 | ] |
|
116 | 115 | }, |
|
117 | 116 | "execution_count": 6, |
|
118 | 117 | "metadata": {}, |
|
119 | 118 | "output_type": "execute_result" |
|
120 | 119 | } |
|
121 | 120 | ], |
|
122 | 121 | "source": [ |
|
123 | 122 | "a.shape" |
|
124 | 123 | ] |
|
125 | 124 | }, |
|
126 | 125 | { |
|
127 | 126 | "cell_type": "code", |
|
128 | 127 | "execution_count": 7, |
|
129 | 128 | "metadata": { |
|
130 | 129 | "collapsed": false |
|
131 | 130 | }, |
|
132 | 131 | "outputs": [], |
|
133 | 132 | "source": [ |
|
134 | 133 | "evs = np.linalg.eigvals(a)" |
|
135 | 134 | ] |
|
136 | 135 | }, |
|
137 | 136 | { |
|
138 | 137 | "cell_type": "code", |
|
139 | 138 | "execution_count": 8, |
|
140 | 139 | "metadata": { |
|
141 | 140 | "collapsed": false |
|
142 | 141 | }, |
|
143 | 142 | "outputs": [ |
|
144 | 143 | { |
|
145 | 144 | "data": { |
|
146 | 145 | "text/plain": [ |
|
147 | 146 | "(100,)" |
|
148 | 147 | ] |
|
149 | 148 | }, |
|
150 | 149 | "execution_count": 8, |
|
151 | 150 | "metadata": {}, |
|
152 | 151 | "output_type": "execute_result" |
|
153 | 152 | } |
|
154 | 153 | ], |
|
155 | 154 | "source": [ |
|
156 | 155 | "evs.shape" |
|
157 | 156 | ] |
|
158 | 157 | }, |
|
159 | 158 | { |
|
160 |
"cell_type": " |
|
|
161 | "level": 2, | |
|
159 | "cell_type": "markdown", | |
|
162 | 160 | "metadata": {}, |
|
163 | 161 | "source": [ |
|
164 | "Here is a very long heading that pandoc will wrap and wrap and wrap and wrap and wrap and wrap and wrap and wrap and wrap and wrap and wrap and wrap" | |
|
162 | "## Here is a very long heading that pandoc will wrap and wrap and wrap and wrap and wrap and wrap and wrap and wrap and wrap and wrap and wrap and wrap" | |
|
165 | 163 | ] |
|
166 | 164 | }, |
|
167 | 165 | { |
|
168 | 166 | "cell_type": "markdown", |
|
169 | 167 | "metadata": {}, |
|
170 | 168 | "source": [ |
|
171 | 169 | "Here is a cell that has both text and PNG output:" |
|
172 | 170 | ] |
|
173 | 171 | }, |
|
174 | 172 | { |
|
175 | 173 | "cell_type": "code", |
|
176 | 174 | "execution_count": 9, |
|
177 | 175 | "metadata": { |
|
178 | 176 | "collapsed": false |
|
179 | 177 | }, |
|
180 | 178 | "outputs": [ |
|
181 | 179 | { |
|
182 | 180 | "data": { |
|
183 | 181 | "text/plain": [ |
|
184 | 182 | "(array([97, 2, 0, 0, 0, 0, 0, 0, 0, 1]),\n", |
|
185 | 183 | " array([ -2.59479443, 2.67371141, 7.94221725, 13.21072308,\n", |
|
186 | 184 | " 18.47922892, 23.74773476, 29.0162406 , 34.28474644,\n", |
|
187 | 185 | " 39.55325228, 44.82175812, 50.09026395]),\n", |
|
188 | 186 | " <a list of 10 Patch objects>)" |
|
189 | 187 | ] |
|
190 | 188 | }, |
|
191 | 189 | "execution_count": 9, |
|
192 | 190 | "metadata": {}, |
|
193 | 191 | "output_type": "execute_result" |
|
194 | 192 | }, |
|
195 | 193 | { |
|
196 | 194 | "data": { |
|
197 | 195 | "application/pdf": [ |
|
198 | 196 | "JVBERi0xLjQKJazcIKu6CjEgMCBvYmoKPDwgL1R5cGUgL0NhdGFsb2cgL1BhZ2VzIDIgMCBSID4+\n", |
|
199 | 197 | "CmVuZG9iago4IDAgb2JqCjw8IC9YT2JqZWN0IDcgMCBSIC9QYXR0ZXJuIDUgMCBSCi9Qcm9jU2V0\n", |
|
200 | 198 | "IFsgL1BERiAvVGV4dCAvSW1hZ2VCIC9JbWFnZUMgL0ltYWdlSSBdIC9FeHRHU3RhdGUgNCAwIFIK\n", |
|
201 | 199 | "L1NoYWRpbmcgNiAwIFIgL0ZvbnQgMyAwIFIgPj4KZW5kb2JqCjEwIDAgb2JqCjw8IC9Hcm91cCA8\n", |
|
202 | 200 | "PCAvQ1MgL0RldmljZVJHQiAvUyAvVHJhbnNwYXJlbmN5IC9UeXBlIC9Hcm91cCA+PiAvUGFyZW50\n", |
|
203 | 201 | "IDIgMCBSCi9NZWRpYUJveCBbIDAgMCAxNTIuMzk4NDM3NSA4Ny4xOTIxODc1IF0gL1Jlc291cmNl\n", |
|
204 | 202 | "cyA4IDAgUiAvVHlwZSAvUGFnZQovQ29udGVudHMgOSAwIFIgPj4KZW5kb2JqCjkgMCBvYmoKPDwg\n", |
|
205 | 203 | "L0ZpbHRlciAvRmxhdGVEZWNvZGUgL0xlbmd0aCAxMSAwIFIgPj4Kc3RyZWFtCnicxZi/btwwDMYz\n", |
|
206 | 204 | "a+wTCJ3aRSEpiZLGHtAG6FbkgL5AmwTBXYCmQ16/dJycRcWq7SV3k81Pf76fzyZpo703l1/Q3v61\n", |
|
207 | 205 | "ZL9bsE8W7ZUBOTpajOR8ycGnKOcHdZ6Tw0KY5fAgojq9Mw+yKA2Lgiv+9WdvZeCVoewCR6ZoCVyk\n", |
|
208 | 206 | "jHIkewVw0IYPdTix8y/hao0qKvveiHOhcF5t6qJgqWDPRRXlkwmzm92vHp1g8rYzzf5on8xuby+/\n", |
|
209 | 207 | "oUWw+xsjO2L0w+gk06Ld/zKfPn64wAv4bPf39uu+XeGZwITgAuSQCQMVZbtRlHWt1fYbZRNCIAdA\n", |
|
210 | 208 | "5F/mnjAWEFiiEb0vlGNSCI2iELRWIzTKJoQYXSglJU7PcyeEpf9BDFAJWDhQZgXRKApCazVEo2yC\n", |
|
211 | 209 | "SOiQ0efhCnANQQsQhRz5BNHHhEFBNIqC0FoN0SibICR5QCjxde4E4RcgELLDVAqCTPQ6nzSSwmjE\n", |
|
212 | 210 | "mqOVNoEgkCuFwuvkiSQskVBwSDTejKhJGkmTaFGRNNI2Esyu5PLyp9QkcYlkLpHr/K4J5jK8Gr/R\n", |
|
213 | 211 | "uQ9Sc8bxlW1esL1YD6BjermIrTGdHI8VAXm47sDr8unkz6Pj/Mb1FG1c18Nnw6tcyzM/bIahMryU\n", |
|
214 | 212 | "eCZzUkOk+rSWp2hjuR4+G15pGUazvjgPle+lJ3RyGIPUvje+p2jjux4+G159qSPIZpXl9fc0RykT\n", |
|
215 | 213 | "byxP0cZyPXw2vNby8yy5p6hynVe77vRaXKeDFemDNxVUuc6JXKqfQWkIJs9/ZpMColBaaSmyffxt\n", |
|
216 | 214 | "f9qHsZ12BFKZMbIUZxkbEBOHBCw20unEPk49atUtXxlhoITscwhNv5cdJ5TWC1TVO2ghBUkqYQRX\n", |
|
217 | 215 | "S1WC9Mw788O+J9S896ON0gXIxBDZqwp4aBUxFQb3puE9CefA6rk/Dk+NzJQcSZLgFZdSzH+IK+Xd\n", |
|
218 | 216 | "wXr2pW/1LnNhOaeowZRiusjnBevZP9o8ZK4i60pTrp8vpZgu8nnBevalSQfHsiYDSJekTCrFdJHP\n", |
|
219 | 217 | "C9azL2BFsn2W/MaQGrBaMV3kM4N17A+vI0k8JOZEgM2nESWZLvR50boAwoaylaTvBEneMzSbkkwf\n", |
|
220 | 218 | "+8xwPYLx7YtYXAafC2s4JRkpW5B5jtvW0gg3mk4+UZSmm9SHrBX9z/WKNxc9fsvXuu7w+ebt2ph/\n", |
|
221 | 219 | "ACMXFgplbmRzdHJlYW0KZW5kb2JqCjExIDAgb2JqCjg3MAplbmRvYmoKMTYgMCBvYmoKPDwgL0Zp\n", |
|
222 | 220 | "bHRlciAvRmxhdGVEZWNvZGUgL0xlbmd0aDEgMTkgMCBSIC9MZW5ndGggMjAgMCBSID4+CnN0cmVh\n", |
|
223 | 221 | "bQp4nNS9eYAdVZ0vfurudavq3rr7vvftvdOdTtIJi6QTsnQATdhCgsYECRAWIVFAwAUGWQL6JjDj\n", |
|
224 | 222 | "AEEQRJYAvsnNnbZZxjfkzVMExhl7HImgeZBRCIn6BnUcRudB8vt8zqm66QScef/+DqnvreXUWb6f\n", |
|
225 | 223 | "73pO2QpNCBEH8Ynq8iVLlwleawdAhLl81cozz//y80lcm0LoZyw/8+zFIiXCQvvNBj5feebw6M3v\n", |
|
226 | 224 | "9H4RL+zA9YbzP3ne5v959xPrhTj9QSEC2fOvvrIaXKRVhTj3RDyvXrj5ok9etDjUI8Q5T+Od0y+6\n", |
|
227 | 225 | "7NoLR5ee8b+EWLdJaGdt2LTxk9fkfn3RLCFCWSFWbN10wXkbn8ze+XPUHcT7Y5twIzjoXYPrjbju\n", |
|
228 | 226 | "2vTJK68pvnny6UJ4QujPvvSCT12+7NTTbxHarheEqC+57Irzz1v629+uRv8fE8Ib/uR512z23hfG\n", |
|
229 | 227 | "2LWtHM/l533ygq985Ml/EdqPMD/jbzdf8ekr77zla3cJ7fVpjGHW5k9dsPmkX106T4i1eK4NKd6I\n", |
|
230 | 228 | "xZenf/fv66Mn/psoeCWjPtds3cDf7994/87Daw/t8x7wfhOXuvAIVfCe98ChPyM9vPbwWryliaOK\n", |
|
231 | 229 | "dhPvgG4UQXE2sFDPw5iZ0B8B0YTXE9XuEH7h89zuAQfEqepX+7gY1bKs5/d6+OPFUHauEtVT3LZP\n", |
|
232 | 230 | "W/GRlWJcVP+vB2P4a45BW4rbX5X9/sh7j6jiPw+Hqv3OGU0aDf3lBxxXiw2e3WJEHm+K1Z7TcX3s\n", |
|
233 | 231 | "8aawPINigzeMOj8UG7SQPJZrocNv4/gNzj3az0SEbaE/HhHvdbK+OhaLEW9LLJS/H3B4TlJ1ZF+D\n", |
|
234 | 232 | "YlQeJ6E93McYz3rfcf7h99Aexx7wnHT4t51jUGTkEURbziF+LU7gr/cs595u5/desQrHWu3bouKt\n", |
|
235 | 233 | "igF573wxoX0KeLwmTtd8wtR8h/8Vv4tw1MSvD78p7/9OrMBc0e7hn6tfjHNQfERep8XZOBahvRzu\n", |
|
236 | 234 | "ldFeL377OB/gPIdtoM+P4HoA7y3FcQ7ORz7gGIM8baEkEj/5zulixGn/bK0XfeZkvyPOr8DRLXYc\n", |
|
237 | 235 | "Xos+ycez0Nc7fA9jnIvjQ9oJ4gQcS1FvAs8mtQ+j/q95Lk7g2OX88A6Of0b9CTk29nsv5yYC4N/J\n", |
|
238 | 236 | "ePYbZ/wT+L0Jvyc74+Vvg2OceXjvlfwpy+tBsQkY9+AY1y4WY9rpoqL9iajgWa98Dt5D9kfA6zEc\n", |
|
239 | 237 | "Ie8i0e3OF3zIuWMhTzG+YRyDwOx+HOvdA+8tmHFs1E4TpxILjCGrPSFqPDCOk4gRecyxE2+pB4Pi\n", |
|
240 | 238 | "LNSPyHGAlxjnIMZZx5z3oP8JWRfXcu7HHMRIyv8PRQS/PLfdwzN4+BD6zfBgu5RPxecO33GI1ezH\n", |
|
241 | 239 | "weA3zvEmx43fFxxZIS83eL4movI4IIblwTHMEVWMYcLzMfDkTdGn/Rp8rYgLtP9z+Pe4l/N8TywH\n", |
|
242 | 240 | "j9fTHoCHZ+BY7vyeQZkhj4+yCa49mGkXaAM+wDbQJsw8aB+UjYA+hA6/C9twBo7EMfahc3RshGsn\n", |
|
243 | 241 | "XJswsx/XJhxtG44cH2QjcEgb8UfsAnV35iF1Venr+/Xx/GMOhbsJbF7B8VvgEqLezNQd58jDy53j\n", |
|
244 | 242 | "6Id7xGfqCGUURxJH2ZXRzgF5nHl8kOzJQ8md3ZGzFnj7U8jlh6UOSUzJC5QR+kld9/uFN+CUoJ8l\n", |
|
245 | 243 | "6A8GPSy+gN8fCgZDekgWf0g+VlX1gN8pHtwP4K4v6A94vfJFr9/n8Xn8Hq8X9/y4CPg9HlUbHQb9\n", |
|
246 | 244 | "Xq9XvYr7QZ8PV6iuuvSg75BHvqZKCC+GQvINtoIzHd37fPJ99hX04AJPvQH+C3k9ul+17vehbTxj\n", |
|
247 | 245 | "XVnT4xQvJhyUcw3iKYYu5+Rx2RB02CCLywd5TSYcKQ4jnL5QAoHOfdWjnJUzGE6albzu5P0cHSbi\n", |
|
248 | 246 | "DegIBcLEQfYY4CHHEQgFvbI6miMGDg6BkDNMVtTVKCQOuoTOBzhkL152DRQwM698BcwNeDzqBXQY\n", |
|
249 | 247 | "DKi2MXX8C3KEAY8aN36CIY+O+kFXNnRUCoV8Xh8v0KDXG0b3nanhDnAIeCkHpCGfJxzwOWOTDA2Q\n", |
|
250 | 248 | "QcfgQJaS/ayAriTPPYoNQZcNnHIw6PKBwiCZcKSounogEDgKGKc40/F04J2Bgyv1Ph9nHwQOhhEI\n", |
|
251 | 249 | "CK/sISj7JeoBPaRwgFiGdV3ngRLQg+74QsFwh1HAEwhBiPRAUOHgpWhCOL2UXdTzecl6VRsdSpTV\n", |
|
252 | 250 | "WDHPkMTBq3iKH8i+DviC7kzDeFnXMQFeoEGv1whSYp2peX06NYU4hAiF7vMaDg4BpcAB1vUeXcA+\n", |
|
253 | 251 | "8i9ITcZ8A5y8R7Eh5LKBU5aK6FV4Kia4KLmMCIU7Aul35VjWcabjTBW3fEqHleLI9wkuZh9CXGxa\n", |
|
254 | 252 | "xEH2EFK9YADBsK64iREaum6YhiyhMAcYUsMxJGK84cU5Xgz5wzhcHMAYL7jmM4Kogq5wrmZomgE5\n", |
|
255 | 253 | "uQD1z4P7IRqZoItDgDgYXsUJSkaIF1AiH+URrYS9XgtjVTOhdPkMWhlw1qdDJYNhv9cM+h0F1/1S\n", |
|
256 | 254 | "vQNKrGcU6LguK3AYEC925PEqHrhsCKPoussHKCY4ASY4KDlA6SFDckExNujKs6NIUhR9zkyU4Qr4\n", |
|
257 | 255 | "HJFSmhSCxOqGEJYVDAqfahH9KoRDR3AIGuGwYTk4yEE4Q7X0o3EAa4wjOODuDBwCXr2DAzrUQ+5Q\n", |
|
258 | 256 | "PBT+4NE4YOoGbuouDhZwMAyFAwA0vD6Jg+QzrBVxkIOAPhIHw++1HBwoUR+MAyYcDrP9MI2wrljq\n", |
|
259 | 257 | "IRvCsig2HIMDLhUOZEIHB90KdpAJhf4LHOSYj8IBbtanW0JEoh0cdLcXMDysHAlGCBzMiClLyJS+\n", |
|
260 | 258 | "Qo4UOLiS4w2asFI4NSF/jgnkXZpyn0nnAubSvUqwo5EgJ+eTPXl04gCtD3kdyxEkDhbqS5/ENyK4\n", |
|
261 | 259 | "ME1lFzAXy+uNuBKr3LBJa4/24Mrwzwx4IyHHdjpKSy5I7s/EgXMFDkGSkMIBXYcdiZNsQKH7hLvX\n", |
|
262 | 260 | "Hf0gE1Rx5BbF6ozGASZ0xKBRFNVUdQZENFzBI66Go4N59+kRIaJ2KCR8snPioPAImR0cQtAFK2rJ\n", |
|
263 | 261 | "4vBe4RB1OgXOIQvQhYFDSA9IHHyQfcQqIQQjlsTBBw66OERRFXOTI8E9X1ji4OvgEA57LV94Bg54\n", |
|
264 | 262 | "2bJg43kBHPx+G91L5hIHr9/y0SiiFyPEqgFf1MEByuHIphTGIwXWLSyZrVNdMV/JUq8ffFc4yKFS\n", |
|
265 | 263 | "9MLGERxwn0zosNrRnajigjvcGThQ8OkjjsaBouPgEFI4GFEh7FgHB4P9spi6lD9wBwpKDBwcwpZ0\n", |
|
266 | 264 | "2lI39KghRyJxiEgVClpQcxcHHSjoxIFOPugzdAcH3bZDUshCHC/4AZbDV+kuDiEHB91wZxrFRSQC\n", |
|
267 | 265 | "28ILhQP4pWYi9cECpjq0Ba4MUUUk4IvpAcWQoOVEe9LPzyh+TpYSTXUNozUcEgdDab6UNHVKHEKy\n", |
|
268 | 266 | "O4cJYSdqUUCZRlRxQQ23g4/UeZ9PxtvOPakHDAoCjsu3JBbAwRYiFtN14XdxUI4Agm+pWB/MAAaR\n", |
|
269 | 267 | "WESWcASj1cNyOEbMcIfjg26YcOahiN7BQXdw8Ec6OPiVHqFDafXCfOANGz7DwcFJLzAWfxT1OzjY\n", |
|
270 | 268 | "R+MQ8ftjEgelHuzij+FAJzYTB/9MHCxKSJjqGjalKTC8fgcGS7JBzVPioAaDKzBBGisZQToVYnqn\n", |
|
271 | 269 | "KAVxcJCRke4GWkfhEDiCgwlHbcSEiMeJg2It+pE4gOEKhzD6BwbRWFSWcJRO23BxcDXYp9uYsGmF\n", |
|
272 | 270 | "olBzmaJIHGBxwKQoJQ04hB0cwujQoLLLC68BHBhBhn0qd/KHXRxMsok9xPByNAqF5gUa9PvjkEJH\n", |
|
273 | 271 | "BNBDIAocwmgvaIUDqBr0xcPBDg66jLoJ4FE4kNl4YChiyJAQFs4yLcltxQYUJZBh2R0uwQSJg/TY\n", |
|
274 | 272 | "Lg6uHaPPCTvPpGNBR2EXB4MJQsBNQBRqHJ2pB/0WcEgkwmEHBxMdSXmIGNGIEk4oKDCw47Yshm26\n", |
|
275 | 273 | "44sYCUtqEHEO27BYFnAImw43wRVKNphkc4Yhv4VzBRw6NPkgTFvsxalJHAx/0NUHmIKY33RjNMOI\n", |
|
276 | 274 | "40Xbho1Hd3jR9vsTGKtKaqQTsyFmBvKSoGUETMMO+hOGxMxwgglG3ob/qBJQzA4bVFcjYkqWEgdL\n", |
|
277 | 275 | "ab4yOCiRiMsHGEhwwrb5xCmyqpUwHHNON+7ad9PpkSMMONWdgEolUcruyLDTbyWESCaBQ0CZPuAt\n", |
|
278 | 276 | "cYi6OIQdHBIKB1PiYKqRzsQhFo6ErYgOOGbgEHZwsI7GAR1GTEaBEgfofSSMTMj0d/QBU4/5I6Zl\n", |
|
279 | 277 | "gu0cTRygxGKYA2QYViLm9yeVmVaqThzAaIUD/sWC/qQRVFZep+0Od3AIzMQhGjWNsEl1RTgIAxCJ\n", |
|
280 | 278 | "EAc5t6jDhg4O4f8Eh8gMHCz1SAq14UwHnSlHYzoBFV2+41kgShE4auKQShmGCEizg6E5AzDtqGrF\n", |
|
281 | 279 | "ChvAIJaMyWLGaDxNVTkhe2PHfiNuRDEoPWZY7vKLQRxMZFExvGACB9PBwUSHUeIguezD/Sgj+Rk4\n", |
|
282 | 280 | "QAYS/qgbK5tmAhoSj4ckDrAScb8/BSlU2i9xiAEHE5MNRc2gZcZD/hQibDlR4MAuKajH4KCYbVg2\n", |
|
283 | 281 | "cLCACBnq84PvygLL1yl6UTIiEJaw45JMMB0f4jAiklBckDhIJTYVZ/5LHEyaeeIQTQqRTndwwBhs\n", |
|
284 | 282 | "qRe2GVM4GNBd4BBPxWWx4hYHoHBIKR1iRGEmAB3cR9yMhJxFLqIjcYiToTr46verztFh1GIUKHGA\n", |
|
285 | 283 | "I4pSYy1nDRFvYerAATGaqax1CiBKHCCtSP4TgWAaY1USKZPYOLTPxSFCHNKmim0MI2r8ERwo2hZx\n", |
|
286 | 284 | "MEgsaYN8QQUCH7FQ9KK2NCyyO+BAJsg5y5Gp2ilXHqEglrLrNFemMx0IiuKUJVNDnemjuiNxiIZD\n", |
|
287 | 285 | "gWhKiEzGNF0cgLfUtJgVt2Vegv7NRCwWTzs4JCISJhYrFZWWDN0GgIPt4KCrtS4/7wYsJKtxMM/S\n", |
|
288 | 286 | "A1EroHCw0KFNHCSXfQiEbIlDoIMDdDERsN1YGTjAiCQSiHnYHXAIBjMKB0xe4YBM18LUENqFYK5D\n", |
|
289 | 287 | "gYylcDBVMGFRUI9agnNwgEeMAYcIELFxTRzk3GKKDZyyHWPernAALLgjnbcqylqnrIiru+rEch08\n", |
|
290 | 288 | "tf5YHMIzQuAYcLARuEbTQmSzwCEoG4yiHzUAKxGT44WYm9CFZCYpSyQZIS+kjYpkbOWmMEUracUw\n", |
|
291 | 289 | "KLiMqLMKG3BxCCbI0DD4GnCcEDq0I65I+KLAgTlqxFnLxVu2HUgG7IgNky1nlA5ErGQS2QZsCXBI\n", |
|
292 | 290 | "BoNZjFVNXOKQcHGwESpYST2QtXTH28Ypp8xEj8WBoo0K0TjtbCwibZAvqCxPLK7YkECJxVw+0DjG\n", |
|
293 | 291 | "yQSFg5RXFjsj7zgexXL1JGI500HArfxIZAYOinVxgotkzs4IkctZlghKcafWScWIR1wcbNNKJRLJ\n", |
|
294 | 292 | "rItD9Ej32Rk4pGCxYraRJA5qsRF3zUAEF0kwLwIcIg4OEXQYkziQy75oFB7kaBww9XQg5uYskUgG\n", |
|
295 | 293 | "xjyVQphPmx4MpoLBHOyFsgxcOdKT8NERTFaPR0LRSEoP5CIKB9gzFf4ZVKSZOAQVs61owiQYEWmD\n", |
|
296 | 294 | "fGBDTGm+ZIPEIU5GmrZ0VOBEMimdtyrKa2aPaIjCIaIcfAeHkFNdRa9GB4cIpSRmhoLxnBD5/Ewc\n", |
|
297 | 295 | "EmoAkWRcpqsWeJRJJFK5lCzRNIcQVZVzMenGcCMQSUfiGJSZitjhIzhYEgfcIw4xDEt1jg5jUXco\n", |
|
298 | 296 | "Phs4UGMj7n6GFcDUOzhwNNlANJJOI06l1QgG08FgHmKgJFIu6qQcHMJxhGyRtB7Iz8DBkknRMTgE\n", |
|
299 | 297 | "gAPEKmrZCYiDHY92cJAlodhA0Ysn5NpkzMGBTOjgoBgRzykuKEMlH1C5nB4tFwe85uDgpCLS7iAq\n", |
|
300 | 298 | "RwJBHAqFSESEZIMx4C0NVDKaSjo4RCLZVCqdS8tiZ2zy4oNwSETiMTMdibk4RIhDFHlLmkmgEYhH\n", |
|
301 | 299 | "A8oJRdFhXOLAuMAPIxTnmk30CA5x4hCPxh2nGc3hxUwGDs5WOIRCBXQ/A4c0rGA0RP8U1WPRTDhQ\n", |
|
302 | 300 | "iIaVw5OGFOEQDEZALbw6MIDj5GjEhgoDjJj0Bf4QIZBSrww/SjKpcGBnuCQTOGvlSBRoM3CIxaLu\n", |
|
303 | 301 | "M9WjwsGZiLMSQhzUjSSsWQIpP3EoFomDNDuwfimpaSk7rXCAmEegC5l8RhY7A97HbDnWeF4ld2gu\n", |
|
304 | 302 | "GM1Gk9FE3ATPwwG5CAzZD0aCNvKWDF6wjWACHFRuDR3GY/C6UbLVj8QgTo21g86aZSQYTwRzwbjK\n", |
|
305 | 303 | "WTiafBA2GDjAT8bhNTOhUBH2QumKxCGDMNAO2XY4aeuoGg4W7bCtZDIlxZMhaPCoEqJoo0IsBXFA\n", |
|
306 | 304 | "WB6JJ4hDMknLk0wpNlD0FA6RuIMDmECbrEamGJHIKy4oQ2W7o3Z6pKSEnHszcHA8fEThkMwLUSpF\n", |
|
307 | 305 | "o+/HIZNycIhGgUGukEPJ5mLZOBtUlQszcMgRh6SVicYNtZsIU9LBAfVM4hBQnaPDhA0c5IU/Hg8m\n", |
|
308 | 306 | "HByUqEYCiUQgh/oJV+IKACWbRb4A2w0As6FQCWLg4gDf5+JgJO0wqoaDJQeHaCRp/VEcKNnROM0m\n", |
|
309 | 307 | "wnLpC/yKDR0cKHqplMsHKmUGbKAtcHitaheO4KAeyVFD0WkaaJ10555aNzedVIR2BzgkI8ChIES5\n", |
|
310 | 308 | "TByk+U+kUypATcdcHGAoC+i9mJMllotTJhUOpQRNGQUgaOftlJ1MWVk70cEB6ARj4FI2hpjDDCYh\n", |
|
311 | 309 | "ycqtocNEnDjEMBd/wsEhFgy7+pBIBvPBhModOZpiMB7L5ZD2wgbgxVwoVEb3ygpzoSCcRawUC8Vi\n", |
|
312 | 310 | "RioWRlUjWI4ZsqtoNK3CcIv5eDAYOoJDMknJjsbTUYIBHJLEQVkeFMkGiUPa5cMMHJyRKUakSooL\n", |
|
313 | 311 | "0rHKRzEVaHX0QXfqy0RPrQQoVqRhzFKRcChVFKJSsW2hSxyS6XRGDSCWld2HIOZ2MZvNl/KywBax\n", |
|
314 | 312 | "QQVaKTkThzSsaSQHHJwdKdwlDrqeUzikOjigw2QcqikviAMiEAzMxSEaTBKHZCzl4lACDvm8wgFe\n", |
|
315 | 313 | "M6/rFXSvrLDcNssRB13hkIjljWDFwcFGYIHyfhxCIZoYWpYM3FcinZC+wK87OGQUG7Io6bTDBwYM\n", |
|
316 | 314 | "4ASY0MFBMcLFgYXsPxqH6H+KA8KrVDSsp0pCVKvEQQoBRCQrLV42nss4OMCe53KFckGWeCEh1UVW\n", |
|
317 | 315 | "LieVc49BFAuxTCyVjuRjSXe7CiyKhuIhXc/HUc8KpSDJKrxAh+kEcWCM6E8m4MmBQzzk7ChEQ5h6\n", |
|
318 | 316 | "IZRWOTxHUw4l4oUCsm84UOBQ0PUqZAbsZddcwc8jIInrcfinuAF7aYaqcVPFEtGMCsNhMEJHl1Qq\n", |
|
319 | 317 | "m0WFRJb+LpOwYQrSfl1iAC4oNtAEZDIuH2wbl2ACfaNTlO6UFRekoVE8kfYi7kwHguLMxFmRkmuX\n", |
|
320 | 318 | "St5hzNLAIV0WolaLxYQu3TBERCUK2Xg+q/ZsUnYMulCsFGVJFJNsUFZOVlJyRBKHInBIp6MSB7UZ\n", |
|
321 | 319 | "FYPBnolDuoMDOswkEYXKiwD8YAYe9ggOdghTL4YyKofnaMqhZLxYNA2LF7oOHGoQA2Wh5XJqB4cM\n", |
|
322 | 320 | "cSiaoZqDA5McmuYPwCGdBg4wflm4r2QmIX1yQLGBOEg20ARksw4fUHAJJiQVswmUql1J/Cc42C4O\n", |
|
323 | 321 | "uPU+HJiCZeywnqkIUa8fwSGbzckB5BL5nIMD7Dl6ryocksUkgzpVuYqYLillIxQvxbOwptFCPGXN\n", |
|
324 | 322 | "xCGBi0ICeEVCGUiyCi/QocIhgbkEUhIHw0iEjBk4lFA/oyLIZLISSiYcHFJ4sajrdXSvvKHEoQAc\n", |
|
325 | 323 | "EnoiYWUSRioBHOoJU3YVs3PSWjA1DoU6n2HxjKYeFVI5qGUqm5Q+WeJAY5TLdXDI5Vw+IHBzcXBH\n", |
|
326 | 324 | "pnCoKi6oSFf2K+124ggOTv0ZOChW5CQOhp6pCtFoxOMinJW2MJfLS4uXTxQUDrF0LF4pFEq1kizJ\n", |
|
327 | 325 | "EpPrpKycqqWP4FCO54CDXTyCAyKbGHAIh4vH4oAOsymYSHkRQDyShWU/gkMslM2GyqGswoGjqYbg\n", |
|
328 | 326 | "jEoWMnsUXS+Fww3goCy03J0sIkBPoD0rmzBR1Qo1EpaKrWM5aa6ZGh+Fgw6O5/OJZDyVjxGMZDwL\n", |
|
329 | 327 | "AAJhiQG4oNhAU6xwAB9QcAkmpBSzpd2Qpaa4IAPN9+FAy2k495yldCclJA6IJLIxI5ytCdHVRRxk\n", |
|
330 | 328 | "OAQRKagBJIt5uZ4OcxOHLpTrZVlS5RSDOlk5Xc/INAfN6YlKIpfIZu1SIq1wQGoCx6kn9XC4lARe\n", |
|
331 | 329 | "ET0LSVZhHjokDkaCsXogndIlDknd2dOK6TAFFdTPqggylarpqWS5bJkROlFdL4fDXZAZ5Q0lDiWk\n", |
|
332 | 330 | "RclwMmnlkib8lqV3JS0V08XyMrxkaqwfXehyUSFdgNlM51PSJwcUG+gFJBtoAvJ5hw8ouCQTOGs1\n", |
|
333 | 331 | "MlW7rrigMg7Zr0o8nOlAYZ36M3BQrMgDhxxwyNWFaDYTCReHfL4gPU8hVSqoPUwIJXSh0qjIkqqk\n", |
|
334 | 332 | "O91nGhkVNxGHaiKfyGXtciITUV/9wLXqcT0FHMop1IvqOUiyCi/QYS4NHGBkUqlAJq0jEjTNlG4q\n", |
|
335 | 333 | "BsV1iGAV9eVaCkdT19OpSgU4wInixUo43ET3ykLLTbAyAvRUmPFaysykKpbeTFlqbEhyGNbQYBwN\n", |
|
336 | 334 | "AyZcLDJSVzikpU+WONAYFRQbaAIKBZcPCShlCUzAg5RTFA4NxQUV6cr7KvFwpgMcnJk4WxrEQb3P\n", |
|
337 | 335 | "FCwXN8O5hhDd3cDBkGFptlAoSotXTJUdHBA4QBeqXVVZ0tUMG5SVM11ZOSL6zmQ1WUgivSgnj8XB\n", |
|
338 | 336 | "MN6HAzrMZbgvp3DI/Kc4cDQNHc6oGrEYv2fC4aphdEscKFFy80XigMlG8ikLVSN6dyry/4hDhmYz\n", |
|
339 | 337 | "U8goHAyJAbig2EAT4OAgAyhcggkZxWwCpaL5LsWF/wIH3HJWyuVafgeHfNw08l1C9PQkk8KQYSn0\n", |
|
340 | 338 | "sSQHUEqXixKHBBxWo1yuNWuypGsZqS4s2aZadJI41IBDPherJLMuDkloiZ4GDpU08LL1PCyKCvPQ\n", |
|
341 | 339 | "YT7DfTmGisFsRs8nEqaZdnFI6Pm8XkP9fNqJIrv0TLpWkzhkFQ49kBlloSUOFQToaSOdjhTSVjZd\n", |
|
342 | 340 | "i+g96YgaW6JI/qVpMI7BIZ8vlVAhWwIO2WJW+uSgYgO9QAeHYtHlAwI3cKJWw4O0U1TtpuKCDPiz\n", |
|
343 | 341 | "8r5KPJzpwHA6M3G2loiDer8IY1ZImEahKURv7xEcYP+k5ymnKyW1p4/+uyqVWrfCIVPLskGFQ3dO\n", |
|
344 | 342 | "jgiwhlP1VDFVKMarqWxUfeQGHMKJcDpsGFWJQ7gAi6I6R4f57BEcsmHggIGFI2qLNwEWhevhfLrg\n", |
|
345 | 343 | "zqgZzioceBEO1wyjF90rbyhxqIYVDlEHh3BvB4dSB4fwzKKHC4VyOZ1JZstwXxKHgoNDUXoByQaa\n", |
|
346 | 344 | "4lLJ5QMCN3CiVssqZhMohUO34sL7cHCmA8Pp3HsfDiXgUExEjEK3EH19qZQwZFgKEXFwyFTLak8/\n", |
|
347 | 345 | "n0zBJtV76rJk61kGdrJyrgexdVYqYjjVSJWIQy2Vi6qvEUMpOM5wBjjUMsALOECSVZiHDgvEAcY+\n", |
|
348 | 346 | "kwnmsuECPKyVCUcVi5LhQj7cQP1Cxokiu8PZTL0ejdgMZgyjbhh9kBnlKeVmZA04ZAzEzcVMJJep\n", |
|
349 | 347 | "R8N9maiKrZFsMrzkUtEH4IAKOeKQK+VkbBQkG+gUHBxoistlhw8ouCQTOGs1MhXN9yguyIA/J/tV\n", |
|
350 | 348 | "CaAzHeDg1Hd2LOSeilK4JHGIGsUeIfr70ylhyrA0Xy5XpOepZGouDvCrtVqjtyFLtpFjg6pyr8IB\n", |
|
351 | 349 | "sIbTXelyulhK1NN5W1cfrDg4mGadi7WxcLGDQ39/qpCDq5IXwXzu/TgUw13AoejOqCeMoKABHOBE\n", |
|
352 | 350 | "gUPDNPshMyoqkTjUkShl0J5dykTymUY03H8MDjTcR+EQBscrlUw2laukCEYuXSgCB1NiAC4oNtAE\n", |
|
353 | 351 | "uDjIwA2caDRyitnEQUXzvYoLKuOQ/Ur/eQQHy5mJs9U6E4d4vJSMmqVeIQYG0mlhyrAUIlKVnqea\n", |
|
354 | 352 | "rVUkDqlCKg2b1NXXJUuuK0+ZlJXzfVyElYoYTjeBQ+koHNLQknCWOGTxTixcgkVR4TY6LOa5T82Q\n", |
|
355 | 353 | "PQgjBH8ZiWRdHFJhmORmuJgtZdV6Tr43nM92ddkR5lF5w+gyzQGIgfKUHRyyJuLmcjaCqnZ4IGur\n", |
|
356 | 354 | "hChVIf+yXCqS3O/AYJRKtDDpfBU45Cs5GRsFFRvojSUbiEOl4vBB4QAmyCRb5Rmqdp/igky85KOs\n", |
|
357 | 355 | "SsSd6QAH594MHBQrKql4vAwcyn1CDA5mXBwgIjU1gGy9KvdbU0X41Xq92d+UJdc8gkOhvyhxAKxG\n", |
|
358 | 356 | "ppmpZJDmNTIF2/m0J40AxsgaptnIFrLZuFGCKVKdDw4qHORFsJA3FA7q0wpM2SiWjKYxA4c+I59t\n", |
|
359 | 357 | "Nu0ocEBto2mag4gnVVTCN6INJEoODlHED7Yx2MGhKnGg4TaOLhIHqEEN7qtQyWfKUASJQ0V6AckG\n", |
|
360 | 358 | "muJq1eUDAmhwotl8Hw79igsq85P9Sv+ZdaZjGC4Ozlars2RIwwenUk4Bh34hhoYyGWHJ9KBYrdak\n", |
|
361 | 359 | "56nlGgqHdDGdgU3q7u+WJd9dYICtKvcXZdovcejOVBFdJLsyxZjzMVsGjtPIGZbVxUXzuFGGRVHh\n", |
|
362 | 360 | "NjqsFPi9QA5zCRULiKjSkUjOcBBMGxDBbqMCY6HW1Qp9RiHX3Q0c4EQLptm0rCHIjPKUcnO+Czjk\n", |
|
363 | 361 | "LMTNlVy0mOu2jaGcrXKcdJX8y3HJ7hgcyuV6HRUUDtW8jI1CZAOdQk2xgaZY4ZCWOOASTJBJtsoz\n", |
|
364 | 362 | "VFbVr7ggAyC1QSD9Z86ZDhTWmckMHBQrqulEopKyrQpwmDUrCxxkelCCH5IDqOe7agqHUjoDm9Q9\n", |
|
365 | 363 | "0MFBmi2W4oBaDAesRrYnW81Wyslm9mgc8sChmQdecaMCSVbh9qxZEocIjH0+38EhPwOHqtGD+pW8\n", |
|
366 | 364 | "E833G4V8d3fMjjOYMc1uy5oFMVBRicShiYQ1b+XzsWo+Wsx3x4xZ+ZjKcdI1GebTcB+DQ6VSr6NC\n", |
|
367 | 365 | "sY4wolgryNgopNhAbyzZQFNcqzl8QMGlwiHvFFV7QHFB4SDvq0T8CA7OTJwtb+Kg3ufSUDVtW9UB\n", |
|
368 | 366 | "IYaHs1kHB0THDRkBNPLNusQhg8ABNqlnsEeWQk+RDSrQBstyRBKH3mwNM0l1Z0suDlloicShm5sX\n", |
|
369 | 367 | "iRk4oMNqsYNDqWggM8LAXBwyRrVq9BpVhQNHM2AU8z09wAHBDHDosaxhxJPKU8rP7rqP4GCX8j0x\n", |
|
370 | 368 | "Y9jBAXGWdJvvx8GsVBoNVCg2EEYQhyoUQeJQk95YsoGmuF53+YAAGpzo6SkqZhMohcOg4oJMvJRs\n", |
|
371 | 369 | "yjgm70zHwQGvyQVZtfetWFHPODgMCjEykgMOMj2AqnbJAXQVmg35HQj7H2g2e4d6ZSn2FimTsnJp\n", |
|
372 | 370 | "CDlOUeqomevL1XNV4JArxdWX68DBzJgFEzgUSgXkKlVYFBVuj4woHGDsCwXgYEocCurTFEzZrNbM\n", |
|
373 | 371 | "PtSvFpxoftAsFnp7FQ4l0+y1rBGIgYqlFA5mMlmwCoV4rWCXCr0xc6QQUzlOpiHDfDwuyFG5n2oa\n", |
|
374 | 372 | "ZrXa1YUKpS6EEaV6KUeGhsgGOoWurg4OjYbLB4kDmcBZq5GprGpIcUHh4OSBPHGmY5oRp/4MHBQr\n", |
|
375 | 373 | "GsChlrGt2pAQs2fnciIi0wOISJeMxLoK3QqHLAK4we7uvll9shT7SmxQVi7PqhzBoT/XyNWq6Z5c\n", |
|
376 | 374 | "Oe58ZJuD4wQOkUgPN5GSZq2DAzqslSKRqMKhXDIRtxAH58PRrAlT0I/6NXdGQ2ap0NcXjyUQVJYs\n", |
|
377 | 375 | "qy8SmQ2ZUZ5SfqzSY8JDYrLxesEuF/ri5uxCXCWm2YZ0m3Sg5tGFoU+hmCt3IYwoN8oyRg2RDXQK\n", |
|
378 | 376 | "XYoNNMUKh6wMZHEJJpQUs4mDyqpmKS7IxEttmKkFEWc6MJzOTJxPQGbgkE2l6plYpD5LiNHRvItD\n", |
|
379 | 377 | "tdFoygigWezpUjhU4Vd7evqH+2Up9Zcpkwq04Sqaljpq5gfyjTxw6M1XEjNxKAKHXm4iAQdYFJX2\n", |
|
380 | 378 | "jI7m6mXgAKdbLIYqZUS2WdsuHsEBpmDArBdrKrMtl2eZ5WJ/P3BAMFO2rP5IZBTxpIql5McqvcCh\n", |
|
381 | 379 | "GCkWE/ViDPFD3BwtxlWume2S6RaXTo+GwWLogwrlZq4AMMr5o3BoKjbQFHd1uXxAIgNO9PfLxQ6V\n", |
|
382 | 380 | "7ykchhUXVAYu+5VxTPEIDs5M5MK4+gZBsaKLOGSBw7AQc+bk8yIi0zSoarccQHextylxyCGQhk0a\n", |
|
383 | 381 | "GBmQpTQgcZCVKyNH4dCVrzcyfUdwyENLJA59Cod6Bwd0eAQHnTjkcjNwyLk41F0choHDwEA8lmRQ\n", |
|
384 | 382 | "KXGYAzFQEYvEoc+EhyQODeIwEDfnODjkc00ZvtCBvg+H7u5iKV/pRjhX6arIGFWPSF2gN5ZsoClu\n", |
|
385 | 383 | "Nl0+IJEBJwYGZuCgstsRxQWZAL8Ph9zRONCZH8GBS3QN4NAYEWLu3AJwkGlaDX5IRmI9pd5u+cFZ\n", |
|
386 | 384 | "DoH0LPQ+W+FQHqgw4ZSVq7ORa5aljpqFwUITUV6mv1BNyC0nB4cScOgvAa+U2YBlV+nn3Ln5RgU4\n", |
|
387 | 385 | "wOmWSnq1YjaIQ+kIDo26OYj6jZJaZ66MmJXSwEAinkRQiRcHIpG5kBkV08rPMfqBQymCPLKrFKuW\n", |
|
388 | 386 | "BhLm3FJC5fy5bnKnxCXsY3BgCIoKlR6Ec5VmpVBvEAfMqym9sWQDcejudvng4iAXnVTerbLb2YoL\n", |
|
389 | 387 | "MhCtyn5lHFPq4GA7M5mBg2JFN3DoysUiXbOFmDevUBDRY3HoUzjka/nCcF/f4OigLOXBGTiMKhwA\n", |
|
390 | 388 | "q1UcKjaLja5sf7GaVP9rJoSaVt4qWdGowsFqwLKrztFhoxKN2i4OFuIWDMyKq09E82CRNWTNwGG2\n", |
|
391 | 389 | "VSkNDiocqpHIYDQ6DzioWEp+NNRvwUNGkUd2leKI4xLWPAcHxLsyfKEDtY4uXV29vaVyodqDcK7a\n", |
|
392 | 390 | "XZG5gh49Gge6RIVDXuKASzDhfTiMKi6oQHYGDs504MCcmTif4shvUBQO+UymKxePdo0KMTZWBA4y\n", |
|
393 | 391 | "XYaq9spIrLfc36NwQCA90t8/NGdIlspQlbZBVq7NqaNpqaNWcVaxu9jVlR0o1o7CoQwcBsrAK211\n", |
|
394 | 392 | "wbKr9HNsrNBVBQ4lprB6rWp1EYfyERy6GtYs1O9SKwzV6qhVLQ8NJeMpBJXAYSgaHYPMzMBhADiU\n", |
|
395 | 393 | "o8gjm+V4rTyUtMbKSZXz53vInTKXsD8AB1So9SKcq3VXIUXEAfOic+5VbKBL7Olx+YBEBpwYGpKL\n", |
|
396 | 394 | "fyrvVqsMcxQX1EqI7FctTB3BwZnJDBwUK3qAQzMfjzbnCDF/frEoojJNa/T09MlIrK8y0Ku+RW0U\n", |
|
397 | 395 | "irBJs+bOkqU6q0aZlJXrc5FrVqVsWKXhUk+p2cwOluouDkUEklYFOAxWgFfaasKyq/QTHXbVgAOc\n", |
|
398 | 396 | "bqWi12sW4sdYrOLiUACLrGGrC8ZCrTPX5li1yqxZyUQKQWUtEpkVjc6HzKhYSuIwCBwq0Uol2V2J\n", |
|
399 | 397 | "1yuzktb8SlLl/IVe8q+Cx5VjcGg2+/pQodaHcK7WU5Uxqk420Dn3KTbQFPf2OnxAwSWYIBedVN6t\n", |
|
400 | 398 | "stu5igsyAa7LfmUcU3GmAwfmzGQGDooVvYVMphs4dM8VYsGCUlHYLg79cgD9lUEXB8Q3g4PD84Zl\n", |
|
401 | 399 | "qQ7PwGHeDBxGJA65oVI9JT/+tywHB9seOhaHBQuKzZptxzo4NBFxxmfg0OyyRlC/g8Nc4DA8nEyk\n", |
|
402 | 400 | "GdxHo8O2vaCDg/yIbshCpGIzj6wkEMclrQXH4MBA5mgYIgxBK9Vivb9YLtZ7a6VuKIJuOzj0KzbQ\n", |
|
403 | 401 | "FLs4yEQGnBgefh8O8/5fcZAbFOrbKBeHbLanELe758m/w+R1jqL6q4C+j+BKk9c+HyyXWCPGhV9k\n", |
|
404 | 402 | "xRe0AW2+tkL7gvZnnoLne54XPf/b+xXv495ve3dXk9V8tVytV7urI9Xjq0uq36wlIL3dtVl1Tz1Q\n", |
|
405 | 403 | "j9bj9VQdcVJ9oD5R31C/oPnSvj0/t35/+P96Dh/mX0oUD2qztOO009By1vM8Wn6l03KiiryPk0bL\n", |
|
406 | 404 | "x31AyzG0nOu0vFG2LNCyJlt2yiH5dxQPNYV47xPvrXzvQ+8dL8S+h3lv34p9N+47Zd+Cfce9fuD1\n", |
|
407 | 405 | "1uv/+Po/vPbua2+/9q9CvPY7HK+/9qPX/ua1R177xk+Pq94sRMgv/9riGi3p6fec6PmYEJ6/8XwH\n", |
|
408 | 406 | "9DtuT57neXheEn+keKbUcdS9J3D8rUThSvG0+Kq4UOwUS8Vz4r+LvxQrxF+JdeJW0RIvijfEN8Q/\n", |
|
409 | 407 | "iX8QnxXXiBfE98TlYrv4mHhe3CE+JW4QU+IU7Uahi7AwhSUSIilSIi0KwLEkKuBxXfSLATEohsSw\n", |
|
410 | 408 | "mC3GxHyxQBwnThSniw+LM8Ry8RNxvThJnCZWiw3iYnG1+Ly4WWwV/038qdgm/lzcI+4TT4pvid3i\n", |
|
411 | 409 | "f4nvi5fFT8Ve8b/Fa+JnYqX4iFglJrQ/EVeJc8XfifXin8VZ4rtio/i4eEz8ibhTu0H8T/EVcb6Y\n", |
|
412 | 410 | "FD8S02KRuEt8U+wSa8WjYoe4UTwiHhY/EE+JgHhJ+EQIshbUvigMERMRERW2yIsMpC8n4qImekSX\n", |
|
413 | 411 | "aIo+0S3uFr1inhgVc8RccbwYEV8QS8RCSOqpYrFYJk6G1H5SXCIuFZeJL4vbxO3iS+LT4l7xkLhf\n", |
|
414 | 412 | "fE08IR4QF4jHxatij/ixeEW8Lv5e7NMMbYlmaks1S1umRbTlWlSb0GLaKZoNmY9rp2oJyGdK+4iW\n", |
|
415 | 413 | "1lZqGW2VltVO15Lah7WcdoaW187UCtpZWlE7Wytpq7Wydo5W0dZoVW2tVtfO1WpiE/Tmeq2hfUzr\n", |
|
416 | 414 | "0tZpTe3jWo+2QevW1mu92nmiLP5M69M+AQ3bqPVr52sXaIPahdqQdhH0YpNoQD+GtYu12dol2oh2\n", |
|
417 | 415 | "qTaqXabN0T6pzdUuF7PEd6CVW7QxbTM06NPa8dqV2gnaVdqJ2tXah7TPaCdp12gLtWu1ce06bZH2\n", |
|
418 | 416 | "WXGCtlj7nHay9nnxIfFzbZ52hbZA+5T4qDhHnCkuEn8rvi7+UdwitojN4lnx1+IZcZ74hDhb08Rf\n", |
|
419 | 417 | "aGEYhf3iLXFAHBS/FL8S/0e8LX4tfiN+K34h/lX8TnxGXCsC2ktSn/f9/1uWMQdIIWQwApnrhoQt\n", |
|
420 | 418 | "hHSNQ7JOhWytgVx9UkrWbZAtSta9kKqHIFcPQLL2QKooU+dB3qkN3xVnQ9q/AA34uPghZH+j5od0\n", |
|
421 | 419 | "94r3xKQW1ELQlbvEIU3TPOI/xGHoyw7x75Dex6EPV0FzhLhOC4h/gxbdKK6AhgWgH32Uhw5C3xb/\n", |
|
422 | 420 | "Q1ygecHxE8TnxJvii+ImicQnoGF/A/za0KkoNMuGPik9ylOHNB90idozT2wC+v8I/VT4rwX6Xxfn\n", |
|
423 | 421 | "tMTgqS191Zpdmvana5/WDt/cWlLapXvXf3yopQ1Wq0svXtLSNgy1PIMtrb821PIOVpe1vM1lZ6xp\n", |
|
424 | 422 | "rK3eXr19xcbbq8uqm87b2PI15S8eXHD72uFqS5y55mLQs9bUWuNrC53TC9auPX6o5WMzPtnM7WvR\n", |
|
425 | 423 | "wCVOA5fIBvD+e0Mt/+Cp1Za3e9Wa09e0blhSaI0vWVuo1apLW7tXrWntXlKorV071Ap0xojfz1+c\n", |
|
426 | 424 | "VaMNDrYC/UOtkGrhTLyP19fefru6atRau2+/vXA7ZuBcP62JY2+Mz7yBGS99WrthlXxyQ6NW4I1G\n", |
|
427 | 425 | "rVHDiNYuGWrpg6eeuWYphlRbOwSRakFk25rHM6C1vV7QKe/yRfOa2dDAlO/Dzon/LHUipjTnbMrz\n", |
|
428 | 426 | "sWVj8lY74A8OtISaT3tDSPt0+/owyAMkz5G8TnKYpBLWrmwvJFlPso1kJ8kPSN4miYa1q9rDJCtJ\n", |
|
429 | 427 | "riDZaeLdt0kqJqoMk6wn2UbyAMlzJD8gOUwSNdkKyUKSlSRXkLztVPk0q2BovLQjOBsnWUWyk+Rt\n", |
|
430 | 428 | "kuEIhxvBa4d5eQUu6RhT0LgToZET+BUifrgoTO1HIg5vG/f8DpZBQLvVf1+Gb3kFVnuWp9/7qP+l\n", |
|
431 | 429 | "wNbADwO/DWaDZwWvCV0e+qb+2/Bp4S+EHwq/ZAij23jUfNictiYin4rmo2P2JbGJ2ObY12J/EzuQ\n", |
|
432 | 430 | "/I9UOvX99O8ze3KX5LbmXshfXjilcGHh9sJkYbq4oXRLRVS+VvmbyhvVrdUdtQOIQOr1c+vXdd3e\n", |
|
433 | 431 | "9WhPqOfcnlbvpr5Ng/cOTg1tHTowy5z1w+EHh58f/tXIZSMPjbw02jV65ZzpudV5l8z79lh17KwF\n", |
|
434 | 432 | "Xz7u9uM3H986IXLCwyf8/sSNJ3lOGj3pEwu/sPDBhd9euH9cLJpYNL3oXxaHFy9Y8u2l6aVXLn13\n", |
|
435 | 433 | "2e7lkxNLVixbsXvFj05dctrVp019OPThlz5yw0cOrFy18oerxlatXrV71U9W/fr09OmDp0+ecd8Z\n", |
|
436 | 434 | "3z+zfOaSM58/69dnB86unv3s6jWrD63pXjO+dvTckXMnzr3w3C987NmPHVqXXHf1+lkbzt2w47w1\n", |
|
437 | 435 | "5x3aGN7YfUHgglUXvHHhZZs8myY23XjJpksevuS3lz592QuXhy5fdvm9l//HFR+/4r4r3tic3Lxg\n", |
|
438 | 436 | "c+tTOz5911Weq+KfyX7mK9f4ru2/9t5rv3Pdjs+e9Lmxz09d/+ANX/uTxTce/8W5N+Vv+sub/vam\n", |
|
439 | 437 | "vTcdutm+uf/m3bc8sXXktk/dduNtk7d/4kuXfelzX/7Uf3vov/3sT/N/etmffvtPX9n2uW3T2/Zv\n", |
|
440 | 438 | "e/eO+p32nVfe+fCdu+985c5Df9b1Zz/88xu+kv/K1r84/i+uu2vwbnH3GXdfdvef3f303b+455R7\n", |
|
441 | 439 | "7tpe3X7a9s9tv2P7S9v3bP/ZvcvuPePej997yb1X33vjV6/56k1fveOr9311x32R+/L3dd83et9J\n", |
|
442 | 440 | "951y30P3/eV9z973/P3x+8v3998/dv/i+z9y/7n3X3j/p+7/wv2333/X/Q/d/5f3P3v/8/f/8P7X\n", |
|
443 | 441 | "vrb7a9//2itfe+Nrv35g9IGTHjjlgdUPfOKByx+MPJh/sPvB0QdPevCUB1d/fcnXV339Y1/f9PUr\n", |
|
444 | 442 | "v37DQ2se2vjQ5oc+99DWb4x848RvTHzjrG9s+MZl3/jdw+Jh8+GtD08/vPfhAw//7hHxiPlI9pGu\n", |
|
445 | 443 | "R0YeOfGRiUfOemTDI5c9cs0jNz1yxyP3PbLj0Tseve/RHY9OPrr7sfHHTntszWMbH9v82Od29O6Y\n", |
|
446 | 444 | "u2N8x2k71uzYuGPzjjt23PH4xidGGLbLSFJ4/gGetwHbPiBGW4PDraHh1qDd6p5udQ/vSvvebQ3Z\n", |
|
447 | 445 | "rebeXUXfu+KvvFqXb+CvmloO1KdpvoGR2fPnzUn19MydPzY2/yTvvLndjXog2DM2Nmc0nUryLwIG\n", |
|
448 | 446 | "UplYLabheG3BPI8VTMfsZNg3VKkMBUaDp4yNLct1NwOB5w5t1P7hkLjq5JOvii3IWaVYNJOI6V2z\n", |
|
449 | 447 | "B+eEJhYtP7E6r1FLJOc+7bn4vbs99703iiELoaJ1z196P+3phucXWhBe6XXEDh9qX2Fo6yYXGisN\n", |
|
450 | 448 | "zxbajS2TO6PPRT3rpnZHp6P7ot51grZmHe3UOhqhdbQruETNkdlH2r240+5G2e6YbLe90NC2jFsP\n", |
|
451 | 449 | "GDuN54wfGK8bbxuBde0rSnxSkk9KO0vPlX5Qer30dimwbmT2B4zzetneQPsKC29xgKJ9mKdvcxgL\n", |
|
452 | 450 | "3bF0RoVGZs73nk47fyvbWdleFUPtK2KofQPIlIjZsWrMu2Vqd2w6ti/mxZ2aXavWvKhUY481Dc9q\n", |
|
453 | 451 | "07V9NS9ewS3RXp9kX8Vj+/pop69/lH012wvz6Atk3dQD+Z355/Jo4Yq8bKGCFg73qha8sLDCczzs\n", |
|
454 | 452 | "bhgxxID22XZzwDvQHhnAyzZIa8DeJXzvtu9o4qWRJu+CtJr2roD33ZawW8Y0Llrl6VZ5uL2qrK3b\n", |
|
455 | 453 | "FfO+264ZzVj8uPbmQfTXEkvXtHLDhV0586S18qIfF/2Bk9YiAHm3beT6UbVlDO8Ke95t5exdaY3v\n", |
|
456 | 454 | "h/n+wRoHqU3u8D7t9axrT3jR/R+8GIgewtm9CQjPNcmtSTw6QK5cTHIvyYEUL0nGiqh5C2Y8eWH1\n", |
|
457 | 455 | "6ipqrq7ixltVPHqzAbKH5EddvASZWt11YdfVXQBidc+FPVf3gGcv95JnZ7Hrb7HrpTx7lGfvkAR4\n", |
|
458 | 456 | "GeZw9kdxuYm93wMyeW3yNg7sIG9sSrlj2s+ON5G83HD6bP+Y5BV0M3/O6EkeqmZjnjqb5Wk0euaM\n", |
|
459 | 457 | "lj1U0VQamhrBnR239ywZLZ17zp/fmZ/Tl9crJ865feKfBs8Y71504qlnx8YuPPuVxXZttLFsyYlW\n", |
|
460 | 458 | "ebhu9PaWFsf7l4wef2bEE1j3kdjiRSMy0x05/C+exzx7RI/nlnY87B1oxe2WmG6J4fa4wHSmhbau\n", |
|
461 | 459 | "FbZ3lQDnql6qXh8Frw9KurBvZR+mdn2fi24UgEZddP248APddiLqJ7KJ4VbU3pXV3m357V11gNvj\n", |
|
462 | 460 | "j/J+z3B7ugdNbuiRILff1HBxWxBkbYhnJG9S59eS3Ebysk2wqD5XkXyX5FaSt0im43wAMnlbYnsC\n", |
|
463 | 461 | "A3wGAtJ+ieQXJE9SXp5JvkhYniQsv+xgs5ZkO8mLJM+S/ILkSfkgDfIMyRMkvyJJ58CjN/KUMJK7\n", |
|
464 | 462 | "SPaQvAMyGcin8zBpy+XzAm48WpgqoNv9Bb5awKvLebacZ29SOMcqyyp4flfVlZE0xXQ5zw5SPFZ0\n", |
|
465 | 463 | "4XIHdXAtyXaSHLVxBcmzvHy8G+082/1SN9r5aTdvkLu/6qH4HiRvD5CFK2i+9pCPL4Nnk1fHbolx\n", |
|
466 | 464 | "XOTfleTfGyQvk3yPPJN69aLLp8lnUi+mUH1H+iiuHCS5hnM9QHIKiZzpAVoaOQmpcPs5kwuaZEdz\n", |
|
467 | 465 | "qol2pjjMPSQHMMxmxNuoz4LYn+SBV8oEZ+EyAtEve6gN8z2PxectWTm48tbzFyw4/9aVi28aXmh0\n", |
|
468 | 466 | "z15QXHLZqb29p162pDh/3nByc2GkkVxw/tbTT996/oK5Jw7H6nl79KwrPvShK84aDWf7KlLue6Tc\n", |
|
469 | 467 | "r/B+rj3YBVsX7BqkPAYhj5C+VmRvexvt+esgraDdSu5t/5oMKEeCqDZufLX8ZPmvy39X/mnZD7GE\n", |
|
470 | 468 | "xWv3gbS67F3zYRHhkRdPtxYPT44vXrUYIjC9GM/KdmvF3vaqU6hFp9LjnbryVCrQqa4C9UFn+lwF\n", |
|
471 | 469 | "WoGLFVCglrm3PQLMWrG9rRU0se2hvhUcKRx/n71rFBq1wt51IjRq0Yo+3l803N6wiIqwSGnU3Vnq\n", |
|
472 | 470 | "Rw4dXly6toQOl9Op7KhTikjWkPPLwfnJH/e/1Y/nPxogSiS3knyP5J8GiTDI1L1DTww9OwST+HdD\n", |
|
473 | 471 | "FCySF2bh5SdmPTsLL/9yFqVkmD2QvECylmQ7yTMk15H8gmT/XLw4f+7yuXD2n5l769y756Ldb82j\n", |
|
474 | 472 | "JsxbNg+tPTqPtUhuJfkxydhxHC/JrSS3HM8qJMtJ7ia5ZyGaWLvw4oU0vQupwCTf5t0Xx18dp2qQ\n", |
|
475 | 473 | "Q78iufpkvk9yN8ktSyinJHuWcvJLqTiPgIWT382+nPWsm7wlexd+2reAoe0pcvXu3GM5j6P73yO5\n", |
|
476 | 474 | "Dm65fTEjjM+SHMPuZ0jOIc9vo2aeQsbv6d9Pxr9BTr9MckuH8W+S8XtIXiCrd5DVz856iaz+RYfV\n", |
|
477 | 475 | "B0iu7XD5RZJzhwnK8LPDqLlgLplCcoBkBdl+7dzbwPb2VrL0aZIVJK+SvLWAsBy3/DiPw+M3XfZO\n", |
|
478 | 476 | "3nr83cfj7pvk510kU2TqOQsvIqsf442Xxzl0krfI3mvI1AMk20m2krMHlxCIpa8u9azzZ5zgEy6t\n", |
|
479 | 477 | "3jM/PWd0TDo8hqXzu3v+uB3I0Ez0aJd6QjGjPJyq9SXnDtn13nSvL5yMRtLh+Nyh/pP/MxtxgrQj\n", |
|
480 | 478 | "hnGi5vX1dGXqqXC2K57M+SKWHvDHlgdixT9uP/ppXzQZjq8G+RbiJlPktMF2IgdLspOicT0I4xhG\n", |
|
481 | 479 | "TbthQ1sJGSu119MiPkAiaPZ3F1zlj0DfI67yZ3GRdWKjVsTeZWjvUpWfZqxxHMnjJK/KIIihx708\n", |
|
482 | 480 | "e9pHFEEmt/se9wGPp+k8V4R4I/R4CDde5Q0ZNT2l42yCZAfJcSTbSV4l0XVWoXtYTZcg/cKt9Aa3\n", |
|
483 | 481 | "0gSuliEMyRRN/kSaKiKjomUkMipaJsfCtp4g+WuSFWzwGZJl6U6YMyO4YVTztS+f/pmV3d0rP3P6\n", |
|
484 | 482 | "lyd+ufjmSxcvvvTmxb9cPPv0i+bPv+j02YsH1968Zu1Nawdl7MKYtQHeG+LClne4bYMT5HfLa7e0\n", |
|
485 | 483 | "va3AdCswzNg0NN3S7FZ4b3snvN7k9dY2y+PwXAYpLs89uPC4PEeQEoBJ1f0emlQdYSkRmF9L1WI4\n", |
|
486 | 484 | "+N8O7bOHPqQ9dehO7ZxDjy9e7PnO4t8sRhwux8TcQVgyDl8kdiEOb3DhZZ2YfNs8bHqcJAbpzBZ5\n", |
|
487 | 485 | "WyY2bhx/7Psfle/Pbm8D36aG7YX2StuLBMl+zvYwiKcf57TaCxl3ro+iybejsrVOWxd32too21o3\n", |
|
488 | 486 | "rg+bC82V5nrTt2Vc32Y+YO40nzN966ZeNzk+mOAoh7YBo5p6Pft29nCWt7JIlvTh7MLsyuz6rG/L\n", |
|
489 | 487 | "5APZnbSDG+hdttH/PVc+ut8jc7he9jugHOqGKMVFZk0yf5JjXs/RHybZGXV4Ad2yHN2yRU27vV2o\n", |
|
490 | 488 | "UbdoTK8HadUc3YICtQqdPMSaJo3sxeNWXNLkdHs9g+wHSEQDyZtEOw200y70VVxUXejTUt3aVrpK\n", |
|
491 | 489 | "6K3hXTYykth0y2Jb1MIc5GzyOO8Kr8dRvJ+SfJNkAcX+HpJnSHI+1FwQmoDuTd4T2kEVfIYqmDta\n", |
|
492 | 490 | "BaXi/ZTkmyRPZ6hkWSYTtCTdjDHP4dmt9C6r6VP2k3Qjf23fyrPVZbZHEHY3yN3JjjLOl8kKx3IX\n", |
|
493 | 491 | "yQL2vp3kFJInSBawz1NIniV5hr2fxd5XEFrZ8RSbXk7yUfQ0Q3OpCMxTYh+owZrn0KGJFSs+QI9/\n", |
|
494 | 492 | "MzamzXmfLhvAWhdntzTosuboMjTXu5eYQp2h18G97ZWGazK9gM3rYihwIRgvee1dPuAX9AoVz+0K\n", |
|
495 | 493 | "UXXnNDqKO6E9eeh+7ZRDU1JnnRzovyMWbHpK7WQJOVDJ3hWCrR5OgguHafJaIK2kvSuGESXtVhPZ\n", |
|
496 | 494 | "7nB7hE681eOOpo4B1I814G1Rz3IYYrhVt3d5IV5Ze5eF4SXU/cRwex+8w664MvAvIt2a/Kp4UjBE\n", |
|
497 | 495 | "wXn72yQXMW5fQ3INyNRt2nbtcQ06+SJv/YHkpyTfJnncA/J3JHf5Qd4hCfghhvP9y/0Qw7HAsgAa\n", |
|
498 | 496 | "fyfA+wHMbxnJVJgeP7w8TC8e5stcOtlD8g5JwEALy4zVhgcNGcsNtkDLtZqG4i2KZR/XGQ7Qr/XR\n", |
|
499 | 497 | "r/VVQNaSrGHM38c8Zi2JTLffYArwsky3mQfc1XyUecDzzF+ealKA7+a0d5C8Kty57yB5gQy4WLtW\n", |
|
500 | 498 | "u40MeIa3fiIfcsYvgkwe51+BebaXcRbzScY6U1lOspajPSjTFI52dSfXeqOThf+MA/kuyaMke9xx\n", |
|
501 | 499 | "ad3dR2KQsfnzKPiBwMxsxXNp18bFbpgx/4Lex39z4rZFbq5y9mdHPIu7B91AopD5P4sPPdJounnK\n", |
|
502 | 500 | "8IirB5+SPu3mlgE9AOPbq0hGQHaFIX+e6ZYhFWE98xTvNLKTXQHfu5PCsi1YpG10ctPWPji59iqL\n", |
|
503 | 501 | "dtxyJVSDUGquhIZxEaaEejSussD9Udd808j2W8HplsfepVMmE3NitdicGLQn1tgwod04MXHoCxOe\n", |
|
504 | 502 | "7xz6e23OeydqKw/tUmMWOzBmrzgNfUizvI9hyCrfBoQhk9f7twGRqYp/2L/QD+e12z9NhITftcVH\n", |
|
505 | 503 | "6bEcJMYlVXbOjgl0Rp+yHMwJSJ+SdvyqCZ8ya/IB/86ZjcPF+g4z9llIc7feRxfrnMm1vcNv4+3c\n", |
|
506 | 504 | "jHY+KtuZO3l9cFsQrz0HiziuV0LDoYWhlSHfFngqatBOkvUkb3NpApzn0iPGdfg3aCUjfWza8bGm\n", |
|
507 | 505 | "XOO7Hh2ORx/w7fQ95/uB73UfhxVcN25EfRXfsG+hb6XPv6W90sb4rk/Lmumd6efSP0i/nn47fTiN\n", |
|
508 | 506 | "mno0XUkPpxemfVvc2ID/l2r/c8bYr5d9DbtjFxhVezMImBA4TC1fSC1fTwXf6Zw5vlUTkcP/on0Z\n", |
|
509 | 507 | "rE2Iv2mFhuW8J18PvQ0X1UrslZY3BD/IJT/av20pV4ak2LhY2biwpZWzw8rKyQWj9g1cNbKlvaNV\n", |
|
510 | 508 | "6wXS7YvJvetINnEsB0CmQoFsoDfg3dK+hSHMLQwH7kGYOfVM/MX4q3Eo+BNxWoML+daFfGsr693m\n", |
|
511 | 509 | "1ms/DTI/nZb+CEIqk4junnPCYyM9swvhicTwacet+IR559DcyuyFNe2N9w51nfqh3lNXuHp2HeYf\n", |
|
512 | 510 | "0f5HyxymOp1MZP+K5DDJn5NsJhkHS6lnCDHPhDud/Ib3r7gO+T261rWMvu/xUmhS3qZ3nnepF7HR\n", |
|
513 | 511 | "P3l/zhpfZI1fkwhUa/n2Tp7v+zQ1IuVr+qCqf6BkjlFGl5J4QcajN/ju8D3oa/l2+6Z9+yAyLVPi\n", |
|
514 | 512 | "wDWIwN72z8i28wOfDnwxAPb8L/LkX0m8AHnqjsCDgRbvT/OW3whw9XQZjX+vf4EfpvtW/93UvEfJ\n", |
|
515 | 513 | "z2+B0JBEptsVimHL/sBM5CjdNHBhBJyLIC6CEnyv4bg4fW97KVMHv9DZdQ9xf4qdcRDtFEkiRNXR\n", |
|
516 | 514 | "2j+hwf4Vyd+TfIdc+g758Sbrf48kxPovMkTZG2Lw/LLnTQ9G/12/W4vpTGLOHG2OpjW0RiNGe6Hp\n", |
|
517 | 515 | "2ocvOvRV7dpLDj1saBMT2p3anEPPHfq89slDf64+4pHYa7/FhV8cd2ze4NlL4xcc/oD8QHKCQaLo\n", |
|
518 | 516 | "pALo7pRDl08w+pc65bRrib9GE60omqbowD770LqYbvnYQdtGxNuK2k6CAlz1vaTGtIDxg4LJ3iz0\n", |
|
519 | 517 | "ZpnHsnobfV1FY5QP1zZurA9fEb4+vC38QNgPSQurtVrY7bbQiMDU82KP2C+862Dad3lwO6RrBMYr\n", |
|
520 | 518 | "QjI2UpGSIa8mbzHugl+HxZ+fCjJOmhecNx8zfOUVzvGMMya0S55d9uzPFu9ftmyZdo/LR2+eOuTJ\n", |
|
521 | 519 | "t4MhROcrGdeupBkSoaDqAdFbex/BvYFkFUkLRHJE29teyAmtJ5G+/FUQGB6ueT3H+ELu+2xzcySp\n", |
|
522 | 520 | "B5G97T00AFMkZ5KMkEQ7aQTzHynN7etJHiCZJhn/YAkP4SIk5ThCPrQ/RQv2TyRnMxobE8sQjU2e\n", |
|
523 | 521 | "LM4UUNm/4v19JLtp4yLINKc5YN902x+K8PXvQzInv+y/j4r2WUrpkyR7qZG67GDyy/p9Olr8vr5X\n", |
|
524 | 522 | "Zx0G3U/qat7GdHuNrZbtnmInF5Mp2zWuuWovalzN4o0nSG5Ci5M/CrwBOz95QeAq/Ew9EvhW4LvU\n", |
|
525 | 523 | "/7uCNEhTweeDe4L7gz5EkLRjj5Fsoj7tcNOAcf2Z0IuhV0MHQ6j0uM5lGf1VjGrqEv06/Xbd62Tu\n", |
|
526 | 524 | "vyR5hGy+kOQukudJ9pOcE6GRfpDjvZPkRyRTJPtBmglGDw1qKBVU+x9vXz7hOSy64c4mLr/JM/7e\n", |
|
527 | 525 | "iZ6N790nj+84dvkJxj9aue3VIVNVWthVTLlu8N5BqzrtyhAjfQ8kwj8NRR2PrfSv91/hZ7DBmOA5\n", |
|
528 | 526 | "f2hLS0ccjwoGIqbh8cSIMW6sMjYYm40bjDuMB42WoW9hKr6F30JsmVxlbWDMdD1czBTjp19bmH6r\n", |
|
529 | 527 | "EzxJ2/e+3Q3hp+2bukBcJW6GnrX/gBmPW7rIiT5xnFgh1orAlvZXeNN4EO3sFtNin/BLw+uZRljN\n", |
|
530 | 528 | "vZGpHwReD7wN3MatSwLXBW4P3Bt4IvBsILCu/W8BtuYPpALNwLzA0sDZgcCWlp8rGiOzm3MYlimm\n", |
|
531 | 529 | "ejZ4Js49dC7IZZ41YOjH33tI2jonF3+C+4KiqvYFNQsxQ7l9PfRpknk/pjxuyg1B7uwc7pMhgoc5\n", |
|
532 | 530 | "kTeOnCgherTftMowSnvbgjtCmwnsuJDr2bvCMuvelUSyNN4LHrb6dnNPaCGb2tfHvc0+u6/a53UC\n", |
|
533 | 531 | "vQbY1nB5KDcD6Uwa9i6/Jjf9oipemKBHANnSPo5n20kOMrbXPTkPlHABJeAAyQqS7Z21MGbm7f+Q\n", |
|
534 | 532 | "Z3SoaUY+1IUpqsE7QeCTDjIVCi5nvDRGLXiUZD+jn0AoHeJuDW88RbKc1mwZjc+jJPtJ0hSXp3i2\n", |
|
535 | 533 | "nDIzZi2jzNxFmdlj7bfegcxMBqw0A/F3qBtpbgzn6F8XcBFtBcl2bvq+GjsY+0MMtfVYLobaE4xn\n", |
|
536 | 534 | "QDBnnh0kyfFyNdfYbiVZzcz8VpK1zFy2cpl5LclWpi9rJeHyyGrmK7eSrGaGems30SVPJxd4J6BB\n", |
|
537 | 535 | "kwuCE5j/5Hxzuckfa7nFn9jyGH/iy+OedZpcg52x3CpDKzfPKXs832GC4yY6/P0IMxw30+Gv9gkm\n", |
|
538 | 536 | "OW6yw18mOW6yg1+1xrMQPuRG+hDR0FbBMLcKeyd3Fp7jNtnbmKVc14nYuxJQ4+g07W1yr9r83paU\n", |
|
539 | 537 | "eyLt62MyNW/Vp5GBj+sLmyub65tXNGHPtjVd3a1B1Gqu3KVwkaLc1eRGJP1yCiLMhdbptl1L0W/Z\n", |
|
540 | 538 | "w7tiShb3UJqWM+y7yPsZMm++bznzi7tl7Ea7KDPNu0lkfvkYV03WSMKlmR1yC4BLJ0+XicM1bO8V\n", |
|
541 | 539 | "kt+ThCixUoov7qwfbSc5hWQZ25+vu+0vZfty/+6AlAJ28jjJQRK5JrTf7am9AkRzMPTNmZNwli5d\n", |
|
542 | 540 | "EHHqCR239OrVs8O5gaUbFi2f0PKH9mujhxZd+ufr+k7+5JeWa9869BPPjc0Vn1yeOmHhwtkVbeXi\n", |
|
543 | 541 | "Q/+6eMmmLxy39uY1A1zrlDZC5iN1lZNpfcyl2pt7wa71vVf00rb0chdZ7p7v5P7xepqJt3sP89l6\n", |
|
544 | 542 | "3ljofILwAe19VLY33r6C5mQVv0XYPICW7YHqgGfL1O6B6YF9A9Dp8UF+kaE2pllpIfdN3h5Ql0e3\n", |
|
545 | 543 | "fXGn7Y2y7S6Ob93keO+qXuggx90e5+bI+NxVc3nj+D86tuvl+wva4+hx8sGB1gCcphjg0JDOTA/I\n", |
|
546 | 544 | "+TpDwHwHDg941HDk6GQS5u3YWENkxBz/1nahjzGUnGwfQsQ+Z6GpNbq3PTLKmG+U4yMRvNwsz5qj\n", |
|
547 | 545 | "jCleEj/hmtFlNM7XkjxDC92n1rEMWaf9Y4rPfpKrQPi9Rtfe1qjdmrO3bXbNYY2rXDs3+V3zZXqG\n", |
|
548 | 546 | "T/DGPm5dby7cQJ1s0fKMcIVnFQgXXmn7M+r1VyiVnyWRS5j7SbLq0XXcQZvKPs8l43+mtDbU/a1c\n", |
|
549 | 547 | "DjpAspGkW430Rdqtq0hmqxuXzGZ7s+lQ5tnzqvPA44XcJmzN281twn3zXE2fBeWe5Wr6KC5Gj13j\n", |
|
550 | 548 | "lRdduOjixSy1KFeVvgeZDL9JmHxavEBmXkI+XkPyBokR9XIoL5OBt5BcSfIzElM9+h65tdV0lfRq\n", |
|
551 | 549 | "ko0kGdlu+1Uy5DqSZ47wZxaXmSefyn6PrPm5ZE11Fmt/iQw5SHKBZI26+8IR1sg3FWt+PlsFjQs4\n", |
|
552 | 550 | "0BUMW7eLxzmHAwwVT2EA2a8dr0Gk5zGpkkuDexioOquCQX8G+WH7akapexhYzg8s5wLCvDBqd4NM\n", |
|
553 | 551 | "PhZ+iouDTS5FPcU5L+XE/oJkzFkJXDf5qDlFqemmk1xAMs864iSXcTHqMSbwb5EEeXm86xknD8R+\n", |
|
554 | 552 | "z08Qsvw0SnrJV0mO4yWz/PbvSbJxrrzHV8Q9joc8TjrMBMhWesjHSf5A0p/m0mPGtcdvkfyeJMSV\n", |
|
555 | 553 | "7WVcUv8FV7abXEOXS+pyIb3JhfRz6hjPssbqBnr5PVnfz88u3uFKZaCZboJPY/zcYjlJoBvkGcLx\n", |
|
556 | 554 | "JMkabulme/iBEs/WUOG3khwg6ad1WsO93P5BJv0jnPwIxYkYZudws2DOxByuDMzBDR032v1zaNxu\n", |
|
557 | 555 | "Jq5yUXSC5DgivECbYEbwOME9qP2B57rGJvwTzD10Ap1n8r8gMEEsZ8I4RQR7ieXZBE8GORK1+YTx\n", |
|
558 | 556 | "bvMxwng2YVpKBB+1pojgft4I8IaKGdoX8UaaGP2YaP07yV8Ql38jSREtFU+0byMoa4mHnwA8SnPw\n", |
|
559 | 557 | "VvbfKfMSjK3k/lb6rbVlcr++uo5H87lX/pbcMCcOEoztIJOhZpY4/IFBzg4yPtTB4fdk/FqSHHE4\n", |
|
560 | 558 | "p/Mdw1skq8n9/SS3cjt9WQeCU0Amb579F7M9R5Z50/yjMs7XWD3znQ+v6t093Jrudpd852c867o+\n", |
|
561 | 559 | "fjxjoEat0TkbnTXKSGjpNcOnNU9zzj8zclrTc3q1wWDouE19Tefsov6x2Td+mFHRQPfp9TOc8/6e\n", |
|
562 | 560 | "0+sdv/PRjt/5R+l3CuOGvbS6dGTp+NJVS/0QkPX8WOHw0iN7Z4z7M3JfOqPV2rEMPIudgcXO2PIr\n", |
|
563 | 561 | "UTHdXsjAKaZ2pZ/jhwwLcyv5IQN3rj8gTZYbZkx5UpE0Q6TUcPt17gHfAMIlkRnb1Ecim16SFzuh\n", |
|
564 | 562 | "+SWd3bJNDG96GaRfy7OD7m6Zyk97GXkfZFB+QP8909GQntV7dVj9axkMvUhyK1P6W+T6YDfb/rFX\n", |
|
565 | 563 | "GlqcXc3GLiK5lo31sbFLeHYN3+vTIZU/0X/B3LvAxapbbK4izdyM5rewXE7aceXIyb3xeO/JI1dO\n", |
|
566 | 564 | "/MNln//8ZbdMaF9K1obyuaF6YvHH169ff+gp8noEznwAfjwl+rTX2nYAvJYrr6uYfxzmOIdp5xIB\n", |
|
567 | 565 | "W8aWdiu1txUADghtbXtX1fvuZGtgNwMEMeAuiR+VbbpL4rsKYHOCy/+7morTa+UaJKe6lROUn8xt\n", |
|
568 | 566 | "5SzXkqymet5Kspq5yEEujDxPHf2Wq57tR3nWzTO5v7+C5FF+ITeWXUbl3E+bmabKnuMYTmQ7OWY7\n", |
|
569 | 567 | "uf25d3LMdnLpnGfL5PLcOfhpp/Pg7qvFg0W8+2Pq9Aska2hlV/Bse4nWqvQHfoek4+7kRHlNGa8f\n", |
|
570 | 568 | "V15Rhh96tXwQP+013DiaqPMl2uKD9T/QGuTkjY4NeLVxEBZ6Um/kGug4RxudphVYRt2/q4dj7Nnf\n", |
|
571 | 569 | "804Px9iT7kGdc2gQljHI20+SZii6vPcchH6i/T3yRXqa/UypfkzyFY74RyRvkjwPUqvNyILk95hz\n", |
|
572 | 570 | "NCdHmufkTN6BQ5d++IsbxsY2fPHDp+F35Tl73juze2LT4kWbJrrxu2gxfsfOu3nlypvPG+Pvhu2z\n", |
|
573 | 571 | "PFrfCZeeMXv2GZee4Py6Ony81OG8diG0kf/zii27LLWWGJHrwc9RzihsuxKQpoDdyk63ssPtP9C+\n", |
|
574 | 572 | "hrLZrGdLK7e3naeJ/SZ1fGVuPXRc/Wxpv0s4TT48nqQPREpl1m5l9rZvgLkej41nVmU2ZDZnbsjc\n", |
|
575 | 573 | "kXkw08qEtrRX8mvaneTQwiK/qChuK7pfVMgdAVdu5Rqm2h6wnBViWxoJrhnkudUud9Wzclc9T9U9\n", |
|
576 | 574 | "wG2ji0PXcqf8dgpznhoql5+66WbGKKkX8MPaq5O38AvO5SkqPHdQLDW83ZnpzL5MAAbAzZZF+0DI\n", |
|
577 | 575 | "tQWyzUtJDrDNiwj6VjQ31Z86PnVKyrtlhiHgwor6LD7R8DZ23ODaghsmfnLZ59et+f6av73miDV4\n", |
|
578 | 576 | "7wue73x8/SkXhA61NLm/MHr4X7T/gE0Y8TzQjvR6B1q9dmtkb3snfc1hkitIXifZNkIL6n8XVXYF\n", |
|
579 | 577 | "YYz5HTnhTe9t/wAz25XxS+NawaOVDPmvINk26lrpIXB5yGV5AhcJyfKhhMPyIbX0G1Y3wsPtTGKI\n", |
|
580 | 578 | "Z5lhfpNEGMJ2q7F33NjZeK7xg8brjbcbfhlMbu0kE9vlAtaT4q/F34mfil8K/7r2e7y/yV2elOuS\n", |
|
581 | 579 | "k89qLzEKeZWB5TJ9NS2sTF5Xd9ZQHqExesPmd9j21bbH+QZ1D2G4h87k8RTXJJ9NvZT6SeoXKd+6\n", |
|
582 | 580 | "qQuzV2dvyXJp7NEs04c92f3Zd7KA10eBZYY9uaA2UfNwJbP2Yu3V2sGab93kpu5r+P3rq4wHXqE5\n", |
|
583 | 581 | "+AmTqq39FK7+a/mp3cF+eiKSixkWHJRf3vGzuX8HmXpk5Fsj3x1BavnmCOXndwy3psTzDKi5pKk4\n", |
|
584 | 582 | "w53pqae072k/5lb0L8mFPXKvQ3dnew7JDhnxcsqb7Gsw5XFjR+rp1AupV1IHUn7nc+Pf0cpenSWT\n", |
|
585 | 583 | "j0wTDy+Sn26SBHNunLqgRhY9XXuh9krtACbbXsE1n2s41YtJftKZ9B5O+mXO8UKSt+QZJ/pjd6Lt\n", |
|
586 | 584 | "x0a4q+2uErjxjbulNndWwI1ytJ3D5xbHBvJjq9avGus7+cz+RVf1LcqcsaAwNlCszFm0dNGcSs+i\n", |
|
587 | 585 | "MwZO/ES/Z+XSaGV2bWRevTB0yvjIh+cWZy8Y7hmO1UYqzdm1dLo4sGj2nNNGs90jMq+WeiLz6iEZ\n", |
|
588 | 586 | "35zz/zH2JvBtXdeZ+FuwcwMJYuUCkCAAghQJkCABQqJIiBJJUCtta7cZsrUtWf05lZjEizLJSP80\n", |
|
589 | 587 | "sSVPMtK0iSylnUj/NNqcTgU+w9DSzkitLWpJfyMktTYbrdjakiU5E6mNrcWVybnfeXggKSnTOtHB\n", |
|
590 | 588 | "e49vue++e88963e4nzD5poqUW6ZCQzC+BdKJQT8ItZcRknLI3yIEGX/Ucs+8rVUJqvqEQNEisqvs\n", |
|
591 | 589 | "HL7DIEgnmMju7O6wtBlbRr2y1KrYlFE9EkWikhVDLeNNVYwVtFaZ3fzc+P8Rqv+P8J2urodlrAru\n", |
|
592 | 590 | "TqKC8We2oiH1Bvy5Asu81InP62RMSglQKkpLuxEPvQnkOIK+O51LnMLjJK5ytlOOuVxWDs9Coiyg\n", |
|
593 | 591 | "WMYoiDBQBrcVm9lFheX4c1FA2sZW+JF8WTS4kbUnDUvrFAkr+YLuVXBW4odyPJ8pO8A46RrOfznn\n", |
|
594 | 592 | "kST56YUc47wJMlOnyAl03VbbQ1F85skoIDMTnso7mquqmjvKvxGP75mxMOJyRRbO2BO/pbE319c3\n", |
|
595 | 593 | "2TX/+GfWQG8w2Bu0/g/2LZdO/EZYzfqygh9E3MMSJe5hJB8GfGOiPEPpLtK57LIzLN3CFq1Cg9jF\n", |
|
596 | 594 | "UjRSoXqQ3FC5GaLEbuchxNJ3UpoLyDmQfkgWLqfy7fNZF+c/bNQnW2A+eyTWpeQ+IQWvY0QxQqf2\n", |
|
597 | 595 | "iSlxVGRSRUTsnbSmpg5qj2rPwMRMxuSDuqPo6R3sgySvFd1BNpOmyFLkLWIy7PIiJne8ZtwB/ncV\n", |
|
598 | 596 | "rG8HFGBLsRd2YAtWuFomqUu7sIDdALFjdwvYwC6s63abn63ryRv2+2wpT+ntdrvfzm67yg5N0Qs/\n", |
|
599 | 597 | "GMnGtGBSSoQH139izX5qXrHlwmNeqWIfUMU2hdXmmc8v6X9upjleWuX3ewsLgBpSGud1M55dGoks\n", |
|
600 | 598 | "fXYG/9fjC0N9zRVGtdpY0dwX4pOYv/TdaP42ZeMykHdUySVvVU5AlOuETjcItfpQdkvOsXr4OjkX\n", |
|
601 | 599 | "rCF5qPI4LluCKzZU5xKVboEcAukEuxusUnK/5Pusy91Hzv2aGSvaXYlbnau8UomWaJVbohFL6rBV\n", |
|
602 | 600 | "R2EXwUPB48FzwSvBW8GJoPbxbduUfSfpkCv7bGpF8lbVRJVAB8CQ+IkvGT9YQ/zo7tsoIl8vcWoV\n", |
|
603 | 601 | "pqaK3KAxWJET4gk4scgbGoTIk4sPGBFExJ2CdXVCcSgCWQL5bhvIOQh5EA+CmIUxzEcXuFkRyDaw\n", |
|
604 | 602 | "tD0gG+DEG9Pf1isshXzHyhAnXkfigQr+2eRT3LNY1JbBsdML8jJWtu9ivftj7qccllXFaaWiNAiB\n", |
|
605 | 603 | "ZDXSOJar8XWu4oLlIMjc8YRMId7Nh/hG4fri8V/Hx3/bL3ukyD8Oo2eCbRYJ+ZLI5GTpCibVcUbA\n", |
|
606 | 604 | "uAsyUhFsC3KArnSOoloLwNDYS3MF+TB23aNoMJDXQUbJEYsOhIs5uV3cw/oWbnxdBt00kNyg24xp\n", |
|
607 | 605 | "eIJtj+jZbVR6cvGeZu1PtaniqpUqNmG34G3ugmjB+XyMwBerZUsIPKa9WtkNIRkEWPlSKw0vGF41\n", |
|
608 | 606 | "iAMQXQszUhyq1QlGRorYOXsw8wYx85Zg5lGS3zaQEyBjxY8NXSQuRF8ln+yI31NsPNJ7IP8MopL/\n", |
|
609 | 607 | "9F00cxYImilHTPyzinyhiCdgXEuflgwiddZN+Ax+QSFwjKTMBo+h1SAO49Qi+ox3cWMrPjtZleIQ\n", |
|
610 | 608 | "YXQILriD76KBA+4TdO79XJx5BA8lJ0UbRJ17uTANCvEhh9o9WlwwFGeB3MPzdTAj3sUHjYNEQWxF\n", |
|
611 | 609 | "YFd4eoQNGvxPdNP/Ql8I0nJJOND/y6WSIC39Zf8a8md+ZYpfk40lDZtrG+AnFo6Qnzh5SH8cAudx\n", |
|
612 | 610 | "TIdbmASb9Ntw4E204r9heJwQ05h6nB49KQd7yGEob4HsBAmyd07wmVjRNn43f4g/zp/jr/C3eO1A\n", |
|
613 | 611 | "zNTJL+EH+fX8Jl75m569E7pMy/PUqaqM1I+uuYTQrwJOZVS5VEFVTNWv0gxL2/GR1JlY8aSD+pz6\n", |
|
614 | 612 | "ivqWWjcQMyN27WH3tWFY0sgt1WM8x/KUoLRBnZpJM+jlQZCLOiQoZWKmoDam7dcOaTdoN2u3a/do\n", |
|
615 | 613 | "E1o9womy2ye0ae2YVjuAuxkysj+pE5/lArb2InQkj7Vu0jd+Ii+dN5bHWmc15rnyHvWd5w3Lgefw\n", |
|
616 | 614 | "l0tLEHR4q2ACE9cJw24aR4OPd55PBg7lgQlJpRiB58Fz1nAvgx3tx2i8A6LBn1pBvpezw8ObDomA\n", |
|
617 | 615 | "T0saLbzvUh/jlMkPNZ/CyvlzWK+Pac5i2w8OuoLCozhNNhxFnZb0tIMJ0IvB3oOBfXj6OF+Bca5H\n", |
|
618 | 616 | "9HavegUs42RN1cB5HNeu1LIDGnDhVSB3MMA0GHZtIEcp1QFb5G+J52GYezjEz3LLEUJiQ6ueZoRn\n", |
|
619 | 617 | "Q553i6KbF0N8++jq27xq8NLl1bx46/f4g3zZeGL8+/yc8eP8N/h+GvMT/8rG/EI25nV8YUIISOfA\n", |
|
620 | 618 | "ONm6sg2xECqMABpsQ6oNKiWITP+4gDKBoiIktSAHATFFH4GkGnaDTs0SzaBmvWaTZptmt+aQ5rgG\n", |
|
621 | 619 | "N1C25TAFtpLuxpAZBDmX3RoGHgVblUA2G5Sv/ljJWlKrEJgtdaNHl6mxCH9P/SP1XvU76pPq8+qr\n", |
|
622 | 620 | "avaApWqEy4Gj4St9gkmFeEGOqUfqlHpUfUF9Ta2W45qlN9ktmITOh0xs6WEi+vjd1X//96vH7/JN\n", |
|
623 | 621 | "/J+MS/zi8a9SnCb1Ha3p0aycsp/yMvAaTFjRT4BXdOZ0hEOK8pCNvcxevy53/XN0fTDLdlJX9LgF\n", |
|
624 | 622 | "EwqL9E49E84OmY+bcdh8yzxhxmGz0yzIgZw8Z2X3MiPWnbcwCYGtg+vBRwN4myXYWoLXVyOJhX1T\n", |
|
625 | 623 | "Psb380P8Bn4zv53fwyd4+qbZ7RN8mh9j7AmahZBGDC8i5f/DXxIPoXA3aQM+ZD9IEGQMC8Z2wx5D\n", |
|
626 | 624 | "gi100hUM5AkQJ8RySqufjMKn+KmHg+QQPaol57qkzQkXPhDMa4rcQZZNWl447CBxECwm7JvziD/j\n", |
|
627 | 625 | "q1qrhKLxZ/k/Hxf4n4y/wP+rsOXLY13tQk+XHNtC/UjftH2K7uiltkkb8kh4xIjszI1XRM0BJkWJ\n", |
|
628 | 626 | "cfmM/1/8GGfkWvh/kSoDYn0iYBxRs7kxATHRyQRGBLmUqB8kjGn2p4Q1nbAGpFtMkkaatDstBZEu\n", |
|
629 | 627 | "dyWM7glPS3I3PJTkPhn+ginQIme7twSS6ZaxFmFghBMeJOqMSu57qfBAssinWNjjLIyjBS0xC3w4\n", |
|
630 | 628 | "dS0Q2z70fuoVyEbzEha2i+InUETe0Z5EWMsdCC3Eqi4WfAKGvAXK2veQuPuO+SQblckd5n3I36UU\n", |
|
631 | 629 | "rosgv4V35im4zE7ClJansVgsXkvY0mNRs7tYPsGj4dxN7ijbB/1zH7SuN8lOCkPqZbhSboLUBvnh\n", |
|
632 | 630 | "1NbgruBBWE/s8K7YmnCoaVfTwSZ2yM/2kkeaTzezyeFvjjb3NYvD2aCI67kwHnqDD7CCfApC7f8c\n", |
|
633 | 631 | "7YSNKAnDCRJpcGCFBeZmyw008IJVaRSy6KUbcOxfbrjRIGT9a1Y8OtU8yh4tWZr5Yc+U+JbZYou7\n", |
|
634 | 632 | "WusLkwILx4/b6211T4nt55+0L+huMrl8pTWtNcWvPjm7tuu71Z2N5WoxJopCxZKoc2ZD2axVz9fd\n", |
|
635 | 633 | "UJtq3dYqs97mjzirw/kbI4F5pf6O+l+WzTIV15oC/mJ3qDo6x6Uj3w4bf8J7bPx2ZHnS99nAtklc\n", |
|
636 | 634 | "mPVbMAxtIXwizJq7PTwlDmH6NU/TNW6Ji+IaJGv2Y+tEFPJwdE8UWWK3WyfjvmcJLdwXFKu/FGtI\n", |
|
637 | 635 | "ERN4kseFc0zFBbvRK1KOajglizpMzuUysl2FsR0RIjZUmLQ4JmoHuG8xtm5jclSySHAKFDzqjoRe\n", |
|
638 | 636 | "nvXc00LLdm5Ke4/l2vsctbdG2gb3/ZXWW3Df0ywKIlt0Wy+O9t7qFSZjJD4Ta9gcNXBl3FKxTXoq\n", |
|
639 | 637 | "zPhl7Ck2A58ywmgqDWL2tYefwmxpD4wY2GQNG0eMqgeJdmOijNIZytPs5ERtOlEbSPgyUmM7TpZW\n", |
|
640 | 638 | "NbKbhI2J7nSiOxAr7u8e6t7Qvbl7e/ee7kT3iW7dQGJeJrlnXmIea+GC7CULMAhB9iOBe9vy3cux\n", |
|
641 | 639 | "aiyHLrac9frYcoUJLGZTfbHCBOJsJ67sNLGdJoUj1LOdeuwsZnyHzfr2xU3yeyQ725e0s6nqbA+0\n", |
|
642 | 640 | "C8MJQzrRZBwxC3ipkTL2w16p3jhSzS7xLa7P4ig01i9GI3+NtOAP8XJx40gXO2NenG46L5AMzovR\n", |
|
643 | 641 | "29Al0s/wIssYSb234P0FHy9g0/OPF8hxBCshDK+FeHkS5p4UyDHYHg47T8GqsgaK8CjIVgIdANkI\n", |
|
644 | 642 | "w+MukKRfYQpkabyEnONPQW5E2MPeiPw48laEPexSG3jN1rZdbQfbjradaWMr+gEM4NMgx0BOImWY\n", |
|
645 | 643 | "ErTXgrwOchIZxDtAXge5BMfnpR7IsEisPwxyeiHYCchlkAv9uAHIJ/3glk988gRmBb3jOiJ40STe\n", |
|
646 | 644 | "cRQkCUYyCnISNpfDICmYHk4RwVvvxQu/BvIjvPArIEf8kwznBt77Q2RgX2q5juz21yI7Ivvw0p+w\n", |
|
647 | 645 | "LpB+xt5ceh/kHaRav9a2ow35TziQxHt/D2Qv9QDIVuRVv8BePrll3k72AZPnu692s58LPdd62HXv\n", |
|
648 | 646 | "4J3fw5tepdddiIzy/mv9MC89gQOM5AL6tFO4XmtraDKfGszO65vC8kKtSLnOogNRmjZ4o/DPpd7W\n", |
|
649 | 647 | "qsqQ1/ILc6PXThxxpt/SZXKHXJUN1Y68Fu/aSOuQw/3sfLDEuq4nfOv5cm9twVOz/NWD0fDSYutA\n", |
|
650 | 648 | "qGVJuIwvrIrUWqy1EVdYZ3LaiGXWzXTr9a6Z9Y58c3mRv6mxJdreBH4ZiDoNFZ5AmaEt6Kpp8dYF\n", |
|
651 | 649 | "azqXN1U+lh9uIv5SnnS1BduYsB1En3JtSI5o29OWaBOnxF4JCeECV8Q5uW7x39hMTIQyieqMdALh\n", |
|
652 | 650 | "BlyoGjPkc+gbH0FgYZNNzdT7Ivn4n8KTehNkKyOJkDExOyNtmM0PEN8JkYtdOuBgf6o2JqoysYKv\n", |
|
653 | 651 | "V/1R1Z9U/XnV21XvVmmYOgIT0hcwZH0E8iuQIZAySxXu/yrsuztB1oK46Ghy1HUB0DVuuQ2RHG5N\n", |
|
654 | 652 | "UD7wFnxJoyBd8l1OdmFpB5krH7iE+bMT5A6IZi6Tb2YzBpihyAGpn5GReewtO3sVNtbG+FObItt5\n", |
|
655 | 653 | "2Y5X4VyU7UhKnLcNjUOwMzAJ0GNkV4DKk/AakTgtaSGFuelEKYomXwaZ2+bFgffRls9B1KxB0kvY\n", |
|
656 | 654 | "+iHI34IUuefipDfR2VfR2W3GERO75V5k8JXJd3gOnfQyyA9B3kW82q/K/hmSimuumyKvMGlfRw8H\n", |
|
657 | 655 | "uTIc6CojJeQueof6aR7dijFJsL/XoNYfJr8WwmbXaF+GYNUKNvG5DvhAujW6l3VsNpMW2Kuo4VNi\n", |
|
658 | 656 | "v85QKBikl1UgFL30Y5A7iF19E7LLXZAtIF641ntBTsIhexiEhsANkJsQaXqRl3gdfPUF8NWDIGcU\n", |
|
659 | 657 | "sSv5QuOrAIQ4CM5/BuQGyLFJKA4ssEdBDgPJYe8sjBSQwyDaTsjmRGJoCIhvDiM350KE3pLLzvgE\n", |
|
660 | 658 | "zPIlCGcX8LZ3QLTogdFcfPTrIO9QNhfIfQrdgr92q3kXpLYvcu/bA3IKr/ox3vIlkI/wquTh78P7\n", |
|
661 | 659 | "3iA5Di+9F6+6BmQU5BO89JrGl9lLp/Y1phpHG2F3x+uuIa8W3nTfLCxXs07NQqQBXs5PBC/XB+LH\n", |
|
662 | 660 | "G37E3tBUKOa4oEiIaNi1dogmq3sKP8yF/MguDq01Ehp3N1UW2mpbKioC/ppiX9TfMLvYateXNvrs\n", |
|
663 | 661 | "m3aveW7Gc/EZT8yucTTMdLlCZcGY190RKCtvaCv78997gn+m1O2bUVbZ7C41lnst/O66UFuwxFdd\n", |
|
664 | 662 | "oc23u+rGt/zsheicspYFQV8sVFtU/VRTbUe9xVw7y+eONLgLDxyYKlvdyPG+vyXe94bEzYIsiE+7\n", |
|
665 | 663 | "CSSI3RPoju2z9qA7NkHU2oNVI7hAJsMSB3ICu9uBRyO5OnCPDrAFtpUc67jdAdsZtrd37GHbybGe\n", |
|
666 | 664 | "21h9uB54akBcPfhjzx4cDfbINnGunzcJ85m8qeFek3iOaVg87G5JlxCEyClmpN9C4ldxPHmrobwm\n", |
|
667 | 665 | "A5pOjQBjmfQA2jAMudykCQHcSJ1JiGl2EbInYvq/Vv2dKqP6tUo1IH1GWZdTTW9DKi3lm93F2L2n\n", |
|
668 | 666 | "YSthyEQ2l9bg1Y7jxzuE98aX8OvG34RsvIr7VJjDf53zcF8yZpcwZSD6mgAkIMfJILQNbfRkpB8r\n", |
|
669 | 667 | "Yg/2fRkuoQ4kCjLQp0vSiRK2bRyxCQQj4RIonoIieVlDYvp3hJMCUtlUAzH9YfGUCO2NNX0nLA47\n", |
|
670 | 668 | "DeTczbqHccYRy2nLJct1CzsD0W6xAoPH4anzzPTM96z2aIa5mP6ocEa4zEYBzj4qnhEvizdwP4AK\n", |
|
671 | 669 | "JHcaDhhgxE+ZR80XzNfoju9YTlrOW67ijvdwxzwE09V62jxxj3oYwFLDvAzB5JPj4LS+DhGjPhsL\n", |
|
672 | 670 | "FxHm5JVV+W1Gi8VRYg+XF1c6TNq6Rw/xcWNVWTGvyTcUVhVZ7Yba6bvobyc/xP93ysEchem7nqwY\n", |
|
673 | 671 | "mVRQiAn9gjic3CBshuvtNtCP8mG2TCLXjc35TsMSw6BBHJZEA/A5krPEBQBjQAgY7qHKSFdkc6vU\n", |
|
674 | 672 | "DKPCv2IY1WBrN7b+AWQudp8EKQHhyL6XT4vCZQ3l0cHoqu/XDengRGCd1a9DLl9GqkN+2wNwwdlQ\n", |
|
675 | 673 | "sou0TtgDF+Lo0yC/wp+2g+ipddI/5DAeWmBauk1IHY/momkzSiLvElz8JghHaFNs4CfhgoGOlkaO\n", |
|
676 | 674 | "oJCRzLDOU2bMN0Ei2P0cWypsQY3OWjt76c3oPtKPYQv9TyB4R2mZhr0RU+0MBJCSR9AZ+WRyO0wW\n", |
|
677 | 675 | "cZhSj2hOayAtU4L9aZBjlJODPFRkKZ3ViAOpg4ajhjMGccAUsWqtWsRH+iLW1tCD75t/sDr4zDPB\n", |
|
678 | 676 | "1T8wf79daG1oa9hY861v1WxkG9s4gatnMtjnTAZbyH1FvU5qqWMjoM6YmJuRtmHln5iLr5mRbisJ\n", |
|
679 | 677 | "R9J2SGI8Ywu8/J3bM9LediazqJkaGGhhr7mHKRmJFuNIgZrMKQicaTEmXOmEKyBthwgwxMiIk52+\n", |
|
680 | 678 | "kGtHhyxqJ5CIucaRFezgAB1MLhkaHGJfYfeQ8okC7BMFFCmIiaEjHkhBAWMinpHScdwW5HYcrQJ0\n", |
|
681 | 679 | "HkLrY5lEND2iY5M/QAzkNvKauRJjiatEBHAiHNoTbLlLFZU7ywPlbCw7PQG0xRmQhqBntMfiaOGC\n", |
|
682 | 680 | "eAxHmSr3JLtXzDiyWpDzUmDJuk8E1q7TcDQfLDpahLAXDLD7IKvgDF6NLQO2PsUW8gslHcVdg9zH\n", |
|
683 | 681 | "7o9BzoKU4ZgVAdWfQ1DZh6X7ldLXSxEjXmotZQOdsA1PYhknk8wamGT2mVNY3DUIxgqDvKKYlpIn\n", |
|
684 | 682 | "7efhpVbbzXYPvNRrEIW2z55CpOkrWP3fBDkJae5zkDUg+xxgg4DP8zrCDtVw8nXHmw5EFOKPZmQf\n", |
|
685 | 683 | "7IO40IOtNrh1v4C97h1I7oCQk/oAqtVWG6+Fe35GfAY6BTG/KyE8XAfpAyEVdSZIaTObyWuaX4Zt\n", |
|
686 | 684 | "6HVEmphb2V3fh2lhB8h+kPNQ3faDLO9At3S8jiXxNBbTPpDLIFEIk2dAbnYBjaK7rxtiDxOtkwd6\n", |
|
687 | 685 | "jmBptGGZjPb0YfsLKK5tvbgDSLgPEg7IfkZS5+dfnf/5fCbajGKt7gXZD3JsCZq8DF6TZWghyCiI\n", |
|
688 | 686 | "dSU79tkqtpUCWf4MlMtndjyDvn4Gr/4MlvYPMGpWYixcBzkKosf4oOFyFruUsRYFWZ0bHwbs7sLX\n", |
|
689 | 687 | "95cyfeoPSr9Z+kYpa5wDKCkzQfJBCEnxMkgUI+Gb2PpTkHzs/ghf+3OQl0HWKvJuSmu32n0YID/K\n", |
|
690 | 688 | "DYVuxJK+7HgNX55AFTXAGAmDrKWTMAa6MQZaMQa8IEcwBrq96GFfnw8KCYZCtLYPQyEyoxdD4SKG\n", |
|
691 | 689 | "wnmIkOGGHmjr1zAEVoC8jG8P46C0Fls0FKwYCltgjftx+C1Y4z7AYDiIcfAByCoISRtB3uhQhsJZ\n", |
|
692 | 690 | "EMKYO92lDIobIL1QtLrx1d8B2QdyB8QCCSrSg0b19vSyp/wMw6AV5Cq+eQ/IPpALIHdAjmIc3FwK\n", |
|
693 | 691 | "Vo2vb8OIMGMI3MXX/whffAvIRpBdIKufgQAkapiIa5kas6pAmoSmgi9mY3mqvT6yhOYi3kNaXAWp\n", |
|
694 | 692 | "me4hBNuWqtT5eY5wfXlwyfMtc762rLl52dfmLNjq77TNe3KgadGWNbNmrdmyqPtbA+FAd391ZY1K\n", |
|
695 | 693 | "sM6cEVtc1bG81TPbyO5lqTDWdDTYW/1VbXU2wTt+raAsT5fvmb24LvqVed7WlV/v6Pj6ytZY1D+n\n", |
|
696 | 694 | "wRZ9fsvixVuejzY8OTx3zgvzfeVOm/upuS3P9zfVNC42e8qKBH/nAndduD42Pycj/0VORv4lyciV\n", |
|
697 | 695 | "EoevGoOicAKWyO2te1qxzAX7sr6B+MRnwizhM87ENfIVUlUjW5tkxCmkDDWwhYUtmg3GhDktJaBy\n", |
|
698 | 696 | "UCBnJ8hgUAkuokTDwqnBXIoNkEI2NQ+r1eVkA4TOXAQHQDnpthdg/YfIBmsOzPT1XkR7JY/Vn0XE\n", |
|
699 | 697 | "+E3E812ulwFydwkHmbwkQ1MNJHeJB/GzQ7sPyZ47dPuAQrUjfx9yPncU7EPOZ7S4Dzmfu4oPIvdm\n", |
|
700 | 698 | "FcIWkH2a3FVyEEkbgH1KRip7EaCdco462akp9yiCriM1vTWImkYmruehXFE+VBySJUZzNtLI5za7\n", |
|
701 | 699 | "+d/aG+f4/fOay8ub5/n9cxrt48u6BOOMYMgaebrL4+l6OmINBWcYha6bwLWtaJ7ny/4KTeN/bKu2\n", |
|
702 | 700 | "GDxdq1tbV3d5DJZq22KyZasnfsN/lckPIvfThIgMZQgHE4hELeKdvDCc9fFPQGCBoZuwXB4DhaM4\n", |
|
703 | 701 | "rZQMquQqbh2MGVsp7PUgd5Q7w13mbiDs9U3owW0CjvcJq4R1wkZhq6BmS69wlHV9zI6+XyWuEzeK\n", |
|
704 | 702 | "W0V8AEUgz2eyEa9VR/nATOFvS7+sN6H9T0z8hvsBG2Mi15hQBRC5mG0tk1ynNFMZQgpAHYHyuJ9o\n", |
|
705 | 703 | "bxc+e/AF7pM/8RxfLGS4AJ+XmBFIDs3YMEMgZKAZlOKXh42RCjZmS+hQgMm12wK7A4cCxwNMrrUF\n", |
|
706 | 704 | "KjDQOpswbg0BIFtxBk8WzmUwi/+bJ1DQdoANTBtHcorHOFJDokhMr+ftvJ+P8iq2EBMkFfpHj2Rt\n", |
|
707 | 705 | "vxAV2NF1kDa/aMBRQ4Ojoa5hZgOg5/SN9kZ/Y7QR1zViZUI4RUyv5a28j4/wOEUjWASvEMZNSIMj\n", |
|
708 | 706 | "FJh1MAncpdvpG+wN/oYou510r5EO5O5pag63yoZMMw1P0trNlaKZBioOMkYHnOX86khJpc8caysx\n", |
|
709 | 707 | "6wVzRaVeX1lhFvTmkraY2VdZEqnmO2a2Su5gRUF7ka2y8C9qmioKeIEvqGiq+YvCSltRe0FF0C21\n", |
|
710 | 708 | "ziQf/W8nnuPu0bdwsHGVHBTXK+FebHzG9Ju57RyAAFQUsWPIwBNawkRPK1eCTq0gf0UNQZ3NSE/7\n", |
|
711 | 709 | "JgEPQewE2DcJ8LLHUP4u7ANy0z6I9PlD3SjVCNmgniT6EwlsOLAWfblmsi+1DdYGX0OEPo260dzo\n", |
|
712 | 710 | "aWzFp7mDTzPtI9/DnXSCDXfy404zQQjWZ60fd1I3mBs8Da34Krg13YLdv9Ha6GuM4NNUa8xynKgM\n", |
|
713 | 711 | "cU32ldZGsVWOJG1V3HChe//upxH+o5+GzZM57Nt8xL6NlvNBXweuXBoquqB+wAGwRQU0FupZRP+i\n", |
|
714 | 712 | "L03uYjZQikMfDQ399KfCvgefhcVX5XtVsXu9S/fyJzQBKYboPF5NKRhaWCc4ultg2t2sbNq2sn9V\n", |
|
715 | 713 | "uNsaMT/8YAuNmatCjM8j3JgzEqdBLBN3HJgjJzRpGELkWwLcMMN9iw0qG7RQYBRldc8UfgJaMTuk\n", |
|
716 | 714 | "UB+EqRUGpyGAaC8tQBFpmqb4Uf4Cf41nc34/RkjefuGwcEq4KHzCOFhMf0R1WnVJdV2lQoi6+oj6\n", |
|
717 | 715 | "tPqS+rpaDd2PzgaLky0N08+WDqrIaJG9AAcYm+Vlf0IIRoNwhM9TPdHR8YRqhnam1ztTK7zX2d3d\n", |
|
718 | 716 | "iYpoFEc9yQe1XE9CBzQmREFOaGSFSksgKxrg5EwJnlO4oobtaGTcP6wA7DR1Rv5wIuvqH7TjP/bi\n", |
|
719 | 717 | "jeO1479i362PG+F/LpjYul4gGTixnpOK1GI9u2CayNMo9JUHYx5PLFiu/PK/P3WP/XJZ/PTf8n/P\n", |
|
720 | 718 | "/xNXJXRLVUB/XW9nSrVdDrFZDzt/Ech2GbIyUZxOrXdvcm9zM8H5Fgydg25Em2BrCcimHEBlJXuv\n", |
|
721 | 719 | "SkVgKGU7pWRtryyVOXPKxQW5GKB9Kml0AZ2wgDEDY2mlDGCQBFSoHCRwDMrzv4H8GmQ9wjAITe8Y\n", |
|
722 | 720 | "yM0cgOBNzOuwugfpo/thJNmHKY3YMKkVSmYPyD6QA1ASjuW8IF8gveFD46eIaF4PNeFdRDRfKL4G\n", |
|
723 | 721 | "6aK3eAUCm9+FBW0popuvYes6ZJljIF+AGBB8MB/e/LPWD6zsNn0Q8+/Dkn+s7Cws+QYI+kdhIL4M\n", |
|
724 | 722 | "ch/EgMDv+SCE50+uuXdh5V+BPv8AW0Xo3/XoVUqJly4p2Soyig6GqnQAr0ngDfvwNgThj4wNKY53\n", |
|
725 | 723 | "6StGwmDxTYhI+RCRKLxzJd7kJoSlG5b7EM7oXQ5DJblLuiladTiXSnYXiVInXedztQeeQgtPooVX\n", |
|
726 | 724 | "QdTYvVglYwx6ZWEqwiaOVaPRamSB3GqxWPn/Xjzbx4Qnm40JU77ZxWH3ymD0mTnV1XOeiQZXuvk1\n", |
|
727 | 725 | "jhq+vLm7tra7uZyvcfj9Pp5nolVrKxOxeN7nl+PIPhJa+AKyyW6SOJ6N2U0E2garCllnpVu0gA8K\n", |
|
728 | 726 | "64VNwjZBNZADcVLxXM5OK40BnUbfrxnSbNBs1qjI3nYLEta3mNxiI0EMF04gRKVIdGId3IDgOhVP\n", |
|
729 | 727 | "YY3qNKapj8l/oT39X+166qkuoWX7iy/K2Ow0p7r4L2Rs9hPQ2LYzAvGlIy1pazpkbE8Fpn0KQjsy\n", |
|
730 | 728 | "pyoyWZx26U9hGHgLcuzRyjOVAgG0tzIhvtKY6GKthQd5cJ4y5Qh/XZlyXWyn6yH89a4s/nqXjL+e\n", |
|
731 | 729 | "DDbEmP4ImIUgm4FdxpGZbAbO7iIY9tlsBs5eMptmYBLpOuz1oZ0mz1RfRjbjEfiMzzKSOuI77buE\n", |
|
732 | 730 | "IhPIS05+2PApu2fyQOORHMb3LwD6HW7ugXViPzLDW6F39uTMEfvg5OwFOdKOMQ1yE+QXtDUb8xvk\n", |
|
733 | 731 | "r0GuQkm92AFxi5Txk1MMMkcxFM+CTG0p4fOfAklRWhHIKZCPJ7HJ0czraObBxqONsLo0x9HaA1Cg\n", |
|
734 | 732 | "D4SUhvagjfvJ742WXQXZBzIK8gmadxnN+5QR638EGRxzQvvojHE/+J2w4JFKR2NuvoQfnU26x+OB\n", |
|
735 | 733 | "L1AZTFPmkf/ReUaYij7un9kMc3KdkraQaYy/Y1QCTsmZmcLm5WGWKMrAzF3Mlq//58uH1v/Ot+vw\n", |
|
736 | 734 | "P775S2mdXTxxhP8XoZyr5PyCSVIVAU+Z8bqUHC/KBiBQO6UTIPoilQx8nUzrx4BWFtTH8LNdv4f9\n", |
|
737 | 735 | "JHQkOumNCX86UUp2Yyuh2znSqPJRo3ogv5yVvZzV8FDYL4lEMjDciayZWpchGHJsMrXaCqBlUEsG\n", |
|
738 | 736 | "tCwjnQPIs9U4UsmudNLj/GSmpqULgdvJ08IlqL6yGpb8QLwJbrMSgIr6I/mn8y/lX8+HB4V8kojE\n", |
|
739 | 737 | "14OpXyq5ztTcJNAm2c8R02mUC7mHaDM9LKB3YYUs0DqsDp8j4uh1rHBohqVdWJI+LPu0DFeUn0ae\n", |
|
740 | 738 | "80Ew+BvllEQF5RPuHWEgtUNA6hBCPrJJ2my9QNc+gLiUl68qV81QtasWAgcUGZPSDeBtH8s/m/8B\n", |
|
741 | 739 | "ILiPUlMJKIM1NXWy5HzJVSBiUijOSbRRjTamsHUX5O9hEvstNVl0mBxuR8gx1/EUmoz6JMlLZdex\n", |
|
742 | 740 | "iv4Ya9MBNHhyKT0LAi+zJyxPH7MbsjjJ5CGzPMN8WtlLauX7a9qKwq6lDcGmxeGKivDipmDDUle4\n", |
|
743 | 741 | "qK0m6ArVmEw1IVeT4Lb5vbXC7E61f87SYHDpHL+6c7ZQ6/Xb3IKgcQU73O6OoEvz0Fr0HUmDWNhN\n", |
|
744 | 742 | "kPo0kOUIZ48tMNwQt4HbDJWJqfe38Mk3o78ENcV0q8nfc4tk0EHVetUm1TbV5IolC8y0BkGIFCEd\n", |
|
745 | 743 | "JovUTog4E7jLBrhHBFEtR4S7fVp3JMQXYDX6ar/Q8uKL29m8WTbxBfc3/GXC6fkWSehSP1ZMeCaS\n", |
|
746 | 744 | "HGfkhOFYnqzXIVdGPZCSA28h42lkV0U+CbAlaekW2O16+yaw2wS2Y/Z+u5KrQxYjw8OhtPpMwmxk\n", |
|
747 | 745 | "zCHYFCmV7XDgDcVTtv+m0marnPovaK6qMrN//FeyG1n95xvceW6QydmLCO43IwMr3wOmso638bW8\n", |
|
748 | 746 | "OJys5dt4Nnrl2GJRTkwWmIiJuBAFCpejSOMMYbWxi62sz747d+4T3/+UUnw4+8RvRK2MHcctEH8i\n", |
|
749 | 747 | "VZaK9alNpdtKd8Ne7CxlU+9c6RX4FJaUDiKLe0yG18Y3nyBvD0y5Y1i6E5Vy4RSm1hC8ZSmyqJND\n", |
|
750 | 748 | "wQ1BBHcE2Z1OBNPYjrHtxMyM1I8qFRtmbp7JuFRtOjHTmJjFLoXzm5tlnCUMJ4LkYSLn0ixjYkFa\n", |
|
751 | 749 | "GkLQVBBBU0sWDS5C5uCiQ4sQ1rdIkQumla1Sgngh7WAEpTCaAmoRQj/7SOTeS3FFxiJXETvmNibq\n", |
|
752 | 750 | "mYgCK91EPVWESLRmkmOttxH3OKuVQvdmBRKtTKxhl3bg0g5jh6tDRMkt+Jcm4nhE3BkPxMVhaUF9\n", |
|
753 | 751 | "K65YAE/yJIO5AMtIL8jnkLUARAsdn22ndohIV8Q5uTJVADOT4kDF26VF0iL742X4Gr+ARunQ1jGN\n", |
|
754 | 752 | "MotZn0LZiKOIc6HCEV8g9MWgc+jqdKwpUbCrXfkH84+CXV1G3Md8pbRQalfBwYKjwE+8DA72BQ4Z\n", |
|
755 | 753 | "ChwFdQXsQhXE58+hIJiLPUwzSO0o3lecKhazeeAREDWk6zBcZjtK9pWkwPgugPH1gqzMJUYuB+ci\n", |
|
756 | 754 | "vAaC8V4OyeUayA0C44GJ/3TDJZj4VzLZJHWp8XrjPYSKUIzMq5BNVoFcBjkLchNkJeSVLSFcHLoU\n", |
|
757 | 755 | "wpKAAxtBboCsQCjja5BnXmtD8kBY6IGbWoXOJdD9HiUCW4qgTyO6Xphe2wriiMYmHEBdDuaIcP90\n", |
|
758 | 756 | "eN2Z2CKMvxUE5UdlnvAKZxou4xUowHpVLsTnPgiJhyvQ6FcYSZ5qvgip63shxCiF1oReDsF5hDbf\n", |
|
759 | 757 | "wetcDH2C11mWa//rrP2mh+ArtA8pwp6pCOdsAXBPB0Ff1rT8a11dX1vepPy2t6/Zsmjh1jXsd+vC\n", |
|
760 | 758 | "RVvWtAtzip/vDj0501UZfTJUE2uuVrPR1eJt91us9e2elh4dPzT368vY9S/Nm/uNZcGmZS919299\n", |
|
761 | 759 | "Lhp99vUl2V99fKl79lNNTUvbq03eqLeurayxo8bd2VQxq57kmkpunVAoPM34TYTvl6xAUUNVMmkI\n", |
|
762 | 760 | "JOaXgdAYH0sCw4J1QBqdnAAZAolZZenCoH7ASa5m5CWyDwBMMITkJpohITVvbt7ezJTtZjLOQ6SP\n", |
|
763 | 761 | "lPaCg8muz2TE3IufsL0HjH2f4taSredZcTrq7oPtvM0bBzgBwIoUJ9Vb5K+sj8OifxS84gA0gbZA\n", |
|
764 | 762 | "PACZJnAUNXxScFNEWnvhplAeHjb3wO96GO61I3hcFkblrcpjylOlg3h0mzs+5dGkehzAMyP1vXjm\n", |
|
765 | 763 | "fjwuEujFc/ZNPkc63Pro+PBYLFqLBm5+2cJDYEgRbxgufzlUNGL9vfLmLq+nq6m8vKnL4+1iMvIr\n", |
|
766 | 764 | "jnKeL3e0zmitWlRbu6iKbTxyhP99X3eosjLU7cv+DlctqquTzy0rk8+cto9vXzvxmVCW9dPEpdKq\n", |
|
767 | 765 | "ST9NqXHELPtp2OrZkJaCOT8NXDTS8aDiCyAHzDTXzDSnjeKnyeFGPs5PE9Mfs5y1fGC5ibAa2UUT\n", |
|
768 | 766 | "079Tf7L+fP3VehXpgD8S9kI2/ZG4F26ZsNhDThrGggWlPk8S7BSnFO+F4SRc3IOfH5XshTMGaDmS\n", |
|
769 | 767 | "vpLPYuUMJ486zyAUW4+MdiBjJY+6zwCyTA+LRxQkDkyco4ikuw+ix24UBHE/kt4DpHhwaoUrzcQj\n", |
|
770 | 768 | "Tjv5gchD35x3t7qnewatoeLQBnh0oAFBE4JHh//5f8yjM35r8cMOHf4PmXzin/iOIFLtgyffFtUa\n", |
|
771 | 769 | "VT3Z9NJZN85tgc/aQsn4SQZB2cw6NcNQ4vJUsoWMrGIa0hb00BZgyAWSQ6g1xEf+7u+62P/5e+1f\n", |
|
772 | 770 | "jgoz2/9OtuU1T3yH/4Iw8f8ze37h456vlquQEPyOgShb8lG4BhJeIex7HAyYOSgWapFJN9kiSaUj\n", |
|
773 | 771 | "HBZVYEQr0OhUUdUaEUjsaGux0lb2jwniZDCW2/wu+6+LiKBqH0+1nzjRzs9vPyFjUYT4ffyAkCaZ\n", |
|
774 | 772 | "KyWVVkJGZYJWVqpaIqcyQYwifMnJoo05SF51BsKKPZPFBiJ5k6ewnyTsvuAMWNZGQQgelyBOTiLx\n", |
|
775 | 773 | "MwsPdxRj6CBWsTOA5coqY3IxkgO47DQICuAkDxecwhWHccVeKjNYwv+7oLN8g7HMYzZ7yozKb9BS\n", |
|
776 | 774 | "C1iJWovyK8ya+mf8Tv0r+0VfTVwVlvJ5wjGS5weA/g+7cSZmkg1ZMoo+bO9jGj0TGzVGDeuOfETx\n", |
|
777 | 775 | "JBHAw4R901DJhpLNJdtL9pQkSk6UpEvGSvRQNcwBG5R4kVgOBp2pJVtaF5xyyvbecqu1HP9OKBvC\n", |
|
778 | 776 | "66VOZ+mUf0yOXsytEBYKWmpnGbdZ1jygFCWhEwmK7pGE2sH24FtinXoF1kzYzuWiD5se0kCwbSM7\n", |
|
779 | 777 | "uZ0p4ECUGQLhMPe3V0CJtTsYE7UTkgpTPRwEV4bR4Pkd2oe1qrWK/6OHVZAz4wI//gNFDwlkN863\n", |
|
780 | 778 | "s/eqn/gL/r5o4xq4MDdH+LZUDr1vDKhB6fIxaNQxiHSbQYZA3GoCOHEHpH7G5xgvT8xJY+aw8Vqd\n", |
|
781 | 779 | "STSmYXxgU6g8G3w5YlITkIIvnfAFRmrZDuPYIRVFY7Yrpolp+PqEDwzz+pwCBMqjhOLEnKzH7jh3\n", |
|
782 | 780 | "jrvC3YL6WUBzvgDw9KAmUBSqTcwhvKw6K1PUB63rrZusItMirIeYrJE1Zyf7rKusbBRVUYuryMXH\n", |
|
783 | 781 | "aG0mubl2e61A1awa2Y0ayO4RxmPD58JXwrfC7LEWYyICppCS3criQGqddqN2KwT3F3I1UrWI3dHA\n", |
|
784 | 782 | "Xr0flcJSxaPFFyBTixAtyWhAZve7sFifNX1gYm36uemvYPDYSYFekFgoGhuxV9LH0L1+BPI5bKcv\n", |
|
785 | 783 | "V74GseJl52tYcQhw8TmAKb1WtwNgSheALPQKDhyuO4UDVyHDrGwCE0CbEX6EqU8JRRo0dC+s69Ra\n", |
|
786 | 784 | "qt5Kgj8xg9+ikQRPdxVEi9ZTCdLLILty9Vr3o6n7qYoPWvkqIuZQ+lQ6yZqRerkOLYO1BC2j5q0F\n", |
|
787 | 785 | "oaKWK5AM+A5SakYZMU1aOrCsab1ebXGlKPuK3a1ery9SKYYiWAvDXp+YNYKMV3dH3FXhbk+wpm2G\n", |
|
788 | 786 | "u7DNHK/xxGfWOCPz64M96yvbjbW1PmPQ1Ogr4xdEg2UzXCWmqhl2Pm5wNnY11vc0V4g98wptTmPQ\n", |
|
789 | 787 | "XcWPf15Q1dTdVNfdXCnO61J11tebXZY8Pr+yyROaW8KvEMzVDQ6Ht8KipzWqW/gK93NaI5slDcf0\n", |
|
790 | 788 | "6t0cvIVsUMjcS1Q4VkrmYCL4kp7xJTEznR115zjPf1M4Du6/gtFd/PtslvYwJT+JSFxheERUP5A2\n", |
|
791 | 789 | "w3gVU6Jok0PqDTCijKmnQVooYpSS7S1X8dnV1cVuSesU4nEe8GOcjvPwp6QaB2Y+hJMTIBwTTmCh\n", |
|
792 | 790 | "RwWhfqTPOGQAf32aoLbZn+QZLg2ycQHwbyrB1Q+yHgbpbSBjICdyZbmcrCVOw8MynJOcZkx4Mstm\n", |
|
793 | 791 | "Tuk24nM5PT9MMZtm40gh+3Ox2Yk/Fwek7cVyYhyVTqGQ2v1grqug5Mmw3yCEDt8Dsh+Low9bvYBD\n", |
|
794 | 792 | "IOjF1cD9WWl8wcim0hbjTjjLVmIKbMRkiFiRGGs9DWYRsfUC4Odo+ZlyWBkrTgMtMQoGTcot3EQS\n", |
|
795 | 793 | "ByzDJVTW9wChjuH5kVxLsDgnw/k9+ew+1nwf+5Hxdz9BQ1ZgCu4g5DWq8WiEmXSFca3xFePrRlW2\n", |
|
796 | 794 | "LUetZ6ArUZoG+bEAfygdBtGiKRGgN16oulYFtHhZJdSyqSJb4KcFkZn5ZH/c1d5QJojlje3u1kWl\n", |
|
797 | 795 | "obrnZ7asinlqYsubW5dGK/nCuU/Z68IVYXdHg6PJVdfaqMiG3s5lwUol1+EB5Xmty+bK/oSNJx8+\n", |
|
798 | 796 | "/rC0HiNgCUgAuzQqOAQBbvBu9gq52ooP3+NpukclXZ4MeDu9rJe2g0+M1aFfb/uzWEXydcdy1z1H\n", |
|
799 | 797 | "17XRc2L6Q97j3nPeK17WcRtywzEInRwYZuzvbcfbzrVdaUMIedu0PN6pbdlE93RI27M663ByzH/b\n", |
|
800 | 798 | "jzXeb/QTcoDIhdk1d7Iy3iL+r6XYfDZ79qDUahEyWjZjawgkxghihaEGzTdS1bAYFpFEJDBSSsew\n", |
|
801 | 799 | "0jQEpD0N/MBIJZtt7fNjlDIGP8wiefvsImUKTcPR7mY73Vgr3c3d8qpM2lA3IWhDP7bzD6RaNaVd\n", |
|
802 | 800 | "tbuzdlVJi1D5FflrgSsMmOzkioK1kACBAp1cWfwCnKuwyUtnYRhaWfICVB6IkdILYOjrAhsDWwNY\n", |
|
803 | 801 | "8KC/rW1hh9a0vtz6Wis7tBYpTadms8vOd1xFYsqKjrUIzD0FT9L5yfK0yfNdV7vY8ZcRh3keEeYf\n", |
|
804 | 802 | "IOZ2Y5yd8UH8ZpydsXLBC6jI/AGSe1cufGEh2gDD4AcLby5EdCBhg+gx50/m8P2AhyydgplrBRYw\n", |
|
805 | 803 | "WOvlNNIVIGuU9kqj8G6Nok0nFz4aNCc+tK+Vl6VctpFS9p3mVTjC/6XFF612t/ksFl+buzrqszhM\n", |
|
806 | 804 | "1Y1lZY3VJuX3A6uv3OgKx2tr42GXsdxnbY97Zj/R0PDEbE+8/ZSzFZe2OrO//LqyxiqTqQqX0u+3\n", |
|
807 | 805 | "dc665rK67qDDEeyuK2uuc+oE43M9jfNby8tb5zf2PGdk43F44gvxFW4Nyadu7qdwa5VAkobcZFXM\n", |
|
808 | 806 | "9pN28THuNpenCK0AUMjHaflD+RvyN+dvz9+Tn8g/kZ/OH8u/nY/T8o2Ma0FpseE025Btg22zbbtt\n", |
|
809 | 807 | "jy1hO2FL28Zst204zWZkvFIazNV6KGPjswwsvigNQbwMCZgJc5rE8akSrPp3bIuvKBLs+NuPbimG\n", |
|
810 | 808 | "9Yf/cTK+1TnxOl/MesaJ+CKmmaqN2bJPfJqTBLjaxwSwAA8TmcXrD2zi9XNdnHIt/xldW04XBqZc\n", |
|
811 | 809 | "yAvTLuQ/G8/nP6MLBaYjjAoL+Z0UO9MC1VNAFCT0VIEQoXg5bEarhBeSFisDJN6mcnC8uarVw/4J\n", |
|
812 | 810 | "CyGws39Ce/uO9vbsWi1Ui3mcn5utegKJCeoisT65ybmNSYFsBU34MxLn9FOUKpSS+dxq4Nu8hu23\n", |
|
813 | 811 | "uXehi3ydEKaK1FQYCba2X4P8HORDEJd8+acweD6NsIgPsFXhojwc4Acn91WkKuSnudPQABAvkwRG\n", |
|
814 | 812 | "Kbu7Tz6PfNGvMQLfY50s57cwnrYEKWwBkEFIe50gm0A4ZAKOdWLE1AQACuAMTEbZKKJCrj6irxZC\n", |
|
815 | 813 | "gPQynvIeyB+BVDhrcTSD9fAmGvpWxTEs05yPoikJnsxaipA96T16U/n4dbzfJibrIJQSJqqoHLL3\n", |
|
816 | 814 | "PM6PIDBnK9Tlb0Pt7hGXQ3TeAZMyme+1YD+ElbEV5CbIUkhlpJQTasZbIK061kejuguAPqMkzR6q\n", |
|
817 | 815 | "N4stNTKQWkEAW5SM5vXlAUcdjEyPgjbR/D7ICmdy3sczYGo5l6mMkEx8mVI79ZDP78D8eAfhLyhL\n", |
|
818 | 816 | "kvym7Q0gR6+0s9tttG+FPfQgpPU/gIFyl+Mgwvmp/iZCfJJtFfEK9sCVkOJ3onPeAtkFEecuAqK0\n", |
|
819 | 817 | "MGT5yJoFkoSY+DxVDgXpqUF9AW8PrJphLP1hiEURfKBaFB5ZhQzSd7GkvjljMt7/TcoAgRqwC+St\n", |
|
820 | 818 | "JvREc18zLHDNB/HTFo4j0v8AIv13gRwFOQCb+S4KZEBeZQRepTdn7Z/FLnizfX87Voi1GPyvCltg\n", |
|
821 | 819 | "+CBHC8GSrwShD0c1uI7hSxyjNGF0MWlnyxEAdZWcGkBrfBVgC6/at9izPSnFEQ91Jle7NF422Xe7\n", |
|
822 | 820 | "siWAWetdBxFgdAC992MQB/rs39CP9dhaANIO8gxIIUgvDIJhyCzUgb205QNyv68Xtuk69OPT6MfT\n", |
|
823 | 821 | "6Mc+JppIBpB9CPzYj67cj15shcSzn+I90FfRXK/Nz3XdAfRaFOQAkzP4SlE7zcJjsUYaRdmeDAha\n", |
|
824 | 822 | "KxNDH7ZDDjXGmx28LToUD8smxvCMnhqh1OP1W/+w5kVHwNLuCFrX1I6P2BvmUJA5BZ3PabALP2z8\n", |
|
825 | 823 | "yrMvzmr4yuImRbQsrxQ80WBdabSmzVZb5DH7za3ucddDpkriseT/JZ2riPvm2/mqAlU99H+q3xfT\n", |
|
826 | 824 | "K0BLquH/yLqXvFJ8C8KOEwEI64s3Ybs/BwtYxJhO0SNYSvoMWyqne399TKvKeX1L4nFlXfpPgorL\n", |
|
827 | 825 | "trmc+xv+GrX5/3u7QJXP2pxvlPPTkku4QSzBGjRX86jV67YmDwB2TI10aYKamKZfo/l32j1N96OX\n", |
|
828 | 826 | "0MkRmdmmT1U8EQW7bErT+YTS9i8fZGuTMtIrcpydO/E2r1ap6pNAwEImKNzVHEDbTmSD1WDbJFc8\n", |
|
829 | 827 | "2CAHwDa56CxFsWD9VGdAtXJZ8HSikH2w/sKhwg2FmwtVdAdbWupEaGGwbBpYneICoELOhoci8FHE\n", |
|
830 | 828 | "mUdgbxqpvVpC5C+RGXlcQd/npOV6VGDK2pxlS5k26zwzh/jq9V3PPru8t7CiMD/fUVBWXaJZz+8c\n", |
|
831 | 829 | "f4Hf2b55YIlKbBdVJVUz7K/Cn47++CXrD3xLP58HDKrb4BQcCjoUZlAAcVgpdw8Mv4dGn459TCMn\n", |
|
832 | 830 | "x4tidGqGASdepH4ApxfMY8WPxNxUZpInKtPwIQXhgK+ltd6F8iXkykYZJipyJCXqp8ldSq/Vsp1a\n", |
|
833 | 831 | "pddK2E4Jeq0M4yF1Tg+wNHEgltepX6If1K/Xb9KrEbABkbAgjYcVgo4UY4WkfSvkOKDdwI8St69E\n", |
|
834 | 832 | "wITUaweW7RTBjU0J7e/s7l9WlpRU4l9RV9eeR7te2GIuKzOzf18+y7/f/rjPQHGJn/E3GR/w8F+X\n", |
|
835 | 833 | "DCViPRpck2YyxAjPpI6arIiCmoTSEIJmgYQHTDyghVEFM4NxpIx+shXEEzmplbJK86dOIHSYx0gA\n", |
|
836 | 834 | "z2pPEUW6BCRBTYWEPoKMYCKxSqkgDtkHpkhknLNL3HQiaw3G5HksOstz1nsqBnkY5B3Y4gFmwT70\n", |
|
837 | 835 | "KIHgYFFCSZjkaP6FXA2YNSCjBMUFQeBrMMWdx6L/CQiViZ8JcgDLvB6r1UEsSVGs6fNBrhOQ7ztw\n", |
|
838 | 836 | "hi/XrkGKM61+W3G3V1Ft4qL5Ezgy1VkgjAFpL26lwa3ewq1QA4av0mZBaB6BKafAOFMV/8vxf1RZ\n", |
|
839 | 837 | "g7bmJ2dV1cRWhOa+WNFbGg9Uz6y3OxpjXu+Cai2/TvjOeb2uevZTTaFls6tjHc66JnvdzCpPR4PN\n", |
|
840 | 838 | "XMKvJ96J+fa3ImZeBfceqiPfRt9wOsIGlYJUml5NBZLV7EeVAVqsPiPX7wQtYSfBzgrPgEAge+Vp\n", |
|
841 | 839 | "aQNMlNtAEiDAoJbSTuX7E2cpnPr9H5s4lgt259OKG1JHhu88CryzZHmQgjvCJXsLVjA1uwrR8L9z\n", |
|
842 | 840 | "avzt42fEZ+M/+x3zgJt4SdAIaa6O/w4bfkifyAIl2DLSEL4ex74jOAvTXGppjJLnqdRky+4wdcyM\n", |
|
843 | 841 | "OgS0zzioMyON5TrFT9dwCT/yJ+itK9hbV2By+GW2qyXrHJg3Yw9+Yg8VxhE3vXwqwvfyK3hxCoht\n", |
|
844 | 842 | "8hXhdXherYJPEIZTO40HjEeM4oBky+U/67F1D5YHXbENweorEVt3D4KWDkJqraPNgRojbDt1pOx0\n", |
|
845 | 843 | "2aUydvlBAmcBISCotSBvgkRQGGqFB+Ch3hVeYZhL7TDuM6bwSAsedBeP1LKtpKbYgqdR3SSKNtQr\n", |
|
846 | 844 | "0YaqYekd3HoU5BrIfpCLBAyEh6wDAfgW7xbhms1Nh4iJfeQIEvCUb6zVhvj9r8xVl7ojtZb6Ylde\n", |
|
847 | 845 | "eYG10pQndr74SpmmtKbF21JfXVBRZHeVGkTLi/xXx/eUhWeU5RUENRpTpdfEPxne7myb4agI6vS2\n", |
|
848 | 846 | "mlrjt2mOeBnREI5cIfc/UVViCfhcfkbajZm9HqQTJXsxOBi/E5HYNKJV0ZpJ6ieOMm5fEJDEAiXQ\n", |
|
849 | 847 | "6vF1ebWFMlBpIAuHIPmziJIDKF+MW8txo6KCXnAeX/4aSA8Sk1ZQJVHYYslW0wZih92pr2BVgTDM\n", |
|
850 | 848 | "OnCWQL7WqlY+xK8UPrsTX7MmPv6/+cpnhG+N/2HXgQNP8mcRq7hqYoxfInzM3llPpZpFxl3dvJXf\n", |
|
851 | 849 | "z78bGu8QPnZ+WZa1cRsFKz/Gmbh2ISK1eFHVzyujIcGyvaSFbbcYR8rl6AQ2e5vT7G+J9nSinSm4\n", |
|
852 | 850 | "UFivwE7UCXIcBGAs3CRgnMINyC5neMiHRTtRthPVyTUuwSTq5ViF0igCzpInS88j6i4FR8rHyPDf\n", |
|
853 | 851 | "XrqHHUhEjSNWdlZFVb2i2ib/quIX0Go/BRMO1sM5lkoG3wu+HxQppgEhaOzPrRT1BELK6n5Eoe3U\n", |
|
854 | 852 | "HgCj34klZmf+AcQ17Cw4AJtfK4b7PpBekDcx7xDmJWTju17DqkIwAmuxFceiEMdS0EaaDxShI1D+\n", |
|
855 | 853 | "zoCchmYC6DUpDqUkCpJCsvaK8FqocKewfT5yNcKefzhyiv2kzrRfbr/RLiKMRkbwf1PcD0WbdLMd\n", |
|
856 | 854 | "VBoZwzdO7myQH4N8A215H+R5kKsgrWgkmpsEwApeDS3sATmNxh0DSaFxp0BWQBO6BE3oDMgxkKNQ\n", |
|
857 | 855 | "hy7B7HoG5AbIsfbJEAyfUlUou9hNQ6WkQIzWXOH7V8sCnZ6aOc1lvK2xy+/pDJTlVwxEm3vqTYLr\n", |
|
858 | 856 | "mVBoVZe3pnNFizkQaCwVukyR31/S84cNtz1zmiocAXY6+61omjP+A1+gonmud2mwtqZzZSi0ssuj\n", |
|
859 | 857 | "K3WXLR4PepfHg41Bjmo1fCZUsPWxhb8olcKodUiWxgmPEbGc0olsQGd+Gu71Usac2bj3cjAKJ7wB\n", |
|
860 | 858 | "qdBbStZmQKdXyEcrAih0PwP1G1o3I/ZoSVgZ8xQ4XviQY2laCWHJp7XLIIgjXjaAi3yE5WWXwXe0\n", |
|
861 | 859 | "lLaK0bpOtRGqwavwl6wDATZ48k3DfpTEewmLJvlDoiDkl+yGsiOnMUlhmD96cobdHghB78PoQZYP\n", |
|
862 | 860 | "DdT3s9haicoA66o2It8DqRTJldUvVCvBWN8EOQuyEjUI5oNshAp9LYh6VU3Xmu4AJdUCzNQLzdea\n", |
|
863 | 861 | "7zSjelWzpZmtIsm1qlfQ/OfR8lcoPQu6xsYCpcko7SWX8R1G4UTWfII0RKNGs0lRA8lk9XtozUto\n", |
|
864 | 862 | "wxqqrIf4sO66ZXVCtilvMBJyF+esz5Qzmx1hrRY5FcHrbpXL4pEMsaPL3PREe21PqPIbM+bUlVZ3\n", |
|
865 | 863 | "rmgtrCzMt+X3D744UBn2WeOh2nBVoeCa8USHx9bQVfdSnaCqifb6Wld0VInqqCg8s/Tppe0FFYHq\n", |
|
866 | 864 | "9q7KxjYH47V3hBbuHVpfngOiCjDZHwd6LGZieZOIpOoBqUjkh2MFQTEm9otD4gZxs6hhmoZLVI6o\n", |
|
867 | 865 | "hxOCkkbJZ+REccbKxJDVbXj6uVnCe9tlHXQxVycsZG3QcN+eNJ6qRQD6xIr+i/pP1T9X/5X6F+oP\n", |
|
868 | 866 | "1Z+qtewBZrVH3aruVi9Tq4elz9Q5QH4ByQ2yBVdWV7MlalQZaQIqq5oXJhOqZINs8hR3EeEcp8VL\n", |
|
869 | 867 | "jCuZ1GZ1q8ezmEyz/2P8KaHlN42/aT9zButMC+fk9/J/w6m5PH7R2xqVXlX/NqcSmb5MCv5Acok4\n", |
|
870 | 868 | "mC2IkA1WhtyoZ9JihuCcmeZKyO2cpDOgZh2shLfA/4AuD0FWSKeMBpchaBCHUycMacMYyh4YUO0e\n", |
|
871 | 869 | "kpZc4ZwN1+XQyO9T0rGcI9yHLGEDHaVMMjkRvA9Z3AYsxvcpWt+u8quiqj4VjiI74r6ajqr96qi6\n", |
|
872 | 870 | "T42jajYN/Jqopg+h9Mvhd7lPle3tWr82qu3T4hw6SqXs7Tq/Lqrr0+EoXuU+gWnZDX5D1NBnwFHA\n", |
|
873 | 871 | "EK4EhDUwc9if8vx5sIDiTwTT/jQcu0+zTY9V64tY1UT55q8Hvv/9wPhF+rmdqPrlL6sSRPENZrNv\n", |
|
874 | 872 | "8JfZb9D6tl6lYd9AVHGqemkIdok9RLAoDskV66FBwIwBaCYq3uYEHLwTFtnjcHHrKcDtNgLc8tIc\n", |
|
875 | 873 | "exGxPnVCl9aN6cSBlFHn0gV14rD8bWT8foK0BiJ77sNIdyhfV8NbeC8f5nt4NiRXKmUdpqXU36Hv\n", |
|
876 | 874 | "oFFZVF5VGN/hjpquVFvUXjUSQdmVMCuzQ1qL1qsNa3u0uBn6/A71OYqme3Vh9Pkd6m6NwWLwGsLo\n", |
|
877 | 875 | "7jt5dGWeJc+bF87ryUOdytVoxzLqZtxkGetrBI5qfR6iCepj3v+YrgZ2Mefk7lBf/+XbaqXeU3Ym\n", |
|
878 | 876 | "AWl8UIuxzIsYy3gO5YrsRnaDzB7QgyJYgUiQcPcpvcTOyeMYg4DLjuOUPIxFZRAjkt4u+sWoiEO5\n", |
|
879 | 877 | "AgGPHcYpefgy8UIuq7KaHYtgHGnv4KW+HqOXkmM52Njh6H0OvS1QvZiJbC2ULOwV+55ylor8ZiKP\n", |
|
880 | 878 | "wUDcD6/Cu/gg2rgbw6sTrbolylEKd+jNLExID3M9eDPCYFfTGMDryQODXarGVXfwehbRK4bxemq8\n", |
|
881 | 879 | "mTww5GHRw96MTQ3cAZUupOXsBAB9+SLd9EL8HvmNeC7OXuqy8Bln445I+TbIBUwZhK0MQFxsvG6S\n", |
|
882 | 880 | "gdwAzyWloeAjAUaacEwD5SicKv4rwi0lkmGhF3RWSA4k3JOY/y7I25hbBdC9YTRCDyzHhDpFxecw\n", |
|
883 | 881 | "SbYU4X02GrcadxkPGlVM9DusPwXEf/xB2gjwrF1FB4sYu82Cl1jMTFvOLm9md7xLyKuuC1hXL+8K\n", |
|
884 | 882 | "96kbQ7VdTDv+kcllLRhcOX6RFxc/pauJx24jtjAptPDttG5puZ8CGWCTUqExCex9xo2FTHJMuC0D\n", |
|
885 | 883 | "budAtqcib/8/ALfl9PaUXCeErsrWDWFXqTJydOyjNT/YcqfCckcORQ1b9DROakhaxutWs39HZj33\n", |
|
886 | 884 | "9Pjbs54HcPf27exberlzvI/8kW74I3nCQlRnsl7MTsysTnT9FLekb3yC589la6OxscAdEI6QzXIX\n", |
|
887 | 885 | "U+ySscL+QuHfMVMWTzVT4u86xVQpbUaK+VDxBohiu5VaOlKsGEKiPjBpNlFGjFJTJwljo5At7UBV\n", |
|
888 | 886 | "HdZn2SwFRD1kPzwwxUo4zSRIMRuz2Dt9QTEbL7CRruHmUMTGblRWQwqlINdwSMbU/Wq51sPExMRH\n", |
|
889 | 887 | "7MyCKdc8za4pTR5SHcfp/SqsOrfVcpzJxFV2Rh7FmcjnPsfObYkV7Vbh9HOqK6pbqgmVdiBZpHKq\n", |
|
890 | 888 | "hGH2B8shy3HLOcsVyy3LhAV/sDgteDK71x127TtTnruJ7ZekOK1R69KKrI3afm22HoUw8U8Txuy3\n", |
|
891 | 889 | "cnJ/kbCwb2Xpt0z9VnmT30U9/Lgvl7DQJJc2u/CVqjZA+N0NmTOGvPaxKszw7FealhNKlh2mp9KX\n", |
|
892 | 890 | "UT7V+mzNvuxXgm3HKAvwPWXLy4QBLhUvW1n2Qpk4MO3zKbWai7P6kC/3Mf+XqDPpbBWFqi7BGmkp\n", |
|
893 | 891 | "t+W+7IMUL6hKKqqLBe+X5wxNzV4D8WXwsY8YHzPwf87YUPKQ7rhOGBjRqqmuH1u/RbDBFkyBHhCC\n", |
|
894 | 892 | "FLDRwgbyR9h9F+RrWOeZ2FjCZJ6UWwgJcwXGYJdBAgpj7swD+SlqygHpcruACZ0QTghpYQxJ9zoS\n", |
|
895 | 893 | "294C/8cikPxAfRMRd3+MA7+vppov0tcgRH5BGaWiyqRyq0KqucgoHSIg1IdLv0gih+D4JArYCXJi\n", |
|
896 | 894 | "anKt+Aq2qXLyXqwkP8RRVPlRshLJE66wZeLRyudTKuY9VNaHh2E6eZH7BCEAq7FwWECACM36joIB\n", |
|
897 | 895 | "1uJJlBi7EYRKRB/Bg7O6OJV0NoNo5Auu51ArCa3BA6mpVINiIaZISKt2+xAx/8Y/PHuDF9b8tquL\n", |
|
898 | 896 | "5//+wvidO+wjKjGNhC8SZ+2XtiFJF1VVBLLjUkxjEmWXhN8V1fiw8pmLapTvP6krfItgZMArJZ7K\n", |
|
899 | 897 | "3MT0dfxMfj6/GhLxv+HBwNHB5P0u/0P+Z3ySf49/n/8Y2oxAPipoC2oV0xaoElwO/5KfUkhOQYli\n", |
|
900 | 898 | "qoKsIyRPaS4yhs6r1WZPq0dYOP4U0xQEfpy/d+ZMO1MX5DZ+h+JE1FwDJvWUYBBFNdBmuCynl8vV\n", |
|
901 | 899 | "3SZhwgOzWJWwsH28gx//zgft2dpb3E326nnceXavJByEcoxoLlkii1lDKRrSZlhTYrC67YauOoaU\n", |
|
902 | 900 | "gaGCDQUYX3xASZeYNsqUOnWxoun1b5iqpYfUg2OsQ1EAK4mKWEjAPa47p7uiu6Wb0KkHUkU6lMti\n", |
|
903 | 901 | "assm3TbdbiY7ZwvSsMFJGfi8XBRXowXucLY8VK4wlCli1rLlX9saYR/5iSe62P/5s0v7nhr/z/zs\n", |
|
904 | 902 | "p/qe5NezPpjLcaLAj3Ez+PcTMwLS8Rn8wEi9msybMxByRFUBpW0gt0FcjBGOuFDJlyK/LewEKObb\n", |
|
905 | 903 | "QG6DuCzsBDMbjojJkzYgsa+zkfXZOWwNgmwDKcKxTmy5sDXWqAxUPesyvTIxi9lOsWFqZyo7SsUJ\n", |
|
906 | 904 | "Sa2XbYHq8xjwaojk/wTOUlhM1j91IZsU7xd+XIjg9DQqNRcbRxzCA8aTRzyyjEXpHCl83Esw5MRz\n", |
|
907 | 905 | "iJKXc4iScdglKL6BylceRFTDLvtBRDXEYcq+BBIFiSPEVFc+WT38OkyOB5HXtKvmYA0iWWohA49O\n", |
|
908 | 906 | "ZlRK5/HYHghvF4quAfmUguDDeGYvyBt45k7ImK1ZuNAB6QLIVTzsAuGqg2iB1XINz/svCJXYWcMP\n", |
|
909 | 907 | "mFq8qGcqO5yyYAxTJcIpsqEo9Aq2ZXWm+lp3fumKAJMRm+d5mp2F7EdT3+jp4l90tDh6/XU6s7ey\n", |
|
910 | 908 | "oYUExuLehRXB2VX3sZGVHGFf/hdhJTch/FfGp4yEy5Itr0KCCpuEE+P/yhcKK8OyfYIvZvN5EbKt\n", |
|
911 | 909 | "p8tnFCwGDZN9Ipq5xAmK27GuTZTz/8hkmXLuH6R8DvI5R7khAK7KCed55BCWLpbIDnZHWkqjZxIg\n", |
|
912 | 910 | "VBZpe+U0ed0w1VGumTr+lB3yDOtkr7la9tvkpaUSG029DAYHcHQkh40Y/bdhPf2vIH/moKrTjr9y\n", |
|
913 | 911 | "/MLxoeNTB1WlTh7VndFRFWX7Eftp+yX7dbsahcHesh+zn7V/YL/JdpkQn4W3hG3UYs1mr/kgyEfi\n", |
|
914 | 912 | "lS1eSxc+Gon03f4u/v3xL5cvsDXOrb89/ieOkGNhictWWPG5bAf6Lve8YOHvM+1eQ3UG5fJgV3Jl\n", |
|
915 | 913 | "hQkWpx8LlVxXULok17cCE2Ta22QJP0MmoUtTSTxpiGwuiN5PQqQShlOIDXFxTC7LwjxzsNGgwt3E\n", |
|
916 | 914 | "lOp1Mk9FATsNlw2rnQmB42mQXkgVVMQyDgVuFqnYIGQ2uQurTi+MIndhLlhO1o4VWI/bFCuNtBB3\n", |
|
917 | 915 | "mIeLI7huFVbYz3Bdt2JMkeYzXYqfgvHML/pJ/e7d9T/ZXbd7dx2/enfdnt3Y372njvpuLvRBxiMr\n", |
|
918 | 916 | "uNtSAbCxDtkpBX7ERksFlQ5ECk0h9EEl218u1rvd+Vi+RgvwwyNOUunhSExeUF2DUH0SnZCESaAQ\n", |
|
919 | 917 | "xi4lMOM0mFs3lMGUQVELT2GrGwYh9IjkA9mZNQGzLWgYG0HeAHkL5LQZn+4U7jWKi7fgbArgJ9f4\n", |
|
920 | 918 | "LpBRdo7JYjE/RpFkW77XBf5hbZKtJO+bPKZHFEr+q6aZjmzeBOvLBxT7PYP/O8lXwXpzM8LcYiB7\n", |
|
921 | 919 | "EPzok71LnWyiQmRG0LfPmKjLSPY6trKUig+kg6V0GhAJBhG8sZuRkRliNiOKKnrkP7RMJKrZnGUL\n", |
|
922 | 920 | "pa2+mny1TBq2HbcxabiIHTTbcDCJYu3CZNkgCnZbgbVhBUYPBUmvKFB6cSWm+laQI3AUIIIgqbVY\n", |
|
923 | 921 | "mboh3QOnvo+ZfwZM+gzGwWkoFDdc9xHWdj8XFHgBfpWT8IBeALkKH9AoyH4Qqkl2EtV49vlTfnbh\n", |
|
924 | 922 | "NThfLoKcnsErlX9WaZV2vYZ2LSfPEzEjeHYc8Oxcxrp8H8QO8z5hlFEjLzumtXQULT2PuMU7IARD\n", |
|
925 | 923 | "9gntosWfocUX0eJRNPYayAEUJzvgP+IXHsl61PoeSp8o1WhFN5+01s10u2fWWZXfuFActTUumVlV\n", |
|
926 | 924 | "3bG0uXlpR7XbcXwZ/3l1W63VWttWXd3mt1j8bX8u5OdXzewPNvXPdLlm9jfNWlk/fga6LM1NwsXd\n", |
|
927 | 925 | "mcXFRf6BFdAbWfyN/llgEsFmpXaYwLkZ0ZNtw8l/F/HAKKmd7HcOISvsNrY5p9GJoO0MLRWI2s3P\n", |
|
928 | 926 | "SBuwshSwQ+hsrrKAUM4J1+cWem83wH2M7DTMIr7MCCYqGKlKy0Z8qBdAxALA2kkqZ372aia1avMp\n", |
|
929 | 927 | "MFcn/1CZcuTDMZETCT158uFC+cIiumHCCHglaYJ9cAQjOTJkfJJKih00uDOIJygNSGbalyyOYvzY\n", |
|
930 | 928 | "5Z9yuWUV1P7H5BAqQE4SR08EeGonJHe5AYlCtlsoA6LdzpYpqGCbFWTkw56WRGcdZRHnUZahkbZL\n", |
|
931 | 929 | "6LiZzrFQWXl7GlHxZbDehCJuLdz9+BfS0j+zm/658Zf//T3L955e84eWF1+qmF3xPfZv9bOWwbWV\n", |
|
932 | 930 | "syu/VzmbL/npP7b/tP199h/7uXDhQi4/S6gi37WPf13OI3bJecTEXVzZmogGbMPXugSE0BYGQTpB\n", |
|
933 | 931 | "xkA4v+K/oxRjw0Muu4RbFgbsOUAFGb1YioN9RKEKTgcwjmh7H8UxDhf0FEzCGcs4xsm2kjjwnGQQ\n", |
|
934 | 932 | "YxkjYTiZsowCpS/nrEumrKPIb7qDQDoNJTyVnQFCEjAHJT3Ca+X8KxlpUA/JNFrRV8FuFXX2OZGe\n", |
|
935 | 933 | "5TpDXAkTnSkl7EDVmSqFTemr8AjPqAePwIzXIB4k5R1FpPIdxNhqkJ8U9vX44NprE+OTpeSTkYJe\n", |
|
936 | 934 | "+MnDCuLJw8kijyRGX1bCXJWw1ziy75UQWWTjP5yC70MErBIJy36VnCShimxGf5bNsRphY8IkDYJb\n", |
|
937 | 935 | "7a49VAuTlZ8fnpJPNe38p+l8F50vLanlh1Mn6tP1Y/XigGSsJ0tX/dT8J3btsdy1z9G1FukQrnUh\n", |
|
938 | 936 | "5vgQ8npcM3k59wl1AP+A6gBWcgvFvdKCWcDpQL2aACrXUCGbBCOJBbIbOm/WAky7vIB0Ow81H1QU\n", |
|
939 | 937 | "azHLOGJmWwvYGphGyS+2OjblEZ84jRjmuXkI2E/GFvUDAOjKYkUGibFBG1NGcA/b6VF2wmwnrAi6\n", |
|
940 | 938 | "jWynETs9MnSIs6cxW9EBzFFiXHOYSnzGyKCFMoVQqBpJoZLq5JPrAtIhpKA1hZGElbzSdKuJNWVx\n", |
|
941 | 939 | "EzwJ1MRYGM1divyluXPZEErPHZs7ZfWVC9phDq3BAncKxAcRcA3442mwYAqAIXyxA1Cg+kDOgBwD\n", |
|
942 | 940 | "oUo3vfBu78PU2A8dqg9z4ihIH3AsD5YfxcT4BSbGAegFbcgFPFpxBqEiJ3Oe5RQ8y5HqXvib12AR\n", |
|
943 | 941 | "7IU2t7F2ay2CMGov196oZSNjJ5gFFXk6C/IhyK/RA/8AMgo5ZS8izVMgd0FsAbjxQM4gsUrbhoAQ\n", |
|
944 | 942 | "gAreo4KCR6Kno5ei16P3ouqB5JHZp2cDwQfJV/rZ7MTTiKc5CnIfRI9om/tICrkDtP6VqNNwMf5J\n", |
|
945 | 943 | "PFcgEEpuEv5GNuOPFJzGvDyYrWE+TF2XOlh4tPBMoZiF8jkAEkf3HQDZiz7sAdmLjiR1cz/IKZCT\n", |
|
946 | 944 | "6DwkUlJfSRGQk0pPST/CtDtfexXTjqSbH6JvroKM5iSaS+ilX9Tjq8w4iuoGX1ChC2Cd3Ef9QXvA\n", |
|
947 | 945 | "H2Cy1Sp01yl0132qWRBB76HP7Oi9Y9j6AsSA3XsoOniUkdTZ6AfRm1H2bnfQgZrZ4GEdo8iuu4Pe\n", |
|
948 | 946 | "06D37uZ6bzmKG0S6ETMRvxafItpoH2ZgD5cdnAouMllrUKxVag3GLXUdtTWzZ9hsM2bX1HbUWeLT\n", |
|
949 | 947 | "6g1Gf6+8tKmlxRJe0VFdE1vRHH2xquqpzulVBms880KVCgesDM0tnVZoMFxRa89X+GFTWygsVxjk\n", |
|
950 | 948 | "ucoJH/crTsNZuVlvF6t1qvpYGaL2vMVAZ1levKb45eLXimUEq9HiAva9iq8Ww7AlBhDaZhULSFOb\n", |
|
951 | 949 | "khIbCWWrL4QjvyoO2ktc9iKjw1UU9NRWlhaWGd4pNuVbnSazz+3M90QqzGV5eY/ltZuIXxopADvF\n", |
|
952 | 950 | "1RvrXfWiUl8aFv9nCFPv/4e98xBB5vEADVeR9q3KSAHoeeeYkpSSEfNEUvbVaW4yzDR/qsWXfG8a\n", |
|
953 | 951 | "2VhGPxT8xlNJuOT74sciqky9qdqvOqw6pVKxyQMsYdLCku+rPmZqWVKlKlWxgfg5Du1Q7YOmNqqi\n", |
|
954 | 952 | "0t2AtOSfiW9qSMaEP9gQ/iFhyPkmxsQy4WPG7T2cX/gEUUNOF2P5Vpg3gE+b3GNNsAUc0erZ0Ak4\n", |
|
955 | 953 | "zYrSiSKgwmK7Qg5lZ9JSgJTKhMuYcGdiBYNuGYJ5t/uQWzOQvOWecAv0x5q0VKTkDyMgz5eRzkG9\n", |
|
956 | 954 | "upVTtIagaNVm8Ed/RtpU/9jw7VyIUlYMThVVOisDleIwfKAISJWWo/2jwgWUDNDDF98jLBdUwwpE\n", |
|
957 | 955 | "0MfCZ4JsBCjJIFYDK1iKyzPmufLEYamwhJMFSlQRcmakGIJmKXK2ykNLWTX9MH0OJxAIhoyYmfDT\n", |
|
958 | 956 | "J7uBxaEPFosD0JR3gXwKYkPaGCG/DUu1sG18Con8KtQ0NSq79GBrBchdEKr8c818x4yX0JgtZq85\n", |
|
959 | 957 | "bFYNSyuoNhDkLC0UpjYIO69SgVSQdci13uU96MUa4L3sveFl3GUVen0+SBt6eQvIEZB1AKna5Tvo\n", |
|
960 | 958 | "w9m+y74bgMldhRyv5WCIr9XCrZuqHa29UHutVjWAo8NSL/70Sk4dvAc2qqu11bLX6vYj1T3lH/Vf\n", |
|
961 | 959 | "8F/z4wJkWvf6VyDT+hX/637w/ecxdK+il3rRS/up/DzIVaj9UVhDHCDzQerQUVcReXW19HNEVU72\n", |
|
962 | 960 | "khadRslxFjOyn81rESJIMfNaqJc+kKu5EDL0VlVVayQ8CfU6Ge+u1YY88kwReSsvlo1/+PNSb6G5\n", |
|
963 | 961 | "vKAqoGszLAqXN3utRkd18Xc++vJw+5MVL4WfpJjU6M9KAxX5lmJ9lVXf1FJYVldmq6txGV/6lP/q\n", |
|
964 | 962 | "XO+qL8NKzKqKi7H5JlBsayFn5uz8Fyg9rkVYUJERBsVsgAlT55YgknZJvuzagh8iheLPAYGNbznQ\n", |
|
965 | 963 | "V2t8TJAv4owIbZbQkqRDRih9wFBJ3jJNmNgQKhg0rTdtMm0z7TYdMmnoj6VpaT16ZjNIP+seQKFY\n", |
|
966 | 964 | "2aTEenprOn4bU94sBGmzKZfHQ2APyqQkMxImZSF7g0L2BgEQrlCPGTMXippWX5gFlc6GlKTgZw2o\n", |
|
967 | 965 | "2HtNDzGW0TglF4zNMZBiM2VllNAPqv+Zs6XiYfdj2pqd5l0bKrm8atkCNeQI3mgdDuyyHLRgcFtQ\n", |
|
968 | 966 | "xRyDm+YMXutVkCMg65BWuct60IoTrZetN6w4EWmCyyFUvGajWWAbtV2wXbNhUOfSKF6xKSLcPZje\n", |
|
969 | 967 | "dTYbkqVfQyZmyj4KM/w12DOWI7oW+TTSRSTVuLXZgGh3qymknhx2whvCljeAp3/i7b5xz5Rhxn/1\n", |
|
970 | 968 | "cvgrX+ngC7Y8NK54LsxXcf8knGVr0atw9mQRPuVVKAl/tjDZz2wMZAFc4fLWZJekFAKRlqsZ5+vM\n", |
|
971 | 969 | "VYKcXKAyKA3H+B+IQHZRyQUWK9I2rVIm+Q3+iRrMV1ETSdd18gd4j5DmCrgm7n2p1iTWJzEI4btG\n", |
|
972 | 970 | "Ro0pFzYnpWvlLCgHY8YOOdbElC0sB4CkhrS0CSiLh0KPwGqx4WZzF8q2M9balBzbICKuIaHLpOC8\n", |
|
973 | 971 | "Wq+TgULL2V/L+8uHqBicfI0zgPNkrIbGQgTKJj9ovAlgcMA/Qmu+WPkJ0rR2IJMoeb3yHnY+gA0H\n", |
|
974 | 972 | "qQgmkrlkU7h2sq5zy1TmQtXuUeHpYkFdbYXH4nAa1c+UeitKSmrnNltiZTNKXI7ZLk9TRZ4ohEW+\n", |
|
975 | 973 | "sJlNdX1pSWlJscNZ8LrB7DRbPY5CXdRY6LEbTWWu/K3FVQU1pZZs//4+698izs2NSUZgvfTDsHoC\n", |
|
976 | 974 | "60p/lgMoHs7dsMSsl0FfAAg9AX3lEFTnTbksKcJykcHKUoiyGALsqpMAqvJYX+YN5q3Po9iu5AHh\n", |
|
977 | 975 | "CIwJZwh7LOdhHoU1nYBb3sllQ1HU9yjs+e/AoLsPBKbd5NGCM5D2oSNlyx8ezd2NfNAH6XK6qFBB\n", |
|
978 | 976 | "L1MKaz2ionuLyryWhra2Bou3rKjdVj+rxj2r/v+y9ybgbVVn/vA9V6styZKszZYX2ZYsyUss2Yol\n", |
|
979 | 977 | "WzKxvMXOQhYSHCclk/wLZGEZyAwkAdqGYUqWzrSkLc3CAGHakm06g3yjOEthyMyQhbRT3CkJCbhN\n", |
|
980 | 978 | "uiQkYWhoSymlwf6f33uvZDsLMDPf9z3P9zxTmp+vjq7OOfe9Z3vPed/fW8D/en38r5hw+Iotieqq\n", |
|
981 | 979 | "uKXIZy9rBFdZ4xjOMpUQHPmVWMXeE4r4eiisekxSWVU1KasyuqJdLoJdfCuHpDnsTrpnuRe773c/\n", |
|
982 | 980 | "6t7o1i3EVtt/QHs7y2HguaJU0aEi1UKZyEoSirClJkeGeBOgRVcyGLFflv6W4XkDl8E6LEBihm7D\n", |
|
983 | 981 | "PAP4rEEwsxJwwgCLYsMruCfPRJtmr0OH/Dmg0G0iBv7CUU/mJgwxxfKND0MBegZAeuRBwIZi8OzL\n", |
|
984 | 982 | "1uKV8m3kUbO9EtxglWexm+KXa/ak/7vYSlmJNcXjWFNI/n/lCekf+3/uJ5PX/jqeSZhuln4KFo5f\n", |
|
985 | 983 | "AyhI9hYK1gVX5TWARYCzAKEhs2fl5C3NmVHys54oghOeKNJpiOnCqKz0TjrpbzL0GPoMywx8BL4A\n", |
|
986 | 984 | "6ayHdAYMR7h0ZEN4KY/ulM5BPD8hGckZzoNcKDKiTCCKqcw9mHKHYFcD0nO9pb9KvCIVlxJdwlNQ\n", |
|
987 | 985 | "wlcXry8e5SCvpG/S36p8HjL6JYQ2CPBX0fbnWkjoDf/bEBkFq9+OhL3+w0igEPZhOYOfht8Fm/JW\n", |
|
988 | 986 | "SGhnWB5iGoUu8DpQVO8BjIZHsyRIH6AfTNZidaNdquU/jOG6z74M7KT77cewIKIwgB9g+omVdZfB\n", |
|
989 | 987 | "3aJsBzbOTsAcfVP5duyZEa/RFuj6u6DKKjEbt0CV3QXH/dO1F3lCemK4M4ywY10Q+wcZyoQ0Qs/w\n", |
|
990 | 988 | "2ykA0TFAD86u/oirZlz1YP+jGQCXl/Q8+1LU6yjWaORmgrlRairLOtCnN9fsAC3qZJQfIzd3wAVA\n", |
|
991 | 989 | "F7hDYxxYhpFFoUDN+rC7dApBritjkTQxwN4u8mBLLjyztKOsvbgU23KhWWXtZRsndGLfrqLU2VSB\n", |
|
992 | 990 | "jbsK9lXPnHpyTy/o9HSWzQnjuqiw0zM3AOW1s64i346LtnF7cN/L6oU/Jr2wSGqFmr+Iw4AlVhYL\n", |
|
993 | 991 | "x1TYy28Z3cvvGT4rJmift441fXp8u1Y8NsW3G2VQLaNIdxNC17opjuMx/+T4diewEjoP2Av4VwAF\n", |
|
994 | 992 | "tTsIqJWD3R2vfbNW/G+FuJOJTcG0nIly14QNmilXR7mTw9tJkz3Y4aAYd8QtIe3H9sp+6HkU606K\n", |
|
995 | 993 | "0clVJvHa0HeOa0LfWf8Hoe+Y9Rqi1OFvZOIOPSYyruObhT+DY/AsdMmNZOE/lH6CbYO3/ExS+YkL\n", |
|
996 | 994 | "sV8tUyIa+JeGbWTZpfCmZl3uiGsG1pbgRdPmkbmRlq+eNOQ3apWJhyIRkbV/ob3u5pjn4bve/ZLK\n", |
|
997 | 995 | "eOV9dhAV/jzitkRHFgtXxLOCVbiA8w64pafDeUmYkOQOkY26bLLeiivYreMQuFlgZOSpkR0FDUPE\n", |
|
998 | 996 | "oWoNpQy0aj4HW3bzSraWbWLbmRzCSqe4HDxPihpgE/GlcCVaJAruFaDg5t9jCQGHrvSA/giaxmR9\n", |
|
999 | 997 | "L5Tb53PAEZizNmcT3NBzBnKO5JzMOZ+j5jfk9ObwG87T/G981Qh1cBW2T7qR33msErqh8L2OJziX\n", |
|
1000 | 998 | "mw0eD1dL8DJdKauvsFrLwp7GjqlTesR/jiy+/a5Jk5Yt/rOJwT+78PADlz5P707P5fQjktN/ZORE\n", |
|
1001 | 999 | "h0PSWcCjeXLc4ykY5MICxQ4h6QhQQaQpXILEEztE7knwEuCi4gKDS8YGtpXtYqqF6VfZaTSB+RDT\n", |
|
1002 | 1000 | "aJQnihc9H8vj3coR6AppK4Q0H6rsbrLofyhnQ87WnF1cGgOv5pzOuZijIj4Dng2e/iIkM2A8At/w\n", |
|
1003 | 1001 | "XhDGDFiOWCClt5H/BX6La5IK+ivcUXF0qR8nkS9dRyAawT/yc1WR+Eu+ynEJNUKrMEdsk7nNCipA\n", |
|
1004 | 1002 | "5Y1QpzMBjwKSGKzvB7Cp5D+sWPRJScD9TBYeSIikXkgQc4US1uhRPHQKMAhYLNJ5XLpAFQRf/lS0\n", |
|
1005 | 1003 | "m17AWhWZrUMPBK9EqsKCZfwIvRyZWS1Vy79CPKKpYOuURuDYNwuBWM/cmlmrzuQda2ZG+yQ7Vzom\n", |
|
1006 | 1004 | "oPjQM+G+gRgKJbTJdH9mfymVM0REhEi38WyhhfB763lqvXzZxRVc7LLO7EL8An5LQrb4P4LnPa/M\n", |
|
1007 | 1005 | "iHyKE5bC9nIzEt4AyL4OOYLs7aBeIT1E7YF8dg4wtJaLiAuHmFjpPnEZ1s50+LqVXEZGQ8zLJqJH\n", |
|
1008 | 1006 | "AOdpPMxy3MBJgpegkv0k1CvS67Vb+IogvdawiY836XWWzeA9XGfdjCO6Dc6tTnwX2RTBn4mbJuK7\n", |
|
1009 | 1007 | "5s3N+BTfFMctk7ZOAtX5Bu1WZLPBsPXabNY6NyGbr9Q9hZhDa5s30e8nbeI/dAWYy/Zp52af8v3p\n", |
|
1010 | 1008 | "iVy77bR5qgsKqj22zN+WIjkGXFHm73DoU2/xFIlvF338VmG1x2r1VBdm/lYmQ0VFIdxCf9n8T7mB\n", |
|
1011 | 1009 | "jx3ERUOca4v+65FIpMuwvbzPtAanpSnTIfxJmmaZxLHGrjLjzHi6mX+5mv+MxrFbmVr4F3Y/r0vP\n", |
|
1012 | 1010 | "aF2SOZny1aOlp89oL+MtnjFdRpnjaiDNInMoGFeNN8jPFsrimVJ1QiEfK16jsQJaZUjoEGYKt4t7\n", |
|
1013 | 1011 | "pFkLePnhOAfSM7fh8JAtiCsDBLkDnUGTNzMMn0PpoNCERe08SG+tkI18Njo6PCqPDtK0zIggPQG1\n", |
|
1014 | 1012 | "tRVwH2CjosAqo8SAoLaoy9Rcd4cSC02M/0JRZ68JyhhGYFbpPR9+5rP4ynw8LU7GOiOgOzRXe6pD\n", |
|
1015 | 1013 | "1TyrjbN4BrMsqU5+cydu7rR0lnXymxdYUlP5zVNx81TP1NBUlHsnyr0zMwAt4i9zUWYAauQfGkcH\n", |
|
1016 | 1014 | "oEWZAajRkmodkja2wjCIlxFAGQFLoCyAyJGD+HoCL2YCipngmRCawJNNlOwYTLVaEIyJZ9XNf9mN\n", |
|
1017 | 1015 | "X3Zbusu6+S087VY+4fOxMHUz//nN+PnNnptDN8uOV0sg9PEj1lVDlZSDoXs1Xtjy6w5UU/BCKYIf\n", |
|
1018 | 1016 | "TunSiMMrXme0moK57pOHLENmyJqi0qwY2K09qD3OG+zA8/q9+sPwuXveuNd42MgvducdzDuehwv/\n", |
|
1019 | 1017 | "Qf9xP74K7g0eDuKidm/t4Vp8VXew7ngdLiYfnHx8Mr7q2dtzuAcX0/dOPzwdX804OOP4DBWNUMSc\n", |
|
1020 | 1018 | "mjkOumr00XzCd5/0uy9i1GILmqurm/EvWlDVVFbWVFWQ+Tt8z42/+u4Nv5JHsCPV8Xg1/pU1YaRr\n", |
|
1021 | 1019 | "KvM0YbBq8twgnW24wReKj21YnC7W8fFjuqTC+DGi+Ehe14y8lYYJAd597yn3qYcUN1vi+JetJmX2\n", |
|
1022 | 1020 | "fJk5vzHC7v75z1v4/9nNwJ8LCmciyo3QGLJEMiBSGxH5YzlKfrEGMtek5TCYFA2wy5FareQpa+Dl\n", |
|
1023 | 1021 | "kw/USHbRkRRld1kNsb/o5AMb/Mo4BMwb5INpuaPcyuvjUOpG/rxUs5/f08KWPv10y+bNVLcg18uK\n", |
|
1024 | 1022 | "FL1M8+nxLJI41yWVDPEsKAqSopc5QjcIbpH5kAlu8ZmCWRB19oAc0GIs9UMmjgXiDN0onIUcYiIT\n", |
|
1025 | 1023 | "zgJnpWKW8GEKAlookSyaoXwpQSwQtSLd7JviE1dcG4zCek0wisb/fjCKj19jf3698OL8XYRGPmID\n", |
|
1026 | 1024 | "4iBvnxPYc/IM99zoRCuHJzPI5G9PaLdpNTLt/sDL2te0Z/gYorDuG0MDZ4yXjSN8DEmbjR6juKLf\n", |
|
1027 | 1025 | "pKbVvJ+PjdiHMfs9fp4KyxQ/toGlVmzwnCm+jA2eJ4q38T/9Raor0n2hzNhOZB/X54lDcylgV6Si\n", |
|
1028 | 1026 | "cjKVKyItClQ3GW4bInMkCsdXYaEwH1Q379hGzyZwLCE9hXOHO7EttQlgB/PNEfdJ93k3NKal7lXu\n", |
|
1029 | 1027 | "de7Nbt48tsOw8XEoxEuyLPAna87XQCcgthsHeBO0AKK5OUzRHlDw24BlKGw94CHAFpx0rC/cgs3C\n", |
|
1030 | 1028 | "ZZhBTyF23Qb3VpBGPoyEHZgzl1Wvrl4PfvchFHeq5gIvrnIcOx5vGmqiJ9DqAlmNXO1gtZk1RUFP\n", |
|
1031 | 1029 | "oa/aW9A2MdKRM03rbewMBCdHSgp81b6CLJfenKIJAV9VXWkk2VKfE5hU43TVtvPBrKYi0OBD+6gd\n", |
|
1032 | 1030 | "sbA9xLE3gQ2TPTeZ/KUvCyNYfZuxNwV6dn6NOOpZhnZyB5UsWi5TmXJvTFtJ5mQ4cNUZDtwxzeW9\n", |
|
1033 | 1031 | "DLP1mMYSRmN5tHgjGoscP4Eay8wQux45H7WcseR8snlmptEYy0cbjQNnWw4i6cdL25eNPEhBB4mw\n", |
|
1034 | 1032 | "cjNe2uN4aUtcK2FOt2nMCwThp/QIgF7lesB+wFa81Ffdp/FSwakkXUIqfD2knWhOu3FsuwsGvHjR\n", |
|
1035 | 1033 | "2INH0yJLlw2AS/Qxs1soXaTtmQLU1o3ankI7I6LSTajeOjTl11HCYcASwFrAAOA8YPP48unYeDus\n", |
|
1036 | 1034 | "a17PNuztaGmrqtehOm8j4QSK3g7A0Die4NCRp1HmZld2pFI3Doy2PVZwo8Y3yoY4p7iWt75QybWt\n", |
|
1037 | 1035 | "r75SHp+e4auhuxRf41tT6pC0EcYVZ9XvwbjifrWsCcvHbUNyOF716JHWYqjzZ3MyjYSchIzyAlGt\n", |
|
1038 | 1036 | "xDCXp9IA/8fqWlq+3tIivvLOO+/IZS8aeYDtpFiCOuGv5WiC14sZSCzEcEwZSGkOaQY1/Es1RUnv\n", |
|
1039 | 1037 | "1/E2+lxONpZglrGYQpUjCGEP68NKb1x0Qv6NpknTo+lDmPEPEX1PrynQBDWqFYhBiH/f7uiYfQfF\n", |
|
1040 | 1038 | "IkRNeT25jHYqMtrCnzKNo0VoIurLathYDFHUdmISkV5QgbBKRQHbidmNJvMXdDxVy2ubhMSeu5HE\n", |
|
1041 | 1039 | "tIrEeBVVMOfsU6GKcK3Xq7DDQJXXwcKzT4dvEIBPryvQBXWqFSyi42LWedmdSu0zgh5f/+e4qAZe\n", |
|
1042 | 1040 | "Fl8Tz4iqhf9tgdNLp9c/hnpOPkv9n74E21UvgZ1W2gsTmthp4Yf0HLeDgRQRVfhAda3saRMzDbd2\n", |
|
1043 | 1041 | "6KbkSS0JmsyxDJnWoK7i0CeK2saFuUGW47iyV/KnJb/1NCwWwMYqXsYq5gXxZcUh/3pxL1ElOfgl\n", |
|
1044 | 1042 | "akL+oteI7hMlBrk8IsuDZDHygPBD6js9qM/LIrth0TPHRdu8cQkupYS/xfPewZ/3OXreEGQNV3ox\n", |
|
1045 | 1043 | "OwZIT1Dvzzq4ZkVKbma8r99B/Rz1nMbhVr4WdQnbU65Qv1N2b3RZYMx/CPYcZzC4m2E8AM8e6dHC\n", |
|
1046 | 1044 | "cRSq1/U/pIM1nKVpDXQWdh5T4U+0tF7utzCZvxBbkk1opR9gFNeCZJqMK5vpow2mxJNxT6OyIbsw\n", |
|
1047 | 1045 | "3ZjfxZeTiteeQn5HWztW70wVaxN17sp6T7HDZCr0R33WdtbuSUbm2bzFVm2bpmTCxILhDwX1uLil\n", |
|
1048 | 1046 | "E4V2VSNFLpUDlsqRSrNRTJUApv+1yKXtQ+nF7fcjBoGlnd+WaucVD7cn23kTf49fp9qG5LBDwUFE\n", |
|
1049 | 1047 | "Gq8bkmbV8U/NPLWZ/61D6PPUpJA0axJbAa19BLENZrYuasX6opWntfC0Fn7nJEvqpiEpBnPXXtht\n", |
|
1050 | 1048 | "ngWEYTG8uAM/6VzUCUaETixPOl/ozOz+/A/CnBZiGzS9JvpElDc0rwVPchYWocloG9YTyRCM5qKW\n", |
|
1051 | 1049 | "VIT/EMEphYglUhZR8TVhs7yf2jKIIEqTiL4GvvE3DG6qUTlU8ib/1cFNodcrFvTXi2yaq3PfMLIp\n", |
|
1052 | 1050 | "+IPSOfpCHA40URDTa4Ob3iCuaRpxTUUloKnG6rg2oClI7saHMU3H8ruh/NwwkOl5QB/Oby+SyxDO\n", |
|
1053 | 1051 | "8jpgntsIOAfoBdyKXa5zgCigG9AFQrlzgCigN4HFEeSXYbuTHSmkGB68RzFl5rqWdcqo74QShhT1\n", |
|
1054 | 1052 | "oTCk52JKsenupnlNXHxN8Z54X5w/zgUU2YSCLgCmJD5DQNHsl3zOozWTDgYoDu+nhxJlwanO6nKb\n", |
|
1055 | 1053 | "tdhrXdjy7Iyp7eEvtK28ueVTA4guUeUVu51Feepooi0e1fzzgQM0txaINcIp8SJ4L9gjktGJ9bvs\n", |
|
1056 | 1054 | "BUu80ljgbuQrSJzGa8EZZg0V0C6AtAjqTAjkcJetIzhUNON6m/UFfg1jC7g0pVuLZsKfJFnEe6Zq\n", |
|
1057 | 1055 | "CLYaORRSj85fQKIj9eLUZX6GlCppiuV1583LW5q3Km9dnnYh/2zuNs8zLzWvMq8z43OTrcfWZ1tm\n", |
|
1058 | 1056 | "W21bb6PP9h47ztpX29fb6XNBT0FfwbKC1QXrC+hzIbiSlxXC+oLyK+kumVeytGRVyboSfI6WTi7t\n", |
|
1059 | 1057 | "LV1SivBeWt5K6LSoj2qGk6F5qNk8qllTXk9eX96yvNV566lmTeYec595mXm1ef11axYr7C6cV7i0\n", |
|
1060 | 1058 | "cFXhuuuWjLCo80qXlq4qXcdLtn3CblbaW1joxT+fuchrs1cUmc1FFXabt8gsfqWwoqIQ/+xed16e\n", |
|
1061 | 1059 | "22u3ewvN5kIvrTfKR95nf8PnrnqxWzIjIix5KyEYLLmwgEpWr+YLIjNFh5XN9aRFINQ2W/rLuHJl\n", |
|
1062 | 1060 | "tqTqB1P1ISkJy5BWmHediVCQ8ch9kTWRJyJqZdgkr4/M9EYhJMhUpM6ueIHBPg2H6jhXNciphpBU\n", |
|
1063 | 1061 | "YK9THCoRzkTE/NBfJF7BfpFvSHrfJx/r+LEN+n3olEPCf0KPBI9X0vAQkw/6DjCNfLKX/gF7i8GE\n", |
|
1064 | 1062 | "1bQOWy0P5j2ex/8M5B3hf6RfocmewPi0z3oUrRXBFtOnnBeg7VPIhp8U/BIhG45kwtZK57L60UnA\n", |
|
1065 | 1063 | "G3BM2AnoqcCRIa4uUlzZQA9iBFzCAVYTzCNexy7U24BGuKycphhw4I7hQ+Q+TJCrAafoCvXewnYi\n", |
|
1066 | 1064 | "2vgxdopd4EsfaQNWKAcAYApL42g2+1jSqjw8Q95RPNSr2ILfn9X0aD+D/DUvEbjGWDjSE1CoOFR5\n", |
|
1067 | 1065 | "a8UuOKRMwYO8OfoMaRgXw+kKT3EOD3AScAKxISrrG+vFFSwT+NgJw45rSKj9gUAmZo/TxZLmBp+V\n", |
|
1068 | 1066 | "Ly/q6jrq2zyR9orowvJm+03V9qDHNrEyaawKFJfUTyqvn+tid5ZU6K1uW3mpwWLoaPDHvJaqhkCZ\n", |
|
1069 | 1067 | "P8dWavd6csx86JpQ7otWWP11sPegdk1+AP9GvD7zFgqCXpDek900RWHSyIPsP8RBwS7MVXkkfye8\n", |
|
1070 | 1068 | "pDp5G+/kDZC397OyaXt/Hr/OUcHGULLTH2wmzB1MzQ3RJmOnJTV9MDU9lH5i+rbpIrlPSVWdfuW+\n", |
|
1071 | 1069 | "2sFUbSj9aO3GWhEZpyYOpiaG+hv572ot/TfxW7vpVukRxFd6B7ChGyvDenlLcjbvI7MRGHUbHJqS\n", |
|
1072 | 1070 | "9bPlJUJ/DrsiVcyul23XpTX83fTb4WUsJzlCqdnkMCVVJclot1H+YWMoVW/pb+Lp3RXEKroOBT7Q\n", |
|
1073 | 1071 | "LXcgcofaTFyfmO/ID35n1lP7EjYyDsIg+yAmvFdghQSzJGkTYB1gB+Aoeedga2AfIIo5cQlgAABi\n", |
|
1074 | 1072 | "ivS64Gb46dA2AbZJRXlzYOD5ur11h+v4gnFLZCfOOk9FLuDPgcirCMW9C4ukJqwDd7bvx8JwPoJT\n", |
|
1075 | 1073 | "3YUT3j9N5rAcJ94HAKdm4AqwG3B8Bjx+Zh6YyX9zeiZP2DULTXYOKgvQz+XNOzgXK+WlEMG3III7\n", |
|
1076 | 1074 | "8PTk0v8t/ahBzEEIYT+EsB3PehJmWevKN8Ms6ygJBA9/hMNA1DfZ1+tDWEVfRgD7AFsyZvbSBsDz\n", |
|
1077 | 1075 | "kMFAzRGKLE3RrEFXcgEj6G6EIT8eeRPP/ndI+D7gTkiBREGPPxXy2N1+EPJIIGEp5PEB5LEMorgI\n", |
|
1078 | 1076 | "ODgVLhQzTs7gwtwxY98MGJRBDgOAHYDtkMg5COMI4A2ACmKxAyo52OCJUyq6MiYLgVidalwX1+qu\n", |
|
1079 | 1077 | "39FlY4/R7v7zkgkOj8/SbnI7TNaiCmvzFo21yOfyVrv0oYo/r46FA36Pp7HT13F3Qbt1SrW9qsLh\n", |
|
1080 | 1078 | "L9sQiCQm5BYVWErCrd6OBWb2VWOwzOFx5evKNPmuYrOz3G3Tuw/lOm0mZ2mpvrLK2uRsm1iXdLib\n", |
|
1081 | 1079 | "aqpvqrI1JcpCwdyCQImnytJhaw03JO06W3GgKJAI2mMBrG/auJ55guuC4GB7ERxsijGOHLjENbpz\n", |
|
1082 | 1080 | "/YJW3rO+rB3RGhbK/HCfKZoJDkhMXHM1HTIN8mVxvxEEN5Z+M9dcX8CEowQKuaxwtfExIC80ntWB\n", |
|
1083 | 1081 | "r4zyLBQjBNqtqcnUY+ozQbvFcltvKjAFTVx/HkfTFoscz+ykTYZS/R1lx+zjF5W9hiiHN8n/aV9G\n", |
|
1084 | 1082 | "3yclu5+pwFQvxTH9vAYAAYq0FYBIVZn9E67kqkPpVvVMdUY1IqKrqx2iyK6KgckCIw2ZR+oxX0eJ\n", |
|
1085 | 1083 | "fnPUZInP0WBdlLRYXkG54V+Ka0VZw8GXGaJ66Q/QY/QqtoIxL8hb2JvDv5zNvMM72HfFxz7+kvhY\n", |
|
1086 | 1084 | "+2gMTYpTXct+IJUEsG4dwwCRhFfho4DnruaCIBqIN2H4SNaP20cJIWaho24cRwhBHBCZhyZ2CDot\n", |
|
1087 | 1085 | "GscGgWhsChuEndggpPPI+BW7PPz2UvQjsjDKMi0QycIxABGQn8J8/SGgAAvuHMAHhZmVx2GYLR+G\n", |
|
1088 | 1086 | "9+x5wBuAw9CO3gD8AYDY59IpjEgfAo4DSG06DtiPEelVwMUsUzi2lgderTpddbEKZMvVfKFxtPaN\n", |
|
1089 | 1087 | "WhxZ3Iq69mVDXRzNslWczPjppLVOJ9gqfl+oLCvSpzwXcHx1CpUhb3DyAP8I1TqdDb5+AZU5TUNm\n", |
|
1090 | 1088 | "hp5C3mLeh33uN6rerhKvCbsec40NeCFH/rNFVn8mJojXFAKICoUQ4jpEECzG+4pm5NfsXvGkoBL+\n", |
|
1091 | 1089 | "VfHPuIKGbBy1mhJEUmCkK9Cvjapirn5fvfs1jhqNJQvBOtorLBFWCmuFTcJ2YUA4IpwUzgtG3vQz\n", |
|
1092 | 1090 | "rKS9oBI0gZ62ly1h6C1aPpKzfTBbewPdZQu2AYJik9gjqviaF9HE5XN93mWoXcEoI92tmscrlN6p\n", |
|
1093 | 1091 | "2q+SjX5a4yzUnG8TT9jJPhYd5p9Ufyn62WOKT/sZ4QWhWXoBFtqHALPA+oKABWnEIUQjoO8WGaDe\n", |
|
1094 | 1092 | "GUZg274ICa0G2XqWCXN5nlV8jeVhd+1hav1ofKKz2ahEENhZTLKz9Iv14kIlQohMqJiNE2Ifkhaj\n", |
|
1095 | 1093 | "CyTt8s9KFfdLYk8yjt09g0ZRqgYPRao0JIceIoUCNhqMWCNKiVTJYVUrayWrpb9AJr5ZD7s14jm9\n", |
|
1096 | 1094 | "BKqsw7YT8HA5j1n/DxTJBVU4AnDBYe0Cri5iOfAWYCfa/YNo5ofdJ3Bg83t0Sw1ObZwIjTHPvdQN\n", |
|
1097 | 1095 | "ma1DKedRyjrAryhnwO8BGhwyHrGBidc+aD9r593OhsIoisz5bDlbAQc4DPS5l7lXu/ltFISjgJfE\n", |
|
1098 | 1096 | "vNaIo7wxIscwkefdMUFMdu/8ePjWJYsX28O3TKqdXRqyN3nroiX6nWzm8LstLczWMi/c2xYoLou4\n", |
|
1099 | 1097 | "iv3NycLZFGeKj6OTxD7BLZzewzQ2dc1ogKnMGx0TZwqmmJJFIJNLaHDb0Cjew9MJNvzAthhyPaR4\n", |
|
1100 | 1098 | "DtkpIIqTXk/hoLQmE8xcID+gzG5bRm0kJhFMKYVyhBOTpV8nM2XZBrG55hykyEeWPgQNXg3VZzlg\n", |
|
1101 | 1099 | "A2C+ha/yBqK5k3N7wdONm5ZZ+IITbLciAlDRqIKwvDSGkPwiXGLxdbn5hWarz6yqnGirqnDefnv7\n", |
|
1102 | 1100 | "OrZl+D/d5fm6XP1N1tzicIAFWr78ZdlefKRYTIjvk13Ccq7zpl+oe7kO3HBD1zUaHzUVh13CGH+8\n", |
|
1103 | 1101 | "64a1IbsE/WeyF1fMES7VsDH24LJt9hTALsB27Pptxq6fbBMubcKIvoM2u7JRHaZmQzvsgj68v+BY\n", |
|
1104 | 1102 | "AXTm0iNwoSJKnyMYwrHiTx+rPoWDv4MZw2/pVTpz3IyZu4m8gshYklyDUPZTKHuLfiesIDabdkB5\n", |
|
1105 | 1103 | "3YGSyHx8B4qDu55ifC4bO+yvPoYiTlcruZMB/LUG5tZPNDB313fVZAzMneHQBPunGD+I9cMbSgNO\n", |
|
1106 | 1104 | "/TgL8x+hb/h533ibj3Ex8XapLKiqgX80he3p1/Ilxn0Kw8dC4uuAZxz5IWH9J8WCZRiDYiHJHaOr\n", |
|
1107 | 1105 | "oKW/ii+syiz99WplaWHh79iSGeHIeRojHLNUyvZ6KYuFtEGjnGAMga8xyhNyo3zQoKiCbkY8GFWV\n", |
|
1108 | 1106 | "YOVJVYWkxXweRcCsWvkM4QQcdrXYy3odqg8ZbDuxofU2rh5E34VXU3pr3i5sJ2hwxrAUb8fBO/PA\n", |
|
1109 | 1107 | "EttK21qbSj5sSC+xr8Re/0+gI96KnQWdy+XiSwAKV+XikD5Rcq6Ev+rekiWgwDiBl7oSgJAL0o+z\n", |
|
1110 | 1108 | "jBjnAVrsPCDqgrSK4i+gka0CXMDh/kVspbwFOAatSQ+Sx1dh6XMMmtIxMDh8OBFt7xQeUI8HfAMP\n", |
|
1111 | 1109 | "eAGPdRrgxlOuxgNuwANuztuBB1ySOTpJr7Ktw0BVgCF5Nfxh9K4CPM18PN4QoADPlQMYgp31CSwl\n", |
|
1112 | 1110 | "5wH6UOHVgOWA04AcPE4f6r8asBxwkQCPcyqQeaYjeBwdHucoHuc4Hof4Oz7iYItkwkmM93p2jYae\n", |
|
1113 | 1111 | "GBvty/vDSk9zdWHXpAmdztay29uqpzaV28prC1SlDT67b9ItdTMeKJme350sjVa5ShvavB72ZJ6n\n", |
|
1114 | 1112 | "wdvcGvSXNccKQl21JRMR0VhbHm4pr58+sahzmitSb6+c6AnGKszkD107clblVPyhk0KnyphqC0l6\n", |
|
1115 | 1113 | "EABW1fPekPNprtCgLh4kJ0bM9Gqa77VDSB7jD01ESRZsTKaq5H3IikH47duG5InlBWyQtML0uz7j\n", |
|
1116 | 1114 | "EFbIC8LKM1lfJW+bINg3V2eT9JHf1jCEfOI8hzhIEtpSbXyUbsPhk3QZyvRrgMWAJM6cOobwZeeQ\n", |
|
1117 | 1115 | "tGZyZpzOhtsa6/t2td80+a0lyW9a/1n9pkvoUOs+NIQzAEsJ7YFaQgMzLYss92HSMls8Fq5WlhBD\n", |
|
1118 | 1116 | "KihRpcK6EgrmgkEBp16tCN5baWlF+a9iPd0g59IQwglZ49CAudHTGGpUUSbtg6l2WnB1DqY6yail\n", |
|
1119 | 1117 | "sYx378llvWVLynj39iPm8FyEQT1HvHIAJ0VFBZxEu+0F28DbuOoGucB56oY4fDkNuAQ4hvO1Juxf\n", |
|
1120 | 1118 | "rAbsByxvw+DStqsNPtttp9sutsGPog3O3ZD9euxx7G8/hj2O5bje2r6rHbuQ7ReVbaAVUi9O7NZ2\n", |
|
1121 | 1119 | "kHN3x5GOkx3nO+Dc3YHq4atVgB10Uyfd1Hmk82Tn+U7chLO97s55OOfb0YnhAk+a7i6bB8+7GK5P\n", |
|
1122 | 1120 | "eS/A0K4ADzqfJIBnpEeeh0c+GRz7yANHmk42nW9SyQ873kO8UgkJM7bvakcjll/VdW1wJH921JH8\n", |
|
1123 | 1121 | "4/6CqkSVp6TSHnInq4vClY6Qt67eVdVYGplmixhrq80lBeacgurykuh4X/P7KyoLKmxF5f4Sc3GV\n", |
|
1124 | 1122 | "29toEPXNgZI6j6VqQmlpmdFWaDIWuczDJaO+6BWsiHXzOa2e3Su54VpyFotLC9ayKcVSmy+3bKGM\n", |
|
1125 | 1123 | "Sbf0Aga41grZBYRWfRlTbqm+gjjj6kOSs56uKkAugiy4Mg2eqzTOCUT55OCq6GYe3gmwvjgDYHke\n", |
|
1126 | 1124 | "edKTY9GsGJDDAKjg9gPzkzIcxeTKN+ViIkyFh2R3PCcLUyfAotnroU7oDcEd2s87gd/jD/llX+hK\n", |
|
1127 | 1125 | "ayNOJWW6GpXC6HEyw+OR1tlddj78v42hfh4G/RMYX96G0noK49OlKrSfydjOCVhjsCA8RbOGvQA/\n", |
|
1128 | 1126 | "+yPyIcIBygBRmdMnqs6BdpFIil6to9H9v9BAHrtxe7BPHNsexMLyiiLvp7YAmVv3pJhkbvF7Qolw\n", |
|
1129 | 1127 | "STILfAQ3w6lHpuETvpCy42gPjzILuph76Npjb3s2bM6A2eAxhAw8TaPElMWXJXx8C9EulmySsgxG\n", |
|
1130 | 1128 | "KQ+RU0yTukfdp16mVisu529TSBUcAs/LX5q/Kl/D74nZum3zbEttapDZ4qR2ngrM7PSVuls9T70U\n", |
|
1131 | 1129 | "Pz+a+fkAwnufxwH26nwU0Zw/JX9+/vJ8NYpTDuPUC1XEQEpuqNFYRA4T6Kf3UK0yOT2u/Mr8/Aqz\n", |
|
1132 | 1130 | "y6Gp4R/LnPyjtcLCP4pJm78kPy9Hb/bY7JUl+WZ9Tp7HJusBLKiCbUme4GTbUvkhSa0BFakSbZer\n", |
|
1133 | 1131 | "SSFsgW0kWwjF8oyUqkfhm6iBFizNhNXGNkBZDtemFF9/RasyykTnTJknFaJwaQ2WLwiqKc0CMXH+\n", |
|
1134 | 1132 | "KI+jmeLGclU6hNe3puAa9g/rEGzDNYOw53aQC52YC0164Lj4pngJJgbwdEo7xEp4D2qV77Rvai/B\n", |
|
1135 | 1133 | "ccWhrdTy5IcheKP8Xdw41bjAqFqRThinwQ/uTzAWMBiLjDU8UXoYxgLfMcokEQ6q2Xt2mDzYLfYy\n", |
|
1136 | 1134 | "O280FrKuMjyv2qs6rDqhOoeoVRQ2bx2gFxPoETW4bDFhoAm+qjmtuajBq0YUEdkfKmmQPRVQS/77\n", |
|
1137 | 1135 | "+Ub0UURvTb9u/BUqhRRYSqu8FPgzYiMmD0QALVc91yL+TeBvxJaFf/VXCz7+zeMt69kUFmQLhrfT\n", |
|
1138 | 1136 | "v6eHX2Et0eGn2JIo/Ex55/ktHzPL2FelQnAvLabVR8bcBwqrXk27ptbBlDVE72TAbPVYQ1bVin4L\n", |
|
1139 | 1137 | "baj2e1RXpD956G6ZNEMYPSy9egMJ4WtBlPQ+0X7aidHjACTzvoqsaPpNXA+wUDpfOUil8h25sLt5\n", |
|
1140 | 1138 | "GEvu7wOIAeMpAALLY95HjARpOdE2QIqIKsVf6ztI6KOlMxbMR7O7JG/mX4IdxDKswuiUaBVG2T8A\n", |
|
1141 | 1139 | "KkG8shbrZOKOjOLjKlytxADYDObIquLmYvipH0b25wDbAUsBy1DafMBFApT7JuA4CgfttrQEBb5B\n", |
|
1142 | 1140 | "myfOTNEoK73KtQ5GtmB1KS9vZPKxxTVMQeXst3yadFvK3BaHv6E4Ot0w3fyXt9TcnPAWBiNFZ9gD\n", |
|
1143 | 1141 | "c5jH4gvWFpTUlVlbIvqZC1x1XXVVnS1R90+VebKc5slSdpfMt/UCOU7iGc+Ca+ezUW7NwuzWiv3Q\n", |
|
1144 | 1142 | "+8oynZJCQSu2htdjx3o+G7QzhsCtMkUWefdKGqT+SpQ7/41JsTJEiOmt6l0wg72E934RGtIlizLj\n", |
|
1145 | 1143 | "SYux4WSH5//vcaXB1eTMTlQaNFbiGBorhRAKnF2SX2Hv4jXJ8kPtHM8PVQijjrdR1nlo/KP0WR/g\n", |
|
1146 | 1144 | "isJGUlkghkrm6BwuR8ARc6hXsE+gfmLdN+Z7YuU3InmSY5lwPR6c7x7hB1KRCe60RUR+2++WObhf\n", |
|
1147 | 1145 | "GMPBncLLGgSMQG/dWD5u5ZLZrMkyKY3ttZKK2JOkl7An+wPVW4jhcUlFIVz67SIOhbj+gsXI1NwF\n", |
|
1148 | 1146 | "ueKK9FTDAgMX8iraFIHxjOIPsg7tvw9dqo+vKYQ02PXQArBlsip/HW7B9km53y9zuvsp3IuybS6z\n", |
|
1149 | 1147 | "vbOnxhBsG0vqKxWK7SzBNqsa/jjQUuUgiu3hb9ri7pERWU50rn5C2ScGH3Je+v6yR7FkTpYxiqtz\n", |
|
1150 | 1148 | "zX2fo/sK0ovK7uP3Ddzve9S30YfgX4j6oHCdyr85mP3NHfSboPQCF/XAa2Vnyi5DFyHquRdgbGJu\n", |
|
1151 | 1149 | "4DrKaw1nGi43qMbnMVruGspDJy2qyHA6IC7zX7P3R/ZynbUI7v2aEE3Jg5h2GbaWQ2Tj6Sh3lLP3\n", |
|
1152 | 1150 | "h43TGmgPlMPrvH3omGaPoGbqGmXXPweNHCqt7EOHNj8gx43jwzosU9WMepxAi1S42w/IUfl4ZyS/\n", |
|
1153 | 1151 | "ci3gvYzt9Gs4VwkD7sfETyT6tA54AhDCxxSuLDkZ29pxXgvZZqYWiGQf8cmko7B2364egDn3CfU5\n", |
|
1154 | 1152 | "tagEXaStUqEPvPqyu7NqxWjEsz/A6gQRonkjRHQz/kenduEPFlniinKvKmLj/zHn1H+e+S3xW9PY\n", |
|
1155 | 1153 | "68Mr2VcERVbiK1xWZvbkHr7s4bJS0SLSPCTdj8F7FlwQzprBusAfmeVRVbdj9UMcApsBJwC/Umzx\n", |
|
1156 | 1154 | "+WJIoyZjhjcxdLwD0+etml0wfV6tWa/BuQFXzCG1RZnYjDDjRqcCAbNBRWulPAs8RGT+7EF0KMzB\n", |
|
1157 | 1155 | "0hOKodpC6WVAK0zWnsOVBVdy4KxrKPUz+9ASM9G0+jqkNZ8tx1b4g7A3lqPW8Nb6CyaTWKsGJY18\n", |
|
1158 | 1156 | "73fxCA/iEeZrloOPZS1tvAEoZNEvKMgMMVvzNZhRIHagJViyDBn/k2LN43qisdMo09lSeIJ5ZJIG\n", |
|
1159 | 1157 | "EhcKOhiEGIib8BQmzzewiRLAhkSAi95mi8j/qWjVo7rtHvGLnV8U75nx5NQviF+Y+iR/k19mX6B/\n", |
|
1160 | 1158 | "tezR4Uf5m2TUcX7BrwziT2UPHqxf008I22BtdQbL2FmCTLjAV7J78fLuA/wQQOGeLHAoFoeSprCY\n", |
|
1161 | 1159 | "FGeJi0XEctKuSJoR0ek5MRPPScfnTkz/r+FZZsH15zktnH9UY8M7aIbS0Db4wLgAMYkOao6jDaiH\n", |
|
1162 | 1160 | "MiSdK5KG0VBgmoWye2T6rO49GHQKENAcwJtYrCZ1oDrMBIJTLxxAyK/FOkTCGUqaERQHca3kkDm6\n", |
|
1163 | 1161 | "hUlTq17mIkPAHO0KJRaO1JyjCFx2rpRm4rAMSpBk5lcDLxheNrxmUC3McG8tlG7DsdkJwzkDkX4k\n", |
|
1164 | 1162 | "TRtzn8tN5crBQ7V8wpuVuzj3/txHER8SjkeSBTy6IcATeJm0LYZYQRnncATMGHPcmGmoFC0IDTUn\n", |
|
1165 | 1163 | "FwFUpd9j8IgCenIQQybnIiKJxVB7J6ALX6lxpRLB8SzHlqoCgCw5jbU473URVQesi+VQHrIpgKRV\n", |
|
1166 | 1164 | "5ZDujWM2tEsX2mUfbPJOCRfQSpqIjQgNwo8GgUhaA7IGp5KDmkpVcBt4A68f/EhSAQAOIFIVXteU\n", |
|
1167 | 1165 | "bISOPjTvD2HP3pPTByISP8Q9GfAHyPzDXCxHTqLsVcI6lP02WigqI92KZ6HYCyexwF2lXQc+JkhD\n", |
|
1168 | 1166 | "WpCDKJsRVywCS1ud9192L3jsC7d855UFz2ye+9GbL7zw5kf//u8Y3ywjFnaC94V8MYklHW/wa9Dn\n", |
|
1169 | 1167 | "t7EX2Mvo84vwjPdm2UT4OEgDXNZ9u4/iZ+JqX9bD+wTgV4LiWGO2IEyUtAUrAzPGv/QTOdvwpkZo\n", |
|
1170 | 1168 | "8Jcz7IMT1y4K4AP4KBtio4micljkEzmu/1EM8UuAKwAjBrZ1GWNHaRaH/nw+EDdhb/81rL7uA0Ab\n", |
|
1171 | 1169 | "G7MazbQoohREKDpBm49aoM7S3vHPcSfgAcA3BHkhynVKraXfKF6RT+V+byFtY2C/cEw4hdC41Dam\n", |
|
1172 | 1170 | "4BcXs27tH2JWpfmVGqEOAFd0ya7mTXev+jAmtL2aw5gGTmrOYyh1ogF9iCPWXbCBbLL04CCQgo9c\n", |
|
1173 | 1171 | "yJ4GHgCcBvwRkANpLcBVDwRDUsjJh0XYL1CV1wGHAT2AQpwknNJkFstFxO6VJwudKy2AUwA9cp2S\n", |
|
1174 | 1172 | "LWRB9jUdB3wfANrYGB+FZWrnGG0+xFSRD56YdcnRdpPZY9Y5SrxBc8WhObPZX38sRZOiJmmoDS5g\n", |
|
1175 | 1173 | "b/J1DrVBWuf8TI6x+BBWOa02WuVkvz+Y/f4O/v1UPizaXra9Zjtju2zj2jDuTntsIRvvQUmoURww\n", |
|
1176 | 1174 | "dFa+XPla5ZnKy5W4B5RynspQJe6pZATyQoqNDPN5vk58RShglj2W0Vi+g3K0JOg+96Evi/K4zVMK\n", |
|
1177 | 1175 | "hmgelCknFVerxTQdk8gEixJ7IndI5gtczKE/h99kyKWgEltxUINIxOJCOURFyjQo5VlylZ/ZlOAP\n", |
|
1178 | 1176 | "Y8KhG6+2N7baKa6ZNYRFvVFnV87NTEMgejDCN13SU2r6cf23cCQKPWXgsP6E/pxetTD9Hf0emCno\n", |
|
1179 | 1177 | "yI/eSsTDdOYs7aMh5wRGp/McYo0Bb2NEhe0EFcJMZPzZG3+re/oL/37rv/3brT985Gndd77T850z\n", |
|
1180 | 1178 | "NxujrHf4e2zu8O6o8eborl0wyxJcHL7Jx5gcdk4SsHV0H5rbZQB8nSQPb3jyglX6BgYZiqb4AOBO\n", |
|
1181 | 1179 | "rEVgLSIq9lSIZ5u2Mx+WchHWwf9ItyDp71k/bIozgXIhO5nsAu9uUMoFRV2Rtobr/+kW7XRsAyxE\n", |
|
1182 | 1180 | "0j9p/5mPmAOyHRzvus/gHd8D+FvAIxhVp2jnY1QFtRwqyVczulAaUxxoTPBm4eojhQGHAPcDzmDo\n", |
|
1183 | 1181 | "fgJwnyEz9IyLbpt14NbLx/78DX4HY/yXhScxxr8P32G1YBd8fCUrD0m9gJWAc4BXAD8B3I57I0KH\n", |
|
1184 | 1182 | "MAccoypLv8jz4++eokj+ADCELaUWzXTNbRrVijQimfNh5h3Nn/ifAYOmSFMDptWHcOcUjbx1gkUg\n", |
|
1185 | 1183 | "8XDBso0vtSBjZQVdoA1CjD3aPojxdJZx75IWrcalgSUbVzcayZhtw/CvWTFffuUPX2F3sO8Ob2kJ\n", |
|
1186 | 1184 | "s2UtvE9Tm6A+/4txNs25ik2zf+R9UUuxjwJsZcobklq9vP9o1FfgasQX33zeQMx3c9I8y7zYfL/5\n", |
|
1187 | 1185 | "UbN2ITko9RdmDpzHbTVlQrVQUBN2heKZyKfG7ytPSZsQimXeOvI9QgdYB8BKIx3NmYxZ6yO81B4s\n", |
|
1188 | 1186 | "Y5oBGwAfAXqydmMfkd8aBqGPyGsaOwwgy+ZS0zgdTv5nu3MAJEaaYkcxPhUPgM+RfG+W4MxVi/AA\n", |
|
1189 | 1187 | "fdhLyQE/wq6yA2AozC1zl/G7d/kPgMGxEKpjLgKK9AWWwZg9J1CIuCKI7rWQIlpDi6MIYLK/nBRF\n", |
|
1190 | 1188 | "LbuzVV0P/brXsQQE1X0oehmKno+QPr2BJTxHNsYIgWxlx5mlTRKZM95RkZNT0RHP/J3+ZxPz8yf+\n", |
|
1191 | 1189 | "2XTlr/i1Sbctq65edtukzN/2yff8VSLxV/dMzvwlHculvOsw+/dUZUh6lI/K/bkqtOH0Ws0mLIdz\n", |
|
1192 | 1190 | "SeeSuaUtg9JKDLFLER34pOU8ZsVbLdhYedzyLcvzlr0WNYwCQBpN21cbOZCBO6jTB9Pf8jzvEemG\n", |
|
1193 | 1191 | "siF43fGLanJwDA+mwsomJdmmZFqOm39wk3vHBLfs3pGawJc07IqkkRO4zs1Vtvdg+SXoLfAnM8lf\n", |
|
1194 | 1192 | "mELSIqxtKQQmIiEh5NF7FuxhWSyWMgvvrW5Lvw2GLu4J+IEzlD7kHHTKM4KH1KYKOkUOkEJfTaPz\n", |
|
1195 | 1193 | "KujBWwAxLHmex7uksDHnAX/gT5s0wVgh4Iq5ul3zXHxhfw67lLfiwCZGERYBsKYZWBVeF94cxtbF\n", |
|
1196 | 1194 | "Q8gwigw3WTN5YddF+hNlaHAVuWpcCdc01+eQYV8mr/TukoMwf4A/vHRnmCesDK8Fm+hmfk3eE7py\n", |
|
1197 | 1195 | "XTn8fFwRnVc+lFACIwS8sQiMqmP8LwVbdLHfuLqqN/lYkXX4XRVj7+WfMs/pCXZaQ8W3R6Ozm336\n", |
|
1198 | 1196 | "afZ6xlRd9ubCr/6f6nmF4l1W50CTL5hXlBeb9/nKooq6Wl/bgmgsr8Ts9zZ9aVWBRT4H+kD8UNir\n", |
|
1199 | 1197 | "Wi+ohDvw9hjCZbON7Dkme9+eRSRW8khOGkYDb/P1gllFY4wqqZqlWqy6X/WoimszBgSTl1M0UAKF\n", |
|
1200 | 1198 | "L/CxvAAUjHSWx0cvVcTlzf3cHQnV+o3yHk2Cl/8RlT8XtslmbHPCpZscdMdGAc+GBv+EcOBKgEiR\n", |
|
1201 | 1199 | "lyd6RJQHT+OViTs+J34olzfyS/FDZuLlaYXHJC3mW8Qjh+IoDMkEJjkZE281HdZczhzWSKKGljca\n", |
|
1202 | 1200 | "Yri6TAHhM/TcamLGQuhD+Yll4h5G5/xch8WZmSgHLZbux0JSVGkoDAaD9hGLMFP7nDnt984SP7zn\n", |
|
1203 | 1201 | "no3j6riG4l5KazCVPcqyrFyXiddpkXifuEZ8QhwtfcwmFF+UQb/mj6OVaTbUFNkWCwteR4Y6MpnQ\n", |
|
1204 | 1202 | "C3VNm1UebFHej7W3mpG2p6Fw6KQmPTfrXtSQC/Ee8Fr2igbhLTnu2R6Visn7Ppqh6/iAQ/xPNE/q\n", |
|
1205 | 1203 | "Fg0HcObIb3ar7vvfM8fPcuaoUt3ozHHkHJejQbVcMPCVwkKsagWM/0mb/KI3auWdlEHtWW0OH3a1\n", |
|
1206 | 1204 | "FjgvGLGGTQv5lnxxBb8z//78R/M35j+Xn8o/lD+YfzY/B83CwTuPGWt3HNTl4P2PofEIjLl+vtjl\n", |
|
1207 | 1205 | "Ksa/Q5kLVdTu8djH/EP8VpVLGFHd/InxW1Wu6H811uvIOXGYP/9jgklwCnt0DBuPOoUkC/GkeAOQ\n", |
|
1208 | 1206 | "Va2ILHRmUM+eNGm2ulYX9/vjOtVjrV1drQH+P9nn9VfCKdW3/9fn9f+XPq+qjhv7vIojx/g4Oovm\n", |
|
1209 | 1207 | "Fp3w7ZQ2RGM9kQ2l4eMjwkwtfVZ8T6G6yEwwY2edT5hs5A3Kgfs0azRPaOhXmpmaRZr7NPxXaoWq\n", |
|
1210 | 1208 | "jf9Kl9lyHNSd1dEUpcaUqHCkyL5FCHYuD5Ya/u+HfL4a3pO4E5PWRj4fCF3isPAPqjt4G22gPdkB\n", |
|
1211 | 1209 | "kCi9LKhGGZSUXj4g93oVSsnJ9J4x3bYr21vrM71U5k52C3tHfnL98Zz2w/UKxQhoNZbz8fz8Afxu\n", |
|
1212 | 1210 | "sThROCe+y39n38NUKvmsBDGXBZG4K/mq5nsY/N89IHPkmDl8XTzG79cK5WNCJl9z5K1BJ46wCF/Q\n", |
|
1213 | 1211 | "lJtZ4VTmGf7+L9hR8djHTeLjHx/4fzYvJoR4Xv8o/lioF97YY9F41DV7nJpCjiGNwLFKo1XXpGFY\n", |
|
1214 | 1212 | "IC5MFuVoC7U4LIfmu1z7kBbmB7u0B7Svak38W63FafFbopbJll7LEstKy1rLJst2CziBEQrLco6v\n", |
|
1215 | 1213 | "x2GQ5BqETWKYMKLI2ccr7LsmZNJYipCUz9JvEK+kTxsuGlAVvaHAEDRkWPZXG9Ybthh2GvYbjhlM\n", |
|
1216 | 1214 | "GK/g75AK8YU7b1rljZmzcVltcTlg9Z5x2FPOVR0RB5MmdIVcgc7bGhtv6wy4Ql0T/nQ4NCXijvQ9\n", |
|
1217 | 1215 | "0Nb2l/Mi7oYp4cN79VWTZkyILmjzVbYtaKydOalatzd+iyk6pS/ccf/sCRNm398enj8larol/r+y\n", |
|
1218 | 1216 | "/X9Vtv8bv/y/Hr+8bOQjMZ/LrFD4CsyHi2Bc3K/nMnIrhHMQmCwOM39O8zV7Ulk6H3wwW/pz4J4y\n", |
|
1219 | 1217 | "iDWodVAOTtvvFK8kixDEOeCMObud85xLnauc65ybnTuc+5xHnby5nnSeB9lAgcpMekClNuOLIlsk\n", |
|
1220 | 1218 | "Obz0wDGHmG8tyS8pN/P5ZzL79XRDkd1p0OfYyqtdrHp4KduaSAy/5izLzcQwGPkt28b7WrlQI/w8\n", |
|
1221 | 1219 | "VRtCLIJaouHkarjsimIbgpemiz9vNl6PzdJfobmSfrPiUgV1worCiqqK5oopFfMrllc8VLGhAgwB\n", |
|
1222 | 1220 | "ByperTCRpUtwUKrS2KyZmL/jPBdo7U9kRiL2cfuLSRDFruJAcay4u3he8dLiVcXrijcX7yjeV3y0\n", |
|
1223 | 1221 | "GIIoPl9MKj1ifqZPV16spN5XWVAZrGyq7Knsq1xWubpyfeWWyp2V+yuPVZoWSlWUN4QGc4dGnTcQ\n", |
|
1224 | 1222 | "s8r+T2RFqXj3RFwqeUXhiEbZtkR3rCcuunvt3lBReNK8uXlOt8k+wSUWTCt1ufxN8apYa9tfTKqc\n", |
|
1225 | 1223 | "y1TVbRNcnS1Tn+3d5K6w6fPtXtHrDzW1/Kztr2UZ145cFutFl1AkVAgFUnEF12IqsPZUmFg9FTTz\n", |
|
1226 | 1224 | "Oa4iu5MHgkAjdH7HM4ne1tv8XlcolgwkFnX6fJ2LEvFFnf4VrXPntjDV3kRzq8MXKTfXTLsjHr9z\n", |
|
1227 | 1225 | "ak3VlDtv8n29peXriHtTJSwTX2RfEwJCTJgibE5NDaWmkQIw1SJHa0b/D+J9Bi8F6X0GC4NVwebg\n", |
|
1228 | 1226 | "lOD84PIgoo1uDe4KHgi+GjSR+Vi7hr8jbbuz3d8ebZ/c3tu+pH1l+9r2Te3b2wfaj7RjbG0/1y4u\n", |
|
1229 | 1227 | "FPY0iho+ZHvFGj7Ra8jOyauE80rVWFI3DaZuIv7kLj4mVma8ca4iJpV9dXRy/HddKf8Urcz6mKOH\n", |
|
1230 | 1228 | "iy/afRPLSibW1dic1RMipWWRSrvNFykraQzV2O1VSJnotzdXVzmqAl6zxRuocvmrh4+bfVXVDlup\n", |
|
1231 | 1229 | "3VAbtFcHvVc80aDL5vHb8v0euzPQ6IHjg6M8YLMFyx3OQLTCH7UVl5vySt2WhkqTp9hmLizL9zdY\n", |
|
1232 | 1230 | "3R45DtbI+3yB8GMu42amTsVDqQRJOE6m+7kkYQck7LjkIAk7Ch1VjmbHFMd8x3LHQ44Njq2OXY4D\n", |
|
1233 | 1231 | "jlcdXMJ8RMjnnc/SHyY5h51hfzganhzuDS8JYztoU3h7eCB8JAw5h8+FeV8gJRYKWHAwFQwJ/N+1\n", |
|
1234 | 1232 | "FKfkf8072h4z3oaUryGaynLig0ifdl90Uy9yF7iD7iZ3j1v2Hlzv3uLe6d7vPuY2Ybe+v5F6Z6Or\n", |
|
1235 | 1233 | "MdAYa+xunNe4tHFV47rGzY07Gvc1Hm1E72w830jGB+MW5E7XxKvsstQZx8OMW9ZRS3h+T2hqpMjd\n", |
|
1236 | 1234 | "0FNX3+th1qquid6I21c2uSY8NVrpzO0qmhWuiHitVm+koibus7C7Y3+9YnrlpNm1NTPiFXV+k9tU\n", |
|
1237 | 1235 | "veiWqNteU1zqiXbPmvMFX8xdG/eUttSXhnvm0Fh+50gN26TKFxoEB19b+NU1wp4y0cHbaJ2oV9eg\n", |
|
1238 | 1236 | "2jSsomZOp8MqG1eT1zyNEdGJjXzk8Mttkm1yWPK4tq0z5ulUjInOhrAjYMsz8SStKU/DRJWhaILX\n", |
|
1239 | 1237 | "UOgwiWetVqPZ5A7U1ZRphvVl829pdhbm5RvzjBOaI1oHu+xqaW0Jl2iMNuiqH45Usw94HfXYwdcJ\n", |
|
1240 | 1238 | "GB00XpUuELPZIszX/t26gjuefan1JJvLCxxOq57EcxWOVIvt/DcGwUFcd/rQnhwRyyWNqMVzuRoZ\n", |
|
1241 | 1239 | "a4TVEit3FLIpw4dF8/Bk1ji8n50+GWOH2IGmScM3D0++CXl187z+iuelE7w8H64VcK2ECPX0il8/\n", |
|
1242 | 1240 | "DqCFPVqRIWeNtZzPQOVWsXV4arsYP6nafaVXdeFKQYbj8qfst+I7gkbIEUKSBpaQWpEmeT39kSOq\n", |
|
1243 | 1241 | "CDBK4t8IavqG/tBD2yI2lcpmY92tu3a1/sPx9es3eNk6tm74IdY1/P3h77Mu+BlRQeKP+Ejn5f2v\n", |
|
1244 | 1242 | "RmgYncf8gyl/qN+pvoKJrHKov1jFK65iPi6YShFrSrX8ELHGiCMQmBiLRmNYmY3a2dMEwf9zuPgj\n", |
|
1245 | 1243 | "Mv7vZ02NoknntFrsueoJHs8EbYNuajQ6udDPJ+SXh+9gPxoWHuzoeNDaVGgqsZpdNmuOr742ou9p\n", |
|
1246 | 1244 | "624pa/SW2+wT94vLP94sPv1xA68ytclbRi6IPaJGsAm9kk3N5aBTY7KEtqcflEzyBxv2rCRr9oOD\n", |
|
1247 | 1245 | "r1ONoT1Wesm5oo4PsGRKhA0DPnvLQSN1GHL50MrbjhzivjzmUsLbs6rpEyd9a2/nH5n75omtTx3s\n", |
|
1248 | 1246 | "Glm9sejBlsdavlm8iiNE2i3ME+eybwilwk3C7XvyNGZ1jRJKz2xJ1Q0Ke5pFCNIuGjhGxGqOboz3\n", |
|
1249 | 1247 | "ROZHHPnXbLSlIrQR7wnxxbMckw8pLYOpFuzBjd3p8o7bA3Pc+CtxrspaWlNaNs1f2VVUEdRM4B9r\n", |
|
1250 | 1248 | "S8unVPq7Snw+XQ19LJtWqXyrtpTgW3/l5BKvT1fLvuFu8LtceXnOeo+7IVDgzMtz1ZXt5pfZxKCS\n", |
|
1251 | 1249 | "SM3sFkHL35Wfa5C5gl/S6Plcrs8YCIqEuYTGIWGPHm+Fz+yNlQ6NxqHh3e8W9sHwQvad4Vz2AQu2\n", |
|
1252 | 1250 | "vdT2zN+1LUkkrs53gpSTzVcS9WQ6o6d3m0PvNmdc9rHGyspGjYNR9t8dvo0XwbO/p+3vnuEFDP8M\n", |
|
1253 | 1251 | "2fMxZf7IWTaTfPFyBHiHIqijl7nYDnIIGvXv+f88HkWWX+BmmV+AjzrvCmfG8A48lk2/jHQuK2Ek\n", |
|
1254 | 1252 | "IL4oviKU8f4+g8JEY36z8fnNlpnsyNr2upoI+TRgGqxgZkyDKhvFu6Q/fMjJBJnmA0E0FijXeVmE\n", |
|
1255 | 1253 | "edH/5V0mVq4SX8yGnLYYjTOGN82YyyZOZhO95fl2Cj89bGeRraMxqC3GnIMHxVc+bikvLKZY1GwD\n", |
|
1256 | 1254 | "e0CJO/ZrcYdqPX/rufR8b7Pm66ZfYN7rpl9khWPS78im/5aVU3ovF9Zeut8o3y+cJfmZkM7lZxHK\n", |
|
1257 | 1255 | "2VekonJogTBWXlMus1iDAOWQYuKsVRG7rInMJ/LAjA67hnIKLLsIrn7bAIJ3XNC/zFso4x/KsKHC\n", |
|
1258 | 1256 | "2BVowAZ2RTI5y+SzvH6LCC0Th3J2OogrVLEVclSyFdJTOJl4C/A9QFP2jO6AWjG0UVgoFQ9x6QCO\n", |
|
1259 | 1257 | "ZclufJ9iwbZQ2gp4C/A9AMWBJTcrCtjqB+cqRQ1cB02zF8rteYAfp8XrcNULj4h9UHgPeck5BHWZ\n", |
|
1260 | 1258 | "nA2A0YW6bAI0oXSKAjUVsDtLvjoVQFGfDqD0uSh9CnmJoWDyXO8GfI6XFBv134J9sZeP2Nasm7r3\n", |
|
1261 | 1259 | "2b+dvWqm3z9z1ey/ZeLwcM+UKe+0P353e/vdj7e/014/e2kstnR2/W+44hKpnf943/wvz6+lNrCY\n", |
|
1262 | 1260 | "v2svtQGT0gZ+MCb95mz6u8KxMemPZdMvC8fHpN+RTf+t8B80XizmfbGTt6VKYd6eAjVmiAIY22R7\n", |
|
1263 | 1261 | "5Thdb1yvzJwD73EwJ/8ZV+fyGTEfFfA/hYNSpcpynS5Zbi130H/875h+KXaO6ZSG4TVs3/DX2bzh\n", |
|
1264 | 1262 | "XewRS6ZbjumRhlzxlfbftA//rj3TJ7P96B9JVnal35WPSX8sm36ZVYxJvyOb/lsWUtLd4j+KJ7Pp\n", |
|
1265 | 1263 | "v2OerAz/gvJ3yPlzKaI/UjqXITimHuQSgwWSRZlC+xlfu2BKH+pXqzNcJTm0E2yk67zBqziIx/Nq\n", |
|
1266 | 1264 | "Z6zyMlLPGH3uUYkmPl8bGa16bQotCJZymEgW97DHenqGv9TDjg9/SXzl+ec/bmEzh/vZ12+5ZWRk\n", |
|
1267 | 1265 | "5Jf8xQdU9/HncPL6a4V3TBRHceQKT8+lNiWnv2uQ4yvewv/sJznJ6b81yese20hAOMqfu0SI78lH\n", |
|
1268 | 1266 | "2/kMrYbsDbFdUKI0D9e45uG18qcYbRZHx7YKdU/+DdrC6NhM9c0b+TX7E72nIuU9/Vp+f/y9Pkw2\n", |
|
1269 | 1267 | "NsXyexX2Zd4r+y3dX0LP93aDMJpO95fQ/ZeEXZl8xqX/Tvj2de9fKnw8olHazW7Kv0yZJ9zZ9jQ2\n", |
|
1270 | 1268 | "/SIzZ+u5m/IpU/L/ONNeVfn0firkPs+qx6Q/lk2/zIJj0tdn03/DEtly45ReK9dH2H/d9IvCP2Xr\n", |
|
1271 | 1269 | "E6f61Cr1+QdKb+By/ojun6Dkc+i66ReEPdReGkYC7CPxpDBb+GXqllBqTih1i0KcmJpjSU0bktjE\n", |
|
1272 | 1270 | "aZjMS+lPaqKlv1MFBbrT2envjHZO7uztXNK5snNt56bO7Z3w9IYC3XmukyvQ8rbWNEt/jYor6TWX\n", |
|
1273 | 1271 | "akhJrymsqapprplSM79mec1DNRtqttbsqjlQ82oNV4Zp70Lues28TTbz1soX40a+pPAX8gmVFRLT\n", |
|
1274 | 1272 | "Y6GlXy1ekUrlT82W/lbGle3Wi62kbLcWtAZbm1p7Wvtal7Wubl3fuqV1Z+v+1mOtJq5Aa1yK/gEV\n", |
|
1275 | 1273 | "VDYBzWrQMb4UHuPxqx0l81FUajVXW6C3MIOotxpKQ47yKvvECZaKoDOozrWb85y5+fXNE+NVba5b\n", |
|
1276 | 1274 | "moqiNcWeSFtXW8QTaLulpuXz1a2hBcXRGnd01qJZ0aqO6uKSFqZSB3yuCkdugS/fXqjOM+VoNdYO\n", |
|
1277 | 1275 | "0VHYFAqErOVhT2V9udNZXNNWH5neUOAP13eZPfXl4caKoglTk+GbJ+blqATl3brxDrPv9nfCJrnP\n", |
|
1278 | 1276 | "8bYTpnceUtrODqUvusUwtZ2Qcv/mG6cr/iVhiuk5Y4+oVvxLdETJb1JGShoCr95+3GOGIoVFjprU\n", |
|
1279 | 1277 | "Gy1UqH49n4r4MGvC+kTeZ4000l6rIyKWvtXz1lvvihXvvsW+OXwv+2bLnvb2PVS3uXxeWEDjYz3V\n", |
|
1280 | 1278 | "7R3egkfTb86mvyv8fEz6Y9n0y+PSv51Nf0/45Zj09dn03wh/pGefy+fiBfzZY8KzqaYQb5appow3\n", |
|
1281 | 1279 | "fjMFSTTZArL2SBpxwNLv4yu9GCVmh95xVn5EK5P5YOQfjJlxmEy68MFo6S9h2BQqcZUESsYe2G4u\n", |
|
1282 | 1280 | "2VGyr+RoCTaFSs7Dqimmsl8zpfOmjF1seKCpeXNW0yW13TGr7pdGx3FV54SGuKPHXl5V5c8zBaqq\n", |
|
1283 | 1281 | "yu09jnjEH3WarhnbVaqC4rm317IXh6dHpjSUWDQaS0nDlAhLD3fW3j632K4pyM8M+4q+oUqRXGPK\n", |
|
1284 | 1282 | "/P9/aF7js7Q4ndKblfFIbpsunu6g9BZl/Hp6TPod2fTfCk9m4gyzfxa/xtMn0Tzx5JeEMemvZNPn\n", |
|
1285 | 1283 | "fEne0gjz8e4X7CzXvmcwdWpmKDUrlKobws67vEUo2eqIQ3CmJVU0iGOJOksqMpiKhLBw71Bj6Otw\n", |
|
1286 | 1284 | "dvg7oh2TO3o7lnSs7FjbsaljeweYMDD0dZzrEImW4ebR9VoVf69VudebeRv4h4arz8D2lImT+JBn\n", |
|
1287 | 1285 | "UxF1ShVvUdhM9F300fjmK/AFfU2+Hl+fb5lvtW+9b4tvp2+/75jPtFC6Sf4J1wp6aE+xx9UT6In1\n", |
|
1288 | 1286 | "dPfM61nas6pnXc/mnh09+3qO9qD59JzvwZ7i+KWgFw6MmRQ+/kUaJ3ordAHZ6RMWcmMWAqqxtpeN\n", |
|
1289 | 1287 | "7Bdj1wVMpRJLZjZ74hOKEvPvrC5ffctNwfYvV7TWFWtUpsyK4YuF07rqbWUBu6/RZx23fLAGbaEq\n", |
|
1290 | 1288 | "bEk2t5XpjQ/FQp32qkk1Py5K2LIK30qNLeh1lTtyCqpinsza8XfsJ/TOe6mNtAl7rpv+OWWuvDp9\n", |
|
1291 | 1289 | "ntIGr05fKnyH0oMj74s/Fd/n6YvltYcoUptC+mzxfT6jR1lBKhbCQCEOEfEYbe2lYhlv5AmZjfoJ\n", |
|
1292 | 1290 | "meY1QXFLxmBahlESQeZ5I/M6vX5v1DvZ2+td4l3pXevd5N3uRQRoNDLvOW+GAdTDG40nQ15G40zu\n", |
|
1293 | 1291 | "VaPw+CVqBYZkSZML3g7JTX8wQPPKVNB2Eh+gg9R2gq5gIBgLdgfnBZcGVwXBI7wjuC94NIi2Ezwf\n", |
|
1294 | 1292 | "lKnBG9A0Gy42UNNsKGgINjQ19DT0NSxrWN2wvmFLw86G/Q3HGjD1YqxvvDZAWob17SqKSXF29Lph\n", |
|
1295 | 1293 | "0o4ebY8Oe66OqSaGPx68JiL17okbNw6vvYpYLDs2XKH3u1x57/8wJv1r2fQnhb+/7v1zsu1kfPpS\n", |
|
1296 | 1294 | "rEWVMeYKH2NiQlL4ZqotBK6ftsyxULsFHuZ59lJI3i5zupda+pv4HzpokGLyV2WWVHIwlQxlR5EM\n", |
|
1297 | 1295 | "Md+eJtHDX2GeqhCvMEZ/sCZK4FUkLiboVSQKEsFEU6In0ZdYllidWJ/YktiZ2J84ljBd0+Vprsgc\n", |
|
1298 | 1296 | "jTnK6TAo5ho/WdjkkyIHWzvayTWaCcHaZKUv2dvQOLe5dPhhVXFdi7fxZnukOuLxui1yH2+b1VPW\n", |
|
1299 | 1297 | "MqFoTO/WqEWLTXlP/tZbw6XeSRPc9WXVja48TbFT6d1/1zGnsDpakhnLLaKL5PxFpf8OXDd9jnDw\n", |
|
1300 | 1298 | "uulLhe+PSX83m/6+sF32YeYT/WkVYtU/ruT/93w+YtjhYad5vy4T+lPlIRBglVtSBYOpghCd3DIy\n", |
|
1301 | 1299 | "yVYN4gVVYPuw38RTuapePCizDYyhrcr00HH+FeMmfxf/4JJHf/RQlbFE3qLst+K9Wi9a6b1aC6xB\n", |
|
1302 | 1300 | "a5O1x9pnXWZdbV1v3WLdad1vPWY1kXkwH1zK0JnR3eR4M04HX2Ipb8/hzZIsTvuXrCt6dAo5ore0\n", |
|
1303 | 1301 | "tP+LGNouu6IPv8FUM+aQI7oYaty4UdZFT3F5FIuQ0zKaU38sCpm5nAnUb+T0J5k81+q5LvqiuJ9r\n", |
|
1304 | 1302 | "XlXCQ3tKVT7YmPgu0TyW4yv0VfkQSXG+b7nvId8G31bfLt8B36uYx8w+6gLmUH8+l6hPCYMgpAKh\n", |
|
1305 | 1303 | "ccrsdafUMcps4NOVWdWYfdSxe5AGsT0vM02x0vz8UvwbN0Wx14drM5ORyuEoKsI/0sFHfj5iEbay\n", |
|
1306 | 1304 | "1wWbMH2PUZMDHTw7BueO3T/VT5oPVYaPtmqXOqDOGLeuUq9Tb1bvUO9TH1VjtFWfV2Om1rkU5QSr\n", |
|
1307 | 1305 | "OVJgnCq9TV9QkqduF12xicUF/8hEdX5JhVX0f/xabn2DP1d+P7w+XGfh/YF9jt7P54YFxXffzX5J\n", |
|
1308 | 1306 | "89nXKP13C+X0efwhnKqdPP0JZR4tFn6lpM+k+5+g+y89IN/vHnEL28ak/+7SaD438f6TyWep8I2R\n", |
|
1309 | 1307 | "HJ7eQf0K/XOLkv8/0v1Xp88TnpLTeT1Ps7PZ9N8JX6X0/HH38/q8mF37ieXUHp9WxvH+MemvZNPn\n", |
|
1310 | 1308 | "3CB9rfAmpVOcKUo/RPm3zZDzt/P63Er1kdN/9ys5vfSq++cl5PRxsRGQz6rrp39ukbyHU87nD8QI\n", |
|
1311 | 1309 | "uUW4CIV8Lqnisk4+15KaDp18Osw6atSfUa8mfzDo7l20tuhydvm7ol2Tu3q7lnSt7Frbtalre9dA\n", |
|
1312 | 1310 | "15EurC26znXxqZ2WK1zpRzlZq4IxmnnuZ9PMkxi7kheTNHYlC5LBZFOyJ9mXXJZcnVyf3JLcmdyf\n", |
|
1313 | 1311 | "PJbEnOT6zJr5uIAWuquCX5CS86Mb6ueN4aq6G8S7SIyPjFFuy7++gt6jsjpuEAcjcHXEDL1alN+z\n", |
|
1314 | 1312 | "G+8z+55/N1dQ9O332YP0/n+o7GU9ldHDwf+rpPP7m4Qbp4/hC64Qntuj1WDjV0sewE4iZ3TSClOL\n", |
|
1315 | 1313 | "5aWAQ8LsnDQu9GbuVec6e1SiWi3H+MWRAlnl8XHK4DIEDDFDt2GeYalhlWGdYbNhh2Gf4agB45Th\n", |
|
1316 | 1314 | "PEip86we5aDVRY4XhYPKArNYmZa4pj+e+rdR3gLI0P/+5V+OJwCeMUOmAF7S+NBYDuC/bVwCEuAs\n", |
|
1317 | 1315 | "B8n3ZA4SLscfg4Mkm/61bPqTinzHcZbQOPD0mPSL2fR/FbZm0sX8MfevFU4KModNgI3wcb5ZGFCs\n", |
|
1318 | 1316 | "U2qGaMaSz2fjyhq/vxTKJdmR1OCMN1UXwkeK4pNd3Y3jHb6xwkhBfTIfMqaBXFUE+XC/l16RF1Gr\n", |
|
1319 | 1317 | "Yt5u7zzvUu8q7zrvZu8O7z7vUWgOJ73nQa7YTPdfV/e7AXnN2OO6kXHz5PVJba5/QvAJVDfZzWJl\n", |
|
1320 | 1318 | "3+oVkveQsh77jTDqY634YGO8VMbRcX6aGF8/f/30pcr8thh7PeIrgrx3rhOKhB8p79nC79/P09dT\n", |
|
1321 | 1319 | "+leFd+g9+4XXWIBZYQsBbY4NUUjKIUGOt90KzySK5XBWhGNoJXxKA8MjjL3WLq+DAP/EyxOFXPYX\n", |
|
1322 | 1320 | "e7RqDR82x3kxbcN5VyuM/VtxZcbVGbUc+AFG3FjoF4D/Y59wFJ63CE8vG7bL7BphBRZKg4CNYLfR\n", |
|
1323 | 1321 | "g+pFJDrUi/BQ3s+OwUPZBb+CHL2okGgslHJyFG4HKVdFqX+Ab3AUoIXTQRm4ZFPwyHwNAKcMaRvA\n", |
|
1324 | 1322 | "jC/uU9JWSGdxNQvwqDFjyEqnJFeHg8YRuOyjKIl0lf6++AMEuxwS/xOsWn8HUd4lypHU9Rg8Ml6w\n", |
|
1325 | 1323 | "q+B+NR9UBb3w9V3GVuOJdoHaZYpmPuhJQGeWnqzthddvN4QC1utYuYrRkXOg/CUW2Tr8sXy2PHfG\n", |
|
1326 | 1324 | "8KYr7IGPN+Ks4qDynlQPkT+VjU0FqaZAMdbNQ/15XJhfAJ/LixwGvpL3VN7uPNUKSZVngMRA+C8z\n", |
|
1327 | 1325 | "JRyE31Yu4DwdZsKlC4R6IoWRBCGdmrLMGZJeUPiGFkpn4Lm7JueJLN+EGbwm2iHJJGd/0ARud0vK\n", |
|
1328 | 1326 | "MpQ0g452jeUJyzbLC5aXLboVSVvcMtWywHKX5WHLVyxPWXZbDlpyFqbftFyCGXaORdnUegHMXmYH\n", |
|
1329 | 1327 | "2AZmOhY57nOscTzh0Cy8Dq1/lsBEsOYqnqRW+RRRHBy4W3xE/BswE8bxjo4T/Zl8mybUr+X35BI/\n", |
|
1330 | 1328 | "Nl6ZkT5RjHlm9aoq5dNF3jV0XnhesxHD71kPsw//J2sYXjt88tFb2b+z54bfZHr28PDaDThGPHJE\n", |
|
1331 | 1329 | "fIU6ENhwKpIC0+wpEITc3AZBLYRGXuQYHfkRx9jInzg2jwxwjBMmCF8a2c3xrZFfcxwi/BnhGcKz\n", |
|
1332 | 1330 | "QBZFPixG2ESYRG6sDTmwh+meRzhqqEQNlaihEjVUooZK1FCJGipRQyVqqEQNlaihEjVUooZK1FCJ\n", |
|
1333 | 1331 | "GipRQyVqqEQNlaihErVUopZK1FKJWipRSyVqqUQtlailErVUopZK1FKJWipRSyVqqUQtlailErVU\n", |
|
1334 | 1332 | "opZK1FKJOipRRyXqqEQdlaijEnVUoo5K1FGJOipRRyXqqEQdlaijEnVUoo5K1FGJOipRRyXqqEQ9\n", |
|
1335 | 1333 | "lainEvVUop5K1FOJeipRTyXqqUQ9lainEvVUop5K1FOJeipRTyXqqUQ9lainEvVUok1Qj7zKUUOo\n", |
|
1336 | 1334 | "JdQR6gkXjqzhmCI8jhRmIDQSmggf41jCa/5djlHCGKU0jzyLU1fCBOFLhD8beYvjGcKzQEa/4rUF\n", |
|
1337 | 1335 | "NhEmkQOvLb+f1/MtoZrXc4CjhlBLqCPUEy4cWcoxRXgcKbyeQCOhifAxjrVCiLeDWiFKGBMsHJtH\n", |
|
1338 | 1336 | "fscxTpgg/JlQwPEM4Vkgo/tZjLCJMInf8hry+9kj/J4Qr+GLHDWEWkIdoZ5w0sjXObYSJgnbCTsJ\n", |
|
1339 | 1337 | "JxNOI+wl7CO8jXAh4XLCuwjvJryH8F7CdfwdhYT1I3/k+DSlPEP4LOE2wm8T7iZMER7i0g4J/0bX\n", |
|
1340 | 1338 | "rxAeITxOdT5B354kfIPwFOFpwiG682eEZwjPArnk+W+55IEmQnpG1kVIT8q6CXsIpxBOJbyZcAbh\n", |
|
1341 | 1339 | "TMJZhLMJF+Dp2BK6Xkq4jHA56sPuIrybkCTDSDLszwnvI3yAvn2QcCXhKsLVhA8RPkx3PkK4hkp8\n", |
|
1342 | 1340 | "jD9FlHpKlHpKlHpKlHpKlHpKlL9fYCthkrCdsJNwMuE0wtt4O4xSz4ryd4qUuwjvJryH8F7CdYTw\n", |
|
1343 | 1341 | "t47yd4rrZwifJdxG+G3C3YQpyvMQ7y9R/h5RynFKP0EpJwnfIDxFeJoQo0eURo8ojR5R6uNR6uNR\n", |
|
1344 | 1342 | "6uNRRk/B3yCQnoW/KeAMwpmEswhnEy5AnfmbwvVSwmWEy1Eif1PAuwkfIHyQcCXhKsLVhA8RPkK1\n", |
|
1345 | 1343 | "WkN5YrSJ8Xfxa44aQi2hjlBPOIn/KsbfBTBJ2E7YSTiZcBrhbXT/Qi6rGH8XuL6L8G7CewjvJVzP\n", |
|
1346 | 1344 | "+3iMvwVcP0P4LOE2wm8T7iZMUW6H6PoI4XHCE4QnCd8gPEV4GshlDjQSmgiptlzmQKozlznSZxDO\n", |
|
1347 | 1345 | "JJxFOJtwAWrIZY7rpYTLCOm5GD0Xo+fiMgc+SLiScBXhasKHCNdQbo/x62Yae5tp7G2msbeZxt5m\n", |
|
1348 | 1346 | "GnububS/y7GVMEnYTthJOJlwGuFthAtHHue4nK7vIryb8B7CewnX8d7XTKNZM5c5Up4hfJZwG+G3\n", |
|
1349 | 1347 | "CXcT/gPVJDXyDMe9lHKE8DilnyA8SfgG4SnC04Rv8RbVTPNFM80XzTRfNDOqP5c/kJ6Cyx84g3Am\n", |
|
1350 | 1348 | "4SzC2YQYnZq5/HG9lHAZ4QOU24OEKwlXEa4mfIhwDf0WM1ScpB0nacdJ2nGSdpykHSdpx0nacZJ2\n", |
|
1351 | 1349 | "nKQdJ2nHSdpxknacpB0nacdJ2nGSdpykHSdpx0nacZJ2nKQdJ2nHSdpxknacpB0nacdJ2nGSdpyk\n", |
|
1352 | 1350 | "HSdpx0nacZJ2nKQdJ2nHSdpxknacpB0nacdJ2nGSdpykHSdpx0nacZJ2nKQdJ2nHSdpxknacpB0n\n", |
|
1353 | 1351 | "acdJ2nGSdpykHSdpx0nacZJ2nKQdJ2nHSdpxknacpJ0gaSdI2gmSdoKknSBpJ0jaCZJ2gqSdIGkn\n", |
|
1354 | 1352 | "SNoJknaCpJ0gaSdI2gmSdoKknSBpJ0jaCZJ2gqSdIGknSNoJknaCpJ0gaSdI2gmSdoKknSBpJ0ja\n", |
|
1355 | 1353 | "CZJ2gqSdIGknSNoJknaCpJ0gaSdI2gmSdoKknSBpJ0jaCZJ2gqSdIGknSNoJknaCpJ0gaSdI2gmS\n", |
|
1356 | 1354 | "doKknSBpJ0jaCZJ2gqSdIGknSNoJknaCpJ0gaa8UMNqsFF4S8oUXhRdHhvjVS4RYgbxEK5CXhB/y\n", |
|
1357 | 1355 | "e16iGfwlmsFfohn8JZrBX2L307crCP+C4yG+XgL2ES7ktTqE/QyOywnvIryb8B7Cewm/SIgZ9pDw\n", |
|
1358 | 1356 | "TV6fQ8IWwqcIn6ZvnyF8lnAb4bcJdxOmqKy9uObrGWAP4RTCqYTTCG8mnEE4k3AW4WzCWwjnEM4l\n", |
|
1359 | 1357 | "vJXw86gJu53wDsI7CZfQt0sJMcIfJ63hOGkNx0lrOE5aw3HSGo6T1nCctIbjpDUcJ63hOM37x2ne\n", |
|
1360 | 1358 | "P07z/nHSGo6T1nCctIbjpDUcJ63hOGkNx2kufotmzLdophvi169yTHH8Gcn/ZySZM3R9hq7P0vVZ\n", |
|
1361 | 1359 | "XDMDasuR15Yjry1HXluOccIEIa8tR15bjkOEPyM8Q3gWiNpyjBE2ESaRG2rL8WG6h9eWGalEI5Vo\n", |
|
1362 | 1360 | "pBKNVKKRSjRSiUYq0UglGqlEI5VopBKNVKKRSjRSiUYq0UglGqlEI5VopBJNVKKJSjRRiSYq0UQl\n", |
|
1363 | 1361 | "mqhEE5VoohJNVKKJSjRRiSYq0UQlmqhEE5VoohJNVKKJSjRRiZXQvzhGCbn+xZHrXxzjhAnClwi5\n", |
|
1364 | 1362 | "/sXxDOFZIKNfQf/i2ESYRA7Qvzhy/Yv5KX8/5e+n/P2Uv5/y91P+fsrfT/n7KX8/5e+n/P2Uv5/y\n", |
|
1365 | 1363 | "91P+fsrfT/kHKP8A5R+g/AOUf4DyD1D+Aco/QPkHKP8A5R+g/AOUf4DyD1D+Aco/QPkHKf8g5R+k\n", |
|
1366 | 1364 | "/IOUf5DyD1L+Qco/SPkHKf8g5R+k/IOUf5DyD1L+Qco/SPmHoPNxjBJyvZIj1ys5xgkThFyv5HiG\n", |
|
1367 | 1365 | "8CyQ0f3QKzk2ESbxW+iVHLleycKUc5hyDlPOYco5TDmHKecw5RymnMOUc5hyDlPOYco5TDmHKecw\n", |
|
1368 | 1366 | "5VxPOddTzvWUcz3lXE8511PO9ZRzPeVcTznXU871lHM95VxPOddTzvWUM3SlFxl0JaCWUEeoJ+S6\n", |
|
1369 | 1367 | "MIOuBEwSthN2Ek4mnEbYS9hHeBvhQsLlhHcR3k14D+G9hFwX5shnWAa9CSnPED5LuI3w24S7CVOE\n", |
|
1370 | 1368 | "XBfm+G90/cr/7e1MgOwo7jPerZV2Vxe3AWMsP+MDDEKWhGBmxGGt7gvd4pAlpKe3o92Zefve8o6V\n", |
|
1371 | 1369 | "VoBlrxHIB5CkcscCh5CkApWEHChEoOC4HBIUJakk5iocQ27HSZzEOSqpOFH+329mtU+ywJWqVLx+\n", |
|
1372 | 1370 | "3+s309PT/f96ju7+PgG+CB6nzi+z9xXwVfA18HXwa+T8Ovgm+JZQY2GvkZRwJkgbNRb2GkkJV4Ar\n", |
|
1373 | 1371 | "wVXgavBWcB24HtwAbgS3qXUaC3uNsISDYKL6aCzsNcISEhlPZPQkNayDLfa2wRFwL7gPHAX3k/Me\n", |
|
1374 | 1372 | "8ABntLGwD+A3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8A\n", |
|
1375 | 1373 | "fgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4\n", |
|
1376 | 1374 | "DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3\n", |
|
1377 | 1375 | "gN8AfgP4DeA3gN8AfgP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8Q\n", |
|
1378 | 1376 | "fkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4\n", |
|
1379 | 1377 | "DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3\n", |
|
1380 | 1378 | "hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4jeA3gt8IfiP4jeA3gt8IfiP4jeA3gt8IfiP4jeA3gt8I\n", |
|
1381 | 1379 | "fiP4jeA3gt8IfiP4jeA3gl9G9z6C3wh+I/iN4DeC3wh+I/iN4DeC3wh+I/iN4DeC3wh+I/iN4DeC\n", |
|
1382 | 1380 | "3wh+I/iN4DeC3wh+I/iN4DeC3wh+I/iN4DeC3wh+I/iN4DeC3wh+I/iN4JfZAB/BbwS/EfxG8BvB\n", |
|
1383 | 1381 | "bwS/EfxG8BvBbwS/EfxG8BvBbwS/EfxG8BvBbwS/zCH4CH4XaX7McArYDfaAveAt9saySPNjhovA\n", |
|
1384 | 1382 | "xeBScDm4BtxOfnvbN0xIp2AGVsEh8JA99xdp3GR4GHwUfAx8HHwSfJrSvkT6RfA4+DL4Cvgq+Br4\n", |
|
1385 | 1383 | "ulDzY4YzwJkgtdX8mCF11jjLcB24HtwAbgS3qYYaPRkOgIMg7fK0y9MuzY8ZtsERcC+4DxwFD1Da\n", |
|
1386 | 1384 | "mKX7NIdgOAXsBnvAXvAWY6pPcwiGi8DF4FJwObgG3A7uOHnQMCGdghlYBYfAB43xPq6gPs0hGB4G\n", |
|
1387 | 1385 | "HwUfAx8HnwSfoiZPnzxs+AxbXgSPs/1l8BXwVfA18HXwDXvX7dMcguEMcCZI/TWHYEgrNIdguA5c\n", |
|
1388 | 1386 | "D24AN4K6Ivo0h2A4AA6CLUprgyPgXnAfOAoe4NgxS69xa12/YQscccsND5I+5LYZPgQ+zJZHwCPg\n", |
|
1389 | 1387 | "s26+4VF3k+Fz4PPkPAa+AJ5wG/waf5vyW2+xLX4H6bvAneAusAwOk/9usAEesKN2Wg03GLbsLDut\n", |
|
1390 | 1388 | "hlcZHmTLIfAh8GHwEfAIOZ91FxketXrutBoKn2f7MfAF8ISb5XdaDe0oq6FwB3gXuBPcBZbBYfLf\n", |
|
1391 | 1389 | "DTbAA7Y90ZyJ4R2gjc0Nd5FOwBTMwCo4BN4HPmj9IdGcieGPgj8OfoG9h8FHwcfAx8Enwac51zNK\n", |
|
1392 | 1390 | "a87EcCW4ClwNrgHXgreC68D14AZwI7gJ3AxuAbeCu1UfzZwY9oMxuIe9A6Cu/ZQ4pMQhJQ4pcUiJ\n", |
|
1393 | 1391 | "Q0ocUuKQEoeUOKTEISUOKXFIiUNKHFLikBKHlDikxCElDilxSIlDShxS4pASh5Q4pMQhJQ4pcUiJ\n", |
|
1394 | 1392 | "Q0ocUuKQEoeUOKTEISUOKXFIiUNKHFLikBKHlDikxCElDilxyIhDRhwy4pARh4w4ZMQhIw4ZcciI\n", |
|
1395 | 1393 | "Q0YcMuKQEYeMOGTEISMOGXHIiENGHDLikBGHjDhkxCEjDhlxyIhDRhwy4pARh4w4ZMQhIw4ZcciI\n", |
|
1396 | 1394 | "Q0YcMuKQEYeMOGTEISMOGXHIiENGHDLikBGHYbtyZxm2wIPgIfAh8GHwEfCI0K5E4TZwB3gXuBPc\n", |
|
1397 | 1395 | "BZbBA4b7NVdm+LThPcT5HiIwxnzRGPNFY8wXjTFfNMZ80RjzRWPMF40xXzTGfNEY80VjzBeNMV80\n", |
|
1398 | 1396 | "xnzRGPNFY8wXjTFfNMZ80RjzRWPM4Dl3ib8s/68qGU7PNSVos3rsV57uciV3QZGe3JFniuWZX6S7\n", |
|
1399 | 1397 | "bXtUpKUnXFqkLyB/l/OTp9r3Z/XfWCHt3cXGRp6e5M7x+4p0l1vkHyjSkzvyTLE8Lxbpbtv+1SLd\n", |
|
1400 | 1398 | "46/y3yzSve6yrguK9FQ3q2t2kZ7W/Uddq4v0dDdn2uVFeoZbPW18+3luxrQfLNLnu95pX+wbiWtJ\n", |
|
1401 | 1399 | "o7S4Xs82xQPtarnRseXGUjhnbv918bwbS/Pnzpt/7dwF9v9iU57tWmUrjkiapXKp1Sj3x0PlRlaq\n", |
|
1402 | 1400 | "7ymtjJP+uLo7bgzEjdLSRruSDZWblcGkFtdKfStml+J9lWq7mYzE1dFSNanEtWbcX2oNNurtgcHS\n", |
|
1403 | 1401 | "2qRWb40Ox6UVQ7tXzi6Va/2lofJoaXdcasQDSbMVNyxzUitV4karbN9pu5E0+5NKK6nXmnPcEld3\n", |
|
1404 | 1402 | "w27UNVziBtyg9fGfM37nu7lOs0ol6/mJq1meluUZdrFtWeGG3G630s229F7+5rjqGbnmuIr9GrLv\n", |
|
1405 | 1403 | "krM3FPsrdZyhya/YvmP7HjHst5x9pGqWq2H7F9vxdZe5TbZtwLWthLJtP3ueGy0dWglzrZzrbP88\n", |
|
1406 | 1404 | "tqgN8wyvte8FBZ6eq7O0a0+Vdvo5Empbtk/Lftvz3fYNUZfMttXdHsOVti1hT9UiozYNgCXr9w2r\n", |
|
1407 | 1405 | "e8Xy6pimpQaJlMpXZFYQxdjtsz1Vy9m0vSOUM2rbFdUKeZvESHUYtBLrllOR/F7slG2fjtK5Vd5u\n", |
|
1408 | 1406 | "cjSIqNrVopZ5yQk1qrClZfnz36mdqUHefurSMqxTnznvcO4+y62jypSxnBi0YD+Gw3faWyKOTX7X\n", |
|
1409 | 1407 | "irqdyYiOm2f3l9D+8nbuKdpSsrrEsNM8xc6g/R7hqIEiJnkZ461XHMZLbbK/SSqmlnuIet7CPba3\n", |
|
1410 | 1408 | "whHq16s44szydKbYrgldGwl8fTdLs6lVXJwvoY357z1w3zpVbt3iWSUW5VOxV33qZ8Qp76HVom+V\n", |
|
1411 | 1409 | "icREW5LiqPwc4/046Sgxj9Qy27O7OHq87yyHnTbHzKYPtalfXoeynbNJSn0so/w2sRsvc/ys6uPD\n", |
|
1412 | 1410 | "RUzFZYWt42dpEptq0SvV0/L25deC7lBDHNXq4HWiPXuLfSo5j3il2KJ6j8LWliL3Xju6cZZeNUTc\n", |
|
1413 | 1411 | "8nhdaeWPtzq2X+MRXM7vGlfxRN0HC/abRZ3KRXzGa3d631Ht98JcicgNdcQqKUqZ6E3DnLF1FvY7\n", |
|
1414 | 1412 | "eZnDvTDnpW15FMecizPZO9u9Le+ZJTtX3t783qOrMa9dC84q3FMTcg5yLytRVqPgq8w9vknuOmc/\n", |
|
1415 | 1413 | "PR5lys63JNwR8+s1z9HZPwdhKHH7aW+r6GPj97OSu8K2X3Fa2ae3o0xbVLqupgrbKrRY99j4tDtj\n", |
|
1416 | 1414 | "szhbi6jkd5v8Ph2TI+ZOMtF/8p5ds0iViz6cPx2Sjntotbi/7rZPlYiNdpxxoLjDn8lFuYhrw2Je\n", |
|
1417 | 1415 | "Z2udK6mzrvmTIOGekF89w7S0DL/j19QeWqQrtV5cDS2uvtZppQ1yXP+pe0bnPS1/+i+gju98rx4v\n", |
|
1418 | 1416 | "7czeXuL+0ijin9cn7+Nv/9TQ2TKOUizWcO/Tc6sMS4nLn1z59Zt1PA/PFsu8VhWOKNP+t8+9rojO\n", |
|
1419 | 1417 | "ROTG823graNFjdtWyxJvS1WiP/EsnMM7Tctas9Bpve97vRP973J/lFrpOjj9uah+2dmO8beXQp/v\n", |
|
1420 | 1418 | "3Mln3Hx3lv/5++0zyXJ1ud+2CP+8necX3Ifch638K91VVt7vuOPud93fuI+4q901drWccL/nft/9\n", |
|
1421 | 1419 | "gb0hzbHa/BlvVXusbP0jwn9otflj9/3uF+2NaoG73t3g/sLeGv/enstfdS9bS1+xp/RCu3Pc5P7W\n", |
|
1422 | 1420 | "Pedudn9lb0S6Nz1k7f2ivV1Mtdr3WYxnug9YW5e5j7md7i63y93iFrk33Dfcg9bn/tTa9XV3v40V\n", |
|
1423 | 1421 | "3uvOdZ9zx6zHjLkvu0/buOtZqavdq9Z7honI3e497in3K+6Xjatv2ojhp6xHf8ld6n7T/Yy7xD3v\n", |
|
1424 | 1422 | "VrvPGIfvt3fcJ91vuBesl71p7/prLbojxkLb3Wq9Yb17n3vC/bnb4LvcP7gfcf/oNrrLrYd027vo\n", |
|
1425 | 1423 | "qLvH3et+yb1ld6eL3L+4f3X/5A67R91PuvvcZhsTTrdRRK873092L7pzbOy7xe5Uj9to5bfcr7pn\n", |
|
1426 | 1424 | "bGz4a+4rbprbaiOfP3G3ub90D7hZ7jL3bhsXvWTjytvdt9zF7t/cP7vX3efdu9y33R3uE+6T7lPu\n", |
|
1427 | 1425 | "gPF7p9vmPu62u79zR90Pux3ur92Fforv9j2+10/10/x0P8PP9Of4c/15/nx/gb/QX+Tf5S92j/lL\n", |
|
1428 | 1426 | "/KXuJ/y7bWT3AzYS/4L7afdjNhb/df8eG7P+rI3Ofshf7t/rZ/n3+ZL7L/9+d9Jf4T/gP+g/5D/s\n", |
|
1429 | 1427 | "r7QR1Uf81e7f/TV+tr/Wz/Ef9XP9PD/fX+cX+Ov9DT7woY/8Qn+jv8nf7G/xH/OLfJ9f7Je4//RL\n", |
|
1430 | 1428 | "/TK/3K/wK/0qv9qv8Wv9rX6dX+83+I1+k9/st/it7r/9bd752/0d/k6/zX/cb/c7/F02Uv4Pv8uX\n", |
|
1431 | 1429 | "/W5f8f0+9nv8gB/0iU9tTF71Q77m6zZ6vts3fNO3fNuP+L1+nx913/H7/T3+Xn+f/4Q/4D/pP2Uj\n", |
|
1432 | 1430 | "20/7+/1B/4B/0B/yn/Gf9Z/zn3cfdN83ZU6tXa12D5UrjXrtnOG4kdT7bXDFiGnysnajPnWgUR6J\n", |
|
1433 | 1431 | "51TKw1PLlXaL1DmVpFFpD+2pxvvYUSnbwR2pcrU1tZVU+8k8oz+xwppJUz+m5SdSsqddS+bOXxJN\n", |
|
1434 | 1432 | "3d2I8xP0NpLagBLnDbZrA+VGe6habre0YWZ/vVWuqF76Nb1SHxoq57/P7UjrvFOWxtVWmbKvixbk\n", |
|
1435 | 1433 | "331R/r14ydTyniS5Yd78MJoaN1vJULkV92vf8nD5cn3Pnz/v+uI76unL69rdRwV7+uoD9VqcTV8y\n", |
|
1436 | 1434 | "0fhpS07Vq3spTbevRr3c6l7Gr55lRRHLKGLaslPZe5YVpa3oKG3Fqd0zVnQ0a/rKiTyTV+4uN7pX\n", |
|
1437 | 1435 | "EdyeVXnp01ZNFLuqKHb1xCEz1nSU1b0WErvXUr8Zazt2TV5rxXSvy/evy/ev69jfs75ozHoaM3N9\n", |
|
1438 | 1436 | "J0ndm/LjNuXHbeo85WZ2Td/cUaXNnfu35Mds6TwXfWNe3+Qtau7WvLlbi/Nv5fxTtqq3zNzaWYue\n", |
|
1439 | 1437 | "rUXzb5841/Q7J9Ld26jKtG0TASsXhZZzkstFAZUOWioTJPfnJPfnJMc5yXFRRJyTHE8UHhelDXSU\n", |
|
1440 | 1438 | "NjBB8kAnyYMdJA+q1Une6iQvvSfJy+q1w6txs5lOTzvimXXGs5pTUc3DWu2kuCqKa/n+Wr6/1lmJ\n", |
|
1441 | 1439 | "Wnm43mw16sODcU+9aFY9p7t+Gt0NypjR6DxvIw9OM6e72VG9Zme2Vn7e1nfTvXhySw1v5w1vF+dv\n", |
|
1442 | 1440 | "53S3obt9Gt3tIr57O+ge7aB7f073/lMhn7Rq9aQk5XRz+5YW33NPzd65cQeZPZ9m2VPfL12+dos9\n", |
|
1443 | 1441 | "y/gXrk+eZI/P4kbNtuX5vO2bxHevfWrknN97YvzPvdK10Pd23dt11C+c/J0p39bfpKWT1k3aMmms\n", |
|
1444 | 1442 | "90TX3N5ne7/MH7m7FhZ/9/J3NP/Tcd3f6Lmt5yv66x3hmBP61/jsbFPsidxj577Q3guuxsFzg717\n", |
|
1445 | 1443 | "5O8bI/asP2ZP/uP2FvE1e3t4071VPB/Hn2n5U2z86aUn1hq/s3i+DPMMGbNnubwdcnbI1yFXhzwd\n", |
|
1446 | 1444 | "cmjIUXH85EtyRMgPITcEDoQZ6IalGpZmWIph6YXlQpIHSatqWi/TapnWyqR9XXzWc8g1Is+IHCPy\n", |
|
1447 | 1445 | "i8hnIX+FnCLbKfEAHhE5ROQPkTtE3hDpVuULkStEnhA5QuQHkRtEXhDVWz4QuUDkAZEDRP4PuT/k\n", |
|
1448 | 1446 | "/ZDzQ/pPqT9RU3a0z+ogp4d8HnJ5yOMhh4f8HXJ3yNshZ4d8HXJ1yNMhR4f8HHJzyMshJ4d8HHJx\n", |
|
1449 | 1447 | "yMOBRvGAHafYTUIFfIy5ZWmAp6MBlgJY+t8TllMr4loP12q41sKHbdvd9pHe9xr0vlL7SlMqpa90\n", |
|
1450 | 1448 | "vlL5SuMrha/0vVL3KkZS9krXK1WvNL1S9ErPKzWvtLxS8kqhqhUIrT9o9UFrD1p50LqD1hu02qC1\n", |
|
1451 | 1449 | "Bq00aJ1BqwxaY9AKg9YXtLqgtQWtLGhdQasKWlOQNncSSlnpZM/DISenm9xx8sbJGSdfnFxx8sTJ\n", |
|
1452 | 1450 | "ESe9odSG0hpKaSidoVSG8sCdi3dNTjT51uRak2dNjjX51eRWewvtXTfaPCnzpMuTKk/+tA340+RO\n", |
|
1453 | 1451 | "kzdNzjT50uRKkydNjjT50eTUkkNLTjT50ORCkwdNDjT5z+Q+k/dM6mxps+U6k5JdjjP5zeQ2k9dM\n", |
|
1454 | 1452 | "TjP5zOQyk8dsnF25y+Qtk7NMvjK5yuQpk6NMfjK5yeQlkzpD2gwpM6TLkCpDmgwpMqTHkBpDWgwp\n", |
|
1455 | 1453 | "MaTDkApDGgwpMKS/0FqztBdSXkh3odV0raVrJf3M3iWdhVQW0lhIYSF9hdQV0lZIWaG1ZznAbsZ1\n", |
|
1456 | 1454 | "JM+RHEfyG8ltJK+RnEbyGcllJNeO3DryF22nlx45aw+Vn+jte+QR/ENyD8k7JOeQfENyDckz9DpX\n", |
|
1457 | 1455 | "7LdQQ0gLISWEdBBSQZytx0r50NErUTywpmcfaR2kdJDOQSoHaRxGuVovxf1z81nvdPJFyBUhT4Qc\n", |
|
1458 | 1456 | "EfITyEcgL4ScEPJByAUhD4QcEPI/yP0g70PeX57A9SDPgxwP8jvI7fAUV8thfA5yOcjjIIeD/A1y\n", |
|
1459 | 1457 | "N8jbIGfDG9yTJ+6w0iJIiSAdglQI0iBIgSD9gdQHeX94At2BVAfSHEhxIL2B1AbSGkhpkHN9xEaX\n", |
|
1460 | 1458 | "a22crLH4iI1MD9r3IRuVPWSfhy39iH2O2OdZez4dtTHvc/Z53vYds88L9pGOQCoCaQikIJB+QOoB\n", |
|
1461 | 1459 | "aQekHJBuQKoBaQYOWH6dbYP0AlILSCsgpYB0AlIJSCMghYD0AVIHSBsgZYB0AVIFoAmQIkB6AKkB\n", |
|
1462 | 1460 | "0ALYRzoAqQCkAZACQOv/B6ys2f+vd9C1/wd3UY3cZ2lVVmuyWpHVeqxWY7UWy0qs1mG1Cqs1WK3A\n", |
|
1463 | 1461 | "av1Vq69l2jyL+/BLeBQm0WrV+EJ8E3JNyDMhx4T8EnJLyCshp4R8Ep1PSa2uam1VK6taV9WqqtZU\n", |
|
1464 | 1462 | "8xXV/J1Kf+5/AIGHtqIKZW5kc3RyZWFtCmVuZG9iagoyMCAwIG9iago3MDc0OQplbmRvYmoKMTkg\n", |
|
1465 | 1463 | "MCBvYmoKMTI3MzQwCmVuZG9iagoxNSAwIG9iago8PCAvRmlsdGVyIC9GbGF0ZURlY29kZSAvTGVu\n", |
|
1466 | 1464 | "Z3RoIDY3ID4+CnN0cmVhbQp4nO3NMQ0AIQAEwVNMTYKOV4AZKhosIOQxQUNmuq02uWynZ2WmpWac\n", |
|
1467 | 1465 | "LreHAAAAAAAAAAAAAAAAAAAAAPCY7weB+gXnCmVuZHN0cmVhbQplbmRvYmoKMTggMCBvYmoKPDwg\n", |
|
1468 | 1466 | "L0ZpbHRlciAvRmxhdGVEZWNvZGUgL0xlbmd0aCAyNjEgPj4Kc3RyZWFtCnicXVE9b8MgEN35FTem\n", |
|
1469 | 1467 | "Q0Rst5UHC6lKFw9Jq7qdogw2HBZSDQjjwf++fCRu1ZPg6T7ece+gx/a11coDfXeGd+hBKi0czmZx\n", |
|
1470 | 1468 | "HGHAUWlSlCAU9zcv3XzqLaGB3K2zx6nV0pCmAfoRkrN3K+xehBnwgQAAfXMCndIj7L6OXQ51i7Xf\n", |
|
1471 | 1469 | "OKH2cCCMgUAZ2p16e+4nBJrI+1aEvPLrPtB+Kz5Xi1Amv8gjcSNwtj1H1+sRSXMIxqCRwRhBLf7l\n", |
|
1472 | 1470 | "q8wa5FZexfIAzwwuf9wiQ5mhyvCY4enOuKYGdXbrW4M6hsuyiNQMl4zXOM/95Tha3OOmmy/OBclp\n", |
|
1473 | 1471 | "2UlrVKk0bv9hjY2seH4AHtCFLgplbmRzdHJlYW0KZW5kb2JqCjEzIDAgb2JqCjw8IC9DSURUb0dJ\n", |
|
1474 | 1472 | "RE1hcCAxNSAwIFIgL0ZvbnREZXNjcmlwdG9yIDEyIDAgUiAvQmFzZUZvbnQgL0F2ZW5pci1Cb29r\n", |
|
1475 | 1473 | "Ci9DSURTeXN0ZW1JbmZvIDw8IC9PcmRlcmluZyAoSWRlbnRpdHkpIC9TdXBwbGVtZW50IDAgL1Jl\n", |
|
1476 | 1474 | "Z2lzdHJ5IChBZG9iZSkgPj4KL1N1YnR5cGUgL0NJREZvbnRUeXBlMiAvVyAxNyAwIFIgL1R5cGUg\n", |
|
1477 | 1475 | "L0ZvbnQgPj4KZW5kb2JqCjE0IDAgb2JqCjw8IC9FbmNvZGluZyAvSWRlbnRpdHktSCAvQmFzZUZv\n", |
|
1478 | 1476 | "bnQgL0F2ZW5pci1Cb29rCi9EZXNjZW5kYW50Rm9udHMgWyAxMyAwIFIgXSAvU3VidHlwZSAvVHlw\n", |
|
1479 | 1477 | "ZTAgL1RvVW5pY29kZSAxOCAwIFIgL1R5cGUgL0ZvbnQKPj4KZW5kb2JqCjEyIDAgb2JqCjw8IC9E\n", |
|
1480 | 1478 | "ZXNjZW50IC0zNjYgL0ZvbnRCQm94IFsgLTE2NyAtMjg4IDEwMDAgOTQwIF0gL1N0ZW1WIDAgL0Zs\n", |
|
1481 | 1479 | "YWdzIDMyCi9YSGVpZ2h0IDAgL1R5cGUgL0ZvbnREZXNjcmlwdG9yIC9Gb250RmlsZTIgMTYgMCBS\n", |
|
1482 | 1480 | "IC9Gb250TmFtZSAvQXZlbmlyLUJvb2sKL01heFdpZHRoIDY4MiAvQ2FwSGVpZ2h0IDAgL0l0YWxp\n", |
|
1483 | 1481 | "Y0FuZ2xlIDAgL0FzY2VudCAxMDAwID4+CmVuZG9iagoxNyAwIG9iagpbIDQ4ClsgNTY5LjMzMzMz\n", |
|
1484 | 1482 | "MzMzMzMgNTY5LjMzMzMzMzMzMzMgNTY5LjMzMzMzMzMzMzMgNTY5LjMzMzMzMzMzMzMKNTY5LjMz\n", |
|
1485 | 1483 | "MzMzMzMzMzMgNTY5LjMzMzMzMzMzMzMgNTY5LjMzMzMzMzMzMzMgXQo1NiBbIDU2OS4zMzMzMzMz\n", |
|
1486 | 1484 | "MzMzIF0gODcyMiBbIDY4MiBdIF0KZW5kb2JqCjMgMCBvYmoKPDwgL0YxIDE0IDAgUiA+PgplbmRv\n", |
|
1487 | 1485 | "YmoKNCAwIG9iago8PCAvQTEgPDwgL0NBIDAgL1R5cGUgL0V4dEdTdGF0ZSAvY2EgMCA+PgovQTIg\n", |
|
1488 | 1486 | "PDwgL0NBIDEgL1R5cGUgL0V4dEdTdGF0ZSAvY2EgMSA+PiA+PgplbmRvYmoKNSAwIG9iago8PCA+\n", |
|
1489 | 1487 | "PgplbmRvYmoKNiAwIG9iago8PCA+PgplbmRvYmoKNyAwIG9iago8PCA+PgplbmRvYmoKMiAwIG9i\n", |
|
1490 | 1488 | "ago8PCAvQ291bnQgMSAvS2lkcyBbIDEwIDAgUiBdIC9UeXBlIC9QYWdlcyA+PgplbmRvYmoKMjEg\n", |
|
1491 | 1489 | "MCBvYmoKPDwgL0NyZWF0aW9uRGF0ZSAoRDoyMDE0MDIyMDE3NTMyNS0wNycwMCcpCi9Qcm9kdWNl\n", |
|
1492 | 1490 | "ciAobWF0cGxvdGxpYiBwZGYgYmFja2VuZCkKL0NyZWF0b3IgKG1hdHBsb3RsaWIgMS4xLjEsIGh0\n", |
|
1493 | 1491 | "dHA6Ly9tYXRwbG90bGliLnNmLm5ldCkgPj4KZW5kb2JqCnhyZWYKMCAyMgowMDAwMDAwMDAwIDY1\n", |
|
1494 | 1492 | "NTM1IGYgCjAwMDAwMDAwMTYgMDAwMDAgbiAKMDAwMDA3MzYzOCAwMDAwMCBuIAowMDAwMDczNDQ0\n", |
|
1495 | 1493 | "IDAwMDAwIG4gCjAwMDAwNzM0NzYgMDAwMDAgbiAKMDAwMDA3MzU3NSAwMDAwMCBuIAowMDAwMDcz\n", |
|
1496 | 1494 | "NTk2IDAwMDAwIG4gCjAwMDAwNzM2MTcgMDAwMDAgbiAKMDAwMDAwMDA2NSAwMDAwMCBuIAowMDAw\n", |
|
1497 | 1495 | "MDAwMzg4IDAwMDAwIG4gCjAwMDAwMDAyMDggMDAwMDAgbiAKMDAwMDAwMTMzMyAwMDAwMCBuIAow\n", |
|
1498 | 1496 | "MDAwMDczMDYwIDAwMDAwIG4gCjAwMDAwNzI3MTIgMDAwMDAgbiAKMDAwMDA3MjkxOSAwMDAwMCBu\n", |
|
1499 | 1497 | "IAowMDAwMDcyMjM5IDAwMDAwIG4gCjAwMDAwMDEzNTMgMDAwMDAgbiAKMDAwMDA3MzI3NyAwMDAw\n", |
|
1500 | 1498 | "MCBuIAowMDAwMDcyMzc4IDAwMDAwIG4gCjAwMDAwNzIyMTYgMDAwMDAgbiAKMDAwMDA3MjE5NCAw\n", |
|
1501 | 1499 | "MDAwMCBuIAowMDAwMDczNjk4IDAwMDAwIG4gCnRyYWlsZXIKPDwgL0luZm8gMjEgMCBSIC9Sb290\n", |
|
1502 | 1500 | "IDEgMCBSIC9TaXplIDIyID4+CnN0YXJ0eHJlZgo3Mzg0OQolJUVPRgo=\n" |
|
1503 | 1501 | ], |
|
1504 | 1502 | "image/png": [ |
|
1505 | 1503 | "iVBORw0KGgoAAAANSUhEUgAAAJgAAABWCAYAAAAzIF/lAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\n", |
|
1506 | 1504 | "AAALEgAACxIB0t1+/AAACutJREFUeJzt3X1QE2ceB/BfNuHFsCExQDFECjqAhRa1DGOtAvbUuU4t\n", |
|
1507 | 1505 | "teDUcQbbcDiTq1d7nSLT8bBjcuBh5WxBGRDB8eWOl/MG5uwInt6LN+Xl5uxdC7aQVAJnLeYAiRJI\n", |
|
1508 | 1506 | "NrxE2L0/2vRiJkE27FJz/D4zzJjdfXYfnO/sbvbHs4+AYRhAiC/ED90B9P8NA4Z4hQFDvMKAIV5h\n", |
|
1509 | 1507 | "wBCvMGCIV6LZVtpsNllZWVl9fHx8S0ZGRrHRaEyoqqqqJghiRqlU3lSr1XsFAgFTU1NzrLe3dz3D\n", |
|
1510 | 1508 | "MIRKpdofGxv76UL9AujxNmvA6uvrjz777LOXJycnSQCAmpqaD/Py8l6TyWRDTU1NeW1tba8HBwcP\n", |
|
1511 | 1509 | "EwRBFxYWpo6Pj0uLi4svFRQUbFqY7qPH3awBU6vVe/V6/SaDwbDebrcv8ff3H5fJZEMAAGlpaTV1\n", |
|
1512 | 1510 | "dXXFUqn0bmpqai0AgFgsHouMjNSZTKaosLCwb1z3d+3aNXyq6+O2bNkiYLP9rAFzRlHUUpIkRxyf\n", |
|
1513 | 1511 | "JRLJPYqi5EKh8AFJkvddl7sLGABAUlISm/49pKmpCV555RVs/wO17+joYN1mzgEjSdJMUZTc8dli\n", |
|
1514 | 1512 | "sYSRJDlCkuSI1WoNlcvlAwAAVqs1VCKR3Pe8J3aGrFMwNf3tiS905dPwjXnyofViPwLCSH+uDoc4\n", |
|
1515 | 1513 | "NueA+fv7T9jt9iVms1mxdOnSwdbW1jcSExP/KpVKh9vb23dHRUV9abPZZEajMSE0NLSfqw623x6F\n", |
|
1516 | 1514 | "6k8HnJaMPbS+8McrMWCPsTkFTCAQMAAAKpUqr6SkpIEgiJnly5d/tX379g8BALq6urZqNJo2hmGI\n", |
|
1517 | 1515 | "7Ozsd/nsMPItjwxYQkJCS0JCQgsAgFKpvHn48OEU12127959gI/OId+3qB60xsXFYfsFtqgCtmrV\n", |
|
1518 | 1516 | "Kmy/wBZVwNDCm/O3SAe73R5YUVHxG4vFEkbTtHDHjh1FISEhRnclJD46jHwL64ANDw+vJEnSnJub\n", |
|
1519 | 1517 | "u+vu3bsrGxsbtRaLJcy1hJSWllbDR4eRb2F9iVy+fLnebrcvyc3N/Uqr1ba++uqrR11LSN3d3Zu5\n", |
|
1520 | 1518 | "7yryRazPYDdv3twYEBBgKy0tjTcajQnnzp0rCw8Pv+VYL5FI7js/8UeLG+szWE9Pz8b169c3AHx7\n", |
|
1521 | 1519 | "NgMAsFqtIY71Fosl1LlmiRY31gFTKpU39Xr9CwAAZrNZQRDEzIMHDwLNZrMCAMBRQuK4n8hHsb5E\n", |
|
1522 | 1520 | "JicnX+rq6tqq1WpbCIKgc3Jy3hEKhQ/clZAQYh0wAICcnJx3XJe5KyEhhA9aEa8wYIhXGDDEK6/u\n", |
|
1523 | 1521 | "wQAAPv/88/TBwcG49PT0Ek+jjbjsKPJNXp3BJicnSYPB8Hx6enoJwP9GGxUUFGxSKBSGtra217nt\n", |
|
1524 | 1522 | "JvJVXgXswoULv7p9+/bajz76qPHOnTtPY6kIecL6Ejk4OBhL07QwPz//5dHR0WUnTpz4nUKhMDjW\n", |
|
1525 | 1523 | "Y6kIOWN9Buvs7Hxp3bp1fwAAkMlkQxKJ5B6WipAnrAMmkUju63S6zQAAExMTktHR0WVYKkKesL5E\n", |
|
1526 | 1524 | "bty48cLp06crtVptKwBAVlZWvkQiuYelIuQO64ARBDHz5ptv/tR1OZaKkDv4oBXxCgOGeIUBQ7zy\n", |
|
1527 | 1525 | "ulRkMpmitFpt6/79+3cGBgZSWCpC7nh1BqNpmvj444/zU1JS6hmGEWCpCHniVcCam5vztm7dWuXn\n", |
|
1528 | 1526 | "5zfJMAyBpSLkCeuA9fX1rWMYRrBixYpOgG/PZi4vpsNSEfoe63uw7u7uzT09PRsMBsPzAwMDT3V0\n", |
|
1529 | 1527 | "dLzs/D4wLBUhZ6wDlpGRcdTx74aGBu3atWuvNjY2alxfTMdtN5Gv8vpbpDNPL6ZDaF4B27lzZ4Hj\n", |
|
1530 | 1528 | "31gqQu7gg1bEKwwY4hUGDPGK9T0YTdPEmTNnKoxG49M0TRO7du06JJPJ7mKpCLnDOmD9/f2rFQqF\n", |
|
1531 | 1529 | "Qa1W/2x8fFxaUlLSIBQKp/EFdMgd1pfI6OjoG+np6aUAAFNTU+KgoKDRgIAAG5aKkDte34NRFCWv\n", |
|
1532 | 1530 | "qqo6vW3btuNBQUFmx3IsFSFnXgVsbGzsifLy8t9mZ2fnrlixotNlDiMsFaHvsQ7YyMhIxMmTJ8/v\n", |
|
1533 | 1531 | "2bPnbYVC0es8hxEAjipCD2N9k9/c3JxnMpmiKisrzwEAkCQ5gqUi5AnrgKlUqjyVSpXnuhxLRcid\n", |
|
1534 | 1532 | "RfWgtaenB9svsEUVMIPB8OiNsD2nFlXA0MLj5O/BAABqamqO9fb2rmcYhlCpVPtjY2M/5WrfyHdx\n", |
|
1535 | 1533 | "cga7cePGiwRB0IWFhan5+fnbamtrf83FfpHv4+QMptPpfpSamloLACAWi8ciIyN1JpMpKiws7Bsu\n", |
|
1536 | 1534 | "9j+bQBEBXwxaPa5/IsgfFMEBfHfjsTBomYJhm93j+rDohZ8vkpOAURQlJ0nyvuOzRCK5R1GU3F3A\n", |
|
1537 | 1535 | "Ojo6WO17JQAcTfK8nh7qnbX94Hc/AABKpZL18Z35ent/YP//P1+cBIwkyRGr1Roql8sHAACsVmuo\n", |
|
1538 | 1536 | "RCK577rdli1bBFwcD/kOTu7BEhMTr7W3t+8GALDZbDKj0ZjgPJQNLV4ChuHm7wLr6uqKe3p6NjAM\n", |
|
1539 | 1537 | "Q2RnZ78bExPzL052jHwaZwFDyB180Ip4hQFDvOLsSf5c6PX6tOPHj//+2LFja6RS6TAAwOXLl9+9\n", |
|
1540 | 1538 | "fv36TpqmiczMzA+Sk5MvuWvrTaXAZrPJysrK6uPj41syMjKK2U55M98BLjMzM6JTp06dGRoaivH3\n", |
|
1541 | 1539 | "9x//bhpEAZs+zOc9bDk5OSPR0dFfAACsWbPmanJychPbwTnznjKIYZgF+TGZTJEVFRXnTpw4UWc2\n", |
|
1542 | 1540 | "m8MZhgGj0fhUaWnpBYZhYHp6WqTRaFqnpqYCXdt2dna+WFtbW8wwDNhsNqlGo2mZyzGrq6tPXbly\n", |
|
1543 | 1541 | "Zd/FixcPMAwDR44c+aPZbF7GMAxcunQpr6Wl5Y3Z2n/99ddrm5qach3HPXz48J/Z7MNms0l1Ot0m\n", |
|
1544 | 1542 | "x+9fVlZWw6b9zMwMUV1dfaquru4Dg8HwHNv+FxUVXXH+zLb9xMQEWV9fX+Rte4ZhFu4SGRoaeuet\n", |
|
1545 | 1543 | "t97KEYlEdkfqdTrdCykpKXUAAEKhcDopKam5r6/vOde2nioFjzqmWq3e++STT3YDANjt9iVs32M2\n", |
|
1546 | 1544 | "3wEuYrF4LCEhoQUAwGQyRUul0mE27ef7Hrb+/v5ErVbbWlhYeM1kMkWxbc/FlEGcXyIHBgZWnT9/\n", |
|
1547 | 1545 | "/rjzMqlUenffvn0/cd2Woih5VFTUl47PjgqAu+3mWinwhKKopd6+x8wxwCUzM/PIJ5988v3vMdd9\n", |
|
1548 | 1546 | "FBUV/WloaCimoKAgtaGh4Zdzae/8HrbPPvtsuzfvYSsvL18pEonsfX19606ePHmezZQ/XE0ZxHnA\n", |
|
1549 | 1547 | "IiIieg4ePPjSXLZ1VAAcny0WS9iyZcv6PG33qErBI45l9mZwytjY2BOVlZVns7Ozc0NCQozNzc37\n", |
|
1550 | 1548 | "2e7j/ffff3FgYCDu7Nmz5QKBgJ5Ley7ewyYSiewAADExMf8UiUR2NlP+cDVl0A/yLZJhGAEAwDPP\n", |
|
1551 | 1549 | "PPO39vb2LACA6elpv87Ozm3ubt65qBR4MzhlvgNcDAbD83q9Pg0AIDg4+N7U1JR4rtPuZGRkHD1w\n", |
|
1552 | 1550 | "4MD29957L3PDhg0X9uzZ83M2x+7t7X3u+vXrrwEA3Lp1K0kul/+HzZQ/XE0ZtKDfIh0c92ARERGG\n", |
|
1553 | 1551 | "uLi4fxw6dOjvNE0TO3bsKPLz85ty3X716tV/6erq2qrRaNoclQJvjsd2cMp8B7iEh4f/u7Ky8ux3\n", |
|
1554 | 1552 | "l0VBVlbWL8Ri8Zi3A2TYHFupVH518eLFg1evXn2bJMkRtVq9l6Io+VzbczVlED7JR7zCB62IVxgw\n", |
|
1555 | 1553 | "xCsMGOIVBgzxCgOGeIUBQ7z6LzWkj3n7AHKHAAAAAElFTkSuQmCC\n" |
|
1556 | 1554 | ], |
|
1557 | 1555 | "text/plain": [ |
|
1558 | 1556 | "<matplotlib.figure.Figure at 0x10b0ecf10>" |
|
1559 | 1557 | ] |
|
1560 | 1558 | }, |
|
1561 | 1559 | "metadata": {}, |
|
1562 | 1560 | "output_type": "display_data" |
|
1563 | 1561 | } |
|
1564 | 1562 | ], |
|
1565 | 1563 | "source": [ |
|
1566 | 1564 | "plt.hist(evs.real)" |
|
1567 | 1565 | ] |
|
1568 | 1566 | }, |
|
1569 | 1567 | { |
|
1570 | 1568 | "cell_type": "markdown", |
|
1571 | 1569 | "metadata": {}, |
|
1572 | 1570 | "source": [ |
|
1573 | 1571 | "```python\n", |
|
1574 | 1572 | "def foo(bar=1):\n", |
|
1575 | 1573 | " \"\"\"docstring\"\"\"\n", |
|
1576 | 1574 | " raise Exception(\"message\")\n", |
|
1577 | 1575 | "```" |
|
1578 | 1576 | ] |
|
1579 | 1577 | } |
|
1580 | 1578 | ], |
|
1581 | 1579 | "metadata": { |
|
1582 | 1580 | "signature": "sha256:9fffd84e69e3d9b8aee7b4cde2099ca5d4158a45391698b191f94fabaf394b41" |
|
1583 | 1581 | }, |
|
1584 | 1582 | "nbformat": 4, |
|
1585 | 1583 | "nbformat_minor": 0 |
|
1586 | 1584 | } No newline at end of file |
@@ -1,145 +1,306 b'' | |||
|
1 | 1 | { |
|
2 | "metadata": { | |
|
3 | "name": 0 | |
|
4 | }, | |
|
5 | "nbformat": 3, | |
|
6 | "nbformat_minor": 0, | |
|
7 | "worksheets": [ | |
|
2 | "cells": [ | |
|
8 | 3 | { |
|
9 | "cells": [ | |
|
10 | { | |
|
11 | "cell_type": "heading", | |
|
12 | "level": 1, | |
|
13 | "source": [ | |
|
14 | "nbconvert latex test" | |
|
15 | ] | |
|
16 | }, | |
|
17 |
|
|
|
18 | "cell_type": "markdown", | |
|
19 | "metadata": {}, | |
|
20 | "source": [ | |
|
21 | "**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus bibendum felis dictum sodales. Ut suscipit, orci ut interdum imperdiet, purus ligula mollis *justo*, non malesuada nisl augue eget lorem. Donec bibendum, erat sit amet porttitor aliquam, urna lorem ornare libero, in vehicula diam diam ut ante. Nam non urna rhoncus, accumsan elit sit amet, mollis tellus. Vestibulum nec tellus metus. Vestibulum tempor, ligula et vehicula rhoncus, sapien turpis faucibus lorem, id dapibus turpis mauris ac orci. Sed volutpat vestibulum venenatis." | |
|
22 | ] | |
|
23 | }, | |
|
24 | { | |
|
25 | "cell_type": "heading", | |
|
26 | "level": 2, | |
|
27 | "metadata": {}, | |
|
28 | "source": [ | |
|
29 | "Printed Using Python" | |
|
30 | ] | |
|
31 | }, | |
|
32 |
|
|
|
33 | "cell_type": "code", | |
|
34 | "collapsed": false, | |
|
35 | "input": [ | |
|
36 | "print(\"hello\")" | |
|
37 | ], | |
|
38 | "language": "python", | |
|
39 | "outputs": [ | |
|
40 | { | |
|
41 | "output_type": "stream", | |
|
42 | "stream": "stdout", | |
|
43 | "text": [ | |
|
44 | "hello\n" | |
|
45 | ] | |
|
46 | } | |
|
47 | ], | |
|
48 | "prompt_number": 1 | |
|
49 | }, | |
|
4 | "cell_type": "markdown", | |
|
5 | "metadata": {} | |
|
6 | }, | |
|
7 | { | |
|
8 | "cell_type": "markdown", | |
|
9 | "metadata": {}, | |
|
10 | "source": [ | |
|
11 | "**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus bibendum felis dictum sodales. Ut suscipit, orci ut interdum imperdiet, purus ligula mollis *justo*, non malesuada nisl augue eget lorem. Donec bibendum, erat sit amet porttitor aliquam, urna lorem ornare libero, in vehicula diam diam ut ante. Nam non urna rhoncus, accumsan elit sit amet, mollis tellus. Vestibulum nec tellus metus. Vestibulum tempor, ligula et vehicula rhoncus, sapien turpis faucibus lorem, id dapibus turpis mauris ac orci. Sed volutpat vestibulum venenatis." | |
|
12 | ] | |
|
13 | }, | |
|
14 | { | |
|
15 | "cell_type": "heading", | |
|
16 | "level": 2, | |
|
17 | "metadata": {}, | |
|
18 | "source": [ | |
|
19 | "Printed Using Python" | |
|
20 | ] | |
|
21 | }, | |
|
22 | { | |
|
23 | "cell_type": "code", | |
|
24 | "execution_count": 1, | |
|
25 | "metadata": { | |
|
26 | "collapsed": false | |
|
27 | }, | |
|
28 | "outputs": [ | |
|
50 | 29 | { |
|
51 | "cell_type": "heading", | |
|
52 | "level": 1000, | |
|
53 |
" |
|
|
54 | "source": [ | |
|
55 | "Pyout" | |
|
30 | "name": "stdout", | |
|
31 | "output_type": "bad stream", | |
|
32 | "text": [ | |
|
33 | "hello\n" | |
|
56 | 34 | ] |
|
57 |
} |
|
|
35 | } | |
|
36 | ], | |
|
37 | "source": [ | |
|
38 | "print(\"hello\")" | |
|
39 | ] | |
|
40 | }, | |
|
41 | { | |
|
42 | "cell_type": "markdown", | |
|
43 | "metadata": {}, | |
|
44 | "source": [ | |
|
45 | "## Pyout" | |
|
46 | ] | |
|
47 | }, | |
|
48 | { | |
|
49 | "cell_type": "code", | |
|
50 | "execution_count": 3, | |
|
51 | "metadata": { | |
|
52 | "collapsed": false | |
|
53 | }, | |
|
54 | "outputs": [ | |
|
58 | 55 | { |
|
59 | "cell_type": "code", | |
|
60 | "collapsed": false, | |
|
61 | "input": [ | |
|
62 | "from IPython.display import HTML\n", | |
|
63 | "HTML(\"\"\"\n", | |
|
64 | "<script>\n", | |
|
65 | "console.log(\"hello\");\n", | |
|
66 | "</script>\n", | |
|
67 | "<b>HTML</b>\n", | |
|
68 | "\"\"\")" | |
|
69 |
] |
|
|
70 | "language": "python", | |
|
56 | "data": { | |
|
57 | "text/html": [ | |
|
58 | "\n", | |
|
59 | "<script>\n", | |
|
60 | "console.log(\"hello\");\n", | |
|
61 | "</script>\n", | |
|
62 | "<b>HTML</b>\n" | |
|
63 | ], | |
|
64 | "text/plain": [ | |
|
65 | "<IPython.core.display.HTML at 0x1112757d0>" | |
|
66 | ] | |
|
67 | }, | |
|
68 | "execution_count": 3, | |
|
71 | 69 | "metadata": {}, |
|
72 | "outputs": [ | |
|
73 |
|
|
|
74 | "html": [ | |
|
75 | "\n", | |
|
76 | "<script>\n", | |
|
77 | "console.log(\"hello\");\n", | |
|
78 |
|
|
|
79 | "<b>HTML</b>\n" | |
|
80 | ], | |
|
81 | "metadata": {}, | |
|
82 | "output_type": "pyout", | |
|
83 | "prompt_number": 3, | |
|
84 | "text": [ | |
|
85 | "<IPython.core.display.HTML at 0x1112757d0>" | |
|
86 | ] | |
|
87 | } | |
|
88 | ], | |
|
89 | "prompt_number": 3 | |
|
90 |
|
|
|
70 | "output_type": "execute_result" | |
|
71 | } | |
|
72 | ], | |
|
73 | "source": [ | |
|
74 | "from IPython.display import HTML\n", | |
|
75 | "HTML(\"\"\"\n", | |
|
76 | "<script>\n", | |
|
77 | "console.log(\"hello\");\n", | |
|
78 | "</script>\n", | |
|
79 | "<b>HTML</b>\n", | |
|
80 | "\"\"\")" | |
|
81 | ] | |
|
82 | }, | |
|
83 | { | |
|
84 | "cell_type": "code", | |
|
85 | "execution_count": 7, | |
|
86 | "metadata": { | |
|
87 | "collapsed": false | |
|
88 | }, | |
|
89 | "outputs": [ | |
|
91 | 90 | { |
|
92 | "cell_type": "code", | |
|
93 | "collapsed": false, | |
|
94 | "input": [ | |
|
95 | "%%javascript\n", | |
|
96 | "console.log(\"hi\");" | |
|
97 | ], | |
|
98 | "language": "python", | |
|
91 | "data": { | |
|
92 | "application/javascript": [ | |
|
93 | "console.log(\"hi\");" | |
|
94 | ], | |
|
95 | "text/plain": [ | |
|
96 | "<IPython.core.display.Javascript at 0x1112b4b50>" | |
|
97 | ] | |
|
98 | }, | |
|
99 | 99 | "metadata": {}, |
|
100 | "outputs": [ | |
|
101 |
|
|
|
102 | "javascript": [ | |
|
103 | "console.log(\"hi\");" | |
|
104 | ], | |
|
105 | "metadata": {}, | |
|
106 | "output_type": "display_data", | |
|
107 | "text": [ | |
|
108 | "<IPython.core.display.Javascript at 0x1112b4b50>" | |
|
109 | ] | |
|
110 | } | |
|
111 | ], | |
|
112 | "prompt_number": 7 | |
|
113 |
|
|
|
114 | { | |
|
115 | "cell_type": "heading", | |
|
116 | "level": 3, | |
|
117 | "metadata": {} | |
|
118 | }, | |
|
100 | "output_type": "display_data" | |
|
101 | } | |
|
102 | ], | |
|
103 | "source": [ | |
|
104 | "%%javascript\n", | |
|
105 | "console.log(\"hi\");" | |
|
106 | ] | |
|
107 | }, | |
|
108 | { | |
|
109 | "cell_type": "markdown", | |
|
110 | "metadata": {}, | |
|
111 | "source": [ | |
|
112 | "### Image" | |
|
113 | ] | |
|
114 | }, | |
|
115 | { | |
|
116 | "cell_type": "code", | |
|
117 | "execution_count": 6, | |
|
118 | "metadata": { | |
|
119 | "collapsed": false | |
|
120 | }, | |
|
121 | "outputs": [ | |
|
119 | 122 | { |
|
120 | "cell_type": "code", | |
|
121 | "collapsed": false, | |
|
122 | "input": [ | |
|
123 | "from IPython.display import Image\n", | |
|
124 | "Image(\"http://ipython.org/_static/IPy_header.png\")" | |
|
125 | ], | |
|
126 | "language": "python", | |
|
123 | "data": { | |
|
124 | "image/png": [ | |
|
125 | "iVBORw0KGgoAAAANSUhEUgAAAggAAABDCAYAAAD5/P3lAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\n", | |
|
126 | "AAAH3AAAB9wBYvxo6AAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURB\n", | |
|
127 | "VHic7Z15uBxF1bjfugkJhCWBsCSAJGACNg4QCI3RT1lEAVE+UEBNOmwCDcjHT1wQgU+WD3dFxA1o\n", | |
|
128 | "CAikAZFFVlnCjizpsCUjHQjBIAkQlpCFJGS79fvjdGf69vTsc2fuza33eeaZmeqq6jM9vZw6dc4p\n", | |
|
129 | "BUwC+tE+fqW1fqmRDpRSHjCggS40sBxYDCxKvL8KzNBaL21EPoPB0DPIWVY/4NlE0ffzYfhgu+Qx\n", | |
|
130 | "GHoy/YFjaK+CcB3QkIIAHAWs3wRZsuhUSs0CXgQeBm7UWi/spn0Z+jA5yxpEfYruqnwYllRic5a1\n", | |
|
131 | "MaWv8U5gaT4M19Sx396IAnZLfB/SLkEMhp5O/3YL0AvoAHaKXl8HLlZK3QZcpbWe0lbJDOsaHuDU\n", | |
|
132 | "0e4u4JAy2wPk/C1JzrKWArOQ0fUtwH35MOysQxaDwbCO0NFuAXoh6wPjgQeUUvcqpUa0WyCDoQls\n", | |
|
133 | "CIwBjgfuAV7KWdY+7RWpmJxlXZezrEdylvXxdstiMKzrGAtCYxwI/EspdZbW+g/tFsbQ67kQuBHY\n", | |
|
134 | "FNgseh9FV6vCbUAeWBC9PgBeq2EfS6J2MQOBrRDTe5KdgAdzlvW1fBjeUUP/3UbOsoYBE6OvG7VT\n", | |
|
135 | "FoOhL9Af+BUwFLkZpV+DaY6V4UPkRpb1+ncT+m8nGwK/V0oN01qf025hDL2XfBi+DLycLMtZVo6u\n", | |
|
136 | "CsKfGnSq8/NheEpqHwOBEcDBwJnAsGhTP2ByzrJG5cPwnQb22Sy+0G4BDIa+RH+t9dmlNiqlFKIk\n", | |
|
137 | "JJWGi+jq5JPmq8BbJJQArfXqpkncczlbKbVQa/3rdgtiMNRCPgxXAK8Ar+Qs63LgXmDvaPPGwPeA\n", | |
|
138 | "H7VJvCRfbLcABkNfouwUg9ZaAwuj178BlFLvVejzgR4WFviM1npcuQpKqf6IyXIjxLS7GzAWuUnu\n", | |
|
139 | "XsO+fqWUellr3ZBJdq/jr9+BDn1uve07O9Rz0y6f8PtGZGgWe53oT6SBkZ/q1/nHZy47aloTRTKU\n", | |
|
140 | "IR+Gy3OWNR6Zxtg0Kv4KRkEwGPocxgcBiCwcsSI0F5iOhF+ilPok8C3gVGS+thK/VErdrbWuO2ys\n", | |
|
141 | "s/+aLZTuOKbe9krrIUCPUBB0B+PQ1P1bdKe6EzAKQgvJh+GbOct6gkJkxM45y+qXDIWMHBhjBWJe\n", | |
|
142 | "PgyDWvaRs6zPIVObAG/nw/DpEvUGAp8E9gGGJzbtl7Os7cvs4skqp0V0Yl8jgcOBjyMDhbmIZeWl\n", | |
|
143 | "fBg+UUVfReQsayhwELAnsAXi6/E28BxwTz4MP6iyn92RaSCA+/NhuCwqXx9R4MYhU0MfRTK/AjyW\n", | |
|
144 | "D8MFGd0ZDFVhFIQKaK3/BXxfKXUlklTq0xWafAI4Driyu2UzGLqRlygoCArYHJif2H4gcFb0+Z2c\n", | |
|
145 | "ZW2bD8NV1XScs6yNgH8g/jsAPwCeTmzfFPgjYsnbiez71MUVdnMQcF8V4nyUs6whwB8QX4+0s2Ys\n", | |
|
146 | "0yPAt/NhGFbRZ/wbzgO+DaxXotqqnGX9GbigCkXhf5CBCsDngYdzljURGQhsWqLN+znL+iFwdT4M\n", | |
|
147 | "dYk6BkNJTJhjlWitQ2Bf4P4qqv848t8wGHor6Yd9+ruHJFkC2BI4rIa+D6egHKwmstYlGAxMQCwH\n", | |
|
148 | "rRjEPI5ER5S7ZvcFXsxZ1phKneUsawSi8HyH0soB0bbvAM9Ebaplt5xlnYkct1LKAYiFZhJwSQ19\n", | |
|
149 | "GwxrMRaEGtBar1RKfRX4JxIzXortou3PN1mE+YgJsSwaeoLHOQCqUy3QSr9eqZ6G/gq2aYVMhqrY\n", | |
|
150 | "OfF5FeJwvJZ8GM7JWdY/gC9HRS7wtyr7Pjrx+e6MqYC3KLbU7Qhck/h+FJIKvRRVjfSREXicU8EH\n", | |
|
151 | "pgAvIIqLBZwGfC7avl5Uf29KkLOsTZCMq8npj9sQx89no37HIlaAODplNPBIzrJ2z4dhNVlaT0HC\n", | |
|
152 | "XwFmIkrAC4if2PaIz8/3KCgn385Z1pX5MJxeRd8Gw1qMglAjWutlSqnTgUcqVP0SzVYQtP5mcMXE\n", | |
|
153 | "SvvtUUy9YsK5QEWHy7EnTB6lOtSsFohkqEDOsgYAdqJoagkT9Z8pKAj75yzr4/kwnF2h748ho/GY\n", | |
|
154 | "q9J1oqiKLj4JOctKK8Yz8mH4Yrl9VcnHkXVYTsyHoZ8WJWdZNyPThbF5/3M5yzowH4alpi9+T0E5\n", | |
|
155 | "WA18Nx+Gf0zVeRG4KmdZ90R9bwCMRKwyX69C5h2j91uA4/JhuCSxbTYwJWdZtwNPIFbifsAFSISZ\n", | |
|
156 | "wVA1ZoqhDrTWjyIjjXIc3ApZDIZu4ELgY4nvt5Wody8wJ/qsgBOr6HsihfvOfCRrY7v5dYZyAECk\n", | |
|
157 | "GP0ISEZmZYZ55yxrB8SyEXNxhnKQ7Pt64H8TRUfmLGuXKmWeC4xPKQfJvp9CLCJlZTYYymEUhPq5\n", | |
|
158 | "tcL2XVsihcHQJHKWtU3Osi5GnAZj5iKWgiKitRouTxQdl7OscnPu0HV64dp8GLY7R8pyxEGxJPkw\n", | |
|
159 | "fBcZ9ceUSvN8IoV76upK/UZcgawcG3NKqYopfleFU+gDic/b5SzLWIwNNWFOmPqp5CG9sVJqPa11\n", | |
|
160 | "VZ7dBkOL2D1nWcmcBkOR8MFtgM/QdTXJZcCR+TBcXqa/SYj5egAFZ8VMX4ScZe2FRPnEXF2z9M3n\n", | |
|
161 | "3nwYVsrtAmK6/0z0uVR4ZXLtivvzYfhGpU7zYbgkZ1k3ACdHRQdWIQsUO3ZmkUzB3Q/xjaolLbeh\n", | |
|
162 | "j2MUhDrRWr+mlFpJ+eV5hyIxz4YWs98Fj/Rf8uZbozo0/ZYt7D8rf9ORK9stUw/hU9GrEnMAp1R+\n", | |
|
163 | "gph8GL4bzdNPiIpOorSzYtJ68FS1IYPdTLWp3hcnPm+Q3pizrA7E+TCmFn+aZN0dcpY1LB+G5e4b\n", | |
|
164 | "y6rM8bA49X39GmQyGMwUQ4NUGnkMrbDd0A3sdeLk4z6cN+89pTtDTWd+gyErF+7pTv5eu+XqJbyK\n", | |
|
165 | "TDHsmg/DJ6tsc2ni8+dzljUqXSGaevhmoqjIObFNVBzlV8kQug4W5tbQNl13WGatAv+poW+DoW6M\n", | |
|
166 | "BaExPgC2LrO9nHWhpSilDqI4NPMhrfXUJvS9M/DfqeJXtdY3N9p3rex50uQ9lFKT6BrTvoFCXbTX\n", | |
|
167 | "yZNfmnrZxHtbLVMP4xng74nvK5DzeD7wfIWRayb5MHwiZ1kzgF0oOCuemar2ZQoK8zLgr7Xup5t4\n", | |
|
168 | "s0n9DEl9b0RBSPeV5q0a+jYY6sYoCI1RacnZ91siRXUMAH6eKnsYicdulDOAY1NlpzWh35pRqG9R\n", | |
|
169 | "IuGN7uw4AfG878s8nw/DX3RDv5dScGY8NmdZP86HYXJaJzm9cHMp7/s2UHdK9BTpKaxBNbRN163k\n", | |
|
170 | "t9Rux05DH8FMMTTGZhW2v9sSKarjbopNk/sqpUY30qlSahCSGS/JCuD6RvqtF6UpMm/HaHTJbYaG\n", | |
|
171 | "mQzED/0umRVzlrUZhXwJ0HOmF5pJOlXyxzJrZbNt6rtZP8HQIzAKQp0opTZAlsItxTKtdTnv75YS\n", | |
|
172 | "LR7lpYqrjV0vx2EUH4fbtdZtucnpMqOrDjPy6jYii8DkRFHSYnAEhem22cBjrZKrVeTDcCldTf/p\n", | |
|
173 | "h345ksrEGprnF2EwNIRREOrnMxW2z2uJFLVxJcXmy2OVUo34ShydUda+EaIq7T2u0SZTY/eSdFY8\n", | |
|
174 | "MGdZm0efk86J6/LCQUnFp5pIkZjkcvQz8mH4YZPkMRgawigI9VNp7v7BlkhRA1rr+RQneNqC2hba\n", | |
|
175 | "WYtSajiS9z3JXLomaGktq/VllLIUdKqSWe0MjZMPwxlIel8Q/6Zv5CxrGIX8AJ10XU+hFtIRQ+UW\n", | |
|
176 | "KWoXyYyTu+Qsa79KDXKWNRpJyx5zZ9OlMhjqxCgIdaCU6g98o0K1npBCNotLM8rcOvuagCRgSXKN\n", | |
|
177 | "1rozq3IrCCZNfFkrfRjotWsCaJinUBODK51/tkuuPkTy/DoYOIDCfeb+fBjW4t2/lqhdcmRdbUri\n", | |
|
178 | "VnILXS2HZ1WRvfAcCk61K4A/dYdgBkM9GAWhPr5F6XSrIBf6Qy2SpSaidSReShV/XilV7veUIj29\n", | |
|
179 | "oOkB2fGmXT7x7sCbOGpFf7VZx4A1m0/znG2nehMyc+0bms7NFJxzxwH7J7Y1OvWUPG9/mLOsLRvs\n", | |
|
180 | "r6lEaaOT0TtfBB5ITLWsJWdZg3KWdRNwTKL4wnwYzu9mMQ2GqjFhjjWilBqBpJYtx51a66UV6rST\n", | |
|
181 | "S+maJz52VvxRdvVilFK7UbzexGNa67Kr+bWS6X+ekPYs79HkLGt34JOI+Xyz6D2d1vfMnGUdini6\n", | |
|
182 | "L0C851/Oh2HD+SyaQT4MV+YsaxJyLm1Gwf9gAXBHg93/JNHHtsArOcuajCztPBDYCkkytBXg5sOw\n", | |
|
183 | "5QmF8mF4W86yLgK+HxXtC8zKWVaALMm8CslHsicS7RFzL8VhyAZDWzEKQg0opbYE7qd8prPVdF2h\n", | |
|
184 | "rSdyLfALYMNE2XFKqR/XsHbEURll62L4Wiv5PuBUqPPF6JXkLuCQbpGoPi4HfohYKGMHWD9axrlu\n", | |
|
185 | "8mF4Z7RuwfioaDBwaonqRemQW0U+DH+Qs6xFwHnIFNwQsv+3mMnA8dHiVwZDj8FMMVSJUuow4DkK\n", | |
|
186 | "a7GX4gqt9cstEKlutNaL6boULMho5tBq2iul+lH8IFuCmJcNfZx8GM6hOCFVU5THfBhOQHxfylkH\n", | |
|
187 | "3gY+asb+6iUfhhcCewC3l5BlFbJk/P75MDwqlVTKYOgRKK1rizhSSk2h67ximo1abV5XSi2n9EIk\n", | |
|
188 | "z2itx5XYVqnfQcjI7DiqW2XtfeCTUbRA3ex50nWfUrqjeJEcrfcLrpj4SCN9xyilxgDPp4of0Fof\n", | |
|
189 | "UEXbg4B/pIqv1FrXnVNh7AmTR3V0qIwwRH1E4E28pd5+De0hZ1m/Bb4bfX0+H4Z7dMM+hgGjkDwC\n", | |
|
190 | "S5FpjFk9bR4/Z1mDkGmF4VHR20g4Y3oxJYOhR9EXphg6lFLlVjFbH0mZvDGwCTAayCFe0ntTOZ1y\n", | |
|
191 | "zDLgkEaVg1ahtX5BKfUU8OlE8ReUUjtorSstCduzch8YehSR5/6ERFG3nBvRuhE9frXUfBguA6pd\n", | |
|
192 | "+Mpg6DH0BQXBBro7o+Ea4Bta66e6eT/N5lK6KggKOAE4u1QDpdTGFOdNmNkLf7uh+zgYcRQEMa+3\n", | |
|
193 | "Je22wWBoDOOD0DhLgYla67vaLUgd3ETxglLHRXkeSnEExQ5gbQ9tNPQokis5TsqHoVlbwGDohRgF\n", | |
|
194 | "oTECYHet9Y3tFqQetNYrKDb/DqN46eYk6emF1UhUhMFAzrImUEhDvgr4VRvFMRgMDWAUhPpYAvwf\n", | |
|
195 | "8Bmte31+/8uQBEdJMjMrKqW2o5A2N+YfWusePw9s6F5yltWRs6zxwKRE8RXtyEVgMBiaQ1/wQWgm\n", | |
|
196 | "eWTe/jqtdU9Zz74htNavKaXuAw5KFB+glBqptZ6Tqj6RQlrYGDO90AfJWdY5wNeQFQwHIAmetk5U\n", | |
|
197 | "eZFCsiCDwdALMQpCed5AphEC4NF12BHvUroqCAoJ7TwvVS+d++BdJEmPoe+xKRLnn0UeODwfhm3N\n", | |
|
198 | "RWAwGBqjLygIbwN/LbNdI1MGH6ReL/eWkMUmcDeSeGa7RNlRSqnzdZQoQym1C7Bzqt11NWReNKxb\n", | |
|
199 | "zEMU6GHAesBiYCaSLOviaF0Cg8HQi+kLCsLrWuvT2y1ET0ZrvUYp5SG57mO2Bz4LPB59/2ZRQ5P7\n", | |
|
200 | "oM+SD8OLgYvbLYfBYOg+jJOiIeZKxOs8STJiIb28daC1/lf3imQwGAyGdmEUBAMA0XTKraniI5VS\n", | |
|
201 | "A6O0zOnloI31wGAwGNZhjIJgSHJp6vtgJBNlehW65cANLZHIYDAYDG3BKAiGtWitHwVeShV/muLF\n", | |
|
202 | "uW7VWi9qjVQGg8FgaAd9wUnRUBuXAn9IfN8f+FyqTo/OfbDnSX8brDpXnqEUe2ropzQvdtDx66ev\n", | |
|
203 | "GN9XolIMPQDb9T8LrBd4zsPtlsXQe7Bd/0BgQeA5QbtlMQqCIc21wC+ADaPv6WWu5wAPtVKgWtjt\n", | |
|
204 | "6Os2XG/9jhdQjIzTQ2rFF9bQecy4E2/I9UQlwXb9LYDDK1R7K/Cc21shj6FxbNcfDjwGKNv1Rwae\n", | |
|
205 | "83q7ZWo2tusPBb6ELGW9BbAICX99Gngs8Jx0hlZDBWzXHwvcC6ywXX9o4DlL2ymPURAMXdBaL1ZK\n", | |
|
206 | "+ZRItwz8Jc6N0BMZMFB9GxiZsWnzTjrPAH7QWomqYgTF/h9pngC6RUGwXf+XwC2B50ztjv57M7br\n", | |
|
207 | "XwJMCjxneo1NP0SWgAfJq7LOYLv+esAFwOkUL9wWM912/d0Dz+lsnWQ9A9v1BwEXAT8PPKfWVOML\n", | |
|
208 | "kPVt3kNWQm0rxgfBkEWph5UG/tJCOWqnQ40ttUkrvWcrRamWwHOmAZsguSfGAi9Hmy5AUhgPAz7f\n", | |
|
209 | "Hfu2XX8k8ENgx+7ovzdju/4uwP9D/peaCDxnCbANsF3gOYubLVu7sF1/AHAHcBaiHDwI/C+ywNsE\n", | |
|
210 | "4KfA68BdfVE5iNgbOBmxqtRE4Dn/BoYDnwg8Z02zBasVY0EwFKG1fkEp9RTioJjkIa11zzaVarYq\n", | |
|
211 | "vVFt2TpBaiN6oCwB5tiu/2FUPCvwnLTTaLM5oJv77800dGwCz1kXHXkvRNKydwI/Cjzn1+kKtuuf\n", | |
|
212 | "i2TX7Ks0et681yxBGsUoCIZSBBQrCL0h98EbdW7rddiuPwoYFJu/bdffFNgL2BZ4DZgWKR5ZbRWS\n", | |
|
213 | "2+KIqGiE7fpjUtXmlrtZRdaHscBAYDowM/CckimWbdffFfgw8JzXou/9kfUccojV5MXAcz4s0XYw\n", | |
|
214 | "sCsymu8PzAVmBJ7zVqn9pdoPRVKF7wSsAN4EgqzRve36HcAoZDEqgO0zjs3rged8kGo3gOJ05ADT\n", | |
|
215 | "s0bTkan+k9HXGaVGjNFxykVf81nH2Hb9Ich/MRJJeT291H9fL7brj6CwANfPspQDgOi3rijRx/rI\n", | |
|
216 | "b8kB7wPPBZ4zL6Ne/JvfCDzn/WhufhvgvsBzVkR1dgN2AR4JPGduom38P7wXeM7c6FzfCfgU4iMR\n", | |
|
217 | "lFLebNfPIefXzMBzikz8tusPQyx676bljmTeCfhyVLST7frp//TV9Dluu/6GwOhUvTWB58zIkjFq\n", | |
|
218 | "sykyNfmfwHMW2K7fLzoWeyDTFPnAc14t1T7qYwNgT+Rc/wi5ZyT/N20UBEMRSqn+wNdTxQspTqTU\n", | |
|
219 | "41BaP6yVOipzGzzSYnG6m6uBz0YPv7OQm3dytc35tuuflHZutF3/BuArwEaJ4p/QNdU2wGnAH9M7\n", | |
|
220 | "jRSTG5CbS5LQdv2joymTLKYBzwHjbNc/DomW2TCxfbXt+sMCz3k/sa8RwM+Qh/X6qf5W2q4/CTit\n", | |
|
221 | "zMN1OPB7CopQktW2658YeM5fEvXvRKZzBiXqZaWUPha4JlW2NfB8Rt0hiANfmjWIuf5jiLPfvVm/\n", | |
|
222 | "AfmvbgNmB54zKrkheuD+Bjg11Wap7fpnBJ5TybelFk4E+iE+Fb+ptbHt+scg//nGqfJbgeMDz1mY\n", | |
|
223 | "KN4UOZYX2q7fSWHhuNdt198ZOBc4MypbbLv+5wPPeTb6PiJqe5ft+ichx3WXRN8rbdc/OfCcrGis\n", | |
|
224 | "R4ChiHKSlSn2f4BzkOvitMRvCKJ9DEzU9TPafwGZlkkyBvExSrKUrtdnmoOBycA5tus/iCyat3li\n", | |
|
225 | "u7Zd/0rk2ihS1mzXPwT4E3LulaLTKAiGLL6EaMlJbtBat91pphIjFw289t9DVh4N7Jva9EKnWnpJ\n", | |
|
226 | "G0RqBXcjCa08YCqy/PJE4L8A33b9HQPPeTNR/0bgvujzGchoywPSq5U+nd6R7fp7IDfRjYDrEE99\n", | |
|
227 | "DeyHrPb5lO364xI36zTb2q4/AUnt/SSyLHQHMvJZklQOIhYChyCLid2FWBoGIQrDfwGnAP8Gskzd\n", | |
|
228 | "VvSbBgPvIMdpJjLHuxdikXgg1ewa4Jbo84+BHRAFI/3gT9/QQZa+/iIy9zwccVQrSeA5nbbrX4s8\n", | |
|
229 | "cI6htIIQK7xdFJLIAvEEYjmYBlyP/E4LeXj92Xb94YHnnFtOjhrYJ3q/vtbpE9v1fwqcjYxUL0GO\n", | |
|
230 | "51bI//g1YIzt+mNTSgJIivfNEIXgBOThfx0ySv8Nct7vgzgfj0+1HQf8E5iPKM/vI+vLHA9cZbs+\n", | |
|
231 | "JZSEevgDBZ++3yIKzgVI1FeSrCnD6ci0zebAJxCfjmoZjxzXPPBL5By0gW8jCt3sqHwtkYL1N0RB\n", | |
|
232 | "/R2ymOG2yHE5CLFAHAu8ahQEQxbfyijrDdML3HTTkWvUBRfsb88bPb6TzjEK+oHKL184YHL+Jmdl\n", | |
|
233 | "u+XrJsYBhwaec0dcYLu+hzw0dkcu/AvjbUmLgu36DqIgPB54zuQq9nURMgI8LjnyBibZrj8z2s/l\n", | |
|
234 | "tuvvVcJJbWvkXDoi8JzbKu0s8JxFtut/IqXgAPzOdv0/IiPnb5KhICAjpMGIEjAhPV1iu35HWsbA\n", | |
|
235 | "c25ObD8ZURAeqibENBqpTYnark8FBSHiakRBOMx2/cHpB29kSv4KooSlLRYnIcrBHcBXk7/Fdv0b\n", | |
|
236 | "gReAM23Xvz7wnJlVyFIJK3qfXUsj2/U/jiiiq4B9ktEytuv/Fhlpfx2xEnw31XxHYLfAc6bbrv8k\n", | |
|
237 | "cny/Bnwz8Jy/2q6/DTLd9F8Zu94ceXAeEHhOvM7MNbbrT0UU4vNs15+c2FY3gedcm/hNP0EUhDvL\n", | |
|
238 | "KMrJtkuIFPboWNWiIOSAO4HDE7/Dj67FSxEn21+m2pyOWDpuCDxn7fG2Xf8e4F1EIVsceE5oohgM\n", | |
|
239 | "XVBKjURuSEke11qXMhv3OPR553VO9Sb407yJZwTexO8FnnNV/qYj11XlAOCfSeUA1s4D/y36mp7f\n", | |
|
240 | "rAvb9fdGLDMzU8pBzMXIg2wsMhLKQiFhgxWVg5gM5SDm+uh9VHqD7fr7IlaNFcAJWb4UPcHLPvCc\n", | |
|
241 | "2YgVZn3gyIwq30AsQg8lQ+aiefUfR1/PzlB08sD9Udusfmsi2t+Q6GutjspnIE6L16dDaSN/irMR\n", | |
|
242 | "p8dTbddPOxK/nwgxTZr8747e30SsEkNL7PvXGQrAVYgvwggK/gK9mXMyfuON0fvWkY9Dkp2i97uT\n", | |
|
243 | "hYHnLKNgURsDxknRUMz5FJ8XP22DHIbqSc9pxsSOW8ObtJ89ovdXbNcvpQC8j4zcdiTbnAoy4q2b\n", | |
|
244 | "6Ia3CYV5/Y0zqsXOf4/WEYveaq5GQuOOQaZekhydqJNkW2BLZF2UzhL/R+xE2XAIa+A52nb9lUho\n", | |
|
245 | "Y63hd7GD5d1ZGwPPmW27/iuIUrkLXc/n9xP13rZd/yNgVezoF8n1NjAyyyKETGGl97fGdv1/IlaL\n", | |
|
246 | "3h7e+06WM2PgOQtt11+GTMcNo6vVJ1aWsyK+4nvFQjAKgiGBUmoshfnOmGe11vdl1Tf0GOaUKI9v\n", | |
|
247 | "lqrE9lqJb6b/Hb3KsU2Zba/VslPb9bdDfA0ORLz0N62iWWxVqMkc3iZuRuawP2u7/g6JKI9RSCTR\n", | |
|
248 | "YoodhOP/YgNKK2Ix2zZJzjnINMN2NbaL/4uiaIUE/0EUhB3pqiCkMwl2IscjXZZFJ/B2iW1xRtWR\n", | |
|
249 | "ZWTqDcwps63U9f8Q0TSN7fp/iK0PtuvviPjmrCHyR1qrICilNkTmHjZDLsDke/JzOtwnzY1KqXcR\n", | |
|
250 | "R4cFiBab9XlRT87I19dQSo1GNPz0tJOxHvR8mhrOVobB0XuAOBiWo1zmwaqdXW3X3x+4BzGVv4SM\n", | |
|
251 | "pN9AnPEg21McxMIArTs2dRN4zoe26/8NOA6xGJwfbYqV9b8GnrM81Sz+Lz5A0qOXo2y4Ww3MoT4F\n", | |
|
252 | "IY4+KTfNF58TaXN4VthstVNDitLKcdxvOjKmEj0tv0M953fs87E3Eul0B2JliBflOzfwnFcA+iul\n", | |
|
253 | "5iEmwQFNEBaK569L0amUWggcqrXO8gg2FKHG2CdW4Uem9XvBlUflu7RUaiByU3lPa92ZKN8cSav8\n", | |
|
254 | "fUQBTHKr1rrqueIsxp18/eg1azrLjSYB6NfRsY3G6Is9nDjDYxh4zundvbMotvtm5N50duA5P09t\n", | |
|
255 | "T0faJIkfirU+zNrF1YiC4FBQECZE73/JqB//F+u14r+ImIVEOB1iu/6ZNfhwzEamp7YuU2e7RN1m\n", | |
|
256 | "oZBnW5YVIfZ1qNWfotw51yuIph++hET0bAkcikwpTAEuCjxnSly3PzIP0a8NcnYgD6SBlSoaIhQX\n", | |
|
257 | "V2UtVup24LBU6S7IyG+NUuodZP52awojrTSvIjeshlij9XdQKh2jXYRRDtpGfOCruQfEpmzbdn0V\n", | |
|
258 | "dP9iPLsgjnEryI67Lzd/PCt6/5Tt+v3LJXAqQ/z7ut2ZO/Ccx23XfxUYZbt+7D8xCngl8Jwsa80s\n", | |
|
259 | "ZBS8ke36O7cg4ybA5UgegJ0QE/XN5auvZRaiIMQRF12wXX8TCv9ls6eERpOtIMR+EXNS5YsRh8dS\n", | |
|
260 | "To/V+CzUck21i6uR5++4wHNeKFXJRDH0PfoR5fqmtHKwDDhCa73O5JA3lCSeF04v6Z3FPRTMzBO7\n", | |
|
261 | "S6AE8Q12PbomgYn5Xpm29yMPhu2RUK96iKMn9q6zfa38JXo/NHoly7oQeM5K4Iro60+jKINuJVJC\n", | |
|
262 | "Yu/439uuX805A4VkWyfbrp+V/MdFnOmeCmpfFKsSRYMc2/U/DeyG3OfSjpOx5WmfVHmcuXFcFfus\n", | |
|
263 | "5ZpqObbrb45EtswqpxyAcVI0FDMbOFxrXeT9a+heopvnEArzolvashT0wmbEapdgGpIU5XDb9R9F\n", | |
|
264 | "YqrXQyyL8wPPeTeuGHjOMtv1T0VuqldH6W//jigNmyHOcAcBgwPPcZog20xkRLcJ8DPb9S9CRqM7\n", | |
|
265 | "I7kDvoDE1hfdxwLPWWy7/plI7oCLbNffHXm4zUQeRtsjGRP/EXhOKSfcABkpj49i5+9G/putgHmB\n", | |
|
266 | "5yxIN4iSF21C14V6Rtiu/yYSW15uHv4a4P8oKAedlPcvOAv4KmItfCTKKfAS8v8NR1ILHwnsl5GA\n", | |
|
267 | "qF7ORdYaGA48HGWyfBqYgViDRwCfQR72PkDgOU9E2TvHI4m0TgeeRczb30DyH2iKcyA0ymrgWNv1\n", | |
|
268 | "FyDK1NvIQ3tStN3LCH+9HUl29UPb9echFo8BUbtLEKfJtJ9EmgA59ifbrj8bCR3cGDlvZqdTLcPa\n", | |
|
269 | "9NCbUMhs2GFLKvPFSAKxZl7/CxEL8pgoA+QMxD+kE3HenAHcHnjOGmNB6Dt8iGjHWSFKK4HHkcQr\n", | |
|
270 | "OxvloLXYrr+77fqrEIejNyiE6P0WccZbabv+lFLtG+Ry5AY/BHkYfRDtR9M79QAAA3FJREFUcwYS\n", | |
|
271 | "NdCFwHPuQR6a7wHfAR5GMhk+i9xcT6G6KIOKBJ6zFBn9r0GUmBlIWN9ziHf/5yjO/phsfy2yqt4i\n", | |
|
272 | "xOJxF3INTI9k/Q7ZoV4xv0PC5LZCci4sQm6g08kYHdquvxy5lt4DwsSmF5EENCts1//Idv3M9LbR\n", | |
|
273 | "egJTkEx4NvBA1joFifqLIjkeR6wcfwdeQfIFTEEcjHNU79RXkShvw95Ixs5+yOj/KuSh+ATiAHcq\n", | |
|
274 | "xb4fxwOXRfJMQc6zlxGF6B3g4MBznmmWnBFzEUfP0xDFcCGiAG+JHKushESXIdanjRBF4l3EInAj\n", | |
|
275 | "8vuOqWK/5yNRGaOQFNkfIhkOX6CQgwAA2/W3jkI3V0T7ejjatAFyXb2PXP/LbVnroWGi6bbzo697\n", | |
|
276 | "IlaWk5Br93wkk+jztusP7o94Lna7eaoMZU0cVXIAped7eqGZfP2ZqmPFl+ptrVf3n19UpvVMYLRS\n", | |
|
277 | "agBywxuEjLwWAe9qrTMXV2mUzs7OP/Xrp+6qt33Hmn5Zue3XNeZTOVoky5nqKiQkrNT883Qk3WvJ\n", | |
|
278 | "sMLAc1bbrv9Z5AH6KWRkOB+5wRWlWo7a3Ga7/mOIomAho/GFyI30YeDREru7ELlOq07TG3jONbbr\n", | |
|
279 | "T0Nu9KOQm+i/gFsDz3nTdv2fI2FbpdpfHnlpH4LcnHdAlIz5yLErqXgFnvOR7fo28lDYE7lu3kKO\n", | |
|
280 | "TdZ9K52xrhTl7knnUVB6SqVeTsr4apQU6lDEbG4hCsFbROsRBE1ebjrwnNB2/XGIGf5gRBkYhPyv\n", | |
|
281 | "7yDpjR9MtVkOnGK7/vWIgrFrVPcF4O8ZKbaXIuduWkH6KfL/JbkEsWClfWK2CDzHt10/jzhXjkGO\n", | |
|
282 | "yzNIZEiRD00ga3ocaLv+kUh2xo8hSuVURKmIUyiXVGYCWVzKQlJD7xrJNg85b9LX8RLgF6X6SpFU\n", | |
|
283 | "9Cpe28gaJgORqEEAbNffDLlvHIQoAndR8NEYilwjExD/nwuUiTQ0GAwGw7qC7fqjEUvKqsBzmhWd\n", | |
|
284 | "t05gu/5pyNoifw48J9N5PForxQeeNFMMBoPBYDD0DWL/llvK1In9jt4zCoLBYDAYDH2DePo5MwrJ\n", | |
|
285 | "dv0hFPwTnjBRDAaDwWAw9A3+hPgOHRPl25iK+FhsiuR4OARx0Lwf+J1REAwGg8Fg6AMEnvNklL78\n", | |
|
286 | "HMRRca/E5hVINNIVwI2B56z6/3ExLRI31pXNAAAAAElFTkSuQmCC\n" | |
|
287 | ], | |
|
288 | "text/plain": [ | |
|
289 | "<IPython.core.display.Image at 0x111275490>" | |
|
290 | ] | |
|
291 | }, | |
|
292 | "execution_count": 6, | |
|
127 | 293 | "metadata": {}, |
|
128 | "outputs": [ | |
|
129 | { | |
|
130 | "metadata": {}, | |
|
131 | "output_type": "pyout", | |
|
132 | "png": "iVBORw0KGgoAAAANSUhEUgAAAggAAABDCAYAAAD5/P3lAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAAH3AAAB9wBYvxo6AAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURB\nVHic7Z15uBxF1bjfugkJhCWBsCSAJGACNg4QCI3RT1lEAVE+UEBNOmwCDcjHT1wQgU+WD3dFxA1o\nCAikAZFFVlnCjizpsCUjHQjBIAkQlpCFJGS79fvjdGf69vTsc2fuza33eeaZmeqq6jM9vZw6dc4p\nBUwC+tE+fqW1fqmRDpRSHjCggS40sBxYDCxKvL8KzNBaL21EPoPB0DPIWVY/4NlE0ffzYfhgu+Qx\nGHoy/YFjaK+CcB3QkIIAHAWs3wRZsuhUSs0CXgQeBm7UWi/spn0Z+jA5yxpEfYruqnwYllRic5a1\nMaWv8U5gaT4M19Sx396IAnZLfB/SLkEMhp5O/3YL0AvoAHaKXl8HLlZK3QZcpbWe0lbJDOsaHuDU\n0e4u4JAy2wPk/C1JzrKWArOQ0fUtwH35MOysQxaDwbCO0NFuAXoh6wPjgQeUUvcqpUa0WyCDoQls\nCIwBjgfuAV7KWdY+7RWpmJxlXZezrEdylvXxdstiMKzrGAtCYxwI/EspdZbW+g/tFsbQ67kQuBHY\nFNgseh9FV6vCbUAeWBC9PgBeq2EfS6J2MQOBrRDTe5KdgAdzlvW1fBjeUUP/3UbOsoYBE6OvG7VT\nFoOhL9Af+BUwFLkZpV+DaY6V4UPkRpb1+ncT+m8nGwK/V0oN01qf025hDL2XfBi+DLycLMtZVo6u\nCsKfGnSq8/NheEpqHwOBEcDBwJnAsGhTP2ByzrJG5cPwnQb22Sy+0G4BDIa+RH+t9dmlNiqlFKIk\nJJWGi+jq5JPmq8BbJJQArfXqpkncczlbKbVQa/3rdgtiMNRCPgxXAK8Ar+Qs63LgXmDvaPPGwPeA\nH7VJvCRfbLcABkNfouwUg9ZaAwuj178BlFLvVejzgR4WFviM1npcuQpKqf6IyXIjxLS7GzAWuUnu\nXsO+fqWUellr3ZBJdq/jr9+BDn1uve07O9Rz0y6f8PtGZGgWe53oT6SBkZ/q1/nHZy47aloTRTKU\nIR+Gy3OWNR6Zxtg0Kv4KRkEwGPocxgcBiCwcsSI0F5iOhF+ilPok8C3gVGS+thK/VErdrbWuO2ys\ns/+aLZTuOKbe9krrIUCPUBB0B+PQ1P1bdKe6EzAKQgvJh+GbOct6gkJkxM45y+qXDIWMHBhjBWJe\nPgyDWvaRs6zPIVObAG/nw/DpEvUGAp8E9gGGJzbtl7Os7cvs4skqp0V0Yl8jgcOBjyMDhbmIZeWl\nfBg+UUVfReQsayhwELAnsAXi6/E28BxwTz4MP6iyn92RaSCA+/NhuCwqXx9R4MYhU0MfRTK/AjyW\nD8MFGd0ZDFVhFIQKaK3/BXxfKXUlklTq0xWafAI4Driyu2UzGLqRlygoCArYHJif2H4gcFb0+Z2c\nZW2bD8NV1XScs6yNgH8g/jsAPwCeTmzfFPgjYsnbiez71MUVdnMQcF8V4nyUs6whwB8QX4+0s2Ys\n0yPAt/NhGFbRZ/wbzgO+DaxXotqqnGX9GbigCkXhf5CBCsDngYdzljURGQhsWqLN+znL+iFwdT4M\ndYk6BkNJTJhjlWitQ2Bf4P4qqv848t8wGHor6Yd9+ruHJFkC2BI4rIa+D6egHKwmstYlGAxMQCwH\nrRjEPI5ER5S7ZvcFXsxZ1phKneUsawSi8HyH0soB0bbvAM9Ebaplt5xlnYkct1LKAYiFZhJwSQ19\nGwxrMRaEGtBar1RKfRX4JxIzXortou3PN1mE+YgJsSwaeoLHOQCqUy3QSr9eqZ6G/gq2aYVMhqrY\nOfF5FeJwvJZ8GM7JWdY/gC9HRS7wtyr7Pjrx+e6MqYC3KLbU7Qhck/h+FJIKvRRVjfSREXicU8EH\npgAvIIqLBZwGfC7avl5Uf29KkLOsTZCMq8npj9sQx89no37HIlaAODplNPBIzrJ2z4dhNVlaT0HC\nXwFmIkrAC4if2PaIz8/3KCgn385Z1pX5MJxeRd8Gw1qMglAjWutlSqnTgUcqVP0SzVYQtP5mcMXE\nSvvtUUy9YsK5QEWHy7EnTB6lOtSsFohkqEDOsgYAdqJoagkT9Z8pKAj75yzr4/kwnF2h748ho/GY\nq9J1oqiKLj4JOctKK8Yz8mH4Yrl9VcnHkXVYTsyHoZ8WJWdZNyPThbF5/3M5yzowH4alpi9+T0E5\nWA18Nx+Gf0zVeRG4KmdZ90R9bwCMRKwyX69C5h2j91uA4/JhuCSxbTYwJWdZtwNPIFbifsAFSISZ\nwVA1ZoqhDrTWjyIjjXIc3ApZDIZu4ELgY4nvt5Wody8wJ/qsgBOr6HsihfvOfCRrY7v5dYZyAECk\nGP0ISEZmZYZ55yxrB8SyEXNxhnKQ7Pt64H8TRUfmLGuXKmWeC4xPKQfJvp9CLCJlZTYYymEUhPq5\ntcL2XVsihcHQJHKWtU3Osi5GnAZj5iKWgiKitRouTxQdl7OscnPu0HV64dp8GLY7R8pyxEGxJPkw\nfBcZ9ceUSvN8IoV76upK/UZcgawcG3NKqYopfleFU+gDic/b5SzLWIwNNWFOmPqp5CG9sVJqPa11\nVZ7dBkOL2D1nWcmcBkOR8MFtgM/QdTXJZcCR+TBcXqa/SYj5egAFZ8VMX4ScZe2FRPnEXF2z9M3n\n3nwYVsrtAmK6/0z0uVR4ZXLtivvzYfhGpU7zYbgkZ1k3ACdHRQdWIQsUO3ZmkUzB3Q/xjaolLbeh\nj2MUhDrRWr+mlFpJ+eV5hyIxz4YWs98Fj/Rf8uZbozo0/ZYt7D8rf9ORK9stUw/hU9GrEnMAp1R+\ngph8GL4bzdNPiIpOorSzYtJ68FS1IYPdTLWp3hcnPm+Q3pizrA7E+TCmFn+aZN0dcpY1LB+G5e4b\ny6rM8bA49X39GmQyGMwUQ4NUGnkMrbDd0A3sdeLk4z6cN+89pTtDTWd+gyErF+7pTv5eu+XqJbyK\nTDHsmg/DJ6tsc2ni8+dzljUqXSGaevhmoqjIObFNVBzlV8kQug4W5tbQNl13WGatAv+poW+DoW6M\nBaExPgC2LrO9nHWhpSilDqI4NPMhrfXUJvS9M/DfqeJXtdY3N9p3rex50uQ9lFKT6BrTvoFCXbTX\nyZNfmnrZxHtbLVMP4xng74nvK5DzeD7wfIWRayb5MHwiZ1kzgF0oOCuemar2ZQoK8zLgr7Xup5t4\ns0n9DEl9b0RBSPeV5q0a+jYY6sYoCI1RacnZ91siRXUMAH6eKnsYicdulDOAY1NlpzWh35pRqG9R\nIuGN7uw4AfG878s8nw/DX3RDv5dScGY8NmdZP86HYXJaJzm9cHMp7/s2UHdK9BTpKaxBNbRN163k\nt9Rux05DH8FMMTTGZhW2v9sSKarjbopNk/sqpUY30qlSahCSGS/JCuD6RvqtF6UpMm/HaHTJbYaG\nmQzED/0umRVzlrUZhXwJ0HOmF5pJOlXyxzJrZbNt6rtZP8HQIzAKQp0opTZAlsItxTKtdTnv75YS\nLR7lpYqrjV0vx2EUH4fbtdZtucnpMqOrDjPy6jYii8DkRFHSYnAEhem22cBjrZKrVeTDcCldTf/p\nh345ksrEGprnF2EwNIRREOrnMxW2z2uJFLVxJcXmy2OVUo34ShydUda+EaIq7T2u0SZTY/eSdFY8\nMGdZm0efk86J6/LCQUnFp5pIkZjkcvQz8mH4YZPkMRgawigI9VNp7v7BlkhRA1rr+RQneNqC2hba\nWYtSajiS9z3JXLomaGktq/VllLIUdKqSWe0MjZMPwxlIel8Q/6Zv5CxrGIX8AJ10XU+hFtIRQ+UW\nKWoXyYyTu+Qsa79KDXKWNRpJyx5zZ9OlMhjqxCgIdaCU6g98o0K1npBCNotLM8rcOvuagCRgSXKN\n1rozq3IrCCZNfFkrfRjotWsCaJinUBODK51/tkuuPkTy/DoYOIDCfeb+fBjW4t2/lqhdcmRdbUri\nVnILXS2HZ1WRvfAcCk61K4A/dYdgBkM9GAWhPr5F6XSrIBf6Qy2SpSaidSReShV/XilV7veUIj29\noOkB2fGmXT7x7sCbOGpFf7VZx4A1m0/znG2nehMyc+0bms7NFJxzxwH7J7Y1OvWUPG9/mLOsLRvs\nr6lEaaOT0TtfBB5ITLWsJWdZg3KWdRNwTKL4wnwYzu9mMQ2GqjFhjjWilBqBpJYtx51a66UV6rST\nS+maJz52VvxRdvVilFK7UbzexGNa67Kr+bWS6X+ekPYs79HkLGt34JOI+Xyz6D2d1vfMnGUdini6\nL0C851/Oh2HD+SyaQT4MV+YsaxJyLm1Gwf9gAXBHg93/JNHHtsArOcuajCztPBDYCkkytBXg5sOw\n5QmF8mF4W86yLgK+HxXtC8zKWVaALMm8CslHsicS7RFzL8VhyAZDWzEKQg0opbYE7qd8prPVdF2h\nrSdyLfALYMNE2XFKqR/XsHbEURll62L4Wiv5PuBUqPPF6JXkLuCQbpGoPi4HfohYKGMHWD9axrlu\n8mF4Z7RuwfioaDBwaonqRemQW0U+DH+Qs6xFwHnIFNwQsv+3mMnA8dHiVwZDj8FMMVSJUuow4DkK\na7GX4gqt9cstEKlutNaL6boULMho5tBq2iul+lH8IFuCmJcNfZx8GM6hOCFVU5THfBhOQHxfylkH\n3gY+asb+6iUfhhcCewC3l5BlFbJk/P75MDwqlVTKYOgRKK1rizhSSk2h67ximo1abV5XSi2n9EIk\nz2itx5XYVqnfQcjI7DiqW2XtfeCTUbRA3ex50nWfUrqjeJEcrfcLrpj4SCN9xyilxgDPp4of0Fof\nUEXbg4B/pIqv1FrXnVNh7AmTR3V0qIwwRH1E4E28pd5+De0hZ1m/Bb4bfX0+H4Z7dMM+hgGjkDwC\nS5FpjFk9bR4/Z1mDkGmF4VHR20g4Y3oxJYOhR9EXphg6lFLlVjFbH0mZvDGwCTAayCFe0ntTOZ1y\nzDLgkEaVg1ahtX5BKfUU8OlE8ReUUjtorSstCduzch8YehSR5/6ERFG3nBvRuhE9frXUfBguA6pd\n+Mpg6DH0BQXBBro7o+Ea4Bta66e6eT/N5lK6KggKOAE4u1QDpdTGFOdNmNkLf7uh+zgYcRQEMa+3\nJe22wWBoDOOD0DhLgYla67vaLUgd3ETxglLHRXkeSnEExQ5gbQ9tNPQokis5TsqHoVlbwGDohRgF\noTECYHet9Y3tFqQetNYrKDb/DqN46eYk6emF1UhUhMFAzrImUEhDvgr4VRvFMRgMDWAUhPpYAvwf\n8Bmte31+/8uQBEdJMjMrKqW2o5A2N+YfWusePw9s6F5yltWRs6zxwKRE8RXtyEVgMBiaQ1/wQWgm\neWTe/jqtdU9Zz74htNavKaXuAw5KFB+glBqptZ6Tqj6RQlrYGDO90AfJWdY5wNeQFQwHIAmetk5U\neZFCsiCDwdALMQpCed5AphEC4NF12BHvUroqCAoJ7TwvVS+d++BdJEmPoe+xKRLnn0UeODwfhm3N\nRWAwGBqjLygIbwN/LbNdI1MGH6ReL/eWkMUmcDeSeGa7RNlRSqnzdZQoQym1C7Bzqt11NWReNKxb\nzEMU6GHAesBiYCaSLOviaF0Cg8HQi+kLCsLrWuvT2y1ET0ZrvUYp5SG57mO2Bz4LPB59/2ZRQ5P7\noM+SD8OLgYvbLYfBYOg+jJOiIeZKxOs8STJiIb28daC1/lf3imQwGAyGdmEUBAMA0XTKraniI5VS\nA6O0zOnloI31wGAwGNZhjIJgSHJp6vtgJBNlehW65cANLZHIYDAYDG3BKAiGtWitHwVeShV/muLF\nuW7VWi9qjVQGg8FgaAd9wUnRUBuXAn9IfN8f+FyqTo/OfbDnSX8brDpXnqEUe2ropzQvdtDx66ev\nGN9XolIMPQDb9T8LrBd4zsPtlsXQe7Bd/0BgQeA5QbtlMQqCIc21wC+ADaPv6WWu5wAPtVKgWtjt\n6Os2XG/9jhdQjIzTQ2rFF9bQecy4E2/I9UQlwXb9LYDDK1R7K/Cc21shj6FxbNcfDjwGKNv1Rwae\n83q7ZWo2tusPBb6ELGW9BbAICX99Gngs8Jx0hlZDBWzXHwvcC6ywXX9o4DlL2ymPURAMXdBaL1ZK\n+ZRItwz8Jc6N0BMZMFB9GxiZsWnzTjrPAH7QWomqYgTF/h9pngC6RUGwXf+XwC2B50ztjv57M7br\nXwJMCjxneo1NP0SWgAfJq7LOYLv+esAFwOkUL9wWM912/d0Dz+lsnWQ9A9v1BwEXAT8PPKfWVOML\nkPVt3kNWQm0rxgfBkEWph5UG/tJCOWqnQ40ttUkrvWcrRamWwHOmAZsguSfGAi9Hmy5AUhgPAz7f\nHfu2XX8k8ENgx+7ovzdju/4uwP9D/peaCDxnCbANsF3gOYubLVu7sF1/AHAHcBaiHDwI/C+ywNsE\n4KfA68BdfVE5iNgbOBmxqtRE4Dn/BoYDnwg8Z02zBasVY0EwFKG1fkEp9RTioJjkIa11zzaVarYq\nvVFt2TpBaiN6oCwB5tiu/2FUPCvwnLTTaLM5oJv77800dGwCz1kXHXkvRNKydwI/Cjzn1+kKtuuf\ni2TX7Ks0et681yxBGsUoCIZSBBQrCL0h98EbdW7rddiuPwoYFJu/bdffFNgL2BZ4DZgWKR5ZbRWS\n2+KIqGiE7fpjUtXmlrtZRdaHscBAYDowM/CckimWbdffFfgw8JzXou/9kfUccojV5MXAcz4s0XYw\nsCsymu8PzAVmBJ7zVqn9pdoPRVKF7wSsAN4EgqzRve36HcAoZDEqgO0zjs3rged8kGo3gOJ05ADT\ns0bTkan+k9HXGaVGjNFxykVf81nH2Hb9Ich/MRJJeT291H9fL7brj6CwANfPspQDgOi3rijRx/rI\nb8kB7wPPBZ4zL6Ne/JvfCDzn/WhufhvgvsBzVkR1dgN2AR4JPGduom38P7wXeM7c6FzfCfgU4iMR\nlFLebNfPIefXzMBzikz8tusPQyx676bljmTeCfhyVLST7frp//TV9Dluu/6GwOhUvTWB58zIkjFq\nsykyNfmfwHMW2K7fLzoWeyDTFPnAc14t1T7qYwNgT+Rc/wi5ZyT/N20UBEMRSqn+wNdTxQspTqTU\n41BaP6yVOipzGzzSYnG6m6uBz0YPv7OQm3dytc35tuuflHZutF3/BuArwEaJ4p/QNdU2wGnAH9M7\njRSTG5CbS5LQdv2joymTLKYBzwHjbNc/DomW2TCxfbXt+sMCz3k/sa8RwM+Qh/X6qf5W2q4/CTit\nzMN1OPB7CopQktW2658YeM5fEvXvRKZzBiXqZaWUPha4JlW2NfB8Rt0hiANfmjWIuf5jiLPfvVm/\nAfmvbgNmB54zKrkheuD+Bjg11Wap7fpnBJ5TybelFk4E+iE+Fb+ptbHt+scg//nGqfJbgeMDz1mY\nKN4UOZYX2q7fSWHhuNdt198ZOBc4MypbbLv+5wPPeTb6PiJqe5ft+ichx3WXRN8rbdc/OfCcrGis\nR4ChiHKSlSn2f4BzkOvitMRvCKJ9DEzU9TPafwGZlkkyBvExSrKUrtdnmoOBycA5tus/iCyat3li\nu7Zd/0rk2ihS1mzXPwT4E3LulaLTKAiGLL6EaMlJbtBat91pphIjFw289t9DVh4N7Jva9EKnWnpJ\nG0RqBXcjCa08YCqy/PJE4L8A33b9HQPPeTNR/0bgvujzGchoywPSq5U+nd6R7fp7IDfRjYDrEE99\nDeyHrPb5lO364xI36zTb2q4/AUnt/SSyLHQHMvJZklQOIhYChyCLid2FWBoGIQrDfwGnAP8Gskzd\nVvSbBgPvIMdpJjLHuxdikXgg1ewa4Jbo84+BHRAFI/3gT9/QQZa+/iIy9zwccVQrSeA5nbbrX4s8\ncI6htIIQK7xdFJLIAvEEYjmYBlyP/E4LeXj92Xb94YHnnFtOjhrYJ3q/vtbpE9v1fwqcjYxUL0GO\n51bI//g1YIzt+mNTSgJIivfNEIXgBOThfx0ySv8Nct7vgzgfj0+1HQf8E5iPKM/vI+vLHA9cZbs+\nJZSEevgDBZ++3yIKzgVI1FeSrCnD6ci0zebAJxCfjmoZjxzXPPBL5By0gW8jCt3sqHwtkYL1N0RB\n/R2ymOG2yHE5CLFAHAu8ahQEQxbfyijrDdML3HTTkWvUBRfsb88bPb6TzjEK+oHKL184YHL+Jmdl\nu+XrJsYBhwaec0dcYLu+hzw0dkcu/AvjbUmLgu36DqIgPB54zuQq9nURMgI8LjnyBibZrj8z2s/l\ntuvvVcJJbWvkXDoi8JzbKu0s8JxFtut/IqXgAPzOdv0/IiPnb5KhICAjpMGIEjAhPV1iu35HWsbA\nc25ObD8ZURAeqibENBqpTYnark8FBSHiakRBOMx2/cHpB29kSv4KooSlLRYnIcrBHcBXk7/Fdv0b\ngReAM23Xvz7wnJlVyFIJK3qfXUsj2/U/jiiiq4B9ktEytuv/Fhlpfx2xEnw31XxHYLfAc6bbrv8k\ncny/Bnwz8Jy/2q6/DTLd9F8Zu94ceXAeEHhOvM7MNbbrT0UU4vNs15+c2FY3gedcm/hNP0EUhDvL\nKMrJtkuIFPboWNWiIOSAO4HDE7/Dj67FSxEn21+m2pyOWDpuCDxn7fG2Xf8e4F1EIVsceE5oohgM\nXVBKjURuSEke11qXMhv3OPR553VO9Sb407yJZwTexO8FnnNV/qYj11XlAOCfSeUA1s4D/y36mp7f\nrAvb9fdGLDMzU8pBzMXIg2wsMhLKQiFhgxWVg5gM5SDm+uh9VHqD7fr7IlaNFcAJWb4UPcHLPvCc\n2YgVZn3gyIwq30AsQg8lQ+aiefUfR1/PzlB08sD9Udusfmsi2t+Q6GutjspnIE6L16dDaSN/irMR\np8dTbddPOxK/nwgxTZr8747e30SsEkNL7PvXGQrAVYgvwggK/gK9mXMyfuON0fvWkY9Dkp2i97uT\nhYHnLKNgURsDxknRUMz5FJ8XP22DHIbqSc9pxsSOW8ObtJ89ovdXbNcvpQC8j4zcdiTbnAoy4q2b\n6Ia3CYV5/Y0zqsXOf4/WEYveaq5GQuOOQaZekhydqJNkW2BLZF2UzhL/R+xE2XAIa+A52nb9lUho\nY63hd7GD5d1ZGwPPmW27/iuIUrkLXc/n9xP13rZd/yNgVezoF8n1NjAyyyKETGGl97fGdv1/IlaL\n3h7e+06WM2PgOQtt11+GTMcNo6vVJ1aWsyK+4nvFQjAKgiGBUmoshfnOmGe11vdl1Tf0GOaUKI9v\nlqrE9lqJb6b/Hb3KsU2Zba/VslPb9bdDfA0ORLz0N62iWWxVqMkc3iZuRuawP2u7/g6JKI9RSCTR\nYoodhOP/YgNKK2Ix2zZJzjnINMN2NbaL/4uiaIUE/0EUhB3pqiCkMwl2IscjXZZFJ/B2iW1xRtWR\nZWTqDcwps63U9f8Q0TSN7fp/iK0PtuvviPjmrCHyR1qrICilNkTmHjZDLsDke/JzOtwnzY1KqXcR\nR4cFiBab9XlRT87I19dQSo1GNPz0tJOxHvR8mhrOVobB0XuAOBiWo1zmwaqdXW3X3x+4BzGVv4SM\npN9AnPEg21McxMIArTs2dRN4zoe26/8NOA6xGJwfbYqV9b8GnrM81Sz+Lz5A0qOXo2y4Ww3MoT4F\nIY4+KTfNF58TaXN4VthstVNDitLKcdxvOjKmEj0tv0M953fs87E3Eul0B2JliBflOzfwnFcA+iul\n5iEmwQFNEBaK569L0amUWggcqrXO8gg2FKHG2CdW4Uem9XvBlUflu7RUaiByU3lPa92ZKN8cSav8\nfUQBTHKr1rrqueIsxp18/eg1azrLjSYB6NfRsY3G6Is9nDjDYxh4zundvbMotvtm5N50duA5P09t\nT0faJIkfirU+zNrF1YiC4FBQECZE73/JqB//F+u14r+ImIVEOB1iu/6ZNfhwzEamp7YuU2e7RN1m\noZBnW5YVIfZ1qNWfotw51yuIph++hET0bAkcikwpTAEuCjxnSly3PzIP0a8NcnYgD6SBlSoaIhQX\nV2UtVup24LBU6S7IyG+NUuodZP52awojrTSvIjeshlij9XdQKh2jXYRRDtpGfOCruQfEpmzbdn0V\ndP9iPLsgjnEryI67Lzd/PCt6/5Tt+v3LJXAqQ/z7ut2ZO/Ccx23XfxUYZbt+7D8xCngl8Jwsa80s\nZBS8ke36O7cg4ybA5UgegJ0QE/XN5auvZRaiIMQRF12wXX8TCv9ls6eERpOtIMR+EXNS5YsRh8dS\nTo/V+CzUck21i6uR5++4wHNeKFXJRDH0PfoR5fqmtHKwDDhCa73O5JA3lCSeF04v6Z3FPRTMzBO7\nS6AE8Q12PbomgYn5Xpm29yMPhu2RUK96iKMn9q6zfa38JXo/NHoly7oQeM5K4Iro60+jKINuJVJC\nYu/439uuX805A4VkWyfbrp+V/MdFnOmeCmpfFKsSRYMc2/U/DeyG3OfSjpOx5WmfVHmcuXFcFfus\n5ZpqObbrb45EtswqpxyAcVI0FDMbOFxrXeT9a+heopvnEArzolvashT0wmbEapdgGpIU5XDb9R9F\nYqrXQyyL8wPPeTeuGHjOMtv1T0VuqldH6W//jigNmyHOcAcBgwPPcZog20xkRLcJ8DPb9S9CRqM7\nI7kDvoDE1hfdxwLPWWy7/plI7oCLbNffHXm4zUQeRtsjGRP/EXhOKSfcABkpj49i5+9G/putgHmB\n5yxIN4iSF21C14V6Rtiu/yYSW15uHv4a4P8oKAedlPcvOAv4KmItfCTKKfAS8v8NR1ILHwnsl5GA\nqF7ORdYaGA48HGWyfBqYgViDRwCfQR72PkDgOU9E2TvHI4m0TgeeRczb30DyH2iKcyA0ymrgWNv1\nFyDK1NvIQ3tStN3LCH+9HUl29UPb9echFo8BUbtLEKfJtJ9EmgA59ifbrj8bCR3cGDlvZqdTLcPa\n9NCbUMhs2GFLKvPFSAKxZl7/CxEL8pgoA+QMxD+kE3HenAHcHnjOGmNB6Dt8iGjHWSFKK4HHkcQr\nOxvloLXYrr+77fqrEIejNyiE6P0WccZbabv+lFLtG+Ry5AY/BHkYfRDtR9M79QAAA3FJREFUcwYS\nNdCFwHPuQR6a7wHfAR5GMhk+i9xcT6G6KIOKBJ6zFBn9r0GUmBlIWN9ziHf/5yjO/phsfy2yqt4i\nxOJxF3INTI9k/Q7ZoV4xv0PC5LZCci4sQm6g08kYHdquvxy5lt4DwsSmF5EENCts1//Idv3M9LbR\negJTkEx4NvBA1joFifqLIjkeR6wcfwdeQfIFTEEcjHNU79RXkShvw95Ixs5+yOj/KuSh+ATiAHcq\nxb4fxwOXRfJMQc6zlxGF6B3g4MBznmmWnBFzEUfP0xDFcCGiAG+JHKushESXIdanjRBF4l3EInAj\n8vuOqWK/5yNRGaOQFNkfIhkOX6CQgwAA2/W3jkI3V0T7ejjatAFyXb2PXP/LbVnroWGi6bbzo697\nIlaWk5Br93wkk+jztusP7o94Lna7eaoMZU0cVXIAped7eqGZfP2ZqmPFl+ptrVf3n19UpvVMYLRS\nagBywxuEjLwWAe9qrTMXV2mUzs7OP/Xrp+6qt33Hmn5Zue3XNeZTOVoky5nqKiQkrNT883Qk3WvJ\nsMLAc1bbrv9Z5AH6KWRkOB+5wRWlWo7a3Ga7/mOIomAho/GFyI30YeDREru7ELlOq07TG3jONbbr\nT0Nu9KOQm+i/gFsDz3nTdv2fI2FbpdpfHnlpH4LcnHdAlIz5yLErqXgFnvOR7fo28lDYE7lu3kKO\nTdZ9K52xrhTl7knnUVB6SqVeTsr4apQU6lDEbG4hCsFbROsRBE1ebjrwnNB2/XGIGf5gRBkYhPyv\n7yDpjR9MtVkOnGK7/vWIgrFrVPcF4O8ZKbaXIuduWkH6KfL/JbkEsWClfWK2CDzHt10/jzhXjkGO\nyzNIZEiRD00ga3ocaLv+kUh2xo8hSuVURKmIUyiXVGYCWVzKQlJD7xrJNg85b9LX8RLgF6X6SpFU\n9Cpe28gaJgORqEEAbNffDLlvHIQoAndR8NEYilwjExD/nwuUiTQ0GAwGw7qC7fqjEUvKqsBzmhWd\nt05gu/5pyNoifw48J9N5PForxQeeNFMMBoPBYDD0DWL/llvK1In9jt4zCoLBYDAYDH2DePo5MwrJ\ndv0hFPwTnjBRDAaDwWAw9A3+hPgOHRPl25iK+FhsiuR4OARx0Lwf+J1REAwGg8Fg6AMEnvNklL78\nHMRRca/E5hVINNIVwI2B56z6/3ExLRI31pXNAAAAAElFTkSuQmCC\n", | |
|
133 | "prompt_number": 6, | |
|
134 | "text": [ | |
|
135 | "<IPython.core.display.Image at 0x111275490>" | |
|
136 | ] | |
|
137 | } | |
|
138 | ], | |
|
139 | "prompt_number": 6 | |
|
294 | "output_type": "execute_result" | |
|
140 | 295 | } |
|
141 | 296 | ], |
|
142 | "metadata": {} | |
|
297 | "source": [ | |
|
298 | "from IPython.display import Image\n", | |
|
299 | "Image(\"http://ipython.org/_static/IPy_header.png\")" | |
|
300 | ] | |
|
143 | 301 | } |
|
144 | ] | |
|
145 | } | |
|
302 | ], | |
|
303 | "metadata": {}, | |
|
304 | "nbformat": 4, | |
|
305 | "nbformat_minor": 0 | |
|
306 | } No newline at end of file |
@@ -1,312 +1,308 b'' | |||
|
1 | 1 | { |
|
2 | 2 | "cells": [ |
|
3 | 3 | { |
|
4 |
"cell_type": " |
|
|
5 | "level": 1, | |
|
4 | "cell_type": "markdown", | |
|
6 | 5 | "metadata": {}, |
|
7 | 6 | "source": [ |
|
8 | "nbconvert latex test" | |
|
7 | "# nbconvert latex test" | |
|
9 | 8 | ] |
|
10 | 9 | }, |
|
11 | 10 | { |
|
12 | 11 | "cell_type": "markdown", |
|
13 | 12 | "metadata": {}, |
|
14 | 13 | "source": [ |
|
15 | 14 | "**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus bibendum felis dictum sodales. Ut suscipit, orci ut interdum imperdiet, purus ligula mollis *justo*, non malesuada nisl augue eget lorem. Donec bibendum, erat sit amet porttitor aliquam, urna lorem ornare libero, in vehicula diam diam ut ante. Nam non urna rhoncus, accumsan elit sit amet, mollis tellus. Vestibulum nec tellus metus. Vestibulum tempor, ligula et vehicula rhoncus, sapien turpis faucibus lorem, id dapibus turpis mauris ac orci. Sed volutpat vestibulum venenatis." |
|
16 | 15 | ] |
|
17 | 16 | }, |
|
18 | 17 | { |
|
19 |
"cell_type": " |
|
|
20 | "level": 2, | |
|
18 | "cell_type": "markdown", | |
|
21 | 19 | "metadata": {}, |
|
22 | 20 | "source": [ |
|
23 | "Printed Using Python" | |
|
21 | "## Printed Using Python" | |
|
24 | 22 | ] |
|
25 | 23 | }, |
|
26 | 24 | { |
|
27 | 25 | "cell_type": "code", |
|
28 | 26 | "execution_count": 1, |
|
29 | 27 | "metadata": { |
|
30 | 28 | "collapsed": false |
|
31 | 29 | }, |
|
32 | 30 | "outputs": [ |
|
33 | 31 | { |
|
34 | 32 | "name": "stdout", |
|
35 | 33 | "output_type": "stream", |
|
36 | 34 | "text": [ |
|
37 | 35 | "hello\n" |
|
38 | 36 | ] |
|
39 | 37 | } |
|
40 | 38 | ], |
|
41 | 39 | "source": [ |
|
42 | 40 | "print(\"hello\")" |
|
43 | 41 | ] |
|
44 | 42 | }, |
|
45 | 43 | { |
|
46 |
"cell_type": " |
|
|
47 | "level": 2, | |
|
44 | "cell_type": "markdown", | |
|
48 | 45 | "metadata": {}, |
|
49 | 46 | "source": [ |
|
50 | "Pyout" | |
|
47 | "## Pyout" | |
|
51 | 48 | ] |
|
52 | 49 | }, |
|
53 | 50 | { |
|
54 | 51 | "cell_type": "code", |
|
55 | 52 | "execution_count": 3, |
|
56 | 53 | "metadata": { |
|
57 | 54 | "collapsed": false |
|
58 | 55 | }, |
|
59 | 56 | "outputs": [ |
|
60 | 57 | { |
|
61 | 58 | "data": { |
|
62 | 59 | "text/html": [ |
|
63 | 60 | "\n", |
|
64 | 61 | "<script>\n", |
|
65 | 62 | "console.log(\"hello\");\n", |
|
66 | 63 | "</script>\n", |
|
67 | 64 | "<b>HTML</b>\n" |
|
68 | 65 | ], |
|
69 | 66 | "text/plain": [ |
|
70 | 67 | "<IPython.core.display.HTML at 0x1112757d0>" |
|
71 | 68 | ] |
|
72 | 69 | }, |
|
73 | 70 | "execution_count": 3, |
|
74 | 71 | "metadata": {}, |
|
75 | 72 | "output_type": "execute_result" |
|
76 | 73 | } |
|
77 | 74 | ], |
|
78 | 75 | "source": [ |
|
79 | 76 | "from IPython.display import HTML\n", |
|
80 | 77 | "HTML(\"\"\"\n", |
|
81 | 78 | "<script>\n", |
|
82 | 79 | "console.log(\"hello\");\n", |
|
83 | 80 | "</script>\n", |
|
84 | 81 | "<b>HTML</b>\n", |
|
85 | 82 | "\"\"\")" |
|
86 | 83 | ] |
|
87 | 84 | }, |
|
88 | 85 | { |
|
89 | 86 | "cell_type": "code", |
|
90 | 87 | "execution_count": 7, |
|
91 | 88 | "metadata": { |
|
92 | 89 | "collapsed": false |
|
93 | 90 | }, |
|
94 | 91 | "outputs": [ |
|
95 | 92 | { |
|
96 | 93 | "data": { |
|
97 | 94 | "application/javascript": [ |
|
98 | 95 | "console.log(\"hi\");" |
|
99 | 96 | ], |
|
100 | 97 | "text/plain": [ |
|
101 | 98 | "<IPython.core.display.Javascript at 0x1112b4b50>" |
|
102 | 99 | ] |
|
103 | 100 | }, |
|
104 | 101 | "metadata": {}, |
|
105 | 102 | "output_type": "display_data" |
|
106 | 103 | } |
|
107 | 104 | ], |
|
108 | 105 | "source": [ |
|
109 | 106 | "%%javascript\n", |
|
110 | 107 | "console.log(\"hi\");" |
|
111 | 108 | ] |
|
112 | 109 | }, |
|
113 | 110 | { |
|
114 |
"cell_type": " |
|
|
115 | "level": 3, | |
|
111 | "cell_type": "markdown", | |
|
116 | 112 | "metadata": {}, |
|
117 | 113 | "source": [ |
|
118 | "Image" | |
|
114 | "### Image" | |
|
119 | 115 | ] |
|
120 | 116 | }, |
|
121 | 117 | { |
|
122 | 118 | "cell_type": "code", |
|
123 | 119 | "execution_count": 6, |
|
124 | 120 | "metadata": { |
|
125 | 121 | "collapsed": false |
|
126 | 122 | }, |
|
127 | 123 | "outputs": [ |
|
128 | 124 | { |
|
129 | 125 | "data": { |
|
130 | 126 | "image/png": [ |
|
131 | 127 | "iVBORw0KGgoAAAANSUhEUgAAAggAAABDCAYAAAD5/P3lAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\n", |
|
132 | 128 | "AAAH3AAAB9wBYvxo6AAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURB\n", |
|
133 | 129 | "VHic7Z15uBxF1bjfugkJhCWBsCSAJGACNg4QCI3RT1lEAVE+UEBNOmwCDcjHT1wQgU+WD3dFxA1o\n", |
|
134 | 130 | "CAikAZFFVlnCjizpsCUjHQjBIAkQlpCFJGS79fvjdGf69vTsc2fuza33eeaZmeqq6jM9vZw6dc4p\n", |
|
135 | 131 | "BUwC+tE+fqW1fqmRDpRSHjCggS40sBxYDCxKvL8KzNBaL21EPoPB0DPIWVY/4NlE0ffzYfhgu+Qx\n", |
|
136 | 132 | "GHoy/YFjaK+CcB3QkIIAHAWs3wRZsuhUSs0CXgQeBm7UWi/spn0Z+jA5yxpEfYruqnwYllRic5a1\n", |
|
137 | 133 | "MaWv8U5gaT4M19Sx396IAnZLfB/SLkEMhp5O/3YL0AvoAHaKXl8HLlZK3QZcpbWe0lbJDOsaHuDU\n", |
|
138 | 134 | "0e4u4JAy2wPk/C1JzrKWArOQ0fUtwH35MOysQxaDwbCO0NFuAXoh6wPjgQeUUvcqpUa0WyCDoQls\n", |
|
139 | 135 | "CIwBjgfuAV7KWdY+7RWpmJxlXZezrEdylvXxdstiMKzrGAtCYxwI/EspdZbW+g/tFsbQ67kQuBHY\n", |
|
140 | 136 | "FNgseh9FV6vCbUAeWBC9PgBeq2EfS6J2MQOBrRDTe5KdgAdzlvW1fBjeUUP/3UbOsoYBE6OvG7VT\n", |
|
141 | 137 | "FoOhL9Af+BUwFLkZpV+DaY6V4UPkRpb1+ncT+m8nGwK/V0oN01qf025hDL2XfBi+DLycLMtZVo6u\n", |
|
142 | 138 | "CsKfGnSq8/NheEpqHwOBEcDBwJnAsGhTP2ByzrJG5cPwnQb22Sy+0G4BDIa+RH+t9dmlNiqlFKIk\n", |
|
143 | 139 | "JJWGi+jq5JPmq8BbJJQArfXqpkncczlbKbVQa/3rdgtiMNRCPgxXAK8Ar+Qs63LgXmDvaPPGwPeA\n", |
|
144 | 140 | "H7VJvCRfbLcABkNfouwUg9ZaAwuj178BlFLvVejzgR4WFviM1npcuQpKqf6IyXIjxLS7GzAWuUnu\n", |
|
145 | 141 | "XsO+fqWUellr3ZBJdq/jr9+BDn1uve07O9Rz0y6f8PtGZGgWe53oT6SBkZ/q1/nHZy47aloTRTKU\n", |
|
146 | 142 | "IR+Gy3OWNR6Zxtg0Kv4KRkEwGPocxgcBiCwcsSI0F5iOhF+ilPok8C3gVGS+thK/VErdrbWuO2ys\n", |
|
147 | 143 | "s/+aLZTuOKbe9krrIUCPUBB0B+PQ1P1bdKe6EzAKQgvJh+GbOct6gkJkxM45y+qXDIWMHBhjBWJe\n", |
|
148 | 144 | "PgyDWvaRs6zPIVObAG/nw/DpEvUGAp8E9gGGJzbtl7Os7cvs4skqp0V0Yl8jgcOBjyMDhbmIZeWl\n", |
|
149 | 145 | "fBg+UUVfReQsayhwELAnsAXi6/E28BxwTz4MP6iyn92RaSCA+/NhuCwqXx9R4MYhU0MfRTK/AjyW\n", |
|
150 | 146 | "D8MFGd0ZDFVhFIQKaK3/BXxfKXUlklTq0xWafAI4Driyu2UzGLqRlygoCArYHJif2H4gcFb0+Z2c\n", |
|
151 | 147 | "ZW2bD8NV1XScs6yNgH8g/jsAPwCeTmzfFPgjYsnbiez71MUVdnMQcF8V4nyUs6whwB8QX4+0s2Ys\n", |
|
152 | 148 | "0yPAt/NhGFbRZ/wbzgO+DaxXotqqnGX9GbigCkXhf5CBCsDngYdzljURGQhsWqLN+znL+iFwdT4M\n", |
|
153 | 149 | "dYk6BkNJTJhjlWitQ2Bf4P4qqv848t8wGHor6Yd9+ruHJFkC2BI4rIa+D6egHKwmstYlGAxMQCwH\n", |
|
154 | 150 | "rRjEPI5ER5S7ZvcFXsxZ1phKneUsawSi8HyH0soB0bbvAM9Ebaplt5xlnYkct1LKAYiFZhJwSQ19\n", |
|
155 | 151 | "GwxrMRaEGtBar1RKfRX4JxIzXortou3PN1mE+YgJsSwaeoLHOQCqUy3QSr9eqZ6G/gq2aYVMhqrY\n", |
|
156 | 152 | "OfF5FeJwvJZ8GM7JWdY/gC9HRS7wtyr7Pjrx+e6MqYC3KLbU7Qhck/h+FJIKvRRVjfSREXicU8EH\n", |
|
157 | 153 | "pgAvIIqLBZwGfC7avl5Uf29KkLOsTZCMq8npj9sQx89no37HIlaAODplNPBIzrJ2z4dhNVlaT0HC\n", |
|
158 | 154 | "XwFmIkrAC4if2PaIz8/3KCgn385Z1pX5MJxeRd8Gw1qMglAjWutlSqnTgUcqVP0SzVYQtP5mcMXE\n", |
|
159 | 155 | "SvvtUUy9YsK5QEWHy7EnTB6lOtSsFohkqEDOsgYAdqJoagkT9Z8pKAj75yzr4/kwnF2h748ho/GY\n", |
|
160 | 156 | "q9J1oqiKLj4JOctKK8Yz8mH4Yrl9VcnHkXVYTsyHoZ8WJWdZNyPThbF5/3M5yzowH4alpi9+T0E5\n", |
|
161 | 157 | "WA18Nx+Gf0zVeRG4KmdZ90R9bwCMRKwyX69C5h2j91uA4/JhuCSxbTYwJWdZtwNPIFbifsAFSISZ\n", |
|
162 | 158 | "wVA1ZoqhDrTWjyIjjXIc3ApZDIZu4ELgY4nvt5Wody8wJ/qsgBOr6HsihfvOfCRrY7v5dYZyAECk\n", |
|
163 | 159 | "GP0ISEZmZYZ55yxrB8SyEXNxhnKQ7Pt64H8TRUfmLGuXKmWeC4xPKQfJvp9CLCJlZTYYymEUhPq5\n", |
|
164 | 160 | "tcL2XVsihcHQJHKWtU3Osi5GnAZj5iKWgiKitRouTxQdl7OscnPu0HV64dp8GLY7R8pyxEGxJPkw\n", |
|
165 | 161 | "fBcZ9ceUSvN8IoV76upK/UZcgawcG3NKqYopfleFU+gDic/b5SzLWIwNNWFOmPqp5CG9sVJqPa11\n", |
|
166 | 162 | "VZ7dBkOL2D1nWcmcBkOR8MFtgM/QdTXJZcCR+TBcXqa/SYj5egAFZ8VMX4ScZe2FRPnEXF2z9M3n\n", |
|
167 | 163 | "3nwYVsrtAmK6/0z0uVR4ZXLtivvzYfhGpU7zYbgkZ1k3ACdHRQdWIQsUO3ZmkUzB3Q/xjaolLbeh\n", |
|
168 | 164 | "j2MUhDrRWr+mlFpJ+eV5hyIxz4YWs98Fj/Rf8uZbozo0/ZYt7D8rf9ORK9stUw/hU9GrEnMAp1R+\n", |
|
169 | 165 | "gph8GL4bzdNPiIpOorSzYtJ68FS1IYPdTLWp3hcnPm+Q3pizrA7E+TCmFn+aZN0dcpY1LB+G5e4b\n", |
|
170 | 166 | "y6rM8bA49X39GmQyGMwUQ4NUGnkMrbDd0A3sdeLk4z6cN+89pTtDTWd+gyErF+7pTv5eu+XqJbyK\n", |
|
171 | 167 | "TDHsmg/DJ6tsc2ni8+dzljUqXSGaevhmoqjIObFNVBzlV8kQug4W5tbQNl13WGatAv+poW+DoW6M\n", |
|
172 | 168 | "BaExPgC2LrO9nHWhpSilDqI4NPMhrfXUJvS9M/DfqeJXtdY3N9p3rex50uQ9lFKT6BrTvoFCXbTX\n", |
|
173 | 169 | "yZNfmnrZxHtbLVMP4xng74nvK5DzeD7wfIWRayb5MHwiZ1kzgF0oOCuemar2ZQoK8zLgr7Xup5t4\n", |
|
174 | 170 | "s0n9DEl9b0RBSPeV5q0a+jYY6sYoCI1RacnZ91siRXUMAH6eKnsYicdulDOAY1NlpzWh35pRqG9R\n", |
|
175 | 171 | "IuGN7uw4AfG878s8nw/DX3RDv5dScGY8NmdZP86HYXJaJzm9cHMp7/s2UHdK9BTpKaxBNbRN163k\n", |
|
176 | 172 | "t9Rux05DH8FMMTTGZhW2v9sSKarjbopNk/sqpUY30qlSahCSGS/JCuD6RvqtF6UpMm/HaHTJbYaG\n", |
|
177 | 173 | "mQzED/0umRVzlrUZhXwJ0HOmF5pJOlXyxzJrZbNt6rtZP8HQIzAKQp0opTZAlsItxTKtdTnv75YS\n", |
|
178 | 174 | "LR7lpYqrjV0vx2EUH4fbtdZtucnpMqOrDjPy6jYii8DkRFHSYnAEhem22cBjrZKrVeTDcCldTf/p\n", |
|
179 | 175 | "h345ksrEGprnF2EwNIRREOrnMxW2z2uJFLVxJcXmy2OVUo34ShydUda+EaIq7T2u0SZTY/eSdFY8\n", |
|
180 | 176 | "MGdZm0efk86J6/LCQUnFp5pIkZjkcvQz8mH4YZPkMRgawigI9VNp7v7BlkhRA1rr+RQneNqC2hba\n", |
|
181 | 177 | "WYtSajiS9z3JXLomaGktq/VllLIUdKqSWe0MjZMPwxlIel8Q/6Zv5CxrGIX8AJ10XU+hFtIRQ+UW\n", |
|
182 | 178 | "KWoXyYyTu+Qsa79KDXKWNRpJyx5zZ9OlMhjqxCgIdaCU6g98o0K1npBCNotLM8rcOvuagCRgSXKN\n", |
|
183 | 179 | "1rozq3IrCCZNfFkrfRjotWsCaJinUBODK51/tkuuPkTy/DoYOIDCfeb+fBjW4t2/lqhdcmRdbUri\n", |
|
184 | 180 | "VnILXS2HZ1WRvfAcCk61K4A/dYdgBkM9GAWhPr5F6XSrIBf6Qy2SpSaidSReShV/XilV7veUIj29\n", |
|
185 | 181 | "oOkB2fGmXT7x7sCbOGpFf7VZx4A1m0/znG2nehMyc+0bms7NFJxzxwH7J7Y1OvWUPG9/mLOsLRvs\n", |
|
186 | 182 | "r6lEaaOT0TtfBB5ITLWsJWdZg3KWdRNwTKL4wnwYzu9mMQ2GqjFhjjWilBqBpJYtx51a66UV6rST\n", |
|
187 | 183 | "S+maJz52VvxRdvVilFK7UbzexGNa67Kr+bWS6X+ekPYs79HkLGt34JOI+Xyz6D2d1vfMnGUdini6\n", |
|
188 | 184 | "L0C851/Oh2HD+SyaQT4MV+YsaxJyLm1Gwf9gAXBHg93/JNHHtsArOcuajCztPBDYCkkytBXg5sOw\n", |
|
189 | 185 | "5QmF8mF4W86yLgK+HxXtC8zKWVaALMm8CslHsicS7RFzL8VhyAZDWzEKQg0opbYE7qd8prPVdF2h\n", |
|
190 | 186 | "rSdyLfALYMNE2XFKqR/XsHbEURll62L4Wiv5PuBUqPPF6JXkLuCQbpGoPi4HfohYKGMHWD9axrlu\n", |
|
191 | 187 | "8mF4Z7RuwfioaDBwaonqRemQW0U+DH+Qs6xFwHnIFNwQsv+3mMnA8dHiVwZDj8FMMVSJUuow4DkK\n", |
|
192 | 188 | "a7GX4gqt9cstEKlutNaL6boULMho5tBq2iul+lH8IFuCmJcNfZx8GM6hOCFVU5THfBhOQHxfylkH\n", |
|
193 | 189 | "3gY+asb+6iUfhhcCewC3l5BlFbJk/P75MDwqlVTKYOgRKK1rizhSSk2h67ximo1abV5XSi2n9EIk\n", |
|
194 | 190 | "z2itx5XYVqnfQcjI7DiqW2XtfeCTUbRA3ex50nWfUrqjeJEcrfcLrpj4SCN9xyilxgDPp4of0Fof\n", |
|
195 | 191 | "UEXbg4B/pIqv1FrXnVNh7AmTR3V0qIwwRH1E4E28pd5+De0hZ1m/Bb4bfX0+H4Z7dMM+hgGjkDwC\n", |
|
196 | 192 | "S5FpjFk9bR4/Z1mDkGmF4VHR20g4Y3oxJYOhR9EXphg6lFLlVjFbH0mZvDGwCTAayCFe0ntTOZ1y\n", |
|
197 | 193 | "zDLgkEaVg1ahtX5BKfUU8OlE8ReUUjtorSstCduzch8YehSR5/6ERFG3nBvRuhE9frXUfBguA6pd\n", |
|
198 | 194 | "+Mpg6DH0BQXBBro7o+Ea4Bta66e6eT/N5lK6KggKOAE4u1QDpdTGFOdNmNkLf7uh+zgYcRQEMa+3\n", |
|
199 | 195 | "Je22wWBoDOOD0DhLgYla67vaLUgd3ETxglLHRXkeSnEExQ5gbQ9tNPQokis5TsqHoVlbwGDohRgF\n", |
|
200 | 196 | "oTECYHet9Y3tFqQetNYrKDb/DqN46eYk6emF1UhUhMFAzrImUEhDvgr4VRvFMRgMDWAUhPpYAvwf\n", |
|
201 | 197 | "8Bmte31+/8uQBEdJMjMrKqW2o5A2N+YfWusePw9s6F5yltWRs6zxwKRE8RXtyEVgMBiaQ1/wQWgm\n", |
|
202 | 198 | "eWTe/jqtdU9Zz74htNavKaXuAw5KFB+glBqptZ6Tqj6RQlrYGDO90AfJWdY5wNeQFQwHIAmetk5U\n", |
|
203 | 199 | "eZFCsiCDwdALMQpCed5AphEC4NF12BHvUroqCAoJ7TwvVS+d++BdJEmPoe+xKRLnn0UeODwfhm3N\n", |
|
204 | 200 | "RWAwGBqjLygIbwN/LbNdI1MGH6ReL/eWkMUmcDeSeGa7RNlRSqnzdZQoQym1C7Bzqt11NWReNKxb\n", |
|
205 | 201 | "zEMU6GHAesBiYCaSLOviaF0Cg8HQi+kLCsLrWuvT2y1ET0ZrvUYp5SG57mO2Bz4LPB59/2ZRQ5P7\n", |
|
206 | 202 | "oM+SD8OLgYvbLYfBYOg+jJOiIeZKxOs8STJiIb28daC1/lf3imQwGAyGdmEUBAMA0XTKraniI5VS\n", |
|
207 | 203 | "A6O0zOnloI31wGAwGNZhjIJgSHJp6vtgJBNlehW65cANLZHIYDAYDG3BKAiGtWitHwVeShV/muLF\n", |
|
208 | 204 | "uW7VWi9qjVQGg8FgaAd9wUnRUBuXAn9IfN8f+FyqTo/OfbDnSX8brDpXnqEUe2ropzQvdtDx66ev\n", |
|
209 | 205 | "GN9XolIMPQDb9T8LrBd4zsPtlsXQe7Bd/0BgQeA5QbtlMQqCIc21wC+ADaPv6WWu5wAPtVKgWtjt\n", |
|
210 | 206 | "6Os2XG/9jhdQjIzTQ2rFF9bQecy4E2/I9UQlwXb9LYDDK1R7K/Cc21shj6FxbNcfDjwGKNv1Rwae\n", |
|
211 | 207 | "83q7ZWo2tusPBb6ELGW9BbAICX99Gngs8Jx0hlZDBWzXHwvcC6ywXX9o4DlL2ymPURAMXdBaL1ZK\n", |
|
212 | 208 | "+ZRItwz8Jc6N0BMZMFB9GxiZsWnzTjrPAH7QWomqYgTF/h9pngC6RUGwXf+XwC2B50ztjv57M7br\n", |
|
213 | 209 | "XwJMCjxneo1NP0SWgAfJq7LOYLv+esAFwOkUL9wWM912/d0Dz+lsnWQ9A9v1BwEXAT8PPKfWVOML\n", |
|
214 | 210 | "kPVt3kNWQm0rxgfBkEWph5UG/tJCOWqnQ40ttUkrvWcrRamWwHOmAZsguSfGAi9Hmy5AUhgPAz7f\n", |
|
215 | 211 | "Hfu2XX8k8ENgx+7ovzdju/4uwP9D/peaCDxnCbANsF3gOYubLVu7sF1/AHAHcBaiHDwI/C+ywNsE\n", |
|
216 | 212 | "4KfA68BdfVE5iNgbOBmxqtRE4Dn/BoYDnwg8Z02zBasVY0EwFKG1fkEp9RTioJjkIa11zzaVarYq\n", |
|
217 | 213 | "vVFt2TpBaiN6oCwB5tiu/2FUPCvwnLTTaLM5oJv77800dGwCz1kXHXkvRNKydwI/Cjzn1+kKtuuf\n", |
|
218 | 214 | "i2TX7Ks0et681yxBGsUoCIZSBBQrCL0h98EbdW7rddiuPwoYFJu/bdffFNgL2BZ4DZgWKR5ZbRWS\n", |
|
219 | 215 | "2+KIqGiE7fpjUtXmlrtZRdaHscBAYDowM/CckimWbdffFfgw8JzXou/9kfUccojV5MXAcz4s0XYw\n", |
|
220 | 216 | "sCsymu8PzAVmBJ7zVqn9pdoPRVKF7wSsAN4EgqzRve36HcAoZDEqgO0zjs3rged8kGo3gOJ05ADT\n", |
|
221 | 217 | "s0bTkan+k9HXGaVGjNFxykVf81nH2Hb9Ich/MRJJeT291H9fL7brj6CwANfPspQDgOi3rijRx/rI\n", |
|
222 | 218 | "b8kB7wPPBZ4zL6Ne/JvfCDzn/WhufhvgvsBzVkR1dgN2AR4JPGduom38P7wXeM7c6FzfCfgU4iMR\n", |
|
223 | 219 | "lFLebNfPIefXzMBzikz8tusPQyx676bljmTeCfhyVLST7frp//TV9Dluu/6GwOhUvTWB58zIkjFq\n", |
|
224 | 220 | "sykyNfmfwHMW2K7fLzoWeyDTFPnAc14t1T7qYwNgT+Rc/wi5ZyT/N20UBEMRSqn+wNdTxQspTqTU\n", |
|
225 | 221 | "41BaP6yVOipzGzzSYnG6m6uBz0YPv7OQm3dytc35tuuflHZutF3/BuArwEaJ4p/QNdU2wGnAH9M7\n", |
|
226 | 222 | "jRSTG5CbS5LQdv2joymTLKYBzwHjbNc/DomW2TCxfbXt+sMCz3k/sa8RwM+Qh/X6qf5W2q4/CTit\n", |
|
227 | 223 | "zMN1OPB7CopQktW2658YeM5fEvXvRKZzBiXqZaWUPha4JlW2NfB8Rt0hiANfmjWIuf5jiLPfvVm/\n", |
|
228 | 224 | "AfmvbgNmB54zKrkheuD+Bjg11Wap7fpnBJ5TybelFk4E+iE+Fb+ptbHt+scg//nGqfJbgeMDz1mY\n", |
|
229 | 225 | "KN4UOZYX2q7fSWHhuNdt198ZOBc4MypbbLv+5wPPeTb6PiJqe5ft+ichx3WXRN8rbdc/OfCcrGis\n", |
|
230 | 226 | "R4ChiHKSlSn2f4BzkOvitMRvCKJ9DEzU9TPafwGZlkkyBvExSrKUrtdnmoOBycA5tus/iCyat3li\n", |
|
231 | 227 | "u7Zd/0rk2ihS1mzXPwT4E3LulaLTKAiGLL6EaMlJbtBat91pphIjFw289t9DVh4N7Jva9EKnWnpJ\n", |
|
232 | 228 | "G0RqBXcjCa08YCqy/PJE4L8A33b9HQPPeTNR/0bgvujzGchoywPSq5U+nd6R7fp7IDfRjYDrEE99\n", |
|
233 | 229 | "DeyHrPb5lO364xI36zTb2q4/AUnt/SSyLHQHMvJZklQOIhYChyCLid2FWBoGIQrDfwGnAP8Gskzd\n", |
|
234 | 230 | "VvSbBgPvIMdpJjLHuxdikXgg1ewa4Jbo84+BHRAFI/3gT9/QQZa+/iIy9zwccVQrSeA5nbbrX4s8\n", |
|
235 | 231 | "cI6htIIQK7xdFJLIAvEEYjmYBlyP/E4LeXj92Xb94YHnnFtOjhrYJ3q/vtbpE9v1fwqcjYxUL0GO\n", |
|
236 | 232 | "51bI//g1YIzt+mNTSgJIivfNEIXgBOThfx0ySv8Nct7vgzgfj0+1HQf8E5iPKM/vI+vLHA9cZbs+\n", |
|
237 | 233 | "JZSEevgDBZ++3yIKzgVI1FeSrCnD6ci0zebAJxCfjmoZjxzXPPBL5By0gW8jCt3sqHwtkYL1N0RB\n", |
|
238 | 234 | "/R2ymOG2yHE5CLFAHAu8ahQEQxbfyijrDdML3HTTkWvUBRfsb88bPb6TzjEK+oHKL184YHL+Jmdl\n", |
|
239 | 235 | "u+XrJsYBhwaec0dcYLu+hzw0dkcu/AvjbUmLgu36DqIgPB54zuQq9nURMgI8LjnyBibZrj8z2s/l\n", |
|
240 | 236 | "tuvvVcJJbWvkXDoi8JzbKu0s8JxFtut/IqXgAPzOdv0/IiPnb5KhICAjpMGIEjAhPV1iu35HWsbA\n", |
|
241 | 237 | "c25ObD8ZURAeqibENBqpTYnark8FBSHiakRBOMx2/cHpB29kSv4KooSlLRYnIcrBHcBXk7/Fdv0b\n", |
|
242 | 238 | "gReAM23Xvz7wnJlVyFIJK3qfXUsj2/U/jiiiq4B9ktEytuv/Fhlpfx2xEnw31XxHYLfAc6bbrv8k\n", |
|
243 | 239 | "cny/Bnwz8Jy/2q6/DTLd9F8Zu94ceXAeEHhOvM7MNbbrT0UU4vNs15+c2FY3gedcm/hNP0EUhDvL\n", |
|
244 | 240 | "KMrJtkuIFPboWNWiIOSAO4HDE7/Dj67FSxEn21+m2pyOWDpuCDxn7fG2Xf8e4F1EIVsceE5oohgM\n", |
|
245 | 241 | "XVBKjURuSEke11qXMhv3OPR553VO9Sb407yJZwTexO8FnnNV/qYj11XlAOCfSeUA1s4D/y36mp7f\n", |
|
246 | 242 | "rAvb9fdGLDMzU8pBzMXIg2wsMhLKQiFhgxWVg5gM5SDm+uh9VHqD7fr7IlaNFcAJWb4UPcHLPvCc\n", |
|
247 | 243 | "2YgVZn3gyIwq30AsQg8lQ+aiefUfR1/PzlB08sD9Udusfmsi2t+Q6GutjspnIE6L16dDaSN/irMR\n", |
|
248 | 244 | "p8dTbddPOxK/nwgxTZr8747e30SsEkNL7PvXGQrAVYgvwggK/gK9mXMyfuON0fvWkY9Dkp2i97uT\n", |
|
249 | 245 | "hYHnLKNgURsDxknRUMz5FJ8XP22DHIbqSc9pxsSOW8ObtJ89ovdXbNcvpQC8j4zcdiTbnAoy4q2b\n", |
|
250 | 246 | "6Ia3CYV5/Y0zqsXOf4/WEYveaq5GQuOOQaZekhydqJNkW2BLZF2UzhL/R+xE2XAIa+A52nb9lUho\n", |
|
251 | 247 | "Y63hd7GD5d1ZGwPPmW27/iuIUrkLXc/n9xP13rZd/yNgVezoF8n1NjAyyyKETGGl97fGdv1/IlaL\n", |
|
252 | 248 | "3h7e+06WM2PgOQtt11+GTMcNo6vVJ1aWsyK+4nvFQjAKgiGBUmoshfnOmGe11vdl1Tf0GOaUKI9v\n", |
|
253 | 249 | "lqrE9lqJb6b/Hb3KsU2Zba/VslPb9bdDfA0ORLz0N62iWWxVqMkc3iZuRuawP2u7/g6JKI9RSCTR\n", |
|
254 | 250 | "YoodhOP/YgNKK2Ix2zZJzjnINMN2NbaL/4uiaIUE/0EUhB3pqiCkMwl2IscjXZZFJ/B2iW1xRtWR\n", |
|
255 | 251 | "ZWTqDcwps63U9f8Q0TSN7fp/iK0PtuvviPjmrCHyR1qrICilNkTmHjZDLsDke/JzOtwnzY1KqXcR\n", |
|
256 | 252 | "R4cFiBab9XlRT87I19dQSo1GNPz0tJOxHvR8mhrOVobB0XuAOBiWo1zmwaqdXW3X3x+4BzGVv4SM\n", |
|
257 | 253 | "pN9AnPEg21McxMIArTs2dRN4zoe26/8NOA6xGJwfbYqV9b8GnrM81Sz+Lz5A0qOXo2y4Ww3MoT4F\n", |
|
258 | 254 | "IY4+KTfNF58TaXN4VthstVNDitLKcdxvOjKmEj0tv0M953fs87E3Eul0B2JliBflOzfwnFcA+iul\n", |
|
259 | 255 | "5iEmwQFNEBaK569L0amUWggcqrXO8gg2FKHG2CdW4Uem9XvBlUflu7RUaiByU3lPa92ZKN8cSav8\n", |
|
260 | 256 | "fUQBTHKr1rrqueIsxp18/eg1azrLjSYB6NfRsY3G6Is9nDjDYxh4zundvbMotvtm5N50duA5P09t\n", |
|
261 | 257 | "T0faJIkfirU+zNrF1YiC4FBQECZE73/JqB//F+u14r+ImIVEOB1iu/6ZNfhwzEamp7YuU2e7RN1m\n", |
|
262 | 258 | "oZBnW5YVIfZ1qNWfotw51yuIph++hET0bAkcikwpTAEuCjxnSly3PzIP0a8NcnYgD6SBlSoaIhQX\n", |
|
263 | 259 | "V2UtVup24LBU6S7IyG+NUuodZP52awojrTSvIjeshlij9XdQKh2jXYRRDtpGfOCruQfEpmzbdn0V\n", |
|
264 | 260 | "dP9iPLsgjnEryI67Lzd/PCt6/5Tt+v3LJXAqQ/z7ut2ZO/Ccx23XfxUYZbt+7D8xCngl8Jwsa80s\n", |
|
265 | 261 | "ZBS8ke36O7cg4ybA5UgegJ0QE/XN5auvZRaiIMQRF12wXX8TCv9ls6eERpOtIMR+EXNS5YsRh8dS\n", |
|
266 | 262 | "To/V+CzUck21i6uR5++4wHNeKFXJRDH0PfoR5fqmtHKwDDhCa73O5JA3lCSeF04v6Z3FPRTMzBO7\n", |
|
267 | 263 | "S6AE8Q12PbomgYn5Xpm29yMPhu2RUK96iKMn9q6zfa38JXo/NHoly7oQeM5K4Iro60+jKINuJVJC\n", |
|
268 | 264 | "Yu/439uuX805A4VkWyfbrp+V/MdFnOmeCmpfFKsSRYMc2/U/DeyG3OfSjpOx5WmfVHmcuXFcFfus\n", |
|
269 | 265 | "5ZpqObbrb45EtswqpxyAcVI0FDMbOFxrXeT9a+heopvnEArzolvashT0wmbEapdgGpIU5XDb9R9F\n", |
|
270 | 266 | "YqrXQyyL8wPPeTeuGHjOMtv1T0VuqldH6W//jigNmyHOcAcBgwPPcZog20xkRLcJ8DPb9S9CRqM7\n", |
|
271 | 267 | "I7kDvoDE1hfdxwLPWWy7/plI7oCLbNffHXm4zUQeRtsjGRP/EXhOKSfcABkpj49i5+9G/putgHmB\n", |
|
272 | 268 | "5yxIN4iSF21C14V6Rtiu/yYSW15uHv4a4P8oKAedlPcvOAv4KmItfCTKKfAS8v8NR1ILHwnsl5GA\n", |
|
273 | 269 | "qF7ORdYaGA48HGWyfBqYgViDRwCfQR72PkDgOU9E2TvHI4m0TgeeRczb30DyH2iKcyA0ymrgWNv1\n", |
|
274 | 270 | "FyDK1NvIQ3tStN3LCH+9HUl29UPb9echFo8BUbtLEKfJtJ9EmgA59ifbrj8bCR3cGDlvZqdTLcPa\n", |
|
275 | 271 | "9NCbUMhs2GFLKvPFSAKxZl7/CxEL8pgoA+QMxD+kE3HenAHcHnjOGmNB6Dt8iGjHWSFKK4HHkcQr\n", |
|
276 | 272 | "OxvloLXYrr+77fqrEIejNyiE6P0WccZbabv+lFLtG+Ry5AY/BHkYfRDtR9M79QAAA3FJREFUcwYS\n", |
|
277 | 273 | "NdCFwHPuQR6a7wHfAR5GMhk+i9xcT6G6KIOKBJ6zFBn9r0GUmBlIWN9ziHf/5yjO/phsfy2yqt4i\n", |
|
278 | 274 | "xOJxF3INTI9k/Q7ZoV4xv0PC5LZCci4sQm6g08kYHdquvxy5lt4DwsSmF5EENCts1//Idv3M9LbR\n", |
|
279 | 275 | "egJTkEx4NvBA1joFifqLIjkeR6wcfwdeQfIFTEEcjHNU79RXkShvw95Ixs5+yOj/KuSh+ATiAHcq\n", |
|
280 | 276 | "xb4fxwOXRfJMQc6zlxGF6B3g4MBznmmWnBFzEUfP0xDFcCGiAG+JHKushESXIdanjRBF4l3EInAj\n", |
|
281 | 277 | "8vuOqWK/5yNRGaOQFNkfIhkOX6CQgwAA2/W3jkI3V0T7ejjatAFyXb2PXP/LbVnroWGi6bbzo697\n", |
|
282 | 278 | "IlaWk5Br93wkk+jztusP7o94Lna7eaoMZU0cVXIAped7eqGZfP2ZqmPFl+ptrVf3n19UpvVMYLRS\n", |
|
283 | 279 | "agBywxuEjLwWAe9qrTMXV2mUzs7OP/Xrp+6qt33Hmn5Zue3XNeZTOVoky5nqKiQkrNT883Qk3WvJ\n", |
|
284 | 280 | "sMLAc1bbrv9Z5AH6KWRkOB+5wRWlWo7a3Ga7/mOIomAho/GFyI30YeDREru7ELlOq07TG3jONbbr\n", |
|
285 | 281 | "T0Nu9KOQm+i/gFsDz3nTdv2fI2FbpdpfHnlpH4LcnHdAlIz5yLErqXgFnvOR7fo28lDYE7lu3kKO\n", |
|
286 | 282 | "TdZ9K52xrhTl7knnUVB6SqVeTsr4apQU6lDEbG4hCsFbROsRBE1ebjrwnNB2/XGIGf5gRBkYhPyv\n", |
|
287 | 283 | "7yDpjR9MtVkOnGK7/vWIgrFrVPcF4O8ZKbaXIuduWkH6KfL/JbkEsWClfWK2CDzHt10/jzhXjkGO\n", |
|
288 | 284 | "yzNIZEiRD00ga3ocaLv+kUh2xo8hSuVURKmIUyiXVGYCWVzKQlJD7xrJNg85b9LX8RLgF6X6SpFU\n", |
|
289 | 285 | "9Cpe28gaJgORqEEAbNffDLlvHIQoAndR8NEYilwjExD/nwuUiTQ0GAwGw7qC7fqjEUvKqsBzmhWd\n", |
|
290 | 286 | "t05gu/5pyNoifw48J9N5PForxQeeNFMMBoPBYDD0DWL/llvK1In9jt4zCoLBYDAYDH2DePo5MwrJ\n", |
|
291 | 287 | "dv0hFPwTnjBRDAaDwWAw9A3+hPgOHRPl25iK+FhsiuR4OARx0Lwf+J1REAwGg8Fg6AMEnvNklL78\n", |
|
292 | 288 | "HMRRca/E5hVINNIVwI2B56z6/3ExLRI31pXNAAAAAElFTkSuQmCC\n" |
|
293 | 289 | ], |
|
294 | 290 | "text/plain": [ |
|
295 | 291 | "<IPython.core.display.Image at 0x111275490>" |
|
296 | 292 | ] |
|
297 | 293 | }, |
|
298 | 294 | "execution_count": 6, |
|
299 | 295 | "metadata": {}, |
|
300 | 296 | "output_type": "execute_result" |
|
301 | 297 | } |
|
302 | 298 | ], |
|
303 | 299 | "source": [ |
|
304 | 300 | "from IPython.display import Image\n", |
|
305 | 301 | "Image(\"http://ipython.org/_static/IPy_header.png\")" |
|
306 | 302 | ] |
|
307 | 303 | } |
|
308 | 304 | ], |
|
309 | 305 | "metadata": {}, |
|
310 | 306 | "nbformat": 4, |
|
311 | 307 | "nbformat_minor": 0 |
|
312 | 308 | } No newline at end of file |
@@ -1,57 +1,57 b'' | |||
|
1 | 1 | """Test nbformat.validator""" |
|
2 | 2 | |
|
3 | 3 | # Copyright (c) IPython Development Team. |
|
4 | 4 | # Distributed under the terms of the Modified BSD License. |
|
5 | 5 | |
|
6 | 6 | import os |
|
7 | 7 | |
|
8 | 8 | from .base import TestsBase |
|
9 | 9 | from jsonschema import ValidationError |
|
10 | 10 | from ..current import read |
|
11 | 11 | from ..validator import isvalid, validate |
|
12 | 12 | |
|
13 | 13 | |
|
14 | 14 | class TestValidator(TestsBase): |
|
15 | 15 | |
|
16 | 16 | def test_nb2(self): |
|
17 | 17 | """Test that a v2 notebook converted to current passes validation""" |
|
18 | 18 | with self.fopen(u'test2.ipynb', u'r') as f: |
|
19 | 19 | nb = read(f, u'json') |
|
20 | 20 | validate(nb) |
|
21 | 21 | self.assertEqual(isvalid(nb), True) |
|
22 | 22 | |
|
23 | 23 | def test_nb3(self): |
|
24 | 24 | """Test that a v3 notebook passes validation""" |
|
25 | 25 | with self.fopen(u'test3.ipynb', u'r') as f: |
|
26 | 26 | nb = read(f, u'json') |
|
27 | 27 | validate(nb) |
|
28 | 28 | self.assertEqual(isvalid(nb), True) |
|
29 | 29 | |
|
30 | 30 | def test_nb4(self): |
|
31 |
"""Test that a v |
|
|
31 | """Test that a v4 notebook passes validation""" | |
|
32 | 32 | with self.fopen(u'test4.ipynb', u'r') as f: |
|
33 | 33 | nb = read(f, u'json') |
|
34 | 34 | validate(nb) |
|
35 | 35 | self.assertEqual(isvalid(nb), True) |
|
36 | 36 | |
|
37 | 37 | def test_invalid(self): |
|
38 | 38 | """Test than an invalid notebook does not pass validation""" |
|
39 | 39 | # this notebook has a few different errors: |
|
40 | # - the name is an integer, rather than a string | |
|
41 | 40 | # - one cell is missing its source |
|
42 |
# - |
|
|
41 | # - invalid cell type | |
|
42 | # - invalid output_type | |
|
43 | 43 | with self.fopen(u'invalid.ipynb', u'r') as f: |
|
44 | 44 | nb = read(f, u'json') |
|
45 | 45 | with self.assertRaises(ValidationError): |
|
46 | 46 | validate(nb) |
|
47 | 47 | self.assertEqual(isvalid(nb), False) |
|
48 | 48 | |
|
49 | 49 | def test_future(self): |
|
50 | 50 | """Test than a notebook from the future with extra keys passes validation""" |
|
51 | 51 | with self.fopen(u'test3plus.ipynb', u'r') as f: |
|
52 | 52 | nb = read(f) |
|
53 | 53 | with self.assertRaises(ValidationError): |
|
54 | 54 | validate(nb, version=3) |
|
55 | 55 | |
|
56 | 56 | self.assertEqual(isvalid(nb, version=3), False) |
|
57 | 57 | self.assertEqual(isvalid(nb), True) |
@@ -1,19 +1,19 b'' | |||
|
1 | 1 | """The main API for the v4 notebook format.""" |
|
2 | 2 | |
|
3 | 3 | # Copyright (c) IPython Development Team. |
|
4 | 4 | # Distributed under the terms of the Modified BSD License. |
|
5 | 5 | |
|
6 | 6 | from .nbbase import ( |
|
7 | 7 | NotebookNode, from_dict, |
|
8 | 8 | nbformat, nbformat_minor, nbformat_schema, |
|
9 |
new_code_cell |
|
|
9 | new_code_cell, new_markdown_cell, new_notebook, | |
|
10 | 10 | new_output, output_from_msg, |
|
11 | 11 | ) |
|
12 | 12 | |
|
13 | 13 | from .nbjson import reads as reads_json, writes as writes_json |
|
14 | 14 | from .nbjson import reads as read_json, writes as write_json |
|
15 | 15 | from .nbjson import to_notebook as to_notebook_json |
|
16 | 16 | |
|
17 | 17 | from .convert import downgrade, upgrade |
|
18 | 18 | |
|
19 | 19 |
@@ -1,230 +1,248 b'' | |||
|
1 | 1 | """Code for converting notebooks to and from v3.""" |
|
2 | 2 | |
|
3 | 3 | # Copyright (c) IPython Development Team. |
|
4 | 4 | # Distributed under the terms of the Modified BSD License. |
|
5 | 5 | |
|
6 | 6 | import json |
|
7 | import re | |
|
7 | 8 | |
|
8 | 9 | from .nbbase import ( |
|
9 | 10 | nbformat, nbformat_minor, |
|
10 | 11 | NotebookNode, |
|
11 | 12 | ) |
|
12 | 13 | |
|
13 | 14 | from IPython.nbformat import v3 |
|
14 | 15 | from IPython.utils.log import get_logger |
|
15 | 16 | |
|
16 | 17 | def _warn_if_invalid(nb, version): |
|
17 | 18 | """Log validation errors, if there are any.""" |
|
18 | 19 | from IPython.nbformat.current import validate, ValidationError |
|
19 | 20 | try: |
|
20 | 21 | validate(nb, version=version) |
|
21 | 22 | except ValidationError as e: |
|
22 | 23 | get_logger().error("Notebook JSON is not valid v%i: %s", version, e) |
|
23 | 24 | |
|
24 | 25 | def upgrade(nb, from_version=3, from_minor=0): |
|
25 | 26 | """Convert a notebook to v4. |
|
26 | 27 | |
|
27 | 28 | Parameters |
|
28 | 29 | ---------- |
|
29 | 30 | nb : NotebookNode |
|
30 | 31 | The Python representation of the notebook to convert. |
|
31 | 32 | from_version : int |
|
32 | 33 | The original version of the notebook to convert. |
|
33 | 34 | from_minor : int |
|
34 | 35 | The original minor version of the notebook to convert (only relevant for v >= 3). |
|
35 | 36 | """ |
|
36 | 37 | if from_version == 3: |
|
37 | 38 | # Validate the notebook before conversion |
|
38 | 39 | _warn_if_invalid(nb, from_version) |
|
39 | 40 | |
|
40 | 41 | # Mark the original nbformat so consumers know it has been converted |
|
41 | 42 | orig_nbformat = nb.pop('orig_nbformat', None) |
|
42 | 43 | nb.metadata.orig_nbformat = orig_nbformat or 3 |
|
43 | 44 | |
|
44 | 45 | # Mark the new format |
|
45 | 46 | nb.nbformat = nbformat |
|
46 | 47 | nb.nbformat_minor = nbformat_minor |
|
47 | 48 | |
|
48 | 49 | # remove worksheet(s) |
|
49 | 50 | nb['cells'] = cells = [] |
|
50 | 51 | # In the unlikely event of multiple worksheets, |
|
51 | 52 | # they will be flattened |
|
52 | 53 | for ws in nb.pop('worksheets', []): |
|
53 | 54 | # upgrade each cell |
|
54 | 55 | for cell in ws['cells']: |
|
55 | 56 | cells.append(upgrade_cell(cell)) |
|
56 | 57 | # upgrade metadata |
|
57 | 58 | nb.metadata.pop('name', '') |
|
58 | 59 | # Validate the converted notebook before returning it |
|
59 | 60 | _warn_if_invalid(nb, nbformat) |
|
60 | 61 | return nb |
|
61 | 62 | elif from_version == 4: |
|
62 | 63 | # nothing to do |
|
63 | 64 | if from_minor != nbformat_minor: |
|
64 | 65 | nb.metadata.orig_nbformat_minor = from_minor |
|
65 | 66 | nb.nbformat_minor = nbformat_minor |
|
66 | 67 | |
|
67 | 68 | return nb |
|
68 | 69 | else: |
|
69 | 70 | raise ValueError('Cannot convert a notebook directly from v%s to v4. ' \ |
|
70 | 71 | 'Try using the IPython.nbformat.convert module.' % from_version) |
|
71 | 72 | |
|
72 | 73 | def upgrade_cell(cell): |
|
73 | 74 | """upgrade a cell from v3 to v4 |
|
74 | 75 | |
|
76 | heading cell -> markdown heading | |
|
75 | 77 | code cell: |
|
76 | 78 | - remove language metadata |
|
77 | 79 | - cell.input -> cell.source |
|
78 | 80 | - cell.prompt_number -> cell.execution_count |
|
79 | 81 | - update outputs |
|
80 | 82 | """ |
|
81 | 83 | cell.setdefault('metadata', NotebookNode()) |
|
82 | 84 | if cell.cell_type == 'code': |
|
83 | 85 | cell.pop('language', '') |
|
84 | 86 | cell.metadata.collapsed = cell.pop('collapsed') |
|
85 | cell.source = cell.pop('input') | |
|
87 | cell.source = cell.pop('input', '') | |
|
86 | 88 | cell.execution_count = cell.pop('prompt_number', None) |
|
87 | 89 | cell.outputs = upgrade_outputs(cell.outputs) |
|
90 | elif cell.cell_type == 'heading': | |
|
91 | cell.cell_type = 'markdown' | |
|
92 | level = cell.pop('level', 1) | |
|
93 | cell.source = '{hashes} {single_line}'.format( | |
|
94 | hashes='#' * level, | |
|
95 | single_line = ' '.join(cell.get('source', '').splitlines()), | |
|
96 | ) | |
|
88 | 97 | elif cell.cell_type == 'html': |
|
89 | 98 | # Technically, this exists. It will never happen in practice. |
|
90 | 99 | cell.cell_type = 'markdown' |
|
91 | 100 | return cell |
|
92 | 101 | |
|
93 | 102 | def downgrade_cell(cell): |
|
94 | 103 | """downgrade a cell from v4 to v3 |
|
95 | 104 | |
|
96 | 105 | code cell: |
|
97 | 106 | - set cell.language |
|
98 | 107 | - cell.input <- cell.source |
|
99 | 108 | - cell.prompt_number <- cell.execution_count |
|
100 | 109 | - update outputs |
|
110 | markdown cell: | |
|
111 | - single-line heading -> heading cell | |
|
101 | 112 | """ |
|
102 | 113 | if cell.cell_type == 'code': |
|
103 | 114 | cell.language = 'python' |
|
104 | 115 | cell.input = cell.pop('source', '') |
|
105 | 116 | cell.prompt_number = cell.pop('execution_count', None) |
|
106 | 117 | cell.collapsed = cell.metadata.pop('collapsed', False) |
|
107 | 118 | cell.outputs = downgrade_outputs(cell.outputs) |
|
119 | elif cell.cell_type == 'markdown': | |
|
120 | source = cell.get('source', '') | |
|
121 | if '\n' not in source and source.startswith('#'): | |
|
122 | prefix, text = re.match(r'(#+)\s*(.*)', source).groups() | |
|
123 | cell.cell_type = 'heading' | |
|
124 | cell.source = text | |
|
125 | cell.level = len(prefix) | |
|
108 | 126 | return cell |
|
109 | 127 | |
|
110 | 128 | _mime_map = { |
|
111 | 129 | "text" : "text/plain", |
|
112 | 130 | "html" : "text/html", |
|
113 | 131 | "svg" : "image/svg+xml", |
|
114 | 132 | "png" : "image/png", |
|
115 | 133 | "jpeg" : "image/jpeg", |
|
116 | 134 | "latex" : "text/latex", |
|
117 | 135 | "json" : "application/json", |
|
118 | 136 | "javascript" : "application/javascript", |
|
119 | 137 | }; |
|
120 | 138 | |
|
121 | 139 | def to_mime_key(d): |
|
122 | 140 | """convert dict with v3 aliases to plain mime-type keys""" |
|
123 | 141 | for alias, mime in _mime_map.items(): |
|
124 | 142 | if alias in d: |
|
125 | 143 | d[mime] = d.pop(alias) |
|
126 | 144 | return d |
|
127 | 145 | |
|
128 | 146 | def from_mime_key(d): |
|
129 | 147 | """convert dict with mime-type keys to v3 aliases""" |
|
130 | 148 | for alias, mime in _mime_map.items(): |
|
131 | 149 | if mime in d: |
|
132 | 150 | d[alias] = d.pop(mime) |
|
133 | 151 | return d |
|
134 | 152 | |
|
135 | 153 | def upgrade_output(output): |
|
136 | 154 | """upgrade a single code cell output from v3 to v4 |
|
137 | 155 | |
|
138 | 156 | - pyout -> execute_result |
|
139 | 157 | - pyerr -> error |
|
140 | 158 | - output.type -> output.data.mime/type |
|
141 | 159 | - mime-type keys |
|
142 | 160 | - stream.stream -> stream.name |
|
143 | 161 | """ |
|
144 | 162 | if output['output_type'] in {'pyout', 'display_data'}: |
|
145 | 163 | output.setdefault('metadata', NotebookNode()) |
|
146 | 164 | if output['output_type'] == 'pyout': |
|
147 | 165 | output['output_type'] = 'execute_result' |
|
148 | 166 | output['execution_count'] = output.pop('prompt_number', None) |
|
149 | 167 | |
|
150 | 168 | # move output data into data sub-dict |
|
151 | 169 | data = {} |
|
152 | 170 | for key in list(output): |
|
153 | 171 | if key in {'output_type', 'execution_count', 'metadata'}: |
|
154 | 172 | continue |
|
155 | 173 | data[key] = output.pop(key) |
|
156 | 174 | to_mime_key(data) |
|
157 | 175 | output['data'] = data |
|
158 | 176 | to_mime_key(output.metadata) |
|
159 | 177 | if 'application/json' in data: |
|
160 | 178 | data['application/json'] = json.loads(data['application/json']) |
|
161 | 179 | # promote ascii bytes (from v2) to unicode |
|
162 | 180 | for key in ('image/png', 'image/jpeg'): |
|
163 | 181 | if key in data and isinstance(data[key], bytes): |
|
164 | 182 | data[key] = data[key].decode('ascii') |
|
165 | 183 | elif output['output_type'] == 'pyerr': |
|
166 | 184 | output['output_type'] = 'error' |
|
167 | 185 | elif output['output_type'] == 'stream': |
|
168 | 186 | output['name'] = output.pop('stream') |
|
169 | 187 | return output |
|
170 | 188 | |
|
171 | 189 | def downgrade_output(output): |
|
172 | 190 | """downgrade a single code cell output to v3 from v4 |
|
173 | 191 | |
|
174 | 192 | - pyout <- execute_result |
|
175 | 193 | - pyerr <- error |
|
176 | 194 | - output.data.mime/type -> output.type |
|
177 | 195 | - un-mime-type keys |
|
178 | 196 | - stream.stream <- stream.name |
|
179 | 197 | """ |
|
180 | 198 | if output['output_type'] in {'execute_result', 'display_data'}: |
|
181 | 199 | if output['output_type'] == 'execute_result': |
|
182 | 200 | output['output_type'] = 'pyout' |
|
183 | 201 | output['prompt_number'] = output.pop('execution_count', None) |
|
184 | 202 | |
|
185 | 203 | # promote data dict to top-level output namespace |
|
186 | 204 | data = output.pop('data', {}) |
|
187 | 205 | if 'application/json' in data: |
|
188 | 206 | data['application/json'] = json.dumps(data['application/json']) |
|
189 | 207 | from_mime_key(data) |
|
190 | 208 | output.update(data) |
|
191 | 209 | from_mime_key(output.get('metadata', {})) |
|
192 | 210 | elif output['output_type'] == 'error': |
|
193 | 211 | output['output_type'] = 'pyerr' |
|
194 | 212 | elif output['output_type'] == 'stream': |
|
195 | 213 | output['stream'] = output.pop('name') |
|
196 | 214 | return output |
|
197 | 215 | |
|
198 | 216 | def upgrade_outputs(outputs): |
|
199 | 217 | """upgrade outputs of a code cell from v3 to v4""" |
|
200 | 218 | return [upgrade_output(op) for op in outputs] |
|
201 | 219 | |
|
202 | 220 | def downgrade_outputs(outputs): |
|
203 | 221 | """downgrade outputs of a code cell to v3 from v4""" |
|
204 | 222 | return [downgrade_output(op) for op in outputs] |
|
205 | 223 | |
|
206 | 224 | def downgrade(nb): |
|
207 | 225 | """Convert a v4 notebook to v3. |
|
208 | 226 | |
|
209 | 227 | Parameters |
|
210 | 228 | ---------- |
|
211 | 229 | nb : NotebookNode |
|
212 | 230 | The Python representation of the notebook to convert. |
|
213 | 231 | """ |
|
214 | 232 | if nb.nbformat != nbformat: |
|
215 | 233 | return nb |
|
216 | 234 | |
|
217 | 235 | # Validate the notebook before conversion |
|
218 | 236 | _warn_if_invalid(nb, nbformat) |
|
219 | 237 | |
|
220 | 238 | nb.nbformat = v3.nbformat |
|
221 | 239 | nb.nbformat_minor = v3.nbformat_minor |
|
222 | 240 | cells = [ downgrade_cell(cell) for cell in nb.pop('cells') ] |
|
223 | 241 | nb.worksheets = [v3.new_worksheet(cells=cells)] |
|
224 | 242 | nb.metadata.setdefault('name', '') |
|
225 | 243 | nb.metadata.pop('orig_nbformat', None) |
|
226 | 244 | nb.metadata.pop('orig_nbformat_minor', None) |
|
227 | 245 | |
|
228 | 246 | # Validate the converted notebook before returning it |
|
229 | 247 | _warn_if_invalid(nb, v3.nbformat) |
|
230 | 248 | return nb |
@@ -1,151 +1,141 b'' | |||
|
1 | 1 | """Python API for composing notebook elements |
|
2 | 2 | |
|
3 | 3 | The Python representation of a notebook is a nested structure of |
|
4 | 4 | dictionary subclasses that support attribute access |
|
5 | 5 | (IPython.utils.ipstruct.Struct). The functions in this module are merely |
|
6 | 6 | helpers to build the structs in the right form. |
|
7 | 7 | """ |
|
8 | 8 | |
|
9 | 9 | # Copyright (c) IPython Development Team. |
|
10 | 10 | # Distributed under the terms of the Modified BSD License. |
|
11 | 11 | |
|
12 | 12 | from IPython.utils.ipstruct import Struct |
|
13 | 13 | |
|
14 | 14 | # Change this when incrementing the nbformat version |
|
15 | 15 | nbformat = 4 |
|
16 | 16 | nbformat_minor = 0 |
|
17 | 17 | nbformat_schema = 'nbformat.v4.schema.json' |
|
18 | 18 | |
|
19 | 19 | |
|
20 | 20 | def validate(node, ref=None): |
|
21 | 21 | """validate a v4 node""" |
|
22 | 22 | from ..current import validate |
|
23 | 23 | return validate(node, ref=ref, version=nbformat) |
|
24 | 24 | |
|
25 | 25 | |
|
26 | 26 | class NotebookNode(Struct): |
|
27 | 27 | pass |
|
28 | 28 | |
|
29 | 29 | def from_dict(d): |
|
30 | 30 | if isinstance(d, dict): |
|
31 | 31 | newd = NotebookNode() |
|
32 | 32 | for k,v in d.items(): |
|
33 | 33 | newd[k] = from_dict(v) |
|
34 | 34 | return newd |
|
35 | 35 | elif isinstance(d, (tuple, list)): |
|
36 | 36 | return [from_dict(i) for i in d] |
|
37 | 37 | else: |
|
38 | 38 | return d |
|
39 | 39 | |
|
40 | 40 | |
|
41 | 41 | def new_output(output_type, data=None, **kwargs): |
|
42 | 42 | """Create a new output, to go in the ``cell.outputs`` list of a code cell.""" |
|
43 | 43 | output = NotebookNode(output_type=output_type) |
|
44 | 44 | output.update(from_dict(kwargs)) |
|
45 | 45 | if data is not None: |
|
46 | 46 | output.data = from_dict(data) |
|
47 | 47 | |
|
48 | 48 | # populate defaults: |
|
49 | 49 | if output_type == 'stream': |
|
50 | 50 | output.setdefault('name', 'stdout') |
|
51 | 51 | output.setdefault('text', '') |
|
52 | 52 | elif output_type in {'execute_result', 'display_data'}: |
|
53 | 53 | output.setdefault('metadata', NotebookNode()) |
|
54 | 54 | output.setdefault('data', NotebookNode()) |
|
55 | 55 | validate(output, output_type) |
|
56 | 56 | return output |
|
57 | 57 | |
|
58 | 58 | |
|
59 | 59 | def output_from_msg(msg): |
|
60 | 60 | """Create a NotebookNode for an output from a kernel's IOPub message. |
|
61 | 61 | |
|
62 | 62 | Returns |
|
63 | 63 | ------- |
|
64 | 64 | |
|
65 | 65 | NotebookNode: the output as a notebook node. |
|
66 | 66 | |
|
67 | 67 | Raises |
|
68 | 68 | ------ |
|
69 | 69 | |
|
70 | 70 | ValueError: if the message is not an output message. |
|
71 | 71 | |
|
72 | 72 | """ |
|
73 | 73 | msg_type = msg['header']['msg_type'] |
|
74 | 74 | content = msg['content'] |
|
75 | 75 | |
|
76 | 76 | if msg_type == 'execute_result': |
|
77 | 77 | return new_output(output_type=msg_type, |
|
78 | 78 | metadata=content['metadata'], |
|
79 | 79 | data=content['data'], |
|
80 | 80 | execution_count=content['execution_count'], |
|
81 | 81 | ) |
|
82 | 82 | |
|
83 | 83 | elif msg_type == 'stream': |
|
84 | 84 | return new_output(output_type=msg_type, |
|
85 | 85 | name=content['name'], |
|
86 | 86 | text=content['text'], |
|
87 | 87 | ) |
|
88 | 88 | elif msg_type == 'display_data': |
|
89 | 89 | return new_output(output_type=msg_type, |
|
90 | 90 | metadata=content['metadata'], |
|
91 | 91 | data=content['data'], |
|
92 | 92 | ) |
|
93 | 93 | elif msg_type == 'error': |
|
94 | 94 | return new_output(output_type=msg_type, |
|
95 | 95 | ename=content['ename'], |
|
96 | 96 | evalue=content['evalue'], |
|
97 | 97 | traceback=content['traceback'], |
|
98 | 98 | ) |
|
99 | 99 | else: |
|
100 | 100 | raise ValueError("Unrecognized output msg type: %r" % msg_type) |
|
101 | 101 | |
|
102 | 102 | |
|
103 | 103 | def new_code_cell(source='', **kwargs): |
|
104 | 104 | """Create a new code cell""" |
|
105 | 105 | cell = NotebookNode(cell_type='code', source=source) |
|
106 | 106 | cell.update(from_dict(kwargs)) |
|
107 | 107 | cell.setdefault('metadata', NotebookNode()) |
|
108 | 108 | cell.setdefault('source', '') |
|
109 | 109 | cell.setdefault('execution_count', None) |
|
110 | 110 | cell.setdefault('outputs', []) |
|
111 | 111 | |
|
112 | 112 | validate(cell, 'code_cell') |
|
113 | 113 | return cell |
|
114 | 114 | |
|
115 | 115 | def new_markdown_cell(source='', **kwargs): |
|
116 | 116 | """Create a new markdown cell""" |
|
117 | 117 | cell = NotebookNode(cell_type='markdown', source=source) |
|
118 | 118 | cell.update(from_dict(kwargs)) |
|
119 | 119 | cell.setdefault('metadata', NotebookNode()) |
|
120 | 120 | |
|
121 | 121 | validate(cell, 'markdown_cell') |
|
122 | 122 | return cell |
|
123 | 123 | |
|
124 | def new_heading_cell(source='', **kwargs): | |
|
125 | """Create a new heading cell""" | |
|
126 | cell = NotebookNode(cell_type='heading', source=source) | |
|
127 | cell.update(from_dict(kwargs)) | |
|
128 | cell.setdefault('metadata', NotebookNode()) | |
|
129 | cell.setdefault('level', 1) | |
|
130 | ||
|
131 | validate(cell, 'heading_cell') | |
|
132 | return cell | |
|
133 | ||
|
134 | 124 | def new_raw_cell(source='', **kwargs): |
|
135 | 125 | """Create a new raw cell""" |
|
136 | 126 | cell = NotebookNode(cell_type='raw', source=source) |
|
137 | 127 | cell.update(from_dict(kwargs)) |
|
138 | 128 | cell.setdefault('metadata', NotebookNode()) |
|
139 | 129 | |
|
140 | 130 | validate(cell, 'raw_cell') |
|
141 | 131 | return cell |
|
142 | 132 | |
|
143 | 133 | def new_notebook(**kwargs): |
|
144 | 134 | """Create a new notebook""" |
|
145 | 135 | nb = from_dict(kwargs) |
|
146 | 136 | nb.nbformat = nbformat |
|
147 | 137 | nb.nbformat_minor = nbformat_minor |
|
148 | 138 | nb.setdefault('cells', []) |
|
149 | 139 | nb.setdefault('metadata', NotebookNode()) |
|
150 | 140 | validate(nb) |
|
151 | 141 | return nb |
@@ -1,337 +1,308 b'' | |||
|
1 | 1 | { |
|
2 | 2 | "$schema": "http://json-schema.org/draft-04/schema#", |
|
3 | 3 | "description": "IPython Notebook v4.0 JSON schema.", |
|
4 | 4 | "type": "object", |
|
5 | 5 | "additionalProperties": false, |
|
6 | 6 | "required": ["metadata", "nbformat_minor", "nbformat", "cells"], |
|
7 | 7 | "properties": { |
|
8 | 8 | "metadata": { |
|
9 | 9 | "description": "Notebook root-level metadata.", |
|
10 | 10 | "type": "object", |
|
11 | 11 | "additionalProperties": true, |
|
12 | 12 | "properties": { |
|
13 | 13 | "kernel_info": { |
|
14 | 14 | "description": "Kernel information.", |
|
15 | 15 | "type": "object", |
|
16 | 16 | "required": ["name", "language"], |
|
17 | 17 | "properties": { |
|
18 | 18 | "name": { |
|
19 | 19 | "description": "Name of the kernel specification.", |
|
20 | 20 | "type": "string" |
|
21 | 21 | }, |
|
22 | 22 | "language": { |
|
23 | 23 | "description": "The programming language which this kernel runs.", |
|
24 | 24 | "type": "string" |
|
25 | 25 | }, |
|
26 | 26 | "codemirror_mode": { |
|
27 | 27 | "description": "The codemirror mode to use for code in this language.", |
|
28 | 28 | "type": "string" |
|
29 | 29 | } |
|
30 | 30 | } |
|
31 | 31 | }, |
|
32 | 32 | "signature": { |
|
33 | 33 | "description": "Hash of the notebook.", |
|
34 | 34 | "type": "string" |
|
35 | 35 | }, |
|
36 | 36 | "orig_nbformat": { |
|
37 | 37 | "description": "Original notebook format (major number) before converting the notebook between versions. This should never be written to a file.", |
|
38 | 38 | "type": "integer", |
|
39 | 39 | "minimum": 1 |
|
40 | 40 | } |
|
41 | 41 | } |
|
42 | 42 | }, |
|
43 | 43 | "nbformat_minor": { |
|
44 | 44 | "description": "Notebook format (minor number). Incremented for backward compatible changes to the notebook format.", |
|
45 | 45 | "type": "integer", |
|
46 | 46 | "minimum": 0 |
|
47 | 47 | }, |
|
48 | 48 | "nbformat": { |
|
49 | 49 | "description": "Notebook format (major number). Incremented between backwards incompatible changes to the notebook format.", |
|
50 | 50 | "type": "integer", |
|
51 | 51 | "minimum": 4, |
|
52 | 52 | "maximum": 4 |
|
53 | 53 | }, |
|
54 | 54 | "cells": { |
|
55 | 55 | "description": "Array of cells of the current notebook.", |
|
56 | 56 | "type": "array", |
|
57 | 57 | "items": { |
|
58 | 58 | "type": "object", |
|
59 | 59 | "oneOf": [ |
|
60 | 60 | {"$ref": "#/definitions/raw_cell"}, |
|
61 | 61 | {"$ref": "#/definitions/markdown_cell"}, |
|
62 | {"$ref": "#/definitions/heading_cell"}, | |
|
63 | 62 | {"$ref": "#/definitions/code_cell"} |
|
64 | 63 | ] |
|
65 | 64 | } |
|
66 | 65 | } |
|
67 | 66 | }, |
|
68 | 67 | |
|
69 | 68 | "definitions": { |
|
70 | 69 | |
|
71 | 70 | "raw_cell": { |
|
72 | 71 | "description": "Notebook raw nbconvert cell.", |
|
73 | 72 | "type": "object", |
|
74 | 73 | "additionalProperties": false, |
|
75 | 74 | "required": ["cell_type", "metadata", "source"], |
|
76 | 75 | "properties": { |
|
77 | 76 | "cell_type": { |
|
78 | 77 | "description": "String identifying the type of cell.", |
|
79 | 78 | "enum": ["raw"] |
|
80 | 79 | }, |
|
81 | 80 | "metadata": { |
|
82 | 81 | "description": "Cell-level metadata.", |
|
83 | 82 | "type": "object", |
|
84 | 83 | "additionalProperties": true, |
|
85 | 84 | "properties": { |
|
86 | 85 | "format": { |
|
87 | 86 | "description": "Raw cell metadata format for nbconvert.", |
|
88 | 87 | "type": "string" |
|
89 | 88 | }, |
|
90 | 89 | "name": {"$ref": "#/definitions/misc/metadata_name"}, |
|
91 | 90 | "tags": {"$ref": "#/definitions/misc/metadata_tags"} |
|
92 | 91 | } |
|
93 | 92 | }, |
|
94 | 93 | "source": {"$ref": "#/definitions/misc/source"} |
|
95 | 94 | } |
|
96 | 95 | }, |
|
97 | 96 | |
|
98 | 97 | "markdown_cell": { |
|
99 | 98 | "description": "Notebook markdown cell.", |
|
100 | 99 | "type": "object", |
|
101 | 100 | "additionalProperties": false, |
|
102 | 101 | "required": ["cell_type", "metadata", "source"], |
|
103 | 102 | "properties": { |
|
104 | 103 | "cell_type": { |
|
105 | 104 | "description": "String identifying the type of cell.", |
|
106 | 105 | "enum": ["markdown"] |
|
107 | 106 | }, |
|
108 | 107 | "metadata": { |
|
109 | 108 | "description": "Cell-level metadata.", |
|
110 | 109 | "type": "object", |
|
111 | 110 | "properties": { |
|
112 | 111 | "name": {"$ref": "#/definitions/misc/metadata_name"}, |
|
113 | 112 | "tags": {"$ref": "#/definitions/misc/metadata_tags"} |
|
114 | 113 | }, |
|
115 | 114 | "additionalProperties": true |
|
116 | 115 | }, |
|
117 | 116 | "source": {"$ref": "#/definitions/misc/source"} |
|
118 | 117 | } |
|
119 | 118 | }, |
|
120 | 119 | |
|
121 | "heading_cell": { | |
|
122 | "description": "Notebook heading cell.", | |
|
123 | "type": "object", | |
|
124 | "additionalProperties": false, | |
|
125 | "required": ["cell_type", "metadata", "source", "level"], | |
|
126 | "properties": { | |
|
127 | "cell_type": { | |
|
128 | "description": "String identifying the type of cell.", | |
|
129 | "enum": ["heading"] | |
|
130 | }, | |
|
131 | "metadata": { | |
|
132 | "description": "Cell-level metadata.", | |
|
133 | "type": "object", | |
|
134 | "properties": { | |
|
135 | "name": {"$ref": "#/definitions/misc/metadata_name"}, | |
|
136 | "tags": {"$ref": "#/definitions/misc/metadata_tags"} | |
|
137 | }, | |
|
138 | "additionalProperties": true | |
|
139 | }, | |
|
140 | "source": {"$ref": "#/definitions/misc/source"}, | |
|
141 | "level": { | |
|
142 | "description": "Level of heading cells.", | |
|
143 | "type": "integer", | |
|
144 | "minimum": 1 | |
|
145 | } | |
|
146 | } | |
|
147 | }, | |
|
148 | ||
|
149 | 120 | "code_cell": { |
|
150 | 121 | "description": "Notebook code cell.", |
|
151 | 122 | "type": "object", |
|
152 | 123 | "additionalProperties": false, |
|
153 | 124 | "required": ["cell_type", "metadata", "source", "outputs", "execution_count"], |
|
154 | 125 | "properties": { |
|
155 | 126 | "cell_type": { |
|
156 | 127 | "description": "String identifying the type of cell.", |
|
157 | 128 | "enum": ["code"] |
|
158 | 129 | }, |
|
159 | 130 | "metadata": { |
|
160 | 131 | "description": "Cell-level metadata.", |
|
161 | 132 | "type": "object", |
|
162 | 133 | "additionalProperties": true, |
|
163 | 134 | "properties": { |
|
164 | 135 | "collapsed": { |
|
165 | 136 | "description": "Whether the cell is collapsed/expanded.", |
|
166 | 137 | "type": "boolean" |
|
167 | 138 | }, |
|
168 | 139 | "autoscroll": { |
|
169 | 140 | "description": "Whether the cell's output is scrolled, unscrolled, or autoscrolled.", |
|
170 | 141 | "enum": [true, false, "auto"] |
|
171 | 142 | }, |
|
172 | 143 | "name": {"$ref": "#/definitions/misc/metadata_name"}, |
|
173 | 144 | "tags": {"$ref": "#/definitions/misc/metadata_tags"} |
|
174 | 145 | } |
|
175 | 146 | }, |
|
176 | 147 | "source": {"$ref": "#/definitions/misc/source"}, |
|
177 | 148 | "outputs": { |
|
178 | 149 | "description": "Execution, display, or stream outputs.", |
|
179 | 150 | "type": "array", |
|
180 | 151 | "items": {"$ref": "#/definitions/output"} |
|
181 | 152 | }, |
|
182 | 153 | "execution_count": { |
|
183 | 154 | "description": "The code cell's prompt number. Will be null if the cell has not been run.", |
|
184 | 155 | "type": ["integer", "null"], |
|
185 | 156 | "minimum": 0 |
|
186 | 157 | } |
|
187 | 158 | } |
|
188 | 159 | }, |
|
189 | 160 | "output": { |
|
190 | 161 | "type": "object", |
|
191 | 162 | "oneOf": [ |
|
192 | 163 | {"$ref": "#/definitions/execute_result"}, |
|
193 | 164 | {"$ref": "#/definitions/display_data"}, |
|
194 | 165 | {"$ref": "#/definitions/stream"}, |
|
195 | 166 | {"$ref": "#/definitions/error"} |
|
196 | 167 | ] |
|
197 | 168 | }, |
|
198 | 169 | |
|
199 | 170 | "execute_result": { |
|
200 | 171 | "description": "Result of executing a code cell.", |
|
201 | 172 | "type": "object", |
|
202 | 173 | "additionalProperties": false, |
|
203 | 174 | "required": ["output_type", "data", "metadata", "execution_count"], |
|
204 | 175 | "properties": { |
|
205 | 176 | "output_type": { |
|
206 | 177 | "description": "Type of cell output.", |
|
207 | 178 | "enum": ["execute_result"] |
|
208 | 179 | }, |
|
209 | 180 | "execution_count": { |
|
210 | 181 | "description": "A result's prompt number.", |
|
211 | 182 | "type": ["integer", "null"], |
|
212 | 183 | "minimum": 0 |
|
213 | 184 | }, |
|
214 | 185 | "data": {"$ref": "#/definitions/misc/mimebundle"}, |
|
215 | 186 | "metadata": {"$ref": "#/definitions/misc/output_metadata"} |
|
216 | 187 | } |
|
217 | 188 | }, |
|
218 | 189 | |
|
219 | 190 | "display_data": { |
|
220 | 191 | "description": "Data displayed as a result of code cell execution.", |
|
221 | 192 | "type": "object", |
|
222 | 193 | "additionalProperties": false, |
|
223 | 194 | "required": ["output_type", "data", "metadata"], |
|
224 | 195 | "properties": { |
|
225 | 196 | "output_type": { |
|
226 | 197 | "description": "Type of cell output.", |
|
227 | 198 | "enum": ["display_data"] |
|
228 | 199 | }, |
|
229 | 200 | "data": {"$ref": "#/definitions/misc/mimebundle"}, |
|
230 | 201 | "metadata": {"$ref": "#/definitions/misc/output_metadata"} |
|
231 | 202 | } |
|
232 | 203 | }, |
|
233 | 204 | |
|
234 | 205 | "stream": { |
|
235 | 206 | "description": "Stream output from a code cell.", |
|
236 | 207 | "type": "object", |
|
237 | 208 | "additionalProperties": false, |
|
238 | 209 | "required": ["output_type", "name", "text"], |
|
239 | 210 | "properties": { |
|
240 | 211 | "output_type": { |
|
241 | 212 | "description": "Type of cell output.", |
|
242 | 213 | "enum": ["stream"] |
|
243 | 214 | }, |
|
244 | 215 | "name": { |
|
245 | 216 | "description": "The name of the stream (stdout, stderr).", |
|
246 | 217 | "type": "string" |
|
247 | 218 | }, |
|
248 | 219 | "text": { |
|
249 | 220 | "description": "The stream's text output, represented as an array of strings.", |
|
250 | 221 | "$ref": "#/definitions/misc/multiline_string" |
|
251 | 222 | } |
|
252 | 223 | } |
|
253 | 224 | }, |
|
254 | 225 | |
|
255 | 226 | "error": { |
|
256 | 227 | "description": "Output of an error that occurred during code cell execution.", |
|
257 | 228 | "type": "object", |
|
258 | 229 | "additionalProperties": false, |
|
259 | 230 | "required": ["output_type", "ename", "evalue", "traceback"], |
|
260 | 231 | "properties": { |
|
261 | 232 | "output_type": { |
|
262 | 233 | "description": "Type of cell output.", |
|
263 | 234 | "enum": ["error"] |
|
264 | 235 | }, |
|
265 | 236 | "ename": { |
|
266 | 237 | "description": "The name of the error.", |
|
267 | 238 | "type": "string" |
|
268 | 239 | }, |
|
269 | 240 | "evalue": { |
|
270 | 241 | "description": "The value, or message, of the error.", |
|
271 | 242 | "type": "string" |
|
272 | 243 | }, |
|
273 | 244 | "traceback": { |
|
274 | 245 | "description": "The error's traceback, represented as an array of strings.", |
|
275 | 246 | "type": "array", |
|
276 | 247 | "items": {"type": "string"} |
|
277 | 248 | } |
|
278 | 249 | } |
|
279 | 250 | }, |
|
280 | 251 | |
|
281 | 252 | "misc": { |
|
282 | 253 | "metadata_name": { |
|
283 | 254 | "description": "The cell's name. If present, must be a non-empty string.", |
|
284 | 255 | "type": "string", |
|
285 | 256 | "pattern": "^.+$" |
|
286 | 257 | }, |
|
287 | 258 | "metadata_tags": { |
|
288 | 259 | "description": "The cell's tags. Tags must be unique, and must not contain commas.", |
|
289 | 260 | "type": "array", |
|
290 | 261 | "uniqueItems": true, |
|
291 | 262 | "items": { |
|
292 | 263 | "type": "string", |
|
293 | 264 | "pattern": "^[^,]+$" |
|
294 | 265 | } |
|
295 | 266 | }, |
|
296 | 267 | "source": { |
|
297 | 268 | "description": "Contents of the cell, represented as an array of lines.", |
|
298 | 269 | "$ref": "#/definitions/misc/multiline_string" |
|
299 | 270 | }, |
|
300 | 271 | "execution_count": { |
|
301 | 272 | "description": "The code cell's prompt number. Will be null if the cell has not been run.", |
|
302 | 273 | "type": ["integer", "null"], |
|
303 | 274 | "minimum": 0 |
|
304 | 275 | }, |
|
305 | 276 | "mimebundle": { |
|
306 | 277 | "description": "A mime-type keyed dictionary of data", |
|
307 | 278 | "type": "object", |
|
308 | 279 | "additionalProperties": false, |
|
309 | 280 | "properties": { |
|
310 | 281 | "application/json": { |
|
311 | 282 | "type": "object" |
|
312 | 283 | } |
|
313 | 284 | }, |
|
314 | 285 | "patternProperties": { |
|
315 | 286 | "^(?!application/json$)[a-zA-Z0-9]+/[a-zA-Z0-9\\-\\+\\.]+$": { |
|
316 | 287 | "description": "mimetype output (e.g. text/plain), represented as either an array of strings or a string.", |
|
317 | 288 | "$ref": "#/definitions/misc/multiline_string" |
|
318 | 289 | } |
|
319 | 290 | } |
|
320 | 291 | }, |
|
321 | 292 | "output_metadata": { |
|
322 | 293 | "description": "Cell output metadata.", |
|
323 | 294 | "type": "object", |
|
324 | 295 | "additionalProperties": true |
|
325 | 296 | }, |
|
326 | 297 | "multiline_string": { |
|
327 | 298 | "oneOf" : [ |
|
328 | 299 | {"type": "string"}, |
|
329 | 300 | { |
|
330 | 301 | "type": "array", |
|
331 | 302 | "items": {"type": "string"} |
|
332 | 303 | } |
|
333 | 304 | ] |
|
334 | 305 | } |
|
335 | 306 | } |
|
336 | 307 | } |
|
337 | 308 | } |
@@ -1,124 +1,125 b'' | |||
|
1 | 1 | """Base classes and utilities for readers and writers.""" |
|
2 | 2 | |
|
3 | 3 | # Copyright (c) IPython Development Team. |
|
4 | 4 | # Distributed under the terms of the Modified BSD License. |
|
5 | 5 | |
|
6 | 6 | from IPython.utils import py3compat |
|
7 | 7 | from IPython.utils.py3compat import unicode_type, string_types |
|
8 | 8 | |
|
9 | 9 | # output keys that are likely to have multiline values |
|
10 | 10 | _multiline_outputs = { |
|
11 | 11 | 'text/plain', |
|
12 | 12 | 'text/html', |
|
13 | 13 | 'image/svg+xml', |
|
14 | 14 | 'text/latex', |
|
15 | 15 | 'application/javascript', |
|
16 | 16 | } |
|
17 | 17 | |
|
18 | 18 | |
|
19 | 19 | # FIXME: workaround for old splitlines() |
|
20 | 20 | def _join_lines(lines): |
|
21 | 21 | """join lines that have been written by splitlines() |
|
22 | 22 | |
|
23 | 23 | Has logic to protect against `splitlines()`, which |
|
24 | 24 | should have been `splitlines(True)` |
|
25 | 25 | """ |
|
26 | 26 | if lines and lines[0].endswith(('\n', '\r')): |
|
27 | 27 | # created by splitlines(True) |
|
28 | 28 | return u''.join(lines) |
|
29 | 29 | else: |
|
30 | 30 | # created by splitlines() |
|
31 | 31 | return u'\n'.join(lines) |
|
32 | 32 | |
|
33 | 33 | |
|
34 | 34 | def rejoin_lines(nb): |
|
35 | 35 | """rejoin multiline text into strings |
|
36 | 36 | |
|
37 | 37 | For reversing effects of ``split_lines(nb)``. |
|
38 | 38 | |
|
39 | 39 | This only rejoins lines that have been split, so if text objects were not split |
|
40 | 40 | they will pass through unchanged. |
|
41 | 41 | |
|
42 | 42 | Used when reading JSON files that may have been passed through split_lines. |
|
43 | 43 | """ |
|
44 | 44 | for cell in nb.cells: |
|
45 | 45 | if 'source' in cell and isinstance(cell.source, list): |
|
46 | 46 | cell.source = _join_lines(cell.source) |
|
47 | if cell.cell_type == 'code': | |
|
48 | for output in cell.outputs: | |
|
49 | if output.output_type in {'execute_result', 'display_data'}: | |
|
50 | for key, value in output.data.items(): | |
|
47 | if cell.get('cell_type', None) == 'code': | |
|
48 | for output in cell.get('outputs', []): | |
|
49 | output_type = output.get('output_type', '') | |
|
50 | if output_type in {'execute_result', 'display_data'}: | |
|
51 | for key, value in output.get('data', {}).items(): | |
|
51 | 52 | if key != 'application/json' and isinstance(value, list): |
|
52 | 53 | output.data[key] = _join_lines(value) |
|
53 |
elif |
|
|
54 | if isinstance(output.text, list): | |
|
54 | elif output_type: | |
|
55 | if isinstance(output.get('text', ''), list): | |
|
55 | 56 | output.text = _join_lines(output.text) |
|
56 | 57 | return nb |
|
57 | 58 | |
|
58 | 59 | |
|
59 | 60 | def split_lines(nb): |
|
60 | 61 | """split likely multiline text into lists of strings |
|
61 | 62 | |
|
62 | 63 | For file output more friendly to line-based VCS. ``rejoin_lines(nb)`` will |
|
63 | 64 | reverse the effects of ``split_lines(nb)``. |
|
64 | 65 | |
|
65 | 66 | Used when writing JSON files. |
|
66 | 67 | """ |
|
67 | 68 | for cell in nb.cells: |
|
68 | 69 | source = cell.get('source', None) |
|
69 | 70 | if isinstance(source, string_types): |
|
70 | 71 | cell['source'] = source.splitlines(True) |
|
71 | 72 | |
|
72 | 73 | if cell.cell_type == 'code': |
|
73 | 74 | for output in cell.outputs: |
|
74 | 75 | if output.output_type in {'execute_result', 'display_data'}: |
|
75 | 76 | for key, value in output.data.items(): |
|
76 | 77 | if key != 'application/json' and isinstance(value, string_types): |
|
77 | 78 | output.data[key] = value.splitlines(True) |
|
78 | 79 | elif output.output_type == 'stream': |
|
79 | 80 | if isinstance(output.text, string_types): |
|
80 | 81 | output.text = output.text.splitlines(True) |
|
81 | 82 | return nb |
|
82 | 83 | |
|
83 | 84 | |
|
84 | 85 | def strip_transient(nb): |
|
85 | 86 | """Strip transient values that shouldn't be stored in files. |
|
86 | 87 | |
|
87 | 88 | This should be called in *both* read and write. |
|
88 | 89 | """ |
|
89 | 90 | nb.metadata.pop('orig_nbformat', None) |
|
90 | 91 | nb.metadata.pop('orig_nbformat_minor', None) |
|
91 | 92 | for cell in nb.cells: |
|
92 | 93 | cell.metadata.pop('trusted', None) |
|
93 | 94 | return nb |
|
94 | 95 | |
|
95 | 96 | |
|
96 | 97 | class NotebookReader(object): |
|
97 | 98 | """A class for reading notebooks.""" |
|
98 | 99 | |
|
99 | 100 | def reads(self, s, **kwargs): |
|
100 | 101 | """Read a notebook from a string.""" |
|
101 | 102 | raise NotImplementedError("loads must be implemented in a subclass") |
|
102 | 103 | |
|
103 | 104 | def read(self, fp, **kwargs): |
|
104 | 105 | """Read a notebook from a file like object""" |
|
105 | 106 | nbs = fp.read() |
|
106 | 107 | if not py3compat.PY3 and not isinstance(nbs, unicode_type): |
|
107 | 108 | nbs = py3compat.str_to_unicode(nbs) |
|
108 | 109 | return self.reads(nbs, **kwargs) |
|
109 | 110 | |
|
110 | 111 | |
|
111 | 112 | class NotebookWriter(object): |
|
112 | 113 | """A class for writing notebooks.""" |
|
113 | 114 | |
|
114 | 115 | def writes(self, nb, **kwargs): |
|
115 | 116 | """Write a notebook to a string.""" |
|
116 | 117 | raise NotImplementedError("loads must be implemented in a subclass") |
|
117 | 118 | |
|
118 | 119 | def write(self, nb, fp, **kwargs): |
|
119 | 120 | """Write a notebook to a file like object""" |
|
120 | 121 | nbs = self.writes(nb,**kwargs) |
|
121 | 122 | if not py3compat.PY3 and not isinstance(nbs, unicode_type): |
|
122 | 123 | # this branch is likely only taken for JSON on Python 2 |
|
123 | 124 | nbs = py3compat.str_to_unicode(nbs) |
|
124 | 125 | return fp.write(nbs) |
@@ -1,105 +1,104 b'' | |||
|
1 | 1 | # -*- coding: utf-8 -*- |
|
2 | 2 | |
|
3 | 3 | import os |
|
4 | 4 | from base64 import encodestring |
|
5 | 5 | |
|
6 | 6 | from ..nbbase import ( |
|
7 |
new_code_cell |
|
|
7 | new_code_cell, new_markdown_cell, new_notebook, | |
|
8 | 8 | new_output, new_raw_cell |
|
9 | 9 | ) |
|
10 | 10 | |
|
11 | 11 | # some random base64-encoded *text* |
|
12 | 12 | png = encodestring(os.urandom(5)).decode('ascii') |
|
13 | 13 | jpeg = encodestring(os.urandom(6)).decode('ascii') |
|
14 | 14 | |
|
15 | 15 | cells = [] |
|
16 | 16 | cells.append(new_markdown_cell( |
|
17 | 17 | source='Some NumPy Examples', |
|
18 | 18 | )) |
|
19 | 19 | |
|
20 | 20 | |
|
21 | 21 | cells.append(new_code_cell( |
|
22 | 22 | source='import numpy', |
|
23 | 23 | execution_count=1, |
|
24 | 24 | )) |
|
25 | 25 | |
|
26 | 26 | cells.append(new_markdown_cell( |
|
27 | 27 | source='A random array', |
|
28 | 28 | )) |
|
29 | 29 | |
|
30 | 30 | cells.append(new_raw_cell( |
|
31 | 31 | source='A random array', |
|
32 | 32 | )) |
|
33 | 33 | |
|
34 |
cells.append(new_ |
|
|
35 | source=u'My Heading', | |
|
36 | level=2, | |
|
34 | cells.append(new_markdown_cell( | |
|
35 | source=u'## My Heading', | |
|
37 | 36 | )) |
|
38 | 37 | |
|
39 | 38 | cells.append(new_code_cell( |
|
40 | 39 | source='a = numpy.random.rand(100)', |
|
41 | 40 | execution_count=2, |
|
42 | 41 | )) |
|
43 | 42 | cells.append(new_code_cell( |
|
44 | 43 | source='a = 10\nb = 5\n', |
|
45 | 44 | execution_count=3, |
|
46 | 45 | )) |
|
47 | 46 | cells.append(new_code_cell( |
|
48 | 47 | source='a = 10\nb = 5', |
|
49 | 48 | execution_count=4, |
|
50 | 49 | )) |
|
51 | 50 | |
|
52 | 51 | cells.append(new_code_cell( |
|
53 | 52 | source=u'print "ünîcødé"', |
|
54 | 53 | execution_count=3, |
|
55 | 54 | outputs=[new_output( |
|
56 | 55 | output_type=u'execute_result', |
|
57 | 56 | data={ |
|
58 | 57 | 'text/plain': u'<array a>', |
|
59 | 58 | 'text/html': u'The HTML rep', |
|
60 | 59 | 'text/latex': u'$a$', |
|
61 | 60 | 'image/png': png, |
|
62 | 61 | 'image/jpeg': jpeg, |
|
63 | 62 | 'image/svg+xml': u'<svg>', |
|
64 | 63 | 'application/json': { |
|
65 | 64 | 'key': 'value' |
|
66 | 65 | }, |
|
67 | 66 | 'application/javascript': u'var i=0;' |
|
68 | 67 | }, |
|
69 | 68 | execution_count=3 |
|
70 | 69 | ),new_output( |
|
71 | 70 | output_type=u'display_data', |
|
72 | 71 | data={ |
|
73 | 72 | 'text/plain': u'<array a>', |
|
74 | 73 | 'text/html': u'The HTML rep', |
|
75 | 74 | 'text/latex': u'$a$', |
|
76 | 75 | 'image/png': png, |
|
77 | 76 | 'image/jpeg': jpeg, |
|
78 | 77 | 'image/svg+xml': u'<svg>', |
|
79 | 78 | 'application/json': { |
|
80 | 79 | 'key': 'value' |
|
81 | 80 | }, |
|
82 | 81 | 'application/javascript': u'var i=0;' |
|
83 | 82 | }, |
|
84 | 83 | ),new_output( |
|
85 | 84 | output_type=u'error', |
|
86 | 85 | ename=u'NameError', |
|
87 | 86 | evalue=u'NameError was here', |
|
88 | 87 | traceback=[u'frame 0', u'frame 1', u'frame 2'] |
|
89 | 88 | ),new_output( |
|
90 | 89 | output_type=u'stream', |
|
91 | 90 | text='foo\rbar\r\n' |
|
92 | 91 | ),new_output( |
|
93 | 92 | output_type=u'stream', |
|
94 | 93 | name='stderr', |
|
95 | 94 | text='\rfoo\rbar\n' |
|
96 | 95 | )] |
|
97 | 96 | )) |
|
98 | 97 | |
|
99 | 98 | nb0 = new_notebook(cells=cells, |
|
100 | 99 | metadata={ |
|
101 | 100 | 'language': 'python', |
|
102 | 101 | } |
|
103 | 102 | ) |
|
104 | 103 | |
|
105 | 104 |
@@ -1,19 +1,67 b'' | |||
|
1 | 1 | import copy |
|
2 | 2 | |
|
3 | import nose.tools as nt | |
|
4 | ||
|
3 | 5 | from IPython.nbformat.current import validate |
|
4 | 6 | from .. import convert |
|
5 | 7 | |
|
6 | 8 | from . import nbexamples |
|
7 | 9 | from IPython.nbformat.v3.tests import nbexamples as v3examples |
|
10 | from IPython.nbformat import v3, v4 | |
|
8 | 11 | |
|
9 | 12 | def test_upgrade_notebook(): |
|
10 | 13 | nb03 = copy.deepcopy(v3examples.nb0) |
|
11 | 14 | validate(nb03) |
|
12 | 15 | nb04 = convert.upgrade(nb03) |
|
13 | 16 | validate(nb04) |
|
14 | 17 | |
|
15 | 18 | def test_downgrade_notebook(): |
|
16 | 19 | nb04 = copy.deepcopy(nbexamples.nb0) |
|
17 | 20 | validate(nb04) |
|
18 | 21 | nb03 = convert.downgrade(nb04) |
|
19 | 22 | validate(nb03) |
|
23 | ||
|
24 | def test_upgrade_heading(): | |
|
25 | v3h = v3.new_heading_cell | |
|
26 | v4m = v4.new_markdown_cell | |
|
27 | for v3cell, expected in [ | |
|
28 | ( | |
|
29 | v3h(source='foo', level=1), | |
|
30 | v4m(source='# foo'), | |
|
31 | ), | |
|
32 | ( | |
|
33 | v3h(source='foo\nbar\nmulti-line\n', level=4), | |
|
34 | v4m(source='#### foo bar multi-line'), | |
|
35 | ), | |
|
36 | ]: | |
|
37 | upgraded = convert.upgrade_cell(v3cell) | |
|
38 | nt.assert_equal(upgraded, expected) | |
|
39 | ||
|
40 | def test_downgrade_heading(): | |
|
41 | v3h = v3.new_heading_cell | |
|
42 | v4m = v4.new_markdown_cell | |
|
43 | v3m = lambda source: v3.new_text_cell('markdown', source) | |
|
44 | for v4cell, expected in [ | |
|
45 | ( | |
|
46 | v4m(source='# foo'), | |
|
47 | v3h(source='foo', level=1), | |
|
48 | ), | |
|
49 | ( | |
|
50 | v4m(source='#foo'), | |
|
51 | v3h(source='foo', level=1), | |
|
52 | ), | |
|
53 | ( | |
|
54 | v4m(source='#\tfoo'), | |
|
55 | v3h(source='foo', level=1), | |
|
56 | ), | |
|
57 | ( | |
|
58 | v4m(source='# \t foo'), | |
|
59 | v3h(source='foo', level=1), | |
|
60 | ), | |
|
61 | ( | |
|
62 | v4m(source='# foo\nbar'), | |
|
63 | v3m(source='# foo\nbar'), | |
|
64 | ), | |
|
65 | ]: | |
|
66 | downgraded = convert.downgrade_cell(v4cell) | |
|
67 | nt.assert_equal(downgraded, expected) |
@@ -1,112 +1,101 b'' | |||
|
1 | 1 | # coding: utf-8 |
|
2 | 2 | """Tests for the Python API for composing notebook elements""" |
|
3 | 3 | |
|
4 | 4 | import nose.tools as nt |
|
5 | 5 | |
|
6 | 6 | from IPython.nbformat.validator import isvalid, validate, ValidationError |
|
7 | 7 | from ..nbbase import ( |
|
8 | 8 | NotebookNode, nbformat, |
|
9 |
new_code_cell |
|
|
9 | new_code_cell, new_markdown_cell, new_notebook, | |
|
10 | 10 | new_output, new_raw_cell, |
|
11 | 11 | ) |
|
12 | 12 | |
|
13 | 13 | def test_empty_notebook(): |
|
14 | 14 | nb = new_notebook() |
|
15 | 15 | nt.assert_equal(nb.cells, []) |
|
16 | 16 | nt.assert_equal(nb.metadata, NotebookNode()) |
|
17 | 17 | nt.assert_equal(nb.nbformat, nbformat) |
|
18 | 18 | |
|
19 | 19 | def test_empty_markdown_cell(): |
|
20 | 20 | cell = new_markdown_cell() |
|
21 | 21 | nt.assert_equal(cell.cell_type, 'markdown') |
|
22 | 22 | nt.assert_equal(cell.source, '') |
|
23 | 23 | |
|
24 | 24 | def test_markdown_cell(): |
|
25 | 25 | cell = new_markdown_cell(u'* Søme markdown') |
|
26 | 26 | nt.assert_equal(cell.source, u'* Søme markdown') |
|
27 | 27 | |
|
28 | 28 | def test_empty_raw_cell(): |
|
29 | 29 | cell = new_raw_cell() |
|
30 | 30 | nt.assert_equal(cell.cell_type, u'raw') |
|
31 | 31 | nt.assert_equal(cell.source, '') |
|
32 | 32 | |
|
33 | 33 | def test_raw_cell(): |
|
34 | 34 | cell = new_raw_cell('hi') |
|
35 | 35 | nt.assert_equal(cell.source, u'hi') |
|
36 | 36 | |
|
37 | def test_empty_heading_cell(): | |
|
38 | cell = new_heading_cell() | |
|
39 | nt.assert_equal(cell.cell_type, u'heading') | |
|
40 | nt.assert_equal(cell.source, '') | |
|
41 | nt.assert_equal(cell.level, 1) | |
|
42 | ||
|
43 | def test_heading_cell(): | |
|
44 | cell = new_heading_cell(u'hi', level=2) | |
|
45 | nt.assert_equal(cell.source, u'hi') | |
|
46 | nt.assert_equal(cell.level, 2) | |
|
47 | ||
|
48 | 37 | def test_empty_code_cell(): |
|
49 | 38 | cell = new_code_cell('hi') |
|
50 | 39 | nt.assert_equal(cell.cell_type, 'code') |
|
51 | 40 | nt.assert_equal(cell.source, u'hi') |
|
52 | 41 | |
|
53 | 42 | def test_empty_display_data(): |
|
54 | 43 | output = new_output('display_data') |
|
55 | 44 | nt.assert_equal(output.output_type, 'display_data') |
|
56 | 45 | |
|
57 | 46 | def test_empty_stream(): |
|
58 | 47 | output = new_output('stream') |
|
59 | 48 | nt.assert_equal(output.output_type, 'stream') |
|
60 | 49 | nt.assert_equal(output.name, 'stdout') |
|
61 | 50 | nt.assert_equal(output.text, '') |
|
62 | 51 | |
|
63 | 52 | def test_empty_execute_result(): |
|
64 | 53 | output = new_output('execute_result', execution_count=1) |
|
65 | 54 | nt.assert_equal(output.output_type, 'execute_result') |
|
66 | 55 | |
|
67 | 56 | mimebundle = { |
|
68 | 57 | 'text/plain': "some text", |
|
69 | 58 | "application/json": { |
|
70 | 59 | "key": "value" |
|
71 | 60 | }, |
|
72 | 61 | "image/svg+xml": 'ABCDEF', |
|
73 | 62 | "application/octet-stream": 'ABC-123', |
|
74 | 63 | "application/vnd.foo+bar": "Some other stuff", |
|
75 | 64 | } |
|
76 | 65 | |
|
77 | 66 | def test_display_data(): |
|
78 | 67 | output = new_output('display_data', mimebundle) |
|
79 | 68 | for key, expected in mimebundle.items(): |
|
80 | 69 | nt.assert_equal(output.data[key], expected) |
|
81 | 70 | |
|
82 | 71 | def test_execute_result(): |
|
83 | 72 | output = new_output('execute_result', mimebundle, execution_count=10) |
|
84 | 73 | nt.assert_equal(output.execution_count, 10) |
|
85 | 74 | for key, expected in mimebundle.items(): |
|
86 | 75 | nt.assert_equal(output.data[key], expected) |
|
87 | 76 | |
|
88 | 77 | def test_error(): |
|
89 | 78 | o = new_output(output_type=u'error', ename=u'NameError', |
|
90 | 79 | evalue=u'Name not found', traceback=[u'frame 0', u'frame 1', u'frame 2'] |
|
91 | 80 | ) |
|
92 | 81 | nt.assert_equal(o.output_type, u'error') |
|
93 | 82 | nt.assert_equal(o.ename, u'NameError') |
|
94 | 83 | nt.assert_equal(o.evalue, u'Name not found') |
|
95 | 84 | nt.assert_equal(o.traceback, [u'frame 0', u'frame 1', u'frame 2']) |
|
96 | 85 | |
|
97 | 86 | def test_code_cell_with_outputs(): |
|
98 | 87 | cell = new_code_cell(execution_count=10, outputs=[ |
|
99 | 88 | new_output('display_data', mimebundle), |
|
100 | 89 | new_output('stream', text='hello'), |
|
101 | 90 | new_output('execute_result', mimebundle, execution_count=10), |
|
102 | 91 | ]) |
|
103 | 92 | nt.assert_equal(cell.execution_count, 10) |
|
104 | 93 | nt.assert_equal(len(cell.outputs), 3) |
|
105 | 94 | er = cell.outputs[-1] |
|
106 | 95 | nt.assert_equal(er.execution_count, 10) |
|
107 | 96 | nt.assert_equal(er['output_type'], 'execute_result') |
|
108 | 97 | |
|
109 | 98 | def test_stream(): |
|
110 | 99 | output = new_output('stream', name='stderr', text='hello there') |
|
111 | 100 | nt.assert_equal(output.name, 'stderr') |
|
112 | 101 | nt.assert_equal(output.text, 'hello there') |
@@ -1,130 +1,105 b'' | |||
|
1 | 1 | """Tests for nbformat validation""" |
|
2 | 2 | |
|
3 | 3 | # Copyright (c) IPython Development Team. |
|
4 | 4 | # Distributed under the terms of the Modified BSD License. |
|
5 | 5 | |
|
6 | 6 | import io |
|
7 | 7 | import os |
|
8 | 8 | |
|
9 | 9 | import nose.tools as nt |
|
10 | 10 | |
|
11 | 11 | from IPython.nbformat.validator import validate, ValidationError |
|
12 | 12 | from ..nbjson import reads |
|
13 | 13 | from ..nbbase import ( |
|
14 | 14 | nbformat, |
|
15 |
new_code_cell |
|
|
15 | new_code_cell, new_markdown_cell, new_notebook, | |
|
16 | 16 | new_output, new_raw_cell, |
|
17 | 17 | ) |
|
18 | 18 | |
|
19 | 19 | def validate4(obj, ref=None): |
|
20 | 20 | return validate(obj, ref, version=nbformat) |
|
21 | 21 | |
|
22 | 22 | def test_valid_code_cell(): |
|
23 | 23 | cell = new_code_cell() |
|
24 | 24 | validate4(cell, 'code_cell') |
|
25 | 25 | |
|
26 | 26 | def test_invalid_code_cell(): |
|
27 | 27 | cell = new_code_cell() |
|
28 | 28 | |
|
29 | 29 | cell['source'] = 5 |
|
30 | 30 | with nt.assert_raises(ValidationError): |
|
31 | 31 | validate4(cell, 'code_cell') |
|
32 | 32 | |
|
33 | 33 | cell = new_code_cell() |
|
34 | 34 | del cell['metadata'] |
|
35 | 35 | |
|
36 | 36 | with nt.assert_raises(ValidationError): |
|
37 | 37 | validate4(cell, 'code_cell') |
|
38 | 38 | |
|
39 | 39 | cell = new_code_cell() |
|
40 | 40 | del cell['source'] |
|
41 | 41 | |
|
42 | 42 | with nt.assert_raises(ValidationError): |
|
43 | 43 | validate4(cell, 'code_cell') |
|
44 | 44 | |
|
45 | 45 | cell = new_code_cell() |
|
46 | 46 | del cell['cell_type'] |
|
47 | 47 | |
|
48 | 48 | with nt.assert_raises(ValidationError): |
|
49 | 49 | validate4(cell, 'code_cell') |
|
50 | 50 | |
|
51 | 51 | def test_invalid_markdown_cell(): |
|
52 | 52 | cell = new_markdown_cell() |
|
53 | 53 | |
|
54 | 54 | cell['source'] = 5 |
|
55 | 55 | with nt.assert_raises(ValidationError): |
|
56 | 56 | validate4(cell, 'markdown_cell') |
|
57 | 57 | |
|
58 | 58 | cell = new_markdown_cell() |
|
59 | 59 | del cell['metadata'] |
|
60 | 60 | |
|
61 | 61 | with nt.assert_raises(ValidationError): |
|
62 | 62 | validate4(cell, 'markdown_cell') |
|
63 | 63 | |
|
64 | 64 | cell = new_markdown_cell() |
|
65 | 65 | del cell['source'] |
|
66 | 66 | |
|
67 | 67 | with nt.assert_raises(ValidationError): |
|
68 | 68 | validate4(cell, 'markdown_cell') |
|
69 | 69 | |
|
70 | 70 | cell = new_markdown_cell() |
|
71 | 71 | del cell['cell_type'] |
|
72 | 72 | |
|
73 | 73 | with nt.assert_raises(ValidationError): |
|
74 | 74 | validate4(cell, 'markdown_cell') |
|
75 | 75 | |
|
76 | def test_invalid_heading_cell(): | |
|
77 | cell = new_heading_cell() | |
|
78 | ||
|
79 | cell['source'] = 5 | |
|
80 | with nt.assert_raises(ValidationError): | |
|
81 | validate4(cell, 'heading_cell') | |
|
82 | ||
|
83 | cell = new_heading_cell() | |
|
84 | del cell['metadata'] | |
|
85 | ||
|
86 | with nt.assert_raises(ValidationError): | |
|
87 | validate4(cell, 'heading_cell') | |
|
88 | ||
|
89 | cell = new_heading_cell() | |
|
90 | del cell['source'] | |
|
91 | ||
|
92 | with nt.assert_raises(ValidationError): | |
|
93 | validate4(cell, 'heading_cell') | |
|
94 | ||
|
95 | cell = new_heading_cell() | |
|
96 | del cell['cell_type'] | |
|
97 | ||
|
98 | with nt.assert_raises(ValidationError): | |
|
99 | validate4(cell, 'heading_cell') | |
|
100 | ||
|
101 | 76 | def test_invalid_raw_cell(): |
|
102 | 77 | cell = new_raw_cell() |
|
103 | 78 | |
|
104 | 79 | cell['source'] = 5 |
|
105 | 80 | with nt.assert_raises(ValidationError): |
|
106 | 81 | validate4(cell, 'raw_cell') |
|
107 | 82 | |
|
108 | 83 | cell = new_raw_cell() |
|
109 | 84 | del cell['metadata'] |
|
110 | 85 | |
|
111 | 86 | with nt.assert_raises(ValidationError): |
|
112 | 87 | validate4(cell, 'raw_cell') |
|
113 | 88 | |
|
114 | 89 | cell = new_raw_cell() |
|
115 | 90 | del cell['source'] |
|
116 | 91 | |
|
117 | 92 | with nt.assert_raises(ValidationError): |
|
118 | 93 | validate4(cell, 'raw_cell') |
|
119 | 94 | |
|
120 | 95 | cell = new_raw_cell() |
|
121 | 96 | del cell['cell_type'] |
|
122 | 97 | |
|
123 | 98 | with nt.assert_raises(ValidationError): |
|
124 | 99 | validate4(cell, 'raw_cell') |
|
125 | 100 | |
|
126 | 101 | def test_sample_notebook(): |
|
127 | 102 | here = os.path.dirname(__file__) |
|
128 | 103 | with io.open(os.path.join(here, os.pardir, os.pardir, 'tests', "test4.ipynb"), encoding='utf-8') as f: |
|
129 | 104 | nb = reads(f.read()) |
|
130 | 105 | validate4(nb) |
@@ -1,291 +1,276 b'' | |||
|
1 | 1 | .. _nbformat: |
|
2 | 2 | |
|
3 | 3 | =========================== |
|
4 | 4 | The Jupyter Notebook Format |
|
5 | 5 | =========================== |
|
6 | 6 | |
|
7 | 7 | Introduction |
|
8 | 8 | ============ |
|
9 | 9 | |
|
10 | 10 | Jupyter (née IPython) notebook files are simple JSON documents, |
|
11 | 11 | containing text, source code, rich media output, and metadata. |
|
12 | 12 | each segment of the document is stored in a cell. |
|
13 | 13 | |
|
14 | 14 | Some general points about the notebook format: |
|
15 | 15 | |
|
16 | 16 | .. note:: |
|
17 | 17 | |
|
18 | 18 | *All* metadata fields are optional. |
|
19 | 19 | While the type and values of some metadata are defined, |
|
20 | 20 | no metadata values are required to be defined. |
|
21 | 21 | |
|
22 | 22 | |
|
23 | 23 | Top-level structure |
|
24 | 24 | =================== |
|
25 | 25 | |
|
26 | 26 | At the highest level, a Jupyter notebook is a dictionary with a few keys: |
|
27 | 27 | |
|
28 | 28 | - metadata (dict) |
|
29 | 29 | - nbformat (int) |
|
30 | 30 | - nbformat_minor (int) |
|
31 | 31 | - cells (list) |
|
32 | 32 | |
|
33 | 33 | .. sourcecode:: python |
|
34 | 34 | |
|
35 | 35 | { |
|
36 | 36 | "metadata" : { |
|
37 | 37 | "signature": "hex-digest", # used for authenticating unsafe outputs on load |
|
38 | 38 | "kernel_info": { |
|
39 | 39 | # if kernel_info is defined, its name and language fields are required. |
|
40 | 40 | "name" : "the name of the kernel", |
|
41 | 41 | "language" : "the programming language of the kernel", |
|
42 | 42 | "codemirror_mode": "The name of the codemirror mode to use [optional]" |
|
43 | 43 | }, |
|
44 | 44 | }, |
|
45 | 45 | "nbformat": 4, |
|
46 | 46 | "nbformat_minor": 0, |
|
47 | 47 | "cells" : [ |
|
48 | 48 | # list of cell dictionaries, see below |
|
49 | 49 | ], |
|
50 | 50 | } |
|
51 | 51 | |
|
52 | 52 | |
|
53 | 53 | Cell Types |
|
54 | 54 | ========== |
|
55 | 55 | |
|
56 | 56 | There are a few basic cell types for encapsulating code and text. |
|
57 | 57 | All cells have the following basic structure: |
|
58 | 58 | |
|
59 | 59 | .. sourcecode:: python |
|
60 | 60 | |
|
61 | 61 | { |
|
62 | 62 | "cell_type" : "name", |
|
63 | 63 | "metadata" : {}, |
|
64 | 64 | "source" : "single string or [list, of, strings]", |
|
65 | 65 | } |
|
66 | 66 | |
|
67 | 67 | |
|
68 | 68 | Markdown cells |
|
69 | 69 | -------------- |
|
70 | 70 | |
|
71 | 71 | Markdown cells are used for body-text, and contain markdown, |
|
72 | 72 | as defined in `GitHub-flavored markdown`_, and implemented in marked_. |
|
73 | 73 | |
|
74 | 74 | .. _GitHub-flavored markdown: https://help.github.com/articles/github-flavored-markdown |
|
75 | 75 | .. _marked: https://github.com/chjj/marked |
|
76 | 76 | |
|
77 | 77 | .. sourcecode:: python |
|
78 | 78 | |
|
79 | 79 | { |
|
80 | 80 | "cell_type" : "markdown", |
|
81 | 81 | "metadata" : {}, |
|
82 | 82 | "source" : ["some *markdown*"], |
|
83 | 83 | } |
|
84 | 84 | |
|
85 | .. versionchanged:: 4.0 | |
|
85 | 86 | |
|
86 | Heading cells | |
|
87 | ------------- | |
|
88 | ||
|
89 | Heading cells are single lines describing a section header (mapping onto h1-h6 tags in HTML). | |
|
90 | These cells indicate structure of the document, | |
|
91 | and are used for things like outline-views and automatically generating HTML anchors | |
|
92 | within the page for quick navigation. | |
|
93 | They have a ``level`` field, with an integer value from 1-6 (inclusive). | |
|
94 | ||
|
95 | .. sourcecode:: python | |
|
96 | ||
|
97 | { | |
|
98 | "cell_type" : "markdown", | |
|
99 | "metadata" : {}, | |
|
100 | "level" : 1, # An integer on [1-6] | |
|
101 | "source" : ["A simple heading"], | |
|
102 | } | |
|
87 | Heading cells have been removed, in favor of simple headings in markdown. | |
|
103 | 88 | |
|
104 | 89 | |
|
105 | 90 | Code cells |
|
106 | 91 | ---------- |
|
107 | 92 | |
|
108 | 93 | Code cells are the primary content of Jupyter notebooks. |
|
109 | 94 | They contain source code int e language of the document's associated kernel, |
|
110 | 95 | and a list of outputs associated with executing. |
|
111 | 96 | They also have an execution_count, which must be an integer or ``null``. |
|
112 | 97 | |
|
113 | 98 | .. sourcecode:: python |
|
114 | 99 | |
|
115 | 100 | { |
|
116 | 101 | "cell_type" : "code", |
|
117 | 102 | "execution_count": 1, # integer or null |
|
118 | 103 | "metadata" : { |
|
119 | 104 | "collapsed" : True, # whether the output of the cell is collapsed |
|
120 | 105 | "autoscroll": False, # any of true, false or "auto" |
|
121 | 106 | }, |
|
122 | 107 | "source" : ["some code"], |
|
123 | 108 | "outputs": [{ |
|
124 | 109 | # list of output dicts (described below) |
|
125 | 110 | "output_type": "stream", |
|
126 | 111 | ... |
|
127 | 112 | }], |
|
128 | 113 | } |
|
129 | 114 | |
|
130 | 115 | .. versionchanged:: 4.0 |
|
131 | 116 | |
|
132 | 117 | ``input`` was renamed to ``source``, for consistency among cell types. |
|
133 | 118 | |
|
134 | 119 | .. versionchanged:: 4.0 |
|
135 | 120 | |
|
136 | 121 | ``prompt_number`` renamed to ``execution_count`` |
|
137 | 122 | |
|
138 | 123 | Code cell outputs |
|
139 | 124 | ----------------- |
|
140 | 125 | |
|
141 | 126 | A code cell can have a variety of outputs (stream data or rich mime-type output). |
|
142 | 127 | These correspond to :ref:`messages <messaging>` produced as a result of executing the cell. |
|
143 | 128 | |
|
144 | 129 | All outputs have an ``output_type`` field, |
|
145 | 130 | which is a string defining what type of output it is. |
|
146 | 131 | |
|
147 | 132 | |
|
148 | 133 | stream output |
|
149 | 134 | ************* |
|
150 | 135 | |
|
151 | 136 | .. sourcecode:: python |
|
152 | 137 | |
|
153 | 138 | { |
|
154 | 139 | "output_type" : "stream", |
|
155 | 140 | "name" : "stdout", # or stderr |
|
156 | 141 | "data" : ["multiline stream text"], |
|
157 | 142 | } |
|
158 | 143 | |
|
159 | 144 | .. versionchanged:: 4.0 |
|
160 | 145 | |
|
161 | 146 | The keys ``stream`` and ``text`` were changed to ``name`` and ``data`` to match |
|
162 | 147 | the stream message specification. |
|
163 | 148 | |
|
164 | 149 | |
|
165 | 150 | display_data |
|
166 | 151 | ************ |
|
167 | 152 | |
|
168 | 153 | Rich display messages (as created by ``display_data`` messages) |
|
169 | 154 | contain data keyed by mime-type. All mime-type data should |
|
170 | 155 | The metadata of these messages may be keyed by mime-type as well. |
|
171 | 156 | |
|
172 | 157 | |
|
173 | 158 | .. sourcecode:: python |
|
174 | 159 | |
|
175 | 160 | { |
|
176 | 161 | "output_type" : "display_data", |
|
177 | 162 | "data" : { |
|
178 | 163 | "text/plain" : ["multiline text data"], |
|
179 | 164 | "image/png": ["base64-encoded-png-data"], |
|
180 | 165 | "application/json": { |
|
181 | 166 | # JSON data is included as-is |
|
182 | 167 | "json": "data", |
|
183 | 168 | }, |
|
184 | 169 | }, |
|
185 | 170 | "metadata" : { |
|
186 | 171 | "image/png": { |
|
187 | 172 | "width": 640, |
|
188 | 173 | "height": 480, |
|
189 | 174 | }, |
|
190 | 175 | }, |
|
191 | 176 | } |
|
192 | 177 | |
|
193 | 178 | |
|
194 | 179 | .. versionchanged:: 4.0 |
|
195 | 180 | |
|
196 | 181 | ``application/json`` output is no longer double-serialized into a string. |
|
197 | 182 | |
|
198 | 183 | .. versionchanged:: 4.0 |
|
199 | 184 | |
|
200 | 185 | mime-types are used for keys, instead of a combination of short names (``text``) |
|
201 | 186 | and mime-types, and are stored in a ``data`` key, rather than the top-level. |
|
202 | 187 | i.e. ``output.data['image/png']`` instead of ``output.png``. |
|
203 | 188 | |
|
204 | 189 | |
|
205 | 190 | execute_result |
|
206 | 191 | ************** |
|
207 | 192 | |
|
208 | 193 | Results of executing a cell (as created by ``displayhook`` in Python) |
|
209 | 194 | are stored in ``execute_result`` outputs. |
|
210 | 195 | `execute_result` outputs are identical to ``display_data``, |
|
211 | 196 | adding only a ``prompt_number`` field, which must be an integer. |
|
212 | 197 | |
|
213 | 198 | .. sourcecode:: python |
|
214 | 199 | |
|
215 | 200 | { |
|
216 | 201 | "output_type" : "execute_result", |
|
217 | 202 | "execute_result": 42, |
|
218 | 203 | "data" : { |
|
219 | 204 | "text/plain" : ["multiline text data"], |
|
220 | 205 | "image/png": ["base64-encoded-png-data"], |
|
221 | 206 | "application/json": { |
|
222 | 207 | # JSON data is included as-is |
|
223 | 208 | "json": "data", |
|
224 | 209 | }, |
|
225 | 210 | }, |
|
226 | 211 | "metadata" : { |
|
227 | 212 | "image/png": { |
|
228 | 213 | "width": 640, |
|
229 | 214 | "height": 480, |
|
230 | 215 | }, |
|
231 | 216 | }, |
|
232 | 217 | } |
|
233 | 218 | |
|
234 | 219 | .. versionchanged:: 4.0 |
|
235 | 220 | |
|
236 | 221 | ``pyout`` renamed to ``execute_result`` |
|
237 | 222 | |
|
238 | 223 | .. versionchanged:: 4.0 |
|
239 | 224 | |
|
240 | 225 | ``prompt_number`` renamed to ``execution_count`` |
|
241 | 226 | |
|
242 | 227 | |
|
243 | 228 | error |
|
244 | 229 | ***** |
|
245 | 230 | |
|
246 | 231 | Failed execution may show a traceback |
|
247 | 232 | |
|
248 | 233 | .. sourcecode:: python |
|
249 | 234 | |
|
250 | 235 | { |
|
251 | 236 | 'ename' : str, # Exception name, as a string |
|
252 | 237 | 'evalue' : str, # Exception value, as a string |
|
253 | 238 | |
|
254 | 239 | # The traceback will contain a list of frames, |
|
255 | 240 | # represented each as a string. |
|
256 | 241 | 'traceback' : list, |
|
257 | 242 | } |
|
258 | 243 | |
|
259 | 244 | .. versionchanged:: 4.0 |
|
260 | 245 | |
|
261 | 246 | ``pyerr`` renamed to ``error`` |
|
262 | 247 | |
|
263 | 248 | |
|
264 | 249 | Raw NBConvert cells |
|
265 | 250 | ------------------- |
|
266 | 251 | |
|
267 | 252 | A raw cell is defined as content that should be included *unmodified* in :ref:`nbconvert <nbconvert>` output. |
|
268 | 253 | For example, this cell could include raw LaTeX for nbconvert to pdf via latex, |
|
269 | 254 | or restructured text for use in Sphinx documentation. |
|
270 | 255 | |
|
271 | 256 | The notebook authoring environment does not render raw cells. |
|
272 | 257 | |
|
273 | 258 | The only logic in a raw cell is the `format` metadata field. |
|
274 | 259 | If defined, it specifies which nbconvert output format is the intended target |
|
275 | 260 | for the raw cell. When outputting to any other format, |
|
276 | 261 | the raw cell's contents will be excluded. |
|
277 | 262 | In the default case when this value is undefined, |
|
278 | 263 | a raw cell's contents will be included in any nbconvert output, |
|
279 | 264 | regardless of format. |
|
280 | 265 | |
|
281 | 266 | .. sourcecode:: python |
|
282 | 267 | |
|
283 | 268 | { |
|
284 | 269 | "cell_type" : "raw", |
|
285 | 270 | "metadata" : { |
|
286 | 271 | # the mime-type of the target nbconvert format. |
|
287 | 272 | # nbconvert to formats other than this will exclude this cell. |
|
288 | 273 | "format" : "mime/type" |
|
289 | 274 | }, |
|
290 | 275 | "source" : ["some nbformat mime-type data"] |
|
291 | 276 | } |
General Comments 0
You need to be logged in to leave comments.
Login now