Commit 16553955 authored by Ludovic Courtès's avatar Ludovic Courtès
Browse files

Move more kernel helpers to (guix kernels).

* guix-kernel/jupyter-client.scm (read-message, send-message, pub)
(pub-busy, pub-idle, reply-html): Move to...
* jupyter/kernels.scm: ... here.
parent 0556e9dd
......@@ -25,15 +25,7 @@
#:export (guile-version
KERNEL-INFO
json->kernel
read-message
send-message
relay-message
pub-busy
pub-idle
reply-html))
json->kernel))
;;
;; Kernel information.
......@@ -89,117 +81,3 @@
("help_links" .
(("Gitlab Inria" .
"https://gitlab.inria.fr/guix-hpc/guix-kernel")))))
;;
;; Send procedures.
;;
(define (read-message kernel)
"Read a message for KERNEL--i.e., a message sent by Jupyter--and return
it or #f if nothing is available."
;; FIXME Use 'zmq_poll'.
(define (waiting-data socket next)
(catch 'zmq-error
(λ _
(zmq-get-msg-parts-bytevector socket))
(λ stuff
(cond
((equal? EAGAIN (cadr stuff))
(and next (waiting-data next socket)))
(else #f)))))
(and=> (waiting-data (kernel-shell kernel)
(kernel-control kernel))
parts->message))
(define* (send-message kernel message
#:key
(kernel-socket kernel-shell)
(recipient (and=> (message-parent-header message)
header-sender)))
"Send message over the shell socket of KERNEL to RECIPIENT, a ZeroMQ
identity (bytevector)."
(zmq-send-msg-parts-bytevector (kernel-socket kernel)
(message-parts message
(kernel-key kernel)
#:recipient recipient)))
(define* (relay-message socket kernel name request)
"Relay REQUEST, a message, over SOCKET, with recipient NAME (a bytevector
representing a ZeroMQ identity), and return its reply. Send replies to
KERNEL."
(let ((parts (message-parts request (kernel-key kernel)
#:recipient name)))
(zmq-send-msg-parts-bytevector socket parts))
(let loop ()
(let* ((parts (zmq-get-msg-parts-bytevector socket))
(reply (parts->message parts))
(sender (message-sender request)))
(match (message-type reply)
("execute_reply"
(send-message kernel reply
#:recipient sender)
(loop))
((or "execute_result" "error")
(send-message kernel reply #:kernel-socket kernel-iopub
#:recipient sender)
(loop))
("execute_input"
(send-message kernel reply #:kernel-socket kernel-iopub
#:recipient sender)
(loop))
("stream"
(send-message kernel reply #:kernel-socket kernel-iopub
#:recipient sender)
(loop))
("status"
(let ((content (json-string->scm (message-content reply))))
(match (hash-ref content "execution_state")
("idle" reply)
(_ (loop)))))
(_
reply)))))
(define (pub kernel message status)
(let ((content `(("execution_state" . ,status))))
(send-message kernel (reply message "status"
(scm->json-string content))
#:kernel-socket kernel-iopub)))
(define (pub-busy kernel message)
(pub kernel message "busy"))
(define (pub-idle kernel message)
(pub kernel message "idle"))
;;
;; Reply.
;;
(define (reply-html kernel message html count)
"Reply to MESSAGE with HTML."
(let ((code (hash-ref (json-string->scm (message-content message))
"code"))
(empty-object (make-hash-table 1))
(counter (+ count 1)) ;execution counter
(send (lambda (socket type content)
(send-message kernel
(reply message type
(scm->json-string content))
#:kernel-socket socket))))
(send kernel-iopub
"execute_input" `(("code" . ,code)
("execution_count" . ,counter)))
(send kernel-iopub
"execute_result" `(("data" . (("text/html" . ,html)))
("metadata" . ,empty-object)
("execution_count" . ,counter)))
(send kernel-shell
"execute_reply" `(("status" . "ok")
("execution_count" . ,counter)
("payload" . [])
("user_expressions" . ,empty-object)))
counter))
......@@ -16,6 +16,7 @@
;;; along with this program. If not, see <https://www.gnu.org/licenses/>.
(define-module (jupyter kernels)
#:use-module (jupyter messages)
#:use-module (guix build utils)
#:use-module (ice-9 rdelim)
#:use-module (ice-9 match)
......@@ -40,6 +41,14 @@
kernel-iosub
kernel-iopub ;alias
read-message
send-message
relay-message
pub-busy
pub-idle
reply-html
close-kernel))
;;; Commentary:
......@@ -214,6 +223,7 @@ return its PID."
(number->string port))))
(kernel (kernel name pid
#:key key
#:control socket-control
#:shell socket-shell
#:standard-input socket-stdin
......@@ -231,3 +241,118 @@ return its PID."
(zmq-connect socket-iosub (addr-p port-iosub))
kernel))
;;
;; Communicating with a kernel.
;;
(define (read-message kernel)
"Read a message for KERNEL--i.e., a message sent by Jupyter--and return
it or #f if nothing is available."
;; FIXME Use 'zmq_poll'.
(define (waiting-data socket next)
(catch 'zmq-error
(λ _
(zmq-get-msg-parts-bytevector socket))
(λ stuff
(cond
((equal? EAGAIN (cadr stuff))
(and next (waiting-data next socket)))
(else #f)))))
(and=> (waiting-data (kernel-shell kernel)
(kernel-control kernel))
parts->message))
(define* (send-message kernel message
#:key
(kernel-socket kernel-shell)
(recipient (and=> (message-parent-header message)
header-sender)))
"Send message over the shell socket of KERNEL to RECIPIENT, a ZeroMQ
identity (bytevector)."
(zmq-send-msg-parts-bytevector (kernel-socket kernel)
(message-parts message
(kernel-key kernel)
#:recipient recipient)))
(define* (relay-message socket kernel name request)
"Relay REQUEST, a message, over SOCKET, with recipient NAME (a bytevector
representing a ZeroMQ identity), and return its reply. Send replies to
KERNEL."
(let ((parts (message-parts request (kernel-key kernel)
#:recipient name)))
(zmq-send-msg-parts-bytevector socket parts))
(let loop ()
(let* ((parts (zmq-get-msg-parts-bytevector socket))
(reply (parts->message parts))
(sender (message-sender request)))
(match (message-type reply)
("execute_reply"
(send-message kernel reply
#:recipient sender)
(loop))
((or "execute_result" "error")
(send-message kernel reply #:kernel-socket kernel-iopub
#:recipient sender)
(loop))
("execute_input"
(send-message kernel reply #:kernel-socket kernel-iopub
#:recipient sender)
(loop))
("stream"
(send-message kernel reply #:kernel-socket kernel-iopub
#:recipient sender)
(loop))
("status"
(let ((content (json-string->scm (message-content reply))))
(match (hash-ref content "execution_state")
("idle" reply)
(_ (loop)))))
(_
reply)))))
(define (pub kernel message status)
(let ((content `(("execution_state" . ,status))))
(send-message kernel (reply message "status"
(scm->json-string content))
#:kernel-socket kernel-iopub)))
(define (pub-busy kernel message)
(pub kernel message "busy"))
(define (pub-idle kernel message)
(pub kernel message "idle"))
;;
;; Reply.
;;
(define (reply-html kernel message html count)
"Reply to MESSAGE with HTML."
(let ((code (hash-ref (json-string->scm (message-content message))
"code"))
(empty-object (make-hash-table 1))
(counter (+ count 1)) ;execution counter
(send (lambda (socket type content)
(send-message kernel
(reply message type
(scm->json-string content))
#:kernel-socket socket))))
(send kernel-iopub
"execute_input" `(("code" . ,code)
("execution_count" . ,counter)))
(send kernel-iopub
"execute_result" `(("data" . (("text/html" . ,html)))
("metadata" . ,empty-object)
("execution_count" . ,counter)))
(send kernel-shell
"execute_reply" `(("status" . "ok")
("execution_count" . ,counter)
("payload" . [])
("user_expressions" . ,empty-object)))
counter))
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment