From 2f4d5748f4a7656be21121a020dc69d6b4d2ad7e Mon Sep 17 00:00:00 2001 From: Johan Forsberg Date: Thu, 28 Jul 2016 19:11:32 +0200 Subject: [PATCH 1/5] Add a --profile flag to install Setting the IPython profile to be used by the kernel. --- ipykernel/kernelspec.py | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/ipykernel/kernelspec.py b/ipykernel/kernelspec.py index 10d320859..4bc8f5226 100644 --- a/ipykernel/kernelspec.py +++ b/ipykernel/kernelspec.py @@ -44,22 +44,22 @@ def make_ipkernel_cmd(mod='ipykernel', executable=None, extra_arguments=None, ** if executable is None: executable = sys.executable extra_arguments = extra_arguments or [] - arguments = [ executable, '-m', mod, '-f', '{connection_file}' ] + arguments = [executable, '-m', mod, '-f', '{connection_file}'] arguments.extend(extra_arguments) return arguments -def get_kernel_dict(): +def get_kernel_dict(extra_arguments): """Construct dict for kernel.json""" return { - 'argv': make_ipkernel_cmd(), + 'argv': make_ipkernel_cmd(extra_arguments=extra_arguments), 'display_name': 'Python %i' % sys.version_info[0], 'language': 'python', } -def write_kernel_spec(path=None, overrides=None): +def write_kernel_spec(path=None, overrides=None, extra_arguments=None): """Write a kernel spec directory to `path` If `path` is not specified, a temporary directory is created. @@ -73,7 +73,8 @@ def write_kernel_spec(path=None, overrides=None): # stage resources shutil.copytree(RESOURCES, path) # write kernel.json - kernel_dict = get_kernel_dict() + kernel_dict = get_kernel_dict(extra_arguments) + if overrides: kernel_dict.update(overrides) with open(pjoin(path, 'kernel.json'), 'w') as f: @@ -82,7 +83,8 @@ def write_kernel_spec(path=None, overrides=None): return path -def install(kernel_spec_manager=None, user=False, kernel_name=KERNEL_NAME, display_name=None, prefix=None): +def install(kernel_spec_manager=None, user=False, kernel_name=KERNEL_NAME, display_name=None, + profile=None, prefix=None): """Install the IPython kernelspec for Jupyter Parameters @@ -96,12 +98,14 @@ def install(kernel_spec_manager=None, user=False, kernel_name=KERNEL_NAME, displ kernel_name: str, optional Specify a name for the kernelspec. This is needed for having multiple IPython kernels for different environments. + display_name: str, optional + Specify the display name for the kernelspec + profile: str, optional + Specify a custom profile to be loaded by the kernel. prefix: str, optional Specify an install prefix for the kernelspec. This is needed to install into a non-default location, such as a conda/virtual-env. - display_name: str, optional - Specify the display name for the kernelspec - + Returns ------- @@ -118,9 +122,13 @@ def install(kernel_spec_manager=None, user=False, kernel_name=KERNEL_NAME, displ overrides = dict(display_name=display_name) else: overrides = None - path = write_kernel_spec(overrides=overrides) - dest = kernel_spec_manager.install_kernel_spec(path, - kernel_name=kernel_name, user=user, prefix=prefix) + if profile: + extra_arguments = ["--profile", profile] + else: + extra_arguments = None + path = write_kernel_spec(overrides=overrides, extra_arguments=extra_arguments) + dest = kernel_spec_manager.install_kernel_spec( + path, kernel_name=kernel_name, user=user, prefix=prefix) # cleanup afterward shutil.rmtree(path) return dest @@ -151,6 +159,9 @@ def start(self): parser.add_argument('--display-name', type=str, help="Specify the display name for the kernelspec." " This is helpful when you have multiple IPython kernels.") + parser.add_argument('--profile', type=str, + help="Specify an IPython profile to load. " + "This can be used to create custom versions of the kernel.") parser.add_argument('--prefix', type=str, help="Specify an install prefix for the kernelspec." " This is needed to install into a non-default location, such as a conda/virtual-env.") @@ -159,9 +170,8 @@ def start(self): " Shorthand for --prefix='%s'. For use in conda/virtual-envs." % sys.prefix) opts = parser.parse_args(self.argv) try: - dest = install(user=opts.user, kernel_name=opts.name, prefix=opts.prefix, - display_name=opts.display_name, - ) + dest = install(user=opts.user, kernel_name=opts.name, profile=opts.profile, + prefix=opts.prefix, display_name=opts.display_name) except OSError as e: if e.errno == errno.EACCES: print(e, file=sys.stderr) From 627676ec3374e47af7e3b9b284e7210d4e1734cf Mon Sep 17 00:00:00 2001 From: Johan Forsberg Date: Thu, 28 Jul 2016 19:25:20 +0200 Subject: [PATCH 2/5] Make extra_arguments optional --- ipykernel/kernelspec.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipykernel/kernelspec.py b/ipykernel/kernelspec.py index 4bc8f5226..9f5512632 100644 --- a/ipykernel/kernelspec.py +++ b/ipykernel/kernelspec.py @@ -50,7 +50,7 @@ def make_ipkernel_cmd(mod='ipykernel', executable=None, extra_arguments=None, ** return arguments -def get_kernel_dict(extra_arguments): +def get_kernel_dict(extra_arguments=None): """Construct dict for kernel.json""" return { 'argv': make_ipkernel_cmd(extra_arguments=extra_arguments), From 337a0d545d2499dbccac7233d67f277d0bf6dc41 Mon Sep 17 00:00:00 2001 From: Johan Forsberg Date: Thu, 28 Jul 2016 19:26:36 +0200 Subject: [PATCH 3/5] Add kernelspec test for profile --- ipykernel/tests/test_kernelspec.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ipykernel/tests/test_kernelspec.py b/ipykernel/tests/test_kernelspec.py index c849436fe..45345b713 100644 --- a/ipykernel/tests/test_kernelspec.py +++ b/ipykernel/tests/test_kernelspec.py @@ -52,6 +52,18 @@ def test_get_kernel_dict(): assert_kernel_dict(d) +def assert_kernel_dict_with_profile(d): + nt.assert_equal(d['argv'], make_ipkernel_cmd( + extra_arguments=["--profile", "test"])) + nt.assert_equal(d['display_name'], 'Python %i' % sys.version_info[0]) + nt.assert_equal(d['language'], 'python') + + +def test_get_kernel_dict_with_profile(): + d = get_kernel_dict(["--profile", "test"]) + assert_kernel_dict_with_profile(d) + + def assert_is_spec(path): for fname in os.listdir(RESOURCES): dst = pjoin(path, fname) From 3bc6ad10617bd00efffa840c2c57069a0b5dae9a Mon Sep 17 00:00:00 2001 From: Johan Forsberg Date: Mon, 1 Aug 2016 10:58:48 +0200 Subject: [PATCH 4/5] Reorder install arguments for backwards compat --- ipykernel/kernelspec.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipykernel/kernelspec.py b/ipykernel/kernelspec.py index 9f5512632..ff40e6b1f 100644 --- a/ipykernel/kernelspec.py +++ b/ipykernel/kernelspec.py @@ -84,7 +84,7 @@ def write_kernel_spec(path=None, overrides=None, extra_arguments=None): def install(kernel_spec_manager=None, user=False, kernel_name=KERNEL_NAME, display_name=None, - profile=None, prefix=None): + prefix=None, profile=None): """Install the IPython kernelspec for Jupyter Parameters From c5ffa0d3eb63746c06c5a98f08460f20c2715a81 Mon Sep 17 00:00:00 2001 From: Johan Forsberg Date: Mon, 1 Aug 2016 10:59:27 +0200 Subject: [PATCH 5/5] Append profile to display name unless specified --- ipykernel/kernelspec.py | 8 +++++--- ipykernel/tests/test_kernelspec.py | 25 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/ipykernel/kernelspec.py b/ipykernel/kernelspec.py index ff40e6b1f..dcd57d4c1 100644 --- a/ipykernel/kernelspec.py +++ b/ipykernel/kernelspec.py @@ -118,12 +118,14 @@ def install(kernel_spec_manager=None, user=False, kernel_name=KERNEL_NAME, displ # kernel_name is specified and display_name is not # default display_name to kernel_name display_name = kernel_name + overrides = {} if display_name: - overrides = dict(display_name=display_name) - else: - overrides = None + overrides["display_name"] = display_name if profile: extra_arguments = ["--profile", profile] + if not display_name: + # add the profile to the default display name + overrides["display_name"] = 'Python %i [profile=%s]' % (sys.version_info[0], profile) else: extra_arguments = None path = write_kernel_spec(overrides=overrides, extra_arguments=extra_arguments) diff --git a/ipykernel/tests/test_kernelspec.py b/ipykernel/tests/test_kernelspec.py index 45345b713..f1c0c4282 100644 --- a/ipykernel/tests/test_kernelspec.py +++ b/ipykernel/tests/test_kernelspec.py @@ -119,3 +119,28 @@ def test_install(): assert_is_spec(os.path.join(system_jupyter_dir, 'kernels', KERNEL_NAME)) +def test_install_profile(): + system_jupyter_dir = tempfile.mkdtemp() + + with mock.patch('jupyter_client.kernelspec.SYSTEM_JUPYTER_PATH', + [system_jupyter_dir]): + install(profile="Test") + + spec = os.path.join(system_jupyter_dir, 'kernels', KERNEL_NAME, "kernel.json") + with open(spec) as f: + spec = json.load(f) + nt.assert_true(spec["display_name"].endswith(" [profile=Test]")) + nt.assert_equal(spec["argv"][-2:], ["--profile", "Test"]) + + +def test_install_display_name_overrides_profile(): + system_jupyter_dir = tempfile.mkdtemp() + + with mock.patch('jupyter_client.kernelspec.SYSTEM_JUPYTER_PATH', + [system_jupyter_dir]): + install(display_name="Display", profile="Test") + + spec = os.path.join(system_jupyter_dir, 'kernels', KERNEL_NAME, "kernel.json") + with open(spec) as f: + spec = json.load(f) + nt.assert_equal(spec["display_name"], "Display")