22// Licensed under the MIT License.
33'use strict' ;
44
5- import { inject , injectable } from 'inversify' ;
5+ import { inject , injectable , named } from 'inversify' ;
66import * as path from 'path' ;
77import { InterpreterUri } from '../../common/installer/types' ;
88import { traceError , traceInfo } from '../../common/logger' ;
99import { IFileSystem , IPlatformService } from '../../common/platform/types' ;
1010import { IExtensionContext , IPathUtils , Resource } from '../../common/types' ;
1111import { isResource } from '../../common/utils/misc' ;
12- import { IInterpreterService , PythonInterpreter } from '../../interpreter/contracts' ;
12+ import {
13+ IInterpreterLocatorService ,
14+ IInterpreterService ,
15+ KNOWN_PATH_SERVICE ,
16+ PythonInterpreter
17+ } from '../../interpreter/contracts' ;
1318import { IJupyterKernelSpec } from '../types' ;
1419import { IKernelFinder } from './types' ;
1520
@@ -38,6 +43,9 @@ export class KernelFinder implements IKernelFinder {
3843
3944 constructor (
4045 @inject ( IInterpreterService ) private interpreterService : IInterpreterService ,
46+ @inject ( IInterpreterLocatorService )
47+ @named ( KNOWN_PATH_SERVICE )
48+ private readonly interpreterLocator : IInterpreterLocatorService ,
4149 @inject ( IPlatformService ) private platformService : IPlatformService ,
4250 @inject ( IFileSystem ) private file : IFileSystem ,
4351 @inject ( IPathUtils ) private readonly pathUtils : IPathUtils ,
@@ -62,20 +70,24 @@ export class KernelFinder implements IKernelFinder {
6270 }
6371
6472 if ( kernelSpec ) {
73+ // tslint:disable-next-line: no-floating-promises
74+ this . writeCache ( this . cache ) ;
6575 return kernelSpec ;
6676 }
6777
68- const kernelSearches = [
69- this . interpreterService . getInterpreters ( resource ) . then ( ( interpreters ) => {
70- const interpreterPaths = interpreters . map ( ( interp ) => interp . path ) ;
71- return this . findInterpreterPath ( interpreterPaths , kernelName ) ;
72- } ) ,
73- this . findDiskPath ( kernelName )
74- ] ;
78+ const diskSearch = this . findDiskPath ( kernelName ) ;
79+ const interpreterSearch = this . interpreterLocator . getInterpreters ( resource , false ) . then ( ( interpreters ) => {
80+ const interpreterPaths = interpreters . map ( ( interp ) => interp . path ) ;
81+ return this . findInterpreterPath ( interpreterPaths , kernelName ) ;
82+ } ) ;
83+
84+ let result = await Promise . race ( [ diskSearch , interpreterSearch ] ) ;
85+ if ( ! result ) {
86+ const both = await Promise . all ( [ diskSearch , interpreterSearch ] ) ;
87+ result = both [ 0 ] ? both [ 0 ] : both [ 1 ] ;
88+ }
7589
76- const result = await Promise . all ( kernelSearches ) ;
77- const spec = result . find ( ( sp ) => sp ?. name === kernelName ) ;
78- foundKernel = spec ? spec : await this . getDefaultKernelSpec ( resource ) ;
90+ foundKernel = result ? result : await this . getDefaultKernelSpec ( resource ) ;
7991 } else {
8092 foundKernel = await this . getDefaultKernelSpec ( resource ) ;
8193 }
@@ -87,7 +99,7 @@ export class KernelFinder implements IKernelFinder {
8799
88100 private async getKernelSpecFromActiveInterpreter (
89101 resource : Resource ,
90- kernelName ? : string
102+ kernelName : string
91103 ) : Promise < IJupyterKernelSpec | undefined > {
92104 this . activeInterpreter = await this . interpreterService . getActiveInterpreter ( resource ) ;
93105
@@ -99,47 +111,15 @@ export class KernelFinder implements IKernelFinder {
99111 }
100112 }
101113
102- private async getKernelSpec ( kernelPath : string , kernelName ? : string ) : Promise < IJupyterKernelSpec | undefined > {
114+ private async getKernelSpec ( kernelPath : string , kernelName : string ) : Promise < IJupyterKernelSpec | undefined > {
103115 try {
104- const kernels = await this . file . getSubDirectories ( kernelPath ) ;
116+ const paths = await this . file . getSubDirectories ( kernelPath ) ;
105117
106- if ( kernels . length === 0 ) {
118+ if ( paths . length === 0 ) {
107119 return undefined ;
108120 }
109121
110- // If no kernel name is included, return the first kernel
111- if ( ! kernelName ) {
112- try {
113- const kernelSpec : IJupyterKernelSpec = JSON . parse (
114- await this . file . readFile ( path . join ( kernels [ 0 ] , 'kernel.json' ) )
115- ) ;
116- this . cache . push ( kernelSpec ) ;
117- return kernelSpec ;
118- } catch ( e ) {
119- traceError ( 'Invalid kernel.json' , e ) ;
120- return undefined ;
121- }
122- }
123-
124- let spec : IJupyterKernelSpec | undefined ;
125- const promises = kernels . map ( async ( kernel ) => {
126- try {
127- const kernelSpec : IJupyterKernelSpec = JSON . parse (
128- await this . file . readFile ( path . join ( kernel , 'kernel.json' ) )
129- ) ;
130- this . cache . push ( kernelSpec ) ;
131- if ( kernelSpec . name === kernelName ) {
132- spec = kernelSpec ;
133- }
134- return kernelSpec ;
135- } catch ( e ) {
136- traceError ( 'Invalid kernel.json' , e ) ;
137- return undefined ;
138- }
139- } ) ;
140-
141- await Promise . all ( promises ) ;
142- return spec ;
122+ return this . getKernelSpecFromDisk ( paths , kernelName ) ;
143123 } catch {
144124 traceInfo ( `The path ${ kernelPath } does not exist.` ) ;
145125 return undefined ;
0 commit comments