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

New KernelLauncher API for kernel discovery system #308

Closed
wants to merge 55 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
d67c82a
Make a start on kernel discovery framework
takluyver May 18, 2017
6406393
Undeprecate KernelManager.kernel_cmd, add extra_env
takluyver May 19, 2017
6ca3ec7
Use entry points to find kernel finders
takluyver Jul 26, 2017
dddda32
Tests for kernel discovery machinery
takluyver Jul 26, 2017
1509dac
Use older ABC definition style with metaclass
takluyver Jul 26, 2017
38ccbdc
Rename kernel finders -> kernel providers
takluyver Oct 9, 2017
3c09a57
Missed a rename
takluyver Oct 9, 2017
e92e5c1
Add dependency on entrypoints
takluyver Oct 9, 2017
aad40cb
Document new kernel providers system
takluyver Oct 10, 2017
c09b8ac
Break it up a bit with a subheading
takluyver Oct 10, 2017
cc8176b
Update doc with Carol's suggestions
takluyver Oct 10, 2017
1f74c5f
Fix variable name
takluyver Oct 10, 2017
8f7a865
Merge pull request #261 from takluyver/discovery
takluyver Oct 16, 2017
16608fc
Fix typo in documentation.
Oct 19, 2017
4776e8c
Merge pull request #299 from didiercrunch/patch-1
takluyver Oct 19, 2017
936dfe0
Updated URL for Jupyter Kernels
frelon Nov 1, 2017
2822872
Merge pull request #300 from frelon/patch-1
blink1073 Nov 1, 2017
aca5f70
tornado 5 support
minrk Nov 10, 2017
172d6cd
Configure interrupt mode via spec.
filmor Sep 21, 2017
f0e33ba
Update docs.
filmor Oct 30, 2017
21b9569
Bump protocol version.
filmor Nov 6, 2017
6674afa
disable pyzmq zero-copy optimizations during session tests
minrk Nov 13, 2017
7a0278a
Merge pull request #304 from minrk/tornado-5
takluyver Nov 13, 2017
e2772bd
Fix signal name.
filmor Nov 13, 2017
0d7d00f
Merge pull request #294 from filmor/interrupt
takluyver Nov 13, 2017
250178f
Add 'jupyter kernel' command
takluyver Feb 10, 2017
9359b33
Use native kernel by default
takluyver Dec 11, 2017
ae03ddd
More description
takluyver Dec 11, 2017
7e6d167
Add test of 'jupyter kernel'
takluyver Dec 11, 2017
28f908f
Workaround lack of timeout on Py2
takluyver Dec 11, 2017
aa8b184
Restrict to older pytest on Python 3.3
takluyver Dec 11, 2017
5291f94
Another go at fixing pytest dependency on Python 3.3
takluyver Dec 11, 2017
7bbb56d
Merge pull request #240 from takluyver/jupyter-kernel-cmd
minrk Dec 12, 2017
e952b83
First go at new launcher APIs
takluyver Nov 29, 2017
b6050cc
Integrate launcher classes into the discovery API
takluyver Nov 30, 2017
fd2631e
Fix up discovery tests
takluyver Nov 30, 2017
2955d35
Start making new Manager and Client interfaces
takluyver Dec 4, 2017
fd5f400
Start recombining launcher interface with manager
takluyver Dec 5, 2017
4b93592
Rename async_launcher -> async_manager
takluyver Dec 5, 2017
56b0b49
Bring async manager in line with synchronous one
takluyver Dec 5, 2017
7ca1070
Move ioloop based client to new module, improve
takluyver Dec 5, 2017
64b47a6
Managers start kernel on creation
takluyver Dec 5, 2017
673dda7
Clarify docstring
takluyver Dec 5, 2017
5c70b56
Fix use of interrupt event for Windows, close stdin pipe
takluyver Dec 5, 2017
910020c
No TimeoutExpired on Py2
takluyver Dec 5, 2017
9c6f55f
Drop Python 3.3 tests from Travis
takluyver Dec 5, 2017
626b832
Misc Python 2 fixes
takluyver Dec 5, 2017
bce030c
Ignore asyncio tests on Python 2
takluyver Dec 5, 2017
a550bb4
Fix getting messages from correct socket
takluyver Dec 6, 2017
eebeca4
Copy client tests for KernelClient2
takluyver Dec 6, 2017
07ba2ea
Add tests for running a KernelClient in a separate thread
takluyver Dec 6, 2017
f9d8493
Add relaunch() method to kernel manager classes
takluyver Dec 11, 2017
8c6d5ee
Add new restarter machinery
takluyver Dec 11, 2017
01e88a8
Update 'jupyter kernel' command to use new APIs
takluyver Dec 13, 2017
ca78b7e
Don't rely on KernelManager having a log attribute
takluyver Feb 13, 2018
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
10 changes: 7 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
language: python
python:
- "nightly"
- '3.6-dev'
- 3.6
- 3.5
- 3.4
- 3.3
- 2.7
sudo: false
install:
- pip install --upgrade setuptools pip
- pip install --upgrade --pre -e .[test] pytest-cov pytest-warnings codecov
script:
- py.test --cov jupyter_client jupyter_client
- |
if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
py.test --cov jupyter_client jupyter_client --ignore jupyter_client/tests/test_async_manager.py
else
py.test --cov jupyter_client jupyter_client
fi
after_success:
- codecov
matrix:
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ with Jupyter kernels.

