Remove jupyter-send-* methods

These methods were not used much internally.
This commit is contained in:
Nathaniel Nicandro 2020-04-29 22:20:28 -05:00
parent 0c6d90cc7e
commit 348df7feb5
9 changed files with 240 additions and 292 deletions

View file

@ -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
request is also kept track of.
Each request contains: a message ID, a time sent, a last message
received by the client that sent it, a list of message types that
tell the client to not call the handler methods of those types,
and an alist mapping message types to callback functions a client
should call."
(id "")
Each request contains: a message ID, a request type, a request
message, a time sent, a last message received by the client that
sent it, a list of message types that tell the client to not call
the handler methods of those types, and an alist mapping message
types to callback functions a client should call."
(id (jupyter-new-uuid) :read-only t)
(type nil :read-only t)
(content nil :read-only t)
(time (current-time) :read-only t)
(idle-p nil)
(last-message nil)

View file

@ -169,7 +169,7 @@ For example to prevent a client from calling its :execute-reply
handler:
(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
`not', then inhibit handlers not in the list.
@ -300,45 +300,6 @@ method is called."
,(or doc (format "A :%s handler." type))
,@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'
(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)
do (error "Not a valid message type (`%s')" msg-type))))
(cl-defmethod jupyter-send ((client jupyter-kernel-client)
channel
type
message
&optional msg-id)
;; FIXME: Remove the need for this
(defun jupyter--merge-message-defaults (type content)
(let ((req (intern (concat "jupyter-" (substring (symbol-name type) 1)))))
(apply req content)))
(cl-defmethod jupyter-send ((client jupyter-kernel-client) (type symbol) &rest content)
"Send a message on CLIENT's CHANNEL.
Return a `jupyter-request' representing the sent message. CHANNEL
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'."
(declare (indent 1))
(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
;; The logging of messages is deferred until the next command loop for
;; security reasons. When sending :input-reply messages that read
;; passwords, clearing the password string using `clear-string' happens
;; *after* the call to `jupyter-send'.
(run-at-time 0 nil (lambda () (message "SENDING: %s %s %s" type msg-id message))))
(jupyter--send
(jupyter-kernel-connection (oref client kernel))
'send channel type message msg-id)
;; Anything sent to stdin is a reply not a request so don't add it as a
;; pending request
(unless (eq channel :stdin)
(let ((req (jupyter-generate-request client message))
(requests (oref client requests)))
(setf (jupyter-request-id req) msg-id)
(setf (jupyter-request-inhibited-handlers req) jupyter-inhibit-handlers)
(puthash msg-id req requests)
(puthash "last-sent" req requests)))))
(run-at-time 0 nil (lambda () (message "SENDING: %s %s %s" type id content))))
(let ((channel (if (memq type '(:input-reply :input-request)) :stdin :shell))
(requests (oref client requests)))
(cl-call-next-method
(jupyter-kernel-connection (oref client kernel))
'send channel content id)
;; Anything sent to stdin is a reply not a request so consider
;; the "request" completed.
(setf (jupyter-request-idle-p req) (eq channel :stdin))
(setf (jupyter-request-inhibited-handlers req) jupyter-inhibit-handlers)
(puthash id 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
@ -625,7 +598,7 @@ After CLIENT shuts down the kernel it is connected to, it is no
longer connected to a kernel."
(when-let* ((kernel (and (slot-boundp 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)))
(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
(jupyter-add-callback
(jupyter-send-execute-request client :code \"1 + 2\")
(jupyter-send client (jupyter-execute-request :code \"1 + 2\"))
:status (lambda (msg) ...)
:execute-reply (lambda (msg) ...)
:execute-result (lambda (msg) ...))"
@ -968,10 +941,7 @@ user. Otherwise `read-from-minibuffer' is used."
(with-timeout-unsuspend timeout-spec)))
(quit ""))))
(unwind-protect
(jupyter-send
client :stdin
:input-reply (jupyter-message-input-reply
:value value))
(jupyter-send client :input-reply :value value)
(when (eq password t)
(clear-string value)))
value)))
@ -1048,8 +1018,8 @@ text/plain representation."
(interactive (list (jupyter-read-expression) nil))
(let ((msg (jupyter-wait-until-received :execute-result
(let* ((jupyter-inhibit-handlers t)
(req (jupyter-send-execute-request jupyter-current-client
:code code :store-history nil)))
(req (jupyter-send jupyter-current-client
:execute-request :code code :store-history nil)))
(prog1 req
(jupyter-add-callback req
:execute-reply
@ -1202,8 +1172,8 @@ current buffer that STR was extracted from.")
(cl-check-type jupyter-current-client jupyter-kernel-client
"Not a valid client")
(let ((jupyter-inhibit-handlers '(not :input-request))
(req (jupyter-send-execute-request jupyter-current-client
:code str :store-history nil)))
(req (jupyter-send jupyter-current-client
:execute-request :code str :store-history nil)))
(prog1 req
(jupyter-eval-add-callbacks req beg end))))
@ -1418,15 +1388,6 @@ STR is displayed after the region."
;;;;; 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)
(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'"))
(let ((client jupyter-current-client)
(msg (jupyter-wait-until-received :inspect-reply
(jupyter-send-inspect-request jupyter-current-client
:code code :pos pos :detail detail)
(jupyter-send jupyter-current-client
:inspect-request :code code :pos pos :detail detail)
;; Longer timeout for the Julia kernel
jupyter-long-timeout)))
(if msg
@ -1536,19 +1497,10 @@ DETAIL is the detail level to use for the request and defaults to
(symbol-at-point)))))
(message "Inspect timed out"))))
(define--jupyter-client-sender inspect-request
:code nil
:pos 0
:detail 0)
(define-jupyter-client-handler inspect-reply)
;;;; Completion
(define--jupyter-client-sender complete-request
:code nil
:pos 0)
(define-jupyter-client-handler complete-reply)
;;;;; Code context
@ -1847,9 +1799,8 @@ Run FUN when the completions are available."
(cl-destructuring-bind (code pos)
(jupyter-code-context 'completion)
(let ((req (let ((jupyter-inhibit-handlers t))
(jupyter-send-complete-request
jupyter-current-client
:code code :pos pos))))
(jupyter-send jupyter-current-client
:complete-request :code code :pos pos))))
(prog1 req
(jupyter-add-callback req :complete-reply fun)))))
@ -1966,46 +1917,16 @@ snippet text property, if any, and if `yasnippet' is available."
;;;; 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)
;;;; Is Complete
(define--jupyter-client-sender is-complete-request
:code nil)
(define-jupyter-client-handler is-complete-reply)
;;;; Comms
(define--jupyter-client-sender comm-info-request
:target-name nil)
(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
(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)
(or (oref client kernel-info)
(let* ((jupyter-inhibit-handlers t)
(req (jupyter-send-kernel-info-request client))
(msg (jupyter-wait-until-received :kernel-info-reply
(jupyter-send client :kernel-info-request)
;; Go to great lengths to ensure we have waited long
;; enough. When communicating with slow to start kernels
;; behind a kernel server this is necessary.
req (* 3 jupyter-long-timeout) "Requesting kernel info...")))
(* 3 jupyter-long-timeout) "Requesting kernel info...")))
(unless msg
(error "Kernel did not respond to kernel-info request"))
(prog1 (oset client kernel-info (jupyter-message-content msg))
@ -2087,15 +2008,10 @@ CLIENT is a kernel client."
(support (intern (format "jupyter-%s" lang))))
(require support nil t)))
(define--jupyter-client-sender kernel-info-request)
(define-jupyter-client-handler kernel-info-reply)
;;;; Shutdown
(define--jupyter-client-sender shutdown-request
:restart nil)
(define-jupyter-client-handler shutdown-reply)
;;; IOPUB handlers

View file

@ -122,7 +122,8 @@ Make the character after `point' invisible."
If the Pkg prompt can't be retrieved from the kernel, return
nil."
(when-let* ((msg (jupyter-wait-until-received :execute-reply
(jupyter-send-execute-request jupyter-current-client
(jupyter-send jupyter-current-client
:execute-request
:code ""
:silent t
:user-expressions
@ -189,14 +190,15 @@ nil."
(defun jupyter-julia--setup-hooks (client)
(let ((jupyter-inhibit-handlers t))
(jupyter-send-execute-request client
:store-history nil
:silent t
;; This is mainly for supporting the :dir header argument in `org-mode'
;; source blocks. We send this after initializing the REPL and after a
;; kernel restart so that we can get proper line numbers when an error
;; occurs.
:code "\
(jupyter-send client
:execute-request
:store-history nil
:silent t
;; This is mainly for supporting the :dir header argument in `org-mode'
;; source blocks. We send this after initializing the REPL and after a
;; kernel restart so that we can get proper line numbers when an error
;; occurs.
:code "\
if !isdefined(Main, :__JUPY_saved_dir)
Core.eval(Main, :(__JUPY_saved_dir = Ref(\"\")))
let popdir = () -> begin

View file

@ -150,8 +150,7 @@ request on KERNEL's control channel if its kernelspec has an
(format "%s://%s:%d" transport ip control_port)))))
;; TODO: `with-live-jupyter-channel'
(jupyter-start channel)
(jupyter-send channel :interrupt-request
(jupyter-message-interrupt-request))
(jupyter-send channel :interrupt-request '())
(jupyter-with-timeout
((format "Interrupting %s kernel"
(jupyter-kernel-name kernel))

View file

@ -369,36 +369,44 @@ and `:msg_type'."
;;; Control messages
(cl-defun jupyter-message-interrupt-request ()
(list))
(cl-defun jupyter-interrupt-request ()
(jupyter-request
:type :interrupt-request
:content (list)))
;;; stdin messages
(cl-defun jupyter-message-input-reply (&key value)
(cl-defun jupyter-input-reply (&key value)
(cl-check-type value string)
(list :value value))
(jupyter-request
:type :input-reply
:content (list :value value)))
;;; shell messages
(cl-defun jupyter-message-kernel-info-request ()
(list))
(cl-defun jupyter-kernel-info-request ()
(jupyter-request
:type :kernel-info-request
:content (list)))
(cl-defun jupyter-message-execute-request (&key
code
(silent nil)
(store-history t)
(user-expressions nil)
(allow-stdin t)
(stop-on-error nil))
(cl-defun jupyter-execute-request (&key
code
(silent nil)
(store-history t)
(user-expressions nil)
(allow-stdin t)
(stop-on-error nil))
(cl-check-type code string)
(cl-check-type user-expressions json-plist)
(list :code code :silent (if silent t jupyter--false)
:store_history (if store-history 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)))
(jupyter-request
:type :execute-request
:content (list :code code :silent (if silent t jupyter--false)
:store_history (if store-history 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))
(unless (member detail '(0 1))
(error "Detail can only be 0 or 1 (%s)" detail))
@ -406,71 +414,89 @@ and `:msg_type'."
(setq pos (marker-position pos)))
(cl-check-type code string)
(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)
(setq pos (marker-position pos)))
(cl-check-type code string)
(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
output
raw
hist-access-type
session
start
stop
n
pattern
unique)
(cl-defun jupyter-history-request (&key
output
raw
(hist-access-type "tail")
session
start
stop
(n 10)
pattern
unique)
(unless (member hist-access-type '("range" "tail" "search"))
(error "History access type can only be one of (range, tail, search)"))
(append
(list :output (if output t jupyter--false) :raw (if raw t jupyter--false)
:hist_access_type hist-access-type)
(cond
((equal hist-access-type "range")
(cl-check-type session integer)
(cl-check-type start integer)
(cl-check-type stop integer)
(list :session session :start start :stop stop))
((equal hist-access-type "tail")
(cl-check-type n integer)
(list :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)))))
(jupyter-request
:type :history-request
:content
(append
(list :output (if output t jupyter--false) :raw (if raw t jupyter--false)
:hist_access_type hist-access-type)
(cond
((equal hist-access-type "range")
(cl-check-type session integer)
(cl-check-type start integer)
(cl-check-type stop integer)
(list :session session :start start :stop stop))
((equal hist-access-type "tail")
(cl-check-type n integer)
(list :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)
(list :code code))
(jupyter-request
:type :is-complete-request
:content (list :code code)))
(cl-defun jupyter-message-comm-info-request (&key target-name)
(when target-name
(cl-check-type target-name string)
(list :target_name target-name)))
(cl-check-type target-name string)
(jupyter-request
: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 target-name string)
(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 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 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)
(list :restart (if restart t jupyter--false)))
(cl-defun jupyter-shutdown-request (&key restart)
(jupyter-request
:type :shutdown-request
:content (list :restart (if restart t jupyter--false))))
;;; Convenience functions and macros

View file

@ -602,10 +602,9 @@ first move is to the beginning of the current cell."
(defun jupyter-repl-goto-cell (req)
"Go to the cell beginning position of REQ.
REQ should be a `jupyter-request' that corresponds to one of the
`jupyter-send-execute-request's created by a cell in the
`current-buffer'. Note that the `current-buffer' is assumed to be
a Jupyter REPL buffer."
REQ should be a `jupyter-request' associated with a cell in the
`current-buffer'. Note that the `current-buffer' is assumed to
be a Jupyter REPL buffer."
(goto-char (point-max))
(unless (catch 'done
(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+insert+extend jupyter-repl-history code))
(cl-defmethod jupyter-send-execute-request ((client jupyter-repl-client)
&key code
(silent nil)
(store-history t)
(user-expressions nil)
(allow-stdin t)
(stop-on-error nil))
(if code (cl-call-next-method)
(jupyter-with-repl-buffer client
(jupyter-repl-truncate-buffer)
(save-excursion
(goto-char (jupyter-repl-cell-code-beginning-position))
(run-hooks 'jupyter-repl-cell-pre-send-hook))
(setq code (string-trim (jupyter-repl-cell-code)))
;; Handle empty code cells as just an update of the prompt number
(if (= (length code) 0)
(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)))
(defun jupyter-repl-execute-cell (client)
"Execute the last REPL cell of CLIENT.
Return the `jupyter-request' representing the executed code."
(cl-check-type client jupyter-repl-client)
(jupyter-with-repl-buffer client
(jupyter-repl-truncate-buffer)
(save-excursion
(goto-char (jupyter-repl-cell-code-beginning-position))
(run-hooks 'jupyter-repl-cell-pre-send-hook))
(let ((code (string-trim (jupyter-repl-cell-code))))
(let ((req (jupyter-send client
:execute-request
:code code
;; Handle empty code cells as just an update of the
;; prompt number
:silent (and (= (length code) 0) t))))
(jupyter-repl-without-continuation-prompts
(jupyter-repl-cell-mark-busy)
(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))
(save-excursion
(jupyter-repl-backward-cell)
@ -1111,17 +1105,17 @@ elements."
(jupyter-with-message-content msg (status indent)
(pcase status
("complete"
(jupyter-send-execute-request client))
(jupyter-repl-execute-cell client))
("incomplete"
(insert "\n")
(if (= (length indent) 0) (jupyter-repl-indent-line)
(insert indent)))
("invalid"
;; Force an execute to produce a traceback
(jupyter-send-execute-request client))
(jupyter-repl-execute-cell client))
("unknown"
;; 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)
(jupyter-with-repl-buffer client
@ -1185,7 +1179,7 @@ execute the current cell."
(not jupyter-repl-allow-RET-when-busy))
(error "Kernel busy"))
(cond
(force (jupyter-send-execute-request jupyter-current-client))
(force (jupyter-repl-execute-cell jupyter-current-client))
((or jupyter-repl-use-builtin-is-complete
(and jupyter-repl-allow-RET-when-busy
(jupyter-kernel-busy-p jupyter-current-client)))
@ -1199,8 +1193,8 @@ execute the current cell."
(t
(let ((res (jupyter-wait-until-received :is-complete-reply
(let ((jupyter-inhibit-handlers '(not :is-complete-reply)))
(jupyter-send-is-complete-request
jupyter-current-client
(jupyter-send jupyter-current-client
:is-complete-request
:code (jupyter-repl-cell-code)))
jupyter-repl-maximum-is-complete-timeout)))
(unless res
@ -1451,9 +1445,10 @@ value."
;; update the REPL state
(unless jupyter-repl-echo-eval-p
'(not :input-request))))
(setq req (jupyter-send-execute-request jupyter-current-client
:code str
:store-history jupyter-repl-echo-eval-p))
(setq req (jupyter-send jupyter-current-client
:execute-request
:code str
:store-history jupyter-repl-echo-eval-p))
(if jupyter-repl-echo-eval-p
(jupyter-repl-replace-cell-code cell-previous-code))))
;; Add callbacks to display evaluation output in pop-up buffers either when
@ -1696,8 +1691,11 @@ Return the buffer switched to."
;; ring.
(ring-insert jupyter-repl-history 'jupyter-repl-history)
(let ((jupyter-inhibit-handlers '(:status)))
(jupyter-send-history-request jupyter-current-client
:n jupyter-repl-history-maximum-length :raw nil :unique t))
(jupyter-send jupyter-current-client
:history-request
:n jupyter-repl-history-maximum-length
:raw nil
:unique t))
(erase-buffer)
;; Add local hooks
(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."
(let* ((client jupyter-current-client)
(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
:execute-reply
(jupyter-message-lambda (execution_count)

View file

@ -208,7 +208,7 @@ return nil."
(with-current-buffer (org-babel-jupyter-initiate-session session params)
(goto-char (point-max))
(and (org-babel-jupyter--insert-variable-assignments params)
(jupyter-send-execute-request jupyter-current-client))
(jupyter-repl-execute-cell jupyter-current-client))
(current-buffer)))
(defun org-babel-load-session:jupyter (session body params)
@ -428,7 +428,9 @@ These parameters are handled internally."
(delq fparam params)))
(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
,(cond
(async-p

View file

@ -47,8 +47,7 @@
:tags '(mock)
(jupyter-with-echo-client client
(ert-info ("Mock echo client echo's messages back to channel.")
(let* ((msg (jupyter-message-execute-request :code "foo"))
(req (jupyter-send client :shell :execute-request msg)))
(let ((req (jupyter-send client :execute-request :code "foo")))
(sleep-for 0.3)
(setq msgs (nreverse (ring-elements (oref client messages))))
(should (= (length msgs) 3))
@ -71,7 +70,7 @@
(ert-deftest jupyter-wait-until-idle ()
:tags '(callbacks)
(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")
(jupyter-wait-until-idle req)
(should (jupyter-request-idle-p req)))
@ -86,7 +85,7 @@
(cb (lambda (msg)
(should (eq (jupyter-message-type msg) :status))
(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-wait-until-idle req)
(should (= callback-count 2))))
@ -96,7 +95,7 @@
(setq callback-count (1+ callback-count))
(should (memq (jupyter-message-type msg)
'(: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-wait-until-idle req)
(should (= callback-count 3))))))
@ -409,19 +408,19 @@
(jupyter-test-with-python-client client
(ert-info ("Kernel info")
(let ((res (jupyter-wait-until-received :kernel-info-reply
(jupyter-send-kernel-info-request client))))
(jupyter-send client :kernel-info-request))))
(should res)
(should (json-plist-p res))
(should (eq (jupyter-message-type res) :kernel-info-reply))))
(ert-info ("Comm info")
(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 (json-plist-p res))
(should (eq (jupyter-message-type res) :comm-info-reply))))
(ert-info ("Execute")
(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 (json-plist-p res))
(should (eq (jupyter-message-type res) :execute-reply))))
@ -429,45 +428,49 @@
(cl-letf (((symbol-function 'read-from-minibuffer)
(lambda (_prompt &rest _args) "foo")))
(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 (json-plist-p res))
(should (eq (jupyter-message-type res) :execute-result))
(should (equal (jupyter-message-data res :text/plain) "'foo'")))))
(ert-info ("Inspect")
(let ((res (jupyter-wait-until-received :inspect-reply
(jupyter-send-inspect-request client
:code "list((1, 2, 3))"
:pos 2
:detail 0))))
(jupyter-send client
:inspect-request
:code "list((1, 2, 3))"
:pos 2
:detail 0))))
(should-not (null res))
(should (json-plist-p res))
(should (eq (jupyter-message-type res) :inspect-reply))))
(ert-info ("Complete")
(let ((res (jupyter-wait-until-received :complete-reply
(jupyter-send-complete-request client
:code "foo = lis"
:pos 8))))
(jupyter-send client
:complete-request
:code "foo = lis"
:pos 8))))
(should-not (null res))
(should (json-plist-p res))
(should (eq (jupyter-message-type res) :complete-reply))))
(ert-info ("History")
(let ((res (jupyter-wait-until-received :history-reply
(jupyter-send-history-request client
:hist-access-type "tail" :n 2))))
(jupyter-send client
:history-request
:hist-access-type "tail" :n 2))))
(should-not (null res))
(should (json-plist-p res))
(should (eq (jupyter-message-type res) :history-reply))))
(ert-info ("Is Complete")
(let ((res (jupyter-wait-until-received :is-complete-reply
(jupyter-send-is-complete-request client
:code "for i in range(5):"))))
(jupyter-send client
:is-complete-request
:code "for i in range(5):"))))
(should-not (null res))
(should (json-plist-p res))
(should (eq (jupyter-message-type res) :is-complete-reply))))
(ert-info ("Shutdown")
(let ((res (jupyter-wait-until-received :shutdown-reply
(jupyter-send-shutdown-request client))))
(jupyter-send client :shutdown-request))))
(should-not (null res))
(should (json-plist-p res))
(should (eq (jupyter-message-type res) :shutdown-reply))
@ -814,14 +817,14 @@
:tags '(client handlers)
(jupyter-test-with-python-client client
(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)
'(:stream)))
(should-not (jupyter--request-allows-handler-p
req (jupyter-test-message
req :stream (list :name "stdout" :text "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 ()
:tags '(client)
@ -835,7 +838,7 @@
;; print the class object on failure and will fail at doing so.
(setq pending (jupyter-requests-pending-p client))
(should-not pending)
(let ((req (jupyter-send-kernel-info-request client)))
(let ((req (jupyter-send client :kernel-info-request)))
(ert-info ("Pending after send")
(setq pending (jupyter-requests-pending-p client))
(should pending)
@ -843,8 +846,9 @@
(setq pending (jupyter-requests-pending-p client))
(should-not pending))
(ert-info ("Pending until idle received")
(setq req (jupyter-send-execute-request client
:code "import time; time.sleep(0.2)"))
(setq req (jupyter-send client
:execute-request
:code "import time; time.sleep(0.2)"))
;; Empty out the pending-requests slot of CLIENT
(jupyter-wait-until-received :status req)
(setq pending (jupyter-requests-pending-p client))
@ -930,11 +934,11 @@
(ert-deftest jupyter-idle-sync ()
:tags '(client hook)
(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))
(jupyter-idle-sync 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))
(jupyter-add-idle-sync-hook 'jupyter-test-idle-sync-hook req)
(should-not (null jupyter-test-idle-sync-hook))
@ -1106,13 +1110,12 @@
(ert-deftest jupyter-zmq-channel-ioloop-send-fast ()
:tags '(ioloop queue)
;; :expected-result :failed
(jupyter-test-with-python-client client
(let ((jupyter-current-client client))
(jupyter-send-execute-request client :code "1 + 1")
(jupyter-send-execute-request client :code "1 + 1")
(jupyter-send-execute-request client :code "1 + 1")
(let ((req (jupyter-send-execute-request client :code "1 + 1")))
(jupyter-send client :execute-request :code "1 + 1")
(jupyter-send client :execute-request :code "1 + 1")
(jupyter-send client :execute-request :code "1 + 1")
(let ((req (jupyter-send client :execute-request :code "1 + 1")))
(should
(equal
(jupyter-message-data
@ -1576,7 +1579,7 @@ last element being the newest element added to the history."
(jupyter-ert-info ("Cell boundary errors")
(goto-char (point-max))
(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)
(should (eq (car (get-text-property (1- (point)) 'jupyter-cell))
'out))
@ -1814,8 +1817,9 @@ next(x"))))))
(unwind-protect
(let ((msg (jupyter-wait-until-received :execute-result
(let ((jupyter-inhibit-handlers t))
(jupyter-send-execute-request cclient
:code "1 + 1")))))
(jupyter-send cclient
:execute-request
:code "1 + 1")))))
(should msg)
(should (equal (jupyter-message-data msg :text/plain) "2")))
(with-current-buffer (oref cclient buffer)

View file

@ -97,12 +97,8 @@ handling a message is always
:send #'ignore
:alive-p #'ignore))))
(cl-defmethod jupyter-send ((client jupyter-echo-client)
channel
type
message
&optional _flags)
(let ((req (jupyter-request :id (jupyter-new-uuid))))
(cl-defmethod jupyter-send ((client jupyter-echo-client) (type symbol) &rest content)
(let ((req (jupyter-request :type type :content content)))
(if (string-match "request" (symbol-name type))
(setq type (intern (replace-match "reply" nil nil (symbol-name 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
(if (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
(ignore-errors (jupyter-stop-channels ,saved)))
(let ((client (,client-fun (jupyter-kernelspec-name ,spec))))