Give ein notebooks content checkpoint functionality.

This commit is contained in:
John Miller 2016-10-19 14:43:19 -05:00
parent 7d8474e2c4
commit bb95f71f5e
2 changed files with 93 additions and 14 deletions

View file

@ -54,40 +54,40 @@ global setting. For global setting and more information, see
`ein:$content-url-or-port' `ein:$content-url-or-port'
URL or port of Jupyter server. URL or port of Jupyter server.
`ein:$content-name `ein:$content-name'
The name/filename of the content. Always equivalent to the last The name/filename of the content. Always equivalent to the last
part of the path field part of the path field
`ein:$content-path `ein:$content-path'
The full file path. It will not start with /, and it will be /-delimited. The full file path. It will not start with /, and it will be /-delimited.
`ein:$content-type `ein:$content-type'
One of three values: :directory, :file, :notebook. One of three values: :directory, :file, :notebook.
`ein:$content-writable `ein:$content-writable'
Indicates if requester has permission to modified the requested content. Indicates if requester has permission to modified the requested content.
`ein:$content-created `ein:$content-created'
`ein:$content-last-modified `ein:$content-last-modified'
`ein:$content-mimetype `ein:$content-mimetype'
Specify the mime-type of :file content, null otherwise. Specify the mime-type of :file content, null otherwise.
`ein:$content-raw-content `ein:$content-raw-content'
Contents of resource as returned by Jupyter. Depending on content-type will hold: Contents of resource as returned by Jupyter. Depending on content-type will hold:
:directory : JSON list of models for each item in the directory. :directory : JSON list of models for each item in the directory.
:file : Text of file as a string or base64 encoded string if mimetype :file : Text of file as a string or base64 encoded string if mimetype
is other than 'text/plain'. is other than 'text/plain'.
:notebook : JSON structure of the file. :notebook : JSON structure of the file.
`ein:$content-format `ein:$content-format'
Value will depend on content-type: Value will depend on content-type:
:directory : :json. :directory : :json.
:file : Either :text or :base64 :file : Either :text or :base64
:notebook : :json. :notebook : :json.
`ein:$content-checkpoints `ein:$content-checkpoints'
Names auto-saved checkpoints for content. Stored as a list Names auto-saved checkpoints for content. Stored as a list
of (<id> . <last_modified>) pairs. of (<id> . <last_modified>) pairs.
" "
@ -439,9 +439,11 @@ global setting. For global setting and more information, see
:error (apply-partially #'ein:content-query-checkpoints-error content)))) :error (apply-partially #'ein:content-query-checkpoints-error content))))
(defun* ein:content-query-checkpoints-success (content cb cbargs &key data status response &allow-other-keys) (defun* ein:content-query-checkpoints-success (content cb cbargs &key data status response &allow-other-keys)
(unless (listp (car data))
(setq data (list data)))
(setf (ein:$content-checkpoints content) data) (setf (ein:$content-checkpoints content) data)
(when cb (when cb
(apply cb cbargs))) (apply cb content cbargs)))
(defun* ein:content-query-checkpoints-error (content &key symbol-status response &allow-other-keys) (defun* ein:content-query-checkpoints-error (content &key symbol-status response &allow-other-keys)
(ein:log 'error "Content checkpoint operation failed with status %s (%s)." symbol-status response)) (ein:log 'error "Content checkpoint operation failed with status %s (%s)." symbol-status response))

View file

@ -62,6 +62,12 @@
(make-obsolete-variable 'ein:notebook-discard-output-on-save nil "0.2.0") (make-obsolete-variable 'ein:notebook-discard-output-on-save nil "0.2.0")
(defcustom ein:notebook-checkpoint-frequency 60
"Controls frequency (in seconds) at which checkpoints are
generated for the current notebook."
:type 'number
:group 'ein)
(defcustom ein:notebook-discard-output-on-save 'no (defcustom ein:notebook-discard-output-on-save 'no
"Configure if the output part of the cell should be saved or not. "Configure if the output part of the cell should be saved or not.
@ -206,6 +212,10 @@ Current buffer for these functions is set to the notebook buffer.")
`ein:$notebook-api-version' : integer `ein:$notebook-api-version' : integer
Major version of the IPython notebook server we are talking to. Major version of the IPython notebook server we are talking to.
`ein:$notebook-checkpoints'
Names auto-saved checkpoints for content. Stored as a list
of (<id> . <last_modified>) pairs.
" "
url-or-port url-or-port
notebook-id ;; In IPython-2.0 this is "[:path]/[:name].ipynb" notebook-id ;; In IPython-2.0 this is "[:path]/[:name].ipynb"
@ -223,7 +233,8 @@ Current buffer for these functions is set to the notebook buffer.")
worksheets worksheets
scratchsheets scratchsheets
api-version api-version
) checkpoint-timer
checkpoints)
(ein:deflocal ein:%notebook% nil (ein:deflocal ein:%notebook% nil
"Buffer local variable to store an instance of `ein:$notebook'.") "Buffer local variable to store an instance of `ein:$notebook'.")
@ -396,9 +407,11 @@ See `ein:notebook-open' for more information."
(cons #'ein:notebook-buffer-list notebook))) (cons #'ein:notebook-buffer-list notebook)))
(ein:notebook-put-opened-notebook notebook) (ein:notebook-put-opened-notebook notebook)
(ein:notebook--check-nbformat (ein:$content-raw-content content)) (ein:notebook--check-nbformat (ein:$content-raw-content content))
(ein:notebook-enable-checkpoints notebook)
(ein:log 'info "Notebook %s is ready" (ein:log 'info "Notebook %s is ready"
(ein:$notebook-notebook-name notebook)))) (ein:$notebook-notebook-name notebook))))
(defun ein:notebook--different-number (n1 n2) (defun ein:notebook--different-number (n1 n2)
(and (numberp n1) (numberp n2) (not (= n1 n2)))) (and (numberp n1) (numberp n2) (not (= n1 n2))))
@ -429,6 +442,34 @@ of minor mode."
;;; Initialization. ;;; Initialization.
(defun ein:notebook-enable-checkpoints (notebook)
"Enable checkpoints for notebook."
(interactive
(let* ((notebook (or (ein:get-notebook)
(completing-read
"Select notebook [URL-OR-PORT/NAME]: "
(ein:notebook-opened-buffer-names)))))
(list notebook)))
(if (stringp notebook)
(error "Fix me!")) ;; FIXME
(setf (ein:$notebook-checkpoint-timer notebook)
(run-at-time t ein:notebook-checkpoint-frequency #'ein:notebook-save-checkpoint notebook))
(ein:log 'info "Enabling checkpoints for %s with frequency %s seconds."
(ein:$notebook-notebook-name notebook)
ein:notebook-checkpoint-frequency))
(defun ein:notebook-disable-checkpoints (notebook)
"Stop automatically saving checkpoints for notebook."
(interactive
(let* ((notebook (or (ein:get-notebook)
(completing-read
"Select notebook [URL-OR-PORT/NAME]: "
(ein:notebook-opened-buffer-names)))))
(list notebook)))
(ein:log 'info "Disabling auto checkpoints for notebook %s" (ein:$notebook-notebook-name notebook))
(when (ein:$notebook-checkpoint-timer notebook)
(cancel-timer (ein:$notebook-checkpoint-timer notebook))))
(defun ein:notebook-bind-events (notebook events) (defun ein:notebook-bind-events (notebook events)
"Bind events related to PAGER to the event handler EVENTS." "Bind events related to PAGER to the event handler EVENTS."
(setf (ein:$notebook-events notebook) events) (setf (ein:$notebook-events notebook) events)
@ -525,8 +566,8 @@ notebook buffer then the user will be prompted to select an opened notebook."
"Select notebook [URL-OR-PORT/NAME]: " "Select notebook [URL-OR-PORT/NAME]: "
(ein:notebook-opened-buffer-names)))) (ein:notebook-opened-buffer-names))))
(kernel-name (completing-read (kernel-name (completing-read
"Select kernel: " "Select kernel: "
(ein:list-available-kernels (ein:$notebook-url-or-port notebook))))) (ein:list-available-kernels (ein:$notebook-url-or-port notebook)))))
(list notebook kernel-name))) (list notebook kernel-name)))
(setf (ein:$notebook-kernelspec notebook) (ein:get-kernelspec (ein:$notebook-url-or-port notebook) (setf (ein:$notebook-kernelspec notebook) (ein:get-kernelspec (ein:$notebook-url-or-port notebook)
kernel-name)) kernel-name))
@ -881,6 +922,42 @@ as usual."
(ein:kernel-kill kernel #'ein:notebook-close (list ein:%notebook%)) (ein:kernel-kill kernel #'ein:notebook-close (list ein:%notebook%))
(ein:notebook-close ein:%notebook%))))) (ein:notebook-close ein:%notebook%)))))
(defun ein:fast-content-from-notebook (notebook)
"Quickly generate a basic content structure from notebook. This
function does not generate the full json representation of the
notebook worksheets."
(make-ein:$content :name (ein:$notebook-notebook-name notebook)
:path (ein:$notebook-notebook-path notebook)
:url-or-port (ein:$notebook-url-or-port notebook)
:type "notebook"
:ipython-version (ein:$notebook-api-version notebook)))
(defun ein:notebook-save-checkpoint (notebook)
(let ((content (ein:fast-content-from-notebook notebook)))
(ein:content-create-checkpoint content
#'(lambda (content)
(ein:log 'info "Checkpoint for %s generated."
(ein:$notebook-notebook-name notebook))
(setf (ein:$notebook-checkpoints notebook)
(ein:$content-checkpoints content))))))
(defun ein:notebook-list-checkpoint-ids (notebook)
(loop for cp in (ein:$notebook-checkpoints notebook)
collecting (plist-get cp :id)))
(defun ein:notebook-restore-to-checkpoint (notebook checkpoint)
(interactive
(let* ((notebook (ein:get-notebook))
(checkpoint (completing-read
"Select checkpoint: "
(ein:notebook-list-checkpoint-ids notebook))))
(list notebook checkpoint)))
(ein:content-restore-checkpoint (ein:fast-content-from-notebook notebook)
checkpoint)
(ein:notebook-close notebook)
(ein:notebook-open (ein:$notebook-url-or-port notebook)
(ein:$notebook-notebook-path notebook)))
;;; Worksheet ;;; Worksheet