@@ -79,7 +79,7 @@ export class KernelService {
79
79
*/
80
80
public async findMatchingKernelSpec (
81
81
interpreter : PythonInterpreter ,
82
- sessionManager : IJupyterSessionManager | undefined ,
82
+ sessionManager ? : IJupyterSessionManager | undefined ,
83
83
cancelToken ?: CancellationToken
84
84
) : Promise < IJupyterKernelSpec | undefined > ;
85
85
public async findMatchingKernelSpec (
@@ -118,7 +118,7 @@ export class KernelService {
118
118
}
119
119
120
120
// Now enumerate them again
121
- const enumerator = sessionManager ? ( ) => sessionManager . getActiveKernelSpecs ( ) : ( ) => this . enumerateSpecs ( cancelToken ) ;
121
+ const enumerator = sessionManager ? ( ) => sessionManager . getKernelSpecs ( ) : ( ) => this . enumerateSpecs ( cancelToken ) ;
122
122
123
123
// Then find our match
124
124
return this . findSpecMatch ( enumerator ) ;
@@ -132,6 +132,7 @@ export class KernelService {
132
132
}
133
133
}
134
134
}
135
+
135
136
/**
136
137
* Registers an interprter as a kernel.
137
138
* The assumption is that `ipykernel` has been installed in the interpreter.
@@ -147,40 +148,64 @@ export class KernelService {
147
148
*/
148
149
@captureTelemetry ( Telemetry . RegisterInterpreterAsKernel , undefined , true )
149
150
@traceDecorators . error ( 'Failed to register an interpreter as a kernel' )
150
- public async registerKernel ( interpreter : PythonInterpreter , cancelToken ?: CancellationToken ) : Promise < IJupyterKernelSpec > {
151
- if ( ! interpreter . displayName ) {
151
+ public async registerKernel ( interpreter : PythonInterpreter , cancelToken ?: CancellationToken ) : Promise < IJupyterKernelSpec | undefined > {
152
+ if ( ! interpreter . displayName ) {
152
153
throw new Error ( 'Interpreter does not have a display name' ) ;
153
154
}
154
155
const ipykernelCommand = await this . commandFinder . findBestCommand ( JupyterCommands . KernelCreateCommand , cancelToken ) ;
155
- if ( ipykernelCommand . status === ModuleExistsStatus . NotFound || ! ipykernelCommand . command ) {
156
+ if ( ipykernelCommand . status === ModuleExistsStatus . NotFound || ! ipykernelCommand . command ) {
156
157
throw new Error ( 'Command not found to install the kernel' ) ;
157
158
}
159
+ if ( Cancellation . isCanceled ( cancelToken ) ) {
160
+ return ;
161
+ }
158
162
const name = await this . generateKernelNameForIntepreter ( interpreter ) ;
159
163
const output = await ipykernelCommand . command . exec ( [ 'install' , '--user' , '--name' , name , '--display-name' , interpreter . displayName ] , {
160
164
throwOnStdErr : true ,
161
165
encoding : 'utf8' ,
162
166
token : cancelToken
163
167
} ) ;
164
- const kernel = await this . findMatchingKernelSpec ( { display_name : interpreter . displayName , name} , undefined , cancelToken ) ;
165
- if ( ! kernel ) {
168
+ if ( Cancellation . isCanceled ( cancelToken ) ) {
169
+ return ;
170
+ }
171
+
172
+ const kernel = await this . findMatchingKernelSpec ( { display_name : interpreter . displayName , name } , undefined , cancelToken ) ;
173
+ if ( Cancellation . isCanceled ( cancelToken ) ) {
174
+ return ;
175
+ }
176
+ if ( ! kernel ) {
166
177
const error = `Kernel not created with the name ${ name } , display_name ${ interpreter . displayName } . Output is ${ output . stdout } ` ;
167
178
throw new Error ( error ) ;
168
179
}
169
180
if ( ! ( kernel instanceof JupyterKernelSpec ) ) {
170
181
const error = `Kernel not registered locally, created with the name ${ name } , display_name ${ interpreter . displayName } . Output is ${ output . stdout } ` ;
171
182
throw new Error ( error ) ;
172
183
}
173
- if ( ! kernel . specFile ) {
184
+ if ( ! kernel . specFile ) {
174
185
const error = `kernel.json not created with the name ${ name } , display_name ${ interpreter . displayName } . Output is ${ output . stdout } ` ;
175
186
throw new Error ( error ) ;
176
187
}
177
188
const specModel : ReadWrite < Kernel . ISpecModel > = JSON . parse ( await this . fileSystem . readFile ( kernel . specFile ) ) ;
178
189
190
+ // Ensure we use a fully qualified path to the python interpreter in `argv`.
191
+ if ( specModel . argv [ 0 ] . toLowerCase ( ) === 'conda' ) {
192
+ // If conda is the first word, its possible its a conda activation command.
193
+ traceInfo ( `Spec argv[0], not updated as it is using conda.` ) ;
194
+ } else {
195
+ traceInfo ( `Spec argv[0] updated from '${ specModel . argv [ 0 ] } ' to '${ interpreter . path } '` ) ;
196
+ specModel . argv [ 0 ] = interpreter . path ;
197
+ }
198
+
179
199
// Get the activated environment variables (as a work around for `conda run` and similar).
180
200
// This ensures the code runs within the context of an activated environment.
181
- specModel . env = await this . activationHelper . getActivatedEnvironmentVariables ( undefined , interpreter , true )
182
- // tslint:disable-next-line: no-any
183
- . catch ( noop ) . then ( env => ( env || { } ) as any ) ;
201
+ specModel . env = await this . activationHelper
202
+ . getActivatedEnvironmentVariables ( undefined , interpreter , true )
203
+ . catch ( noop )
204
+ // tslint:disable-next-line: no-any
205
+ . then ( env => ( env || { } ) as any ) ;
206
+ if ( Cancellation . isCanceled ( cancelToken ) ) {
207
+ return ;
208
+ }
184
209
185
210
// Ensure we update the metadata to include interpreter stuff as well (we'll use this to search kernels that match an interpreter).
186
211
// We'll need information such as interpreter type, display name, path, etc...
@@ -193,6 +218,7 @@ export class KernelService {
193
218
await this . fileSystem . writeFile ( kernel . specFile , JSON . stringify ( specModel , undefined , 2 ) ) ;
194
219
kernel . metadata = specModel . metadata ;
195
220
221
+ traceInfo ( `Kernel successfully registered for ${ interpreter . path } with the name=${ name } and spec can be found here ${ kernel . specFile } ` ) ;
196
222
return kernel ;
197
223
}
198
224
/**
@@ -208,7 +234,7 @@ export class KernelService {
208
234
return `${ interpreter . displayName || '' } _${ await this . fileSystem . getFileHash ( interpreter . path ) } ` . replace ( / [ ^ A - Z a - z 0 - 9 ] / g, '' ) ;
209
235
}
210
236
private async getKernelSpecs ( sessionManager ?: IJupyterSessionManager , cancelToken ?: CancellationToken ) : Promise < IJupyterKernelSpec [ ] > {
211
- const enumerator = sessionManager ? sessionManager . getActiveKernelSpecs ( ) : this . enumerateSpecs ( cancelToken ) ;
237
+ const enumerator = sessionManager ? sessionManager . getKernelSpecs ( ) : this . enumerateSpecs ( cancelToken ) ;
212
238
if ( Cancellation . isCanceled ( cancelToken ) ) {
213
239
return [ ] ;
214
240
}
@@ -402,21 +428,23 @@ export class KernelService {
402
428
traceInfo ( 'Parsing kernelspecs from jupyter' ) ;
403
429
// This should give us back a key value pair we can parse
404
430
const kernelSpecs = JSON . parse ( output . stdout . trim ( ) ) as Record < string , { resource_dir : string ; spec : Omit < Kernel . ISpecModel , 'name' > } > ;
405
- const specs = await Promise . all ( Object . keys ( kernelSpecs ) . map ( async kernelName => {
406
- const specFile = path . join ( kernelSpecs [ kernelName ] . resource_dir , 'kernel.json' ) ;
407
- const spec = kernelSpecs [ kernelName ] . spec ;
408
- // Add the missing name property.
409
- const model = {
410
- ...spec ,
411
- name : kernelName
412
- } ;
413
- // Check if the spec file exists.
414
- if ( await this . fileSystem . fileExists ( specFile ) ) {
415
- return new JupyterKernelSpec ( model as Kernel . ISpecModel , specFile ) ;
416
- } else {
417
- return ;
418
- }
419
- } ) ) ;
431
+ const specs = await Promise . all (
432
+ Object . keys ( kernelSpecs ) . map ( async kernelName => {
433
+ const specFile = path . join ( kernelSpecs [ kernelName ] . resource_dir , 'kernel.json' ) ;
434
+ const spec = kernelSpecs [ kernelName ] . spec ;
435
+ // Add the missing name property.
436
+ const model = {
437
+ ...spec ,
438
+ name : kernelName
439
+ } ;
440
+ // Check if the spec file exists.
441
+ if ( await this . fileSystem . fileExists ( specFile ) ) {
442
+ return new JupyterKernelSpec ( model as Kernel . ISpecModel , specFile ) ;
443
+ } else {
444
+ return ;
445
+ }
446
+ } )
447
+ ) ;
420
448
return specs . filter ( item => ! ! item ) . map ( item => item as JupyterKernelSpec ) ;
421
449
} catch ( ex ) {
422
450
traceError ( 'Failed to list kernels' , ex ) ;
0 commit comments