2018-01-08 21:38:32 -06:00
|
|
|
;;; jupyter-kernel-manager.el --- Jupyter kernel manager -*- lexical-binding: t -*-
|
|
|
|
|
|
|
|
;; Copyright (C) 2018 Nathaniel Nicandro
|
|
|
|
|
2019-02-06 18:09:09 -06:00
|
|
|
;; Author: Nathaniel Nicandro <nathanielnicandro@gmail.com>
|
2018-01-08 21:38:32 -06:00
|
|
|
;; Created: 08 Jan 2018
|
2019-05-04 03:25:08 -05:00
|
|
|
;; Version: 0.8.0
|
2018-01-08 21:38:32 -06:00
|
|
|
|
|
|
|
;; This program is free software; you can redistribute it and/or
|
|
|
|
;; modify it under the terms of the GNU General Public License as
|
2019-05-31 09:44:39 -05:00
|
|
|
;; published by the Free Software Foundation; either version 3, or (at
|
2018-01-08 21:38:32 -06:00
|
|
|
;; your option) any later version.
|
|
|
|
|
|
|
|
;; This program is distributed in the hope that it will be useful, but
|
|
|
|
;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
;; General Public License for more details.
|
|
|
|
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
|
|
;; along with GNU Emacs; see the file COPYING. If not, write to the
|
|
|
|
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
;; Boston, MA 02111-1307, USA.
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
2019-02-06 18:09:09 -06:00
|
|
|
;; Manage a local Jupyter kernel process.
|
2018-01-08 21:38:32 -06:00
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
2018-01-04 23:03:18 -06:00
|
|
|
(require 'jupyter-base)
|
2019-06-28 20:02:00 -05:00
|
|
|
(require 'jupyter-env)
|
2018-01-08 21:38:32 -06:00
|
|
|
(require 'jupyter-messages)
|
2018-01-04 23:03:18 -06:00
|
|
|
(require 'jupyter-client)
|
2019-06-28 20:02:00 -05:00
|
|
|
(require 'jupyter-kernelspec)
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(eval-when-compile (require 'subr-x))
|
2018-01-04 23:03:18 -06:00
|
|
|
|
2018-10-25 13:30:25 -05:00
|
|
|
(declare-function ansi-color-apply "ansi-color" (string))
|
|
|
|
|
2018-01-08 21:38:32 -06:00
|
|
|
(defgroup jupyter-kernel-manager nil
|
|
|
|
"Jupyter kernel manager"
|
2018-01-18 22:43:52 -06:00
|
|
|
:group 'jupyter)
|
2018-01-08 21:38:32 -06:00
|
|
|
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
;;; `jupyter-kernel-process'
|
2018-10-16 13:28:45 -05:00
|
|
|
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(defclass jupyter-kernel-lifetime (jupyter-finalized-object)
|
|
|
|
()
|
|
|
|
:abstract t
|
|
|
|
:documentation "Trait to control the lifetime of a kernel.")
|
|
|
|
|
|
|
|
(cl-defmethod initialize-instance ((kernel jupyter-kernel-lifetime) &optional _slots)
|
|
|
|
(cl-call-next-method)
|
|
|
|
(jupyter-add-finalizer kernel
|
|
|
|
(lambda ()
|
|
|
|
(when (jupyter-kernel-alive-p kernel)
|
|
|
|
(jupyter-kill-kernel kernel)))))
|
|
|
|
|
|
|
|
(cl-defgeneric jupyter-kernel-alive-p ((kernel jupyter-kernel-lifetime))
|
|
|
|
"Return non-nil if KERNEL is alive.")
|
|
|
|
|
|
|
|
(cl-defgeneric jupyter-start-kernel ((kernel jupyter-kernel-lifetime) &rest args)
|
|
|
|
"Start KERNEL.")
|
|
|
|
|
|
|
|
(cl-defgeneric jupyter-kill-kernel ((kernel jupyter-kernel-lifetime))
|
|
|
|
"Tell the KERNEL to stop.")
|
|
|
|
|
|
|
|
(cl-defgeneric jupyter-kernel-died ((kernel jupyter-kernel-lifetime))
|
|
|
|
"Called when a KERNEL dies unexpectedly.")
|
|
|
|
|
2019-05-09 13:29:01 -05:00
|
|
|
(cl-defmethod jupyter-start-kernel :around ((kernel jupyter-kernel-lifetime) &rest _args)
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
"Error when KERNEL is already alive, otherwise call the next method."
|
2019-06-12 22:30:02 -05:00
|
|
|
(unless (jupyter-kernel-alive-p kernel)
|
|
|
|
(cl-call-next-method)))
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
|
|
|
|
(cl-defmethod jupyter-kill-kernel :around ((kernel jupyter-kernel-lifetime))
|
|
|
|
"Call the next method only when KERNEL is alive."
|
|
|
|
(when (jupyter-kernel-alive-p kernel)
|
|
|
|
(cl-call-next-method)))
|
|
|
|
|
|
|
|
(cl-defmethod jupyter-kernel-died ((_kernel jupyter-kernel-lifetime))
|
|
|
|
(ignore))
|
|
|
|
|
|
|
|
(defclass jupyter-meta-kernel (jupyter-kernel-lifetime)
|
|
|
|
((spec
|
|
|
|
:type cons
|
|
|
|
:initarg :spec
|
|
|
|
:documentation "The kernelspec for this kernel.
|
|
|
|
SPEC is in the same format as one of the elements returned by
|
|
|
|
`jupyter-find-kernelspecs'.")
|
2018-05-06 23:38:09 -05:00
|
|
|
(session
|
|
|
|
:type jupyter-session
|
|
|
|
:initarg :session
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
:documentation "The session used for communicating with the kernel.
|
|
|
|
This slot is set to an unbound state after a call to
|
|
|
|
`jupyter-kill-kernel'."))
|
|
|
|
:abstract t
|
|
|
|
:documentation "Partial representation of a Jupyter kernel.
|
|
|
|
|
|
|
|
Contains the kernelspec associated with the kernel and the
|
|
|
|
`jupyter-session' object used for communicating with the kernel
|
|
|
|
when it is alive.
|
|
|
|
|
|
|
|
Sub-classes must call `cl-next-method-method' in their
|
|
|
|
implementation of `jupyter-kill-kernel'.
|
|
|
|
|
|
|
|
A convenience method, `jupyter-kernel-name', is provided to
|
|
|
|
access the name of the kernelspec.")
|
|
|
|
|
2019-06-12 21:59:50 -05:00
|
|
|
(cl-defmethod jupyter-kill-kernel ((_kernel jupyter-meta-kernel))
|
|
|
|
(ignore))
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
|
|
|
|
(cl-defmethod jupyter-kernel-name ((kernel jupyter-meta-kernel))
|
|
|
|
"Return the name of KERNEL."
|
|
|
|
(car (oref kernel spec)))
|
|
|
|
|
|
|
|
(defclass jupyter-kernel-process (jupyter-meta-kernel)
|
|
|
|
((process
|
|
|
|
:type process
|
|
|
|
:documentation "The kernel process."))
|
|
|
|
:documentation "A Jupyter kernel process.
|
|
|
|
Starts a kernel process using `start-file-process'.
|
|
|
|
|
|
|
|
If the kernel was started on a remote host, ensure that local
|
|
|
|
tunnels are created when setting the session slot after the
|
|
|
|
kernel starts.")
|
|
|
|
|
|
|
|
(cl-defmethod jupyter-kernel-alive-p ((kernel jupyter-kernel-process))
|
|
|
|
(and (slot-boundp kernel 'process)
|
|
|
|
(process-live-p (oref kernel process))))
|
|
|
|
|
|
|
|
(cl-defmethod jupyter-start-kernel ((kernel jupyter-kernel-process) &rest args)
|
|
|
|
"Start a KERNEL process with ARGS."
|
|
|
|
(let ((name (jupyter-kernel-name kernel)))
|
2019-05-09 19:03:00 -05:00
|
|
|
(when jupyter--debug
|
2019-05-13 11:56:39 -05:00
|
|
|
(message "jupyter-start-kernel: default-directory = %s" default-directory)
|
2019-05-09 19:03:00 -05:00
|
|
|
(message "jupyter-start-kernel: Starting process with args \"%s\""
|
|
|
|
(mapconcat #'identity args " ")))
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(oset kernel process
|
|
|
|
(apply #'start-file-process
|
|
|
|
(format "jupyter-kernel-%s" name)
|
|
|
|
(generate-new-buffer
|
|
|
|
(format " *jupyter-kernel[%s]*" name))
|
|
|
|
(car args) (cdr args)))
|
|
|
|
(set-process-query-on-exit-flag
|
|
|
|
(oref kernel process) jupyter--debug)))
|
|
|
|
|
|
|
|
(defun jupyter--kernel-died-process-sentinel (kernel)
|
|
|
|
"Return a sentinel function calling KERNEL's `jupyter-kernel-died' method.
|
|
|
|
The method will be called when the process exits or receives a
|
|
|
|
fatal signal."
|
|
|
|
(cl-check-type kernel jupyter-kernel-lifetime)
|
|
|
|
(let ((ref (jupyter-weak-ref kernel)))
|
|
|
|
(lambda (process _)
|
|
|
|
(when (memq (process-status process) '(exit signal))
|
|
|
|
(when-let* ((kernel (jupyter-weak-ref-resolve ref)))
|
|
|
|
(jupyter-kernel-died kernel))))))
|
|
|
|
|
|
|
|
(cl-defmethod jupyter-start-kernel :after ((kernel jupyter-kernel-process) &rest _args)
|
|
|
|
(setf (process-sentinel (oref kernel process))
|
|
|
|
(jupyter--kernel-died-process-sentinel kernel)))
|
|
|
|
|
|
|
|
(cl-defmethod jupyter-kill-kernel ((kernel jupyter-kernel-process))
|
|
|
|
(with-slots (process) kernel
|
|
|
|
(delete-process process)
|
|
|
|
(when (buffer-live-p (process-buffer process))
|
|
|
|
(kill-buffer (process-buffer process))))
|
|
|
|
(cl-call-next-method))
|
|
|
|
|
|
|
|
(defclass jupyter-command-kernel (jupyter-kernel-process)
|
|
|
|
()
|
|
|
|
:documentation "A Jupyter kernel process using the \"jupyter kernel\" command.")
|
|
|
|
|
|
|
|
(cl-defmethod jupyter-start-kernel ((kernel jupyter-command-kernel) &rest args)
|
|
|
|
"Start KERNEL, passing ARGS as command line arguments to \"jupyter kernel\".
|
|
|
|
The --kernel argument of \"jupyter kernel\" is filled in with the
|
|
|
|
`jupyter-kernel-name' of KERNEL and passed as the first
|
|
|
|
argument of the process."
|
2019-05-16 20:23:29 -05:00
|
|
|
;; NOTE: On Windows, apparently the "jupyter kernel" command uses something
|
|
|
|
;; like an exec shell command to start the process which launches the kernel,
|
|
|
|
;; but exec like commands on Windows start a new process instead of replacing
|
|
|
|
;; the current one which results in the process we start here exiting after
|
2019-05-09 19:05:00 -05:00
|
|
|
;; the new process is launched. We call python directly to avoid this.
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(apply #'cl-call-next-method
|
2019-05-09 19:05:00 -05:00
|
|
|
kernel (jupyter-locate-python)
|
|
|
|
"-c" "from jupyter_client.kernelapp import main; main()"
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(format "--kernel=%s" (jupyter-kernel-name kernel))
|
|
|
|
args))
|
|
|
|
|
|
|
|
(cl-defmethod jupyter-start-kernel :after ((kernel jupyter-command-kernel) &rest _args)
|
|
|
|
"Set the session slot from KERNEL's process output."
|
|
|
|
(with-slots (process) kernel
|
|
|
|
(with-current-buffer (process-buffer process)
|
|
|
|
(jupyter-with-timeout
|
|
|
|
((format "Launching %s kernel process..." (jupyter-kernel-name kernel))
|
|
|
|
jupyter-long-timeout
|
|
|
|
(if (process-live-p process)
|
|
|
|
(error "\
|
|
|
|
`jupyter kernel` output did not show connection file within timeout")
|
|
|
|
(error "Kernel process exited:\n%s"
|
|
|
|
(ansi-color-apply (buffer-string)))))
|
|
|
|
(and (process-live-p process)
|
|
|
|
(goto-char (point-min))
|
|
|
|
(re-search-forward "Connection file: \\(.+\\)\n" nil t)))
|
|
|
|
(let* ((conn-file (match-string 1))
|
|
|
|
(remote (file-remote-p default-directory))
|
|
|
|
(conn-info (if remote (jupyter-tunnel-connection
|
|
|
|
(concat remote conn-file))
|
|
|
|
(jupyter-read-plist conn-file))))
|
|
|
|
(oset kernel session (jupyter-session
|
|
|
|
:conn-info conn-info
|
|
|
|
:key (plist-get conn-info :key)))))))
|
|
|
|
|
|
|
|
(defclass jupyter-spec-kernel (jupyter-kernel-process)
|
|
|
|
()
|
|
|
|
:documentation "A Jupyter kernel launched from a kernelspec.")
|
|
|
|
|
|
|
|
(defun jupyter--block-until-conn-file-access (atime kernel conn-file)
|
|
|
|
(with-slots (process) kernel
|
|
|
|
(jupyter-with-timeout
|
|
|
|
((format "Starting %s kernel process..." (jupyter-kernel-name kernel))
|
|
|
|
jupyter-long-timeout
|
|
|
|
;; If the process is still alive, punt farther down the line.
|
|
|
|
(unless (process-live-p process)
|
|
|
|
(error "Kernel process exited:\n%s"
|
|
|
|
(with-current-buffer (process-buffer process)
|
|
|
|
(ansi-color-apply (buffer-string))))))
|
|
|
|
(let ((attribs (file-attributes conn-file)))
|
|
|
|
;; `file-attributes' can potentially return nil, in this case
|
|
|
|
;; just assume it has read the connection file so that we can
|
|
|
|
;; know for sure it is not connected if it fails to respond to
|
|
|
|
;; any messages we send it.
|
|
|
|
(or (null attribs)
|
|
|
|
(not (equal atime (nth 4 attribs))))))))
|
|
|
|
|
2019-06-28 20:02:00 -05:00
|
|
|
(defun jupyter-write-connection-file (session obj)
|
|
|
|
"Write a connection file based on SESSION to `jupyter-runtime-directory'.
|
|
|
|
Return the path to the connection file.
|
|
|
|
|
|
|
|
Also register a finalizer on OBJ to delete the file when OBJ is
|
|
|
|
garbage collected. The file is also deleted when Emacs exits if
|
|
|
|
it hasn't been already."
|
|
|
|
(cl-check-type session jupyter-session)
|
|
|
|
(cl-check-type obj jupyter-finalized-object)
|
|
|
|
(make-directory jupyter-runtime-directory 'parents)
|
|
|
|
(let* ((temporary-file-directory jupyter-runtime-directory)
|
|
|
|
(json-encoding-pretty-print t)
|
|
|
|
(file (make-temp-file "emacs-kernel-" nil ".json"))
|
|
|
|
(kill-hook (lambda () (when (and file (file-exists-p file))
|
|
|
|
(delete-file file)))))
|
|
|
|
(add-hook 'kill-emacs-hook kill-hook)
|
|
|
|
(jupyter-add-finalizer obj
|
|
|
|
(lambda ()
|
|
|
|
(funcall kill-hook)
|
|
|
|
(remove-hook 'kill-emacs-hook kill-hook)))
|
|
|
|
(prog1 file
|
|
|
|
(with-temp-file file
|
|
|
|
(insert (json-encode-plist
|
|
|
|
(jupyter-session-conn-info session)))))))
|
|
|
|
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(cl-defmethod jupyter-start-kernel ((kernel jupyter-spec-kernel) &rest _args)
|
|
|
|
(cl-destructuring-bind (_name . (resource-dir . spec)) (oref kernel spec)
|
|
|
|
(let ((conn-file (jupyter-write-connection-file
|
|
|
|
(oref kernel session) kernel))
|
|
|
|
(process-environment
|
|
|
|
(append
|
|
|
|
;; The first entry takes precedence when duplicated
|
|
|
|
;; variables are found in `process-environment'
|
|
|
|
(cl-loop
|
|
|
|
for (k v) on (plist-get spec :env) by #'cddr
|
|
|
|
collect (format "%s=%s" (cl-subseq (symbol-name k) 1) v))
|
|
|
|
process-environment)))
|
|
|
|
(let ((atime (nth 4 (file-attributes conn-file))))
|
|
|
|
(apply #'cl-call-next-method
|
|
|
|
kernel (cl-loop
|
|
|
|
for arg in (append (plist-get spec :argv) nil)
|
|
|
|
if (equal arg "{connection_file}")
|
|
|
|
collect (file-local-name conn-file)
|
|
|
|
else if (equal arg "{resource_dir}")
|
|
|
|
collect (file-local-name resource-dir)
|
|
|
|
else collect arg))
|
|
|
|
;; Windows systems may not have good time resolution when retrieving
|
|
|
|
;; the last access time of a file so we don't bother with checking that
|
|
|
|
;; the kernel has read the connection file and leave it to the
|
|
|
|
;; downstream initialization to ensure that we can communicate with a
|
|
|
|
;; kernel.
|
|
|
|
(unless (memq system-type '(ms-dos windows-nt cygwin))
|
|
|
|
(jupyter--block-until-conn-file-access atime kernel conn-file))))))
|
|
|
|
|
2019-06-25 09:33:08 -05:00
|
|
|
(defvar jupyter--kernel-managers nil)
|
|
|
|
|
|
|
|
;; TODO: Move to generalize the kernel manager even more so it is independent
|
|
|
|
;; of a control channel and only relies mainly on the kernel and possibly some
|
|
|
|
;; other general object that can also be a control channel. This way we can
|
|
|
|
;; avoid this class.
|
|
|
|
(defclass jupyter-kernel-manager-base (jupyter-kernel-lifetime
|
|
|
|
jupyter-instance-tracker)
|
|
|
|
((tracking-symbol :initform 'jupyter--kernel-managers)))
|
|
|
|
|
|
|
|
(defclass jupyter-kernel-manager (jupyter-kernel-manager-base)
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
((kernel
|
|
|
|
:type jupyter-meta-kernel
|
|
|
|
:initarg :kernel
|
|
|
|
:documentation "The name of the kernel that is being managed.")
|
2018-01-04 23:03:18 -06:00
|
|
|
(control-channel
|
2019-06-28 20:04:00 -05:00
|
|
|
:type (or null jupyter-zmq-channel)
|
2018-01-04 23:03:18 -06:00
|
|
|
:initform nil
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
:documentation "The kernel's control channel.")))
|
2018-11-15 10:23:23 -06:00
|
|
|
|
2019-06-25 09:33:08 -05:00
|
|
|
(defun jupyter-kernel-managers ()
|
|
|
|
"Return a list of all `jupyter-kernel-manager' objects."
|
|
|
|
(jupyter-all-objects 'jupyter--kernel-managers))
|
|
|
|
|
2018-01-18 23:00:31 -06:00
|
|
|
(cl-defgeneric jupyter-make-client ((manager jupyter-kernel-manager) class &rest slots)
|
|
|
|
"Make a new client from CLASS connected to MANAGER's kernel.
|
|
|
|
SLOTS are the slots used to initialize the client with.")
|
|
|
|
|
2019-05-10 19:12:51 -05:00
|
|
|
(cl-defmethod jupyter-make-client :before (_manager class &rest _slots)
|
|
|
|
"Signal an error if CLASS is not a subclass of `jupyter-kernel-client'."
|
|
|
|
(unless (child-of-class-p class 'jupyter-kernel-client)
|
|
|
|
(signal 'wrong-type-argument (list '(subclass jupyter-kernel-client) class))))
|
|
|
|
|
|
|
|
(cl-defmethod jupyter-make-client (manager class &rest slots)
|
|
|
|
"Return an instance of CLASS using SLOTS and its manager slot set to MANAGER."
|
|
|
|
(let ((client (apply #'make-instance class slots)))
|
|
|
|
(prog1 client
|
|
|
|
(oset client manager manager))))
|
|
|
|
|
2019-06-28 20:03:00 -05:00
|
|
|
;; FIXME: Do not hard-code the communication layer
|
2019-05-10 19:12:51 -05:00
|
|
|
(cl-defmethod jupyter-make-client ((manager jupyter-kernel-manager) _class &rest _slots)
|
2018-01-04 23:03:18 -06:00
|
|
|
"Make a new client from CLASS connected to MANAGER's kernel.
|
|
|
|
CLASS should be a subclass of `jupyter-kernel-client', a new
|
2018-05-12 14:52:35 -05:00
|
|
|
instance of CLASS is initialized with SLOTS and configured to
|
2018-05-06 23:38:09 -05:00
|
|
|
connect to MANAGER's kernel."
|
2019-05-10 19:12:51 -05:00
|
|
|
(let ((client (cl-call-next-method)))
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(with-slots (kernel) manager
|
|
|
|
(prog1 client
|
2019-06-28 20:03:00 -05:00
|
|
|
(require 'jupyter-channel-ioloop-comm)
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
;; TODO: We can also have the manager hold the kcomm object and just
|
|
|
|
;; pass a single kcomm object to all clients using this manager since the
|
|
|
|
;; kcomm broadcasts event to all connected clients. This is more
|
|
|
|
;; efficient as it only uses one subprocess for every client connected to
|
|
|
|
;; a kernel.
|
2019-06-28 20:03:00 -05:00
|
|
|
(oset client kcomm (make-instance 'jupyter-channel-ioloop-comm))
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(jupyter-initialize-connection client (oref kernel session))))))
|
|
|
|
|
|
|
|
(cl-defmethod jupyter-start-kernel ((manager jupyter-kernel-manager) &rest args)
|
|
|
|
"Start MANAGER's kernel."
|
2018-01-22 18:35:25 -06:00
|
|
|
(unless (jupyter-kernel-alive-p manager)
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(with-slots (kernel) manager
|
|
|
|
(apply #'jupyter-start-kernel kernel args)
|
|
|
|
(jupyter-start-channels manager))))
|
|
|
|
|
|
|
|
(cl-defmethod jupyter-start-kernel :after ((manager jupyter-kernel-manager) &rest _args)
|
|
|
|
(with-slots (kernel) manager
|
|
|
|
(when (object-of-class-p kernel 'jupyter-kernel-process)
|
|
|
|
(add-function
|
|
|
|
:after (process-sentinel (oref kernel process))
|
|
|
|
(jupyter--kernel-died-process-sentinel manager)))))
|
2018-01-04 23:03:18 -06:00
|
|
|
|
|
|
|
(cl-defmethod jupyter-start-channels ((manager jupyter-kernel-manager))
|
|
|
|
"Start a control channel on MANAGER."
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(with-slots (kernel control-channel) manager
|
|
|
|
(if control-channel (jupyter-start-channel control-channel)
|
2018-11-12 22:25:53 -06:00
|
|
|
(cl-destructuring-bind (&key transport ip control_port &allow-other-keys)
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(jupyter-session-conn-info (oref kernel session))
|
2018-01-04 23:03:18 -06:00
|
|
|
(oset manager control-channel
|
2019-06-28 20:04:00 -05:00
|
|
|
(jupyter-zmq-channel
|
2018-02-03 00:02:33 -06:00
|
|
|
:type :control
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
:session (oref kernel session)
|
|
|
|
:endpoint (format "%s://%s:%d" transport ip control_port)))
|
|
|
|
(jupyter-start-channels manager)))))
|
2018-01-04 23:03:18 -06:00
|
|
|
|
|
|
|
(cl-defmethod jupyter-stop-channels ((manager jupyter-kernel-manager))
|
|
|
|
"Stop the control channel on MANAGER."
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(when-let* ((channel (oref manager control-channel)))
|
|
|
|
(jupyter-stop-channel channel)
|
|
|
|
(oset manager control-channel nil)))
|
2018-01-04 23:03:18 -06:00
|
|
|
|
2018-01-18 23:00:31 -06:00
|
|
|
(cl-defgeneric jupyter-shutdown-kernel ((manager jupyter-kernel-manager) &optional restart timeout)
|
2018-10-10 14:01:41 -05:00
|
|
|
"Shutdown MANAGER's kernel or restart instead if RESTART is non-nil.
|
2018-01-18 23:00:31 -06:00
|
|
|
Wait until TIMEOUT before forcibly shutting down the kernel.")
|
|
|
|
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(cl-defmethod jupyter-kill-kernel ((manager jupyter-kernel-manager))
|
|
|
|
(jupyter-shutdown-kernel manager))
|
|
|
|
|
2018-01-13 22:08:14 -06:00
|
|
|
(cl-defmethod jupyter-shutdown-kernel ((manager jupyter-kernel-manager) &optional restart timeout)
|
2018-01-18 23:00:31 -06:00
|
|
|
"Shutdown MANAGER's kernel with an optional RESTART.
|
|
|
|
If RESTART is non-nil, then restart the kernel after shutdown.
|
|
|
|
First send a shutdown request on the control channel to the
|
|
|
|
kernel. If the kernel has not shutdown within TIMEOUT, forcibly
|
|
|
|
kill the kernel subprocess. After shutdown the MANAGER's control
|
|
|
|
channel is stopped unless RESTART is non-nil."
|
2018-01-04 23:03:18 -06:00
|
|
|
(when (jupyter-kernel-alive-p manager)
|
2019-01-17 18:51:29 -06:00
|
|
|
;; FIXME: For some reason the control-channel is nil sometimes
|
|
|
|
(jupyter-start-channels manager)
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(with-slots (control-channel kernel) manager
|
|
|
|
(jupyter-send control-channel :shutdown-request
|
|
|
|
(jupyter-message-shutdown-request :restart restart))
|
2019-05-13 11:57:42 -05:00
|
|
|
;; FIXME: This doesn't work properly, the kernel sends a shutdown reply
|
|
|
|
;; but the process status cannot be determined correctly as it is still
|
|
|
|
;; considered alive. This is mainly when using the
|
|
|
|
;; `jupyter-command-kernel' and probably has to do with the fact that the
|
|
|
|
;; kernel is launched by a python process instead of being launched
|
|
|
|
;; directly as a process by Emacs.
|
2018-11-11 21:13:40 -06:00
|
|
|
(jupyter-with-timeout
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
((format "%s kernel shutting down..."
|
|
|
|
(jupyter-kernel-name kernel))
|
2018-11-12 00:17:17 -06:00
|
|
|
(or timeout jupyter-default-timeout)
|
|
|
|
(message "%s kernel did not shutdown by request"
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(jupyter-kernel-name kernel))
|
|
|
|
(jupyter-kill-kernel kernel))
|
2018-11-11 21:13:40 -06:00
|
|
|
(not (jupyter-kernel-alive-p manager)))
|
2018-01-13 22:08:14 -06:00
|
|
|
(if restart
|
|
|
|
(jupyter-start-kernel manager)
|
|
|
|
(jupyter-stop-channels manager)))))
|
2018-01-08 22:30:00 -06:00
|
|
|
|
2018-01-18 23:00:31 -06:00
|
|
|
(cl-defgeneric jupyter-interrupt-kernel ((manager jupyter-kernel-manager) &optional timeout)
|
|
|
|
"Interrupt MANAGER's kernel.
|
|
|
|
When the kernel has an interrupt mode of \"message\" send an
|
|
|
|
interrupt request and wait until TIMEOUT for a reply.")
|
|
|
|
|
2018-01-08 22:30:00 -06:00
|
|
|
(cl-defmethod jupyter-interrupt-kernel ((manager jupyter-kernel-manager) &optional timeout)
|
2018-01-18 23:00:31 -06:00
|
|
|
"Interrupt MANAGER's kernel.
|
|
|
|
If the kernel's interrupt mode is set to \"message\" send an
|
|
|
|
interrupt request on MANAGER's control channel and wait until
|
|
|
|
TIMEOUT for a reply. Otherwise if the kernel does not specify an
|
|
|
|
interrupt mode, send an interrupt signal to the kernel
|
|
|
|
subprocess."
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(when (jupyter-kernel-alive-p manager)
|
|
|
|
;; FIXME: For some reason the control-channel is nil sometimes
|
|
|
|
(jupyter-start-channels manager)
|
|
|
|
(with-slots (kernel) manager
|
|
|
|
(cl-destructuring-bind (_name _resource-dir . spec) (oref kernel spec)
|
|
|
|
(pcase (plist-get spec :interrupt_mode)
|
|
|
|
("message"
|
|
|
|
(with-slots (control-channel) manager
|
|
|
|
(jupyter-send control-channel :interrupt-request
|
|
|
|
(jupyter-message-interrupt-request))
|
|
|
|
(jupyter-with-timeout
|
2019-06-22 22:02:00 -05:00
|
|
|
((format "Interrupting %s kernel"
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(jupyter-kernel-name kernel))
|
|
|
|
(or timeout jupyter-default-timeout)
|
|
|
|
(message "No interrupt reply from kernel (%s)"
|
|
|
|
(jupyter-kernel-name kernel)))
|
|
|
|
(condition-case nil
|
|
|
|
(with-slots (session socket) control-channel
|
|
|
|
(jupyter-recv session socket zmq-DONTWAIT))
|
|
|
|
(zmq-EAGAIN nil)))))
|
2019-05-10 23:06:02 -05:00
|
|
|
(_
|
|
|
|
(if (object-of-class-p kernel 'jupyter-kernel-process)
|
|
|
|
(interrupt-process (oref kernel process) t)
|
|
|
|
(warn "Can't interrupt kernel"))))))))
|
2018-01-18 23:00:31 -06:00
|
|
|
|
2018-01-04 23:03:18 -06:00
|
|
|
(cl-defmethod jupyter-kernel-alive-p ((manager jupyter-kernel-manager))
|
2018-01-18 23:00:31 -06:00
|
|
|
"Is MANGER's kernel alive?"
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(and (slot-boundp manager 'kernel)
|
|
|
|
(jupyter-kernel-alive-p (oref manager kernel))))
|
2018-01-04 23:03:18 -06:00
|
|
|
|
2018-11-16 17:15:31 -06:00
|
|
|
(defun jupyter--error-if-no-kernel-info (client)
|
|
|
|
(jupyter-kernel-info client))
|
|
|
|
|
2019-06-28 20:02:00 -05:00
|
|
|
(cl-defun jupyter-create-connection-info (&key
|
|
|
|
(kernel-name "python")
|
|
|
|
(transport "tcp")
|
|
|
|
(ip "127.0.0.1")
|
|
|
|
(signature-scheme "hmac-sha256")
|
|
|
|
(key (jupyter-new-uuid))
|
|
|
|
(hb-port 0)
|
|
|
|
(stdin-port 0)
|
|
|
|
(control-port 0)
|
|
|
|
(shell-port 0)
|
|
|
|
(iopub-port 0))
|
|
|
|
"Create a connection info plist used to connect to a kernel.
|
|
|
|
|
|
|
|
The plist has the standard keys found in the jupyter spec. See
|
|
|
|
http://jupyter-client.readthedocs.io/en/latest/kernels.html#connection-files.
|
|
|
|
A port number of 0 for a channel means to use a randomly assigned
|
|
|
|
port for that channel."
|
|
|
|
(unless (or (= (length key) 0)
|
|
|
|
(equal signature-scheme "hmac-sha256"))
|
|
|
|
(error "Only hmac-sha256 signing is currently supported"))
|
|
|
|
(append
|
|
|
|
(list :kernel_name kernel-name
|
|
|
|
:transport transport
|
|
|
|
:ip ip)
|
|
|
|
(when (> (length key) 0)
|
|
|
|
(list :signature_scheme signature-scheme
|
|
|
|
:key key))
|
|
|
|
(cl-loop
|
|
|
|
with sock = (zmq-socket (zmq-current-context) zmq-REP)
|
|
|
|
with addr = (concat transport "://" ip)
|
|
|
|
for (channel . port) in `((:hb_port . ,hb-port)
|
|
|
|
(:stdin_port . ,stdin-port)
|
|
|
|
(:control_port . ,control-port)
|
|
|
|
(:shell_port . ,shell-port)
|
|
|
|
(:iopub_port . ,iopub-port))
|
|
|
|
collect channel and
|
|
|
|
if (= port 0) do (setq port (zmq-bind-to-random-port sock addr))
|
|
|
|
and collect port else collect port
|
|
|
|
finally
|
|
|
|
(zmq-socket-set sock zmq-LINGER 0)
|
|
|
|
(zmq-close sock))))
|
|
|
|
|
2018-01-06 16:42:55 -06:00
|
|
|
(defun jupyter-start-new-kernel (kernel-name &optional client-class)
|
2018-01-08 18:11:08 -06:00
|
|
|
"Start a managed Jupyter kernel.
|
|
|
|
KERNEL-NAME is the name of the kernel to start. It can also be
|
|
|
|
the prefix of a valid kernel name, in which case the first kernel
|
2018-02-12 11:03:41 -06:00
|
|
|
in `jupyter-available-kernelspecs' that has KERNEL-NAME as a
|
|
|
|
prefix will be used. Optional argument CLIENT-CLASS is a subclass
|
|
|
|
of `jupyer-kernel-client' and will be used to initialize a new
|
2019-02-06 17:46:14 -06:00
|
|
|
client connected to the kernel. CLIENT-CLASS defaults to the
|
|
|
|
symbol `jupyter-kernel-client'.
|
|
|
|
|
|
|
|
Return a list (KM KC) where KM is the kernel manager managing the
|
|
|
|
lifetime of the kernel subprocess. KC is a new client connected
|
|
|
|
to the kernel whose class is CLIENT-CLASS. The client is
|
|
|
|
connected to the kernel with all channels listening for messages
|
|
|
|
and the heartbeat channel unpaused. Note that the client's
|
|
|
|
`manager' slot will also be set to the kernel manager instance,
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
see `jupyter-make-client'.
|
|
|
|
|
|
|
|
Note, if `default-directory' is a remote directory, a kernel will
|
|
|
|
start on the remote host by using the \"jupyter kernel\" shell
|
|
|
|
command on the host."
|
2018-05-06 10:51:18 -05:00
|
|
|
(or client-class (setq client-class 'jupyter-kernel-client))
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
;; TODO: Replace with
|
|
|
|
;; (cl-assert (child-of-class-p client-class 'jupyter-kernel-client))
|
2019-04-08 11:35:00 -05:00
|
|
|
(jupyter-error-if-not-client-class-p client-class)
|
Refactor of `jupyter-kernel-manager.el`
This refactor implements a new class hierarchy to manage the lifetime of a
Jupyter kernel. The first node in this hierarchy is the
`jupyter-kernel-lifetime` class which defines a set of methods to manage the
lifetime of a kernel. An object that inherits from `jupyter-kernel-lifetime` is
stating that it has an association with a kernel and can be used to manage the
lifetime of the associated kernel.
The `jupyter-meta-kernel` class inherits from `jupyter-kernel-lifetime` and
mainly defines a `spec` slot used to hold the `kernelspec` from which a command
can be constructed to start a kernel and a `session` slot used to hold the
`jupyter-session` object that clients can use to establish communication with a
kernel once its live. Concrete classes that actually launch kernels are
intended to inherit from this class and use its slots.
`jupyter-kernel-process` manages the lifetime of a kernel started as a process
using the function `start-file-process`, `jupyter-command-kernel` calls the
`jupyter kernel` shell command to start a kernel, finally `jupyter-spec-kernel`
uses the `spec` slot to construct a shell command to start a kernel.
A `jupyter-kernel-manager` now consists of a `kernel` slot that holds a
`jupyter-meta-kernel` and a `control-channel` slot and inherits from
`jupyter-kernel-lifetime`. The `jupyter-kernel-lifetime` methods of the manager
just defer to those of `kernel` while also taking into account the
`control-channel`.
* jupyter-base.el (jupyter-write-connection-file): New function.
* jupyter-channel-ioloop.el
(jupyter-channel-ioloop-add-start-channel-event): Remove `sleep-for` call.
The startup message is not so important anymore.
* jupyter-client.el (jupyter-wait-until-startup: New function.
* jupyter-kernel-manager.el (jupyter-kernel-lifetime)
(jupyter-kernel, jupyter-kernel-process, jupyter-command-kernel)
(jupyter-spec-kernel): New classes.
(jupyter-kernel-manager): Inherit from jupyter-kernel-lifetime only and
implement its methods.
(jupyter-kernel-manager--cleanup, jupyter-kernel-managers)
(jupyter-delete-all-kernels, jupyter--kernel-sentinel)
(jupyter--start-kernel): Remove and remove related, their functionality has
been generalized in the new classes.
(jupyter-interrupt-kernel, jupyter-shutdown-kernel)
(jupyter-start-channels, jupyter-start-kernel, jupyter-kernel-alive-p)
(jupyter-kill-kernel): Refactor and implement to use the new class hierarchy.
* test/jupyter-test.el: Refactor tests to account for changes.
(jupyter-write-connect-file, jupyter-command-kernel): New tests.
* jupyter-kernelspec.el (jupyter-guess-kernelspec): New function.
2019-05-09 08:31:00 -05:00
|
|
|
(let* ((spec (jupyter-guess-kernelspec kernel-name))
|
|
|
|
(kernel (if (file-remote-p default-directory)
|
|
|
|
(jupyter-command-kernel :spec spec)
|
|
|
|
(let* ((key (jupyter-new-uuid))
|
|
|
|
(conn-info (jupyter-create-connection-info
|
|
|
|
:kernel-name kernel-name
|
|
|
|
:key key)))
|
|
|
|
(jupyter-spec-kernel
|
|
|
|
:spec spec
|
|
|
|
;; TODO: Convert `jupyter-session' into an object and
|
|
|
|
;; only require `conn-info'.
|
|
|
|
:session (jupyter-session
|
|
|
|
:key key
|
|
|
|
:conn-info conn-info)))))
|
|
|
|
(manager (jupyter-kernel-manager :kernel kernel)))
|
|
|
|
(jupyter-start-kernel manager)
|
|
|
|
(let ((client (jupyter-make-client manager client-class)))
|
|
|
|
(jupyter-start-channels client)
|
|
|
|
(jupyter--error-if-no-kernel-info client)
|
|
|
|
;; Un-pause the hearbeat after the kernel starts since waiting for
|
|
|
|
;; it to start may cause the heartbeat to think the kernel died.
|
|
|
|
(jupyter-hb-unpause client)
|
|
|
|
(list manager client))))
|
2018-01-06 16:42:55 -06:00
|
|
|
|
2018-01-04 23:03:18 -06:00
|
|
|
(provide 'jupyter-kernel-manager)
|
2018-01-08 21:38:32 -06:00
|
|
|
|
|
|
|
;;; jupyter-kernel-manager.el ends here
|