(code: string, session: IKernelSession)
| 157 | } |
| 158 | |
| 159 | private async execute(code: string, session: IKernelSession) { |
| 160 | if (!session.kernel) { |
| 161 | const error = new Error('No kernel available to execute code'); |
| 162 | this._done.resolve(); |
| 163 | throw error; |
| 164 | } |
| 165 | traceExecMessage(this.extensionId, this.executionId, 'Send code for execution'); |
| 166 | |
| 167 | const kernelConnection = session.kernel; |
| 168 | try { |
| 169 | this.started = true; |
| 170 | this._onRequestSent.fire(); |
| 171 | traceExecMessage(this.extensionId, this.executionId, `Execution Request Sent to Kernel`); |
| 172 | // For Jupyter requests, silent === don't output, while store_history === don't update execution count |
| 173 | // https://jupyter-client.readthedocs.io/en/stable/api/client.html#jupyter_client.KernelClient.execute |
| 174 | this.request = executeSilentlyAndEmitOutput( |
| 175 | kernelConnection, |
| 176 | code, |
| 177 | () => this._onRequestAcknowledge.fire(), |
| 178 | (output) => this._onDidEmitOutput.fire(output) |
| 179 | ); |
| 180 | // Don't want dangling promises. |
| 181 | this.request.done.then(noop, noop); |
| 182 | } catch (ex) { |
| 183 | logger.error(`Code execution failed without request, for exec ${this.executionId}`, ex); |
| 184 | this._completed = true; |
| 185 | this._done.reject(ex); |
| 186 | return; |
| 187 | } |
| 188 | |
| 189 | // WARNING: Do not dispose `request`. |
| 190 | // Even after request.done & execute_reply is sent we could have more messages coming from iopub. |
| 191 | // E.g. background threads. |
| 192 | |
| 193 | try { |
| 194 | // When the request finishes we are done |
| 195 | // request.done resolves even before all iopub messages have been sent through. |
| 196 | // Solution is to wait for all messages to get processed. |
| 197 | const response = await this.request!.done; |
| 198 | this._completed = true; |
| 199 | if (response.content.status === 'error') { |
| 200 | traceExecMessage(this.extensionId, this.executionId, 'Executed with errors'); |
| 201 | this._done.reject(new KernelError(response.content)); |
| 202 | } else { |
| 203 | traceExecMessage(this.extensionId, this.executionId, 'Executed successfully'); |
| 204 | this._done.resolve(); |
| 205 | } |
| 206 | } catch (ex) { |
| 207 | this._completed = true; |
| 208 | if (this.cancelHandled) { |
| 209 | return; |
| 210 | } |
| 211 | if (!this.disposed && !this.cancelRequested) { |
| 212 | // @jupyterlab/services throws a `Canceled` error when the kernel is interrupted. |
| 213 | // Or even when the kernel dies when running a cell with the code `os.kill(os.getpid(), 9)` |
| 214 | logger.error(`Error in waiting for code ${this.executionId} to complete`, ex); |
| 215 | } |
| 216 | this._done.reject(ex); |
no test coverage detected