diff --git a/IPython/html/services/kernelspecs/handlers.py b/IPython/html/services/kernelspecs/handlers.py index 6561b0b..f810414 100644 --- a/IPython/html/services/kernelspecs/handlers.py +++ b/IPython/html/services/kernelspecs/handlers.py @@ -19,7 +19,11 @@ class MainKernelSpecHandler(IPythonHandler): ksm = self.kernel_spec_manager results = [] for kernel_name in sorted(ksm.find_kernel_specs(), key=_pythonfirst): - d = ksm.get_kernel_spec(kernel_name).to_dict() + try: + d = ksm.get_kernel_spec(kernel_name).to_dict() + except Exception: + self.log.error("Failed to load kernel spec: '%s'", kernel_name, exc_info=True) + continue d['name'] = kernel_name results.append(d) diff --git a/IPython/html/services/kernelspecs/tests/test_kernelspecs_api.py b/IPython/html/services/kernelspecs/tests/test_kernelspecs_api.py index 871f163..a2d3fb2 100644 --- a/IPython/html/services/kernelspecs/tests/test_kernelspecs_api.py +++ b/IPython/html/services/kernelspecs/tests/test_kernelspecs_api.py @@ -5,6 +5,7 @@ import errno import io import json import os +import shutil pjoin = os.path.join @@ -66,6 +67,25 @@ class APITest(NotebookTestBase): self.ks_api = KernelSpecAPI(self.base_url()) + def test_list_kernelspecs_bad(self): + """Can list kernelspecs when one is invalid""" + bad_kernel_dir = pjoin(self.ipython_dir.name, 'kernels', 'bad') + try: + os.makedirs(bad_kernel_dir) + except OSError as e: + if e.errno != errno.EEXIST: + raise + + with open(pjoin(bad_kernel_dir, 'kernel.json'), 'w') as f: + f.write("garbage") + + specs = self.ks_api.list().json() + assert isinstance(specs, list) + # 2: the sample kernelspec created in setUp, and the native Python kernel + self.assertGreaterEqual(len(specs), 2) + + shutil.rmtree(bad_kernel_dir) + def test_list_kernelspecs(self): specs = self.ks_api.list().json() assert isinstance(specs, list)