From 5bdee427d257d906223d71a7c2917f5905f82b7e Mon Sep 17 00:00:00 2001 From: Rob DeLine Date: Wed, 31 Jul 2019 14:51:17 -0700 Subject: [PATCH] move LabCell back into this project --- package-lock.json | 6 +- package.json | 2 +- src/main/execution-logger.ts | 2 +- src/model/labcell.ts | 109 ++++++++++++++++++++++++++++++++++ src/overlay/cell-listener.ts | 2 +- src/overlay/element-finder.ts | 3 +- src/overlay/gather-markers.ts | 5 +- 7 files changed, 120 insertions(+), 9 deletions(-) create mode 100644 src/model/labcell.ts diff --git a/package-lock.json b/package-lock.json index 1bda249..237b14a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -283,9 +283,9 @@ } }, "@msrvida/python-program-analysis": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@msrvida/python-program-analysis/-/python-program-analysis-0.1.0.tgz", - "integrity": "sha512-o+cjjuMY2HKW1ncvW445ByVXx8jShwmNK1mURUX68D8+mCzYCgwVXARH7BciOTBiqa9sFmqEgt896H+OEcwd7A==", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@msrvida/python-program-analysis/-/python-program-analysis-0.1.4.tgz", + "integrity": "sha512-bJkrzGv04i260RtHPOtPTKcRzO9q5QQs1r3jyHnJ238LC2NRSNGYkfWIlaH3ji/Ta1FKjqqoOiYSpugKzqCeHg==", "requires": { "@jupyterlab/cells": "^0.19.1", "@jupyterlab/coreutils": "^2.2.1", diff --git a/package.json b/package.json index b909fb5..c27e1c8 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "@jupyterlab/notebook": "^0.19.1", "@jupyterlab/outputarea": "^0.19.1", "@jupyterlab/rendermime": "^0.19.1", - "@msrvida/python-program-analysis": "0.1.0", + "@msrvida/python-program-analysis": "^0.1.4", "@phosphor/widgets": "^1.6.0", "diff-match-patch": "^1.0.1", "jquery": "^3.3.1" diff --git a/src/main/execution-logger.ts b/src/main/execution-logger.ts index 3d5cb80..f945a84 100644 --- a/src/main/execution-logger.ts +++ b/src/main/execution-logger.ts @@ -4,7 +4,7 @@ import { GatherModelEvent, GatherEventData, } from '../model'; -import { LabCell } from '@msrvida/python-program-analysis'; +import { LabCell } from '../model/labcell'; export class ExecutionLogger implements IGatherObserver { constructor(gatherModel: GatherModel) { diff --git a/src/model/labcell.ts b/src/model/labcell.ts new file mode 100644 index 0000000..d5a9787 --- /dev/null +++ b/src/model/labcell.ts @@ -0,0 +1,109 @@ +import {AbstractCell} from '@msrvida/python-program-analysis'; +import { ICodeCellModel, CodeCellModel } from '@jupyterlab/cells'; +import { UUID } from '@phosphor/coreutils'; +import { IOutputModel } from '@jupyterlab/rendermime'; +import { nbformat } from '@jupyterlab/coreutils'; + + +/** + * Wrapper around a code cell model created by Jupyter Lab. Provides a consistent interface to + * lab data to other cells that have been loaded from a log. + */ +export class LabCell extends AbstractCell { + constructor(model: ICodeCellModel) { + super(); + this._model = model; + /* + * Force the initialization of a persistent ID to make sure it's set before someone tries to clone the cell. + */ + this.persistentId; + } + + get model(): ICodeCellModel { + return this._model; + } + + get id(): string { + return this._model.id; + } + + get persistentId(): string { + if (!this._model.metadata.has('persistent_id')) { + this._model.metadata.set('persistent_id', UUID.uuid4()); + } + return this._model.metadata.get('persistent_id') as string; + } + + get executionEventId(): string { + return this._model.metadata.get('execution_event_id') as string; + } + + set executionEventId(id: string) { + this._model.metadata.set('execution_event_id', id); + } + + get text(): string { + return this._model.value.text; + } + + set text(text: string) { + this._model.value.text = text; + } + + get lastExecutedText(): string { + return this._model.metadata.get('last_executed_text') as string; + } + + set lastExecutedText(text: string) { + this._model.metadata.set('last_executed_text', text); + } + + get executionCount(): number { + return this._model.executionCount; + } + + set executionCount(count: number) { + this._model.executionCount = count; + } + + get isCode(): boolean { + return this._model.type == 'code'; + } + + get hasError(): boolean { + return this.output.some(o => o.type === 'error'); + } + + get output(): IOutputModel[] { + let outputs = []; + if (this._model.outputs) { + for (let i = 0; i < this._model.outputs.length; i++) { + outputs.push(this._model.outputs.get(i)); + } + return outputs; + } + } + + get outputs(): nbformat.IOutput[] { + return this.output.map(output => output.toJSON()); + } + + get gathered(): boolean { + return this._model.metadata.get('gathered') as boolean; + } + + deepCopy(): LabCell { + return new LabCell( + new CodeCellModel({ id: this.id, cell: this.model.toJSON() }) + ); + } + + serialize(): any { + return this._model.toJSON(); + } + + is_cell: boolean = true; + is_outputter_cell: boolean = true; + private _model: ICodeCellModel; + } + \ No newline at end of file diff --git a/src/overlay/cell-listener.ts b/src/overlay/cell-listener.ts index 42ab102..eea4fa0 100644 --- a/src/overlay/cell-listener.ts +++ b/src/overlay/cell-listener.ts @@ -2,7 +2,7 @@ import { CodeCellModel, ICellModel, ICodeCellModel } from '@jupyterlab/cells'; import { NotebookPanel } from '@jupyterlab/notebook'; import { IObservableList } from '@jupyterlab/observables'; import { GatherModel } from '../model'; -import { LabCell } from '@msrvida/python-program-analysis'; +import { LabCell } from '../model/labcell'; import { UUID } from '@phosphor/coreutils'; /** diff --git a/src/overlay/element-finder.ts b/src/overlay/element-finder.ts index 3f1da2b..014ca80 100644 --- a/src/overlay/element-finder.ts +++ b/src/overlay/element-finder.ts @@ -3,6 +3,7 @@ import { Cell, isCodeCellModel } from '@jupyterlab/cells'; import { CodeMirrorEditor } from '@jupyterlab/codemirror'; import { NotebookPanel } from '@jupyterlab/notebook'; import CodeMirror from 'codemirror'; +import { LabCell } from '../model/labcell'; /** * Finds the HTML elements in a notebook corresponding to a cell. Useful for looking up HTML @@ -21,7 +22,7 @@ export class NotebookElementFinder { getCellWidget(cell: py.Cell): Cell | null { for (let cellWidget of this._notebook.content.widgets) { if (isCodeCellModel(cellWidget.model)) { - let labCell = new py.LabCell(cellWidget.model); + let labCell = new LabCell(cellWidget.model); if (labCell.executionEventId == cell.executionEventId) { return cellWidget; } diff --git a/src/overlay/gather-markers.ts b/src/overlay/gather-markers.ts index 9b3023e..dc280ea 100644 --- a/src/overlay/gather-markers.ts +++ b/src/overlay/gather-markers.ts @@ -23,6 +23,7 @@ import { Widget, PanelLayout } from '@phosphor/widgets'; * preferred user interface toolkit. */ import * as $ from 'jquery'; +import { LabCell } from '../model/labcell'; /** * Class for a highlighted, clickable output. @@ -385,7 +386,7 @@ export class MarkerManager implements IGatherObserver { let editor = this._elementFinder.getEditor(loggedCell); if (liveCellWidget && editor) { - let liveCell = new py.LabCell(liveCellWidget.model as ICodeCellModel); + let liveCell = new LabCell(liveCellWidget.model as ICodeCellModel); let numLines = 0; // Batch the highlight operations for each cell to spend less time updating cell height. editor.operation(() => { @@ -428,7 +429,7 @@ export class MarkerManager implements IGatherObserver { private _updateDependenceHighlightsForCell(cell: py.Cell) { let editor = this._elementFinder.getEditor(cell); let liveCellWidget = this._elementFinder.getCellWidget(cell); - let liveCell = new py.LabCell(liveCellWidget.model as ICodeCellModel); + let liveCell = new LabCell(liveCellWidget.model as ICodeCellModel); this._dependencyLineMarkers .filter(marker => marker.editor == editor) .forEach(marker => {