From 82d5cffeca77974676f2e8b161f00accd914af71 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Fri, 25 May 2012 20:57:48 +0200 Subject: [PATCH 01/30] Add ein-query.el --- ein-query.el | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 ein-query.el diff --git a/ein-query.el b/ein-query.el new file mode 100644 index 0000000..ce02823 --- /dev/null +++ b/ein-query.el @@ -0,0 +1,132 @@ +;;; 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 . + +;;; 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)))) + +(defun* ein:query-ajax (url &rest settings + &key + (cache t) + (type "GET") + (data 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' +: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]) + +The second note is 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. + +Finally, note that callback FUNCTION is executed on the process +buffer, meaning that response data is on the current buffer when +the FUNCTION is called. There is no `:data' argument for +FUNCTION so it must be fetched from the buffer. + +* :ERROR callback + +:SYMBOL-STATUS (`error'/`timeout') : analogous of `textStatus' +:STATUS (list) : see `url-retrieve' + +The :SUCCESS callback also takes the :STATUS argument. + +* See also: http://api.jquery.com/jQuery.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 + (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) + (success nil) + (error nil) + (timeout nil) + (status-code nil) + &allow-other-keys) + (declare (special url-http-response-status + url-http-method)) + (unwind-protect + (progn + (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)) + + (apply #'ein:safe-funcall-packed + (if (plist-get status :error) + (list error :symbol-status 'error :status status) + (list success :status status))) + (ein:aif (assq url-http-response-status status-code) + (ein:safe-funcall-packed (cdr it)))) + (kill-buffer))) + +(defun* ein:query-ajax-timeout-callback (buffer &key + (error nil) + &allow-other-keys) + (with-current-buffer buffer + (ein:safe-funcall-packed error :symbol-status 'timeout)) + (let ((proc (process-buffer buffer))) + (kill-process proc) + (kill-buffer buffer))) + +(provide 'ein-query) + +;;; ein-query.el ends here From 81334a86e8044b79db2e7d5329f280fde231cfd7 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Fri, 25 May 2012 22:12:34 +0200 Subject: [PATCH 02/30] Use ein-query-ajax in ein:notebook-save-notebook This change adds timeout to notebook-save-notebook. This is useful since sometimes Emacs does not start transaction and have opened process hanging around. This change also fixes a bug which might be occurred in the previous version: ein:notebook-discard-output-p is called from ein:notebook-save-notebook via ein:notebook-to-json but not on the notebook buffer. This function access to the buffer, but not treated properly. This change fixes this problem. --- ein-notebook.el | 85 ++++++++++++++++++++++--------------------------- 1 file changed, 38 insertions(+), 47 deletions(-) diff --git a/ein-notebook.el b/ein-notebook.el index 8eebcc1..7605155 100644 --- a/ein-notebook.el +++ b/ein-notebook.el @@ -39,6 +39,7 @@ (require 'ein-events) (require 'ein-notification) (require 'ein-kill-ring) +(require 'ein-query) ;;; Configuration @@ -62,12 +63,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 @@ -738,7 +740,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 +753,52 @@ 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) +(defun* ein:notebook-save-notebook-workaround (nb-retry &rest args + &key + status + &allow-other-keys) + (declare (special url-http-response-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. + (unless (eq url-http-response-status 204) + (let ((notebook (car nb-retry)) + (retry (cdr nb-retry))) + (if (< retry ein:notebook-save-retry-max) (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))))))) + (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)." + url-http-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) (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))) From 3385c6fb4713afc47f79e23fddf098f811fefbf2 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Fri, 25 May 2012 22:19:05 +0200 Subject: [PATCH 03/30] Add ein:debug global switch --- ein-log.el | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/ein-log.el b/ein-log.el index 9439b92..7bfa063 100644 --- a/ein-log.el +++ b/ein-log.el @@ -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'." From be1148ff4ad812c6904ba7b43849a7660fdcd8bc Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Fri, 25 May 2012 22:43:56 +0200 Subject: [PATCH 04/30] Fix a bug: retrying save saves random texts This is because ein:notebook-to-json touches to current buffer and read the text from there. --- ein-notebook.el | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/ein-notebook.el b/ein-notebook.el index 7605155..b486376 100644 --- a/ein-notebook.el +++ b/ein-notebook.el @@ -740,11 +740,12 @@ 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 notebook)) - (cells (mapcar (lambda (c) (ein:cell-to-json c discard)) - (ein:notebook-get-cells notebook)))) - `((worksheets . [((cells . ,(apply #'vector cells)))]) - (metadata . ,(ein:$notebook-metadata notebook))))) + (with-current-buffer (ein:notebook-buffer notebook) + (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)))]) + (metadata . ,(ein:$notebook-metadata notebook)))))) (defun ein:notebook-save-notebook (notebook retry) (let ((data (ein:notebook-to-json notebook))) @@ -794,7 +795,8 @@ Do not clear input prompts when the prefix argument is given." (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))) From 33ef77d3be56ecd9817f6dbef4a843c322a5cb37 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Fri, 25 May 2012 22:58:01 +0200 Subject: [PATCH 05/30] Add "Coding rule about current buffer." And apply it to the previous fix. --- ein-notebook.el | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/ein-notebook.el b/ein-notebook.el index b486376..6f342c3 100644 --- a/ein-notebook.el +++ b/ein-notebook.el @@ -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: @@ -740,12 +747,11 @@ Do not clear input prompts when the prefix argument is given." (defun ein:notebook-to-json (notebook) "Return json-ready alist." - (with-current-buffer (ein:notebook-buffer notebook) - (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)))]) - (metadata . ,(ein:$notebook-metadata notebook)))))) + (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)))]) + (metadata . ,(ein:$notebook-metadata notebook))))) (defun ein:notebook-save-notebook (notebook retry) (let ((data (ein:notebook-to-json notebook))) @@ -783,14 +789,15 @@ Do not clear input prompts when the prefix argument is given." (unless (eq url-http-response-status 204) (let ((notebook (car nb-retry)) (retry (cdr nb-retry))) - (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)." - url-http-response-status ein:notebook-save-retry-max))))) + (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)." + url-http-response-status ein:notebook-save-retry-max)))))) (defun ein:notebook-save-notebook-success (notebook &rest ignore) (ein:log 'info "Notebook is saved.") From 4011a79ace09cba4cc806fe59ed828f3dc18cac4 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 16:34:04 +0200 Subject: [PATCH 06/30] Add ein:query-ajax-cancel-timer --- ein-query.el | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/ein-query.el b/ein-query.el index ce02823..79dd3fd 100644 --- a/ein-query.el +++ b/ein-query.el @@ -35,6 +35,8 @@ (when packed (ein:log-ignore-errors (apply #'ein:funcall-packed packed args)))) +(ein:deflocal ein:query-ajax-timer nil) + (defun* ein:query-ajax (url &rest settings &key (cache t) @@ -81,6 +83,7 @@ FUNCTION so it must be fetched from the buffer. The :SUCCESS callback also takes the :STATUS argument. * 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) @@ -88,9 +91,12 @@ The :SUCCESS callback also takes the :STATUS argument. (url-request-data data) (buffer (url-retrieve url #'ein:query-ajax-callback settings))) (when timeout - (run-at-time (/ timeout 1000.0) nil - #'ein:query-ajax-timeout-callback - (cons buffer settings))) + (ein:log 'debug "Start timer: timeout=%s ms" timeout) + (with-current-buffer buffer + (setq ein:query-ajax-timer + (run-at-time (/ timeout 1000.0) nil + #'ein:query-ajax-timeout-callback + (cons buffer settings))))) buffer)) (defun* ein:query-ajax-callback (status &key @@ -116,17 +122,24 @@ The :SUCCESS callback also takes the :STATUS argument. (list success :status status))) (ein:aif (assq url-http-response-status status-code) (ein:safe-funcall-packed (cdr it)))) + (ein:query-ajax-cancel-timer) (kill-buffer))) (defun* ein:query-ajax-timeout-callback (buffer &key (error nil) &allow-other-keys) + (ein:log 'debug "EIN:QUERY-AJAX-TIMEOUT-CALLBACK") (with-current-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))) + (provide 'ein-query) ;;; ein-query.el ends here From c90d66f4f4129d9070251dc435d04c15e1148391 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 16:57:42 +0200 Subject: [PATCH 07/30] Use ein:query-ajax in ein:notebooklist-open notebooklist-open does not work. --- ein-notebooklist.el | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/ein-notebooklist.el b/ein-notebooklist.el index a5a7ca4..fc4bf61 100644 --- a/ein-notebooklist.el +++ b/ein-notebooklist.el @@ -71,16 +71,23 @@ (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 + :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 + &allow-other-keys) "Called via `ein:notebooklist-open'." (ein:aif (plist-get status :error) (error "Failed to connect to server '%s'. Got: %S" From 48a8f3835e2cebde77b55a905aba8b090fbde450 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 16:59:42 +0200 Subject: [PATCH 08/30] Suppress error: url-http-response-status is void --- ein-query.el | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ein-query.el b/ein-query.el index 79dd3fd..0d4edfa 100644 --- a/ein-query.el +++ b/ein-query.el @@ -106,21 +106,20 @@ The :SUCCESS callback also takes the :STATUS argument. (timeout nil) (status-code nil) &allow-other-keys) - (declare (special url-http-response-status - url-http-method)) (unwind-protect (progn (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:eval-if-bound 'url-http-response-status)) (ein:log 'debug "(buffer-string) =\n%s" (buffer-string)) (apply #'ein:safe-funcall-packed (if (plist-get status :error) (list error :symbol-status 'error :status status) (list success :status status))) - (ein:aif (assq url-http-response-status status-code) + (ein:aif (assq (ein:eval-if-bound 'url-http-response-status) + status-code) (ein:safe-funcall-packed (cdr it)))) (ein:query-ajax-cancel-timer) (kill-buffer))) From a06442194a780380a2b48b0b426ab446cca95ba8 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 17:00:21 +0200 Subject: [PATCH 09/30] Bit better ein:query-ajax-cancel-timer --- ein-query.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ein-query.el b/ein-query.el index 0d4edfa..eac29bb 100644 --- a/ein-query.el +++ b/ein-query.el @@ -137,7 +137,8 @@ The :SUCCESS callback also takes the :STATUS argument. (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))) + (cancel-timer ein:query-ajax-timer) + (setq ein:query-ajax-timer nil))) (provide 'ein-query) From ef8f59a3bf87b1a476002bb500e2b8b839144ee4 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 17:01:23 +0200 Subject: [PATCH 10/30] Fix arguments for run-at-time in ein-query --- ein-query.el | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ein-query.el b/ein-query.el index eac29bb..8a1ee31 100644 --- a/ein-query.el +++ b/ein-query.el @@ -94,9 +94,10 @@ The :SUCCESS callback also takes the :STATUS argument. (ein:log 'debug "Start timer: timeout=%s ms" timeout) (with-current-buffer buffer (setq ein:query-ajax-timer - (run-at-time (/ timeout 1000.0) nil - #'ein:query-ajax-timeout-callback - (cons buffer settings))))) + (apply #'run-at-time + (/ timeout 1000.0) nil + #'ein:query-ajax-timeout-callback + (cons buffer settings))))) buffer)) (defun* ein:query-ajax-callback (status &key @@ -127,7 +128,7 @@ The :SUCCESS callback also takes the :STATUS argument. (defun* ein:query-ajax-timeout-callback (buffer &key (error nil) &allow-other-keys) - (ein:log 'debug "EIN:QUERY-AJAX-TIMEOUT-CALLBACK") + (ein:log 'debug "EIN:QUERY-AJAX-TIMEOUT-CALLBACK buffer = %s" buffer) (with-current-buffer buffer (ein:safe-funcall-packed error :symbol-status 'timeout)) (let ((proc (process-buffer buffer))) From 4d1166dcbde3195448a4ddf0f536dcd277325210 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 17:13:17 +0200 Subject: [PATCH 11/30] Fix bugs in ein:notebooklist-open There was two bugs: * Process buffer was killed in ein:notebooklist-url-retrieve-callback where should be handled by ein:query-ajax-callback. There was two calls of kill-buffer. This is why the list buffer was killed. * At the time ein:query-ajax-cancel-timer is called in ein:query-ajax-callback the current buffer was changed because pop-to-buffer is called in the callback. Wrapping callbacks with save-current-buffer fixes the problem. --- ein-notebooklist.el | 1 - ein-query.el | 15 ++++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ein-notebooklist.el b/ein-notebooklist.el index fc4bf61..946e4ac 100644 --- a/ein-notebooklist.el +++ b/ein-notebooklist.el @@ -93,7 +93,6 @@ (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 diff --git a/ein-query.el b/ein-query.el index 8a1ee31..9cac80e 100644 --- a/ein-query.el +++ b/ein-query.el @@ -115,13 +115,14 @@ The :SUCCESS callback also takes the :STATUS argument. (ein:eval-if-bound 'url-http-response-status)) (ein:log 'debug "(buffer-string) =\n%s" (buffer-string)) - (apply #'ein:safe-funcall-packed - (if (plist-get status :error) - (list error :symbol-status 'error :status status) - (list success :status status))) - (ein:aif (assq (ein:eval-if-bound 'url-http-response-status) - status-code) - (ein:safe-funcall-packed (cdr it)))) + (save-current-buffer + (apply #'ein:safe-funcall-packed + (if (plist-get status :error) + (list error :symbol-status 'error :status status) + (list success :status status))) + (ein:aif (assq (ein:eval-if-bound 'url-http-response-status) + status-code) + (ein:safe-funcall-packed (cdr it))))) (ein:query-ajax-cancel-timer) (kill-buffer))) From 56d92f91214b62c8a2b5d306172fcd798e46a72e Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 17:18:34 +0200 Subject: [PATCH 12/30] Revert "Suppress error: url-http-response-status is void" This reverts commit 48a8f3835e2cebde77b55a905aba8b090fbde450. Conflicts: ein-query.el --- ein-query.el | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ein-query.el b/ein-query.el index 9cac80e..40da878 100644 --- a/ein-query.el +++ b/ein-query.el @@ -107,12 +107,14 @@ The :SUCCESS callback also takes the :STATUS argument. (timeout nil) (status-code nil) &allow-other-keys) + (declare (special url-http-response-status + url-http-method)) (unwind-protect (progn (ein:log 'debug "EIN:QUERY-AJAX-CALLBACK") (ein:log 'debug "status = %S" status) (ein:log 'debug "url-http-response-status = %s" - (ein:eval-if-bound 'url-http-response-status)) + url-http-response-status) (ein:log 'debug "(buffer-string) =\n%s" (buffer-string)) (save-current-buffer @@ -120,8 +122,7 @@ The :SUCCESS callback also takes the :STATUS argument. (if (plist-get status :error) (list error :symbol-status 'error :status status) (list success :status status))) - (ein:aif (assq (ein:eval-if-bound 'url-http-response-status) - status-code) + (ein:aif (assq url-http-response-status status-code) (ein:safe-funcall-packed (cdr it))))) (ein:query-ajax-cancel-timer) (kill-buffer))) From fb67781402593f91bf0e84424a29b6af699ee0d4 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 17:20:20 +0200 Subject: [PATCH 13/30] Fix ein:query-ajax-callback Callback must be wrapped one by one. Fix "url-http-response-status is void" error when calling ein:notebooklist-open. --- ein-query.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ein-query.el b/ein-query.el index 40da878..e072d38 100644 --- a/ein-query.el +++ b/ein-query.el @@ -121,7 +121,8 @@ The :SUCCESS callback also takes the :STATUS argument. (apply #'ein:safe-funcall-packed (if (plist-get status :error) (list error :symbol-status 'error :status status) - (list success :status status))) + (list success :status status)))) + (save-current-buffer (ein:aif (assq url-http-response-status status-code) (ein:safe-funcall-packed (cdr it))))) (ein:query-ajax-cancel-timer) From 55eb90899352b198ac8a30e6a5eb5016538ee325 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 17:21:47 +0200 Subject: [PATCH 14/30] Remove unused url-http-method in ajax callback --- ein-query.el | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ein-query.el b/ein-query.el index e072d38..0ebf00f 100644 --- a/ein-query.el +++ b/ein-query.el @@ -107,8 +107,7 @@ The :SUCCESS callback also takes the :STATUS argument. (timeout nil) (status-code nil) &allow-other-keys) - (declare (special url-http-response-status - url-http-method)) + (declare (special url-http-response-status)) (unwind-protect (progn (ein:log 'debug "EIN:QUERY-AJAX-CALLBACK") From 783e430105c4e43888ef6662bacab417ebb7d87f Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 17:30:58 +0200 Subject: [PATCH 15/30] Use ein:query-ajax in ein:notebooklist-new-notebook --- ein-notebooklist.el | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/ein-notebooklist.el b/ein-notebooklist.el index 946e4ac..c815c3d 100644 --- a/ein-notebooklist.el +++ b/ein-notebooklist.el @@ -123,20 +123,23 @@ "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)))) + :success + (cons (lambda (buffer &rest ignore) + (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))))) + (current-buffer)) + :timeout 5000)) (defun ein:notebooklist-delete-notebook-ask (notebook-id name) (when (y-or-n-p (format "Delete notebook %s?" name)) From 388a59efa29f147147d89c8aee7b100af97e2504 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 19:00:34 +0200 Subject: [PATCH 16/30] Fix ein:notebooklist-new-notebook Do not kill process buffer when using ein:query-ajax --- ein-notebooklist.el | 1 - 1 file changed, 1 deletion(-) diff --git a/ein-notebooklist.el b/ein-notebooklist.el index c815c3d..7712882 100644 --- a/ein-notebooklist.el +++ b/ein-notebooklist.el @@ -129,7 +129,6 @@ (cons (lambda (buffer &rest ignore) (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 From 9061e1c5154234ba08c4d68d903cda01c445930d Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 19:01:39 +0200 Subject: [PATCH 17/30] Use ein:query-ajax in ein:notebooklist-delete-notebook --- ein-notebooklist.el | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/ein-notebooklist.el b/ein-notebooklist.el index 7712882..fb33289 100644 --- a/ein-notebooklist.el +++ b/ein-notebooklist.el @@ -146,19 +146,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. From fff269fc3901883c74f4e6a6b22993c944347610 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 19:08:15 +0200 Subject: [PATCH 18/30] ein:notebooklist-delete-notebook works again The bug was in ein:query-ajax-callback. When url-retrieve called in its callback (which is the case of ein:notebooklist-delete-notebook), same process buffer is reused. Therefore, old code killed another buffer (namely notebook list buffer) by accident and the variable url-http-response-status was void because it is outside of the process buffer (I am not sure about this part). Current workaround is to check if the buffer is live before executing buffer, using new macro ein:with-live-buffer. --- ein-query.el | 53 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/ein-query.el b/ein-query.el index 0ebf00f..3631590 100644 --- a/ein-query.el +++ b/ein-query.el @@ -35,6 +35,11 @@ (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 @@ -108,34 +113,38 @@ The :SUCCESS callback also takes the :STATUS argument. (status-code nil) &allow-other-keys) (declare (special url-http-response-status)) - (unwind-protect - (progn - (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)) + (let ((buffer (current-buffer))) + (unwind-protect + (progn + (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)) - (save-current-buffer - (apply #'ein:safe-funcall-packed - (if (plist-get status :error) - (list error :symbol-status 'error :status status) - (list success :status status)))) - (save-current-buffer - (ein:aif (assq url-http-response-status status-code) - (ein:safe-funcall-packed (cdr it))))) - (ein:query-ajax-cancel-timer) - (kill-buffer))) + (ein:with-live-buffer buffer + (ein:log 'debug "Executing success/error callback.") + (apply #'ein:safe-funcall-packed + (if (plist-get status :error) + (list error :symbol-status 'error :status status) + (list success :status status)))) + (ein:with-live-buffer buffer + (ein:log 'debug "Executing status-code callback.") + (ein:aif (assq url-http-response-status status-code) + (ein:safe-funcall-packed (cdr it))))) + (ein:with-live-buffer buffer + (ein:query-ajax-cancel-timer)) + (kill-buffer buffer)))) (defun* ein:query-ajax-timeout-callback (buffer &key (error nil) &allow-other-keys) (ein:log 'debug "EIN:QUERY-AJAX-TIMEOUT-CALLBACK buffer = %s" buffer) - (with-current-buffer buffer - (ein:safe-funcall-packed error :symbol-status 'timeout)) - (let ((proc (process-buffer buffer))) - (kill-process proc) - (kill-buffer 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") From cb5f53c18333efdd80484bf9bd6d3d4b39d00fdd Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 19:25:00 +0200 Subject: [PATCH 19/30] Simpler and better fix than the previous one Previous fix ignores callbacks even if it is specified if the buffer is killed. This is simply wrong. As the user of :STATUS-CODE callback does not touch current buffer, I change the spec. --- ein-query.el | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/ein-query.el b/ein-query.el index 3631590..c2ed9c0 100644 --- a/ein-query.el +++ b/ein-query.el @@ -87,6 +87,12 @@ FUNCTION so it must be fetched from the buffer. The :SUCCESS callback also takes the :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. + * See also: http://api.jquery.com/jQuery.ajax/" (ein:log 'debug "EIN:QUERY-AJAX") (unless cache @@ -113,7 +119,9 @@ The :SUCCESS callback also takes the :STATUS argument. (status-code nil) &allow-other-keys) (declare (special url-http-response-status)) - (let ((buffer (current-buffer))) + (let ((buffer (current-buffer)) + (status-code-callback + (cdr (assq url-http-response-status status-code)))) (unwind-protect (progn (ein:log 'debug "EIN:QUERY-AJAX-CALLBACK") @@ -122,16 +130,14 @@ The :SUCCESS callback also takes the :STATUS argument. url-http-response-status) (ein:log 'debug "(buffer-string) =\n%s" (buffer-string)) - (ein:with-live-buffer buffer - (ein:log 'debug "Executing success/error callback.") - (apply #'ein:safe-funcall-packed - (if (plist-get status :error) - (list error :symbol-status 'error :status status) - (list success :status status)))) - (ein:with-live-buffer buffer - (ein:log 'debug "Executing status-code callback.") - (ein:aif (assq url-http-response-status status-code) - (ein:safe-funcall-packed (cdr it))))) + (ein:log 'debug "Executing success/error callback.") + (apply #'ein:safe-funcall-packed + (if (plist-get status :error) + (list error :symbol-status 'error :status status) + (list success :status status))) + + (ein:log 'debug "Executing status-code callback.") + (ein:safe-funcall-packed status-code-callback)) (ein:with-live-buffer buffer (ein:query-ajax-cancel-timer)) (kill-buffer buffer)))) From 7a50ae0a3a17950ef9ba5879ca2485cf99f5dc93 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 19:51:57 +0200 Subject: [PATCH 20/30] Add ein:notebooklist-new-notebook-callback --- ein-notebooklist.el | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/ein-notebooklist.el b/ein-notebooklist.el index fb33289..ef6e2a9 100644 --- a/ein-notebooklist.el +++ b/ein-notebooklist.el @@ -125,21 +125,20 @@ (unless (setq url-or-port (ein:$notebooklist-url-or-port ein:notebooklist))) (ein:query-ajax (ein:notebooklist-new-url url-or-port) - :success - (cons (lambda (buffer &rest ignore) - (let ((notebook-id - (ein:notebooklist-get-data-in-body-tag "data-notebook-id"))) - (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))))) - (current-buffer)) + :success (cons #'ein:notebooklist-new-notebook-callback (current-buffer)) :timeout 5000)) +(defun ein:notebooklist-new-notebook-callback (buffer &rest ignore) + (let ((notebook-id + (ein:notebooklist-get-data-in-body-tag "data-notebook-id"))) + (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)) (ein:notebooklist-delete-notebook notebook-id name))) From 5a65aba368b1d2fc56de601ab975b492f19f9f10 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 20:00:17 +0200 Subject: [PATCH 21/30] Add DATA-TYPE argument to ein:query-ajax This solves the problem due to the url-retrieve gotcha. Main changes: * Separation of the function to parse buffer and callback. This is good because parsed data can be used from multiple callbacks (SUCCESS and STATUS-CODE). * As a result, current buffer for callbacks is not process buffer anymore. Callbacks should not assume any particular current buffer. * RESPONSE-STATUS is added to the arguments for callbacks to pass around the value of url-http-response-status. Previous attempts: * cb5f53c18333efdd80484bf9bd6d3d4b39d00fdd: Simpler and better fix than the previous one * fff269fc3901883c74f4e6a6b22993c944347610: ein:notebooklist-delete-notebook works again --- ein-notebook.el | 6 ++--- ein-notebooklist.el | 26 +++++++++++-------- ein-query.el | 61 +++++++++++++++++++++++++-------------------- 3 files changed, 52 insertions(+), 41 deletions(-) diff --git a/ein-notebook.el b/ein-notebook.el index 6f342c3..fd3c295 100644 --- a/ein-notebook.el +++ b/ein-notebook.el @@ -780,13 +780,13 @@ Do not clear input prompts when the prefix argument is given." (defun* ein:notebook-save-notebook-workaround (nb-retry &rest args &key status + response-status &allow-other-keys) - (declare (special url-http-response-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. - (unless (eq url-http-response-status 204) + (unless (eq response-status 204) (let ((notebook (car nb-retry)) (retry (cdr nb-retry))) (with-current-buffer (ein:notebook-buffer notebook) @@ -797,7 +797,7 @@ Do not clear input prompts when the prefix argument is given." (ein:notebook-save-notebook-error notebook :status status) (ein:log 'info "Status code (=%s) is not 204 and retry exceeds limit (=%s)." - url-http-response-status ein:notebook-save-retry-max)))))) + response-status ein:notebook-save-retry-max)))))) (defun ein:notebook-save-notebook-success (notebook &rest ignore) (ein:log 'info "Notebook is saved.") diff --git a/ein-notebooklist.el b/ein-notebooklist.el index ef6e2a9..d058399 100644 --- a/ein-notebooklist.el +++ b/ein-notebooklist.el @@ -80,6 +80,7 @@ (ein:query-ajax (ein:notebooklist-url url-or-port) :cache nil + :data-type #'ein:json-read :success (cons success url-or-port) :timeout 5000)) (ein:notebooklist-get-buffer url-or-port)) @@ -87,19 +88,19 @@ (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))) - (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." @@ -125,12 +126,15 @@ (unless (setq url-or-port (ein:$notebooklist-url-or-port ein:notebooklist))) (ein:query-ajax (ein:notebooklist-new-url url-or-port) + :data-type (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 &rest ignore) - (let ((notebook-id - (ein:notebooklist-get-data-in-body-tag "data-notebook-id"))) +(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 diff --git a/ein-query.el b/ein-query.el index c2ed9c0..e86bec6 100644 --- a/ein-query.el +++ b/ein-query.el @@ -47,6 +47,7 @@ (cache t) (type "GET") (data nil) + (data-type nil) (headers nil) (success nil) (error nil) @@ -57,6 +58,7 @@ :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' +:DATA-TYPE (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 @@ -70,22 +72,23 @@ cdr is its first ARGUMENT. It is analogous of `$.proxy'. Call signature is like this: \(FUNCTION ARGUMENT [other callback specific arguments]) -The second note is that the callback FUNCTION must be defined +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. -Finally, note that callback FUNCTION is executed on the process -buffer, meaning that response data is on the current buffer when -the FUNCTION is called. There is no `:data' argument for -FUNCTION so it must be fetched from the buffer. - * :ERROR callback :SYMBOL-STATUS (`error'/`timeout') : analogous of `textStatus' :STATUS (list) : see `url-retrieve' +:RESPONSE-STATUS : = `url-http-response-status' -The :SUCCESS callback also takes the :STATUS argument. +* :SUCCESS callback + +This callback takes :DATA (object), which is a data object parsed +by :DATA-TYPE. If :DATA-TYPE is not specified, this is nil. +The :SUCCESS callback also takes the :STATUS and :RESPONSE-STATUS +argument. * :STATUS-CODE callback @@ -113,34 +116,38 @@ is not guaranteed to be the process buffer. (defun* ein:query-ajax-callback (status &key (headers nil) + (data-type nil) (success nil) (error nil) (timeout nil) (status-code nil) &allow-other-keys) (declare (special url-http-response-status)) - (let ((buffer (current-buffer)) - (status-code-callback - (cdr (assq url-http-response-status status-code)))) - (unwind-protect - (progn - (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:log 'debug "Executing success/error callback.") - (apply #'ein:safe-funcall-packed - (if (plist-get status :error) - (list error :symbol-status 'error :status status) - (list success :status 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:log 'debug "Executing status-code callback.") - (ein:safe-funcall-packed status-code-callback)) - (ein:with-live-buffer buffer - (ein:query-ajax-cancel-timer)) - (kill-buffer buffer)))) + (ein:query-ajax-cancel-timer) + (let* ((buffer (current-buffer)) ; `data-type' 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 data-type (not status-error)) + (unwind-protect + (funcall data-type) + (kill-buffer buffer))))) + + (ein:log 'debug "Executing success/error callback.") + (apply #'ein:safe-funcall-packed + (if (plist-get status :error) + (list error :symbol-status 'error :status status :data data) + (list success :status status :data data))) + + (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) From f6bcb438e8a7e1f7277cd00385b2531af530bf02 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 20:23:22 +0200 Subject: [PATCH 22/30] Rename s/data-type/parser/g --- ein-notebooklist.el | 6 +++--- ein-query.el | 20 +++++++++++++------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/ein-notebooklist.el b/ein-notebooklist.el index d058399..e201d73 100644 --- a/ein-notebooklist.el +++ b/ein-notebooklist.el @@ -80,7 +80,7 @@ (ein:query-ajax (ein:notebooklist-url url-or-port) :cache nil - :data-type #'ein:json-read + :parser #'ein:json-read :success (cons success url-or-port) :timeout 5000)) (ein:notebooklist-get-buffer url-or-port)) @@ -126,8 +126,8 @@ (unless (setq url-or-port (ein:$notebooklist-url-or-port ein:notebooklist))) (ein:query-ajax (ein:notebooklist-new-url url-or-port) - :data-type (lambda () - (ein:notebooklist-get-data-in-body-tag "data-notebook-id")) + :parser (lambda () + (ein:notebooklist-get-data-in-body-tag "data-notebook-id")) :success (cons #'ein:notebooklist-new-notebook-callback (current-buffer)) :timeout 5000)) diff --git a/ein-query.el b/ein-query.el index e86bec6..5d1e936 100644 --- a/ein-query.el +++ b/ein-query.el @@ -47,7 +47,7 @@ (cache t) (type "GET") (data nil) - (data-type nil) + (parser nil) (headers nil) (success nil) (error nil) @@ -58,7 +58,7 @@ :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' -:DATA-TYPE (symbol) : a function that reads current buffer and return 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 @@ -86,7 +86,7 @@ arguments to be passed, depending on situation. * :SUCCESS callback This callback takes :DATA (object), which is a data object parsed -by :DATA-TYPE. If :DATA-TYPE is not specified, this is nil. +by :PARSER. If :PARSER is not specified, this is nil. The :SUCCESS callback also takes the :STATUS and :RESPONSE-STATUS argument. @@ -96,6 +96,12 @@ 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 @@ -116,7 +122,7 @@ is not guaranteed to be the process buffer. (defun* ein:query-ajax-callback (status &key (headers nil) - (data-type nil) + (parser nil) (success nil) (error nil) (timeout nil) @@ -130,13 +136,13 @@ is not guaranteed to be the process buffer. (ein:log 'debug "(buffer-string) =\n%s" (buffer-string)) (ein:query-ajax-cancel-timer) - (let* ((buffer (current-buffer)) ; `data-type' could change buffer... + (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 data-type (not status-error)) + (data (if (and parser (not status-error)) (unwind-protect - (funcall data-type) + (funcall parser) (kill-buffer buffer))))) (ein:log 'debug "Executing success/error callback.") From 95434c845d1f6495e1df39a40ff336a41ff56647 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 20:41:21 +0200 Subject: [PATCH 23/30] Use ein:query-ajax in ein:notebook-request-open --- ein-notebook.el | 14 +++++++------- ein-query.el | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ein-notebook.el b/ein-notebook.el index fd3c295..dc3f3ea 100644 --- a/ein-notebook.el +++ b/ein-notebook.el @@ -221,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)) diff --git a/ein-query.el b/ein-query.el index 5d1e936..489fc04 100644 --- a/ein-query.el +++ b/ein-query.el @@ -144,6 +144,7 @@ is killed immediately after the execution of this function. (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 From 053962a5bf1c71529ae4b5a4057c28523389501f Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 20:49:31 +0200 Subject: [PATCH 24/30] Fix eintest:notebook-from-json --- tests/test-ein-notebook.el | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/test-ein-notebook.el b/tests/test-ein-notebook.el index 2db4740..c6c2dcd 100644 --- a/tests/test-ein-notebook.el +++ b/tests/test-ein-notebook.el @@ -46,12 +46,11 @@ (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)) + (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) From fffeeb2d3bbe3ea5a290fa13fb741f6a1f67cb7f Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 20:51:18 +0200 Subject: [PATCH 25/30] Clean up eintest:notebook-from-json --- tests/test-ein-notebook.el | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/tests/test-ein-notebook.el b/tests/test-ein-notebook.el index c6c2dcd..a9d314d 100644 --- a/tests/test-ein-notebook.el +++ b/tests/test-ein-notebook.el @@ -44,18 +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) - (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))))) + (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")) From 58fbfc3f0e8bc325ab1b29c0f69e49aa318bd9ad Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 21:08:48 +0200 Subject: [PATCH 26/30] Use ein:query-ajax in ein-kernel.el --- ein-kernel.el | 83 ++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 44 deletions(-) diff --git a/ein-kernel.el b/ein-kernel.el index 4eae032..94b85fa 100644 --- a/ein-kernel.el +++ b/ein-kernel.el @@ -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. From 27d924b0202a771d07f3884379efbcf379abbed5 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 21:25:20 +0200 Subject: [PATCH 27/30] Fix test-ein-kernel.el --- tests/test-ein-kernel.el | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/tests/test-ein-kernel.el b/tests/test-ein-kernel.el index e4dfe23..ef2c770 100644 --- a/tests/test-ein-kernel.el +++ b/tests/test-ein-kernel.el @@ -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)) From b9e056d8f70c53638f9d564678e3cce94383912c Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 22:37:26 +0200 Subject: [PATCH 28/30] Fix eintest:get-untitled0-or-create --- tests/func-test.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/func-test.el b/tests/func-test.el index 2ba1209..0991173 100644 --- a/tests/func-test.el +++ b/tests/func-test.el @@ -39,12 +39,12 @@ 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")))) (ert-deftest eintest:get-untitled0-or-create () From b37dbaeeeb374c84b8fbfee4e3b1e0fc47900eba Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 22:39:39 +0200 Subject: [PATCH 29/30] Add eintest:delete-untitled0 --- tests/func-test.el | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/func-test.el b/tests/func-test.el index 0991173..ff197c9 100644 --- a/tests/func-test.el +++ b/tests/func-test.el @@ -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. @@ -47,6 +48,19 @@ Make MAX-COUNT larger \(default 50) to wait longer before timeout." (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) From 878c74d3e1a6aace4b408c51505af638e768f064 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 26 May 2012 22:55:23 +0200 Subject: [PATCH 30/30] Fix: response-status was not passed to ajax callbacks --- ein-query.el | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ein-query.el b/ein-query.el index 489fc04..52a38dc 100644 --- a/ein-query.el +++ b/ein-query.el @@ -148,9 +148,11 @@ is killed immediately after the execution of this function. (ein:log 'debug "Executing success/error callback.") (apply #'ein:safe-funcall-packed - (if (plist-get status :error) - (list error :symbol-status 'error :status status :data data) - (list success :status status :data data))) + (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