mirror of
https://github.com/vale981/emacs-jupyter
synced 2025-03-06 07:51:39 -05:00
Remove jupyter-send-*
methods
These methods were not used much internally.
This commit is contained in:
parent
0c6d90cc7e
commit
348df7feb5
9 changed files with 240 additions and 292 deletions
|
@ -443,12 +443,14 @@ each other. A client has a request table to keep track of all
|
||||||
requests that are not considered idle. The most recent idle
|
requests that are not considered idle. The most recent idle
|
||||||
request is also kept track of.
|
request is also kept track of.
|
||||||
|
|
||||||
Each request contains: a message ID, a time sent, a last message
|
Each request contains: a message ID, a request type, a request
|
||||||
received by the client that sent it, a list of message types that
|
message, a time sent, a last message received by the client that
|
||||||
tell the client to not call the handler methods of those types,
|
sent it, a list of message types that tell the client to not call
|
||||||
and an alist mapping message types to callback functions a client
|
the handler methods of those types, and an alist mapping message
|
||||||
should call."
|
types to callback functions a client should call."
|
||||||
(id "")
|
(id (jupyter-new-uuid) :read-only t)
|
||||||
|
(type nil :read-only t)
|
||||||
|
(content nil :read-only t)
|
||||||
(time (current-time) :read-only t)
|
(time (current-time) :read-only t)
|
||||||
(idle-p nil)
|
(idle-p nil)
|
||||||
(last-message nil)
|
(last-message nil)
|
||||||
|
|
|
@ -169,7 +169,7 @@ For example to prevent a client from calling its :execute-reply
|
||||||
handler:
|
handler:
|
||||||
|
|
||||||
(let ((jupyter-inhibit-handlers '(:execute-reply)))
|
(let ((jupyter-inhibit-handlers '(:execute-reply)))
|
||||||
(jupyter-send-execute-request client ...))
|
(jupyter-send client :execute-request ...)))
|
||||||
|
|
||||||
In addition, if the first element of the list is the symbol
|
In addition, if the first element of the list is the symbol
|
||||||
`not', then inhibit handlers not in the list.
|
`not', then inhibit handlers not in the list.
|
||||||
|
@ -300,45 +300,6 @@ method is called."
|
||||||
,(or doc (format "A :%s handler." type))
|
,(or doc (format "A :%s handler." type))
|
||||||
,@body))
|
,@body))
|
||||||
|
|
||||||
;; FIXME: Remove the need to call `jupyter-message-*' functions by
|
|
||||||
;; introducing some kind of property list defaults mechanism (e.g. by
|
|
||||||
;; appending the defaults to the property list passed to
|
|
||||||
;; `jupyter-send-*').
|
|
||||||
;;
|
|
||||||
;; - Document the :inhibit-handlers key
|
|
||||||
;; - Document that client is bound to the kernel client in BODY
|
|
||||||
(defmacro define--jupyter-client-sender (type &optional doc &rest body)
|
|
||||||
(declare (indent 2) (doc-string 2))
|
|
||||||
(when doc
|
|
||||||
(unless (stringp doc)
|
|
||||||
(setq body (cons doc body)
|
|
||||||
doc nil)))
|
|
||||||
(let (defaults)
|
|
||||||
(while (keywordp (car body))
|
|
||||||
(push (pop body) defaults)
|
|
||||||
(push (pop body) defaults))
|
|
||||||
(cl-callf nreverse defaults)
|
|
||||||
(cl-labels ((keyword-name (k) (intern (substring (symbol-name k) 1)))
|
|
||||||
(as-keyword
|
|
||||||
(k) (if (keywordp k) k
|
|
||||||
(intern (format ":%s" k)))))
|
|
||||||
`(cl-defgeneric ,(intern (format "jupyter-send-%s" type))
|
|
||||||
((client jupyter-kernel-client)
|
|
||||||
&key (inhibit-handlers nil)
|
|
||||||
,@(cl-loop for (k v) on defaults by #'cddr
|
|
||||||
collect (list (keyword-name k) v)))
|
|
||||||
,(or doc (format "Send an :%s message." type))
|
|
||||||
(declare (indent 1))
|
|
||||||
(let ((jupyter-inhibit-handlers
|
|
||||||
(or inhibit-handlers jupyter-inhibit-handlers))
|
|
||||||
(msg
|
|
||||||
(,(intern (format "jupyter-message-%s" type))
|
|
||||||
,@(cl-loop
|
|
||||||
for (k _) on defaults by #'cddr
|
|
||||||
nconc (list k (keyword-name k))))))
|
|
||||||
(prog1 (jupyter-send client :shell ,(as-keyword type) msg)
|
|
||||||
,@body))))))
|
|
||||||
|
|
||||||
;;; Initializing a `jupyter-kernel-client'
|
;;; Initializing a `jupyter-kernel-client'
|
||||||
|
|
||||||
(cl-defmethod initialize-instance ((client jupyter-kernel-client) &optional _slots)
|
(cl-defmethod initialize-instance ((client jupyter-kernel-client) &optional _slots)
|
||||||
|
@ -433,11 +394,12 @@ If it does not contain a valid value, raise an error."
|
||||||
unless (plist-member jupyter-message-types msg-type)
|
unless (plist-member jupyter-message-types msg-type)
|
||||||
do (error "Not a valid message type (`%s')" msg-type))))
|
do (error "Not a valid message type (`%s')" msg-type))))
|
||||||
|
|
||||||
(cl-defmethod jupyter-send ((client jupyter-kernel-client)
|
;; FIXME: Remove the need for this
|
||||||
channel
|
(defun jupyter--merge-message-defaults (type content)
|
||||||
type
|
(let ((req (intern (concat "jupyter-" (substring (symbol-name type) 1)))))
|
||||||
message
|
(apply req content)))
|
||||||
&optional msg-id)
|
|
||||||
|
(cl-defmethod jupyter-send ((client jupyter-kernel-client) (type symbol) &rest content)
|
||||||
"Send a message on CLIENT's CHANNEL.
|
"Send a message on CLIENT's CHANNEL.
|
||||||
Return a `jupyter-request' representing the sent message. CHANNEL
|
Return a `jupyter-request' representing the sent message. CHANNEL
|
||||||
is one of the channel keywords, either (:stdin or :shell).
|
is one of the channel keywords, either (:stdin or :shell).
|
||||||
|
@ -449,25 +411,36 @@ response to the sent message, see `jupyter-add-callback' and
|
||||||
`jupyter-request-inhibited-handlers'."
|
`jupyter-request-inhibited-handlers'."
|
||||||
(declare (indent 1))
|
(declare (indent 1))
|
||||||
(jupyter-verify-inhibited-handlers)
|
(jupyter-verify-inhibited-handlers)
|
||||||
(let ((msg-id (or msg-id (jupyter-new-uuid))))
|
(pcase-let* ((req
|
||||||
|
(jupyter-request
|
||||||
|
:id (if (stringp (car content)) (pop content)
|
||||||
|
(jupyter-new-uuid))
|
||||||
|
:type type
|
||||||
|
:content (jupyter--merge-message-defaults type content)))
|
||||||
|
((cl-struct jupyter-request id) req))
|
||||||
(when jupyter--debug
|
(when jupyter--debug
|
||||||
;; The logging of messages is deferred until the next command loop for
|
;; The logging of messages is deferred until the next command loop for
|
||||||
;; security reasons. When sending :input-reply messages that read
|
;; security reasons. When sending :input-reply messages that read
|
||||||
;; passwords, clearing the password string using `clear-string' happens
|
;; passwords, clearing the password string using `clear-string' happens
|
||||||
;; *after* the call to `jupyter-send'.
|
;; *after* the call to `jupyter-send'.
|
||||||
(run-at-time 0 nil (lambda () (message "SENDING: %s %s %s" type msg-id message))))
|
(run-at-time 0 nil (lambda () (message "SENDING: %s %s %s" type id content))))
|
||||||
(jupyter--send
|
(let ((channel (if (memq type '(:input-reply :input-request)) :stdin :shell))
|
||||||
(jupyter-kernel-connection (oref client kernel))
|
(requests (oref client requests)))
|
||||||
'send channel type message msg-id)
|
(cl-call-next-method
|
||||||
;; Anything sent to stdin is a reply not a request so don't add it as a
|
(jupyter-kernel-connection (oref client kernel))
|
||||||
;; pending request
|
'send channel content id)
|
||||||
(unless (eq channel :stdin)
|
;; Anything sent to stdin is a reply not a request so consider
|
||||||
(let ((req (jupyter-generate-request client message))
|
;; the "request" completed.
|
||||||
(requests (oref client requests)))
|
(setf (jupyter-request-idle-p req) (eq channel :stdin))
|
||||||
(setf (jupyter-request-id req) msg-id)
|
(setf (jupyter-request-inhibited-handlers req) jupyter-inhibit-handlers)
|
||||||
(setf (jupyter-request-inhibited-handlers req) jupyter-inhibit-handlers)
|
(puthash id req requests)
|
||||||
(puthash msg-id req requests)
|
(puthash "last-sent" req requests))))
|
||||||
(puthash "last-sent" req requests)))))
|
|
||||||
|
(cl-defmethod jupyter-send :after ((client jupyter-kernel-client) (_type (eql :execute-request)) &rest _content)
|
||||||
|
(jupyter-server-mode-set-client client))
|
||||||
|
|
||||||
|
(cl-defmethod jupyter-send ((type symbol) &rest content)
|
||||||
|
(apply #'cl-call-next-method jupyter-current-client type content))
|
||||||
|
|
||||||
;;; Pending requests
|
;;; Pending requests
|
||||||
|
|
||||||
|
@ -625,7 +598,7 @@ After CLIENT shuts down the kernel it is connected to, it is no
|
||||||
longer connected to a kernel."
|
longer connected to a kernel."
|
||||||
(when-let* ((kernel (and (slot-boundp client 'kernel)
|
(when-let* ((kernel (and (slot-boundp client 'kernel)
|
||||||
(oref client kernel))))
|
(oref client kernel))))
|
||||||
(jupyter-wait-until-idle (jupyter-send-shutdown-request client))
|
(jupyter-wait-until-idle (jupyter-send client :shutdown-request))
|
||||||
(jupyter-shutdown kernel)))
|
(jupyter-shutdown kernel)))
|
||||||
|
|
||||||
(cl-defmethod jupyter-interrupt-kernel ((client jupyter-kernel-client))
|
(cl-defmethod jupyter-interrupt-kernel ((client jupyter-kernel-client))
|
||||||
|
@ -680,7 +653,7 @@ interpreted as additional CALLBACKS to add to REQ. So to add
|
||||||
multiple callbacks you would do
|
multiple callbacks you would do
|
||||||
|
|
||||||
(jupyter-add-callback
|
(jupyter-add-callback
|
||||||
(jupyter-send-execute-request client :code \"1 + 2\")
|
(jupyter-send client (jupyter-execute-request :code \"1 + 2\"))
|
||||||
:status (lambda (msg) ...)
|
:status (lambda (msg) ...)
|
||||||
:execute-reply (lambda (msg) ...)
|
:execute-reply (lambda (msg) ...)
|
||||||
:execute-result (lambda (msg) ...))"
|
:execute-result (lambda (msg) ...))"
|
||||||
|
@ -968,10 +941,7 @@ user. Otherwise `read-from-minibuffer' is used."
|
||||||
(with-timeout-unsuspend timeout-spec)))
|
(with-timeout-unsuspend timeout-spec)))
|
||||||
(quit ""))))
|
(quit ""))))
|
||||||
(unwind-protect
|
(unwind-protect
|
||||||
(jupyter-send
|
(jupyter-send client :input-reply :value value)
|
||||||
client :stdin
|
|
||||||
:input-reply (jupyter-message-input-reply
|
|
||||||
:value value))
|
|
||||||
(when (eq password t)
|
(when (eq password t)
|
||||||
(clear-string value)))
|
(clear-string value)))
|
||||||
value)))
|
value)))
|
||||||
|
@ -1048,8 +1018,8 @@ text/plain representation."
|
||||||
(interactive (list (jupyter-read-expression) nil))
|
(interactive (list (jupyter-read-expression) nil))
|
||||||
(let ((msg (jupyter-wait-until-received :execute-result
|
(let ((msg (jupyter-wait-until-received :execute-result
|
||||||
(let* ((jupyter-inhibit-handlers t)
|
(let* ((jupyter-inhibit-handlers t)
|
||||||
(req (jupyter-send-execute-request jupyter-current-client
|
(req (jupyter-send jupyter-current-client
|
||||||
:code code :store-history nil)))
|
:execute-request :code code :store-history nil)))
|
||||||
(prog1 req
|
(prog1 req
|
||||||
(jupyter-add-callback req
|
(jupyter-add-callback req
|
||||||
:execute-reply
|
:execute-reply
|
||||||
|
@ -1202,8 +1172,8 @@ current buffer that STR was extracted from.")
|
||||||
(cl-check-type jupyter-current-client jupyter-kernel-client
|
(cl-check-type jupyter-current-client jupyter-kernel-client
|
||||||
"Not a valid client")
|
"Not a valid client")
|
||||||
(let ((jupyter-inhibit-handlers '(not :input-request))
|
(let ((jupyter-inhibit-handlers '(not :input-request))
|
||||||
(req (jupyter-send-execute-request jupyter-current-client
|
(req (jupyter-send jupyter-current-client
|
||||||
:code str :store-history nil)))
|
:execute-request :code str :store-history nil)))
|
||||||
(prog1 req
|
(prog1 req
|
||||||
(jupyter-eval-add-callbacks req beg end))))
|
(jupyter-eval-add-callbacks req beg end))))
|
||||||
|
|
||||||
|
@ -1418,15 +1388,6 @@ STR is displayed after the region."
|
||||||
|
|
||||||
;;;;; Handlers
|
;;;;; Handlers
|
||||||
|
|
||||||
(define--jupyter-client-sender execute-request
|
|
||||||
:code nil
|
|
||||||
:silent nil
|
|
||||||
:store-history t
|
|
||||||
:user-expressions nil
|
|
||||||
:allow-stdin (jupyter-alive-p client :stdin)
|
|
||||||
:stop-on-error nil
|
|
||||||
(jupyter-server-mode-set-client client))
|
|
||||||
|
|
||||||
(define-jupyter-client-handler execute-reply)
|
(define-jupyter-client-handler execute-reply)
|
||||||
|
|
||||||
(cl-defgeneric jupyter-handle-payload ((source symbol) _payload)
|
(cl-defgeneric jupyter-handle-payload ((source symbol) _payload)
|
||||||
|
@ -1493,8 +1454,8 @@ DETAIL is the detail level to use for the request and defaults to
|
||||||
(error "Need a valid `jupyter-current-client'"))
|
(error "Need a valid `jupyter-current-client'"))
|
||||||
(let ((client jupyter-current-client)
|
(let ((client jupyter-current-client)
|
||||||
(msg (jupyter-wait-until-received :inspect-reply
|
(msg (jupyter-wait-until-received :inspect-reply
|
||||||
(jupyter-send-inspect-request jupyter-current-client
|
(jupyter-send jupyter-current-client
|
||||||
:code code :pos pos :detail detail)
|
:inspect-request :code code :pos pos :detail detail)
|
||||||
;; Longer timeout for the Julia kernel
|
;; Longer timeout for the Julia kernel
|
||||||
jupyter-long-timeout)))
|
jupyter-long-timeout)))
|
||||||
(if msg
|
(if msg
|
||||||
|
@ -1536,19 +1497,10 @@ DETAIL is the detail level to use for the request and defaults to
|
||||||
(symbol-at-point)))))
|
(symbol-at-point)))))
|
||||||
(message "Inspect timed out"))))
|
(message "Inspect timed out"))))
|
||||||
|
|
||||||
(define--jupyter-client-sender inspect-request
|
|
||||||
:code nil
|
|
||||||
:pos 0
|
|
||||||
:detail 0)
|
|
||||||
|
|
||||||
(define-jupyter-client-handler inspect-reply)
|
(define-jupyter-client-handler inspect-reply)
|
||||||
|
|
||||||
;;;; Completion
|
;;;; Completion
|
||||||
|
|
||||||
(define--jupyter-client-sender complete-request
|
|
||||||
:code nil
|
|
||||||
:pos 0)
|
|
||||||
|
|
||||||
(define-jupyter-client-handler complete-reply)
|
(define-jupyter-client-handler complete-reply)
|
||||||
|
|
||||||
;;;;; Code context
|
;;;;; Code context
|
||||||
|
@ -1847,9 +1799,8 @@ Run FUN when the completions are available."
|
||||||
(cl-destructuring-bind (code pos)
|
(cl-destructuring-bind (code pos)
|
||||||
(jupyter-code-context 'completion)
|
(jupyter-code-context 'completion)
|
||||||
(let ((req (let ((jupyter-inhibit-handlers t))
|
(let ((req (let ((jupyter-inhibit-handlers t))
|
||||||
(jupyter-send-complete-request
|
(jupyter-send jupyter-current-client
|
||||||
jupyter-current-client
|
:complete-request :code code :pos pos))))
|
||||||
:code code :pos pos))))
|
|
||||||
(prog1 req
|
(prog1 req
|
||||||
(jupyter-add-callback req :complete-reply fun)))))
|
(jupyter-add-callback req :complete-reply fun)))))
|
||||||
|
|
||||||
|
@ -1966,46 +1917,16 @@ snippet text property, if any, and if `yasnippet' is available."
|
||||||
|
|
||||||
;;;; History
|
;;;; History
|
||||||
|
|
||||||
(define--jupyter-client-sender history-request
|
|
||||||
:output nil
|
|
||||||
:raw nil
|
|
||||||
:hist-access-type "tail"
|
|
||||||
:session nil
|
|
||||||
:start nil
|
|
||||||
:stop nil
|
|
||||||
:n 10
|
|
||||||
:pattern nil
|
|
||||||
:unique nil)
|
|
||||||
|
|
||||||
(define-jupyter-client-handler history-reply)
|
(define-jupyter-client-handler history-reply)
|
||||||
|
|
||||||
;;;; Is Complete
|
;;;; Is Complete
|
||||||
|
|
||||||
(define--jupyter-client-sender is-complete-request
|
|
||||||
:code nil)
|
|
||||||
|
|
||||||
(define-jupyter-client-handler is-complete-reply)
|
(define-jupyter-client-handler is-complete-reply)
|
||||||
|
|
||||||
;;;; Comms
|
;;;; Comms
|
||||||
|
|
||||||
(define--jupyter-client-sender comm-info-request
|
|
||||||
:target-name nil)
|
|
||||||
|
|
||||||
(define-jupyter-client-handler comm-info-reply)
|
(define-jupyter-client-handler comm-info-reply)
|
||||||
|
|
||||||
(define--jupyter-client-sender comm-open
|
|
||||||
:id nil
|
|
||||||
:target-name nil
|
|
||||||
:data nil)
|
|
||||||
|
|
||||||
(define--jupyter-client-sender comm-msg
|
|
||||||
:id nil
|
|
||||||
:data nil)
|
|
||||||
|
|
||||||
(define--jupyter-client-sender comm-close
|
|
||||||
:id nil
|
|
||||||
:data nil)
|
|
||||||
|
|
||||||
;;;; Kernel info
|
;;;; Kernel info
|
||||||
|
|
||||||
(defvar jupyter-kernel-language-mode-properties nil
|
(defvar jupyter-kernel-language-mode-properties nil
|
||||||
|
@ -2030,12 +1951,12 @@ name are changed to \"-\" and all uppercase characters lowered."
|
||||||
(cl-check-type client jupyter-kernel-client)
|
(cl-check-type client jupyter-kernel-client)
|
||||||
(or (oref client kernel-info)
|
(or (oref client kernel-info)
|
||||||
(let* ((jupyter-inhibit-handlers t)
|
(let* ((jupyter-inhibit-handlers t)
|
||||||
(req (jupyter-send-kernel-info-request client))
|
|
||||||
(msg (jupyter-wait-until-received :kernel-info-reply
|
(msg (jupyter-wait-until-received :kernel-info-reply
|
||||||
|
(jupyter-send client :kernel-info-request)
|
||||||
;; Go to great lengths to ensure we have waited long
|
;; Go to great lengths to ensure we have waited long
|
||||||
;; enough. When communicating with slow to start kernels
|
;; enough. When communicating with slow to start kernels
|
||||||
;; behind a kernel server this is necessary.
|
;; behind a kernel server this is necessary.
|
||||||
req (* 3 jupyter-long-timeout) "Requesting kernel info...")))
|
(* 3 jupyter-long-timeout) "Requesting kernel info...")))
|
||||||
(unless msg
|
(unless msg
|
||||||
(error "Kernel did not respond to kernel-info request"))
|
(error "Kernel did not respond to kernel-info request"))
|
||||||
(prog1 (oset client kernel-info (jupyter-message-content msg))
|
(prog1 (oset client kernel-info (jupyter-message-content msg))
|
||||||
|
@ -2087,15 +2008,10 @@ CLIENT is a kernel client."
|
||||||
(support (intern (format "jupyter-%s" lang))))
|
(support (intern (format "jupyter-%s" lang))))
|
||||||
(require support nil t)))
|
(require support nil t)))
|
||||||
|
|
||||||
(define--jupyter-client-sender kernel-info-request)
|
|
||||||
|
|
||||||
(define-jupyter-client-handler kernel-info-reply)
|
(define-jupyter-client-handler kernel-info-reply)
|
||||||
|
|
||||||
;;;; Shutdown
|
;;;; Shutdown
|
||||||
|
|
||||||
(define--jupyter-client-sender shutdown-request
|
|
||||||
:restart nil)
|
|
||||||
|
|
||||||
(define-jupyter-client-handler shutdown-reply)
|
(define-jupyter-client-handler shutdown-reply)
|
||||||
|
|
||||||
;;; IOPUB handlers
|
;;; IOPUB handlers
|
||||||
|
|
|
@ -122,7 +122,8 @@ Make the character after `point' invisible."
|
||||||
If the Pkg prompt can't be retrieved from the kernel, return
|
If the Pkg prompt can't be retrieved from the kernel, return
|
||||||
nil."
|
nil."
|
||||||
(when-let* ((msg (jupyter-wait-until-received :execute-reply
|
(when-let* ((msg (jupyter-wait-until-received :execute-reply
|
||||||
(jupyter-send-execute-request jupyter-current-client
|
(jupyter-send jupyter-current-client
|
||||||
|
:execute-request
|
||||||
:code ""
|
:code ""
|
||||||
:silent t
|
:silent t
|
||||||
:user-expressions
|
:user-expressions
|
||||||
|
@ -189,14 +190,15 @@ nil."
|
||||||
|
|
||||||
(defun jupyter-julia--setup-hooks (client)
|
(defun jupyter-julia--setup-hooks (client)
|
||||||
(let ((jupyter-inhibit-handlers t))
|
(let ((jupyter-inhibit-handlers t))
|
||||||
(jupyter-send-execute-request client
|
(jupyter-send client
|
||||||
:store-history nil
|
:execute-request
|
||||||
:silent t
|
:store-history nil
|
||||||
;; This is mainly for supporting the :dir header argument in `org-mode'
|
:silent t
|
||||||
;; source blocks. We send this after initializing the REPL and after a
|
;; This is mainly for supporting the :dir header argument in `org-mode'
|
||||||
;; kernel restart so that we can get proper line numbers when an error
|
;; source blocks. We send this after initializing the REPL and after a
|
||||||
;; occurs.
|
;; kernel restart so that we can get proper line numbers when an error
|
||||||
:code "\
|
;; occurs.
|
||||||
|
:code "\
|
||||||
if !isdefined(Main, :__JUPY_saved_dir)
|
if !isdefined(Main, :__JUPY_saved_dir)
|
||||||
Core.eval(Main, :(__JUPY_saved_dir = Ref(\"\")))
|
Core.eval(Main, :(__JUPY_saved_dir = Ref(\"\")))
|
||||||
let popdir = () -> begin
|
let popdir = () -> begin
|
||||||
|
|
|
@ -150,8 +150,7 @@ request on KERNEL's control channel if its kernelspec has an
|
||||||
(format "%s://%s:%d" transport ip control_port)))))
|
(format "%s://%s:%d" transport ip control_port)))))
|
||||||
;; TODO: `with-live-jupyter-channel'
|
;; TODO: `with-live-jupyter-channel'
|
||||||
(jupyter-start channel)
|
(jupyter-start channel)
|
||||||
(jupyter-send channel :interrupt-request
|
(jupyter-send channel :interrupt-request '())
|
||||||
(jupyter-message-interrupt-request))
|
|
||||||
(jupyter-with-timeout
|
(jupyter-with-timeout
|
||||||
((format "Interrupting %s kernel"
|
((format "Interrupting %s kernel"
|
||||||
(jupyter-kernel-name kernel))
|
(jupyter-kernel-name kernel))
|
||||||
|
|
|
@ -369,36 +369,44 @@ and `:msg_type'."
|
||||||
|
|
||||||
;;; Control messages
|
;;; Control messages
|
||||||
|
|
||||||
(cl-defun jupyter-message-interrupt-request ()
|
(cl-defun jupyter-interrupt-request ()
|
||||||
(list))
|
(jupyter-request
|
||||||
|
:type :interrupt-request
|
||||||
|
:content (list)))
|
||||||
|
|
||||||
;;; stdin messages
|
;;; stdin messages
|
||||||
|
|
||||||
(cl-defun jupyter-message-input-reply (&key value)
|
(cl-defun jupyter-input-reply (&key value)
|
||||||
(cl-check-type value string)
|
(cl-check-type value string)
|
||||||
(list :value value))
|
(jupyter-request
|
||||||
|
:type :input-reply
|
||||||
|
:content (list :value value)))
|
||||||
|
|
||||||
;;; shell messages
|
;;; shell messages
|
||||||
|
|
||||||
(cl-defun jupyter-message-kernel-info-request ()
|
(cl-defun jupyter-kernel-info-request ()
|
||||||
(list))
|
(jupyter-request
|
||||||
|
:type :kernel-info-request
|
||||||
|
:content (list)))
|
||||||
|
|
||||||
(cl-defun jupyter-message-execute-request (&key
|
(cl-defun jupyter-execute-request (&key
|
||||||
code
|
code
|
||||||
(silent nil)
|
(silent nil)
|
||||||
(store-history t)
|
(store-history t)
|
||||||
(user-expressions nil)
|
(user-expressions nil)
|
||||||
(allow-stdin t)
|
(allow-stdin t)
|
||||||
(stop-on-error nil))
|
(stop-on-error nil))
|
||||||
(cl-check-type code string)
|
(cl-check-type code string)
|
||||||
(cl-check-type user-expressions json-plist)
|
(cl-check-type user-expressions json-plist)
|
||||||
(list :code code :silent (if silent t jupyter--false)
|
(jupyter-request
|
||||||
:store_history (if store-history t jupyter--false)
|
:type :execute-request
|
||||||
:user_expressions (or user-expressions jupyter--empty-dict)
|
:content (list :code code :silent (if silent t jupyter--false)
|
||||||
:allow_stdin (if allow-stdin t jupyter--false)
|
:store_history (if store-history t jupyter--false)
|
||||||
:stop_on_error (if stop-on-error t jupyter--false)))
|
:user_expressions (or user-expressions jupyter--empty-dict)
|
||||||
|
:allow_stdin (if allow-stdin t jupyter--false)
|
||||||
|
:stop_on_error (if stop-on-error t jupyter--false))))
|
||||||
|
|
||||||
(cl-defun jupyter-message-inspect-request (&key code pos detail)
|
(cl-defun jupyter-inspect-request (&key code (pos 0) (detail 0))
|
||||||
(setq detail (or detail 0))
|
(setq detail (or detail 0))
|
||||||
(unless (member detail '(0 1))
|
(unless (member detail '(0 1))
|
||||||
(error "Detail can only be 0 or 1 (%s)" detail))
|
(error "Detail can only be 0 or 1 (%s)" detail))
|
||||||
|
@ -406,71 +414,89 @@ and `:msg_type'."
|
||||||
(setq pos (marker-position pos)))
|
(setq pos (marker-position pos)))
|
||||||
(cl-check-type code string)
|
(cl-check-type code string)
|
||||||
(cl-check-type pos integer)
|
(cl-check-type pos integer)
|
||||||
(list :code code :cursor_pos pos :detail_level detail))
|
(jupyter-request
|
||||||
|
:type :inspect-request
|
||||||
|
:content (list :code code :cursor_pos pos :detail_level detail)))
|
||||||
|
|
||||||
(cl-defun jupyter-message-complete-request (&key code pos)
|
(cl-defun jupyter-complete-request (&key code (pos 0))
|
||||||
(when (markerp pos)
|
(when (markerp pos)
|
||||||
(setq pos (marker-position pos)))
|
(setq pos (marker-position pos)))
|
||||||
(cl-check-type code string)
|
(cl-check-type code string)
|
||||||
(cl-check-type pos integer)
|
(cl-check-type pos integer)
|
||||||
(list :code code :cursor_pos pos))
|
(jupyter-request
|
||||||
|
:type :complete-requesr
|
||||||
|
:content (list :code code :cursor_pos pos)))
|
||||||
|
|
||||||
(cl-defun jupyter-message-history-request (&key
|
(cl-defun jupyter-history-request (&key
|
||||||
output
|
output
|
||||||
raw
|
raw
|
||||||
hist-access-type
|
(hist-access-type "tail")
|
||||||
session
|
session
|
||||||
start
|
start
|
||||||
stop
|
stop
|
||||||
n
|
(n 10)
|
||||||
pattern
|
pattern
|
||||||
unique)
|
unique)
|
||||||
(unless (member hist-access-type '("range" "tail" "search"))
|
(unless (member hist-access-type '("range" "tail" "search"))
|
||||||
(error "History access type can only be one of (range, tail, search)"))
|
(error "History access type can only be one of (range, tail, search)"))
|
||||||
(append
|
(jupyter-request
|
||||||
(list :output (if output t jupyter--false) :raw (if raw t jupyter--false)
|
:type :history-request
|
||||||
:hist_access_type hist-access-type)
|
:content
|
||||||
(cond
|
(append
|
||||||
((equal hist-access-type "range")
|
(list :output (if output t jupyter--false) :raw (if raw t jupyter--false)
|
||||||
(cl-check-type session integer)
|
:hist_access_type hist-access-type)
|
||||||
(cl-check-type start integer)
|
(cond
|
||||||
(cl-check-type stop integer)
|
((equal hist-access-type "range")
|
||||||
(list :session session :start start :stop stop))
|
(cl-check-type session integer)
|
||||||
((equal hist-access-type "tail")
|
(cl-check-type start integer)
|
||||||
(cl-check-type n integer)
|
(cl-check-type stop integer)
|
||||||
(list :n n))
|
(list :session session :start start :stop stop))
|
||||||
((equal hist-access-type "search")
|
((equal hist-access-type "tail")
|
||||||
(cl-check-type pattern string)
|
(cl-check-type n integer)
|
||||||
(cl-check-type n integer)
|
(list :n n))
|
||||||
(list :pattern pattern :unique (if unique t jupyter--false) :n n)))))
|
((equal hist-access-type "search")
|
||||||
|
(cl-check-type pattern string)
|
||||||
|
(cl-check-type n integer)
|
||||||
|
(list :pattern pattern :unique (if unique t jupyter--false) :n n))))))
|
||||||
|
|
||||||
(cl-defun jupyter-message-is-complete-request (&key code)
|
(cl-defun jupyter-is-complete-request (&key code)
|
||||||
(cl-check-type code string)
|
(cl-check-type code string)
|
||||||
(list :code code))
|
(jupyter-request
|
||||||
|
:type :is-complete-request
|
||||||
|
:content (list :code code)))
|
||||||
|
|
||||||
(cl-defun jupyter-message-comm-info-request (&key target-name)
|
(cl-defun jupyter-message-comm-info-request (&key target-name)
|
||||||
(when target-name
|
(cl-check-type target-name string)
|
||||||
(cl-check-type target-name string)
|
(jupyter-request
|
||||||
(list :target_name target-name)))
|
:type :comm-info-request
|
||||||
|
:content (list :target_name target-name)))
|
||||||
|
|
||||||
(cl-defun jupyter-message-comm-open (&key id target-name data)
|
(cl-defun jupyter-comm-open (&key id target-name data)
|
||||||
(cl-check-type id string)
|
(cl-check-type id string)
|
||||||
(cl-check-type target-name string)
|
(cl-check-type target-name string)
|
||||||
(cl-check-type data json-plist)
|
(cl-check-type data json-plist)
|
||||||
(list :comm_id id :target_name target-name :data data))
|
(jupyter-request
|
||||||
|
:type :comm-open
|
||||||
|
:content (list :comm_id id :target_name target-name :data data)))
|
||||||
|
|
||||||
(cl-defun jupyter-message-comm-msg (&key id data)
|
(cl-defun jupyter-comm-msg (&key id data)
|
||||||
(cl-check-type id string)
|
(cl-check-type id string)
|
||||||
(cl-check-type data json-plist)
|
(cl-check-type data json-plist)
|
||||||
(list :comm_id id :data data))
|
(jupyter-request
|
||||||
|
:type :comm-msg
|
||||||
|
:content (list :comm_id id :data data)))
|
||||||
|
|
||||||
(cl-defun jupyter-message-comm-close (&key id data)
|
(cl-defun jupyter-comm-close (&key id data)
|
||||||
(cl-check-type id string)
|
(cl-check-type id string)
|
||||||
(cl-check-type data json-plist)
|
(cl-check-type data json-plist)
|
||||||
(list :comm_id id :data data))
|
(jupyter-request
|
||||||
|
:type :comm-close
|
||||||
|
:content (list :comm_id id :data data)))
|
||||||
|
|
||||||
(cl-defun jupyter-message-shutdown-request (&key restart)
|
(cl-defun jupyter-shutdown-request (&key restart)
|
||||||
(list :restart (if restart t jupyter--false)))
|
(jupyter-request
|
||||||
|
:type :shutdown-request
|
||||||
|
:content (list :restart (if restart t jupyter--false))))
|
||||||
|
|
||||||
;;; Convenience functions and macros
|
;;; Convenience functions and macros
|
||||||
|
|
||||||
|
|
|
@ -602,10 +602,9 @@ first move is to the beginning of the current cell."
|
||||||
|
|
||||||
(defun jupyter-repl-goto-cell (req)
|
(defun jupyter-repl-goto-cell (req)
|
||||||
"Go to the cell beginning position of REQ.
|
"Go to the cell beginning position of REQ.
|
||||||
REQ should be a `jupyter-request' that corresponds to one of the
|
REQ should be a `jupyter-request' associated with a cell in the
|
||||||
`jupyter-send-execute-request's created by a cell in the
|
`current-buffer'. Note that the `current-buffer' is assumed to
|
||||||
`current-buffer'. Note that the `current-buffer' is assumed to be
|
be a Jupyter REPL buffer."
|
||||||
a Jupyter REPL buffer."
|
|
||||||
(goto-char (point-max))
|
(goto-char (point-max))
|
||||||
(unless (catch 'done
|
(unless (catch 'done
|
||||||
(while (= (jupyter-repl-previous-cell) 0)
|
(while (= (jupyter-repl-previous-cell) 0)
|
||||||
|
@ -811,33 +810,28 @@ lines, truncate it to something less than
|
||||||
(ring-remove jupyter-repl-history -2))
|
(ring-remove jupyter-repl-history -2))
|
||||||
(ring-remove+insert+extend jupyter-repl-history code))
|
(ring-remove+insert+extend jupyter-repl-history code))
|
||||||
|
|
||||||
(cl-defmethod jupyter-send-execute-request ((client jupyter-repl-client)
|
(defun jupyter-repl-execute-cell (client)
|
||||||
&key code
|
"Execute the last REPL cell of CLIENT.
|
||||||
(silent nil)
|
Return the `jupyter-request' representing the executed code."
|
||||||
(store-history t)
|
(cl-check-type client jupyter-repl-client)
|
||||||
(user-expressions nil)
|
(jupyter-with-repl-buffer client
|
||||||
(allow-stdin t)
|
(jupyter-repl-truncate-buffer)
|
||||||
(stop-on-error nil))
|
(save-excursion
|
||||||
(if code (cl-call-next-method)
|
(goto-char (jupyter-repl-cell-code-beginning-position))
|
||||||
(jupyter-with-repl-buffer client
|
(run-hooks 'jupyter-repl-cell-pre-send-hook))
|
||||||
(jupyter-repl-truncate-buffer)
|
(let ((code (string-trim (jupyter-repl-cell-code))))
|
||||||
(save-excursion
|
(let ((req (jupyter-send client
|
||||||
(goto-char (jupyter-repl-cell-code-beginning-position))
|
:execute-request
|
||||||
(run-hooks 'jupyter-repl-cell-pre-send-hook))
|
:code code
|
||||||
(setq code (string-trim (jupyter-repl-cell-code)))
|
;; Handle empty code cells as just an update of the
|
||||||
;; Handle empty code cells as just an update of the prompt number
|
;; prompt number
|
||||||
(if (= (length code) 0)
|
:silent (and (= (length code) 0) t))))
|
||||||
(setq silent t)
|
|
||||||
;; Needed by the prompt insertion below
|
|
||||||
(oset client execution-count (1+ (oref client execution-count)))
|
|
||||||
(jupyter-repl-history-add code))
|
|
||||||
(let ((req (cl-call-next-method
|
|
||||||
client :code code :silent silent :store-history store-history
|
|
||||||
:user-expressions user-expressions :allow-stdin allow-stdin
|
|
||||||
:stop-on-error stop-on-error)))
|
|
||||||
(jupyter-repl-without-continuation-prompts
|
(jupyter-repl-without-continuation-prompts
|
||||||
(jupyter-repl-cell-mark-busy)
|
(jupyter-repl-cell-mark-busy)
|
||||||
(jupyter-repl-finalize-cell req)
|
(jupyter-repl-finalize-cell req)
|
||||||
|
(jupyter-repl-history-add code)
|
||||||
|
;; Needed by the prompt insertion below
|
||||||
|
(oset client execution-count (1+ (oref client execution-count)))
|
||||||
(jupyter-repl-insert-prompt 'in))
|
(jupyter-repl-insert-prompt 'in))
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(jupyter-repl-backward-cell)
|
(jupyter-repl-backward-cell)
|
||||||
|
@ -1111,17 +1105,17 @@ elements."
|
||||||
(jupyter-with-message-content msg (status indent)
|
(jupyter-with-message-content msg (status indent)
|
||||||
(pcase status
|
(pcase status
|
||||||
("complete"
|
("complete"
|
||||||
(jupyter-send-execute-request client))
|
(jupyter-repl-execute-cell client))
|
||||||
("incomplete"
|
("incomplete"
|
||||||
(insert "\n")
|
(insert "\n")
|
||||||
(if (= (length indent) 0) (jupyter-repl-indent-line)
|
(if (= (length indent) 0) (jupyter-repl-indent-line)
|
||||||
(insert indent)))
|
(insert indent)))
|
||||||
("invalid"
|
("invalid"
|
||||||
;; Force an execute to produce a traceback
|
;; Force an execute to produce a traceback
|
||||||
(jupyter-send-execute-request client))
|
(jupyter-repl-execute-cell client))
|
||||||
("unknown"
|
("unknown"
|
||||||
;; Let the kernel decide if the code is complete
|
;; Let the kernel decide if the code is complete
|
||||||
(jupyter-send-execute-request client))))))
|
(jupyter-repl-execute-cell client))))))
|
||||||
|
|
||||||
(defun jupyter-repl--insert-banner-and-prompt (client)
|
(defun jupyter-repl--insert-banner-and-prompt (client)
|
||||||
(jupyter-with-repl-buffer client
|
(jupyter-with-repl-buffer client
|
||||||
|
@ -1185,7 +1179,7 @@ execute the current cell."
|
||||||
(not jupyter-repl-allow-RET-when-busy))
|
(not jupyter-repl-allow-RET-when-busy))
|
||||||
(error "Kernel busy"))
|
(error "Kernel busy"))
|
||||||
(cond
|
(cond
|
||||||
(force (jupyter-send-execute-request jupyter-current-client))
|
(force (jupyter-repl-execute-cell jupyter-current-client))
|
||||||
((or jupyter-repl-use-builtin-is-complete
|
((or jupyter-repl-use-builtin-is-complete
|
||||||
(and jupyter-repl-allow-RET-when-busy
|
(and jupyter-repl-allow-RET-when-busy
|
||||||
(jupyter-kernel-busy-p jupyter-current-client)))
|
(jupyter-kernel-busy-p jupyter-current-client)))
|
||||||
|
@ -1199,8 +1193,8 @@ execute the current cell."
|
||||||
(t
|
(t
|
||||||
(let ((res (jupyter-wait-until-received :is-complete-reply
|
(let ((res (jupyter-wait-until-received :is-complete-reply
|
||||||
(let ((jupyter-inhibit-handlers '(not :is-complete-reply)))
|
(let ((jupyter-inhibit-handlers '(not :is-complete-reply)))
|
||||||
(jupyter-send-is-complete-request
|
(jupyter-send jupyter-current-client
|
||||||
jupyter-current-client
|
:is-complete-request
|
||||||
:code (jupyter-repl-cell-code)))
|
:code (jupyter-repl-cell-code)))
|
||||||
jupyter-repl-maximum-is-complete-timeout)))
|
jupyter-repl-maximum-is-complete-timeout)))
|
||||||
(unless res
|
(unless res
|
||||||
|
@ -1451,9 +1445,10 @@ value."
|
||||||
;; update the REPL state
|
;; update the REPL state
|
||||||
(unless jupyter-repl-echo-eval-p
|
(unless jupyter-repl-echo-eval-p
|
||||||
'(not :input-request))))
|
'(not :input-request))))
|
||||||
(setq req (jupyter-send-execute-request jupyter-current-client
|
(setq req (jupyter-send jupyter-current-client
|
||||||
:code str
|
:execute-request
|
||||||
:store-history jupyter-repl-echo-eval-p))
|
:code str
|
||||||
|
:store-history jupyter-repl-echo-eval-p))
|
||||||
(if jupyter-repl-echo-eval-p
|
(if jupyter-repl-echo-eval-p
|
||||||
(jupyter-repl-replace-cell-code cell-previous-code))))
|
(jupyter-repl-replace-cell-code cell-previous-code))))
|
||||||
;; Add callbacks to display evaluation output in pop-up buffers either when
|
;; Add callbacks to display evaluation output in pop-up buffers either when
|
||||||
|
@ -1696,8 +1691,11 @@ Return the buffer switched to."
|
||||||
;; ring.
|
;; ring.
|
||||||
(ring-insert jupyter-repl-history 'jupyter-repl-history)
|
(ring-insert jupyter-repl-history 'jupyter-repl-history)
|
||||||
(let ((jupyter-inhibit-handlers '(:status)))
|
(let ((jupyter-inhibit-handlers '(:status)))
|
||||||
(jupyter-send-history-request jupyter-current-client
|
(jupyter-send jupyter-current-client
|
||||||
:n jupyter-repl-history-maximum-length :raw nil :unique t))
|
:history-request
|
||||||
|
:n jupyter-repl-history-maximum-length
|
||||||
|
:raw nil
|
||||||
|
:unique t))
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
;; Add local hooks
|
;; Add local hooks
|
||||||
(add-hook 'kill-buffer-query-functions #'jupyter-repl-kill-buffer-query-function nil t)
|
(add-hook 'kill-buffer-query-functions #'jupyter-repl-kill-buffer-query-function nil t)
|
||||||
|
@ -1815,7 +1813,10 @@ Also update the cell count of the current REPL input prompt using
|
||||||
the updated state."
|
the updated state."
|
||||||
(let* ((client jupyter-current-client)
|
(let* ((client jupyter-current-client)
|
||||||
(req (let ((jupyter-inhibit-handlers t))
|
(req (let ((jupyter-inhibit-handlers t))
|
||||||
(jupyter-send-execute-request client :code "" :silent t))))
|
(jupyter-send client
|
||||||
|
:execute-request
|
||||||
|
:code ""
|
||||||
|
:silent t))))
|
||||||
(jupyter-add-callback req
|
(jupyter-add-callback req
|
||||||
:execute-reply
|
:execute-reply
|
||||||
(jupyter-message-lambda (execution_count)
|
(jupyter-message-lambda (execution_count)
|
||||||
|
|
|
@ -208,7 +208,7 @@ return nil."
|
||||||
(with-current-buffer (org-babel-jupyter-initiate-session session params)
|
(with-current-buffer (org-babel-jupyter-initiate-session session params)
|
||||||
(goto-char (point-max))
|
(goto-char (point-max))
|
||||||
(and (org-babel-jupyter--insert-variable-assignments params)
|
(and (org-babel-jupyter--insert-variable-assignments params)
|
||||||
(jupyter-send-execute-request jupyter-current-client))
|
(jupyter-repl-execute-cell jupyter-current-client))
|
||||||
(current-buffer)))
|
(current-buffer)))
|
||||||
|
|
||||||
(defun org-babel-load-session:jupyter (session body params)
|
(defun org-babel-load-session:jupyter (session body params)
|
||||||
|
@ -428,7 +428,9 @@ These parameters are handled internally."
|
||||||
(delq fparam params)))
|
(delq fparam params)))
|
||||||
|
|
||||||
(defun org-babel-jupyter--execute (code async-p)
|
(defun org-babel-jupyter--execute (code async-p)
|
||||||
(let ((req (jupyter-send-execute-request jupyter-current-client :code code)))
|
(let ((req (jupyter-send jupyter-current-client
|
||||||
|
(jupyter-execute-request
|
||||||
|
:code code))))
|
||||||
`(,req
|
`(,req
|
||||||
,(cond
|
,(cond
|
||||||
(async-p
|
(async-p
|
||||||
|
|
|
@ -47,8 +47,7 @@
|
||||||
:tags '(mock)
|
:tags '(mock)
|
||||||
(jupyter-with-echo-client client
|
(jupyter-with-echo-client client
|
||||||
(ert-info ("Mock echo client echo's messages back to channel.")
|
(ert-info ("Mock echo client echo's messages back to channel.")
|
||||||
(let* ((msg (jupyter-message-execute-request :code "foo"))
|
(let ((req (jupyter-send client :execute-request :code "foo")))
|
||||||
(req (jupyter-send client :shell :execute-request msg)))
|
|
||||||
(sleep-for 0.3)
|
(sleep-for 0.3)
|
||||||
(setq msgs (nreverse (ring-elements (oref client messages))))
|
(setq msgs (nreverse (ring-elements (oref client messages))))
|
||||||
(should (= (length msgs) 3))
|
(should (= (length msgs) 3))
|
||||||
|
@ -71,7 +70,7 @@
|
||||||
(ert-deftest jupyter-wait-until-idle ()
|
(ert-deftest jupyter-wait-until-idle ()
|
||||||
:tags '(callbacks)
|
:tags '(callbacks)
|
||||||
(jupyter-with-echo-client client
|
(jupyter-with-echo-client client
|
||||||
(let ((req (jupyter-send-execute-request client :code "foo")))
|
(let ((req (jupyter-send client :execute-request :code "foo")))
|
||||||
(ert-info ("Blocking callbacks")
|
(ert-info ("Blocking callbacks")
|
||||||
(jupyter-wait-until-idle req)
|
(jupyter-wait-until-idle req)
|
||||||
(should (jupyter-request-idle-p req)))
|
(should (jupyter-request-idle-p req)))
|
||||||
|
@ -86,7 +85,7 @@
|
||||||
(cb (lambda (msg)
|
(cb (lambda (msg)
|
||||||
(should (eq (jupyter-message-type msg) :status))
|
(should (eq (jupyter-message-type msg) :status))
|
||||||
(setq callback-count (1+ callback-count))))
|
(setq callback-count (1+ callback-count))))
|
||||||
(req (jupyter-send-execute-request client :code "foo")))
|
(req (jupyter-send client :execute-request :code "foo")))
|
||||||
(jupyter-add-callback req :status cb)
|
(jupyter-add-callback req :status cb)
|
||||||
(jupyter-wait-until-idle req)
|
(jupyter-wait-until-idle req)
|
||||||
(should (= callback-count 2))))
|
(should (= callback-count 2))))
|
||||||
|
@ -96,7 +95,7 @@
|
||||||
(setq callback-count (1+ callback-count))
|
(setq callback-count (1+ callback-count))
|
||||||
(should (memq (jupyter-message-type msg)
|
(should (memq (jupyter-message-type msg)
|
||||||
'(:status :execute-reply)))))
|
'(:status :execute-reply)))))
|
||||||
(req (jupyter-send-execute-request client :code "foo")))
|
(req (jupyter-send client :execute-request :code "foo")))
|
||||||
(jupyter-add-callback req '(:status :execute-reply) cb)
|
(jupyter-add-callback req '(:status :execute-reply) cb)
|
||||||
(jupyter-wait-until-idle req)
|
(jupyter-wait-until-idle req)
|
||||||
(should (= callback-count 3))))))
|
(should (= callback-count 3))))))
|
||||||
|
@ -409,19 +408,19 @@
|
||||||
(jupyter-test-with-python-client client
|
(jupyter-test-with-python-client client
|
||||||
(ert-info ("Kernel info")
|
(ert-info ("Kernel info")
|
||||||
(let ((res (jupyter-wait-until-received :kernel-info-reply
|
(let ((res (jupyter-wait-until-received :kernel-info-reply
|
||||||
(jupyter-send-kernel-info-request client))))
|
(jupyter-send client :kernel-info-request))))
|
||||||
(should res)
|
(should res)
|
||||||
(should (json-plist-p res))
|
(should (json-plist-p res))
|
||||||
(should (eq (jupyter-message-type res) :kernel-info-reply))))
|
(should (eq (jupyter-message-type res) :kernel-info-reply))))
|
||||||
(ert-info ("Comm info")
|
(ert-info ("Comm info")
|
||||||
(let ((res (jupyter-wait-until-received :comm-info-reply
|
(let ((res (jupyter-wait-until-received :comm-info-reply
|
||||||
(jupyter-send-comm-info-request client))))
|
(jupyter-send client :comm-info-request))))
|
||||||
(should-not (null res))
|
(should-not (null res))
|
||||||
(should (json-plist-p res))
|
(should (json-plist-p res))
|
||||||
(should (eq (jupyter-message-type res) :comm-info-reply))))
|
(should (eq (jupyter-message-type res) :comm-info-reply))))
|
||||||
(ert-info ("Execute")
|
(ert-info ("Execute")
|
||||||
(let ((res (jupyter-wait-until-received :execute-reply
|
(let ((res (jupyter-wait-until-received :execute-reply
|
||||||
(jupyter-send-execute-request client :code "y = 1 + 2"))))
|
(jupyter-send client :execute-request :code "y = 1 + 2"))))
|
||||||
(should-not (null res))
|
(should-not (null res))
|
||||||
(should (json-plist-p res))
|
(should (json-plist-p res))
|
||||||
(should (eq (jupyter-message-type res) :execute-reply))))
|
(should (eq (jupyter-message-type res) :execute-reply))))
|
||||||
|
@ -429,45 +428,49 @@
|
||||||
(cl-letf (((symbol-function 'read-from-minibuffer)
|
(cl-letf (((symbol-function 'read-from-minibuffer)
|
||||||
(lambda (_prompt &rest _args) "foo")))
|
(lambda (_prompt &rest _args) "foo")))
|
||||||
(let ((res (jupyter-wait-until-received :execute-result
|
(let ((res (jupyter-wait-until-received :execute-result
|
||||||
(jupyter-send-execute-request client :code "input('')"))))
|
(jupyter-send client :execute-request :code "input('')"))))
|
||||||
(should-not (null res))
|
(should-not (null res))
|
||||||
(should (json-plist-p res))
|
(should (json-plist-p res))
|
||||||
(should (eq (jupyter-message-type res) :execute-result))
|
(should (eq (jupyter-message-type res) :execute-result))
|
||||||
(should (equal (jupyter-message-data res :text/plain) "'foo'")))))
|
(should (equal (jupyter-message-data res :text/plain) "'foo'")))))
|
||||||
(ert-info ("Inspect")
|
(ert-info ("Inspect")
|
||||||
(let ((res (jupyter-wait-until-received :inspect-reply
|
(let ((res (jupyter-wait-until-received :inspect-reply
|
||||||
(jupyter-send-inspect-request client
|
(jupyter-send client
|
||||||
:code "list((1, 2, 3))"
|
:inspect-request
|
||||||
:pos 2
|
:code "list((1, 2, 3))"
|
||||||
:detail 0))))
|
:pos 2
|
||||||
|
:detail 0))))
|
||||||
(should-not (null res))
|
(should-not (null res))
|
||||||
(should (json-plist-p res))
|
(should (json-plist-p res))
|
||||||
(should (eq (jupyter-message-type res) :inspect-reply))))
|
(should (eq (jupyter-message-type res) :inspect-reply))))
|
||||||
(ert-info ("Complete")
|
(ert-info ("Complete")
|
||||||
(let ((res (jupyter-wait-until-received :complete-reply
|
(let ((res (jupyter-wait-until-received :complete-reply
|
||||||
(jupyter-send-complete-request client
|
(jupyter-send client
|
||||||
:code "foo = lis"
|
:complete-request
|
||||||
:pos 8))))
|
:code "foo = lis"
|
||||||
|
:pos 8))))
|
||||||
(should-not (null res))
|
(should-not (null res))
|
||||||
(should (json-plist-p res))
|
(should (json-plist-p res))
|
||||||
(should (eq (jupyter-message-type res) :complete-reply))))
|
(should (eq (jupyter-message-type res) :complete-reply))))
|
||||||
(ert-info ("History")
|
(ert-info ("History")
|
||||||
(let ((res (jupyter-wait-until-received :history-reply
|
(let ((res (jupyter-wait-until-received :history-reply
|
||||||
(jupyter-send-history-request client
|
(jupyter-send client
|
||||||
:hist-access-type "tail" :n 2))))
|
:history-request
|
||||||
|
:hist-access-type "tail" :n 2))))
|
||||||
(should-not (null res))
|
(should-not (null res))
|
||||||
(should (json-plist-p res))
|
(should (json-plist-p res))
|
||||||
(should (eq (jupyter-message-type res) :history-reply))))
|
(should (eq (jupyter-message-type res) :history-reply))))
|
||||||
(ert-info ("Is Complete")
|
(ert-info ("Is Complete")
|
||||||
(let ((res (jupyter-wait-until-received :is-complete-reply
|
(let ((res (jupyter-wait-until-received :is-complete-reply
|
||||||
(jupyter-send-is-complete-request client
|
(jupyter-send client
|
||||||
:code "for i in range(5):"))))
|
:is-complete-request
|
||||||
|
:code "for i in range(5):"))))
|
||||||
(should-not (null res))
|
(should-not (null res))
|
||||||
(should (json-plist-p res))
|
(should (json-plist-p res))
|
||||||
(should (eq (jupyter-message-type res) :is-complete-reply))))
|
(should (eq (jupyter-message-type res) :is-complete-reply))))
|
||||||
(ert-info ("Shutdown")
|
(ert-info ("Shutdown")
|
||||||
(let ((res (jupyter-wait-until-received :shutdown-reply
|
(let ((res (jupyter-wait-until-received :shutdown-reply
|
||||||
(jupyter-send-shutdown-request client))))
|
(jupyter-send client :shutdown-request))))
|
||||||
(should-not (null res))
|
(should-not (null res))
|
||||||
(should (json-plist-p res))
|
(should (json-plist-p res))
|
||||||
(should (eq (jupyter-message-type res) :shutdown-reply))
|
(should (eq (jupyter-message-type res) :shutdown-reply))
|
||||||
|
@ -814,14 +817,14 @@
|
||||||
:tags '(client handlers)
|
:tags '(client handlers)
|
||||||
(jupyter-test-with-python-client client
|
(jupyter-test-with-python-client client
|
||||||
(let* ((jupyter-inhibit-handlers '(:stream))
|
(let* ((jupyter-inhibit-handlers '(:stream))
|
||||||
(req (jupyter-send-kernel-info-request client)))
|
(req (jupyter-send client :kernel-info-request)))
|
||||||
(should (equal (jupyter-request-inhibited-handlers req)
|
(should (equal (jupyter-request-inhibited-handlers req)
|
||||||
'(:stream)))
|
'(:stream)))
|
||||||
(should-not (jupyter--request-allows-handler-p
|
(should-not (jupyter--request-allows-handler-p
|
||||||
req (jupyter-test-message
|
req (jupyter-test-message
|
||||||
req :stream (list :name "stdout" :text "foo"))))
|
req :stream (list :name "stdout" :text "foo"))))
|
||||||
(setq jupyter-inhibit-handlers '(:foo))
|
(setq jupyter-inhibit-handlers '(:foo))
|
||||||
(should-error (jupyter-send-kernel-info-request client)))))
|
(should-error (jupyter-send client :kernel-info-request)))))
|
||||||
|
|
||||||
(ert-deftest jupyter-requests-pending-p ()
|
(ert-deftest jupyter-requests-pending-p ()
|
||||||
:tags '(client)
|
:tags '(client)
|
||||||
|
@ -835,7 +838,7 @@
|
||||||
;; print the class object on failure and will fail at doing so.
|
;; print the class object on failure and will fail at doing so.
|
||||||
(setq pending (jupyter-requests-pending-p client))
|
(setq pending (jupyter-requests-pending-p client))
|
||||||
(should-not pending)
|
(should-not pending)
|
||||||
(let ((req (jupyter-send-kernel-info-request client)))
|
(let ((req (jupyter-send client :kernel-info-request)))
|
||||||
(ert-info ("Pending after send")
|
(ert-info ("Pending after send")
|
||||||
(setq pending (jupyter-requests-pending-p client))
|
(setq pending (jupyter-requests-pending-p client))
|
||||||
(should pending)
|
(should pending)
|
||||||
|
@ -843,8 +846,9 @@
|
||||||
(setq pending (jupyter-requests-pending-p client))
|
(setq pending (jupyter-requests-pending-p client))
|
||||||
(should-not pending))
|
(should-not pending))
|
||||||
(ert-info ("Pending until idle received")
|
(ert-info ("Pending until idle received")
|
||||||
(setq req (jupyter-send-execute-request client
|
(setq req (jupyter-send client
|
||||||
:code "import time; time.sleep(0.2)"))
|
:execute-request
|
||||||
|
:code "import time; time.sleep(0.2)"))
|
||||||
;; Empty out the pending-requests slot of CLIENT
|
;; Empty out the pending-requests slot of CLIENT
|
||||||
(jupyter-wait-until-received :status req)
|
(jupyter-wait-until-received :status req)
|
||||||
(setq pending (jupyter-requests-pending-p client))
|
(setq pending (jupyter-requests-pending-p client))
|
||||||
|
@ -930,11 +934,11 @@
|
||||||
(ert-deftest jupyter-idle-sync ()
|
(ert-deftest jupyter-idle-sync ()
|
||||||
:tags '(client hook)
|
:tags '(client hook)
|
||||||
(jupyter-test-with-python-client client
|
(jupyter-test-with-python-client client
|
||||||
(let ((req (jupyter-send-execute-request client :code "1 + 1")))
|
(let ((req (jupyter-send client :execute-request :code "1 + 1")))
|
||||||
(should-not (jupyter-request-idle-p req))
|
(should-not (jupyter-request-idle-p req))
|
||||||
(jupyter-idle-sync req)
|
(jupyter-idle-sync req)
|
||||||
(should (jupyter-request-idle-p req)))
|
(should (jupyter-request-idle-p req)))
|
||||||
(let ((req (jupyter-send-execute-request client :code "1 + 1")))
|
(let ((req (jupyter-send client :execute-request :code "1 + 1")))
|
||||||
(should (null jupyter-test-idle-sync-hook))
|
(should (null jupyter-test-idle-sync-hook))
|
||||||
(jupyter-add-idle-sync-hook 'jupyter-test-idle-sync-hook req)
|
(jupyter-add-idle-sync-hook 'jupyter-test-idle-sync-hook req)
|
||||||
(should-not (null jupyter-test-idle-sync-hook))
|
(should-not (null jupyter-test-idle-sync-hook))
|
||||||
|
@ -1106,13 +1110,12 @@
|
||||||
|
|
||||||
(ert-deftest jupyter-zmq-channel-ioloop-send-fast ()
|
(ert-deftest jupyter-zmq-channel-ioloop-send-fast ()
|
||||||
:tags '(ioloop queue)
|
:tags '(ioloop queue)
|
||||||
;; :expected-result :failed
|
|
||||||
(jupyter-test-with-python-client client
|
(jupyter-test-with-python-client client
|
||||||
(let ((jupyter-current-client client))
|
(let ((jupyter-current-client client))
|
||||||
(jupyter-send-execute-request client :code "1 + 1")
|
(jupyter-send client :execute-request :code "1 + 1")
|
||||||
(jupyter-send-execute-request client :code "1 + 1")
|
(jupyter-send client :execute-request :code "1 + 1")
|
||||||
(jupyter-send-execute-request client :code "1 + 1")
|
(jupyter-send client :execute-request :code "1 + 1")
|
||||||
(let ((req (jupyter-send-execute-request client :code "1 + 1")))
|
(let ((req (jupyter-send client :execute-request :code "1 + 1")))
|
||||||
(should
|
(should
|
||||||
(equal
|
(equal
|
||||||
(jupyter-message-data
|
(jupyter-message-data
|
||||||
|
@ -1576,7 +1579,7 @@ last element being the newest element added to the history."
|
||||||
(jupyter-ert-info ("Cell boundary errors")
|
(jupyter-ert-info ("Cell boundary errors")
|
||||||
(goto-char (point-max))
|
(goto-char (point-max))
|
||||||
(jupyter-repl-replace-cell-code "1 + 1")
|
(jupyter-repl-replace-cell-code "1 + 1")
|
||||||
(jupyter-wait-until-idle (jupyter-send-execute-request client))
|
(jupyter-wait-until-idle (jupyter-repl-execute-cell client))
|
||||||
(forward-line -2)
|
(forward-line -2)
|
||||||
(should (eq (car (get-text-property (1- (point)) 'jupyter-cell))
|
(should (eq (car (get-text-property (1- (point)) 'jupyter-cell))
|
||||||
'out))
|
'out))
|
||||||
|
@ -1814,8 +1817,9 @@ next(x"))))))
|
||||||
(unwind-protect
|
(unwind-protect
|
||||||
(let ((msg (jupyter-wait-until-received :execute-result
|
(let ((msg (jupyter-wait-until-received :execute-result
|
||||||
(let ((jupyter-inhibit-handlers t))
|
(let ((jupyter-inhibit-handlers t))
|
||||||
(jupyter-send-execute-request cclient
|
(jupyter-send cclient
|
||||||
:code "1 + 1")))))
|
:execute-request
|
||||||
|
:code "1 + 1")))))
|
||||||
(should msg)
|
(should msg)
|
||||||
(should (equal (jupyter-message-data msg :text/plain) "2")))
|
(should (equal (jupyter-message-data msg :text/plain) "2")))
|
||||||
(with-current-buffer (oref cclient buffer)
|
(with-current-buffer (oref cclient buffer)
|
||||||
|
|
|
@ -97,12 +97,8 @@ handling a message is always
|
||||||
:send #'ignore
|
:send #'ignore
|
||||||
:alive-p #'ignore))))
|
:alive-p #'ignore))))
|
||||||
|
|
||||||
(cl-defmethod jupyter-send ((client jupyter-echo-client)
|
(cl-defmethod jupyter-send ((client jupyter-echo-client) (type symbol) &rest content)
|
||||||
channel
|
(let ((req (jupyter-request :type type :content content)))
|
||||||
type
|
|
||||||
message
|
|
||||||
&optional _flags)
|
|
||||||
(let ((req (jupyter-request :id (jupyter-new-uuid))))
|
|
||||||
(if (string-match "request" (symbol-name type))
|
(if (string-match "request" (symbol-name type))
|
||||||
(setq type (intern (replace-match "reply" nil nil (symbol-name type))))
|
(setq type (intern (replace-match "reply" nil nil (symbol-name type))))
|
||||||
(error "Not a request message type (%s)" type))
|
(error "Not a request message type (%s)" type))
|
||||||
|
@ -198,7 +194,7 @@ If the `current-buffer' is not a REPL, this is identical to
|
||||||
(when ,saved
|
(when ,saved
|
||||||
(if (oref ,saved manager)
|
(if (oref ,saved manager)
|
||||||
(jupyter-shutdown-kernel (oref ,saved manager))
|
(jupyter-shutdown-kernel (oref ,saved manager))
|
||||||
(jupyter-send-shutdown-request ,saved))
|
(jupyter-send ,saved :shutdown-request))
|
||||||
;; FIXME: This will be removed after the transition
|
;; FIXME: This will be removed after the transition
|
||||||
(ignore-errors (jupyter-stop-channels ,saved)))
|
(ignore-errors (jupyter-stop-channels ,saved)))
|
||||||
(let ((client (,client-fun (jupyter-kernelspec-name ,spec))))
|
(let ((client (,client-fun (jupyter-kernelspec-name ,spec))))
|
||||||
|
|
Loading…
Add table
Reference in a new issue