Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle non-existing kernels #309

Merged
merged 9 commits into from
Jul 29, 2019

Conversation

jtpio
Copy link
Member

@jtpio jtpio commented Jul 17, 2019

Fixes #259. It should also provide a simple solution for #267.

This PR makes use of the KernelSpecManager to first check that the requested kernel name (from the notebook metadata) is available. If it isn't then it will default to the default kernel name.

I also got hit by that recently while using xeus-python and decided to give it a shot.

@jtpio
Copy link
Member Author

jtpio commented Jul 17, 2019

Another approach would be to make use of the language field from the kernelspec metadata to find a spec that matches the same language.

@SylvainCorlay
Copy link
Member

What does the classic notebook do? It appears to be quite liberal with kernelspecs.

@jtpio
Copy link
Member Author

jtpio commented Jul 17, 2019

It looks like most of the logic for dealing with missing kernel names in the classic notebook is actually handled by the frontend.

This is what it appears to be doing:

  1. The frontend fetches the list of kernelspecs. When a spec is not found it logs it in the dev tools console: https://github.com/jupyter/notebook/blob/master/notebook/static/notebook/js/kernelselector.js#L226-L227

  2. It then defaults to the first match using the language field, and emits the spec_changed.Kernel event: https://github.com/jupyter/notebook/blob/e498de6775b3de57f5ff827e562c179b17893064/notebook/static/notebook/js/kernelselector.js#L249

  3. The spec_changed.Kernel event is then consumed here: https://github.com/jupyter/notebook/blob/master/notebook/static/notebook/js/notebook.js#L345-L357

  4. A new session is started using the name from 2.: https://github.com/jupyter/notebook/blob/e498de6775b3de57f5ff827e562c179b17893064/notebook/static/notebook/js/notebook.js#L356

I might have missed some details but this is basically the outcome of stepping through the code in the dev tools.

@SylvainCorlay
Copy link
Member

Thanks for looking into this. What do you think is the cleanest thing to do?

It seems that jupyterlab pops up a dialog to select a kernel.

Or such a logic could be in the backend?

@jtpio
Copy link
Member Author

jtpio commented Jul 17, 2019

Finding a match based on the language field would certainly help with many of the common issues related to:

  • having "name": "python2" in the notebook metadata
  • conda named kernels: "name": "conda-env-foo-py"

And in some way it follows the logic from the classic notebook.

For the case where there is no match for a given language, for example trying to execute a C++ notebook on a Voila setup that only has Python kernels installed, this would still return a 500.

@jtpio
Copy link
Member Author

jtpio commented Jul 17, 2019

The last commits implement finding a spec matching the language field from the metadata, as well as sorting the matches by display name (cf notebook implementation).

If there is no language in the metadata, it defaults to python.

Copy link
Member

@maartenbreddels maartenbreddels left a comment

Choose a reason for hiding this comment

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

I like this approach, my remaining question is: should we do this in voila or nbconvert.

I'm ok with getting this into voila first, then see if we can upstream this.

voila/handler.py Outdated
]
if matches:
matches.sort(key=lambda name: all_kernel_specs[name]["spec"]["display_name"])
kernel_name = matches[0]
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if we have 0 matches, if we can have a custom template with a proper error msg and http error code: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes

If there are 1 or more matches, I think we should log a warning, so users are aware of it (I can imagine someone expecting it to run with a conda-env-kernel, which cannot be found, leading to surprises).

Copy link
Member Author

Choose a reason for hiding this comment

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

Agreed, a warning would definitely be useful to let the users know the kernel being used is not the one they expect.

Having a custom template with a proper error message is also a good idea, but maybe for a follow-up PR?

voila/handler.py Outdated
kernel_name = kernelspec.get('name', self.kernel_manager.default_kernel_name)

# Find a spec matching the language if the kernel name does not exist in the kernelspecs
all_kernel_specs = yield tornado.gen.maybe_future(self.kernel_spec_manager.get_all_specs())
Copy link
Member

Choose a reason for hiding this comment

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

Why is yield tornado.gen.maybe_future needed? The current implementation gives a plain dict, or can other implementations return a future?

Copy link
Member Author

Choose a reason for hiding this comment

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

The kernel spec manager could be a GatewayKernelSpecManager, in which case the maybe_future would be needed: https://github.com/jupyter/notebook/blob/e498de6775b3de57f5ff827e562c179b17893064/notebook/gateway/managers.py#L521

@jtpio
Copy link
Member Author

jtpio commented Jul 29, 2019

Not sure it was discussed before, but do we need to keep supporting Python 2?

@maartenbreddels
Copy link
Member

Not really, but we have it now, and it doesn't lead yet to any major hurdles. I'd say the incentive to keep supporting is decaying exponentially though.

@maartenbreddels maartenbreddels dismissed their stale review July 29, 2019 10:14

did it myself

voila/handler.py Outdated Show resolved Hide resolved
voila/handler.py Outdated Show resolved Hide resolved
@jtpio
Copy link
Member Author

jtpio commented Jul 29, 2019

Right, the hurdles are quite minimal for now.

@jtpio
Copy link
Member Author

jtpio commented Jul 29, 2019

@maartenbreddels this looks good to me.

Returning a 500 when there is no matching kernel is definitely useful.
The other case (showing a warning when 1+ matches found) could be added in a different PR.

@maartenbreddels maartenbreddels merged commit 34718a2 into voila-dashboards:master Jul 29, 2019
@jtpio jtpio deleted the default-kernel branch January 23, 2020 14:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Work with non-existing kernels
3 participants