Pārlūkot izejas kodu

Merge pull request #32 from blink1073/get-state

Clean up notebook save/load
Steven Silvester 9 gadi atpakaļ
vecāks
revīzija
45e5bd90d2

+ 8 - 9
example/src/index.ts

@@ -2,7 +2,7 @@
 
 import {
   NotebookModel, NotebookWidget,
-  NBData, populateNotebookModel, saveNotebook
+  NotebookContent, populateNotebookModel, getNotebookContent
 } from 'jupyter-js-notebook';
 
 import {
@@ -56,13 +56,8 @@ function main(): void {
 
   let contents = new ContentsManager(SERVER_URL);
   contents.get(NOTEBOOK, {}).then(data => {
-    let nbdata = {
-      content: data.content,
-      name: data.name,
-      path: data.path
-    }
     let nbModel = new NotebookModel();
-    populateNotebookModel(nbModel, nbdata);
+    populateNotebookModel(nbModel, data.content as NotebookContent);
     let nbWidget = new NotebookWidget(nbModel);
     keymap.add(bindings(nbModel));
     nbWidget.attach(document.body);
@@ -70,11 +65,15 @@ function main(): void {
     // start session
     startNewSession({
       notebookPath: NOTEBOOK,
-      kernelName: nbdata.content.metadata.kernelspec.name,
+      kernelName: data.content.metadata.kernelspec.name,
       baseUrl: SERVER_URL
     }).then(session => {
       nbModel.session = session;
-      saveNotebook(nbModel, contents);
+      let content = getNotebookContent(nbModel);
+      contents.save(NOTEBOOK, {
+        type: 'notebook',
+        content
+      });
     });
   });
 }

+ 37 - 5
src/notebook/notebook/model.ts

@@ -41,6 +41,10 @@ import {
   StreamName
 } from '../output-area';
 
+import {
+  NotebookMetadata
+} from './nbformat';
+
 import {
   messageToModel
 } from './serialize';
@@ -167,6 +171,11 @@ interface INotebookModel {
    * Run the selected cell, taking the appropriate action.
    */
   runSelectedCell(): void;
+
+  /**
+   * The metadata associated with the notebook.
+   */
+  metadata: NotebookMetadata;
 }
 
 
@@ -203,7 +212,7 @@ class NotebookModel implements INotebookModel {
   /**
    * Get the default mimetype for cells new code cells.
    */
-  get defaultMimetype() {
+  get defaultMimetype(): string {
     return NotebookModelPrivate.defaultMimetype.get(this);
   }
 
@@ -217,7 +226,7 @@ class NotebookModel implements INotebookModel {
   /**
    * Get the mode of the notebook.
    */
-  get mode() {
+  get mode(): NotebookMode {
     return NotebookModelPrivate.modeProperty.get(this);
   }
 
@@ -231,7 +240,7 @@ class NotebookModel implements INotebookModel {
   /**
    * Get the session for the notebook.
    */
-  get session() {
+  get session(): INotebookSession {
     return NotebookModelPrivate.sessionProperty.get(this);
   }
 
@@ -242,10 +251,24 @@ class NotebookModel implements INotebookModel {
     NotebookModelPrivate.sessionProperty.set(this, value);
   }
 
+  /**
+   * Get the metadata for the notebook.
+   */
+  get metadata(): NotebookMetadata {
+    return NotebookModelPrivate.metadataProperty.get(this);
+  }
+
+  /**
+   * Set the metadata for the notebook.
+   */
+  set metadata(value: NotebookMetadata) {
+    NotebookModelPrivate.metadataProperty.set(this, value);
+  }
+
   /**
    * Get the selected cell index.
    */
-  get selectedCellIndex() {
+  get selectedCellIndex(): number {
     return NotebookModelPrivate.selectedCellIndexProperty.get(this);
   }
 
@@ -420,7 +443,7 @@ namespace NotebookModelPrivate {
     notify: stateChangedSignal,
   });
 
-  /**
+ /**
   * A property descriptor which holds the session of the notebook.
   */
   export
@@ -429,6 +452,15 @@ namespace NotebookModelPrivate {
     notify: stateChangedSignal,
   });
 
+ /**
+  * A property descriptor which holds the metadata of the notebook.
+  */
+  export
+  const metadataProperty = new Property<NotebookModel, NotebookMetadata>({
+    name: 'metadata',
+    notify: stateChangedSignal,
+  });
+
   /**
   * A property descriptor for the selected cell index.
   */

+ 62 - 64
src/notebook/notebook/nbformat.ts

@@ -1,8 +1,9 @@
 // Notebook format interfaces
 // https://nbformat.readthedocs.org/en/latest/format_description.html
+// https://github.com/jupyter/nbformat/blob/master/nbformat/v4/nbformat.v4.schema.json
 
 import {
-    MimeBundle
+  MimeBundle
 } from '../output-area';
 
 
@@ -25,37 +26,37 @@ const MINOR_VERSION = 0;
 
 export
 interface BaseOutput {
-    output_type: string;
+  output_type: string;
 }
 
 export
 interface ExecuteResult extends BaseOutput {
-    output_type: string; // "execute_result"
-    execution_count: number;
-    data:  MimeBundle;
-    metadata: {};
+  output_type: string; // "execute_result"
+  execution_count: number;
+  data:  MimeBundle;
+  metadata: {};
 }
 
 export
 interface DisplayData extends BaseOutput {
-    output_type: string; // "display_data"
-    data: MimeBundle;
-    metadata: {};
+  output_type: string; // "display_data"
+  data: MimeBundle;
+  metadata: {};
 }
 
 export
 interface Stream extends BaseOutput {
-    output_type: string; // "stream"
-    name: string;
-    text: multilineString;
+  output_type: string; // "stream"
+  name: string;
+  text: multilineString;
 }
 
 export
 interface JupyterError extends BaseOutput {
-    output_type: string; // "error"
-    ename: string;
-    evalue: string;
-    traceback: string[];
+  output_type: string; // "error"
+  ename: string;
+  evalue: string;
+  traceback: string[];
 }
 
 export
@@ -63,22 +64,22 @@ type Output = ExecuteResult | DisplayData | Stream | JupyterError;
 
 export
 function isExecuteResult(d: BaseOutput): d is ExecuteResult {
-    return d.output_type === "execute_result";
+  return d.output_type === "execute_result";
 }
 
 export
 function isDisplayData(d: BaseOutput): d is DisplayData {
-    return d.output_type === "display_data";
+  return d.output_type === "display_data";
 }
 
 export
 function isStream(d: BaseOutput): d is Stream {
-    return d.output_type === "stream";
+  return d.output_type === "stream";
 }
 
 export
 function isJupyterError(d: BaseOutput): d is JupyterError {
-    return d.output_type === "error";
+  return d.output_type === "error";
 }
 
 export
@@ -86,74 +87,71 @@ type Cell = BaseCell | RawCell | MarkdownCell | CodeCell;
 
 export
 interface BaseCell {
-    cell_type: string;
-    source: multilineString;
-    metadata: {
-        name?: string;
-        tags?: string[];
-    }
+  cell_type: string;
+  source: multilineString;
+  metadata: {
+    name?: string;
+    tags?: string[];
+  }
 }
 
 export
 interface RawCell extends BaseCell {
-    cell_type: string; /*"raw"*/
-    metadata: {
-        format?: string;
-    }
+  cell_type: string; /*"raw"*/
+  metadata: {
+    format?: string;
+  }
 }
 
 export
 interface MarkdownCell extends BaseCell {
-    cell_type: string; /*"markdown"*/
+  cell_type: string; /*"markdown"*/
 }
 
 export
 interface CodeCell extends BaseCell {
-    cell_type: string; /*"code"*/
-    metadata: {
-        name?: string;
-        tags?: string[];
-        collapsed?: boolean;
-        scrolled?: boolean | string;
-    }
-    outputs: Output[];
-    execution_count: number;
+  cell_type: string; /*"code"*/
+  metadata: {
+    name?: string;
+    tags?: string[];
+    collapsed?: boolean;
+    scrolled?: boolean | string;
+  }
+  outputs: Output[];
+  execution_count: number;
 }
 
 export
 function isMarkdownCell(d: BaseCell): d is MarkdownCell {
-    return d.cell_type === "markdown";
+  return d.cell_type === "markdown";
 }
 
 export
 function isCodeCell(d: BaseCell): d is CodeCell {
-    return d.cell_type === "code";
+  return d.cell_type === "code";
 }
 
 export
-interface Notebook {
-    metadata: {
-        kernelspec: {
-            name: string;
-            display_name: string;
-        };
-        language_info: {
-            name: string;
-            codemirror_mode?: string | {};
-            file_extension?: string;
-            mimetype?: string;
-            pygments_lexer?: string
-        };
-        orig_nbformat?: number;
-    }
-    nbformat_minor: number;
-    nbformat: number;
-    cells: Cell[];
+interface NotebookMetadata {
+  kernelspec: {
+    name: string;
+    display_name: string;
+  };
+  language_info: {
+    name: string;
+    codemirror_mode?: string | {};
+    file_extension?: string;
+    mimetype?: string;
+    pygments_lexer?: string
+  };
+  orig_nbformat?: number;
 }
 
+
 export
-interface NBData {
-    content: Notebook;
-    name: string;
-    path: string;
+interface NotebookContent {
+  metadata: NotebookMetadata
+  nbformat_minor: number;
+  nbformat: number;
+  cells: Cell[];
 }

+ 16 - 26
src/notebook/notebook/serialize.ts

@@ -3,7 +3,7 @@
 'use strict';
 
 import {
-  IContentsModel, IKernelMessage, IContentsManager
+  IKernelMessage
 } from 'jupyter-js-services';
 
 import {
@@ -31,11 +31,11 @@ import {
 } from '../output-area';
 
 import {
-  NBData, MarkdownCell, CodeCell,
+  MarkdownCell, CodeCell,
   isMarkdownCell, isCodeCell,
   DisplayData, isDisplayData,
   ExecuteResult, isExecuteResult,
-  Stream, isStream, Cell,
+  Stream, isStream, Cell, NotebookContent,
   JupyterError, isJupyterError, Output, BaseOutput,
   MAJOR_VERSION, MINOR_VERSION
 } from './nbformat';
@@ -45,11 +45,11 @@ import {
  * Build a complete notebook model from the notebook data.
  */
 export
-function populateNotebookModel(nb: INotebookModel, data: NBData): void {
+function populateNotebookModel(nb: INotebookModel, data: NotebookContent): void {
   nb.cells.clear();
 
   // iterate through the cell data, creating cell models
-  data.content.cells.forEach((c) => {
+  data.cells.forEach((c) => {
     let input = new InputAreaModel();
     input.textEditor = new EditorModel({ lineNumbers: false });
     input.textEditor.text = c.source;
@@ -75,8 +75,10 @@ function populateNotebookModel(nb: INotebookModel, data: NBData): void {
   if (nb.cells.length) {
     nb.selectedCellIndex = 0;
   }
+  nb.metadata = data.metadata;
 }
 
+
 /**
  * Build an output model from output message data.
  */
@@ -134,35 +136,23 @@ function messageToModel(msg: IKernelMessage) {
 
 
 /**
- * Save the current notebook state to disk.
+ * Get the current notebook content.
  */
 export
-function saveNotebook(nb: NotebookModel, contents: IContentsManager): Promise<IContentsModel> {
-  if (!nb.session) {
-    Promise.reject('No notebook session');
-  }
-  let cells = getNotebookData(nb);
-  return nb.session.kernel.kernelInfo().then(info => {
-    let name = nb.session.kernel.name;
-    // TODO: Get the display name.
-    let metadata = { kernelspec: { name, display_name: name },
-                     language_info: info.language_info
-                   };
-    let notebook = { cells, metadata, nbformat: MAJOR_VERSION, 
-                     nbformat_minor: MINOR_VERSION };
-    return contents.save(nb.session.notebookPath, {
-      type: 'notebook',
-      content: notebook
-    });
-  });
+function getNotebookContent(nb: NotebookModel): NotebookContent {
+  return {
+    cells: getNotebookCells(nb),
+    metadata: nb.metadata, 
+    nbformat: MAJOR_VERSION, 
+    nbformat_minor: MINOR_VERSION 
+  };
 }
 
 
 /**
  * Get the cell data for a given notebook.
  */
-export
-function getNotebookData(nb: NotebookModel): Cell[] {
+function getNotebookCells(nb: NotebookModel): Cell[] {
   let cells: Cell[] = [];
   for (let i = 0; i < nb.cells.length; i++) {
     let cell = nb.cells.get(i);