Add the jupyter-kernelspecs method

Replaces both `jupyter-available-kernelspecs` and
`jupyter-server-kernelspecs`.
This commit is contained in:
Nathaniel Nicandro 2021-04-03 13:34:16 -05:00
parent 35e44798c4
commit 5857352135
6 changed files with 57 additions and 43 deletions

View file

@ -94,18 +94,26 @@ REFRESH."
jupyter--kernelspecs)))))
kernelspecs))
(cl-defgeneric jupyter-kernelspecs (host &optional refresh)
"Return a list of kernelspecs on HOST.")
(cl-defmethod jupyter-kernelspecs ((host string) &optional refresh)
(let ((default-directory host))
(jupyter-available-kernelspecs refresh)))
(defun jupyter-get-kernelspec (name &optional specs refresh)
"Get the kernelspec for a kernel named NAME.
If no kernelspec is found, return nil. Otherwise return the
kernelspec plist for the kernel names NAME. Optional argument
REFRESH has the same meaning as in
`jupyter-available-kernelspecs'.
kernelspec for the kernel named NAME.
If SPECS is provided, it is a list of kernelspecs that will be
searched, otherwise the kernelspecs returned by
`jupyter-available-kernelspecs' are used."
searched. Otherwise the kernelspecs associated with the
`default-directory' are used.
Optional argument REFRESH has the same meaning as in
`jupyter-kernelspecs'."
(cl-loop
for kernelspec in (or specs (jupyter-available-kernelspecs refresh))
for kernelspec in (or specs (jupyter-kernelspecs default-directory refresh))
thereis (when (string= (jupyter-kernelspec-name kernelspec) name)
kernelspec)))
@ -114,15 +122,15 @@ searched, otherwise the kernelspecs returned by
RE is a regular expression use to match the name of a kernel.
Return a list of `jupyter-kernelspec' objects.
If SPECS is non-nil search SPECS, otherwise search the specs
returned by `jupyter-available-kernelspecs'.
If SPECS is non-nil search SPECS, otherwise search the
kernelspecs associated with the `default-directory'.
Optional argument REFRESH has the same meaning as in
`jupyter-available-kernelspecs'."
`jupyter-kernelspecs'."
(cl-remove-if-not
(lambda (kernelspec)
(string-match-p re (jupyter-kernelspec-name kernelspec)))
(or specs (jupyter-available-kernelspecs refresh))))
(or specs (jupyter-kernelspecs default-directory refresh))))
(defun jupyter-guess-kernelspec (name &optional specs refresh)
"Return the first kernelspec starting with NAME.
@ -137,11 +145,12 @@ SPECS and REFRESH have the same meaning as in
"Use `completing-read' to select a kernel and return its kernelspec.
SPECS is a list of kernelspecs that will be used for completion,
if it is nil the `jupyter-available-kernelspecs' will be used.
if it is nil the kernelspecs associated with the
`default-directory' will be used.
Optional argument REFRESH has the same meaning as in
`jupyter-available-kernelspecs'."
(let* ((specs (or specs (jupyter-available-kernelspecs refresh)))
`jupyter-kernelspecs'."
(let* ((specs (or specs (jupyter-kernelspecs default-directory refresh)))
(display-names (if (null specs) (error "No kernelspecs available")
(mapcar (lambda (k)
(plist-get

View file

@ -26,11 +26,11 @@
;;
;; The main entry points are `jupyter-run-repl' and `jupyter-connect-repl'.
;;
;; When called interactively, `jupyter-run-repl' asks for a kernel to start
;; (based on the kernels found using `jupyter-available-kernelspecs'), connects
;; a `jupyter-repl-client' to the selected kernel, and pops up a REPL buffer.
;; The main difference of `jupyter-connect-repl' is that it will obtain the
;; kernel's connection info by asking for the JSON file containing it to start
;; When called interactively, `jupyter-run-repl' asks for a kernel to
;; start, connects a `jupyter-repl-client' to the selected kernel, and
;; pops up a REPL buffer. The main difference of
;; `jupyter-connect-repl' is that it will obtain the kernel's
;; connection info by asking for the JSON file containing it to start
;; connection to a kernel.
;;
;; Additionally, `jupyter-repl-associate-buffer' associates the

View file

@ -54,8 +54,8 @@ Used in, e.g. a `jupyter-server-kernel-list-mode' buffer.")
(kernelspecs
:type json-plist
:initform nil
:documentation "Kernelspecs for the kernels available behind this gateway.
Access should be done through `jupyter-available-kernelspecs'.")))
:documentation "Kernelspecs for the kernels available behind
this gateway. Access them through `jupyter-kernelspecs'.")))
(cl-defmethod make-instance ((class (subclass jupyter-server)) &rest slots)
(cl-assert (plist-get slots :url))
@ -87,18 +87,18 @@ with default `jupyter-api-authentication-method'"))
(prog1 (cl-call-next-method)
(jupyter-reauthenticate-websockets server)))))
(cl-defmethod jupyter-server-kernelspecs ((server jupyter-server) &optional refresh)
(cl-defmethod jupyter-kernelspecs ((client jupyter-rest-client) &optional _refresh)
(or (jupyter-api-get-kernelspec client)
(error "Can't retrieve kernelspecs from server @ %s"
(oref client url))))
(cl-defmethod jupyter-kernelspecs ((server jupyter-server) &optional refresh)
"Return the kernelspecs on SERVER.
By default the available kernelspecs are cached. To force an
update of the cached kernelspecs, give a non-nil value to
REFRESH.
The kernelspecs are returned in the same form as returned by
`jupyter-available-kernelspecs'."
REFRESH."
(when (or refresh (null (oref server kernelspecs)))
(let ((specs (or (jupyter-api-get-kernelspec server)
(error "Can't retrieve kernelspecs from server @ %s"
(oref server url)))))
(let ((specs (cl-call-next-method)))
(plist-put specs :kernelspecs
(cl-loop
for (_ spec) on (plist-get specs :kernelspecs) by #'cddr
@ -109,9 +109,14 @@ The kernelspecs are returned in the same form as returned by
(oset server kernelspecs specs)))
(plist-get (oref server kernelspecs) :kernelspecs))
(cl-defmethod jupyter-kernelspecs :extra "server" ((host string) &optional refresh)
(if (jupyter-tramp-file-name-p host)
(jupyter-kernelspecs (jupyter-tramp-server-from-file-name host) refresh)
(cl-call-next-method)))
(cl-defmethod jupyter-server-has-kernelspec-p ((server jupyter-server) name)
"Return non-nil if SERVER can launch kernels with kernelspec NAME."
(jupyter-guess-kernelspec name (jupyter-server-kernelspecs server)))
(jupyter-guess-kernelspec name (jupyter-kernelspecs server)))
;;; Kernel definition
@ -165,7 +170,7 @@ Call the next method if ARGS does not contain :server."
;; the server connection already open and
;; kernelspecs already retrieved.
(or (jupyter-guess-kernelspec
spec (jupyter-server-kernelspecs server))
spec (jupyter-kernelspecs server))
;; TODO: Return the error to the I/O context.
(error "No kernelspec matching %s @ %s" spec
(oref server url))))))
@ -287,7 +292,7 @@ this case FN will be evaluated on KERNEL."
(cl-defmethod jupyter-launch ((server jupyter-server) &optional (kernel string))
(cl-check-type kernel string)
(let* ((spec (jupyter-guess-kernelspec
kernel (jupyter-server-kernelspecs server)))
kernel (jupyter-kernelspecs server)))
(plist (jupyter-api-start-kernel
server (jupyter-kernelspec-name spec))))
(jupyter-kernel :server server :id (plist-get plist :id) :spec spec)))
@ -313,7 +318,7 @@ using its SPEC."
(setf (jupyter-kernel-spec kernel)
(jupyter-guess-kernelspec
(plist-get model :name)
(jupyter-server-kernelspecs server)))))
(jupyter-kernelspecs server)))))
(let ((plist (jupyter-api-start-kernel
server (jupyter-kernelspec-name spec))))
(setf (jupyter-server-kernel-id kernel) (plist-get plist :id))

View file

@ -29,7 +29,7 @@
;; Websocket URL for the server, the `jupyter-server' object can launch kernels
;; using the function `jupyter-server-start-new-kernel'. The kernelspecs
;; available on the server can be accessed by calling
;; `jupyter-server-kernelspecs'.
;; `jupyter-kernelspecs'.
;;
;; Starting REPLs
;;
@ -290,7 +290,7 @@ With a prefix argument, ask to select a server if there are
mutiple to choose from, otherwise the most recently used server
is used as determined by `jupyter-current-server'."
(interactive (list (jupyter-current-server current-prefix-arg)))
(let* ((specs (jupyter-server-kernelspecs server))
(let* ((specs (jupyter-kernelspecs server))
(spec (jupyter-completing-read-kernelspec specs)))
(jupyter-api-start-kernel server (jupyter-kernelspec-name spec))))
@ -310,7 +310,7 @@ is used as determined by `jupyter-current-server'."
(let ((server (jupyter-current-server current-prefix-arg)))
(list server
(car (jupyter-completing-read-kernelspec
(jupyter-server-kernelspecs server)))
(jupyter-kernelspecs server)))
;; FIXME: Ambiguity with `jupyter-current-server' and
;; `current-prefix-arg'
(when (and current-prefix-arg

View file

@ -48,7 +48,7 @@
(declare-function jupyter-run-server-repl "jupyter-server")
(declare-function jupyter-connect-server-repl "jupyter-server")
(declare-function jupyter-server-kernelspecs "jupyter-server")
(declare-function jupyter-kernelspecs "jupyter-server")
(declare-function jupyter-server-kernel-id-from-name "jupyter-server")
(declare-function jupyter-server-name-client-kernel "jupyter-server")
(declare-function jupyter-api-get-kernel "jupyter-rest-api")
@ -316,7 +316,7 @@ session."
;; Language aliases may not exist for the kernels that are accessible on
;; the server so ensure they do.
(org-babel-jupyter-aliases-from-kernelspecs
nil (jupyter-server-kernelspecs server))
nil (jupyter-kernelspecs server))
(let ((sname (file-local-name rsession)))
(if-let ((id (jupyter-server-kernel-id-from-name server sname)))
;; Connecting to an existing kernel
@ -682,9 +682,9 @@ For all kernel SPECS, make a language alias for the kernel
language if one does not already exist. The alias is created with
`org-babel-jupyter-make-language-alias'.
SPECS defaults to `jupyter-available-kernelspecs'. Optional
argument REFRESH has the same meaning as in
`jupyter-available-kernelspecs'.
SPECS defaults to those associated with the `default-directory'.
Optional argument REFRESH has the same meaning as in
`jupyter-kernelspecs'.
Note, spaces in the kernel language name are converted into
dashes in the language alias, e.g.
@ -701,7 +701,7 @@ language to exist on someone's system."
(cl-loop
for spec in (or specs
(with-demoted-errors "Error retrieving kernelspecs: %S"
(jupyter-available-kernelspecs refresh)))
(jupyter-kernelspecs default-directory refresh)))
for kernel = (jupyter-kernelspec-name spec)
for lang = (jupyter-canonicalize-language-string
(plist-get (jupyter-kernelspec-plist spec) :language))
@ -726,7 +726,7 @@ mapped to their appropriate minted language in
(cond
((org-export-derived-backend-p backend 'latex)
(cl-loop
for spec in (jupyter-available-kernelspecs)
for spec in (jupyter-kernelspecs default-directory)
for lang = (plist-get (jupyter-kernelspec-plist spec) :language)
do (cl-pushnew (list (intern (concat "jupyter-" lang)) lang)
org-latex-minted-langs :test #'equal)))))

View file

@ -302,7 +302,7 @@ For `url-retrieve', the callback will be called with a nil status."
`(let ((,kernel (jupyter-kernel
:server server
:spec (jupyter-guess-kernelspec
,name (jupyter-server-kernelspecs ,server)))))
,name (jupyter-kernelspecs ,server)))))
(jupyter-launch ,kernel)
(unwind-protect
(progn ,@body)