8383(declare-function jupyter-tramp-file-name-p " jupyter-tramp" (filename))
8484(declare-function jupyter-tramp-server-from-file-name " jupyter-tramp" (filename))
8585(declare-function jupyter-tramp-file-name-from-url " jupyter-tramp" (url))
86+ (declare-function jupyter-server-ioloop-kernel-comm " jupyter-server-ioloop-comm" )
87+ (declare-function jupyter-server-ioloop-comm " jupyter-server-ioloop-comm" )
8688
8789(defgroup jupyter-server nil
8890 " Support for the Jupyter kernel gateway"
@@ -169,9 +171,9 @@ Access should be done through `jupyter-available-kernelspecs'.")))
169171 :abstract t )
170172
171173(defclass jupyter-server-kernel-comm (jupyter-server-abstract-kcomm)
172- ())
174+ ((ws :type websocket) ))
173175
174- (cl-defmethod jupyter-comm-id ((comm jupyter-server-kernel-comm ))
176+ (cl-defmethod jupyter-comm-id ((comm jupyter-server-abstract-kcomm ))
175177 (let* ((kernel (oref comm kernel))
176178 (id (oref kernel id)))
177179 (or (jupyter-server-kernel-name (oref kernel server) id)
@@ -250,7 +252,7 @@ CLIENT must be communicating with a `jupyter-server-kernel', the
250252ID of the kernel will be associated with NAME, see
251253`jupyter-server-kernel-names' ."
252254 (cl-check-type client jupyter-kernel-client)
253- (cl-check-type (oref client kcomm) jupyter-server-kernel-comm )
255+ (cl-check-type (oref client kcomm) jupyter-server-abstract-kcomm )
254256 (let* ((kernel (thread-first client
255257 (oref kcomm)
256258 (oref kernel)))
@@ -259,42 +261,10 @@ ID of the kernel will be associated with NAME, see
259261
260262; ;; Plumbing
261263
262- ; ;;; `jupyter-server' events
263-
264- (cl-defmethod jupyter-event-handler ((comm jupyter-server)
265- (event (head disconnect-channels)))
266- (let ((kernel-id (cadr event)))
267- (with-slots (ioloop) comm
268- (cl-callf2 remove kernel-id
269- (process-get (oref ioloop process) :kernel-ids )))))
270-
271- (cl-defmethod jupyter-event-handler ((comm jupyter-server)
272- (event (head connect-channels)))
273- (let ((kernel-id (cadr event)))
274- (with-slots (ioloop) comm
275- (cl-callf append (process-get (oref ioloop process) :kernel-ids )
276- (list kernel-id)))))
277-
278- (cl-defmethod jupyter-event-handler ((comm jupyter-server) event)
279- " Send EVENT to all clients connected to COMM.
280- Each client must have a KERNEL slot which, in turn, must have an
281- ID slot. The second element of EVENT is expected to be a kernel
282- ID. Send EVENT, with the kernel ID excluded, to a client whose
283- kernel has a matching ID."
284- (let ((kernel-id (cadr event)))
285- (setq event (cons (car event) (cddr event)))
286- (jupyter-comm-handler-loop comm client
287- (when (equal kernel-id (oref (oref client kernel) id))
288- ; ; TODO: Since the event handlers of CLIENT will eventually call the
289- ; ; `jupyter-handle-message' of a `jupyter-kernel-client' we really
290- ; ; don't need to do any filtering based off of a `jupyter-session-id' ,
291- ; ; but maybe should? The `jupyter-handle-message' method will only
292- ; ; handle messages that have a parent ID of a previous request so there
293- ; ; already is filtering at the kernel client level.
294- (jupyter-event-handler client event)))))
295-
296264; ;;; `jupyter-server' methods
297265
266+ (cl-defgeneric jupyter-server-kernel-connected-p ((client jupyter-server) id)
267+ " Return non-nil if CLIENT can communicate with a kernel that has ID." )
298268(defun jupyter-server--connect-channels (server id )
299269 (jupyter-send server 'connect-channels id)
300270 (jupyter-with-timeout
@@ -326,44 +296,6 @@ with default `jupyter-api-authentication-method'"))
326296 (prog1 (cl-call-next-method )
327297 (jupyter-server--refresh-comm server)))))
328298
329- (cl-defmethod jupyter-comm-start ((comm jupyter-server))
330- (unless (and (slot-boundp comm 'ioloop )
331- (jupyter-ioloop-alive-p (oref comm ioloop)))
332- ; ; TODO: Is a write to the cookie file and then a read of the cookie file
333- ; ; whenever connecting a websocket in a subprocess good enough? If, e.g.
334- ; ; the notebook is restarted and it clears the login information, there are
335- ; ; sometimes error due to `jupyter-api-request' trying to ask for login
336- ; ; information which look like "wrong type argument listp, [http://...]".
337- ; ; They don't seem to happens with the changes mentioned, but is it enough?
338- (url-cookie-write-file )
339- (oset comm ioloop (jupyter-server-ioloop
340- :url (oref comm url)
341- :ws-url (oref comm ws-url)
342- :ws-headers (jupyter-api-auth-headers comm)))
343- (cl-call-next-method )))
344-
345- (cl-defmethod jupyter-comm-add-handler ((comm jupyter-server)
346- (kcomm jupyter-server-kernel-comm))
347- (cl-call-next-method )
348- (with-slots (id) (oref kcomm kernel)
349- (unless (jupyter-server-kernel-connected-p comm id)
350- (jupyter-server--connect-channels comm id))))
351-
352- (cl-defmethod jupyter-comm-remove-handler ((comm jupyter-server)
353- (kcomm jupyter-server-kernel-comm))
354- (with-slots (id) (oref kcomm kernel)
355- (when (jupyter-server-kernel-connected-p comm id)
356- (jupyter-send comm 'disconnect-channels id)
357- (unless (jupyter-ioloop-wait-until (oref comm ioloop)
358- 'disconnect-channels #'identity )
359- (error " Timeout when disconnecting websocket for kernel id %s " id))))
360- (cl-call-next-method ))
361-
362- (cl-defmethod jupyter-server-kernel-connected-p ((comm jupyter-server) id)
363- " Return non-nil if COMM has a WebSocket connection to a kernel with ID."
364- (and (jupyter-comm-alive-p comm)
365- (member id (process-get (oref (oref comm ioloop) process) :kernel-ids ))))
366-
367299(defun jupyter-server--verify-kernelspec (server spec )
368300 (cl-destructuring-bind (name _ . kspec) spec
369301 (let ((server-spec (assoc name (jupyter-server-kernelspecs server))))
@@ -400,53 +332,18 @@ The kernelspecs are returned in the same form as returned by
400332 (cons nil (plist-get spec :spec )))))))
401333 (plist-get (oref server kernelspecs) :kernelspecs ))
402334
403- ; ;;; `jupyter-server-kernel-comm' methods
404-
405- (cl-defmethod jupyter-comm-start ((comm jupyter-server-kernel-comm) &rest _ignore)
406- " Register COMM to receive server events.
407- If SERVER receives events that have the same kernel ID as the
408- kernel associated with COMM, then COMM's `jupyter-event-handler'
409- will receive those events."
410- (with-slots (server) (oref comm kernel)
411- (jupyter-comm-start server)
412- (jupyter-comm-add-handler server comm)))
413-
414- (cl-defmethod jupyter-comm-stop ((comm jupyter-server-kernel-comm) &rest _ignore)
415- " Disconnect COMM from receiving server events."
416- (jupyter-comm-remove-handler (oref (oref comm kernel) server) comm))
417-
418- (cl-defmethod jupyter-send ((comm jupyter-server-kernel-comm) event-type &rest event)
419- " Use COMM to send an EVENT to the server with type, EVENT-TYPE.
420- SERVER will direct EVENT to the right kernel based on the kernel
421- ID of the kernel associated with COMM."
422- (with-slots (kernel) comm
423- (unless (jupyter-comm-alive-p comm)
424- (jupyter-comm-start comm))
425- (apply #'jupyter-send (oref kernel server) event-type (oref kernel id) event)))
426-
427- (cl-defmethod jupyter-comm-alive-p ((comm jupyter-server-kernel-comm))
428- " Return non-nil if COMM can receive server events for its associated kernel."
429- (with-slots (kernel) comm
430- (and (jupyter-server-kernel-connected-p
431- (oref kernel server)
432- (oref kernel id))
433- (catch 'member
434- (jupyter-comm-handler-loop (oref kernel server) client
435- (when (eq client comm)
436- (throw 'member t )))))))
437-
438335; ; TODO: Remove the need for these methods, they are remnants from an older
439336; ; implementation. They will need to be removed from `jupyter-kernel-client' .
440- (cl-defmethod jupyter-channel-alive-p ((comm jupyter-server-kernel-comm ) _channel)
337+ (cl-defmethod jupyter-channel-alive-p ((comm jupyter-server-abstract-kcomm ) _channel)
441338 (jupyter-comm-alive-p comm))
442339
443- (cl-defmethod jupyter-channels-running-p ((comm jupyter-server-kernel-comm ))
340+ (cl-defmethod jupyter-channels-running-p ((comm jupyter-server-abstract-kcomm ))
444341 (jupyter-comm-alive-p comm))
445342
446343; ;;; `jupyter-server-kernel-manager'
447344
448345(defclass jupyter-server-kernel-manager (jupyter-kernel-manager)
449- ((comm :type jupyter-server-kernel-comm )))
346+ ((comm :type jupyter-server-abstract-kcomm )))
450347
451348(cl-defmethod jupyter-comm-start ((manager jupyter-server-kernel-manager))
452349 " Start a websocket connection to MANAGER's kernel.
@@ -604,7 +501,7 @@ a URL."
604501 ((and jupyter-current-client
605502 (object-of-class-p
606503 (oref jupyter-current-client kcomm)
607- 'jupyter-server-kernel-comm )
504+ 'jupyter-server-abstract-kcomm )
608505 (thread-first jupyter-current-client
609506 (oref kcomm)
610507 (oref kernel)
0 commit comments