jupyterlab-ipyflow 0.0.87 → 0.0.90
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 +91 -78
- package/package.json +1 -1
- package/style/index.css +30 -30
package/lib/index.js
CHANGED
|
@@ -48,17 +48,17 @@ const extension = {
|
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
50
|
};
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
const
|
|
51
|
+
const waitingClass = 'waiting-cell';
|
|
52
|
+
const readyClass = 'ready-cell';
|
|
53
|
+
const readyMakingClass = 'ready-making-cell';
|
|
54
|
+
const readyMakingInputClass = 'ready-making-input-cell';
|
|
55
|
+
const linkedWaitingClass = 'linked-waiting';
|
|
56
|
+
const linkedReadyMakerClass = 'linked-ready-maker';
|
|
57
57
|
let dirtyCells = new Set();
|
|
58
|
-
let
|
|
59
|
-
let
|
|
60
|
-
let
|
|
61
|
-
let
|
|
58
|
+
let waitingCells = new Set();
|
|
59
|
+
let readyCells = new Set();
|
|
60
|
+
let waiterLinks = {};
|
|
61
|
+
let readyMakerLinks = {};
|
|
62
62
|
let activeCell = null;
|
|
63
63
|
let activeCellId = null;
|
|
64
64
|
let cellsById = {};
|
|
@@ -66,10 +66,15 @@ let orderIdxById = {};
|
|
|
66
66
|
let cellPendingExecution = null;
|
|
67
67
|
let lastExecutionMode = null;
|
|
68
68
|
let lastExecutionHighlightsEnabled = null;
|
|
69
|
-
let
|
|
70
|
-
let
|
|
69
|
+
let executedReactiveReadyCells = new Set();
|
|
70
|
+
let newReadyCells = new Set();
|
|
71
71
|
let forcedReactiveCells = new Set();
|
|
72
72
|
const cleanup = new Event('cleanup');
|
|
73
|
+
const resetReactiveState = () => {
|
|
74
|
+
newReadyCells = new Set();
|
|
75
|
+
forcedReactiveCells = new Set();
|
|
76
|
+
executedReactiveReadyCells = new Set();
|
|
77
|
+
};
|
|
73
78
|
const getJpInputCollapser = (elem) => {
|
|
74
79
|
if (elem === null || elem === undefined) {
|
|
75
80
|
return null;
|
|
@@ -98,7 +103,7 @@ const attachCleanupListener = (elem, evt, listener) => {
|
|
|
98
103
|
elem.addEventListener(evt, listener);
|
|
99
104
|
elem.addEventListener('cleanup', cleanupListener);
|
|
100
105
|
};
|
|
101
|
-
const
|
|
106
|
+
const addWaitingOutputInteraction = (elem, linkedElem, evt, add_or_remove, css) => {
|
|
102
107
|
if (elem === null || linkedElem === null) {
|
|
103
108
|
return;
|
|
104
109
|
}
|
|
@@ -107,11 +112,11 @@ const addStaleOutputInteraction = (elem, linkedElem, evt, add_or_remove, css) =>
|
|
|
107
112
|
};
|
|
108
113
|
attachCleanupListener(elem, evt, listener);
|
|
109
114
|
};
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
+
const addWaitingOutputInteractions = (elem, linkedInputClass) => {
|
|
116
|
+
addWaitingOutputInteraction(getJpInputCollapser(elem), getJpOutputCollapser(elem), 'mouseover', 'add', linkedWaitingClass);
|
|
117
|
+
addWaitingOutputInteraction(getJpInputCollapser(elem), getJpOutputCollapser(elem), 'mouseout', 'remove', linkedWaitingClass);
|
|
118
|
+
addWaitingOutputInteraction(getJpOutputCollapser(elem), getJpInputCollapser(elem), 'mouseover', 'add', linkedInputClass);
|
|
119
|
+
addWaitingOutputInteraction(getJpOutputCollapser(elem), getJpInputCollapser(elem), 'mouseout', 'remove', linkedInputClass);
|
|
115
120
|
};
|
|
116
121
|
const refreshNodeMapping = (notebook) => {
|
|
117
122
|
cellsById = {};
|
|
@@ -123,34 +128,34 @@ const refreshNodeMapping = (notebook) => {
|
|
|
123
128
|
};
|
|
124
129
|
const clearCellState = (notebook) => {
|
|
125
130
|
notebook.widgets.forEach((cell, idx) => {
|
|
126
|
-
cell.node.classList.remove(
|
|
127
|
-
cell.node.classList.remove(
|
|
128
|
-
cell.node.classList.remove(
|
|
129
|
-
cell.node.classList.remove(
|
|
131
|
+
cell.node.classList.remove(waitingClass);
|
|
132
|
+
cell.node.classList.remove(readyMakingClass);
|
|
133
|
+
cell.node.classList.remove(readyClass);
|
|
134
|
+
cell.node.classList.remove(readyMakingInputClass);
|
|
130
135
|
// clear any old event listeners
|
|
131
136
|
const inputCollapser = getJpInputCollapser(cell.node);
|
|
132
137
|
if (inputCollapser !== null) {
|
|
133
|
-
inputCollapser.firstElementChild.classList.remove(
|
|
134
|
-
inputCollapser.firstElementChild.classList.remove(
|
|
138
|
+
inputCollapser.firstElementChild.classList.remove(linkedWaitingClass);
|
|
139
|
+
inputCollapser.firstElementChild.classList.remove(linkedReadyMakerClass);
|
|
135
140
|
inputCollapser.dispatchEvent(cleanup);
|
|
136
141
|
}
|
|
137
142
|
const outputCollapser = getJpOutputCollapser(cell.node);
|
|
138
143
|
if (outputCollapser !== null) {
|
|
139
|
-
outputCollapser.firstElementChild.classList.remove(
|
|
140
|
-
outputCollapser.firstElementChild.classList.remove(
|
|
144
|
+
outputCollapser.firstElementChild.classList.remove(linkedWaitingClass);
|
|
145
|
+
outputCollapser.firstElementChild.classList.remove(linkedReadyMakerClass);
|
|
141
146
|
outputCollapser.dispatchEvent(cleanup);
|
|
142
147
|
}
|
|
143
148
|
});
|
|
144
149
|
};
|
|
145
|
-
const addUnsafeCellInteraction = (elem, linkedElems, cellsById, collapserFun, evt, add_or_remove,
|
|
150
|
+
const addUnsafeCellInteraction = (elem, linkedElems, cellsById, collapserFun, evt, add_or_remove, waitingCells) => {
|
|
146
151
|
if (elem === null) {
|
|
147
152
|
return;
|
|
148
153
|
}
|
|
149
154
|
const listener = () => {
|
|
150
155
|
for (const linkedId of linkedElems) {
|
|
151
|
-
let css =
|
|
152
|
-
if (
|
|
153
|
-
css =
|
|
156
|
+
let css = linkedReadyMakerClass;
|
|
157
|
+
if (waitingCells.has(linkedId)) {
|
|
158
|
+
css = linkedWaitingClass;
|
|
154
159
|
}
|
|
155
160
|
const collapser = collapserFun(cellsById[linkedId]);
|
|
156
161
|
if (collapser === null || collapser.firstElementChild === null) {
|
|
@@ -174,17 +179,20 @@ const connectToComm = (session, notebook) => {
|
|
|
174
179
|
return;
|
|
175
180
|
}
|
|
176
181
|
const order_index_by_cell_id = {};
|
|
182
|
+
const content_by_cell_id = {};
|
|
177
183
|
notebook.widgets.forEach((itercell, idx) => {
|
|
178
184
|
order_index_by_cell_id[itercell.model.id] = idx;
|
|
185
|
+
content_by_cell_id[itercell.model.id] = itercell.model.value.text;
|
|
179
186
|
if (itercell.model.id === cell.id) {
|
|
180
|
-
itercell.node.classList.remove(
|
|
181
|
-
itercell.node.classList.remove(
|
|
187
|
+
itercell.node.classList.remove(readyClass);
|
|
188
|
+
itercell.node.classList.remove(readyMakingInputClass);
|
|
182
189
|
}
|
|
183
190
|
});
|
|
184
191
|
const payload = {
|
|
185
|
-
type: '
|
|
192
|
+
type: 'compute_exec_schedule',
|
|
186
193
|
executed_cell_id: cell.id,
|
|
187
194
|
order_index_by_cell_id: order_index_by_cell_id,
|
|
195
|
+
content_by_cell_id: content_by_cell_id,
|
|
188
196
|
};
|
|
189
197
|
comm.send(payload).done.then(() => {
|
|
190
198
|
if (cellPendingExecution !== null) {
|
|
@@ -192,12 +200,10 @@ const connectToComm = (session, notebook) => {
|
|
|
192
200
|
}
|
|
193
201
|
else {
|
|
194
202
|
if (lastExecutionMode === 'reactive') {
|
|
195
|
-
|
|
203
|
+
readyCells = executedReactiveReadyCells;
|
|
196
204
|
updateUI(notebook);
|
|
197
205
|
}
|
|
198
|
-
|
|
199
|
-
forcedReactiveCells = new Set();
|
|
200
|
-
executedReactiveFreshCells = new Set();
|
|
206
|
+
resetReactiveState();
|
|
201
207
|
comm.send({
|
|
202
208
|
type: 'reactivity_cleanup',
|
|
203
209
|
});
|
|
@@ -264,36 +270,36 @@ const connectToComm = (session, notebook) => {
|
|
|
264
270
|
];
|
|
265
271
|
const updateOneCellUI = (id) => {
|
|
266
272
|
const elem = cellsById[id];
|
|
267
|
-
if (
|
|
268
|
-
elem.classList.add(
|
|
269
|
-
elem.classList.add(
|
|
270
|
-
elem.classList.remove(
|
|
271
|
-
|
|
273
|
+
if (waitingCells.has(id)) {
|
|
274
|
+
elem.classList.add(waitingClass);
|
|
275
|
+
elem.classList.add(readyClass);
|
|
276
|
+
elem.classList.remove(readyMakingInputClass);
|
|
277
|
+
addWaitingOutputInteractions(elem, linkedWaitingClass);
|
|
272
278
|
}
|
|
273
|
-
else if (
|
|
274
|
-
elem.classList.add(
|
|
279
|
+
else if (readyCells.has(id)) {
|
|
280
|
+
elem.classList.add(readyMakingInputClass);
|
|
275
281
|
if (lastExecutionMode === 'normal') {
|
|
276
|
-
elem.classList.add(
|
|
277
|
-
|
|
282
|
+
elem.classList.add(readyClass);
|
|
283
|
+
addWaitingOutputInteractions(elem, linkedReadyMakerClass);
|
|
278
284
|
}
|
|
279
285
|
}
|
|
280
286
|
if (lastExecutionMode === 'reactive') {
|
|
281
287
|
return;
|
|
282
288
|
}
|
|
283
|
-
if (
|
|
289
|
+
if (waiterLinks.hasOwnProperty(id)) {
|
|
284
290
|
actionUpdatePairs.forEach(({ action, update }) => {
|
|
285
|
-
addUnsafeCellInteraction(getJpInputCollapser(elem),
|
|
286
|
-
addUnsafeCellInteraction(getJpOutputCollapser(elem),
|
|
291
|
+
addUnsafeCellInteraction(getJpInputCollapser(elem), waiterLinks[id], cellsById, getJpInputCollapser, action, update, waitingCells);
|
|
292
|
+
addUnsafeCellInteraction(getJpOutputCollapser(elem), waiterLinks[id], cellsById, getJpInputCollapser, action, update, waitingCells);
|
|
287
293
|
});
|
|
288
294
|
}
|
|
289
|
-
if (
|
|
290
|
-
if (!
|
|
291
|
-
elem.classList.add(
|
|
292
|
-
elem.classList.add(
|
|
295
|
+
if (readyMakerLinks.hasOwnProperty(id)) {
|
|
296
|
+
if (!waitingCells.has(id)) {
|
|
297
|
+
elem.classList.add(readyMakingClass);
|
|
298
|
+
elem.classList.add(readyClass);
|
|
293
299
|
}
|
|
294
300
|
actionUpdatePairs.forEach(({ action, update }) => {
|
|
295
|
-
addUnsafeCellInteraction(getJpInputCollapser(elem),
|
|
296
|
-
addUnsafeCellInteraction(getJpInputCollapser(elem),
|
|
301
|
+
addUnsafeCellInteraction(getJpInputCollapser(elem), readyMakerLinks[id], cellsById, getJpInputCollapser, action, update, waitingCells);
|
|
302
|
+
addUnsafeCellInteraction(getJpInputCollapser(elem), readyMakerLinks[id], cellsById, getJpOutputCollapser, action, update, waitingCells);
|
|
297
303
|
});
|
|
298
304
|
}
|
|
299
305
|
};
|
|
@@ -315,44 +321,51 @@ const connectToComm = (session, notebook) => {
|
|
|
315
321
|
notebook.activeCell.model.stateChanged.connect(onExecution);
|
|
316
322
|
notifyActiveCell(notebook.activeCell.model);
|
|
317
323
|
}
|
|
318
|
-
else if (msg.content.data['type'] === '
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
324
|
+
else if (msg.content.data['type'] === 'compute_exec_schedule') {
|
|
325
|
+
waitingCells = new Set(msg.content.data['waiting_cells']);
|
|
326
|
+
readyCells = new Set(msg.content.data['ready_cells']);
|
|
327
|
+
newReadyCells = new Set([...newReadyCells, ...msg.content.data['new_ready_cells']]);
|
|
322
328
|
forcedReactiveCells = new Set([...forcedReactiveCells, ...msg.content.data['forced_reactive_cells']]);
|
|
323
|
-
|
|
324
|
-
|
|
329
|
+
waiterLinks = msg.content.data['waiter_links'];
|
|
330
|
+
readyMakerLinks = msg.content.data['ready_maker_links'];
|
|
325
331
|
cellPendingExecution = null;
|
|
326
332
|
const exec_mode = msg.content.data['exec_mode'];
|
|
327
333
|
const flow_order = msg.content.data['flow_order'];
|
|
328
334
|
const exec_schedule = msg.content.data['exec_schedule'];
|
|
329
335
|
lastExecutionMode = exec_mode;
|
|
330
336
|
lastExecutionHighlightsEnabled = msg.content.data['highlights_enabled'];
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
return;
|
|
337
|
+
executedReactiveReadyCells.add(msg.content.data['last_executed_cell_id']);
|
|
338
|
+
for (const cell of notebook.widgets) {
|
|
339
|
+
if (cell.model.type !== 'code' || executedReactiveReadyCells.has(cell.model.id)) {
|
|
340
|
+
continue;
|
|
336
341
|
}
|
|
337
|
-
if (
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
cellPendingExecution = codeCell;
|
|
341
|
-
// break early if using one of the order-based semantics
|
|
342
|
-
found = (flow_order === 'in_order' || exec_schedule === 'strict');
|
|
342
|
+
if (!forcedReactiveCells.has(cell.model.id)) {
|
|
343
|
+
if (exec_mode !== 'reactive' || !newReadyCells.has(cell.model.id)) {
|
|
344
|
+
continue;
|
|
343
345
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
346
|
+
}
|
|
347
|
+
const codeCell = cell;
|
|
348
|
+
if (cellPendingExecution === null) {
|
|
349
|
+
cellPendingExecution = codeCell;
|
|
350
|
+
// break early if using one of the order-based semantics
|
|
351
|
+
if (flow_order === 'in_order' || exec_schedule === 'strict') {
|
|
352
|
+
break;
|
|
347
353
|
}
|
|
348
354
|
}
|
|
349
|
-
|
|
355
|
+
else if (codeCell.model.executionCount == null) {
|
|
356
|
+
// pass
|
|
357
|
+
}
|
|
358
|
+
else if (codeCell.model.executionCount < cellPendingExecution.model.executionCount) {
|
|
359
|
+
// otherwise, execute in order of earliest execution counter
|
|
360
|
+
cellPendingExecution = codeCell;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
350
363
|
if (cellPendingExecution === null) {
|
|
351
|
-
|
|
352
|
-
forcedReactiveCells = new Set();
|
|
364
|
+
resetReactiveState();
|
|
353
365
|
updateUI(notebook);
|
|
354
366
|
}
|
|
355
367
|
else {
|
|
368
|
+
onActiveCellChange(notebook, cellPendingExecution);
|
|
356
369
|
clearCellState(notebook);
|
|
357
370
|
}
|
|
358
371
|
}
|
package/package.json
CHANGED
package/style/index.css
CHANGED
|
@@ -1,64 +1,64 @@
|
|
|
1
1
|
:root {
|
|
2
|
-
--
|
|
3
|
-
--
|
|
2
|
+
--waiting-color: rgb(254,0,82);
|
|
3
|
+
--ready-making-color: rgb(0,197,158);
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
.
|
|
7
|
-
border: 1px solid var(--
|
|
6
|
+
.waiting-cell .jp-InputCollapser {
|
|
7
|
+
border: 1px solid var(--waiting-color);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
.
|
|
11
|
-
background-color: var(--
|
|
10
|
+
.waiting-cell.jp-mod-selected .jp-Collapser-child {
|
|
11
|
+
background-color: var(--waiting-color);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
.
|
|
15
|
-
background-color: var(--
|
|
14
|
+
.waiting-cell .jp-Collapser:hover > .jp-Collapser-child {
|
|
15
|
+
background-color: var(--waiting-color);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
.jp-Collapser-child.linked-
|
|
19
|
-
background-color: var(--
|
|
18
|
+
.jp-Collapser-child.linked-waiting {
|
|
19
|
+
background-color: var(--waiting-color);
|
|
20
20
|
opacity: 0.6;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
.
|
|
24
|
-
border: 1px solid var(--
|
|
23
|
+
.ready-making-cell .jp-InputCollapser {
|
|
24
|
+
border: 1px solid var(--ready-making-color);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
.
|
|
28
|
-
background-color: var(--
|
|
27
|
+
.ready-making-cell.jp-mod-selected .jp-Collapser-child {
|
|
28
|
+
background-color: var(--ready-making-color);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
.
|
|
32
|
-
background-color: var(--
|
|
31
|
+
.ready-making-cell .jp-Collapser:hover > .jp-Collapser-child {
|
|
32
|
+
background-color: var(--ready-making-color);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
.jp-Collapser-child.linked-
|
|
36
|
-
background-color: var(--
|
|
35
|
+
.jp-Collapser-child.linked-ready-maker {
|
|
36
|
+
background-color: var(--ready-making-color);
|
|
37
37
|
opacity: 0.6;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/* put input / output cells later since they should take precedence */
|
|
41
41
|
|
|
42
|
-
.
|
|
43
|
-
border: 1px solid var(--
|
|
42
|
+
.ready-cell .jp-OutputCollapser {
|
|
43
|
+
border: 1px solid var(--waiting-color);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
.
|
|
47
|
-
background-color: var(--
|
|
46
|
+
.ready-cell.jp-mod-selected .jp-OutputCollapser .jp-Collapser-child {
|
|
47
|
+
background-color: var(--waiting-color);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
.
|
|
51
|
-
background-color: var(--
|
|
50
|
+
.ready-cell .jp-OutputCollapser:hover > .jp-Collapser-child {
|
|
51
|
+
background-color: var(--waiting-color);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
.
|
|
55
|
-
border: 1px solid var(--
|
|
54
|
+
.ready-making-input-cell .jp-InputCollapser {
|
|
55
|
+
border: 1px solid var(--ready-making-color);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
.
|
|
59
|
-
background-color: var(--
|
|
58
|
+
.ready-making-input-cell.jp-mod-selected .jp-InputCollapser .jp-Collapser-child {
|
|
59
|
+
background-color: var(--ready-making-color);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
.
|
|
63
|
-
background-color: var(--
|
|
62
|
+
.ready-making-input-cell .jp-InputCollapser:hover > .jp-Collapser-child {
|
|
63
|
+
background-color: var(--ready-making-color);
|
|
64
64
|
}
|