Merge branch 'ein-query'

This commit is contained in:
Takafumi Arakaki 2012-05-27 01:39:39 +02:00
commit 66a8a90ddc
8 changed files with 387 additions and 172 deletions

View file

@ -31,7 +31,7 @@
(require 'ein-utils)
(require 'ein-websocket)
(require 'ein-events)
(require 'url)
(require 'ein-query)
(defstruct ein:$kernel
@ -90,17 +90,14 @@ FIXME: document other slots."
(defun ein:kernel-start (kernel notebook-id)
"Start kernel of the notebook whose id is NOTEBOOK-ID."
(unless (ein:$kernel-running kernel)
(let* ((qs (format "notebook=%s" notebook-id))
(url (concat (ein:url (ein:$kernel-url-or-port kernel)
(ein:$kernel-base-url kernel))
"?" qs))
(url-request-method "POST"))
(url-retrieve
url
(lambda (status kernel)
(ein:kernel--kernel-started kernel (ein:json-read))
(kill-buffer (current-buffer)))
(list kernel)))))
(ein:query-ajax
(concat (ein:url (ein:$kernel-url-or-port kernel)
(ein:$kernel-base-url kernel))
"?" (format "notebook=%s" notebook-id))
:type "POST"
:parser #'ein:json-read
:success (cons #'ein:kernel--kernel-started kernel)
:timeout 5000)))
(defun ein:kernel-restart (kernel)
@ -109,23 +106,21 @@ FIXME: document other slots."
(ein:log 'info "Restarting kernel")
(when (ein:$kernel-running kernel)
(ein:kernel-stop-channels kernel)
(let ((url (ein:url (ein:$kernel-url-or-port kernel)
(ein:$kernel-kernel-url kernel)
"restart"))
(url-request-method "POST"))
(url-retrieve
url
(lambda (status kernel)
(ein:kernel--kernel-started kernel (ein:json-read))
(kill-buffer (current-buffer)))
(list kernel)))))
(ein:query-ajax
(ein:url (ein:$kernel-url-or-port kernel)
(ein:$kernel-kernel-url kernel)
"restart")
:type "POST"
:parser #'ein:json-read
:success (cons #'ein:kernel--kernel-started kernel)
:timeout 5000)))
(defun ein:kernel--kernel-started (kernel json)
(ein:log 'info "Kernel started: %s" (plist-get json :kernel_id))
(defun* ein:kernel--kernel-started (kernel &key data &allow-other-keys)
(ein:log 'info "Kernel started: %s" (plist-get data :kernel_id))
(setf (ein:$kernel-running kernel) t)
(setf (ein:$kernel-kernel-id kernel) (plist-get json :kernel_id))
(setf (ein:$kernel-ws-url kernel) (plist-get json :ws_url))
(setf (ein:$kernel-kernel-id kernel) (plist-get data :kernel_id))
(setf (ein:$kernel-ws-url kernel) (plist-get data :ws_url))
(setf (ein:$kernel-kernel-url kernel)
(concat (ein:$kernel-base-url kernel) "/"
(ein:$kernel-kernel-id kernel)))
@ -362,29 +357,29 @@ http://ipython.org/ipython-doc/dev/development/messaging.html#complete
(defun ein:kernel-interrupt (kernel)
(when (ein:$kernel-running kernel)
(ein:log 'info "Interrupting kernel")
(let ((url (ein:url (ein:$kernel-url-or-port kernel)
(ein:$kernel-kernel-url kernel)
"interrupt"))
(url-request-method "POST"))
(url-retrieve
url
(lambda (s)
(ein:log 'info "Sent interruption command.")
(kill-buffer (current-buffer)))))))
(ein:query-ajax
(ein:url (ein:$kernel-url-or-port kernel)
(ein:$kernel-kernel-url kernel)
"interrupt")
:type "POST"
:success (cons (lambda (&rest ignore)
(ein:log 'info "Sent interruption command."))
nil)
:timeout 5000)))
(defun ein:kernel-kill (kernel)
(when (ein:$kernel-running kernel)
(setf (ein:$kernel-running kernel) nil)
(let ((url-request-method "DELETE")
(url (ein:url-no-cache
(ein:url (ein:$kernel-url-or-port kernel)
(ein:$kernel-kernel-url kernel)))))
(url-retrieve
url
(lambda (s)
(ein:log 'info "Notebook kernel is killed")
(kill-buffer (current-buffer)))))))
(ein:query-ajax
(ein:url (ein:$kernel-url-or-port kernel)
(ein:$kernel-kernel-url kernel))
:cache nil
:type "DELETE"
:success (cons (lambda (&rest ignore)
(ein:log 'info "Notebook kernel is killed"))
nil)
:timeout 5000)))
;; Reply handlers.

View file

@ -92,16 +92,23 @@
(get-buffer-create (format ein:log-buffer-name-template name)))
(ein:log 'verbose "Start logging."))
;; FIXME: this variable must go to somewhere more central
(defvar ein:debug nil
"Set to non-`nil' to raise errors instead of suppressing it.
Change the behavior of `ein:log-ignore-errors'.")
(defmacro ein:log-ignore-errors (&rest body)
"Execute BODY; if an error occurs, log the error and return nil.
Otherwise, return result of last form in BODY."
(declare (debug t) (indent 0))
`(condition-case err
`(if ein:debug
(progn ,@body)
(error
(ein:log 'debug "Error: %S" err)
(ein:log 'error (error-message-string err))
nil)))
(condition-case err
(progn ,@body)
(error
(ein:log 'debug "Error: %S" err)
(ein:log 'error (error-message-string err))
nil))))
(defun ein:log-del ()
"Kill buffer `ein:log-buffer'."

View file

@ -21,7 +21,14 @@
;;; Commentary:
;;
;; * Coding rule about current buffer.
;; A lot of notebook and cell functions touches to current buffer and
;; it is not ideal to wrap all these functions by `with-current-buffer'.
;; Therefore, when the function takes `notebook' to the first argument
;; ("method" function), it is always assumed that the current buffer
;; is the notebook buffer. **However**, functions called as callback
;; (via `url-retrieve', for example) must protect themselves by
;; calling from unknown buffer.
;;; Code:
@ -39,6 +46,7 @@
(require 'ein-events)
(require 'ein-notification)
(require 'ein-kill-ring)
(require 'ein-query)
;;; Configuration
@ -62,12 +70,13 @@ yet. So be careful when using EIN functions. They may change."
)
:group 'ein)
(defun ein:notebook-discard-output-p ()
(defun ein:notebook-discard-output-p (notebook)
"Return non-`nil' if the output must be discarded, otherwise save."
(case ein:notebook-discard-output-on-save
(no nil)
(yes t)
(t (funcall ein:notebook-discard-output-on-save))))
(t (with-current-buffer (ein:notebook-buffer notebook)
(funcall ein:notebook-discard-output-on-save)))))
;;; Class and variable
@ -212,18 +221,18 @@ the time of execution."
(let ((url (ein:notebook-url-from-url-and-id url-or-port notebook-id))
(notebook (ein:notebook-new url-or-port notebook-id)))
(ein:log 'debug "Opening notebook at %s" url)
(url-retrieve url
#'ein:notebook-url-retrieve-callback
(list notebook))
(ein:query-ajax
url
:parser #'ein:json-read
:success (cons #'ein:notebook-request-open-callback notebook))
notebook))
(defun ein:notebook-url-retrieve-callback (status notebook)
(defun* ein:notebook-request-open-callback (notebook &key status data
&allow-other-keys)
(ein:log 'debug "URL-RETRIEVE nodtebook-id = %S, status = %S"
(ein:$notebook-notebook-id notebook)
status)
(let ((data (ein:json-read))
(notebook-id (ein:$notebook-notebook-id notebook)))
(kill-buffer (current-buffer))
(let ((notebook-id (ein:$notebook-notebook-id notebook)))
(ein:notebook-init notebook data)
(with-current-buffer (ein:notebook-get-buffer notebook)
(ein:log-setup (ein:$notebook-notebook-id notebook))
@ -738,7 +747,7 @@ Do not clear input prompts when the prefix argument is given."
(defun ein:notebook-to-json (notebook)
"Return json-ready alist."
(let* ((discard (ein:notebook-discard-output-p))
(let* ((discard (ein:notebook-discard-output-p notebook))
(cells (mapcar (lambda (c) (ein:cell-to-json c discard))
(ein:notebook-get-cells notebook))))
`((worksheets . [((cells . ,(apply #'vector cells)))])
@ -751,63 +760,54 @@ Do not clear input prompts when the prefix argument is given."
(push `(nbformat . ,(ein:$notebook-nbformat notebook)) data)
(ein:events-trigger (ein:$notebook-events notebook)
'(notebook_saving . Notebook))
(let ((url (ein:url-no-cache (ein:notebook-url notebook)))
(url-request-method "PUT")
(url-request-extra-headers '(("Content-Type" . "application/json")))
(url-request-data (json-encode data)))
(ein:log 'debug "URL-RETRIEVE url = %s" url)
(ein:log 'debug "URL-REQUEST-DATA = %s" url-request-data)
(url-retrieve
url
#'ein:notebook-save-notebook-callback
(list notebook retry)))))
(ein:query-ajax
(ein:notebook-url notebook)
:type "PUT"
:headers '(("Content-Type" . "application/json"))
:cache nil
:data (json-encode data)
:error (cons #'ein:notebook-save-notebook-error notebook)
:success (cons #'ein:notebook-save-notebook-workaround
(cons notebook retry))
:status-code
`((204 . ,(cons #'ein:notebook-save-notebook-success notebook)))
:timeout 5000)))
(defun ein:notebook-save-notebook-command ()
(interactive)
(ein:notebook-save-notebook ein:notebook 0))
(defun ein:notebook-save-notebook-callback (status notebook retry)
(declare (special url-http-response-status
url-http-method))
(ein:log 'debug "SAVE-NOTEBOOK-CALLBACK nodtebook-id = %S, status = %S"
(ein:$notebook-notebook-id notebook)
status)
(ein:log 'debug "url-http-response-status = %s" url-http-response-status)
(ein:log 'debug "url-request-method = %s" url-request-method)
(ein:log 'debug "url-http-method = %s" (when (boundp 'url-http-method)
url-http-method))
(ein:log 'debug "(buffer-string) = \n%s" (buffer-string))
(let ((response url-http-response-status))
;; ^-- "save" local variable before killing buffer.
(kill-buffer (current-buffer))
(with-current-buffer (ewoc-buffer (ein:$notebook-ewoc notebook))
(ein:aif (plist-get status :error)
(progn
(ein:log 'debug "ERROR CODE = %S" it)
(ein:notebook-save-notebook-error notebook status))
;; IPython server returns 204 only when the notebook URL is
;; accessed via PUT or DELETE. As it seems Emacs failed to
;; choose PUT method every two times, let's check the response
;; here and fail when 204 is not returned.
(if (eq response 204)
(ein:notebook-save-notebook-success notebook status)
(if (< retry ein:notebook-save-retry-max)
(progn
(ein:log 'info "Retry saving... Next count: %s" (1+ retry))
(ein:notebook-save-notebook notebook (1+ retry)))
(ein:notebook-save-notebook-error notebook status)
(ein:log 'info
"Status code (=%s) is not 204 and retry exceeds limit (=%s)."
response ein:notebook-save-retry-max)))))))
(defun* ein:notebook-save-notebook-workaround (nb-retry &rest args
&key
status
response-status
&allow-other-keys)
;; IPython server returns 204 only when the notebook URL is
;; accessed via PUT or DELETE. As it seems Emacs failed to
;; choose PUT method every two times, let's check the response
;; here and fail when 204 is not returned.
(unless (eq response-status 204)
(let ((notebook (car nb-retry))
(retry (cdr nb-retry)))
(with-current-buffer (ein:notebook-buffer notebook)
(if (< retry ein:notebook-save-retry-max)
(progn
(ein:log 'info "Retry saving... Next count: %s" (1+ retry))
(ein:notebook-save-notebook notebook (1+ retry)))
(ein:notebook-save-notebook-error notebook :status status)
(ein:log 'info
"Status code (=%s) is not 204 and retry exceeds limit (=%s)."
response-status ein:notebook-save-retry-max))))))
(defun ein:notebook-save-notebook-success (notebook status)
(defun ein:notebook-save-notebook-success (notebook &rest ignore)
(ein:log 'info "Notebook is saved.")
(setf (ein:$notebook-dirty notebook) nil)
(set-buffer-modified-p nil)
(with-current-buffer (ein:notebook-buffer notebook)
(set-buffer-modified-p nil))
(ein:events-trigger (ein:$notebook-events notebook)
'(notebook_saved . Notebook)))
(defun ein:notebook-save-notebook-error (notebook status)
(defun ein:notebook-save-notebook-error (notebook &rest ignore)
(ein:log 'info "Failed to save notebook!")
(ein:events-trigger (ein:$notebook-events notebook)
'(notebook_save_failed . Notebook)))

View file

@ -71,29 +71,36 @@
(when (and (stringp url-or-port)
(string-match "^[0-9]+$" url-or-port))
(setq url-or-port (string-to-number url-or-port)))
(url-retrieve
(ein:notebooklist-url url-or-port)
(if no-popup
#'ein:notebooklist-url-retrieve-callback
(lambda (&rest args)
(pop-to-buffer (apply #'ein:notebooklist-url-retrieve-callback args))))
(list url-or-port))
(let ((success
(if no-popup
#'ein:notebooklist-url-retrieve-callback
(lambda (&rest args)
(pop-to-buffer
(apply #'ein:notebooklist-url-retrieve-callback args))))))
(ein:query-ajax
(ein:notebooklist-url url-or-port)
:cache nil
:parser #'ein:json-read
:success (cons success url-or-port)
:timeout 5000))
(ein:notebooklist-get-buffer url-or-port))
(defun ein:notebooklist-url-retrieve-callback (status url-or-port)
(defun* ein:notebooklist-url-retrieve-callback (url-or-port
&key
status
data
&allow-other-keys)
"Called via `ein:notebooklist-open'."
(ein:aif (plist-get status :error)
(error "Failed to connect to server '%s'. Got: %S"
(ein:url url-or-port) it))
(let ((data (ein:json-read)))
(kill-buffer (current-buffer))
(with-current-buffer (ein:notebooklist-get-buffer url-or-port)
(setq ein:notebooklist
(make-ein:$notebooklist :url-or-port url-or-port
:data data))
(ein:notebooklist-render)
(goto-char (point-min))
(current-buffer))))
(with-current-buffer (ein:notebooklist-get-buffer url-or-port)
(setq ein:notebooklist
(make-ein:$notebooklist :url-or-port url-or-port
:data data))
(ein:notebooklist-render)
(goto-char (point-min))
(current-buffer)))
(defun ein:notebooklist-reload ()
"Reload current Notebook list."
@ -117,20 +124,24 @@
"Ask server to create a new notebook and update the notebook list buffer."
(message "Creating a new notebook...")
(unless (setq url-or-port (ein:$notebooklist-url-or-port ein:notebooklist)))
(url-retrieve
(ein:query-ajax
(ein:notebooklist-new-url url-or-port)
(lambda (s buffer)
(let ((notebook-id
(ein:notebooklist-get-data-in-body-tag "data-notebook-id")))
(kill-buffer (current-buffer))
(message "Creating a new notebook... Done.")
(with-current-buffer buffer
(if notebook-id
(ein:notebooklist-open-notebook ein:notebooklist notebook-id)
(message (concat "Oops. EIN failed to open new notebook. "
"Please find it in the notebook list."))
(ein:notebooklist-reload)))))
(list (current-buffer))))
:parser (lambda ()
(ein:notebooklist-get-data-in-body-tag "data-notebook-id"))
:success (cons #'ein:notebooklist-new-notebook-callback (current-buffer))
:timeout 5000))
(defun* ein:notebooklist-new-notebook-callback (buffer &key
data
&allow-other-keys)
(let ((notebook-id data))
(message "Creating a new notebook... Done.")
(with-current-buffer buffer
(if notebook-id
(ein:notebooklist-open-notebook ein:notebooklist notebook-id)
(message (concat "Oops. EIN failed to open new notebook. "
"Please find it in the notebook list."))
(ein:notebooklist-reload)))))
(defun ein:notebooklist-delete-notebook-ask (notebook-id name)
(when (y-or-n-p (format "Delete notebook %s?" name))
@ -138,19 +149,17 @@
(defun ein:notebooklist-delete-notebook (notebook-id name)
(message "Deleting notebook %s..." name)
(let ((url (ein:url-no-cache
(ein:notebook-url-from-url-and-id
(ein:$notebooklist-url-or-port ein:notebooklist)
notebook-id)))
(url-request-method "DELETE"))
(url-retrieve
url
(lambda (s buffer name)
(kill-buffer (current-buffer))
(message "Deleting notebook %s... Done." name)
(with-current-buffer buffer
(ein:notebooklist-reload)))
(list (current-buffer) name))))
(ein:query-ajax
(ein:notebook-url-from-url-and-id
(ein:$notebooklist-url-or-port ein:notebooklist)
notebook-id)
:cache nil
:type "DELETE"
:success (cons (lambda (packed &rest ignore)
(message "Deleting notebook %s... Done." (cdr packed))
(with-current-buffer (car packed)
(ein:notebooklist-reload)))
(cons (current-buffer) name))))
(defun ein:notebooklist-render ()
"Render notebook list widget.

179
ein-query.el Normal file
View file

@ -0,0 +1,179 @@
;;; ein-query.el --- jQuery like interface on to of url-retrieve
;; Copyright (C) 2012- Takafumi Arakaki
;; Author: Takafumi Arakaki
;; This file is NOT part of GNU Emacs.
;; ein-query.el is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; ein-query.el is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with ein-query.el. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(eval-when-compile (require 'cl))
(require 'url)
(require 'ein-utils)
(require 'ein-log)
(defun ein:safe-funcall-packed (packed &rest args)
(when packed
(ein:log-ignore-errors (apply #'ein:funcall-packed packed args))))
(defmacro ein:with-live-buffer (buffer &rest body)
"Execute BODY if BUFFER is alive."
(declare (indent 1) (debug t))
`(when (buffer-live-p ,buffer) (with-current-buffer ,buffer ,@body)))
(ein:deflocal ein:query-ajax-timer nil)
(defun* ein:query-ajax (url &rest settings
&key
(cache t)
(type "GET")
(data nil)
(parser nil)
(headers nil)
(success nil)
(error nil)
(timeout nil)
(status-code nil))
"Mimic `$.ajax'.
:CACHE (nil/t) : append time-stamp to URL so the URL is always loaded.
:TYPE (string) : sets `url-request-method'
:DATA (string) : sets `url-request-data'
:PARSER (symbol) : a function that reads current buffer and return data
:HEADERS (alist) : sets `url-request-extra-headers'
:SUCCESS (cons) : called on success
:ERROR (cons) : called on error
:TIMEOUT (number) : timeout in millisecond
:STATUS-CODE (alist) : map status code (int) to callback (cons)
* Callback functions
All callbacks must be given as `cons' where car is a FUNCTION and
cdr is its first ARGUMENT. It is analogous of `$.proxy'. Call
signature is like this:
\(FUNCTION ARGUMENT [other callback specific arguments])
Also note that the callback FUNCTION must be defined
using `defun*' with `&key' and `&allow-other-keys' to ignore
missing/extra arguments as some callback (namely :ERROR) changes
arguments to be passed, depending on situation.
* :ERROR callback
:SYMBOL-STATUS (`error'/`timeout') : analogous of `textStatus'
:STATUS (list) : see `url-retrieve'
:RESPONSE-STATUS : = `url-http-response-status'
* :SUCCESS callback
This callback takes :DATA (object), which is a data object parsed
by :PARSER. If :PARSER is not specified, this is nil.
The :SUCCESS callback also takes the :STATUS and :RESPONSE-STATUS
argument.
* :STATUS-CODE callback
Each value of this alist is a callback which is similar to :ERROR
or :SUCCESS callback. However, current buffer of this callback
is not guaranteed to be the process buffer.
* :PARSER function
This is analogous to the `dataType' argument of `$.ajax'.
Only this function can accuses to the process buffer, which
is killed immediately after the execution of this function.
* See also: http://api.jquery.com/jQuery.ajax/"
(ein:log 'debug "EIN:QUERY-AJAX")
(unless cache
(setq url (ein:url-no-cache url)))
(let* ((url-request-extra-headers headers)
(url-request-method type)
(url-request-data data)
(buffer (url-retrieve url #'ein:query-ajax-callback settings)))
(when timeout
(ein:log 'debug "Start timer: timeout=%s ms" timeout)
(with-current-buffer buffer
(setq ein:query-ajax-timer
(apply #'run-at-time
(/ timeout 1000.0) nil
#'ein:query-ajax-timeout-callback
(cons buffer settings)))))
buffer))
(defun* ein:query-ajax-callback (status &key
(headers nil)
(parser nil)
(success nil)
(error nil)
(timeout nil)
(status-code nil)
&allow-other-keys)
(declare (special url-http-response-status))
(ein:log 'debug "EIN:QUERY-AJAX-CALLBACK")
(ein:log 'debug "status = %S" status)
(ein:log 'debug "url-http-response-status = %s" url-http-response-status)
(ein:log 'debug "(buffer-string) =\n%s" (buffer-string))
(ein:query-ajax-cancel-timer)
(let* ((buffer (current-buffer)) ; `parser' could change buffer...
(response-status url-http-response-status)
(status-code-callback (cdr (assq response-status status-code)))
(status-error (plist-get status :error))
(data (if (and parser (not status-error))
(unwind-protect
(funcall parser)
(kill-buffer buffer)))))
(ein:log 'debug "data = %s" data)
(ein:log 'debug "Executing success/error callback.")
(apply #'ein:safe-funcall-packed
(append (if (plist-get status :error)
(list error :symbol-status 'error)
(list success))
(list :status status :data data
:response-status response-status)))
(ein:log 'debug "Executing status-code callback.")
(ein:safe-funcall-packed status-code-callback
:status status :data data)))
(defun* ein:query-ajax-timeout-callback (buffer &key
(error nil)
&allow-other-keys)
(ein:log 'debug "EIN:QUERY-AJAX-TIMEOUT-CALLBACK buffer = %s" buffer)
(ein:with-live-buffer buffer
(ein:safe-funcall-packed error :symbol-status 'timeout)
(let ((proc (process-buffer buffer)))
(kill-process proc)
(kill-buffer buffer))))
(defun ein:query-ajax-cancel-timer ()
(ein:log 'debug "EIN:QUERY-AJAX-CANCEL-TIMER")
(when ein:query-ajax-timer
(cancel-timer ein:query-ajax-timer)
(setq ein:query-ajax-timer nil)))
(provide 'ein-query)
;;; ein-query.el ends here

View file

@ -2,6 +2,7 @@
(require 'ert)
(require 'ein-notebooklist)
(require 'wid-edit)
;; Execute `eintest:dz-ipython-start' before starting the following
;; test to setup server.
@ -39,14 +40,27 @@ Make MAX-COUNT larger \(default 50) to wait longer before timeout."
(let ((notebook (eintest:get-notebook-by-name url-or-port "Untitled0")))
(if notebook
notebook
(with-current-buffer (ein:notebooklist-get-buffer url-or-port)
(with-current-buffer (ein:notebooklist-open url-or-port t)
(setq ein:notebooklist nil)
(eintest:wait-until (lambda () ein:notebooklist))
(setq ein:notebooklist nil)
(ein:notebooklist-new-notebook url-or-port)
(eintest:wait-until (lambda () ein:notebooklist)))
(eintest:wait-until
(lambda () (eintest:get-notebook-by-name url-or-port "Untitled0"))))
(eintest:get-notebook-by-name url-or-port "Untitled0"))))
(defun eintest:delete-notebook-by-name (url-or-port notebook-name)
(with-current-buffer (ein:notebooklist-open url-or-port nil)
(eintest:wait-until (lambda () ein:notebooklist))
(save-excursion
(goto-char (point-min))
(search-forward notebook-name)
(move-beginning-of-line 1)
(search-forward "Delete")
(flet ((y-or-n-p (ignore) t))
(widget-button-press (point))))
(setq ein:notebooklist nil)
(eintest:wait-until (lambda () ein:notebooklist))))
(ert-deftest eintest:get-untitled0-or-create ()
(let ((notebook (eintest:get-untitled0-or-create eintest:port)))
(eintest:wait-until (lambda () (ein:aand (ein:$notebook-kernel notebook)
@ -54,6 +68,16 @@ Make MAX-COUNT larger \(default 50) to wait longer before timeout."
(with-current-buffer (ein:notebook-buffer notebook)
(should (equal (ein:$notebook-notebook-name ein:notebook) "Untitled0")))))
(ert-deftest eintest:delete-untitled0 ()
(loop
repeat 2
do (let ((notebook (eintest:get-untitled0-or-create eintest:port)))
(eintest:wait-until
(lambda () (ein:aand (ein:$notebook-kernel notebook)
(ein:kernel-ready-p it)))))
do (eintest:delete-notebook-by-name eintest:port "Untitled0")
do (should-not (eintest:get-notebook-by-name eintest:port "Untitled0"))))
(ert-deftest ein:notebook-execute-current-cell-simple ()
(let ((notebook (eintest:get-untitled0-or-create eintest:port)))
(eintest:wait-until (lambda () (ein:aand (ein:$notebook-kernel notebook)

View file

@ -12,8 +12,9 @@
(let* ((kernel (eintest:kernel-new 8888))
(notebook-id "NOTEBOOK-ID")
(desired-url "http://127.0.0.1:8888/kernels?notebook=NOTEBOOK-ID")
(dummy-buffer (get-buffer-create "*eintest:dummy*"))
got-url)
(flet ((url-retrieve (url &rest ignore) (setq got-url url)))
(flet ((url-retrieve (url &rest ignore) (setq got-url url) dummy-buffer))
(ein:kernel-start kernel notebook-id)
(should (equal got-url desired-url)))))
@ -21,12 +22,13 @@
(let* ((kernel (eintest:kernel-new 8888))
(kernel-id "KERNEL-ID")
(desired-url "http://127.0.0.1:8888/kernels/KERNEL-ID/restart")
(dummy-buffer (get-buffer-create "*eintest:dummy*"))
got-url)
(flet ((url-retrieve (url &rest ignore) (setq got-url url));
(flet ((url-retrieve (url &rest ignore) (setq got-url url) dummy-buffer)
(ein:kernel-stop-channels (&rest ignore))
(ein:websocket (&rest ignore) (make-ein:$websocket))
(ein:events-trigger (&rest ignore)))
(ein:kernel--kernel-started kernel (list :kernel_id kernel-id))
(ein:kernel--kernel-started kernel :data (list :kernel_id kernel-id))
(ein:kernel-restart kernel)
(should (equal got-url desired-url)))))
@ -35,11 +37,12 @@
(let* ((kernel (eintest:kernel-new 8888))
(kernel-id "KERNEL-ID")
(desired-url "http://127.0.0.1:8888/kernels/KERNEL-ID/interrupt")
(dummy-buffer (get-buffer-create "*eintest:dummy*"))
got-url)
(flet ((url-retrieve (url &rest ignore) (setq got-url url))
(flet ((url-retrieve (url &rest ignore) (setq got-url url) dummy-buffer)
(ein:kernel-stop-channels (&rest ignore))
(ein:websocket (&rest ignore) (make-ein:$websocket)))
(ein:kernel--kernel-started kernel (list :kernel_id kernel-id))
(ein:kernel--kernel-started kernel :data (list :kernel_id kernel-id))
(ein:kernel-interrupt kernel)
(should (equal got-url desired-url)))))
@ -47,11 +50,12 @@
(let* ((kernel (eintest:kernel-new 8888))
(kernel-id "KERNEL-ID")
(desired-url "http://127.0.0.1:8888/kernels/KERNEL-ID")
(dummy-buffer (get-buffer-create "*eintest:dummy*"))
got-url)
(flet ((url-retrieve (url &rest ignore) (setq got-url url))
(flet ((url-retrieve (url &rest ignore) (setq got-url url) dummy-buffer)
(ein:kernel-stop-channels (&rest ignore))
(ein:websocket (&rest ignore) (make-ein:$websocket)))
(ein:kernel--kernel-started kernel (list :kernel_id kernel-id))
(ein:kernel--kernel-started kernel :data (list :kernel_id kernel-id))
(ein:kernel-kill kernel)
(let* ((l (split-string got-url "?"))
(got-url-0 (nth 0 l))

View file

@ -44,19 +44,16 @@
(defun eintest:notebook-from-json (json-string &optional notebook-id)
(unless notebook-id (setq notebook-id "NOTEBOOK-ID"))
(with-temp-buffer
(erase-buffer)
(insert json-string)
(flet ((pop-to-buffer (buf) buf)
(ein:notebook-start-kernel ()))
(with-current-buffer (ein:notebook-url-retrieve-callback
nil
(ein:notebook-new "DUMMY-URL" notebook-id))
(let ((events (ein:events-new (current-buffer))))
(setf (ein:$notebook-events ein:notebook) events)
(setf (ein:$notebook-kernel ein:notebook)
(ein:kernel-new 8888 "/kernels" events)))
(current-buffer)))))
(flet ((pop-to-buffer (buf) buf)
(ein:notebook-start-kernel ()))
(with-current-buffer (ein:notebook-request-open-callback
(ein:notebook-new "DUMMY-URL" notebook-id)
:data (ein:json-read-from-string json-string))
(let ((events (ein:events-new (current-buffer))))
(setf (ein:$notebook-events ein:notebook) events)
(setf (ein:$notebook-kernel ein:notebook)
(ein:kernel-new 8888 "/kernels" events)))
(current-buffer))))
(defun eintest:notebook-make-data (cells &optional name)
(unless name (setq name "Dummy Name"))