Преглед изворни кода

Clean up the handling of execution

Steven Silvester пре 8 година
родитељ
комит
c8665f673d

+ 39 - 51
packages/outputarea/src/widget.ts

@@ -17,10 +17,6 @@ import {
   Widget
 } from '@phosphor/widgets';
 
-import {
-  IClientSession
-} from '@jupyterlab/apputils';
-
 import {
   nbformat
 } from '@jupyterlab/coreutils';
@@ -153,7 +149,7 @@ class OutputArea extends Widget {
 
   /**
    * A public signal used to indicate the number of outputs has changed.
-   * 
+   *
    * #### Notes
    * This is useful for parents who want to apply styling based on the number
    * of outputs. Emits the current number of outputs.
@@ -161,25 +157,9 @@ class OutputArea extends Widget {
   readonly outputLengthChanged = new Signal<this, number>(this);
 
   /**
-   * Execute code on a client session and handle response messages.
+   * Clear the output area.
    */
-  execute(code: string, session: IClientSession): Promise<KernelMessage.IExecuteReplyMsg> {
-    // Bail if the model is disposed.
-    if (this.model.isDisposed) {
-      return Promise.reject('Model is disposed');
-    }
-
-    // Bail if there is no kernel.
-    let kernel = session.kernel;
-    if (!kernel) {
-      return Promise.reject('No kernel exists on the session');
-    }
-
-    // Override the default for `stop_on_error`.
-    let content: KernelMessage.IExecuteRequest = {
-      code,
-      stop_on_error: true
-    };
+  clear(): void {
     this.model.clear();
 
     // Make sure there were no input widgets.
@@ -187,25 +167,33 @@ class OutputArea extends Widget {
       this._clear();
       this.outputLengthChanged.emit(this.model.length);
     }
+  }
 
-    return new Promise<KernelMessage.IExecuteReplyMsg>((resolve, reject) => {
-      let future = kernel.requestExecute(content);
-      // Handle published messages.
-      future.onIOPub = (msg: KernelMessage.IIOPubMessage) => {
-        this._onIOPub(msg);
-      };
-      // Handle the execute reply.
-      future.onReply = (msg: KernelMessage.IExecuteReplyMsg) => {
-        this._onExecuteReply(msg);
-        resolve(msg);
-      };
-      // Handle stdin.
-      future.onStdin = (msg: KernelMessage.IStdinMessage) => {
-        if (KernelMessage.isInputRequestMsg(msg)) {
-          this._onInputRequest(msg, session);
-        }
-      };
-    });
+  /**
+   * Handle messages from code execution.
+   */
+  handleExecution(future: Kernel.IFuture): Promise<void> {
+    // Bail if the model is disposed.
+    if (this.model.isDisposed) {
+      return Promise.reject('Model is disposed');
+    }
+
+    // Handle published messages.
+    future.onIOPub = (msg: KernelMessage.IIOPubMessage) => {
+      this._onIOPub(msg);
+    };
+    // Handle the execute reply.
+    future.onReply = (msg: KernelMessage.IExecuteReplyMsg) => {
+      this._onExecuteReply(msg);
+    };
+    // Handle stdin.
+    future.onStdin = (msg: KernelMessage.IStdinMessage) => {
+      if (KernelMessage.isInputRequestMsg(msg)) {
+        this._onInputRequest(msg, future);
+      }
+    };
+
+    return future.done;
   }
 
   /**
@@ -321,7 +309,7 @@ class OutputArea extends Widget {
   /**
    * Handle an input request from a kernel.
    */
-  private _onInputRequest(msg: KernelMessage.IInputRequestMsg, session: IClientSession): void {
+  private _onInputRequest(msg: KernelMessage.IInputRequestMsg, future: Kernel.IFuture): void {
     // Add an output widget to the end.
     let factory = this.contentFactory;
     let stdinPrompt = msg.content.prompt;
@@ -335,8 +323,7 @@ class OutputArea extends Widget {
     prompt.addClass(OUTPUT_AREA_PROMPT_CLASS);
     panel.addWidget(prompt);
 
-    let kernel = session.kernel;
-    let input = factory.createStdin({ prompt: stdinPrompt, password, kernel });
+    let input = factory.createStdin({ prompt: stdinPrompt, password, future });
     input.addClass(OUTPUT_AREA_OUTPUT_CLASS);
     panel.addWidget(input);
 
@@ -421,8 +408,8 @@ namespace OutputArea {
 
   /**
    * An output area widget content factory.
-   * 
-   * The content factory is used to create children in a way 
+   *
+   * The content factory is used to create children in a way
    * that can be customized.
    */
   export
@@ -542,7 +529,7 @@ class Stdin extends Widget implements IStdin {
     if (options.password) {
       this._input.type = 'password';
     }
-    this._kernel = options.kernel;
+    this._future = options.future;
   }
 
   /**
@@ -559,7 +546,7 @@ class Stdin extends Widget implements IStdin {
     let input = this._input;
     if (event.type === 'keydown') {
       if ((event as KeyboardEvent).keyCode === 13) {  // Enter
-        this._kernel.sendInputReply({
+        this._future.sendInputReply({
           value: input.value
         });
         let rendered = document.createElement('span');
@@ -596,10 +583,11 @@ class Stdin extends Widget implements IStdin {
     this._input.removeEventListener('keydown', this);
   }
 
-  private _kernel: Kernel.IKernelConnection = null;
+  private _future: Kernel.IFuture = null;
   private _input: HTMLInputElement = null;
 }
 
+
 export
 namespace Stdin {
   /**
@@ -618,9 +606,9 @@ namespace Stdin {
     password: boolean;
 
     /**
-     * The kernel associated with the request.
+     * The kernel future associated with the request.
      */
-    kernel: Kernel.IKernelConnection;
+    future: Kernel.IFuture;
   }
 }
 

+ 1 - 1
packages/services/src/kernel/default.ts

@@ -266,7 +266,7 @@ class DefaultKernel implements Kernel.IKernel {
     }
     let future = new KernelFutureHandler(() => {
       this._futures.delete(msg.header.msg_id);
-    }, msg, expectReply, disposeOnDone);
+    }, msg, expectReply, disposeOnDone, this);
     this._futures.set(msg.header.msg_id, future);
     return future;
   }

+ 22 - 23
packages/services/src/kernel/future.ts

@@ -1,6 +1,10 @@
 // Copyright (c) Jupyter Development Team.
 // Distributed under the terms of the Modified BSD License.
 
+import {
+  PromiseDelegate
+} from '@phosphor/coreutils';
+
 import {
   DisposableDelegate
 } from '@phosphor/disposable';
@@ -22,13 +26,14 @@ class KernelFutureHandler extends DisposableDelegate implements Kernel.IFuture {
   /**
    * Construct a new KernelFutureHandler.
    */
-  constructor(cb: () => void, msg: KernelMessage.IShellMessage, expectShell: boolean, disposeOnDone: boolean) {
+  constructor(cb: () => void, msg: KernelMessage.IShellMessage, expectShell: boolean, disposeOnDone: boolean, kernel: Kernel.IKernel) {
     super(cb);
     this._msg = msg;
     if (!expectShell) {
       this._setFlag(Private.KernelFutureFlag.GotReply);
     }
     this._disposeOnDone = disposeOnDone;
+    this._kernel = kernel;
   }
 
   /**
@@ -39,10 +44,10 @@ class KernelFutureHandler extends DisposableDelegate implements Kernel.IFuture {
   }
 
   /**
-   * Check for message done state.
+   * A promise that resolves when the future is done.
    */
-  get isDone(): boolean {
-    return this._testFlag(Private.KernelFutureFlag.IsDone);
+  get done(): Promise<void> {
+    return this._done.promise;
   }
 
   /**
@@ -73,20 +78,6 @@ class KernelFutureHandler extends DisposableDelegate implements Kernel.IFuture {
     this._iopub = cb;
   }
 
-  /**
-   * Get the done handler.
-   */
-  get onDone(): () => void  {
-    return this._done;
-  }
-
-  /**
-   * Set the done handler.
-   */
-  set onDone(cb: () => void) {
-    this._done = cb;
-  }
-
   /**
    * Get the stdin handler.
    */
@@ -133,6 +124,14 @@ class KernelFutureHandler extends DisposableDelegate implements Kernel.IFuture {
     this._hooks.remove(hook);
   }
 
+
+  /**
+   * Send an `input_reply` message.
+   */
+  sendInputReply(content: KernelMessage.IInputReply): void {
+    this._kernel.sendInputReply(content);
+  }
+
   /**
    * Dispose and unregister the future.
    */
@@ -144,6 +143,7 @@ class KernelFutureHandler extends DisposableDelegate implements Kernel.IFuture {
     this._msg = null;
     if (this._hooks) { this._hooks.dispose(); }
     this._hooks = null;
+    this._kernel = null;
     super.dispose();
   }
 
@@ -192,13 +192,11 @@ class KernelFutureHandler extends DisposableDelegate implements Kernel.IFuture {
   }
 
   private _handleDone(): void {
-    if (this.isDone) {
+    if (this._testFlag(Private.KernelFutureFlag.IsDone)) {
       return;
     }
     this._setFlag(Private.KernelFutureFlag.IsDone);
-    let done = this._done;
-    if (done) done();
-    this._done = null;
+    this._done.resolve(void 0);
     if (this._disposeOnDone) {
       this.dispose();
     }
@@ -223,9 +221,10 @@ class KernelFutureHandler extends DisposableDelegate implements Kernel.IFuture {
   private _stdin: (msg: KernelMessage.IStdinMessage) => void = null;
   private _iopub: (msg: KernelMessage.IIOPubMessage) => void = null;
   private _reply: (msg: KernelMessage.IShellMessage) => void = null;
-  private _done: () => void = null;
+  private _done = new PromiseDelegate<void>();
   private _hooks = new Private.HookList<KernelMessage.IIOPubMessage>();
   private _disposeOnDone = true;
+  private _kernel: Kernel.IKernel;
 }
 
 namespace Private {

+ 7 - 7
packages/services/src/kernel/kernel.ts

@@ -670,9 +670,9 @@ namespace Kernel {
     readonly msg: KernelMessage.IShellMessage;
 
     /**
-     * Whether the future is done.
+     * A promise that resolves when the future is done.
      */
-    readonly isDone: boolean;
+    readonly done: Promise<void>;
 
     /**
      * The reply handler for the kernel future.
@@ -689,11 +689,6 @@ namespace Kernel {
      */
     onIOPub: (msg: KernelMessage.IIOPubMessage) => void;
 
-    /**
-     * The done handler for the kernel future.
-     */
-    onDone: () => void;
-
     /**
      * Register hook for IOPub messages.
      *
@@ -718,6 +713,11 @@ namespace Kernel {
      * If a hook is removed during the hook processing, it will be deactivated immediately.
      */
     removeMessageHook(hook: (msg: KernelMessage.IIOPubMessage) => boolean): void;
+
+    /**
+     * Send an `input_reply` message.
+     */
+    sendInputReply(content: KernelMessage.IInputReply): void;
   }
 
   /**