mirror of
https://github.com/vale981/emacs-jupyter
synced 2025-03-04 15:41:37 -05:00
Sort available kernelspecs; guess with ^; use guessing in jupyter-run-repl
This commit is contained in:
parent
0a7055d7b1
commit
7d20c0aee2
4 changed files with 62 additions and 18 deletions
|
@ -45,10 +45,10 @@
|
||||||
"Get the available kernelspecs.
|
"Get the available kernelspecs.
|
||||||
Return an alist mapping kernel names to (DIRECTORY . PLIST) pairs
|
Return an alist mapping kernel names to (DIRECTORY . PLIST) pairs
|
||||||
where DIRECTORY is the resource directory of the kernel and PLIST
|
where DIRECTORY is the resource directory of the kernel and PLIST
|
||||||
is its kernelspec plist. The alist is formed by parsing the
|
is its kernelspec plist. The alist is formed by parsing and
|
||||||
output of the shell command
|
sorting the output of the shell command
|
||||||
|
|
||||||
jupyter kernelspec list
|
jupyter kernelspec list --json
|
||||||
|
|
||||||
By default the available kernelspecs are cached. To force an
|
By default the available kernelspecs are cached. To force an
|
||||||
update of the cached kernelspecs, give a non-nil value to
|
update of the cached kernelspecs, give a non-nil value to
|
||||||
|
@ -64,14 +64,16 @@ each DIRECTORY will be a remote file name."
|
||||||
(or (jupyter-command "kernelspec" "list" "--json")
|
(or (jupyter-command "kernelspec" "list" "--json")
|
||||||
(error "Can't obtain kernelspecs from jupyter shell command")))
|
(error "Can't obtain kernelspecs from jupyter shell command")))
|
||||||
:kernelspecs)))
|
:kernelspecs)))
|
||||||
(puthash
|
(puthash host
|
||||||
host (cl-loop
|
(sort (cl-loop
|
||||||
for (name spec) on specs by #'cddr
|
for (name spec) on specs by #'cddr
|
||||||
for dir = (concat (unless (equal host "local") host)
|
for dir = (concat (unless (equal host "local") host)
|
||||||
(plist-get spec :resource_dir))
|
(plist-get spec :resource_dir))
|
||||||
collect (cons (substring (symbol-name name) 1)
|
collect (cons (substring (symbol-name name) 1)
|
||||||
(cons dir (plist-get spec :spec))))
|
(cons dir (plist-get spec :spec))))
|
||||||
jupyter--kernelspecs)))))
|
(lambda (x y)
|
||||||
|
(string< (car x) (car y))))
|
||||||
|
jupyter--kernelspecs)))))
|
||||||
|
|
||||||
(defun jupyter-get-kernelspec (name &optional refresh)
|
(defun jupyter-get-kernelspec (name &optional refresh)
|
||||||
"Get the kernelspec for a kernel named NAME.
|
"Get the kernelspec for a kernel named NAME.
|
||||||
|
@ -103,12 +105,12 @@ Optional argument REFRESH has the same meaning as in
|
||||||
(or specs (jupyter-available-kernelspecs refresh))))
|
(or specs (jupyter-available-kernelspecs refresh))))
|
||||||
|
|
||||||
(defun jupyter-guess-kernelspec (name &optional specs refresh)
|
(defun jupyter-guess-kernelspec (name &optional specs refresh)
|
||||||
"Return the first kernelspec matching NAME.
|
"Return the first kernelspec starting with NAME.
|
||||||
Raise an error if no kernelspec could be found.
|
Raise an error if no kernelspec could be found.
|
||||||
|
|
||||||
SPECS and REFRESH have the same meaning as in
|
SPECS and REFRESH have the same meaning as in
|
||||||
`jupyter-find-kernelspecs'."
|
`jupyter-find-kernelspecs'."
|
||||||
(or (car (jupyter-find-kernelspecs name specs refresh))
|
(or (car (jupyter-find-kernelspecs (format "^%s" name) specs refresh))
|
||||||
(error "No valid kernelspec for kernel name (%s)" name)))
|
(error "No valid kernelspec for kernel name (%s)" name)))
|
||||||
|
|
||||||
(defun jupyter-completing-read-kernelspec (&optional specs refresh)
|
(defun jupyter-completing-read-kernelspec (&optional specs refresh)
|
||||||
|
|
|
@ -2097,7 +2097,7 @@ completing all of the above.")
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun jupyter-run-repl (kernel-name &optional repl-name associate-buffer client-class display)
|
(defun jupyter-run-repl (kernel-name &optional repl-name associate-buffer client-class display)
|
||||||
"Run a Jupyter REPL connected to a kernel with name, KERNEL-NAME.
|
"Run a Jupyter REPL connected to a kernel with name, KERNEL-NAME.
|
||||||
KERNEL-NAME will be passed to `jupyter-find-kernelspecs' and the
|
KERNEL-NAME will be passed to `jupyter-guess-kernelspec' and the
|
||||||
first kernel found will be used to start the new kernel.
|
first kernel found will be used to start the new kernel.
|
||||||
|
|
||||||
With a prefix argument give a new REPL-NAME for the REPL.
|
With a prefix argument give a new REPL-NAME for the REPL.
|
||||||
|
@ -2128,10 +2128,6 @@ command on the host."
|
||||||
t nil t))
|
t nil t))
|
||||||
(or client-class (setq client-class 'jupyter-repl-client))
|
(or client-class (setq client-class 'jupyter-repl-client))
|
||||||
(jupyter-error-if-not-client-class-p client-class 'jupyter-repl-client)
|
(jupyter-error-if-not-client-class-p client-class 'jupyter-repl-client)
|
||||||
(unless (called-interactively-p 'interactive)
|
|
||||||
(or (when-let* ((name (caar (jupyter-find-kernelspecs kernel-name))))
|
|
||||||
(setq kernel-name name))
|
|
||||||
(error "No kernel found for prefix (%s)" kernel-name)))
|
|
||||||
;; For `jupyter-start-new-kernel', we don't require this at top-level since
|
;; For `jupyter-start-new-kernel', we don't require this at top-level since
|
||||||
;; there are many ways to interact with a kernel, e.g. through a notebook
|
;; there are many ways to interact with a kernel, e.g. through a notebook
|
||||||
;; server, and we don't want to load any unnecessary files.
|
;; server, and we don't want to load any unnecessary files.
|
||||||
|
|
|
@ -1912,6 +1912,24 @@ next(x"))))))
|
||||||
font-lock-extend-region-functions)))
|
font-lock-extend-region-functions)))
|
||||||
(font-lock-ensure)))))
|
(font-lock-ensure)))))
|
||||||
|
|
||||||
|
(ert-deftest jupyter-available-kernelspecs-sorting ()
|
||||||
|
:tags '(repl)
|
||||||
|
(jupyter-test-with-some-kernelspecs '("foo_qux" "qux" "bar_qux")
|
||||||
|
(let ((result (mapcar #'car (jupyter-available-kernelspecs t))))
|
||||||
|
(should (equal result (sort (copy-sequence result) #'string<))))))
|
||||||
|
|
||||||
|
(ert-deftest jupyter-run-repl-issue-371 ()
|
||||||
|
:tags '(repl)
|
||||||
|
(jupyter-test-with-some-kernelspecs '("foo_qux" "qux" "bar_qux")
|
||||||
|
(let ((client))
|
||||||
|
(unwind-protect
|
||||||
|
(progn
|
||||||
|
(setq client (jupyter-run-repl "qux"))
|
||||||
|
(should (equal (plist-get (jupyter-session-conn-info (oref client session))
|
||||||
|
:kernel_name)
|
||||||
|
"qux")))
|
||||||
|
(jupyter-test-kill-buffer (oref client buffer))))))
|
||||||
|
|
||||||
;;; `org-mode'
|
;;; `org-mode'
|
||||||
|
|
||||||
(defvar org-babel-jupyter-resource-directory nil)
|
(defvar org-babel-jupyter-resource-directory nil)
|
||||||
|
|
|
@ -365,8 +365,36 @@ For `url-retrieve', the callback will be called with a nil status."
|
||||||
(progn ,@body)
|
(progn ,@body)
|
||||||
(jupyter-api-shutdown-kernel ,server ,id))))))
|
(jupyter-api-shutdown-kernel ,server ,id))))))
|
||||||
|
|
||||||
|
(defmacro jupyter-test-with-some-kernelspecs (names &rest body)
|
||||||
|
"Execute BODY in the context where extra kernelspecs with NAMES are available.
|
||||||
|
|
||||||
|
Those kernelspecs will be created in a temporary dir, which will
|
||||||
|
be presented to Jupyter process via JUPYTER_PATH environemnt
|
||||||
|
variable."
|
||||||
|
(declare (indent 1) (debug (listp body)))
|
||||||
|
`(unwind-protect
|
||||||
|
(let ((jupyter-extra-dir (make-temp-file "jupyter-extra-dir" 'directory)))
|
||||||
|
(jupyter-test-create-some-kernelspecs ,names jupyter-extra-dir)
|
||||||
|
(setenv "JUPYTER_PATH" jupyter-extra-dir)
|
||||||
|
,@body)
|
||||||
|
(setenv "JUPYTER_PATH")))
|
||||||
|
|
||||||
;;; Functions
|
;;; Functions
|
||||||
|
|
||||||
|
(defun jupyter-test-create-some-kernelspecs (kernel-names data-dir)
|
||||||
|
"In DATA-DIR, create kernelspecs according to KERNEL-NAMES list.
|
||||||
|
|
||||||
|
The only difference between them will be their names."
|
||||||
|
(let ((argv (vector "python" "-m" "ipykernel_launcher" "-f" "{connection_file}"))
|
||||||
|
(save-silently t))
|
||||||
|
(dolist (name kernel-names)
|
||||||
|
(let ((kernel-dir (format "%s/kernels/%s" data-dir name)))
|
||||||
|
(make-directory kernel-dir t)
|
||||||
|
(append-to-file (json-serialize
|
||||||
|
`(:argv ,argv :display_name ,name :language "python"))
|
||||||
|
nil
|
||||||
|
(format "%s/kernel.json" kernel-dir))))))
|
||||||
|
|
||||||
(defun jupyter-test-ipython-kernel-version (spec)
|
(defun jupyter-test-ipython-kernel-version (spec)
|
||||||
"Return the IPython kernel version string corresponding to SPEC.
|
"Return the IPython kernel version string corresponding to SPEC.
|
||||||
Assumes that SPEC is a kernelspec for a Python kernel and
|
Assumes that SPEC is a kernelspec for a Python kernel and
|
||||||
|
|
Loading…
Add table
Reference in a new issue