##// END OF EJS Templates
Test kernel specs REST API...
Thomas Kluyver -
Show More
@@ -0,0 +1,94 b''
1 # coding: utf-8
2 """Test the kernel specs webservice API."""
3
4 import errno
5 import io
6 import json
7 import os
8
9 pjoin = os.path.join
10
11 import requests
12
13 from IPython.html.utils import url_path_join
14 from IPython.html.tests.launchnotebook import NotebookTestBase, assert_http_error
15
16 # Copied from IPython.kernel.tests.test_kernelspec so updating that doesn't
17 # break these tests
18 sample_kernel_json = {'argv':['cat', '{connection_file}'],
19 'display_name':'Test kernel',
20 'language':'bash',
21 }
22
23 some_resource = u"The very model of a modern major general"
24
25
26 class KernelSpecAPI(object):
27 """Wrapper for notebook API calls."""
28 def __init__(self, base_url):
29 self.base_url = base_url
30
31 def _req(self, verb, path, body=None):
32 response = requests.request(verb,
33 url_path_join(self.base_url, 'api/kernelspecs', path),
34 data=body,
35 )
36 response.raise_for_status()
37 return response
38
39 def list(self):
40 return self._req('GET', '')
41
42 def kernel_spec_info(self, name):
43 return self._req('GET', name)
44
45 def kernel_resource(self, name, path):
46 return self._req('GET', url_path_join(name, path))
47
48 class APITest(NotebookTestBase):
49 """Test the kernelspec web service API"""
50 def setUp(self):
51 ipydir = self.ipython_dir.name
52 sample_kernel_dir = pjoin(ipydir, 'kernels', 'sample')
53 try:
54 os.makedirs(sample_kernel_dir)
55 except OSError as e:
56 if e.errno != errno.EEXIST:
57 raise
58
59 with open(pjoin(sample_kernel_dir, 'kernel.json'), 'w') as f:
60 json.dump(sample_kernel_json, f)
61
62 with io.open(pjoin(sample_kernel_dir, 'resource.txt'), 'w',
63 encoding='utf-8') as f:
64 f.write(some_resource)
65
66 self.ks_api = KernelSpecAPI(self.base_url())
67
68 def test_list_kernelspecs(self):
69 specs = self.ks_api.list().json()
70 assert isinstance(specs, list)
71
72 # 2: the sample kernelspec created in setUp, and the native Python kernel
73 self.assertEqual(len(specs), 2)
74 assert any(s == {'name': 'sample', 'display_name': 'Test kernel'}
75 for s in specs), specs
76
77 def test_get_kernelspec(self):
78 spec = self.ks_api.kernel_spec_info('Sample').json() # Case insensitive
79 self.assertEqual(spec['language'], 'bash')
80
81 def test_get_nonexistant_kernelspec(self):
82 with assert_http_error(404):
83 self.ks_api.kernel_spec_info('nonexistant')
84
85 def test_get_kernel_resource_file(self):
86 res = self.ks_api.kernel_resource('sAmple', 'resource.txt')
87 self.assertEqual(res.text, some_resource)
88
89 def test_get_nonexistant_resource(self):
90 with assert_http_error(404):
91 self.ks_api.kernel_resource('nonexistant', 'resource.txt')
92
93 with assert_http_error(404):
94 self.ks_api.kernel_resource('sample', 'nonexistant.txt')
@@ -1,75 +1,71 b''
1 """Tornado handlers for kernel specifications."""
1 """Tornado handlers for kernel specifications."""
2
2
3 # Copyright (c) IPython Development Team.
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
4 # Distributed under the terms of the Modified BSD License.
5
5
6 import logging
7 from tornado import web
6 from tornado import web
8
7
9 from zmq.utils import jsonapi
8 from zmq.utils import jsonapi
10
9
11 from ...base.handlers import IPythonHandler, json_errors, path_regex
10 from ...base.handlers import IPythonHandler, json_errors
12
11
13
12
14 class MainKernelSpecHandler(IPythonHandler):
13 class MainKernelSpecHandler(IPythonHandler):
15 SUPPORTED_METHODS = ('GET',)
14 SUPPORTED_METHODS = ('GET',)
16
15
17 @web.authenticated
16 @web.authenticated
18 @json_errors
17 @json_errors
19 def get(self):
18 def get(self):
20 ksm = self.kernel_spec_manager
19 ksm = self.kernel_spec_manager
21 results = []
20 results = []
22 for kernel_name in ksm.find_kernel_specs():
21 for kernel_name in ksm.find_kernel_specs():
23 results.append(dict(name=kernel_name,
22 results.append(dict(name=kernel_name,
24 display_name=ksm.get_kernel_spec(kernel_name).display_name))
23 display_name=ksm.get_kernel_spec(kernel_name).display_name))
25
24
26 self.set_header("Content-Type", 'application/json')
25 self.set_header("Content-Type", 'application/json')
27 self.finish(jsonapi.dumps(results))
26 self.finish(jsonapi.dumps(results))
28
27
29
28
30 class KernelSpecHandler(IPythonHandler):
29 class KernelSpecHandler(IPythonHandler):
31 SUPPORTED_METHODS = ('GET',)
30 SUPPORTED_METHODS = ('GET',)
32
31
33 @web.authenticated
32 @web.authenticated
34 @json_errors
33 @json_errors
35 def get(self, kernel_name):
34 def get(self, kernel_name):
36 ksm = self.kernel_spec_manager
35 ksm = self.kernel_spec_manager
37 kernelspec = ksm.get_kernel_spec(kernel_name)
36 try:
37 kernelspec = ksm.get_kernel_spec(kernel_name)
38 except KeyError:
39 raise web.HTTPError(404, u'Kernel spec %s not found' % kernel_name)
38 self.set_header("Content-Type", 'application/json')
40 self.set_header("Content-Type", 'application/json')
39 self.finish(kernelspec.to_json())
41 self.finish(kernelspec.to_json())
40
42
41
43
42 class KernelSpecResourceHandler(web.StaticFileHandler, IPythonHandler):
44 class KernelSpecResourceHandler(web.StaticFileHandler, IPythonHandler):
43 SUPPORTED_METHODS = ('GET', 'HEAD')
45 SUPPORTED_METHODS = ('GET', 'HEAD')
44
46
45 def initialize(self):
47 def initialize(self):
46 web.StaticFileHandler.initialize(self, path='')
48 web.StaticFileHandler.initialize(self, path='')
47
49
48 def get(self, kernel_name, path, include_body=True):
50 def get(self, kernel_name, path, include_body=True):
49 ksm = self.kernel_spec_manager
51 ksm = self.kernel_spec_manager
50 self.root = ksm.get_kernel_spec(kernel_name).resource_dir
52 try:
51 self.log.warn("Set root: %s", self.root)
53 self.root = ksm.get_kernel_spec(kernel_name).resource_dir
54 except KeyError:
55 raise web.HTTPError(404, u'Kernel spec %s not found' % kernel_name)
56 self.log.debug("Serving kernel resource from: %s", self.root)
52 return web.StaticFileHandler.get(self, path, include_body=include_body)
57 return web.StaticFileHandler.get(self, path, include_body=include_body)
53
58
54 # @classmethod
55 # def get_absolute_path(cls, root, path):
56 # res = web.StaticFileHandler.get_absolute_path(cls, root, path)
57 # self.log.warn("Full path: %s", res)
58 # return res
59
60 def head(self, kernel_name, path):
59 def head(self, kernel_name, path):
61 self.get(kernel_name, path, include_body=False)
60 self.get(kernel_name, path, include_body=False)
62
61
63
62
64 #-----------------------------------------------------------------------------
65 # URL to handler mappings
63 # URL to handler mappings
66 #-----------------------------------------------------------------------------
67
68
64
69 _kernel_name_regex = r"(?P<kernel_name>\w+)"
65 _kernel_name_regex = r"(?P<kernel_name>\w+)"
70
66
71 default_handlers = [
67 default_handlers = [
72 (r"/api/kernelspecs", MainKernelSpecHandler),
68 (r"/api/kernelspecs", MainKernelSpecHandler),
73 (r"/api/kernelspecs/%s" % _kernel_name_regex, KernelSpecHandler),
69 (r"/api/kernelspecs/%s" % _kernel_name_regex, KernelSpecHandler),
74 (r"/api/kernelspecs/%s/(?P<path>.*)" % _kernel_name_regex, KernelSpecResourceHandler),
70 (r"/api/kernelspecs/%s/(?P<path>.*)" % _kernel_name_regex, KernelSpecResourceHandler),
75 ]
71 ]
General Comments 0
You need to be logged in to leave comments. Login now