mirror of
https://github.com/vale981/emacs-jupyter
synced 2025-03-05 23:41:38 -05:00
Convert jupyter-kernel
into a method
* jupyter-kernel-process.el * jupyter-server-kernel.el (jupyter-kernel): New method. * jupyter-kernel.el (jupyter-kernel): Convert. Load files that handle keywords and re-dispatch when ARGS does not have any connection info. Document behavior. * test/test-helper.el (jupyter-test-with-kernel-client) * jupyter-server.el (jupyter-connect-server-repl) (jupyter-server-start-new-kernel): Use `jupyter-kernel`.
This commit is contained in:
parent
a33231b4d3
commit
f2c9d5fb25
5 changed files with 83 additions and 74 deletions
|
@ -48,36 +48,35 @@
|
|||
(cl-call-next-method))))
|
||||
|
||||
(defun jupyter-kernel-process (&rest args)
|
||||
"Return a representation of a kernel process.
|
||||
Return a `jupyter-kernel-process' with ARGS being the slot values
|
||||
used for initialization."
|
||||
(let ((kernel (apply #'make-jupyter-kernel-process args))
|
||||
(session (pcase (plist-get args :session)
|
||||
((and (pred stringp) (pred file-exists-p) `,conn-file)
|
||||
(let ((conn-info (jupyter-read-connection conn-file)))
|
||||
(jupyter-session
|
||||
:conn-info conn-info
|
||||
:key (plist-get conn-info :key))))
|
||||
((and (pred jupyter-session-p) `,session)
|
||||
session)
|
||||
(_
|
||||
(prog1 (jupyter-session-with-random-ports)
|
||||
;; This is here for stability when running
|
||||
;; the tests. Sometimes the kernel ports are
|
||||
;; not set up fast enough due to the hack
|
||||
;; done in
|
||||
;; `jupyter-session-with-random-ports'. The
|
||||
;; effect seems to be messages that are sent
|
||||
;; but never received by the kernel.
|
||||
(sit-for 0.2)))))
|
||||
(spec (pcase (plist-get args :spec)
|
||||
((and (pred stringp) `,name)
|
||||
(or (jupyter-guess-kernelspec name)
|
||||
(error "No kernelspec matching name (%s)" name)))
|
||||
(`,spec spec))))
|
||||
(setf (jupyter-kernel-session kernel) session)
|
||||
(setf (jupyter-kernel-spec kernel) spec)
|
||||
kernel))
|
||||
"Return a `jupyter-kernel-process' initialized with ARGS."
|
||||
(apply #'make-jupyter-kernel-process args))
|
||||
|
||||
(cl-defmethod jupyter-kernel :extra "process" (&rest args)
|
||||
"Return a representation of a kernel based on an Emacs process.
|
||||
If ARGS contains a :spec key, return a `jupyter-kernel-process'
|
||||
initialized using ARGS. If the value is the name of a
|
||||
kernelspec, the returned kernel's spec slot will be set to the
|
||||
corresponding `jupyter-kernelspec'. The session of the returned
|
||||
kernel will be initialized with the return value of
|
||||
`jupyter-session-with-random-ports'.
|
||||
|
||||
Call the next method if ARGS does not contain :spec."
|
||||
(let ((spec (plist-get args :spec)))
|
||||
(if (not spec) (cl-call-next-method)
|
||||
(when (stringp spec)
|
||||
(plist-put args :spec
|
||||
(or (jupyter-guess-kernelspec spec)
|
||||
(error "No kernelspec matching name (%s)" spec))))
|
||||
(apply #'jupyter-kernel-process
|
||||
:session (prog1 (jupyter-session-with-random-ports)
|
||||
;; This is here for stability when running the
|
||||
;; tests. Sometimes the kernel ports are not
|
||||
;; set up fast enough due to the hack done in
|
||||
;; `jupyter-session-with-random-ports'. The
|
||||
;; effect seems to be messages that are sent but
|
||||
;; never received by the kernel.
|
||||
(sit-for 0.2))
|
||||
args))))
|
||||
|
||||
;;; Client connection
|
||||
|
||||
|
|
|
@ -59,20 +59,34 @@
|
|||
"Return non-nil if KERNEL has been launched."
|
||||
(and (jupyter-kernel-session kernel) t))
|
||||
|
||||
(defun jupyter-kernel (&rest args)
|
||||
(cl-defgeneric jupyter-kernel (&rest args)
|
||||
"Return a kernel constructed from ARGS.
|
||||
ARGS are keyword arguments."
|
||||
(if (plist-get args :conn-info)
|
||||
(make-jupyter-kernel
|
||||
:session (let ((conn-info
|
||||
(if (stringp (plist-get args :conn-info))
|
||||
(jupyter-read-connection
|
||||
(plist-get args :conn-file))
|
||||
(plist-get args :conn-info))))
|
||||
(jupyter-session
|
||||
:conn-info conn-info
|
||||
:key (plist-get conn-info :key))))
|
||||
(error "Implement")))
|
||||
ARGS are keyword arguments used to initialize the returned
|
||||
kernel.
|
||||
|
||||
The default implementation will return a `jupyter-kernel' with a
|
||||
session initialized from the value of :conn-info in ARGS, either
|
||||
the name of a connection file to read or itself a connection
|
||||
property list (see `jupyter-read-connection'). A client can
|
||||
connect to the returned kernel using `jupyter-client'.
|
||||
|
||||
This method can be extended with extra primary methods for the
|
||||
purposes of handling different forms of ARGS that do not just
|
||||
need the default behavior."
|
||||
(let ((conn-info (plist-get args :conn-info)))
|
||||
(cond
|
||||
(conn-info
|
||||
(when (stringp conn-info)
|
||||
(setq conn-info (jupyter-read-connection conn-info)))
|
||||
(apply #'make-jupyter-kernel
|
||||
:session (jupyter-session
|
||||
:conn-info conn-info
|
||||
:key (plist-get conn-info :key))
|
||||
(cl-loop
|
||||
for (k v) on args by #'cddr
|
||||
unless (eq k :conn-info) collect k and collect v)))
|
||||
(t
|
||||
(cl-call-next-method)))))
|
||||
|
||||
;;; Kernel management
|
||||
|
||||
|
|
|
@ -156,25 +156,29 @@ The kernelspecs are returned in the same form as returned by
|
|||
(cl-call-next-method))))
|
||||
|
||||
(defun jupyter-server-kernel (&rest args)
|
||||
"Return a representation of a kernel on a Jupyter server.
|
||||
ARGS is a property list used to initialize the returned
|
||||
`jupyter-server-kernel'. The following keys of ARGS are handled
|
||||
specially:
|
||||
|
||||
- If :spec is present and it is the name of a kernelspec, then
|
||||
the SPEC of the returned kernel will be the one associated
|
||||
with that name on the server."
|
||||
(cl-assert (jupyter-server-p (plist-get args :server)))
|
||||
(when (stringp (plist-get args :spec))
|
||||
(let ((server (plist-get args :server))
|
||||
(name (plist-get args :spec)))
|
||||
(plist-put args :spec
|
||||
(or (jupyter-guess-kernelspec
|
||||
name (jupyter-server-kernelspecs server))
|
||||
(error "No kernelspec matching %s @ %s" name
|
||||
(oref server url))))))
|
||||
"Return a `jupyter-server-kernel' initialized with ARGS."
|
||||
(apply #'make-jupyter-server-kernel args))
|
||||
|
||||
(cl-defmethod jupyter-kernel :extra "server" (&rest args)
|
||||
"Return a representation of a kernel on a Jupyter server.
|
||||
If ARGS contains a :server key, return a `jupyter-server-kernel'
|
||||
initialized using ARGS. If ARGS contains a :spec key whose value
|
||||
is the name of a kernelspec, the returned kernel's spec slot will
|
||||
be set to the corresponding `jupyter-kernelspec'.
|
||||
|
||||
Call the next method if ARGS does not contain :server."
|
||||
(let ((server (plist-get args :server)))
|
||||
(if (not server) (cl-call-next-method)
|
||||
(cl-assert (object-of-class-p server 'jupyter-server))
|
||||
(let ((spec (plist-get args :spec)))
|
||||
(when (stringp spec)
|
||||
(plist-put args :spec
|
||||
(or (jupyter-guess-kernelspec
|
||||
spec (jupyter-server-kernelspecs server))
|
||||
(error "No kernelspec matching %s @ %s" spec
|
||||
(oref server url))))))
|
||||
(apply #'jupyter-server-kernel args))))
|
||||
|
||||
;;;; Kernel management
|
||||
|
||||
(cl-defmethod jupyter-launch ((kernel jupyter-server-kernel))
|
||||
|
@ -252,6 +256,8 @@ using its SPEC."
|
|||
(jupyter-server--event-handler-fn handler)
|
||||
event))))))))))
|
||||
|
||||
;;; Client connection
|
||||
|
||||
(defun jupyter-server--connect-channels (server id)
|
||||
(jupyter-send (oref server ioloop) 'connect-channels id)
|
||||
(unless (jupyter-server-kernel-connected-p server id)
|
||||
|
|
|
@ -329,10 +329,7 @@ the kernel whose class is CLIENT-CLASS. Note that the client’s
|
|||
see ‘jupyter-make-client’."
|
||||
(require 'jupyter-server-kernel)
|
||||
(or client-class (setq client-class 'jupyter-kernel-client))
|
||||
(let* ((specs (jupyter-server-kernelspecs server))
|
||||
(kernel (jupyter-server-kernel
|
||||
:server server
|
||||
:spec (jupyter-guess-kernelspec kernel-name specs)))
|
||||
(let* ((kernel (jupyter-kernel :server server :spec kernel-name))
|
||||
(manager (jupyter-server-kernel-manager :kernel kernel)))
|
||||
(let ((client (jupyter-make-client manager client-class)))
|
||||
(list manager client))))
|
||||
|
@ -386,17 +383,10 @@ the same meaning as in `jupyter-connect-repl'."
|
|||
(y-or-n-p "Name REPL? "))
|
||||
(read-string "REPL Name: "))
|
||||
t nil t)))
|
||||
(require 'jupyter-server-kernel)
|
||||
(or client-class (setq client-class 'jupyter-repl-client))
|
||||
(jupyter-error-if-not-client-class-p client-class 'jupyter-repl-client)
|
||||
(let* ((manager
|
||||
;; TODO: Move to making `jupyter-server-kernel' and the
|
||||
;; other one return singleton kernels?
|
||||
(or (jupyter-server-find-kernel server kernel-id)
|
||||
(jupyter-server-kernel-manager
|
||||
:kernel (jupyter-server-kernel
|
||||
:id kernel-id
|
||||
:server server))))
|
||||
(let* ((manager (jupyter-server-kernel-manager
|
||||
:kernel (jupyter-kernel :server server :id kernel-id)))
|
||||
(client (jupyter-make-client manager client-class)))
|
||||
(jupyter-bootstrap-repl client repl-name associate-buffer display)))
|
||||
|
||||
|
|
|
@ -218,7 +218,7 @@ This only starts a single global client unless the variable
|
|||
`(jupyter-test-with-client-cache
|
||||
(lambda (name) (jupyter-make-client
|
||||
(jupyter-kernel-manager
|
||||
:kernel (jupyter-kernel-process :spec name))
|
||||
:kernel (jupyter-kernel :spec name))
|
||||
'jupyter-kernel-client))
|
||||
jupyter-test-global-clients ,kernel ,client
|
||||
(unwind-protect
|
||||
|
|
Loading…
Add table
Reference in a new issue