Browse Source

Deleted Cells Metadata (#5037)

* added cellId field to EventRequest, had cells pass their Id on execution

* added CellIDs to metadata now passed when cell executed

* removed previous extraneous changes to the default kernel

* removed extraneous content details from requestExecute

* removed Untitled.ipynb

* added deleted Cells to Notebook model,  returns which cells have been deleted since last execution as part of metadata

* extraneous changes

* made metadata optional for kernel

* ensured test status -- passing

* initial tests for deletecell functionality

* removed extraneous test

* Added tests, rebased code

* integrity update

* always integrity
Richa Gadgil 6 years ago
parent
commit
45a105e53d

+ 1 - 1
package.json

@@ -23,7 +23,7 @@
     "clean:src": "jlpm run clean",
     "clean:test": "lerna run clean --scope \"@jupyterlab/test-*\"",
     "clean:utils": "cd buildutils && jlpm run clean",
-    "precommit": "lint-staged",
+    "precommit": "lint-staged && jlpm run integrity",
     "coverage": "lerna run coverage --scope \"@jupyterlab/test-*\" --stream --concurrency 1",
     "create:package": "node buildutils/lib/create-package.js",
     "create:test": "node buildutils/lib/create-test-package.js",

+ 6 - 5
packages/cells/src/widget.ts

@@ -30,7 +30,7 @@ import {
 
 import { KernelMessage } from '@jupyterlab/services';
 
-import { JSONValue, PromiseDelegate } from '@phosphor/coreutils';
+import { JSONValue, PromiseDelegate, JSONObject } from '@phosphor/coreutils';
 
 import { Message } from '@phosphor/messaging';
 
@@ -782,7 +782,8 @@ export namespace CodeCell {
    */
   export function execute(
     cell: CodeCell,
-    session: IClientSession
+    session: IClientSession,
+    metadata?: JSONObject
   ): Promise<KernelMessage.IExecuteReplyMsg> {
     let model = cell.model;
     let code = model.value.text;
@@ -792,14 +793,14 @@ export namespace CodeCell {
       return Promise.resolve(void 0);
     }
 
+    let cellId = { cellId: model.id };
+    metadata = { ...metadata, ...cellId };
     model.executionCount = null;
     cell.outputHidden = false;
     cell.setPrompt('*');
     model.trusted = true;
 
-    return OutputArea.execute(code, cell.outputArea, session, {
-      cellId: model.id
-    })
+    return OutputArea.execute(code, cell.outputArea, session, metadata)
       .then(msg => {
         model.executionCount = msg.content.execution_count;
         return msg;

+ 8 - 1
packages/notebook/src/actions.tsx

@@ -1436,8 +1436,14 @@ namespace Private {
         break;
       case 'code':
         if (session) {
-          return CodeCell.execute(cell as CodeCell, session)
+          return CodeCell.execute(cell as CodeCell, session, {
+            deletedCells: notebook.model.deletedCells
+          })
             .then(reply => {
+              notebook.model.deletedCells.splice(
+                0,
+                notebook.model.deletedCells.length
+              );
               if (cell.isDisposed) {
                 return false;
               }
@@ -1636,6 +1642,7 @@ namespace Private {
 
       if (notebook.isSelectedOrActive(child) && deletable) {
         toDelete.push(index);
+        notebook.model.deletedCells.push(child.model.id);
       }
     });
 

+ 12 - 1
packages/notebook/src/model.ts

@@ -55,6 +55,10 @@ export interface INotebookModel extends DocumentRegistry.IModel {
    * The metadata associated with the notebook.
    */
   readonly metadata: IObservableJSON;
+  /**
+   * The array of deleted cells since the notebook was last run.
+   */
+  readonly deletedCells: string[];
 }
 
 /**
@@ -83,6 +87,7 @@ export class NotebookModel extends DocumentModel implements INotebookModel {
     }
     this._ensureMetadata();
     metadata.changed.connect(this.triggerContentChange, this);
+    this._deletedCells = [];
   }
 
   /**
@@ -125,7 +130,12 @@ export class NotebookModel extends DocumentModel implements INotebookModel {
     let spec = this.metadata.get('kernelspec') as nbformat.IKernelspecMetadata;
     return spec ? spec.name : '';
   }
-
+  /**
+   * The default kernel name of the document.
+   */
+  get deletedCells(): string[] {
+    return this._deletedCells;
+  }
   /**
    * The default kernel language of the document.
    */
@@ -308,6 +318,7 @@ export class NotebookModel extends DocumentModel implements INotebookModel {
   private _cells: CellList;
   private _nbformat = nbformat.MAJOR_VERSION;
   private _nbformatMinor = nbformat.MINOR_VERSION;
+  private _deletedCells: string[];
 }
 
 /**

+ 17 - 0
tests/test-notebook/src/actions.spec.ts

@@ -249,6 +249,14 @@ describe('@jupyterlab/notebook', () => {
         expect(widget.widgets.length).to.equal(count - 2);
       });
 
+      it('should increment deletedCells model when cells deleted', () => {
+        let next = widget.widgets[1];
+        widget.select(next);
+        let count = widget.model.deletedCells.length;
+        NotebookActions.deleteCells(widget);
+        expect(widget.model.deletedCells.length).to.equal(count + 2);
+      });
+
       it('should be a no-op if there is no model', () => {
         widget.model = null;
         NotebookActions.deleteCells(widget);
@@ -472,6 +480,15 @@ describe('@jupyterlab/notebook', () => {
         expect(next.rendered).to.equal(true);
       });
 
+      it('should delete deletedCells metadata when cell run', () => {
+        let cell = widget.activeCell as CodeCell;
+        cell.model.outputs.clear();
+        return NotebookActions.run(widget, session).then(result => {
+          expect(result).to.equal(true);
+          expect(widget.model.deletedCells.length).to.equal(0);
+        });
+      });
+
       it('should be a no-op if there is no model', async () => {
         widget.model = null;
         const result = await NotebookActions.run(widget, session);