kernels
wrapperkernels
kernel_providers

.. toctree::
:maxdepth: 2
Expand Down
156 changes: 156 additions & 0 deletions docs/kernel_providers.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
================
Kernel providers
================

.. note::
This is a new interface under development, and may still change.
Not all Jupyter applications use this yet.
See :ref:`kernelspecs` for the established way of discovering kernel types.

Creating a kernel provider
==========================

By writing a kernel provider, you can extend how Jupyter applications discover
and start kernels. For example, you could find kernels in an environment system
like conda, or kernels on remote systems which you can access.

To write a kernel provider, subclass
:class:`jupyter_client.discovery.KernelProviderBase`, giving your provider an ID
and overriding two methods.

.. class:: MyKernelProvider

.. attribute:: id

A short string identifying this provider. Cannot contain forward slash
(``/``).

.. method:: find_kernels()

Get the available kernel types this provider knows about.
Return an iterable of 2-tuples: (name, attributes).
*name* is a short string identifying the kernel type.
*attributes* is a dictionary with information to allow selecting a kernel.

.. method:: make_manager(name)

Prepare and return a :class:`~jupyter_client.KernelManager` instance
ready to start a new kernel instance of the type identified by *name*.
The input will be one of the names given by :meth:`find_kernels`.

For example, imagine we want to tell Jupyter about kernels for a new language
called *oblong*::

# oblong_provider.py
from jupyter_client.discovery import KernelProviderBase
from jupyter_client import KernelManager
from shutil import which

class OblongKernelProvider(KernelProviderBase):
id = 'oblong'

def find_kernels(self):
if not which('oblong-kernel'):
return # Check it's available

# Two variants - for a real kernel, these could be something like
# different conda environments.
yield 'standard', {
'display_name': 'Oblong (standard)',
'language': {'name': 'oblong'},
'argv': ['oblong-kernel'],
}
yield 'rounded', {
'display_name': 'Oblong (rounded)',
'language': {'name': 'oblong'},
'argv': ['oblong-kernel'],
}

def make_manager(self, name):
if name == 'standard':
return KernelManager(kernel_cmd=['oblong-kernel'],
extra_env={'ROUNDED': '0'})
elif name == 'rounded':
return KernelManager(kernel_cmd=['oblong-kernel'],
extra_env={'ROUNDED': '1'})
else:
raise ValueError("Unknown kernel %s" % name)

You would then register this with an *entry point*. In your ``setup.py``, put
something like this::

setup(...
entry_points = {
'jupyter_client.kernel_providers' : [
# The name before the '=' should match the id attribute
'oblong = oblong_provider:OblongKernelProvider',
]
})

Finding kernel types
====================

To find and start kernels in client code, use
:class:`jupyter_client.discovery.KernelFinder`. This uses multiple kernel
providers to find available kernels. Like a kernel provider, it has methods
``find_kernels`` and ``make_manager``. The kernel names it works
with have the provider ID as a prefix, e.g. ``oblong/rounded`` (from the example
above).

::

