forked from DonJayamanne/pythonVSCode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkernel-manager.ts
More file actions
189 lines (171 loc) · 7.61 KB
/
Copy pathkernel-manager.ts
File metadata and controls
189 lines (171 loc) · 7.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
import * as os from 'os';
import * as vscode from 'vscode';
import { Kernel } from './kernel';
import { KernelspecMetadata, Kernelspec } from './contracts';
import { EventEmitter } from 'events';
import { PythonSettings } from '../common/configSettings';
import { formatErrorForLogging } from '../common/utils';
import { JupyterClientAdapter } from './jupyter_client/main';
import { JupyterClientKernel } from './jupyter_client-Kernel';
import { KernelRestartedError, KernelShutdownError } from './common/errors';
const pythonSettings = PythonSettings.getInstance();
export class KernelManagerImpl extends EventEmitter {
private _runningKernels: Map<string, Kernel>;
private _kernelSpecs: { [key: string]: Kernelspec };
private disposables: vscode.Disposable[];
constructor(private outputChannel: vscode.OutputChannel, private jupyterClient: JupyterClientAdapter) {
super();
this.disposables = [];
this._runningKernels = new Map<string, Kernel>();
this._kernelSpecs = {};
}
public dispose() {
this.removeAllListeners();
this._runningKernels.forEach(kernel => {
kernel.dispose();
});
this._runningKernels.clear();
this.jupyterClient.dispose();
}
public setRunningKernelFor(language: string, kernel: Kernel) {
kernel.kernelSpec.language = language;
this._runningKernels.set(language, kernel);
this.emit('kernelChanged', kernel, language);
return kernel;
}
public destroyRunningKernelFor(language: string) {
if (!this._runningKernels.has(language)) {
return;
}
const kernel = this._runningKernels.get(language);
this._runningKernels.delete(language);
if (kernel) {
kernel.dispose();
}
}
public restartRunningKernelFor(language: string): Promise<Kernel> {
const kernel = this._runningKernels.get(language);
let startupPromise: Promise<Kernel>;
// if (kernel instanceof WSKernel) {
// startupPromise = new Promise<Kernel>((resolve, reject) => {
// kernel.restart().then(() => {
// resolve(kernel);
// }, reject.bind(this));
// });
// }
if (kernel instanceof JupyterClientKernel) {
startupPromise = kernel.shutdown(true).then(() => kernel);
}
if (!startupPromise) {
vscode.window.showWarningMessage('Cannot restart this kernel');
startupPromise = Promise.resolve(kernel);
}
return startupPromise.catch(reason => {
let message = 'Failed to start the kernel.';
if (reason && reason.message) {
message = reason.message;
}
vscode.window.showErrorMessage(message);
this.outputChannel.appendLine(formatErrorForLogging(reason));
return Promise.reject(reason);
});
}
public startKernelFor(language: string): Promise<Kernel> {
return this.getKernelSpecFor(language).then(kernelSpec => {
return this.startKernel(kernelSpec, language);
});
}
public startExistingKernel(language: string, connection, connectionFile): Promise<Kernel> {
throw new Error('Start Existing Kernel not implemented');
}
public async startKernel(kernelSpec: KernelspecMetadata, language: string): Promise<Kernel> {
this.destroyRunningKernelFor(language);
const kernelInfo = await this.jupyterClient.startKernel(kernelSpec);
const kernelUUID = kernelInfo[0];
const config = kernelInfo[1];
const connectionFile = kernelInfo[2];
const kernel = new JupyterClientKernel(kernelSpec, language, config, connectionFile, kernelUUID, this.jupyterClient);
this.setRunningKernelFor(language, kernel);
await this.executeStartupCode(kernel);
return kernel;
}
private executeStartupCode(kernel: Kernel): Promise<any> {
if (pythonSettings.jupyter.startupCode.length === 0) {
return Promise.resolve();
}
const suffix = ' ' + os.EOL;
let startupCode = pythonSettings.jupyter.startupCode.join(suffix) + suffix;
return new Promise<any>((resolve, reject) => {
let errorMessage = 'Failed to execute kernel startup code. ';
kernel.execute(startupCode).subscribe(result => {
if (result.stream === 'error' && result.type === 'text' && typeof result.message === 'string') {
errorMessage += 'Details: ' + result.message;
}
if (result.stream === 'status' && result.type === 'text' && result.data === 'error') {
this.outputChannel.appendLine(errorMessage);
vscode.window.showWarningMessage(errorMessage);
}
}, reason => {
if (reason instanceof KernelRestartedError || reason instanceof KernelShutdownError) {
return resolve();
}
// It doesn't matter if startup code execution Failed
// Possible they have placed some stuff that is invalid or we have some missing packages (e.g. matplot lib)
this.outputChannel.appendLine(formatErrorForLogging(reason));
vscode.window.showWarningMessage(errorMessage);
resolve();
}, () => {
resolve();
});
});
}
public getAllRunningKernels() {
return this._runningKernels;
}
public getRunningKernelFor(language: string) {
return this._runningKernels.has(language) ? this._runningKernels.get(language) : null;
}
public getAllKernelSpecs(): Promise<KernelspecMetadata[]> {
if (Object.keys(this._kernelSpecs).length === 0) {
return this.updateKernelSpecs().then(() => {
return Object.keys(this._kernelSpecs).map(key => this._kernelSpecs[key].spec);
});
} else {
const result = Object.keys(this._kernelSpecs).map(key => this._kernelSpecs[key].spec);
return Promise.resolve(result);
}
}
public getAllKernelSpecsFor(language: string): Promise<KernelspecMetadata[]> {
return this.getAllKernelSpecs().then(kernelSpecs => {
const lowerLang = language.toLowerCase();
return kernelSpecs.filter(spec => spec.language.toLowerCase() === lowerLang);
});
}
public getKernelSpecFor(language: string): Promise<KernelspecMetadata> {
return this.getAllKernelSpecsFor(language).then(kernelSpecs => {
if (kernelSpecs.length === 0) {
throw new Error('Unable to find a kernel for ' + language);
}
if (pythonSettings.jupyter.defaultKernel.length > 0) {
const defaultKernel = kernelSpecs.find(spec => spec.display_name === pythonSettings.jupyter.defaultKernel);
if (defaultKernel) {
return defaultKernel;
}
}
return kernelSpecs[0];
});
}
public updateKernelSpecs(): Promise<{ [key: string]: Kernelspec }> {
this._kernelSpecs = {};
return this.getKernelSpecsFromJupyter().then(kernelSpecsFromJupyter => {
this._kernelSpecs = kernelSpecsFromJupyter;
if (Object.keys(this._kernelSpecs).length === 0) {
throw new Error('No kernel specs found, Install or update IPython/Jupyter to a later version');
}
return this._kernelSpecs;
});
}
public getKernelSpecsFromJupyter(): Promise<any> {
return this.jupyterClient.getAllKernelSpecs();
}
}