Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 25 additions & 15 deletions ipykernel/kernelspec.py
Original file line number Diff line number Diff line change
Expand Up @@ -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=None):
"""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.
Expand All @@ -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:
Expand All @@ -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):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add profile on the end instead of just before prefix, so that it's a backward-compatible patch in the extremely unlikely event of people passing all arguments positionally?

"""Install the IPython kernelspec for Jupyter

Parameters
Expand All @@ -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
-------

Expand All @@ -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]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If profile is given, this should probably be reflected in display_name if it has not been specified manually. Something like Python X [profile=Y], perhaps.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, maybe it would be enough with e.g. "Python X [Y]" to make it more compact?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the display_name horizontal space is so precious that profile= should be omitted, but feel free to try both and see how it feels. I don't think [name] is sufficiently clear, since it could be indicating other things, such as conda/virtual env, etc.

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
Expand Down Expand Up @@ -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.")
Expand All @@ -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)
Expand Down
12 changes: 12 additions & 0 deletions ipykernel/tests/test_kernelspec.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down