Show More
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 |
@@ -0,0 +1,32 | |||||
|
1 | """Test the /tree handlers""" | |||
|
2 | import os | |||
|
3 | import io | |||
|
4 | from IPython.html.utils import url_path_join | |||
|
5 | from IPython.nbformat import write | |||
|
6 | from IPython.nbformat.v4 import new_notebook | |||
|
7 | ||||
|
8 | import requests | |||
|
9 | ||||
|
10 | from IPython.html.tests.launchnotebook import NotebookTestBase | |||
|
11 | ||||
|
12 | class TreeTest(NotebookTestBase): | |||
|
13 | def setUp(self): | |||
|
14 | nbdir = self.notebook_dir.name | |||
|
15 | d = os.path.join(nbdir, 'foo') | |||
|
16 | os.mkdir(d) | |||
|
17 | ||||
|
18 | with io.open(os.path.join(d, 'bar.ipynb'), 'w', encoding='utf-8') as f: | |||
|
19 | nb = new_notebook() | |||
|
20 | write(nb, f, version=4) | |||
|
21 | ||||
|
22 | with io.open(os.path.join(d, 'baz.txt'), 'w', encoding='utf-8') as f: | |||
|
23 | f.write(u'flamingo') | |||
|
24 | ||||
|
25 | self.base_url() | |||
|
26 | ||||
|
27 | def test_redirect(self): | |||
|
28 | r = requests.get(url_path_join(self.base_url(), 'tree/foo/bar.ipynb')) | |||
|
29 | self.assertEqual(r.url, self.base_url() + 'notebooks/foo/bar.ipynb') | |||
|
30 | ||||
|
31 | r = requests.get(url_path_join(self.base_url(), 'tree/foo/baz.txt')) | |||
|
32 | self.assertEqual(r.url, url_path_join(self.base_url(), 'files/foo/baz.txt')) |
@@ -28,7 +28,7 class FilesHandler(IPythonHandler): | |||||
28 | else: |
|
28 | else: | |
29 | name = path |
|
29 | name = path | |
30 |
|
30 | |||
31 |
model = cm.get |
|
31 | model = cm.get(path) | |
32 |
|
32 | |||
33 | if self.get_argument("download", False): |
|
33 | if self.get_argument("download", False): | |
34 | self.set_header('Content-Disposition','attachment; filename="%s"' % name) |
|
34 | self.set_header('Content-Disposition','attachment; filename="%s"' % name) |
@@ -81,7 +81,7 class NbconvertFileHandler(IPythonHandler): | |||||
81 | exporter = get_exporter(format, config=self.config, log=self.log) |
|
81 | exporter = get_exporter(format, config=self.config, log=self.log) | |
82 |
|
82 | |||
83 | path = path.strip('/') |
|
83 | path = path.strip('/') | |
84 |
model = self.contents_manager.get |
|
84 | model = self.contents_manager.get(path=path) | |
85 | name = model['name'] |
|
85 | name = model['name'] | |
86 |
|
86 | |||
87 | self.set_header('Last-Modified', model['last_modified']) |
|
87 | self.set_header('Last-Modified', model['last_modified']) |
@@ -200,7 +200,7 class FileContentsManager(ContentsManager): | |||||
200 | self.log.debug("%s not a regular file", os_path) |
|
200 | self.log.debug("%s not a regular file", os_path) | |
201 | continue |
|
201 | continue | |
202 | if self.should_list(name) and not is_hidden(os_path, self.root_dir): |
|
202 | if self.should_list(name) and not is_hidden(os_path, self.root_dir): | |
203 |
contents.append(self.get |
|
203 | contents.append(self.get( | |
204 | path='%s/%s' % (path, name), |
|
204 | path='%s/%s' % (path, name), | |
205 | content=False) |
|
205 | content=False) | |
206 | ) |
|
206 | ) | |
@@ -209,11 +209,15 class FileContentsManager(ContentsManager): | |||||
209 |
|
209 | |||
210 | return model |
|
210 | return model | |
211 |
|
211 | |||
212 | def _file_model(self, path, content=True): |
|
212 | def _file_model(self, path, content=True, format=None): | |
213 | """Build a model for a file |
|
213 | """Build a model for a file | |
214 |
|
214 | |||
215 | if content is requested, include the file contents. |
|
215 | if content is requested, include the file contents. | |
216 | UTF-8 text files will be unicode, binary files will be base64-encoded. |
|
216 | ||
|
217 | format: | |||
|
218 | If 'text', the contents will be decoded as UTF-8. | |||
|
219 | If 'base64', the raw bytes contents will be encoded as base64. | |||
|
220 | If not specified, try to decode as UTF-8, and fall back to base64 | |||
217 | """ |
|
221 | """ | |
218 | model = self._base_model(path) |
|
222 | model = self._base_model(path) | |
219 | model['type'] = 'file' |
|
223 | model['type'] = 'file' | |
@@ -224,13 +228,20 class FileContentsManager(ContentsManager): | |||||
224 | raise web.HTTPError(400, "Cannot get content of non-file %s" % os_path) |
|
228 | raise web.HTTPError(400, "Cannot get content of non-file %s" % os_path) | |
225 | with io.open(os_path, 'rb') as f: |
|
229 | with io.open(os_path, 'rb') as f: | |
226 | bcontent = f.read() |
|
230 | bcontent = f.read() | |
227 | try: |
|
231 | ||
228 | model['content'] = bcontent.decode('utf8') |
|
232 | if format != 'base64': | |
229 | except UnicodeError as e: |
|
233 | try: | |
|
234 | model['content'] = bcontent.decode('utf8') | |||
|
235 | except UnicodeError as e: | |||
|
236 | if format == 'text': | |||
|
237 | raise web.HTTPError(400, "%s is not UTF-8 encoded" % path) | |||
|
238 | else: | |||
|
239 | model['format'] = 'text' | |||
|
240 | ||||
|
241 | if model['content'] is None: | |||
230 | model['content'] = base64.encodestring(bcontent).decode('ascii') |
|
242 | model['content'] = base64.encodestring(bcontent).decode('ascii') | |
231 | model['format'] = 'base64' |
|
243 | model['format'] = 'base64' | |
232 | else: |
|
244 | ||
233 | model['format'] = 'text' |
|
|||
234 | return model |
|
245 | return model | |
235 |
|
246 | |||
236 |
|
247 | |||
@@ -255,13 +266,21 class FileContentsManager(ContentsManager): | |||||
255 | self.validate_notebook_model(model) |
|
266 | self.validate_notebook_model(model) | |
256 | return model |
|
267 | return model | |
257 |
|
268 | |||
258 |
def get |
|
269 | def get(self, path, content=True, type_=None, format=None): | |
259 | """ Takes a path for an entity and returns its model |
|
270 | """ Takes a path for an entity and returns its model | |
260 |
|
271 | |||
261 | Parameters |
|
272 | Parameters | |
262 | ---------- |
|
273 | ---------- | |
263 | path : str |
|
274 | path : str | |
264 | the API path that describes the relative path for the target |
|
275 | the API path that describes the relative path for the target | |
|
276 | content : bool | |||
|
277 | Whether to include the contents in the reply | |||
|
278 | type_ : str, optional | |||
|
279 | The requested type - 'file', 'notebook', or 'directory'. | |||
|
280 | Will raise HTTPError 400 if the content doesn't match. | |||
|
281 | format : str, optional | |||
|
282 | The requested format for file contents. 'text' or 'base64'. | |||
|
283 | Ignored if this returns a notebook or directory model. | |||
265 |
|
284 | |||
266 | Returns |
|
285 | Returns | |
267 | ------- |
|
286 | ------- | |
@@ -276,11 +295,17 class FileContentsManager(ContentsManager): | |||||
276 |
|
295 | |||
277 | os_path = self._get_os_path(path) |
|
296 | os_path = self._get_os_path(path) | |
278 | if os.path.isdir(os_path): |
|
297 | if os.path.isdir(os_path): | |
|
298 | if type_ not in (None, 'directory'): | |||
|
299 | raise web.HTTPError(400, | |||
|
300 | u'%s is a directory, not a %s' % (path, type_)) | |||
279 | model = self._dir_model(path, content=content) |
|
301 | model = self._dir_model(path, content=content) | |
280 | elif path.endswith('.ipynb'): |
|
302 | elif type_ == 'notebook' or (type_ is None and path.endswith('.ipynb')): | |
281 | model = self._notebook_model(path, content=content) |
|
303 | model = self._notebook_model(path, content=content) | |
282 | else: |
|
304 | else: | |
283 | model = self._file_model(path, content=content) |
|
305 | if type_ == 'directory': | |
|
306 | raise web.HTTPError(400, | |||
|
307 | u'%s is not a directory') | |||
|
308 | model = self._file_model(path, content=content, format=format) | |||
284 | return model |
|
309 | return model | |
285 |
|
310 | |||
286 | def _save_notebook(self, os_path, model, path=''): |
|
311 | def _save_notebook(self, os_path, model, path=''): | |
@@ -355,7 +380,7 class FileContentsManager(ContentsManager): | |||||
355 | self.validate_notebook_model(model) |
|
380 | self.validate_notebook_model(model) | |
356 | validation_message = model.get('message', None) |
|
381 | validation_message = model.get('message', None) | |
357 |
|
382 | |||
358 |
model = self.get |
|
383 | model = self.get(path, content=False) | |
359 | if validation_message: |
|
384 | if validation_message: | |
360 | model['message'] = validation_message |
|
385 | model['message'] = validation_message | |
361 | return model |
|
386 | return model | |
@@ -370,7 +395,7 class FileContentsManager(ContentsManager): | |||||
370 | new_path = model.get('path', path).strip('/') |
|
395 | new_path = model.get('path', path).strip('/') | |
371 | if path != new_path: |
|
396 | if path != new_path: | |
372 | self.rename(path, new_path) |
|
397 | self.rename(path, new_path) | |
373 |
model = self.get |
|
398 | model = self.get(new_path, content=False) | |
374 | return model |
|
399 | return model | |
375 |
|
400 | |||
376 | def delete(self, path): |
|
401 | def delete(self, path): |
@@ -58,7 +58,15 class ContentsHandler(IPythonHandler): | |||||
58 | of the files and directories it contains. |
|
58 | of the files and directories it contains. | |
59 | """ |
|
59 | """ | |
60 | path = path or '' |
|
60 | path = path or '' | |
61 | model = self.contents_manager.get_model(path=path) |
|
61 | type_ = self.get_query_argument('type', default=None) | |
|
62 | if type_ not in {None, 'directory', 'file', 'notebook'}: | |||
|
63 | raise web.HTTPError(400, u'Type %r is invalid' % type_) | |||
|
64 | ||||
|
65 | format = self.get_query_argument('format', default=None)# | |||
|
66 | if format not in {None, 'text', 'base64'}: | |||
|
67 | raise web.HTTPError(400, u'Format %r is invalid' % format) | |||
|
68 | ||||
|
69 | model = self.contents_manager.get(path=path, type_=type_, format=format) | |||
62 | if model['type'] == 'directory': |
|
70 | if model['type'] == 'directory': | |
63 | # group listing by type, then by name (case-insensitive) |
|
71 | # group listing by type, then by name (case-insensitive) | |
64 | # FIXME: sorting should be done in the frontends |
|
72 | # FIXME: sorting should be done in the frontends |
@@ -135,7 +135,7 class ContentsManager(LoggingConfigurable): | |||||
135 | """ |
|
135 | """ | |
136 | return self.file_exists(path) or self.dir_exists(path) |
|
136 | return self.file_exists(path) or self.dir_exists(path) | |
137 |
|
137 | |||
138 |
def get |
|
138 | def get(self, path, content=True, type_=None, format=None): | |
139 | """Get the model of a file or directory with or without content.""" |
|
139 | """Get the model of a file or directory with or without content.""" | |
140 | raise NotImplementedError('must be implemented in a subclass') |
|
140 | raise NotImplementedError('must be implemented in a subclass') | |
141 |
|
141 | |||
@@ -300,7 +300,7 class ContentsManager(LoggingConfigurable): | |||||
300 | from_dir = '' |
|
300 | from_dir = '' | |
301 | from_name = path |
|
301 | from_name = path | |
302 |
|
302 | |||
303 |
model = self.get |
|
303 | model = self.get(path) | |
304 | model.pop('path', None) |
|
304 | model.pop('path', None) | |
305 | model.pop('name', None) |
|
305 | model.pop('name', None) | |
306 | if model['type'] == 'directory': |
|
306 | if model['type'] == 'directory': | |
@@ -328,7 +328,7 class ContentsManager(LoggingConfigurable): | |||||
328 | path : string |
|
328 | path : string | |
329 | The path of a notebook |
|
329 | The path of a notebook | |
330 | """ |
|
330 | """ | |
331 |
model = self.get |
|
331 | model = self.get(path) | |
332 | nb = model['content'] |
|
332 | nb = model['content'] | |
333 | self.log.warn("Trusting notebook %s", path) |
|
333 | self.log.warn("Trusting notebook %s", path) | |
334 | self.notary.mark_cells(nb, True) |
|
334 | self.notary.mark_cells(nb, True) |
@@ -35,10 +35,10 class API(object): | |||||
35 | def __init__(self, base_url): |
|
35 | def __init__(self, base_url): | |
36 | self.base_url = base_url |
|
36 | self.base_url = base_url | |
37 |
|
37 | |||
38 | def _req(self, verb, path, body=None): |
|
38 | def _req(self, verb, path, body=None, params=None): | |
39 | response = requests.request(verb, |
|
39 | response = requests.request(verb, | |
40 | url_path_join(self.base_url, 'api/contents', path), |
|
40 | url_path_join(self.base_url, 'api/contents', path), | |
41 | data=body, |
|
41 | data=body, params=params, | |
42 | ) |
|
42 | ) | |
43 | response.raise_for_status() |
|
43 | response.raise_for_status() | |
44 | return response |
|
44 | return response | |
@@ -46,8 +46,13 class API(object): | |||||
46 | def list(self, path='/'): |
|
46 | def list(self, path='/'): | |
47 | return self._req('GET', path) |
|
47 | return self._req('GET', path) | |
48 |
|
48 | |||
49 | def read(self, path): |
|
49 | def read(self, path, type_=None, format=None): | |
50 | return self._req('GET', path) |
|
50 | params = {} | |
|
51 | if type_ is not None: | |||
|
52 | params['type'] = type_ | |||
|
53 | if format is not None: | |||
|
54 | params['format'] = format | |||
|
55 | return self._req('GET', path, params=params) | |||
51 |
|
56 | |||
52 | def create_untitled(self, path='/', ext='.ipynb'): |
|
57 | def create_untitled(self, path='/', ext='.ipynb'): | |
53 | body = None |
|
58 | body = None | |
@@ -243,6 +248,10 class APITest(NotebookTestBase): | |||||
243 | with assert_http_error(404): |
|
248 | with assert_http_error(404): | |
244 | self.api.read('foo/q.txt') |
|
249 | self.api.read('foo/q.txt') | |
245 |
|
250 | |||
|
251 | # Specifying format=text should fail on a non-UTF-8 file | |||
|
252 | with assert_http_error(400): | |||
|
253 | self.api.read('foo/bar/baz.blob', type_='file', format='text') | |||
|
254 | ||||
246 | def test_get_binary_file_contents(self): |
|
255 | def test_get_binary_file_contents(self): | |
247 | for d, name in self.dirs_nbs: |
|
256 | for d, name in self.dirs_nbs: | |
248 | path = url_path_join(d, name + '.blob') |
|
257 | path = url_path_join(d, name + '.blob') | |
@@ -259,6 +268,13 class APITest(NotebookTestBase): | |||||
259 | with assert_http_error(404): |
|
268 | with assert_http_error(404): | |
260 | self.api.read('foo/q.txt') |
|
269 | self.api.read('foo/q.txt') | |
261 |
|
270 | |||
|
271 | def test_get_bad_type(self): | |||
|
272 | with assert_http_error(400): | |||
|
273 | self.api.read(u'unicodΓ©', type_='file') # this is a directory | |||
|
274 | ||||
|
275 | with assert_http_error(400): | |||
|
276 | self.api.read(u'unicodΓ©/innonascii.ipynb', type_='directory') | |||
|
277 | ||||
262 | def _check_created(self, resp, path, type='notebook'): |
|
278 | def _check_created(self, resp, path, type='notebook'): | |
263 | self.assertEqual(resp.status_code, 201) |
|
279 | self.assertEqual(resp.status_code, 201) | |
264 | location_header = py3compat.str_to_unicode(resp.headers['Location']) |
|
280 | location_header = py3compat.str_to_unicode(resp.headers['Location']) |
@@ -105,7 +105,7 class TestContentsManager(TestCase): | |||||
105 | name = model['name'] |
|
105 | name = model['name'] | |
106 | path = model['path'] |
|
106 | path = model['path'] | |
107 |
|
107 | |||
108 |
full_model = cm.get |
|
108 | full_model = cm.get(path) | |
109 | nb = full_model['content'] |
|
109 | nb = full_model['content'] | |
110 | self.add_code_cell(nb) |
|
110 | self.add_code_cell(nb) | |
111 |
|
111 | |||
@@ -152,24 +152,41 class TestContentsManager(TestCase): | |||||
152 | path = model['path'] |
|
152 | path = model['path'] | |
153 |
|
153 | |||
154 | # Check that we 'get' on the notebook we just created |
|
154 | # Check that we 'get' on the notebook we just created | |
155 |
model2 = cm.get |
|
155 | model2 = cm.get(path) | |
156 | assert isinstance(model2, dict) |
|
156 | assert isinstance(model2, dict) | |
157 | self.assertIn('name', model2) |
|
157 | self.assertIn('name', model2) | |
158 | self.assertIn('path', model2) |
|
158 | self.assertIn('path', model2) | |
159 | self.assertEqual(model['name'], name) |
|
159 | self.assertEqual(model['name'], name) | |
160 | self.assertEqual(model['path'], path) |
|
160 | self.assertEqual(model['path'], path) | |
161 |
|
161 | |||
|
162 | nb_as_file = cm.get(path, content=True, type_='file') | |||
|
163 | self.assertEqual(nb_as_file['path'], path) | |||
|
164 | self.assertEqual(nb_as_file['type'], 'file') | |||
|
165 | self.assertEqual(nb_as_file['format'], 'text') | |||
|
166 | self.assertNotIsInstance(nb_as_file['content'], dict) | |||
|
167 | ||||
|
168 | nb_as_bin_file = cm.get(path, content=True, type_='file', format='base64') | |||
|
169 | self.assertEqual(nb_as_bin_file['format'], 'base64') | |||
|
170 | ||||
162 | # Test in sub-directory |
|
171 | # Test in sub-directory | |
163 | sub_dir = '/foo/' |
|
172 | sub_dir = '/foo/' | |
164 | self.make_dir(cm.root_dir, 'foo') |
|
173 | self.make_dir(cm.root_dir, 'foo') | |
165 | model = cm.new_untitled(path=sub_dir, ext='.ipynb') |
|
174 | model = cm.new_untitled(path=sub_dir, ext='.ipynb') | |
166 |
model2 = cm.get |
|
175 | model2 = cm.get(sub_dir + name) | |
167 | assert isinstance(model2, dict) |
|
176 | assert isinstance(model2, dict) | |
168 | self.assertIn('name', model2) |
|
177 | self.assertIn('name', model2) | |
169 | self.assertIn('path', model2) |
|
178 | self.assertIn('path', model2) | |
170 | self.assertIn('content', model2) |
|
179 | self.assertIn('content', model2) | |
171 | self.assertEqual(model2['name'], 'Untitled0.ipynb') |
|
180 | self.assertEqual(model2['name'], 'Untitled0.ipynb') | |
172 | self.assertEqual(model2['path'], '{0}/{1}'.format(sub_dir.strip('/'), name)) |
|
181 | self.assertEqual(model2['path'], '{0}/{1}'.format(sub_dir.strip('/'), name)) | |
|
182 | ||||
|
183 | # Test getting directory model | |||
|
184 | dirmodel = cm.get('foo') | |||
|
185 | self.assertEqual(dirmodel['type'], 'directory') | |||
|
186 | ||||
|
187 | with self.assertRaises(HTTPError): | |||
|
188 | cm.get('foo', type_='file') | |||
|
189 | ||||
173 |
|
190 | |||
174 | @dec.skip_win32 |
|
191 | @dec.skip_win32 | |
175 | def test_bad_symlink(self): |
|
192 | def test_bad_symlink(self): | |
@@ -181,7 +198,7 class TestContentsManager(TestCase): | |||||
181 |
|
198 | |||
182 | # create a broken symlink |
|
199 | # create a broken symlink | |
183 | os.symlink("target", os.path.join(os_path, "bad symlink")) |
|
200 | os.symlink("target", os.path.join(os_path, "bad symlink")) | |
184 |
model = cm.get |
|
201 | model = cm.get(path) | |
185 | self.assertEqual(model['content'], [file_model]) |
|
202 | self.assertEqual(model['content'], [file_model]) | |
186 |
|
203 | |||
187 | @dec.skip_win32 |
|
204 | @dec.skip_win32 | |
@@ -196,8 +213,8 class TestContentsManager(TestCase): | |||||
196 |
|
213 | |||
197 | # create a good symlink |
|
214 | # create a good symlink | |
198 | os.symlink(file_model['name'], os.path.join(os_path, name)) |
|
215 | os.symlink(file_model['name'], os.path.join(os_path, name)) | |
199 |
symlink_model = cm.get |
|
216 | symlink_model = cm.get(path, content=False) | |
200 |
dir_model = cm.get |
|
217 | dir_model = cm.get(parent) | |
201 | self.assertEqual( |
|
218 | self.assertEqual( | |
202 | sorted(dir_model['content'], key=lambda x: x['name']), |
|
219 | sorted(dir_model['content'], key=lambda x: x['name']), | |
203 | [symlink_model, file_model], |
|
220 | [symlink_model, file_model], | |
@@ -219,7 +236,7 class TestContentsManager(TestCase): | |||||
219 | self.assertEqual(model['name'], 'test.ipynb') |
|
236 | self.assertEqual(model['name'], 'test.ipynb') | |
220 |
|
237 | |||
221 | # Make sure the old name is gone |
|
238 | # Make sure the old name is gone | |
222 |
self.assertRaises(HTTPError, cm.get |
|
239 | self.assertRaises(HTTPError, cm.get, path) | |
223 |
|
240 | |||
224 | # Test in sub-directory |
|
241 | # Test in sub-directory | |
225 | # Create a directory and notebook in that directory |
|
242 | # Create a directory and notebook in that directory | |
@@ -240,7 +257,7 class TestContentsManager(TestCase): | |||||
240 | self.assertEqual(model['path'], new_path) |
|
257 | self.assertEqual(model['path'], new_path) | |
241 |
|
258 | |||
242 | # Make sure the old name is gone |
|
259 | # Make sure the old name is gone | |
243 |
self.assertRaises(HTTPError, cm.get |
|
260 | self.assertRaises(HTTPError, cm.get, path) | |
244 |
|
261 | |||
245 | def test_save(self): |
|
262 | def test_save(self): | |
246 | cm = self.contents_manager |
|
263 | cm = self.contents_manager | |
@@ -250,7 +267,7 class TestContentsManager(TestCase): | |||||
250 | path = model['path'] |
|
267 | path = model['path'] | |
251 |
|
268 | |||
252 | # Get the model with 'content' |
|
269 | # Get the model with 'content' | |
253 |
full_model = cm.get |
|
270 | full_model = cm.get(path) | |
254 |
|
271 | |||
255 | # Save the notebook |
|
272 | # Save the notebook | |
256 | model = cm.save(full_model, path) |
|
273 | model = cm.save(full_model, path) | |
@@ -267,7 +284,7 class TestContentsManager(TestCase): | |||||
267 | model = cm.new_untitled(path=sub_dir, type='notebook') |
|
284 | model = cm.new_untitled(path=sub_dir, type='notebook') | |
268 | name = model['name'] |
|
285 | name = model['name'] | |
269 | path = model['path'] |
|
286 | path = model['path'] | |
270 |
model = cm.get |
|
287 | model = cm.get(path) | |
271 |
|
288 | |||
272 | # Change the name in the model for rename |
|
289 | # Change the name in the model for rename | |
273 | model = cm.save(model, path) |
|
290 | model = cm.save(model, path) | |
@@ -286,7 +303,7 class TestContentsManager(TestCase): | |||||
286 | cm.delete(path) |
|
303 | cm.delete(path) | |
287 |
|
304 | |||
288 | # Check that a 'get' on the deleted notebook raises and error |
|
305 | # Check that a 'get' on the deleted notebook raises and error | |
289 |
self.assertRaises(HTTPError, cm.get |
|
306 | self.assertRaises(HTTPError, cm.get, path) | |
290 |
|
307 | |||
291 | def test_copy(self): |
|
308 | def test_copy(self): | |
292 | cm = self.contents_manager |
|
309 | cm = self.contents_manager | |
@@ -309,12 +326,12 class TestContentsManager(TestCase): | |||||
309 | cm = self.contents_manager |
|
326 | cm = self.contents_manager | |
310 | nb, name, path = self.new_notebook() |
|
327 | nb, name, path = self.new_notebook() | |
311 |
|
328 | |||
312 |
untrusted = cm.get |
|
329 | untrusted = cm.get(path)['content'] | |
313 | assert not cm.notary.check_cells(untrusted) |
|
330 | assert not cm.notary.check_cells(untrusted) | |
314 |
|
331 | |||
315 | # print(untrusted) |
|
332 | # print(untrusted) | |
316 | cm.trust_notebook(path) |
|
333 | cm.trust_notebook(path) | |
317 |
trusted = cm.get |
|
334 | trusted = cm.get(path)['content'] | |
318 | # print(trusted) |
|
335 | # print(trusted) | |
319 | assert cm.notary.check_cells(trusted) |
|
336 | assert cm.notary.check_cells(trusted) | |
320 |
|
337 | |||
@@ -328,7 +345,7 class TestContentsManager(TestCase): | |||||
328 | assert not cell.metadata.trusted |
|
345 | assert not cell.metadata.trusted | |
329 |
|
346 | |||
330 | cm.trust_notebook(path) |
|
347 | cm.trust_notebook(path) | |
331 |
nb = cm.get |
|
348 | nb = cm.get(path)['content'] | |
332 | for cell in nb.cells: |
|
349 | for cell in nb.cells: | |
333 | if cell.cell_type == 'code': |
|
350 | if cell.cell_type == 'code': | |
334 | assert cell.metadata.trusted |
|
351 | assert cell.metadata.trusted | |
@@ -342,7 +359,7 class TestContentsManager(TestCase): | |||||
342 | assert not cm.notary.check_signature(nb) |
|
359 | assert not cm.notary.check_signature(nb) | |
343 |
|
360 | |||
344 | cm.trust_notebook(path) |
|
361 | cm.trust_notebook(path) | |
345 |
nb = cm.get |
|
362 | nb = cm.get(path)['content'] | |
346 | cm.mark_trusted_cells(nb, path) |
|
363 | cm.mark_trusted_cells(nb, path) | |
347 | cm.check_and_sign(nb, path) |
|
364 | cm.check_and_sign(nb, path) | |
348 | assert cm.notary.check_signature(nb) |
|
365 | assert cm.notary.check_signature(nb) |
@@ -110,11 +110,8 define([ | |||||
110 | }); |
|
110 | }); | |
111 | }); |
|
111 | }); | |
112 | this.element.find('#open_notebook').click(function () { |
|
112 | this.element.find('#open_notebook').click(function () { | |
113 | window.open(utils.url_join_encode( |
|
113 | var parent = utils.url_path_split(that.notebook.notebook_path)[0]; | |
114 | that.notebook.base_url, |
|
114 | window.open(utils.url_join_encode(that.base_url, 'tree', parent)); | |
115 | 'tree', |
|
|||
116 | that.notebook.notebook_path |
|
|||
117 | )); |
|
|||
118 | }); |
|
115 | }); | |
119 | this.element.find('#copy_notebook').click(function () { |
|
116 | this.element.find('#copy_notebook').click(function () { | |
120 | that.notebook.copy_notebook(); |
|
117 | that.notebook.copy_notebook(); |
@@ -2104,6 +2104,7 define([ | |||||
2104 | this.notebook_name = utils.url_path_split(this.notebook_path)[1]; |
|
2104 | this.notebook_name = utils.url_path_split(this.notebook_path)[1]; | |
2105 | this.events.trigger('notebook_loading.Notebook'); |
|
2105 | this.events.trigger('notebook_loading.Notebook'); | |
2106 | this.contents.get(notebook_path, { |
|
2106 | this.contents.get(notebook_path, { | |
|
2107 | type: 'notebook', | |||
2107 | success: $.proxy(this.load_notebook_success, this), |
|
2108 | success: $.proxy(this.load_notebook_success, this), | |
2108 | error: $.proxy(this.load_notebook_error, this) |
|
2109 | error: $.proxy(this.load_notebook_error, this) | |
2109 | }); |
|
2110 | }); |
@@ -87,7 +87,10 define([ | |||||
87 | error : this.create_basic_error_handler(options.error) |
|
87 | error : this.create_basic_error_handler(options.error) | |
88 | }; |
|
88 | }; | |
89 | var url = this.api_url(path); |
|
89 | var url = this.api_url(path); | |
90 | $.ajax(url, settings); |
|
90 | params = {}; | |
|
91 | if (options.type) { params.type = options.type; } | |||
|
92 | if (options.format) { params.format = options.format; } | |||
|
93 | $.ajax(url + '?' + $.param(params), settings); | |||
91 | }; |
|
94 | }; | |
92 |
|
95 | |||
93 |
|
96 | |||
@@ -241,20 +244,11 define([ | |||||
241 | * last_modified: last modified dat |
|
244 | * last_modified: last modified dat | |
242 | * @method list_notebooks |
|
245 | * @method list_notebooks | |
243 | * @param {String} path The path to list notebooks in |
|
246 | * @param {String} path The path to list notebooks in | |
244 | * @param {Function} load_callback called with list of notebooks on success |
|
247 | * @param {Object} options including success and error callbacks | |
245 | * @param {Function} error called with ajax results on error |
|
|||
246 | */ |
|
248 | */ | |
247 | Contents.prototype.list_contents = function(path, options) { |
|
249 | Contents.prototype.list_contents = function(path, options) { | |
248 | var settings = { |
|
250 | options.type = 'directory'; | |
249 | processData : false, |
|
251 | this.get(path, options); | |
250 | cache : false, |
|
|||
251 | type : "GET", |
|
|||
252 | dataType : "json", |
|
|||
253 | success : options.success, |
|
|||
254 | error : this.create_basic_error_handler(options.error) |
|
|||
255 | }; |
|
|||
256 |
|
||||
257 | $.ajax(this.api_url(path), settings); |
|
|||
258 | }; |
|
252 | }; | |
259 |
|
253 | |||
260 |
|
254 |
General Comments 0
You need to be logged in to leave comments.
Login now