##// END OF EJS Templates
forbid serving hidden files from `/files`
forbid serving hidden files from `/files`

File last commit:

r13141:79553b25
r13174:6298e4ac
Show More
test_notebooks_api.py
312 lines | 11.9 KiB | text/x-python | PythonLexer
MinRK
unicode normalization in test_notebooks_api
r13091 # coding: utf-8
Zachary Sailer
add tests for session api
r13044 """Test the notebooks webservice API."""
Zachary Sailer
Added notebooks API tests.
r13041
Thomas Kluyver
Improve tests for notebook REST API
r13083 import io
MinRK
copy_from in json, not in url param
r13137 import json
Zachary Sailer
Added notebooks API tests.
r13041 import os
Thomas Kluyver
Improve tests for notebook REST API
r13083 import shutil
MinRK
unicode normalization in test_notebooks_api
r13091 from unicodedata import normalize
Thomas Kluyver
Improve tests for notebook REST API
r13083 pjoin = os.path.join
Zachary Sailer
Added notebooks API tests.
r13041 import requests
MinRK
escape URLs in Location headers
r13132 from IPython.html.utils import url_path_join, url_escape
Thomas Kluyver
Add failing test for listing nonexistant directory
r13099 from IPython.html.tests.launchnotebook import NotebookTestBase, assert_http_error
MinRK
test upload of v2 notebooks
r13141 from IPython.nbformat import current
Thomas Kluyver
Add test for saving notebook via REST API
r13085 from IPython.nbformat.current import (new_notebook, write, read, new_worksheet,
new_heading_cell, to_notebook_json)
MinRK
test upload of v2 notebooks
r13141 from IPython.nbformat import v2
MinRK
update notebook api tests...
r13130 from IPython.utils import py3compat
Thomas Kluyver
Improve tests for notebook REST API
r13083 from IPython.utils.data import uniq_stable
MinRK
update notebook api tests...
r13130
Thomas Kluyver
Improve tests for notebook REST API
r13083 class NBAPI(object):
"""Wrapper for notebook API calls."""
def __init__(self, base_url):
self.base_url = base_url
MinRK
copy_from in json, not in url param
r13137 def _req(self, verb, path, body=None):
Thomas Kluyver
Improve tests for notebook REST API
r13083 response = requests.request(verb,
MinRK
update notebook api tests...
r13130 url_path_join(self.base_url, 'api/notebooks', path),
data=body,
)
Thomas Kluyver
Improve tests for notebook REST API
r13083 response.raise_for_status()
return response
def list(self, path='/'):
return self._req('GET', path)
def read(self, name, path='/'):
return self._req('GET', url_path_join(path, name))
def create_untitled(self, path='/'):
return self._req('POST', path)
MinRK
update notebook api tests...
r13130 def upload_untitled(self, body, path='/'):
return self._req('POST', path, body)
def copy_untitled(self, copy_from, path='/'):
MinRK
copy_from in json, not in url param
r13137 body = json.dumps({'copy_from':copy_from})
return self._req('POST', path, body)
MinRK
update notebook api tests...
r13130
def create(self, name, path='/'):
return self._req('PUT', url_path_join(path, name))
Thomas Kluyver
Add test for REST API uploading notebook
r13084 def upload(self, name, body, path='/'):
MinRK
update notebook api tests...
r13130 return self._req('PUT', url_path_join(path, name), body)
Thomas Kluyver
Add test for REST API uploading notebook
r13084
MinRK
update notebook api tests...
r13130 def copy(self, copy_from, copy_to, path='/'):
MinRK
copy_from in json, not in url param
r13137 body = json.dumps({'copy_from':copy_from})
return self._req('PUT', url_path_join(path, copy_to), body)
Thomas Kluyver
Add test for copying notebook through REST API
r13086
Thomas Kluyver
Add test for saving notebook via REST API
r13085 def save(self, name, body, path='/'):
return self._req('PUT', url_path_join(path, name), body)
Thomas Kluyver
Improve tests for notebook REST API
r13083 def delete(self, name, path='/'):
return self._req('DELETE', url_path_join(path, name))
def rename(self, name, path, new_name):
MinRK
don't use jsonapi in test_notebook_api
r13138 body = json.dumps({'name': new_name})
Thomas Kluyver
Improve tests for notebook REST API
r13083 return self._req('PATCH', url_path_join(path, name), body)
Zachary Sailer
Added notebooks API tests.
r13041
Thomas Kluyver
Test notebook checkpoint APIs
r13109 def get_checkpoints(self, name, path):
return self._req('GET', url_path_join(path, name, 'checkpoints'))
def new_checkpoint(self, name, path):
return self._req('POST', url_path_join(path, name, 'checkpoints'))
def restore_checkpoint(self, name, path, checkpoint_id):
return self._req('POST', url_path_join(path, name, 'checkpoints', checkpoint_id))
def delete_checkpoint(self, name, path, checkpoint_id):
return self._req('DELETE', url_path_join(path, name, 'checkpoints', checkpoint_id))
Zachary Sailer
Added notebooks API tests.
r13041 class APITest(NotebookTestBase):
"""Test the kernels web service API"""
Thomas Kluyver
Improve tests for notebook REST API
r13083 dirs_nbs = [('', 'inroot'),
('Directory with spaces in', 'inspace'),
(u'unicodé', 'innonascii'),
('foo', 'a'),
('foo', 'b'),
('foo', 'name with spaces'),
('foo', u'unicodé'),
('foo/bar', 'baz'),
MinRK
update notebook api tests...
r13130 (u'å b', u'ç d')
Thomas Kluyver
Improve tests for notebook REST API
r13083 ]
dirs = uniq_stable([d for (d,n) in dirs_nbs])
del dirs[0] # remove ''
def setUp(self):
nbdir = self.notebook_dir.name
Thomas Kluyver
Add test for REST API uploading notebook
r13084
Thomas Kluyver
Improve tests for notebook REST API
r13083 for d in self.dirs:
MinRK
update notebook api tests...
r13130 if not os.path.isdir(pjoin(nbdir, d)):
os.mkdir(pjoin(nbdir, d))
Thomas Kluyver
Improve tests for notebook REST API
r13083
for d, name in self.dirs_nbs:
with io.open(pjoin(nbdir, d, '%s.ipynb' % name), 'w') as f:
nb = new_notebook(name=name)
write(nb, f, format='ipynb')
self.nb_api = NBAPI(self.base_url())
def tearDown(self):
nbdir = self.notebook_dir.name
MinRK
update notebook api tests...
r13130 for dname in ['foo', 'Directory with spaces in', u'unicodé', u'å b']:
Thomas Kluyver
Improve tests for notebook REST API
r13083 shutil.rmtree(pjoin(nbdir, dname), ignore_errors=True)
if os.path.isfile(pjoin(nbdir, 'inroot.ipynb')):
os.unlink(pjoin(nbdir, 'inroot.ipynb'))
def test_list_notebooks(self):
nbs = self.nb_api.list().json()
self.assertEqual(len(nbs), 1)
self.assertEqual(nbs[0]['name'], 'inroot.ipynb')
nbs = self.nb_api.list('/Directory with spaces in/').json()
self.assertEqual(len(nbs), 1)
self.assertEqual(nbs[0]['name'], 'inspace.ipynb')
nbs = self.nb_api.list(u'/unicodé/').json()
self.assertEqual(len(nbs), 1)
self.assertEqual(nbs[0]['name'], 'innonascii.ipynb')
MinRK
update notebook api tests...
r13130 self.assertEqual(nbs[0]['path'], u'unicodé')
Thomas Kluyver
Improve tests for notebook REST API
r13083
nbs = self.nb_api.list('/foo/bar/').json()
self.assertEqual(len(nbs), 1)
self.assertEqual(nbs[0]['name'], 'baz.ipynb')
MinRK
update notebook api tests...
r13130 self.assertEqual(nbs[0]['path'], 'foo/bar')
Thomas Kluyver
Improve tests for notebook REST API
r13083
nbs = self.nb_api.list('foo').json()
self.assertEqual(len(nbs), 4)
MinRK
unicode normalization in test_notebooks_api
r13091 nbnames = { normalize('NFC', n['name']) for n in nbs }
expected = [ u'a.ipynb', u'b.ipynb', u'name with spaces.ipynb', u'unicodé.ipynb']
expected = { normalize('NFC', name) for name in expected }
self.assertEqual(nbnames, expected)
Thomas Kluyver
Improve tests for notebook REST API
r13083
Thomas Kluyver
Add failing test for listing nonexistant directory
r13099 def test_list_nonexistant_dir(self):
with assert_http_error(404):
self.nb_api.list('nonexistant')
Thomas Kluyver
Add test for and fix REST save with rename
r13087
Thomas Kluyver
Improve tests for notebook REST API
r13083 def test_get_contents(self):
for d, name in self.dirs_nbs:
nb = self.nb_api.read('%s.ipynb' % name, d+'/').json()
MinRK
update notebook api tests...
r13130 self.assertEqual(nb['name'], u'%s.ipynb' % name)
Thomas Kluyver
Improve tests for notebook REST API
r13083 self.assertIn('content', nb)
self.assertIn('metadata', nb['content'])
self.assertIsInstance(nb['content']['metadata'], dict)
# Name that doesn't exist - should be a 404
Thomas Kluyver
Add failing test for listing nonexistant directory
r13099 with assert_http_error(404):
self.nb_api.read('q.ipynb', 'foo')
Thomas Kluyver
Improve tests for notebook REST API
r13083
def _check_nb_created(self, resp, name, path):
Thomas Kluyver
Add test for REST API uploading notebook
r13084 self.assertEqual(resp.status_code, 201)
MinRK
update notebook api tests...
r13130 location_header = py3compat.str_to_unicode(resp.headers['Location'])
MinRK
escape URLs in Location headers
r13132 self.assertEqual(location_header, url_escape(url_path_join(u'/api/notebooks', path, name)))
Thomas Kluyver
Improve tests for notebook REST API
r13083 self.assertEqual(resp.json()['name'], name)
assert os.path.isfile(pjoin(self.notebook_dir.name, path, name))
def test_create_untitled(self):
MinRK
update notebook api tests...
r13130 resp = self.nb_api.create_untitled(path=u'Ã¥ b')
self._check_nb_created(resp, 'Untitled0.ipynb', u'Ã¥ b')
Thomas Kluyver
Improve tests for notebook REST API
r13083
# Second time
MinRK
update notebook api tests...
r13130 resp = self.nb_api.create_untitled(path=u'Ã¥ b')
self._check_nb_created(resp, 'Untitled1.ipynb', u'Ã¥ b')
Thomas Kluyver
Improve tests for notebook REST API
r13083
# And two directories down
resp = self.nb_api.create_untitled(path='foo/bar')
self._check_nb_created(resp, 'Untitled0.ipynb', pjoin('foo', 'bar'))
MinRK
update notebook api tests...
r13130 def test_upload_untitled(self):
Thomas Kluyver
Add test for REST API uploading notebook
r13084 nb = new_notebook(name='Upload test')
Thomas Kluyver
Add test for saving notebook via REST API
r13085 nbmodel = {'content': nb}
MinRK
update notebook api tests...
r13130 resp = self.nb_api.upload_untitled(path=u'Ã¥ b',
MinRK
don't use jsonapi in test_notebook_api
r13138 body=json.dumps(nbmodel))
MinRK
escape URLs in Location headers
r13132 self._check_nb_created(resp, 'Untitled0.ipynb', u'Ã¥ b')
MinRK
update notebook api tests...
r13130
def test_upload(self):
nb = new_notebook(name=u'ignored')
nbmodel = {'content': nb}
resp = self.nb_api.upload(u'Upload tést.ipynb', path=u'å b',
MinRK
don't use jsonapi in test_notebook_api
r13138 body=json.dumps(nbmodel))
MinRK
update notebook api tests...
r13130 self._check_nb_created(resp, u'Upload tést.ipynb', u'å b')
MinRK
test upload of v2 notebooks
r13141 def test_upload_v2(self):
nb = v2.new_notebook()
ws = v2.new_worksheet()
nb.worksheets.append(ws)
ws.cells.append(v2.new_code_cell(input='print("hi")'))
nbmodel = {'content': nb}
resp = self.nb_api.upload(u'Upload tést.ipynb', path=u'å b',
body=json.dumps(nbmodel))
self._check_nb_created(resp, u'Upload tést.ipynb', u'å b')
resp = self.nb_api.read(u'Upload tést.ipynb', u'å b')
data = resp.json()
self.assertEqual(data['content']['nbformat'], current.nbformat)
self.assertEqual(data['content']['orig_nbformat'], 2)
MinRK
update notebook api tests...
r13130 def test_copy_untitled(self):
resp = self.nb_api.copy_untitled(u'ç d.ipynb', path=u'å b')
self._check_nb_created(resp, u'ç d-Copy0.ipynb', u'å b')
Thomas Kluyver
Add test for REST API uploading notebook
r13084
Thomas Kluyver
Add test for copying notebook through REST API
r13086 def test_copy(self):
MinRK
update notebook api tests...
r13130 resp = self.nb_api.copy(u'ç d.ipynb', u'cøpy.ipynb', path=u'å b')
self._check_nb_created(resp, u'cøpy.ipynb', u'å b')
Thomas Kluyver
Add test for copying notebook through REST API
r13086
Thomas Kluyver
Improve tests for notebook REST API
r13083 def test_delete(self):
for d, name in self.dirs_nbs:
resp = self.nb_api.delete('%s.ipynb' % name, d)
self.assertEqual(resp.status_code, 204)
for d in self.dirs + ['/']:
nbs = self.nb_api.list(d).json()
self.assertEqual(len(nbs), 0)
def test_rename(self):
resp = self.nb_api.rename('a.ipynb', 'foo', 'z.ipynb')
Thomas Kluyver
Check Location header from renaming notebook
r13089 self.assertEqual(resp.headers['Location'].split('/')[-1], 'z.ipynb')
Thomas Kluyver
Improve tests for notebook REST API
r13083 self.assertEqual(resp.json()['name'], 'z.ipynb')
assert os.path.isfile(pjoin(self.notebook_dir.name, 'foo', 'z.ipynb'))
nbs = self.nb_api.list('foo').json()
nbnames = set(n['name'] for n in nbs)
self.assertIn('z.ipynb', nbnames)
self.assertNotIn('a.ipynb', nbnames)
Thomas Kluyver
Add test for saving notebook via REST API
r13085
def test_save(self):
resp = self.nb_api.read('a.ipynb', 'foo')
MinRK
don't use jsonapi in test_notebook_api
r13138 nbcontent = json.loads(resp.text)['content']
Thomas Kluyver
Add test for saving notebook via REST API
r13085 nb = to_notebook_json(nbcontent)
ws = new_worksheet()
nb.worksheets = [ws]
Thomas Kluyver
Add some unicode testing for saving notebooks
r13111 ws.cells.append(new_heading_cell(u'Created by test ³'))
Thomas Kluyver
Add test for saving notebook via REST API
r13085
nbmodel= {'name': 'a.ipynb', 'path':'foo', 'content': nb}
MinRK
don't use jsonapi in test_notebook_api
r13138 resp = self.nb_api.save('a.ipynb', path='foo', body=json.dumps(nbmodel))
Thomas Kluyver
Add test for saving notebook via REST API
r13085
nbfile = pjoin(self.notebook_dir.name, 'foo', 'a.ipynb')
Thomas Kluyver
Add some unicode testing for saving notebooks
r13111 with io.open(nbfile, 'r', encoding='utf-8') as f:
Thomas Kluyver
Add test for saving notebook via REST API
r13085 newnb = read(f, format='ipynb')
self.assertEqual(newnb.worksheets[0].cells[0].source,
Thomas Kluyver
Add some unicode testing for saving notebooks
r13111 u'Created by test ³')
nbcontent = self.nb_api.read('a.ipynb', 'foo').json()['content']
newnb = to_notebook_json(nbcontent)
self.assertEqual(newnb.worksheets[0].cells[0].source,
u'Created by test ³')
Thomas Kluyver
Add test for and fix REST save with rename
r13087
# Save and rename
nbmodel= {'name': 'a2.ipynb', 'path':'foo/bar', 'content': nb}
MinRK
don't use jsonapi in test_notebook_api
r13138 resp = self.nb_api.save('a.ipynb', path='foo', body=json.dumps(nbmodel))
Thomas Kluyver
Add test for and fix REST save with rename
r13087 saved = resp.json()
self.assertEqual(saved['name'], 'a2.ipynb')
self.assertEqual(saved['path'], 'foo/bar')
assert os.path.isfile(pjoin(self.notebook_dir.name,'foo','bar','a2.ipynb'))
assert not os.path.isfile(pjoin(self.notebook_dir.name, 'foo', 'a.ipynb'))
Thomas Kluyver
Add failing test for listing nonexistant directory
r13099 with assert_http_error(404):
Thomas Kluyver
Test notebook checkpoint APIs
r13109 self.nb_api.read('a.ipynb', 'foo')
def test_checkpoints(self):
resp = self.nb_api.read('a.ipynb', 'foo')
r = self.nb_api.new_checkpoint('a.ipynb', 'foo')
self.assertEqual(r.status_code, 201)
cp1 = r.json()
MinRK
use 'id' for checkpoint ID key...
r13122 self.assertEqual(set(cp1), {'id', 'last_modified'})
self.assertEqual(r.headers['Location'].split('/')[-1], cp1['id'])
Thomas Kluyver
Test notebook checkpoint APIs
r13109
# Modify it
MinRK
don't use jsonapi in test_notebook_api
r13138 nbcontent = json.loads(resp.text)['content']
Thomas Kluyver
Test notebook checkpoint APIs
r13109 nb = to_notebook_json(nbcontent)
ws = new_worksheet()
nb.worksheets = [ws]
hcell = new_heading_cell('Created by test')
ws.cells.append(hcell)
# Save
nbmodel= {'name': 'a.ipynb', 'path':'foo', 'content': nb}
MinRK
don't use jsonapi in test_notebook_api
r13138 resp = self.nb_api.save('a.ipynb', path='foo', body=json.dumps(nbmodel))
Thomas Kluyver
Test notebook checkpoint APIs
r13109
# List checkpoints
cps = self.nb_api.get_checkpoints('a.ipynb', 'foo').json()
self.assertEqual(cps, [cp1])
nbcontent = self.nb_api.read('a.ipynb', 'foo').json()['content']
nb = to_notebook_json(nbcontent)
self.assertEqual(nb.worksheets[0].cells[0].source, 'Created by test')
# Restore cp1
MinRK
use 'id' for checkpoint ID key...
r13122 r = self.nb_api.restore_checkpoint('a.ipynb', 'foo', cp1['id'])
Thomas Kluyver
Test notebook checkpoint APIs
r13109 self.assertEqual(r.status_code, 204)
nbcontent = self.nb_api.read('a.ipynb', 'foo').json()['content']
nb = to_notebook_json(nbcontent)
self.assertEqual(nb.worksheets, [])
# Delete cp1
MinRK
use 'id' for checkpoint ID key...
r13122 r = self.nb_api.delete_checkpoint('a.ipynb', 'foo', cp1['id'])
Thomas Kluyver
Test notebook checkpoint APIs
r13109 self.assertEqual(r.status_code, 204)
cps = self.nb_api.get_checkpoints('a.ipynb', 'foo').json()
self.assertEqual(cps, [])
MinRK
test upload of v2 notebooks
r13141