From a11521dabfff8606faea4bc9577f8da8249c648c Mon Sep 17 00:00:00 2001 From: Nathaniel Nicandro Date: Fri, 13 Mar 2020 05:56:00 -0500 Subject: [PATCH] Make ZMQ an optional user dependency * jupyter-server.el (jupyter-ioloop, jupyter-server-ioloop): Remove requires. (jupyter-server): Don't subclass `jupyter-ioloop-comm`. (jupyter-server--connect-channels, jupyter-server--refresh-comm): Only do something when the SERVER argument is a `jupyter-comm-layer`, i.e. a `jupyter-server-ioloop-comm`. We don't check for that class directly since we would end up requiring ZMQ. (jupyter-comm-start) [jupyter-server-kernel-manager]: Use the right subclass of `jupyter-server-abstract-kcomm` depending on if the `jupyter-server` object is using ZMQ for communication. (jupyter-server-make-instance): New function. Returns a `jupyter-server` instance (a `jupyter-server-ioloop-comm`) that uses ZMQ if `jupyter-server-use-zmq` is non-nil, and a plain old `jupyter-server` instance otherwise. (jupyter-current-server): `jupyter-server` -> `jupyter-server-make-instance`. * ob-jupyter.el (org-babel-jupyter--server-repl): `jupyter-server` -> `jupyter-server-make-instance`. * test/test-helper.el (jupyter-test-with-notebook): `jupyter-server` -> `jupyter-server-make-instance`. --- jupyter-server.el | 38 +++++++++++++++++++++++++++----------- ob-jupyter.el | 2 +- test/test-helper.el | 2 +- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/jupyter-server.el b/jupyter-server.el index 6ed6873..1f4f6ea 100644 --- a/jupyter-server.el +++ b/jupyter-server.el @@ -77,8 +77,6 @@ (require 'jupyter-repl) (require 'jupyter-rest-api) (require 'jupyter-kernel-manager) -(require 'jupyter-ioloop-comm) -(require 'jupyter-server-ioloop) (declare-function jupyter-tramp-file-name-p "jupyter-tramp" (filename)) (declare-function jupyter-tramp-server-from-file-name "jupyter-tramp" (filename)) @@ -109,7 +107,6 @@ Used in, e.g. a `jupyter-server-kernel-list-mode' buffer.") ;; `jupyter-server-client' since it isn't a representation of a server, but a ;; communication channel with one. (defclass jupyter-server (jupyter-rest-client - jupyter-ioloop-comm eieio-instance-tracker) ((tracking-symbol :initform 'jupyter--servers) (kernelspecs @@ -265,17 +262,21 @@ ID of the kernel will be associated with NAME, see (cl-defgeneric jupyter-server-kernel-connected-p ((client jupyter-server) id) "Return non-nil if CLIENT can communicate with a kernel that has ID.") + +;; TODO: Move the following two functions to jupyter-server-ioloop-comm.el (defun jupyter-server--connect-channels (server id) - (jupyter-send server 'connect-channels id) - (jupyter-with-timeout - (nil jupyter-default-timeout - (error "Timeout when connecting websocket to kernel id %s" id)) - (jupyter-server-kernel-connected-p server id))) + (when (object-of-class-p server 'jupyter-comm-layer) + (jupyter-send server 'connect-channels id) + (jupyter-with-timeout + (nil jupyter-default-timeout + (error "Timeout when connecting websocket to kernel id %s" id)) + (jupyter-server-kernel-connected-p server id)))) (defun jupyter-server--refresh-comm (server) "Stop and then start SERVER communication. Reconnect the previously connected kernels when starting." - (when (jupyter-comm-alive-p server) + (when (and (object-of-class-p server 'jupyter-comm-layer) + (jupyter-comm-alive-p server)) (let ((connected (cl-remove-if-not (apply-partially #'jupyter-server-kernel-connected-p server) (mapcar (lambda (kernel) (plist-get kernel :id)) @@ -408,7 +409,10 @@ MANAGER's COMM slot will be set to the `jupyter-comm-layer' receiving events on the websocket when this method returns." (with-slots (kernel comm) manager (unless (slot-boundp manager 'comm) - (oset manager comm (jupyter-server-kernel-comm :kernel kernel))) + (oset manager comm + (if (object-of-class-p (oref kernel server) 'jupyter-comm-layer) + (jupyter-server-ioloop-kernel-comm :kernel kernel) + (jupyter-server-kernel-comm :kernel kernel)))) (unless (jupyter-comm-alive-p comm) (jupyter-comm-start comm)))) @@ -508,6 +512,18 @@ least the following keys: (define-error 'jupyter-server-non-existent "The server doesn't exist") +(defun jupyter-server-make-instance (&rest args) + "Return a different subclass of `jupyter-server' depending on `jupyter-server-use-zmq'. +A `jupyter-server-ioloop-comm' object is returned if +`jupyter-server-use-zmq' is non-nil, a `jupyter-server' is +returned otherwise. ARGS is passed to the `make-instance' +invocation for the subclass." + (if jupyter-server-use-zmq + (progn + (require 'jupyter-server-ioloop-comm) + (apply #'jupyter-server-ioloop-comm args)) + (apply #'jupyter-server args))) + (defun jupyter-current-server (&optional ask) "Return an existing `jupyter-server' or ASK for a new one. If ASK is non-nil, always ask for a URL and return the @@ -546,7 +562,7 @@ a URL." (setf (url-type u) "ws") (url-recreate-url u))))) (or (jupyter-find-server url ws-url) - (let ((server (jupyter-server :url url :ws-url ws-url))) + (let ((server (jupyter-server-make-instance :url url :ws-url ws-url))) (if (jupyter-api-server-exists-p server) server (delete-instance server) (signal 'jupyter-server-non-existent (list url))))))))) diff --git a/ob-jupyter.el b/ob-jupyter.el index bb4349f..9ae1a90 100644 --- a/ob-jupyter.el +++ b/ob-jupyter.el @@ -239,7 +239,7 @@ variables in PARAMS." (require 'jupyter-server) (let* ((url (jupyter-tramp-url-from-file-name session)) (server (or (jupyter-tramp-server-from-file-name session) - (jupyter-server :url url))) + (jupyter-server-make-instance :url url))) (localname (file-local-name session)) (name-or-id (if (null localname) (error "No remote server session name") ;; If a kernel has an associated name, get its kernel ID diff --git a/test/test-helper.el b/test/test-helper.el index 5288dab..7602edd 100644 --- a/test/test-helper.el +++ b/test/test-helper.el @@ -323,7 +323,7 @@ For `url-retrieve', the callback will be called with a nil status." `(let* ((host (format "localhost:%s" (jupyter-test-ensure-notebook-server))) (url (format "http://%s" host)) (,server (or (jupyter-find-server url) - (jupyter-server :url url)))) + (jupyter-server-make-instance :url url)))) ,@body)) (defmacro jupyter-test-with-server-kernel (server name kernel &rest body)