thebe-core
Version:
Typescript based core functionality for Thebe
228 lines • 8.98 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const cell_1 = tslib_1.__importDefault(require("./cell"));
const utils_1 = require("./utils");
const events_1 = require("./events");
const emitter_1 = require("./emitter");
const markdown_1 = tslib_1.__importDefault(require("./markdown"));
class ThebeNotebook {
constructor(id, config, rendermime) {
this.id = id;
this.events = new emitter_1.EventEmitter(id, config, events_1.EventSubject.notebook, this);
this.cells = [];
this.metadata = {};
this.rendermime = rendermime;
console.debug('thebe:notebook constructor', this);
}
static fromCodeBlocks(blocks, config, rendermime) {
const id = (0, utils_1.shortId)();
const notebook = new ThebeNotebook(id, config, rendermime);
notebook.cells = blocks.map((c) => {
const metadata = {};
const cell = new cell_1.default(c.id, id, c.source, config, metadata, notebook.rendermime);
console.debug(`thebe:notebook:fromCodeBlocks Initializing cell ${c.id}`);
return cell;
});
return notebook;
}
static fromIpynb(ipynb, config, rendermime) {
const notebook = new ThebeNotebook((0, utils_1.shortId)(), config, rendermime);
Object.assign(notebook.metadata, ipynb.metadata);
notebook.cells = ipynb.cells.map((c) => {
if (c.cell_type === 'code')
return cell_1.default.fromICodeCell(c, notebook.id, config, notebook.rendermime);
return markdown_1.default.fromICell(c, notebook.id, notebook.rendermime);
});
return notebook;
}
get parameters() {
const p = this.findCells('parameters');
if (!p || (p === null || p === void 0 ? void 0 : p.length) === 0)
return undefined;
if (p.length > 1)
console.warn(`Mulitple parameter cells found in notebook ${this.id}`);
return p;
}
get widgets() {
var _a;
return (_a = this.findCells('widget')) !== null && _a !== void 0 ? _a : [];
}
get last() {
if (this.cells.length === 0)
throw new Error('empty notebook');
return this.cells[this.cells.length - 1];
}
get markdown() {
return this.cells.filter((c) => c.kind === 'markdown');
}
get code() {
return this.cells.filter((c) => c.kind === 'code');
}
/**
* reset the notebook to its initial state by resetting each cell
*
* @param hideWidgets boolean
*/
reset() {
this.cells.forEach((cell) => cell.reset());
}
numCells() {
var _a, _b;
return (_b = (_a = this.cells) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
}
findCells(tag) {
const found = this.cells.filter((c) => c.tags.includes(tag));
return found.length > 0 ? found : undefined;
}
getCell(idx) {
if (!this.cells)
throw Error('Dag not initialized');
if (idx >= this.cells.length)
throw Error(`Notebook.cells index out of range: ${idx}:${this.cells.length}`);
return this.cells[idx];
}
getCellById(id) {
var _a;
const cell = (_a = this.cells) === null || _a === void 0 ? void 0 : _a.find((c) => c.id === id);
return cell;
}
lastCell() {
if (!this.cells)
throw Error('Notebook not initialized');
return this.cells[this.cells.length - 1];
}
updateParameters(newSource, interpolate = false) {
if (interpolate)
throw new Error('Not implemented yet');
if (this.parameters)
this.parameters[0].source = newSource;
}
waitForKernel(kernel) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
return kernel.then((k) => {
this.attachSession(k);
return k;
});
});
}
attachSession(session) {
var _a;
if (!session.kernel)
throw Error('ThebeNotebook - cannot connect to session, no kernel');
// note all cells in a notebook share the rendermime registry
// we only need to add the widgets factory once
this.session = session;
(_a = this.cells) === null || _a === void 0 ? void 0 : _a.forEach((cell) => (cell.session = session));
this.events.triggerStatus({
status: events_1.NotebookStatusEvent.attached,
message: 'Attached to session',
});
}
detachSession() {
var _a;
(_a = this.cells) === null || _a === void 0 ? void 0 : _a.map((cell) => (cell.session = undefined));
this.session = undefined;
this.events.triggerStatus({
status: events_1.NotebookStatusEvent.detached,
message: 'Detached from session',
});
}
clear() {
this.cells.forEach((cell) => cell.clear());
}
executeUpTo(cellId, stopOnError = false, preprocessor) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
if (!this.cells)
return [];
this.events.triggerStatus({
status: events_1.NotebookStatusEvent.executing,
message: `executeUpTo ${cellId}`,
});
const idx = this.cells.findIndex((c) => c.id === cellId);
if (idx === -1)
return [];
const cellsToExecute = this.cells.slice(0, idx + 1);
cellsToExecute.map((cell) => cell.setAsBusy());
const result = yield this.executeCells(cellsToExecute.map((c) => c.id), stopOnError, preprocessor);
// TODO intercept errors here
this.events.triggerStatus({
status: events_1.NotebookStatusEvent.idle,
message: `executeUpTo ${cellId}`,
});
return result;
});
}
executeOnly(cellId, preprocessor) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
if (!this.cells)
return null;
this.events.triggerStatus({
status: events_1.NotebookStatusEvent.executing,
message: `executeOnly ${cellId}`,
});
const result = yield this.executeCells([cellId], false, preprocessor);
this.events.triggerStatus({
status: events_1.NotebookStatusEvent.idle,
message: `executeUpTo ${cellId}`,
});
return result[0];
});
}
executeCells(cellIds, stopOnError = false, preprocessor) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
if (!this.cells)
return [];
this.events.triggerStatus({
status: events_1.NotebookStatusEvent.executing,
message: `executeCells ${cellIds.length} cells`,
});
const cells = this.cells.filter((c) => {
const found = cellIds.find((id) => id === c.id);
if (!found) {
console.warn(`Cell ${c.id} not found in notebook`);
}
return Boolean(found);
});
let result = [];
if (stopOnError) {
let skipRemaining = false;
for (const cell of cells) {
if (skipRemaining)
continue;
const cellReturn = yield cell.execute(preprocessor ? preprocessor(cell.source) : cell.source);
if (cellReturn == null || cellReturn.error)
skipRemaining = true;
result.push(cellReturn);
}
}
else {
result = yield Promise.all(cells.map((cell) => cell.execute(preprocessor ? preprocessor(cell.source) : cell.source)));
}
this.events.triggerStatus({
status: events_1.NotebookStatusEvent.idle,
message: `executeCells executed ${cellIds.length} cells`,
});
return result;
});
}
executeAll(stopOnError = false, preprocessor) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
if (!this.cells)
return [];
this.events.triggerStatus({
status: events_1.NotebookStatusEvent.executing,
message: `executeAll`,
});
this.cells.map((cell) => cell.setAsBusy());
const result = yield this.executeCells(this.cells.map((c) => c.id), stopOnError, preprocessor);
this.events.triggerStatus({
status: events_1.NotebookStatusEvent.idle,
message: `executeAll`,
});
return result;
});
}
}
exports.default = ThebeNotebook;
//# sourceMappingURL=notebook.js.map