emacs-jupyter/jupyter-connection.el
2018-01-07 14:45:20 -06:00

86 lines
3.6 KiB
EmacsLisp

(require 'jupyter-base)
(defclass jupyter-connection ()
((session
:type jupyter-session
:initarg :session
:documentation "The `jupyter-session' object which holds the
key for authenticating messages.")
(conn-info
:type json-plist
:initarg :conn-info
:documentation "The connection plist which holds the channel
ports and other information required for connecting to a kernel.
See
http://jupyter-client.readthedocs.io/en/latest/kernels.html#connection-files"))
:abstract t)
(cl-defmethod jupyter-clone-connection ((this jupyter-connection) other)
(cl-check-type other jupyter-connection)
(oset other session (copy-sequence (oref this session)))
(oset other conn-info (copy-sequence (oref this conn-info))))
(cl-defun jupyter-create-connection-info (&key
(kernel-name "python")
(transport "tcp")
(ip "127.0.0.1")
(signature-scheme "hmac-sha256")
(key (jupyter-new-uuid))
(hb-port 0)
(stdin-port 0)
(control-port 0)
(shell-port 0)
(iopub-port 0))
"Create a jupyter connection plist.
The plist has the standard keys found in the jupyter spec. See
http://jupyter-client.readthedocs.io/en/latest/kernels.html#connection-files."
(unless (or (= (length key) 0)
(equal signature-scheme "hmac-sha256"))
(error "Only hmac-sha256 signing is currently supported."))
(append
(list :kernel_name kernel-name
:transport transport
:ip ip)
(when (> (length key) 0)
(list :signature_scheme signature-scheme
:key key))
(cl-loop
with sock = (zmq-socket (zmq-current-context) zmq-REP)
with addr = (concat transport "://" ip)
for (channel . port) in (list (cons :hb_port hb-port)
(cons :stdin_port stdin-port)
(cons :control_port control-port)
(cons :shell_port shell-port)
(cons :iopub_port iopub-port))
collect channel and
if (= port 0) do (setq port (zmq-bind-to-random-port sock addr))
and collect port and
do (zmq-unbind sock (zmq-socket-get sock zmq-LAST_ENDPOINT)) else
collect port
finally (zmq-close sock))))
(defun jupyter-connect-endpoint (type endpoint &optional identity)
"Create socket with type TYPE and connect it to ENDPOINT.
If IDENTITY is non-nil, it will be set as the ROUTING_ID of the
socket. The return value is the socket created."
(let ((sock (zmq-socket (zmq-current-context) type)))
(zmq-socket-set sock zmq-LINGER 1000)
(when identity
(zmq-socket-set sock zmq-ROUTING_ID identity))
(zmq-connect sock endpoint)
sock))
(defun jupyter-connect-channel (ctype endpoint &optional identity)
"Create a socket based on a Jupyter channel type.
CTYPE will be mapped to a ZMQ socket type based on the plist
`jupyter-socket-types'. ENDPOINT is the endpoint the socket will
connect to and if IDENTITY is non-nil it will be set as the
ROUTING_ID of the socket. The return value is the socket
created."
(let ((sock-type (plist-get jupyter-socket-types ctype)))
(unless sock-type
(error "Invalid channel type (%s)" ctype))
(jupyter-connect-endpoint sock-type endpoint identity)))
(provide 'jupyter-connection)