Skip to content

Commit 4c73151

Browse files
Notebooks respect stop on error (microsoft#13482)
1 parent 56f9a60 commit 4c73151

File tree

3 files changed

+87
-0
lines changed

3 files changed

+87
-0
lines changed

news/2 Fixes/13338.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Respect stop on error setting for executing cells in native notebook.

src/client/datascience/interactive-ipynb/nativeEditor.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,28 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor {
434434
cellsExecuting.add(cell);
435435
await this.reexecuteCell(cell, tokenSource.token);
436436
cellsExecuting.delete(cell);
437+
438+
// Check the new state of our cell
439+
const resultCell = this.model.cells.find((item) => item.id === cell.id);
440+
441+
// Bail on the rest of our cells if one comes back with an error
442+
if (
443+
this.configuration.getSettings(this.owningResource).datascience.stopOnError &&
444+
resultCell &&
445+
resultCell.state === CellState.error
446+
) {
447+
// Set the remaining cells as finished and break out
448+
if (i < info.cellIds.length) {
449+
const unExecutedCellIds = info.cellIds.slice(i + 1, info.cellIds.length);
450+
unExecutedCellIds.forEach((cellId) => {
451+
const unexecutedCell = this.model.cells.find((item) => item.id === cellId);
452+
if (unexecutedCell) {
453+
this.finishCell(unexecutedCell);
454+
}
455+
});
456+
}
457+
break;
458+
}
437459
}
438460
} catch (exc) {
439461
// Tell the other side we restarted the kernel. This will stop all executions

src/test/datascience/nativeEditor.functional.test.tsx

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
ICell,
3333
IDataScienceErrorHandler,
3434
IJupyterExecution,
35+
INotebookEditor,
3536
INotebookEditorProvider,
3637
INotebookExporter,
3738
ITrustService
@@ -2445,6 +2446,69 @@ df.head()`;
24452446
}
24462447
};
24472448

2449+
suite('Stop On Error', () => {
2450+
let notebookEditor: { editor: INotebookEditor; mount: IMountedWebView };
2451+
setup(async () => {
2452+
await initIoc();
2453+
2454+
// Set up a file where the second cell throws an exception
2455+
addMockData(ioc, 'print("hello")', 'hello');
2456+
addMockData(ioc, 'raise Exception("stop")', undefined, undefined, 'error');
2457+
addMockData(ioc, 'print("world")', 'world');
2458+
2459+
const errorFile = [
2460+
{ id: 'NotebookImport#0', data: { source: 'print("hello")' } },
2461+
{ id: 'NotebookImport#1', data: { source: 'raise Exception("stop")' } },
2462+
{ id: 'NotebookImport#2', data: { source: 'print("world")' } }
2463+
];
2464+
const runAllCells = errorFile.map((cell) => {
2465+
return createFileCell(cell, cell.data);
2466+
});
2467+
const notebook = await ioc
2468+
.get<INotebookExporter>(INotebookExporter)
2469+
.translateToNotebook(runAllCells, undefined);
2470+
notebookEditor = await openEditor(ioc, JSON.stringify(notebook));
2471+
});
2472+
2473+
test('Stop On Error On', async () => {
2474+
const ne = notebookEditor;
2475+
2476+
const runAllButton = findButton(ne.mount.wrapper, NativeEditor, 0);
2477+
// The render method needs to be executed 3 times for three cells.
2478+
const threeCellsUpdated = waitForMessage(ioc, InteractiveWindowMessages.ExecutionRendered, {
2479+
numberOfTimes: 3
2480+
});
2481+
runAllButton!.simulate('click');
2482+
await threeCellsUpdated;
2483+
2484+
verifyHtmlOnCell(ne.mount.wrapper, 'NativeCell', `hello`, 0);
2485+
// There should be no output on the third cell as it's blocked by the exception on the second cell
2486+
assert.throws(() => verifyHtmlOnCell(ne.mount.wrapper, 'NativeCell', `world`, 2));
2487+
});
2488+
2489+
test('Stop On Error Off', async () => {
2490+
const ne = notebookEditor;
2491+
2492+
// Force our settings to not stop on error
2493+
ioc.forceSettingsChanged(undefined, ioc.getSettings().pythonPath, {
2494+
...ioc.getSettings().datascience,
2495+
stopOnError: false
2496+
});
2497+
2498+
const runAllButton = findButton(ne.mount.wrapper, NativeEditor, 0);
2499+
// The render method needs to be executed 3 times for three cells.
2500+
const threeCellsUpdated = waitForMessage(ioc, InteractiveWindowMessages.ExecutionRendered, {
2501+
numberOfTimes: 3
2502+
});
2503+
runAllButton!.simulate('click');
2504+
await threeCellsUpdated;
2505+
2506+
verifyHtmlOnCell(ne.mount.wrapper, 'NativeCell', `hello`, 0);
2507+
// There should be output on the third cell, even with an error on the second
2508+
verifyHtmlOnCell(ne.mount.wrapper, 'NativeCell', `world`, 2);
2509+
});
2510+
});
2511+
24482512
suite('Update Metadata', () => {
24492513
setup(async function () {
24502514
await initIoc();

0 commit comments

Comments
 (0)