Skip to content

Commit 12c99e4

Browse files
authored
Added notifyOnComplete paramater for code execution enabling to send model notifications only when all code execution completed
1 parent 3ac5b26 commit 12c99e4

File tree

5 files changed

+35
-10
lines changed

5 files changed

+35
-10
lines changed

packages/react/src/components/output/Output.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export type IOutputProps = {
4040
showEditor: boolean;
4141
showKernelProgressBar?: boolean;
4242
toolbarPosition: 'up' | 'middle' | 'none';
43+
notifyOnComplete? : boolean;
4344
};
4445

4546
export const Output = (props: IOutputProps) => {
@@ -62,6 +63,7 @@ export const Output = (props: IOutputProps) => {
6263
showControl,
6364
showEditor,
6465
showKernelProgressBar = true,
66+
notifyOnComplete = false,
6567
id: sourceId,
6668
toolbarPosition,
6769
} = props;
@@ -121,7 +123,7 @@ export const Output = (props: IOutputProps) => {
121123
useEffect(() => {
122124
if (adapter) {
123125
if (autoRun) {
124-
adapter.execute(code);
126+
adapter.execute(code, notifyOnComplete);
125127
}
126128
}
127129
}, [adapter]);
@@ -141,12 +143,12 @@ export const Output = (props: IOutputProps) => {
141143
const executeRequest = outputStore.getExecuteRequest(sourceId);
142144
useEffect(() => {
143145
if (adapter && executeRequest && executeRequest === id) {
144-
adapter.execute(code);
146+
adapter.execute(code, notifyOnComplete);
145147
}
146148
}, [executeRequest, adapter]);
147149
useEffect(() => {
148150
if (adapter && executeTrigger > 0) {
149-
adapter.execute(code);
151+
adapter.execute(code, notifyOnComplete);
150152
}
151153
}, [executeTrigger]);
152154
useEffect(() => {
@@ -244,6 +246,7 @@ Output.defaultProps = {
244246
metadata: {},
245247
},
246248
],
249+
notifyOnComplete : false,
247250
toolbarPosition: 'up',
248251
} as Partial<IOutputProps>;
249252

packages/react/src/components/output/OutputAdapter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@ export class OutputAdapter {
7979
this.initKernel();
8080
}
8181

82-
public async execute(code: string) {
82+
public async execute(code: string, notifyOnComplete? : boolean) {
8383
if (this._kernel) {
8484
this.clear();
85-
const done = execute(this._id, code, this._outputArea, this._kernel);
85+
const done = execute(this._id, code, this._outputArea, this._kernel, notifyOnComplete);
8686
await done;
8787
}
8888
}

packages/react/src/components/output/OutputExecutor.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ export async function execute(
1717
code: string,
1818
output: OutputArea,
1919
kernel: Kernel,
20-
metadata?: JSONObject
20+
metadata?: JSONObject,
21+
notifyOnComplete? : boolean
2122
): Promise<KernelMessage.IExecuteReplyMsg | undefined> {
2223
// Override the default for `stop_on_error`.
2324
let stopOnError = true;
@@ -33,6 +34,7 @@ export async function execute(
3334
{
3435
model: output.model,
3536
stopOnError,
37+
notifyOnComplete : notifyOnComplete
3638
}
3739
);
3840
const future = kernelExecutor!.future;

packages/react/src/jupyter/kernel/Kernel.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ export class Kernel {
194194
stopOnError,
195195
storeHistory,
196196
allowStdin,
197+
notifyOnComplete = false
197198
}: {
198199
model?: IOutputAreaModel;
199200
iopubMessageHooks?: IOPubMessageHook[];
@@ -202,12 +203,14 @@ export class Kernel {
202203
stopOnError?: boolean;
203204
storeHistory?: boolean;
204205
allowStdin?: boolean;
206+
notifyOnComplete? : boolean
205207
} = {}
206208
): KernelExecutor | undefined {
207209
if (this._kernelConnection) {
208210
const kernelExecutor = new KernelExecutor({
209211
connection: this._kernelConnection,
210212
model,
213+
notifyOnComplete,
211214
});
212215
kernelExecutor.execute(code, {
213216
iopubMessageHooks,

packages/react/src/jupyter/kernel/KernelExecutor.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ export type IKernelExecutorOptions = {
4141
* Outputs model to populate with the execution results.
4242
*/
4343
model?: IOutputAreaModel;
44+
/**
45+
* Flag defining if notification about model changes
46+
* must only be made when execution complete
47+
*/
48+
notifyOnComplete? : boolean;
4449
}
4550

4651
export class KernelExecutor {
@@ -54,13 +59,15 @@ export class KernelExecutor {
5459
private _outputsChanged = new Signal<KernelExecutor, IOutput[]>(this);
5560
private _future?: JupyterKernel.IFuture<KernelMessage.IExecuteRequestMsg, KernelMessage.IExecuteReplyMsg>;
5661
private _shellMessageHooks = new Array<ShellMessageHook>();
62+
private _notifyOnComplete : boolean = false;
5763

58-
public constructor({ connection, model }: IKernelExecutorOptions) {
64+
public constructor({ connection, model, notifyOnComplete }: IKernelExecutorOptions) {
5965
this._executed = new PromiseDelegate<IOutputAreaModel>();
6066
this._kernelConnection = connection;
6167
this._model = model ?? new OutputAreaModel();
6268
this._outputs = [];
6369
this._kernelState = kernelsStore.getState();
70+
this._notifyOnComplete = !!notifyOnComplete;
6471
}
6572

6673
/**
@@ -118,6 +125,10 @@ export class KernelExecutor {
118125
// Wait for future to be done before resolving the exectud promise.
119126
this._future.done.then(() => {
120127
kernelsStore.getState().setExecutionPhase(this._kernelConnection.id, ExecutionPhase.completed);
128+
// We emit model changes only when execution completed
129+
if (this._notifyOnComplete) {
130+
this._modelChanged.emit(this._model);
131+
}
121132
this._executed.resolve(this._model);
122133
});
123134
return this._executed.promise;
@@ -204,13 +215,17 @@ export class KernelExecutor {
204215
this._outputs.push(message.content as IExecuteResult);
205216
this._outputsChanged.emit(this._outputs);
206217
this._model.add(output);
207-
this._modelChanged.emit(this._model);
218+
if (!this._notifyOnComplete) {
219+
this._modelChanged.emit(this._model);
220+
}
208221
break;
209222
case 'display_data':
210223
this._outputs.push(message.content as IDisplayData);
211224
this._outputsChanged.emit(this._outputs);
212225
this._model.add(output);
213-
this._modelChanged.emit(this._model);
226+
if (!this._notifyOnComplete) {
227+
this._modelChanged.emit(this._model);
228+
}
214229
break;
215230
case 'stream':
216231
case 'error':
@@ -231,7 +246,9 @@ export class KernelExecutor {
231246
this._outputsChanged.emit(this._outputs);
232247
// FIXME this needs more advanced analysis see OutputArea
233248
this._model.add(output);
234-
this._modelChanged.emit(this._model);
249+
if (!this._notifyOnComplete) {
250+
this._modelChanged.emit(this._model);
251+
}
235252
break;
236253
case 'status':
237254
const executionState = (message.content as any).execution_state as KernelMessage.Status;

0 commit comments

Comments
 (0)