##// END OF EJS Templates
review fixes on tests, add extra kernel api test
Zachary Sailer -
Show More
@@ -218,10 +218,6 b' class IPythonHandler(AuthenticatedHandler):'
218 return self.settings['session_manager']
218 return self.settings['session_manager']
219
219
220 @property
220 @property
221 def content_manager(self):
222 return self.settings['content_manager']
223
224 @property
225 def project(self):
221 def project(self):
226 return self.notebook_manager.notebook_dir
222 return self.notebook_manager.notebook_dir
227
223
@@ -16,11 +16,15 b' class KernelAPITest(NotebookTestBase):'
16 def base_url(self):
16 def base_url(self):
17 return super(KernelAPITest,self).base_url() + 'api/kernels'
17 return super(KernelAPITest,self).base_url() + 'api/kernels'
18
18
19 def mkkernel(self):
20 r = requests.post(self.base_url())
21 return r.json()
22
19 def test_no_kernels(self):
23 def test_no_kernels(self):
20 """Make sure there are no kernels running at the start"""
24 """Make sure there are no kernels running at the start"""
21 url = self.base_url()
25 url = self.base_url()
22 r = requests.get(url)
26 r = requests.get(url)
23 assert r.json() == []
27 self.assertEqual(r.json(), [])
24
28
25 def test_main_kernel_handler(self):
29 def test_main_kernel_handler(self):
26 # POST request
30 # POST request
@@ -33,4 +37,17 b' class KernelAPITest(NotebookTestBase):'
33 assert isinstance(r.json(), list)
37 assert isinstance(r.json(), list)
34 self.assertEqual(r.json()[0], data['id'])
38 self.assertEqual(r.json()[0], data['id'])
35
39
36 No newline at end of file
40 def test_kernel_handler(self):
41 # GET kernel with id
42 data = self.mkkernel()
43 url = self.base_url() +'/' + data['id']
44 r = requests.get(url)
45 assert isinstance(r.json(), dict)
46 self.assertIn('id', r.json())
47 self.assertEqual(r.json()['id'], data['id'])
48
49 # DELETE kernel with id
50 r = requests.delete(url)
51 self.assertEqual(r.status_code, 204)
52 r = requests.get(self.base_url())
53 self.assertEqual(r.json(), []) No newline at end of file
@@ -91,7 +91,7 b' class FileNotebookManager(NotebookManager):'
91 notebooks.append(model)
91 notebooks.append(model)
92 return notebooks
92 return notebooks
93
93
94 def change_notebook(self, data, notebook_name, notebook_path='/'):
94 def update_notebook(self, data, notebook_name, notebook_path='/'):
95 """Changes notebook"""
95 """Changes notebook"""
96 changes = data.keys()
96 changes = data.keys()
97 for change in changes:
97 for change in changes:
@@ -16,127 +16,117 b' Authors:'
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 from tornado import web
19 import json
20
20
21 from zmq.utils import jsonapi
21 from tornado import web
22
22
23 from ...utils import url_path_join
23 from IPython.utils.jsonutil import date_default
24 from IPython.utils.jsonutil import date_default
24
25
25 from ...base.handlers import IPythonHandler
26 from ...base.handlers import IPythonHandler, json_errors
26
27
27 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
28 # Notebook web service handlers
29 # Notebook web service handlers
29 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
30
31
31
32
32 class NotebookRootHandler(IPythonHandler):
33
34 @web.authenticated
35 def get(self):
36 """get returns a list of notebooks from the location
37 where the server was started."""
38 nbm = self.notebook_manager
39 notebooks = nbm.list_notebooks("/")
40 self.finish(jsonapi.dumps(notebooks))
41
42 @web.authenticated
43 def post(self):
44 """post creates a notebooks in the directory where the
45 server was started"""
46 nbm = self.notebook_manager
47 self.log.info(nbm.notebook_dir)
48 body = self.request.body.strip()
49 format = self.get_argument('format', default='json')
50 name = self.get_argument('name', default=None)
51 if body:
52 fname = nbm.save_new_notebook(body, notebook_path='/', name=name, format=format)
53 else:
54 fname = nbm.new_notebook(notebook_path='/')
55 self.set_header('Location', nbm.notebook_dir + fname)
56 model = nbm.notebook_model(fname)
57 self.set_header('Location', '{0}api/notebooks/{1}'.format(self.base_project_url, fname))
58 self.finish(jsonapi.dumps(model))
59
60 class NotebookHandler(IPythonHandler):
33 class NotebookHandler(IPythonHandler):
61
34
62 SUPPORTED_METHODS = ('GET', 'PUT', 'PATCH', 'POST','DELETE')
35 SUPPORTED_METHODS = (u'GET', u'PUT', u'PATCH', u'POST', u'DELETE')
36
37 def notebook_location(self, name, path):
38 """Return the full URL location of a notebook based.
39
40 Parameters
41 ----------
42 name : unicode
43 The name of the notebook like "foo.ipynb".
44 path : unicode
45 The URL path of the notebook.
46 """
47 return url_path_join(self.base_project_url, u'/api/notebooks', path, name)
63
48
64 @web.authenticated
49 @web.authenticated
50 @json_errors
65 def get(self, notebook_path):
51 def get(self, notebook_path):
66 """get checks if a notebook is not named, an returns a list of notebooks
52 """get checks if a notebook is not named, an returns a list of notebooks
67 in the notebook path given. If a name is given, return
53 in the notebook path given. If a name is given, return
68 the notebook representation"""
54 the notebook representation"""
69 nbm = self.notebook_manager
55 nbm = self.notebook_manager
56 # path will have leading and trailing slashes, such as '/foo/bar/'
70 name, path = nbm.named_notebook_path(notebook_path)
57 name, path = nbm.named_notebook_path(notebook_path)
71
58
72 # Check to see if a notebook name was given
59 # Check to see if a notebook name was given
73 if name is None:
60 if name is None:
74 # List notebooks in 'notebook_path'
61 # List notebooks in 'notebook_path'
75 notebooks = nbm.list_notebooks(path)
62 notebooks = nbm.list_notebooks(path)
76 self.finish(jsonapi.dumps(notebooks))
63 self.finish(json.dumps(notebooks, default=date_default))
77 else:
64 else:
78 # get and return notebook representation
65 # get and return notebook representation
79 format = self.get_argument('format', default='json')
66 model = nbm.get_notebook_model(name, path)
80 download = self.get_argument('download', default='False')
67 self.set_header(u'Last-Modified', model[u'last_modified'])
81 model = nbm.notebook_model(name, path)
68 self.finish(json.dumps(model, default=date_default))
82 last_mod, representation, name = nbm.get_notebook(name, path, format)
83 self.set_header('Last-Modified', last_mod)
84
85 if download == 'True':
86 if format == u'json':
87 self.set_header('Content-Type', 'application/json')
88 self.set_header('Content-Disposition','attachment; filename="%s.ipynb"' % name)
89 self.finish(representation)
90 elif format == u'py':
91 self.set_header('Content-Type', 'application/x-python')
92 self.set_header('Content-Disposition','attachment; filename="%s.py"' % name)
93 self.finish(representation)
94 else:
95 self.finish(jsonapi.dumps(model))
96
69
97 @web.authenticated
70 @web.authenticated
71 # @json_errors
98 def patch(self, notebook_path):
72 def patch(self, notebook_path):
99 """patch is currently used strictly for notebook renaming.
73 """patch is currently used strictly for notebook renaming.
100 Changes the notebook name to the name given in data."""
74 Changes the notebook name to the name given in data."""
101 nbm = self.notebook_manager
75 nbm = self.notebook_manager
76 # path will have leading and trailing slashes, such as '/foo/bar/'
102 name, path = nbm.named_notebook_path(notebook_path)
77 name, path = nbm.named_notebook_path(notebook_path)
103 data = jsonapi.loads(self.request.body)
78 if name is None:
104 model = nbm.change_notebook(data, name, path)
79 raise web.HTTPError(400, u'Notebook name missing')
105 self.finish(jsonapi.dumps(model))
80 model = self.get_json_body()
81 if model is None:
82 raise web.HTTPError(400, u'JSON body missing')
83 model = nbm.update_notebook_model(model, name, path)
84 if model[u'name'] != name or model[u'path'] != path:
85 self.set_status(301)
86 location = self.notebook_location(model[u'name'], model[u'path'])
87 self.set_header(u'Location', location)
88 self.set_header(u'Last-Modified', model[u'last_modified'])
89 self.finish(json.dumps(model, default=date_default))
106
90
107 @web.authenticated
91 @web.authenticated
108 def post(self,notebook_path):
92 @json_errors
93 def post(self, notebook_path):
109 """Create a new notebook in the location given by 'notebook_path'."""
94 """Create a new notebook in the location given by 'notebook_path'."""
110 nbm = self.notebook_manager
95 nbm = self.notebook_manager
111 fname, path = nbm.named_notebook_path(notebook_path)
96 # path will have leading and trailing slashes, such as '/foo/bar/'
112 body = self.request.body.strip()
97 name, path = nbm.named_notebook_path(notebook_path)
113 format = self.get_argument('format', default='json')
98 model = self.get_json_body()
114 name = self.get_argument('name', default=None)
99 if name is not None:
115 if body:
100 raise web.HTTPError(400, 'No name can be provided when POSTing a new notebook.')
116 fname = nbm.save_new_notebook(body, notebook_path=path, name=name, format=format)
101 model = nbm.create_notebook_model(model, path)
117 else:
102 location = nbm.notebook_dir + model[u'path'] + model[u'name']
118 fname = nbm.new_notebook(notebook_path=path)
103 location = self.notebook_location(model[u'name'], model[u'path'])
119 self.set_header('Location', nbm.notebook_dir + path + fname)
104 self.set_header(u'Location', location)
120 model = nbm.notebook_model(fname, path)
105 self.set_header(u'Last-Modified', model[u'last_modified'])
121 self.finish(jsonapi.dumps(model))
106 self.set_status(201)
107 self.finish(json.dumps(model, default=date_default))
122
108
123 @web.authenticated
109 @web.authenticated
110 @json_errors
124 def put(self, notebook_path):
111 def put(self, notebook_path):
125 """saves the notebook in the location given by 'notebook_path'."""
112 """saves the notebook in the location given by 'notebook_path'."""
126 nbm = self.notebook_manager
113 nbm = self.notebook_manager
114 # path will have leading and trailing slashes, such as '/foo/bar/'
127 name, path = nbm.named_notebook_path(notebook_path)
115 name, path = nbm.named_notebook_path(notebook_path)
128 format = self.get_argument('format', default='json')
116 model = self.get_json_body()
129 nbm.save_notebook(self.request.body, notebook_path=path, name=name, format=format)
117 if model is None:
130 model = nbm.notebook_model(name, path)
118 raise web.HTTPError(400, u'JSON body missing')
131 self.set_status(204)
119 nbm.save_notebook_model(model, name, path)
132 self.finish(jsonapi.dumps(model))
120 self.finish(json.dumps(model, default=date_default))
133
121
134 @web.authenticated
122 @web.authenticated
123 @json_errors
135 def delete(self, notebook_path):
124 def delete(self, notebook_path):
136 """delete rmoves the notebook in the given notebook path"""
125 """delete the notebook in the given notebook path"""
137 nbm = self.notebook_manager
126 nbm = self.notebook_manager
127 # path will have leading and trailing slashes, such as '/foo/bar/'
138 name, path = nbm.named_notebook_path(notebook_path)
128 name, path = nbm.named_notebook_path(notebook_path)
139 nbm.delete_notebook(name, path)
129 nbm.delete_notebook_model(name, path)
140 self.set_status(204)
130 self.set_status(204)
141 self.finish()
131 self.finish()
142
132
@@ -146,29 +136,28 b' class NotebookCheckpointsHandler(IPythonHandler):'
146 SUPPORTED_METHODS = ('GET', 'POST')
136 SUPPORTED_METHODS = ('GET', 'POST')
147
137
148 @web.authenticated
138 @web.authenticated
139 @json_errors
149 def get(self, notebook_path):
140 def get(self, notebook_path):
150 """get lists checkpoints for a notebook"""
141 """get lists checkpoints for a notebook"""
151 nbm = self.notebook_manager
142 nbm = self.notebook_manager
143 # path will have leading and trailing slashes, such as '/foo/bar/'
152 name, path = nbm.named_notebook_path(notebook_path)
144 name, path = nbm.named_notebook_path(notebook_path)
153 checkpoints = nbm.list_checkpoints(name, path)
145 checkpoints = nbm.list_checkpoints(name, path)
154 data = jsonapi.dumps(checkpoints, default=date_default)
146 data = json.dumps(checkpoints, default=date_default)
155 self.finish(data)
147 self.finish(data)
156
148
157 @web.authenticated
149 @web.authenticated
150 @json_errors
158 def post(self, notebook_path):
151 def post(self, notebook_path):
159 """post creates a new checkpoint"""
152 """post creates a new checkpoint"""
160 nbm = self.notebook_manager
153 nbm = self.notebook_manager
161 name, path = nbm.named_notebook_path(notebook_path)
154 name, path = nbm.named_notebook_path(notebook_path)
155 # path will have leading and trailing slashes, such as '/foo/bar/'
162 checkpoint = nbm.create_checkpoint(name, path)
156 checkpoint = nbm.create_checkpoint(name, path)
163 data = jsonapi.dumps(checkpoint, default=date_default)
157 data = json.dumps(checkpoint, default=date_default)
164 if path == None:
158 location = url_path_join(self.base_project_url, u'/api/notebooks',
165 self.set_header('Location', '{0}notebooks/{1}/checkpoints/{2}'.format(
159 path, name, '/checkpoints', checkpoint[u'checkpoint_id'])
166 self.base_project_url, name, checkpoint['checkpoint_id']
160 self.set_header(u'Location', location)
167 ))
168 else:
169 self.set_header('Location', '{0}notebooks/{1}/{2}/checkpoints/{3}'.format(
170 self.base_project_url, path, name, checkpoint['checkpoint_id']
171 ))
172 self.finish(data)
161 self.finish(data)
173
162
174
163
@@ -177,20 +166,24 b' class ModifyNotebookCheckpointsHandler(IPythonHandler):'
177 SUPPORTED_METHODS = ('POST', 'DELETE')
166 SUPPORTED_METHODS = ('POST', 'DELETE')
178
167
179 @web.authenticated
168 @web.authenticated
169 @json_errors
180 def post(self, notebook_path, checkpoint_id):
170 def post(self, notebook_path, checkpoint_id):
181 """post restores a notebook from a checkpoint"""
171 """post restores a notebook from a checkpoint"""
182 nbm = self.notebook_manager
172 nbm = self.notebook_manager
173 # path will have leading and trailing slashes, such as '/foo/bar/'
183 name, path = nbm.named_notebook_path(notebook_path)
174 name, path = nbm.named_notebook_path(notebook_path)
184 nbm.restore_checkpoint(name, checkpoint_id, path)
175 nbm.restore_checkpoint(checkpoint_id, name, path)
185 self.set_status(204)
176 self.set_status(204)
186 self.finish()
177 self.finish()
187
178
188 @web.authenticated
179 @web.authenticated
180 @json_errors
189 def delete(self, notebook_path, checkpoint_id):
181 def delete(self, notebook_path, checkpoint_id):
190 """delete clears a checkpoint for a given notebook"""
182 """delete clears a checkpoint for a given notebook"""
191 nbm = self.notebook_manager
183 nbm = self.notebook_manager
184 # path will have leading and trailing slashes, such as '/foo/bar/'
192 name, path = nbm.named_notebook_path(notebook_path)
185 name, path = nbm.named_notebook_path(notebook_path)
193 nbm.delete_checkpoint(name, checkpoint_id, path)
186 nbm.delete_checkpoint(checkpoint_id, name, path)
194 self.set_status(204)
187 self.set_status(204)
195 self.finish()
188 self.finish()
196
189
@@ -199,19 +192,15 b' class ModifyNotebookCheckpointsHandler(IPythonHandler):'
199 #-----------------------------------------------------------------------------
192 #-----------------------------------------------------------------------------
200
193
201
194
202 _notebook_path_regex = r"(?P<notebook_path>.+)"
195 _notebook_path_regex = r"(?P<notebook_path>.*)"
203 _checkpoint_id_regex = r"(?P<checkpoint_id>[\w-]+)"
196 _checkpoint_id_regex = r"(?P<checkpoint_id>[\w-]+)"
204
197
205 default_handlers = [
198 default_handlers = [
206 (r"api/notebooks/%s/checkpoints" % _notebook_path_regex, NotebookCheckpointsHandler),
199 (r"/api/notebooks/%s/checkpoints" % _notebook_path_regex, NotebookCheckpointsHandler),
207 (r"api/notebooks/%s/checkpoints/%s" % (_notebook_path_regex, _checkpoint_id_regex),
200 (r"/api/notebooks/%s/checkpoints/%s" % (_notebook_path_regex, _checkpoint_id_regex),
208 ModifyNotebookCheckpointsHandler),
201 ModifyNotebookCheckpointsHandler),
209 (r"api/notebooks/%s/" % _notebook_path_regex, NotebookHandler),
202 (r"/api/notebooks%s" % _notebook_path_regex, NotebookHandler),
210 (r"api/notebooks/%s" % _notebook_path_regex, NotebookHandler),
211 (r"api/notebooks/", NotebookRootHandler),
212 (r"api/notebooks", NotebookRootHandler),
213 ]
203 ]
214
204
215
205
216
206
217
@@ -155,12 +155,12 b' class NotebookManager(LoggingConfigurable):'
155 """
155 """
156 raise NotImplementedError('must be implemented in a subclass')
156 raise NotImplementedError('must be implemented in a subclass')
157
157
158 def notebook_model(self, notebook_name, notebook_path='/', content=True):
158 def notebook_model(self, name, path='/', content=True):
159 """ Creates the standard notebook model """
159 """ Creates the standard notebook model """
160 last_modified, contents = self.read_notebook_object(notebook_name, notebook_path)
160 last_modified, contents = self.read_notebook_model(name, path)
161 model = {"name": notebook_name,
161 model = {"name": name,
162 "path": notebook_path,
162 "path": path,
163 "last_modified (UTC)": last_modified.ctime()}
163 "last_modified": last_modified.ctime()}
164 if content is True:
164 if content is True:
165 model['content'] = contents
165 model['content'] = contents
166 return model
166 return model
@@ -180,10 +180,22 b' class NotebookManager(LoggingConfigurable):'
180 name = nb.metadata.get('name', 'notebook')
180 name = nb.metadata.get('name', 'notebook')
181 return last_mod, representation, name
181 return last_mod, representation, name
182
182
183 def read_notebook_object(self, notebook_name, notebook_path='/'):
183 def read_notebook_model(self, notebook_name, notebook_path='/'):
184 """Get the object representation of a notebook by notebook_id."""
184 """Get the object representation of a notebook by notebook_id."""
185 raise NotImplementedError('must be implemented in a subclass')
185 raise NotImplementedError('must be implemented in a subclass')
186
186
187 def save_notebook(self, model, name=None, path='/'):
188 """Save the Notebook"""
189 if name is None:
190 name = self.increment_filename('Untitled', path)
191 if 'content' not in model:
192 metadata = current.new_metadata(name=name)
193 nb = current.new_notebook(metadata=metadata)
194 else:
195 nb = model['content']
196 self.write_notebook_object()
197
198
187 def save_new_notebook(self, data, notebook_path='/', name=None, format=u'json'):
199 def save_new_notebook(self, data, notebook_path='/', name=None, format=u'json'):
188 """Save a new notebook and return its name.
200 """Save a new notebook and return its name.
189
201
@@ -208,7 +220,7 b' class NotebookManager(LoggingConfigurable):'
208 notebook_name = self.write_notebook_object(nb, notebook_path=notebook_path)
220 notebook_name = self.write_notebook_object(nb, notebook_path=notebook_path)
209 return notebook_name
221 return notebook_name
210
222
211 def save_notebook(self, data, notebook_path='/', name=None, new_name=None, format=u'json'):
223 def save_notebook(self, data, notebook_path='/', name=None, format=u'json'):
212 """Save an existing notebook by notebook_name."""
224 """Save an existing notebook by notebook_name."""
213 if format not in self.allowed_formats:
225 if format not in self.allowed_formats:
214 raise web.HTTPError(415, u'Invalid notebook format: %s' % format)
226 raise web.HTTPError(415, u'Invalid notebook format: %s' % format)
@@ -222,7 +234,7 b' class NotebookManager(LoggingConfigurable):'
222 nb.metadata.name = name
234 nb.metadata.name = name
223 self.write_notebook_object(nb, name, notebook_path, new_name)
235 self.write_notebook_object(nb, name, notebook_path, new_name)
224
236
225 def write_notebook_object(self, nb, notebook_name='/', notebook_path='/', new_name=None):
237 def write_notebook_model(self, model):
226 """Write a notebook object and return its notebook_name.
238 """Write a notebook object and return its notebook_name.
227
239
228 If notebook_name is None, this method should create a new notebook_name.
240 If notebook_name is None, this method should create a new notebook_name.
@@ -25,15 +25,15 b' class APITest(NotebookTestBase):'
25 r = requests.delete(url)
25 r = requests.delete(url)
26 return r.status_code
26 return r.status_code
27
27
28 def test_notebook_root_handler(self):
28 def test_notebook_handler(self):
29 # POST a notebook and test the dict thats returned.
29 # POST a notebook and test the dict thats returned.
30 #url, nb = self.mknb()
30 #url, nb = self.mknb()
31 url = self.notebook_url()
31 url = self.notebook_url()
32 nb = requests.post(url)
32 nb = requests.post(url)
33 data = nb.json()
33 data = nb.json()
34 assert isinstance(data, dict)
34 assert isinstance(data, dict)
35 assert data.has_key("name")
35 self.assertIn('name', data)
36 assert data.has_key("path")
36 self.assertIn('path', data)
37 self.assertEqual(data['name'], u'Untitled0.ipynb')
37 self.assertEqual(data['name'], u'Untitled0.ipynb')
38 self.assertEqual(data['path'], u'/')
38 self.assertEqual(data['path'], u'/')
39
39
@@ -43,8 +43,7 b' class APITest(NotebookTestBase):'
43 assert isinstance(r.json()[0], dict)
43 assert isinstance(r.json()[0], dict)
44
44
45 self.delnb('Untitled0.ipynb')
45 self.delnb('Untitled0.ipynb')
46
46
47 def test_notebook_handler(self):
48 # GET with a notebook name.
47 # GET with a notebook name.
49 url, nb = self.mknb()
48 url, nb = self.mknb()
50 data = nb.json()
49 data = nb.json()
@@ -79,18 +78,18 b' class APITest(NotebookTestBase):'
79 data2 = nb2.json()
78 data2 = nb2.json()
80 assert isinstance(data, dict)
79 assert isinstance(data, dict)
81 assert isinstance(data2, dict)
80 assert isinstance(data2, dict)
82 assert data.has_key("name")
81 self.assertIn('name', data)
83 assert data.has_key("path")
82 self.assertIn('path', data)
84 self.assertEqual(data['name'], u'Untitled0.ipynb')
83 self.assertEqual(data['name'], u'Untitled0.ipynb')
85 self.assertEqual(data['path'], u'/foo/')
84 self.assertEqual(data['path'], u'/foo/')
86 assert data2.has_key("name")
85 self.assertIn('name', data2)
87 assert data2.has_key("path")
86 self.assertIn('path', data2)
88 self.assertEqual(data2['name'], u'Untitled0.ipynb')
87 self.assertEqual(data2['name'], u'Untitled0.ipynb')
89 self.assertEqual(data2['path'], u'/foo/bar/')
88 self.assertEqual(data2['path'], u'/foo/bar/')
90
89
91 # GET request on notebooks one and two levels down.
90 # GET request on notebooks one and two levels down.
92 r = requests.get(url+'Untitled0.ipynb')
91 r = requests.get(url+'/Untitled0.ipynb')
93 r2 = requests.get(url2+'Untitled0.ipynb')
92 r2 = requests.get(url2+'/Untitled0.ipynb')
94 assert isinstance(r.json(), dict)
93 assert isinstance(r.json(), dict)
95 self.assertEqual(r.json(), data)
94 self.assertEqual(r.json(), data)
96 assert isinstance(r2.json(), dict)
95 assert isinstance(r2.json(), dict)
@@ -98,13 +97,13 b' class APITest(NotebookTestBase):'
98
97
99 # PATCH notebooks that are one and two levels down.
98 # PATCH notebooks that are one and two levels down.
100 new_name = {'name': 'testfoo.ipynb'}
99 new_name = {'name': 'testfoo.ipynb'}
101 r = requests.patch(url+'Untitled0.ipynb', data=jsonapi.dumps(new_name))
100 r = requests.patch(url+'/Untitled0.ipynb', data=jsonapi.dumps(new_name))
102 r = requests.get(url+'testfoo.ipynb')
101 r = requests.get(url+'/testfoo.ipynb')
103 data = r.json()
102 data = r.json()
104 assert isinstance(data, dict)
103 assert isinstance(data, dict)
105 assert data.has_key('name')
104 self.assertIn('name', data)
106 self.assertEqual(data['name'], 'testfoo.ipynb')
105 self.assertEqual(data['name'], 'testfoo.ipynb')
107 r = requests.get(url+'Untitled0.ipynb')
106 r = requests.get(url+'/Untitled0.ipynb')
108 self.assertEqual(r.status_code, 404)
107 self.assertEqual(r.status_code, 404)
109
108
110 # DELETE notebooks
109 # DELETE notebooks
@@ -43,7 +43,7 b' class SessionAPITest(NotebookTestBase):'
43 r = requests.post(self.session_url(), params=param)
43 r = requests.post(self.session_url(), params=param)
44 data = r.json()
44 data = r.json()
45 assert isinstance(data, dict)
45 assert isinstance(data, dict)
46 assert data.has_key('name')
46 self.assertIn('name', data)
47 self.assertEqual(data['name'], notebook['name'])
47 self.assertEqual(data['name'], notebook['name'])
48
48
49 # GET sessions
49 # GET sessions
@@ -79,8 +79,8 b' class SessionAPITest(NotebookTestBase):'
79 requests.patch(self.notebook_url() + '/Untitled0.ipynb',
79 requests.patch(self.notebook_url() + '/Untitled0.ipynb',
80 data=jsonapi.dumps({'name':'test.ipynb'}))
80 data=jsonapi.dumps({'name':'test.ipynb'}))
81 assert isinstance(r.json(), dict)
81 assert isinstance(r.json(), dict)
82 assert r.json().has_key('name')
82 self.assertIn('name', r.json())
83 assert r.json().has_key('id')
83 self.assertIn('id', r.json())
84 self.assertEqual(r.json()['name'], 'test.ipynb')
84 self.assertEqual(r.json()['name'], 'test.ipynb')
85 self.assertEqual(r.json()['id'], session['id'])
85 self.assertEqual(r.json()['id'], session['id'])
86
86
@@ -88,8 +88,8 b' class SessionAPITest(NotebookTestBase):'
88 r = requests.delete(sess_url)
88 r = requests.delete(sess_url)
89 self.assertEqual(r.status_code, 204)
89 self.assertEqual(r.status_code, 204)
90 r = requests.get(self.session_url())
90 r = requests.get(self.session_url())
91 assert r.json() == []
91 self.assertEqual(r.json(), [])
92
92
93 # Clean up
93 # Clean up
94 r = self.delnb('test.ipynb')
94 r = self.delnb('test.ipynb')
95 assert r == 204 No newline at end of file
95 self.assertEqual(r, 204) No newline at end of file
@@ -2,6 +2,7 b''
2
2
3 import sys
3 import sys
4 import time
4 import time
5 import requests
5 from subprocess import Popen, PIPE
6 from subprocess import Popen, PIPE
6 from unittest import TestCase
7 from unittest import TestCase
7
8
@@ -17,6 +18,26 b' class NotebookTestBase(TestCase):'
17
18
18 port = 1234
19 port = 1234
19
20
21 def wait_till_alive(self):
22 url = 'http://localhost:%i/' % self.port
23 while True:
24 time.sleep(.1)
25 try:
26 r = requests.get(url + 'api/notebooks')
27 break
28 except requests.exceptions.ConnectionError:
29 pass
30
31 def wait_till_dead(self):
32 url = 'http://localhost:%i/' % self.port
33 while True:
34 time.sleep(.1)
35 try:
36 r = requests.get(url + 'api/notebooks')
37 continue
38 except requests.exceptions.ConnectionError:
39 break
40
20 def setUp(self):
41 def setUp(self):
21 self.ipython_dir = TemporaryDirectory()
42 self.ipython_dir = TemporaryDirectory()
22 self.notebook_dir = TemporaryDirectory()
43 self.notebook_dir = TemporaryDirectory()
@@ -27,15 +48,16 b' class NotebookTestBase(TestCase):'
27 '--no-browser',
48 '--no-browser',
28 '--ipython-dir=%s' % self.ipython_dir.name,
49 '--ipython-dir=%s' % self.ipython_dir.name,
29 '--notebook-dir=%s' % self.notebook_dir.name
50 '--notebook-dir=%s' % self.notebook_dir.name
30 ]
51 ]
31 self.notebook = Popen(notebook_args, stdout=PIPE, stderr=PIPE)
52 self.notebook = Popen(notebook_args, stdout=PIPE, stderr=PIPE)
32 time.sleep(3.0)
53 self.wait_till_alive()
54 #time.sleep(3.0)
33
55
34 def tearDown(self):
56 def tearDown(self):
35 self.notebook.terminate()
57 self.notebook.terminate()
36 self.ipython_dir.cleanup()
58 self.ipython_dir.cleanup()
37 self.notebook_dir.cleanup()
59 self.notebook_dir.cleanup()
38 time.sleep(3.0)
60 self.wait_till_dead()
39
61
40 def base_url(self):
62 def base_url(self):
41 return 'http://localhost:%i/' % self.port
63 return 'http://localhost:%i/' % self.port
General Comments 0
You need to be logged in to leave comments. Login now