from jupyter_client.discovery import KernelFinder
kf = KernelFinder.from_entrypoints()

## Find available kernel types
for name, attributes in kf.find_kernels():
print(name, ':', attributes['display_name'])
# oblong/standard : Oblong (standard)
# oblong/rounded : Oblong(rounded)
# ...

## Start a kernel by name
manager = kf.make_manager('oblong/standard')
manager.start_kernel()

.. module:: jupyter_client.discovery

.. autoclass:: KernelFinder

.. automethod:: from_entrypoints

.. automethod:: find_kernels

.. automethod:: make_manager

Kernel providers included in ``jupyter_client``
===============================================

``jupyter_client`` includes two kernel providers:

.. autoclass:: KernelSpecProvider

.. seealso:: :ref:`kernelspecs`

.. autoclass:: IPykernelProvider

Glossary
========

Kernel instance
A running kernel, a process which can accept ZMQ connections from frontends.
Its state includes a namespace and an execution counter.

Kernel type
The software to run a kernel instance, along with the context in which a
kernel starts. One kernel type allows starting multiple, initially similar
kernel instances. For instance, one kernel type may be associated with one
conda environment containing ``ipykernel``. The same kernel software in
another environment would be a different kernel type. Another software package
for a kernel, such as ``IRkernel``, would also be a different kernel type.

Kernel provider
A Python class to discover kernel types and allow a client to start instances
of those kernel types. For instance, one kernel provider might find conda
environments containing ``ipykernel`` and allow starting kernel instances in
these environments.
9 changes: 8 additions & 1 deletion docs/kernels.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Making kernels for Jupyter

A 'kernel' is a program that runs and introspects the user's code. IPython
includes a kernel for Python code, and people have written kernels for
`several other languages <https://github.com/ipython/ipython/wiki/IPython-kernels-for-other-languages>`_.
`several other languages <https://github.com/jupyter/jupyter/wiki/Jupyter-kernels>`_.

When Jupyter starts a kernel, it passes it a connection file. This specifies
how to set up communications with the frontend.
Expand Down Expand Up @@ -132,6 +132,13 @@ JSON serialised dictionary containing the following keys and values:
is found, a kernel with a matching `language` will be used.
This allows a notebook written on any Python or Julia kernel to be properly associated
with the user's Python or Julia kernel, even if they aren't listed under the same name as the author's.
- **interrupt_mode** (optional): May be either ``signal`` or ``message`` and
specifies how a client is supposed to interrupt cell execution on this kernel,
either by sending an interrupt ``signal`` via the operating system's
signalling facilities (e.g. `SIGINT` on POSIX systems), or by sending an
``interrupt_request`` message on the control channel (see
:ref:`msging_interrupt`). If this is not specified
the client will default to ``signal`` mode.
- **env** (optional): A dictionary of environment variables to set for the kernel.
These will be added to the current environment variables before the kernel is
started.
Expand Down
23 changes: 22 additions & 1 deletion docs/messaging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Versioning

The Jupyter message specification is versioned independently of the packages
that use it.
The current version of the specification is 5.2.
The current version of the specification is 5.3.

.. note::
*New in* and *Changed in* messages in this document refer to versions of the
Expand Down Expand Up @@ -959,6 +959,27 @@ Message type: ``shutdown_reply``::
socket, they simply send a forceful process termination signal, since a dead
process is unlikely to respond in any useful way to messages.

.. _msging_interrupt:

Kernel interrupt
----------------

In case a kernel can not catch operating system interrupt signals (e.g. the used
runtime handles signals and does not allow a user program to define a callback),
a kernel can choose to be notified using a message instead. For this to work,
the kernels kernelspec must set `interrupt_mode` to ``message``. An interruption
will then result in the following message on the `control` channel:

Message type: ``interrupt_request``::

content = {}

Message type: ``interrupt_reply``::

content = {}

.. versionadded:: 5.3


Messages on the IOPub (PUB/SUB) channel
=======================================
Expand Down
2 changes: 1 addition & 1 deletion jupyter_client/_version.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
version_info = (5, 1, 0)
__version__ = '.'.join(map(str, version_info))

protocol_version_info = (5, 2)
protocol_version_info = (5, 3)
protocol_version = "%i.%i" % protocol_version_info
Loading