forked from emacs-jupyter/jupyter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
jupyter-kernel-manager.el
164 lines (123 loc) · 5.69 KB
/
jupyter-kernel-manager.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
;;; jupyter-kernel-manager.el --- Jupyter kernel manager -*- lexical-binding: t -*-
;; Copyright (C) 2018-2020 Nathaniel Nicandro
;; Author: Nathaniel Nicandro <nathanielnicandro@gmail.com>
;; Created: 08 Jan 2018
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 3, or (at
;; 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:
;; Define interfaces for managing kernels.
;;; Code:
(require 'jupyter-base)
(require 'jupyter-env)
(require 'jupyter-messages)
(require 'jupyter-client)
(require 'jupyter-kernelspec)
(require 'jupyter-channel)
(eval-when-compile (require 'subr-x))
(declare-function ansi-color-apply "ansi-color" (string))
(defgroup jupyter-kernel-manager nil
"Jupyter kernel manager"
:group 'jupyter)
;;; `jupyter-kernel-lifetime'
(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 () (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.")
(cl-defmethod jupyter-start-kernel :around ((kernel jupyter-kernel-lifetime) &rest _args)
"Error when KERNEL is already alive, otherwise call the next method."
(unless (jupyter-kernel-alive-p kernel)
(cl-call-next-method)))
(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))
;;; `jupyter-kernel'
(defclass jupyter-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'.")
(session
:type jupyter-session
:initarg :session
:documentation "The session used for communicating with the 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.")
(cl-defmethod jupyter-kill-kernel ((_kernel jupyter-kernel))
(ignore))
(cl-defmethod jupyter-kernel-name ((kernel jupyter-kernel))
"Return the name of KERNEL."
(car (oref kernel spec)))
;;; `jupyter-kernel-manager'
(defvar jupyter--kernel-managers nil)
(defclass jupyter-kernel-manager (jupyter-kernel-lifetime
jupyter-instance-tracker)
((tracking-symbol :initform 'jupyter--kernel-managers)
(kernel
:type jupyter-kernel
:initarg :kernel
:documentation "The kernel that is being managed."))
:abstract t)
(defun jupyter-kernel-managers ()
"Return a list of all `jupyter-kernel-manager' objects."
(jupyter-all-objects 'jupyter--kernel-managers))
(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.")
(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))))
(cl-defmethod jupyter-start-kernel ((manager jupyter-kernel-manager) &rest args)
"Start MANAGER's kernel."
(apply #'jupyter-start-kernel (oref manager kernel) args))
(cl-defgeneric jupyter-shutdown-kernel ((manager jupyter-kernel-manager) &rest args)
"Shutdown MANAGER's kernel or restart instead if RESTART is non-nil.
Wait until TIMEOUT before forcibly shutting down the kernel.")
(cl-defgeneric jupyter-interrupt-kernel ((manager jupyter-kernel-manager) &rest args)
"Interrupt MANAGER's kernel.
When the kernel has an interrupt mode of \"message\" send an
interrupt request and wait until TIMEOUT for a reply.")
(cl-defmethod jupyter-kernel-alive-p ((manager jupyter-kernel-manager))
"Is MANGER's kernel alive?"
(and (slot-boundp manager 'kernel)
(jupyter-kernel-alive-p (oref manager kernel))))
(provide 'jupyter-kernel-manager)
;;; jupyter-kernel-manager.el ends here