jupyterlab-ipyflow 0.0.154 → 0.0.156
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +97 -50
- package/package.json +12 -9
package/lib/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ICommandPalette } from '@jupyterlab/apputils';
|
|
2
2
|
import { CodeCell } from '@jupyterlab/cells';
|
|
3
3
|
import { INotebookTracker } from '@jupyterlab/notebook';
|
|
4
|
+
import _ from 'lodash';
|
|
4
5
|
const IPYFLOW_KERNEL_NAME = 'ipyflow';
|
|
5
6
|
const waitingClass = 'waiting-cell';
|
|
6
7
|
const readyClass = 'ready-cell';
|
|
@@ -9,7 +10,7 @@ const readyMakingInputClass = 'ready-making-input-cell';
|
|
|
9
10
|
const linkedWaitingClass = 'linked-waiting';
|
|
10
11
|
const linkedReadyMakerClass = 'linked-ready-maker';
|
|
11
12
|
// ipyflow frontend state
|
|
12
|
-
|
|
13
|
+
const dirtyCells = new Set();
|
|
13
14
|
let waitingCells = new Set();
|
|
14
15
|
let readyCells = new Set();
|
|
15
16
|
let waiterLinks = {};
|
|
@@ -22,6 +23,7 @@ let orderIdxById = {};
|
|
|
22
23
|
let cellPendingExecution = null;
|
|
23
24
|
let lastExecutionMode = null;
|
|
24
25
|
let isReactivelyExecuting = false;
|
|
26
|
+
let isAltModeExecuting = false;
|
|
25
27
|
let lastExecutionHighlights = null;
|
|
26
28
|
let executedReactiveReadyCells = new Set();
|
|
27
29
|
let newReadyCells = new Set();
|
|
@@ -41,19 +43,22 @@ const extension = {
|
|
|
41
43
|
isVisible: () => true,
|
|
42
44
|
isToggled: () => false,
|
|
43
45
|
execute: () => {
|
|
44
|
-
if (notebooks.activeCell.model.type === 'code') {
|
|
46
|
+
if (!isAltModeExecuting && notebooks.activeCell.model.type === 'code') {
|
|
47
|
+
isAltModeExecuting = true;
|
|
45
48
|
const session = notebooks.currentWidget.sessionContext;
|
|
46
49
|
if (session.isReady && notebooks.activeCell.model.type === 'code') {
|
|
47
|
-
session.session.kernel
|
|
50
|
+
session.session.kernel
|
|
51
|
+
.requestExecute({
|
|
48
52
|
code: '%flow toggle-reactivity-until-next-reset',
|
|
49
53
|
silent: true,
|
|
50
54
|
store_history: false,
|
|
51
|
-
})
|
|
55
|
+
})
|
|
56
|
+
.done.then(() => {
|
|
52
57
|
CodeCell.execute(notebooks.activeCell, session);
|
|
53
58
|
});
|
|
54
59
|
}
|
|
55
60
|
}
|
|
56
|
-
}
|
|
61
|
+
},
|
|
57
62
|
});
|
|
58
63
|
app.commands.addKeyBinding({
|
|
59
64
|
command: 'alt-mode-execute',
|
|
@@ -76,15 +81,20 @@ const extension = {
|
|
|
76
81
|
clearCellState(nbPanel.content);
|
|
77
82
|
activeCell = nbPanel.content.activeCell;
|
|
78
83
|
activeCellId = nbPanel.content.activeCell.model.id;
|
|
79
|
-
let commDisconnectHandler = ()
|
|
84
|
+
let commDisconnectHandler = function () {
|
|
85
|
+
// do nothing if not connected.
|
|
86
|
+
};
|
|
80
87
|
if (session.session.kernel.name === IPYFLOW_KERNEL_NAME) {
|
|
81
88
|
commDisconnectHandler = connectToComm(session, nbPanel.content);
|
|
82
89
|
}
|
|
83
90
|
session.kernelChanged.connect((_, args) => {
|
|
84
91
|
clearCellState(nbPanel.content);
|
|
85
92
|
commDisconnectHandler();
|
|
86
|
-
commDisconnectHandler = ()
|
|
87
|
-
|
|
93
|
+
commDisconnectHandler = function () {
|
|
94
|
+
// do nothing if not connected.
|
|
95
|
+
};
|
|
96
|
+
if (args.newValue !== null &&
|
|
97
|
+
args.newValue.name === IPYFLOW_KERNEL_NAME) {
|
|
88
98
|
commDisconnectHandler = connectToComm(session, nbPanel.content);
|
|
89
99
|
}
|
|
90
100
|
});
|
|
@@ -98,7 +108,9 @@ const extension = {
|
|
|
98
108
|
session.ready.then(() => {
|
|
99
109
|
clearCellState(nbPanel.content);
|
|
100
110
|
commDisconnectHandler();
|
|
101
|
-
commDisconnectHandler = ()
|
|
111
|
+
commDisconnectHandler = function () {
|
|
112
|
+
// do nothing if not connected.
|
|
113
|
+
};
|
|
102
114
|
if (session.session.kernel.name === IPYFLOW_KERNEL_NAME) {
|
|
103
115
|
commDisconnectHandler = connectToComm(session, nbPanel.content);
|
|
104
116
|
}
|
|
@@ -107,7 +119,7 @@ const extension = {
|
|
|
107
119
|
});
|
|
108
120
|
});
|
|
109
121
|
});
|
|
110
|
-
}
|
|
122
|
+
},
|
|
111
123
|
};
|
|
112
124
|
const getJpInputCollapser = (elem) => {
|
|
113
125
|
if (elem === null || elem === undefined) {
|
|
@@ -206,6 +218,35 @@ const addUnsafeCellInteraction = (elem, linkedElems, cellsById, collapserFun, ev
|
|
|
206
218
|
const connectToComm = (session, notebook) => {
|
|
207
219
|
const comm = session.session.kernel.createComm('ipyflow');
|
|
208
220
|
let disconnected = false;
|
|
221
|
+
const gatherCellMetadataAndContent = () => {
|
|
222
|
+
const cell_metadata_by_id = {};
|
|
223
|
+
notebook.widgets.forEach((itercell, idx) => {
|
|
224
|
+
cell_metadata_by_id[itercell.model.id] = {
|
|
225
|
+
index: idx,
|
|
226
|
+
content: itercell.model.value.text,
|
|
227
|
+
type: itercell.model.type,
|
|
228
|
+
};
|
|
229
|
+
});
|
|
230
|
+
return cell_metadata_by_id;
|
|
231
|
+
};
|
|
232
|
+
const onContentChanged = _.debounce(() => {
|
|
233
|
+
if (disconnected) {
|
|
234
|
+
notebook.model.contentChanged.disconnect(onContentChanged);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
comm.send({
|
|
238
|
+
type: 'notify_content_changed',
|
|
239
|
+
cell_metadata_by_id: gatherCellMetadataAndContent(),
|
|
240
|
+
});
|
|
241
|
+
}, 500);
|
|
242
|
+
const requestComputeExecSchedule = (cell) => {
|
|
243
|
+
const cell_metadata_by_id = gatherCellMetadataAndContent();
|
|
244
|
+
comm.send({
|
|
245
|
+
type: 'compute_exec_schedule',
|
|
246
|
+
executed_cell_id: cell === null || cell === void 0 ? void 0 : cell.id,
|
|
247
|
+
cell_metadata_by_id,
|
|
248
|
+
});
|
|
249
|
+
};
|
|
209
250
|
const onExecution = (cell, args) => {
|
|
210
251
|
if (disconnected) {
|
|
211
252
|
cell.stateChanged.disconnect(onExecution);
|
|
@@ -214,23 +255,13 @@ const connectToComm = (session, notebook) => {
|
|
|
214
255
|
if (args.name !== 'executionCount' || args.newValue === null) {
|
|
215
256
|
return;
|
|
216
257
|
}
|
|
217
|
-
const cell_metadata_by_id = {};
|
|
218
258
|
notebook.widgets.forEach((itercell, idx) => {
|
|
219
|
-
cell_metadata_by_id[itercell.model.id] = {
|
|
220
|
-
index: idx,
|
|
221
|
-
content: itercell.model.value.text,
|
|
222
|
-
type: itercell.model.type,
|
|
223
|
-
};
|
|
224
259
|
if (itercell.model.id === cell.id) {
|
|
225
260
|
itercell.node.classList.remove(readyClass);
|
|
226
261
|
itercell.node.classList.remove(readyMakingInputClass);
|
|
227
262
|
}
|
|
228
263
|
});
|
|
229
|
-
|
|
230
|
-
type: 'compute_exec_schedule',
|
|
231
|
-
executed_cell_id: cell.id,
|
|
232
|
-
cell_metadata_by_id,
|
|
233
|
-
});
|
|
264
|
+
requestComputeExecSchedule(cell);
|
|
234
265
|
};
|
|
235
266
|
const notifyActiveCell = (newActiveCell) => {
|
|
236
267
|
let newActiveCellOrderIdx = -1;
|
|
@@ -242,7 +273,7 @@ const connectToComm = (session, notebook) => {
|
|
|
242
273
|
const payload = {
|
|
243
274
|
type: 'change_active_cell',
|
|
244
275
|
active_cell_id: newActiveCell.id,
|
|
245
|
-
active_cell_order_idx: newActiveCellOrderIdx
|
|
276
|
+
active_cell_order_idx: newActiveCellOrderIdx,
|
|
246
277
|
};
|
|
247
278
|
comm.send(payload);
|
|
248
279
|
};
|
|
@@ -266,7 +297,9 @@ const connectToComm = (session, notebook) => {
|
|
|
266
297
|
}
|
|
267
298
|
activeCell = cell;
|
|
268
299
|
activeCellId = cell.model.id;
|
|
269
|
-
if (activeCell === null ||
|
|
300
|
+
if (activeCell === null ||
|
|
301
|
+
activeCell.model === null ||
|
|
302
|
+
activeCell.model.type !== 'code') {
|
|
270
303
|
return;
|
|
271
304
|
}
|
|
272
305
|
activeCell.model.stateChanged.connect(onExecution);
|
|
@@ -285,10 +318,11 @@ const connectToComm = (session, notebook) => {
|
|
|
285
318
|
{
|
|
286
319
|
action: 'mouseover',
|
|
287
320
|
update: 'add',
|
|
288
|
-
},
|
|
321
|
+
},
|
|
322
|
+
{
|
|
289
323
|
action: 'mouseout',
|
|
290
324
|
update: 'remove',
|
|
291
|
-
}
|
|
325
|
+
},
|
|
292
326
|
];
|
|
293
327
|
const updateOneCellUI = (id) => {
|
|
294
328
|
const model = cellModelsById[id];
|
|
@@ -308,21 +342,19 @@ const connectToComm = (session, notebook) => {
|
|
|
308
342
|
}
|
|
309
343
|
else if (readyCells.has(id)) {
|
|
310
344
|
elem.classList.add(readyMakingInputClass);
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
addWaitingOutputInteractions(elem, linkedReadyMakerClass);
|
|
314
|
-
}
|
|
345
|
+
elem.classList.add(readyClass);
|
|
346
|
+
addWaitingOutputInteractions(elem, linkedReadyMakerClass);
|
|
315
347
|
}
|
|
316
348
|
if (lastExecutionMode === 'reactive') {
|
|
317
349
|
return;
|
|
318
350
|
}
|
|
319
|
-
if (
|
|
351
|
+
if (Object.prototype.hasOwnProperty.call(waiterLinks, id)) {
|
|
320
352
|
actionUpdatePairs.forEach(({ action, update }) => {
|
|
321
353
|
addUnsafeCellInteraction(getJpInputCollapser(elem), waiterLinks[id], cellsById, getJpInputCollapser, action, update, waitingCells);
|
|
322
354
|
addUnsafeCellInteraction(getJpOutputCollapser(elem), waiterLinks[id], cellsById, getJpInputCollapser, action, update, waitingCells);
|
|
323
355
|
});
|
|
324
356
|
}
|
|
325
|
-
if (
|
|
357
|
+
if (Object.prototype.hasOwnProperty.call(readyMakerLinks, id)) {
|
|
326
358
|
if (!waitingCells.has(id)) {
|
|
327
359
|
elem.classList.add(readyMakingClass);
|
|
328
360
|
elem.classList.add(readyClass);
|
|
@@ -344,45 +376,58 @@ const connectToComm = (session, notebook) => {
|
|
|
344
376
|
}
|
|
345
377
|
};
|
|
346
378
|
comm.onMsg = (msg) => {
|
|
347
|
-
|
|
379
|
+
var _a;
|
|
380
|
+
const payload = msg.content.data;
|
|
381
|
+
if (disconnected || !((_a = payload.success) !== null && _a !== void 0 ? _a : false)) {
|
|
348
382
|
return;
|
|
349
383
|
}
|
|
350
|
-
if (
|
|
384
|
+
if (payload.type === 'establish') {
|
|
351
385
|
notebook.activeCell.model.stateChanged.connect(onExecution);
|
|
352
386
|
notifyActiveCell(notebook.activeCell.model);
|
|
387
|
+
notebook.model.contentChanged.connect(onContentChanged);
|
|
388
|
+
requestComputeExecSchedule();
|
|
353
389
|
}
|
|
354
|
-
else if (
|
|
355
|
-
waitingCells = new Set(
|
|
356
|
-
readyCells = new Set(
|
|
390
|
+
else if (payload.type === 'compute_exec_schedule') {
|
|
391
|
+
waitingCells = new Set(payload.waiting_cells);
|
|
392
|
+
readyCells = new Set(payload.ready_cells);
|
|
357
393
|
newReadyCells = new Set([
|
|
358
394
|
...newReadyCells,
|
|
359
|
-
...
|
|
395
|
+
...payload.new_ready_cells,
|
|
360
396
|
]);
|
|
361
397
|
forcedReactiveCells = new Set([
|
|
362
398
|
...forcedReactiveCells,
|
|
363
|
-
...
|
|
399
|
+
...payload.forced_reactive_cells,
|
|
364
400
|
]);
|
|
365
|
-
waiterLinks =
|
|
366
|
-
readyMakerLinks =
|
|
401
|
+
waiterLinks = payload.waiter_links;
|
|
402
|
+
readyMakerLinks = payload.ready_maker_links;
|
|
367
403
|
cellPendingExecution = null;
|
|
368
|
-
const exec_mode =
|
|
369
|
-
isReactivelyExecuting = isReactivelyExecuting ||
|
|
370
|
-
const flow_order =
|
|
371
|
-
const exec_schedule =
|
|
404
|
+
const exec_mode = payload.exec_mode;
|
|
405
|
+
isReactivelyExecuting = isReactivelyExecuting || exec_mode === 'reactive';
|
|
406
|
+
const flow_order = payload.flow_order;
|
|
407
|
+
const exec_schedule = payload.exec_schedule;
|
|
372
408
|
lastExecutionMode = exec_mode;
|
|
373
|
-
lastExecutionHighlights =
|
|
374
|
-
const lastExecutedCellId =
|
|
409
|
+
lastExecutionHighlights = payload.highlights;
|
|
410
|
+
const lastExecutedCellId = payload.last_executed_cell_id;
|
|
375
411
|
executedReactiveReadyCells.add(lastExecutedCellId);
|
|
376
|
-
const last_execution_was_error =
|
|
412
|
+
const last_execution_was_error = payload.last_execution_was_error;
|
|
377
413
|
if (!last_execution_was_error) {
|
|
414
|
+
let lastExecutedCellIdSeen = false;
|
|
378
415
|
for (const cell of notebook.widgets) {
|
|
379
|
-
if (
|
|
416
|
+
if (!lastExecutedCellIdSeen) {
|
|
417
|
+
lastExecutedCellIdSeen = cell.model.id === lastExecutedCellId;
|
|
418
|
+
if (flow_order === 'in_order' || exec_schedule === 'strict') {
|
|
419
|
+
continue;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
if (cell.model.type !== 'code' ||
|
|
423
|
+
executedReactiveReadyCells.has(cell.model.id)) {
|
|
380
424
|
continue;
|
|
381
425
|
}
|
|
382
426
|
if (!newReadyCells.has(cell.model.id)) {
|
|
383
427
|
continue;
|
|
384
428
|
}
|
|
385
|
-
if (!forcedReactiveCells.has(cell.model.id) &&
|
|
429
|
+
if (!forcedReactiveCells.has(cell.model.id) &&
|
|
430
|
+
exec_mode !== 'reactive') {
|
|
386
431
|
continue;
|
|
387
432
|
}
|
|
388
433
|
const codeCell = cell;
|
|
@@ -396,7 +441,8 @@ const connectToComm = (session, notebook) => {
|
|
|
396
441
|
else if (codeCell.model.executionCount == null) {
|
|
397
442
|
// pass
|
|
398
443
|
}
|
|
399
|
-
else if (codeCell.model.executionCount <
|
|
444
|
+
else if (codeCell.model.executionCount <
|
|
445
|
+
cellPendingExecution.model.executionCount) {
|
|
400
446
|
// otherwise, execute in order of earliest execution counter
|
|
401
447
|
cellPendingExecution = codeCell;
|
|
402
448
|
}
|
|
@@ -416,6 +462,7 @@ const connectToComm = (session, notebook) => {
|
|
|
416
462
|
executedReactiveReadyCells = new Set();
|
|
417
463
|
updateUI(notebook);
|
|
418
464
|
isReactivelyExecuting = false;
|
|
465
|
+
isAltModeExecuting = false;
|
|
419
466
|
}
|
|
420
467
|
else {
|
|
421
468
|
isReactivelyExecuting = true;
|
package/package.json
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
"jupyterlab",
|
|
7
7
|
"jupyterlab-extension"
|
|
8
8
|
],
|
|
9
|
-
"homepage": "https://github.com/
|
|
9
|
+
"homepage": "https://github.com/ipyflow/ipyflow",
|
|
10
10
|
"bugs": {
|
|
11
|
-
"url": "https://github.com/
|
|
11
|
+
"url": "https://github.com/ipyflow/ipyflow/issues"
|
|
12
12
|
},
|
|
13
13
|
"license": "BSD-3-Clause",
|
|
14
14
|
"author": "Stephen Macke",
|
|
@@ -21,20 +21,22 @@
|
|
|
21
21
|
"style": "style/index.css",
|
|
22
22
|
"repository": {
|
|
23
23
|
"type": "git",
|
|
24
|
-
"url": "https://github.com/
|
|
24
|
+
"url": "https://github.com/ipyflow/ipyflow.git"
|
|
25
25
|
},
|
|
26
26
|
"scripts": {
|
|
27
|
-
"build": "
|
|
28
|
-
"build:
|
|
27
|
+
"build": "npm run build:lib && npm run build:labextension",
|
|
28
|
+
"build:dev": "npm run build:lib && npm run build:labextension:dev",
|
|
29
29
|
"build:labextension": "jupyter labextension build .",
|
|
30
30
|
"build:labextension:dev": "jupyter labextension build --development True .",
|
|
31
31
|
"build:lib": "tsc",
|
|
32
|
-
"clean": "
|
|
32
|
+
"clean": "npm run clean:lib",
|
|
33
33
|
"clean:lib": "rimraf lib tsconfig.tsbuildinfo",
|
|
34
34
|
"eslint": "eslint . --ext .ts,.tsx --fix",
|
|
35
35
|
"eslint:check": "eslint . --ext .ts,.tsx",
|
|
36
|
+
"format": "prettier --write 'src/*.ts'",
|
|
37
|
+
"lint": "prettier --check 'src/*.ts'",
|
|
36
38
|
"install:extension": "jupyter labextension develop --overwrite .",
|
|
37
|
-
"prepare": "
|
|
39
|
+
"prepare": "npm run clean && npm run build",
|
|
38
40
|
"watch": "run-p watch:src watch:labextension",
|
|
39
41
|
"watch:src": "tsc -w",
|
|
40
42
|
"watch:labextension": "jupyter labextension watch ."
|
|
@@ -42,7 +44,8 @@
|
|
|
42
44
|
"dependencies": {
|
|
43
45
|
"@jupyterlab/application": "^3.4.3",
|
|
44
46
|
"@jupyterlab/coreutils": "^5.4.3",
|
|
45
|
-
"@jupyterlab/notebook": "^3.4.3"
|
|
47
|
+
"@jupyterlab/notebook": "^3.4.3",
|
|
48
|
+
"lodash": "^4.0"
|
|
46
49
|
},
|
|
47
50
|
"devDependencies": {
|
|
48
51
|
"@jupyterlab/builder": "^3.4.3",
|
|
@@ -63,5 +66,5 @@
|
|
|
63
66
|
"extension": true,
|
|
64
67
|
"outputDir": "../../core/ipyflow/resources/labextension/"
|
|
65
68
|
},
|
|
66
|
-
"version": "0.0.
|
|
69
|
+
"version": "0.0.156"
|
|
67
70
|
}
|