diff --git a/jupyter_client/kernelspec.py b/jupyter_client/kernelspec.py index 99b35447d..ab62f5458 100644 --- a/jupyter_client/kernelspec.py +++ b/jupyter_client/kernelspec.py @@ -16,6 +16,7 @@ from traitlets import Dict from traitlets import HasTraits from traitlets import List +from traitlets import observe from traitlets import Set from traitlets import Type from traitlets import Unicode @@ -148,7 +149,12 @@ def _user_kernel_dir_default(self): whitelist = Set( config=True, - help="""Whitelist of allowed kernel names. + help="""Deprecated, use `KernelSpecManager.allowed_kernelspecs` + """, + ) + allowed_kernelspecs = Set( + config=True, + help="""List of allowed kernel names. By default, all installed kernels are allowed. """, @@ -157,6 +163,32 @@ def _user_kernel_dir_default(self): help="List of kernel directories to search. Later ones take priority over earlier." ) + _deprecated_aliases = { + "whitelist": ("allowed_kernelspecs", "7.0"), + } + + # Method copied from + # https://github.com/jupyterhub/jupyterhub/blob/d1a85e53dccfc7b1dd81b0c1985d158cc6b61820/jupyterhub/auth.py#L143-L161 + @observe(*list(_deprecated_aliases)) + def _deprecated_trait(self, change): + """observer for deprecated traits""" + old_attr = change.name + new_attr, version = self._deprecated_aliases.get(old_attr) + new_value = getattr(self, new_attr) + if new_value != change.new: + # only warn if different + # protects backward-compatible config from warnings + # if they set the same value under both names + self.log.warning( + "{cls}.{old} is deprecated in JupyterLab {version}, use {cls}.{new} instead".format( + cls=self.__class__.__name__, + old=old_attr, + new=new_attr, + version=version, + ) + ) + setattr(self, new_attr, change.new) + def _kernel_dirs_default(self): dirs = jupyter_path("kernels") # At some point, we should stop adding .ipython/kernels to the path, @@ -196,9 +228,9 @@ def find_kernel_specs(self): except ImportError: self.log.warning("Native kernel (%s) is not available", NATIVE_KERNEL_NAME) - if self.whitelist: - # filter if there's a whitelist - d = {name: spec for name, spec in d.items() if name in self.whitelist} + if self.allowed_kernelspecs: + # filter if there's an allow list + d = {name: spec for name, spec in d.items() if name in self.allowed_kernelspecs} return d # TODO: Caching? diff --git a/jupyter_client/tests/test_kernelspec.py b/jupyter_client/tests/test_kernelspec.py index 19436e311..6953d4b18 100644 --- a/jupyter_client/tests/test_kernelspec.py +++ b/jupyter_client/tests/test_kernelspec.py @@ -59,6 +59,18 @@ def test_find_kernel_specs(self): kernels = self.ksm.find_kernel_specs() self.assertEqual(kernels["sample"], self.sample_kernel_dir) + def test_allowed_kernel_names(self): + ksm = kernelspec.KernelSpecManager() + ksm.allowed_kernelspecs = ["foo"] + kernels = ksm.find_kernel_specs() + assert not len(kernels) + + def test_deprecated_whitelist(self): + ksm = kernelspec.KernelSpecManager() + ksm.whitelist = ["bar"] + kernels = ksm.find_kernel_specs() + assert not len(kernels) + def test_get_kernel_spec(self): ks = self.ksm.get_kernel_spec("SAMPLE") # Case insensitive self.assertEqual(ks.resource_dir, self.sample_kernel_dir)