11// Copyright (c) Microsoft Corporation. All rights reserved.
22// Licensed under the MIT License.
33
4- import { Disposable , EventEmitter , Event , workspace , window , Uri } from 'vscode' ;
4+ import { Disposable , EventEmitter , Event , Uri } from 'vscode' ;
55import * as ch from 'child_process' ;
66import * as path from 'path' ;
77import * as rpc from 'vscode-jsonrpc/node' ;
@@ -12,10 +12,16 @@ import { createDeferred, createDeferredFrom } from '../../../../common/utils/asy
1212import { DisposableBase , DisposableStore } from '../../../../common/utils/resourceLifecycle' ;
1313import { DEFAULT_INTERPRETER_PATH_SETTING_KEY } from '../lowLevel/customWorkspaceLocator' ;
1414import { noop } from '../../../../common/utils/misc' ;
15- import { getConfiguration } from '../../../../common/vscodeApis/workspaceApis' ;
15+ import {
16+ getConfiguration ,
17+ getWorkspaceFolderPaths ,
18+ getWorkspaceFolders ,
19+ } from '../../../../common/vscodeApis/workspaceApis' ;
1620import { CONDAPATH_SETTING_KEY } from '../../../common/environmentManagers/conda' ;
1721import { VENVFOLDERS_SETTING_KEY , VENVPATH_SETTING_KEY } from '../lowLevel/customVirtualEnvLocator' ;
1822import { getUserHomeDir } from '../../../../common/utils/platform' ;
23+ import { createLogOutputChannel } from '../../../../common/vscodeApis/windowApis' ;
24+ import { PythonEnvKind } from '../../info' ;
1925
2026const untildify = require ( 'untildify' ) ;
2127
@@ -48,6 +54,7 @@ export interface NativeEnvManagerInfo {
4854export interface NativeGlobalPythonFinder extends Disposable {
4955 resolve ( executable : string ) : Promise < NativeEnvInfo > ;
5056 refresh ( ) : AsyncIterable < NativeEnvInfo > ;
57+ categoryToKind ( category : string ) : PythonEnvKind ;
5158}
5259
5360interface NativeLog {
@@ -60,7 +67,7 @@ class NativeGlobalPythonFinderImpl extends DisposableBase implements NativeGloba
6067
6168 private firstRefreshResults : undefined | ( ( ) => AsyncGenerator < NativeEnvInfo , void , unknown > ) ;
6269
63- private readonly outputChannel = this . _register ( window . createOutputChannel ( 'Python Locator' , { log : true } ) ) ;
70+ private readonly outputChannel = this . _register ( createLogOutputChannel ( 'Python Locator' , { log : true } ) ) ;
6471
6572 constructor ( ) {
6673 super ( ) ;
@@ -80,6 +87,40 @@ class NativeGlobalPythonFinderImpl extends DisposableBase implements NativeGloba
8087 return environment ;
8188 }
8289
90+ categoryToKind ( category : string ) : PythonEnvKind {
91+ switch ( category . toLowerCase ( ) ) {
92+ case 'conda' :
93+ return PythonEnvKind . Conda ;
94+ case 'system' :
95+ case 'homebrew' :
96+ case 'mac-python-org' :
97+ case 'mac-command-line-tools' :
98+ case 'windows-registry' :
99+ return PythonEnvKind . System ;
100+ case 'pyenv' :
101+ case 'pyenv-other' :
102+ return PythonEnvKind . Pyenv ;
103+ case 'pipenv' :
104+ return PythonEnvKind . Pipenv ;
105+ case 'pyenv-virtualenv' :
106+ return PythonEnvKind . VirtualEnv ;
107+ case 'venv' :
108+ return PythonEnvKind . Venv ;
109+ case 'virtualenv' :
110+ return PythonEnvKind . VirtualEnv ;
111+ case 'virtualenvwrapper' :
112+ return PythonEnvKind . VirtualEnvWrapper ;
113+ case 'windows-store' :
114+ return PythonEnvKind . MicrosoftStore ;
115+ case 'unknown' :
116+ return PythonEnvKind . Unknown ;
117+ default : {
118+ this . outputChannel . info ( `Unknown Python Environment category '${ category } ' from Native Locator.` ) ;
119+ return PythonEnvKind . Unknown ;
120+ }
121+ }
122+ }
123+
83124 async * refresh ( ) : AsyncIterable < NativeEnvInfo > {
84125 if ( this . firstRefreshResults ) {
85126 // If this is the first time we are refreshing,
@@ -154,16 +195,33 @@ class NativeGlobalPythonFinderImpl extends DisposableBase implements NativeGloba
154195 // eslint-disable-next-line class-methods-use-this
155196 private start ( ) : rpc . MessageConnection {
156197 this . outputChannel . info ( `Starting Python Locator ${ PYTHON_ENV_TOOLS_PATH } server` ) ;
157- const proc = ch . spawn ( PYTHON_ENV_TOOLS_PATH , [ 'server' ] , { env : process . env } ) ;
158- const disposables : Disposable [ ] = [ ] ;
198+
159199 // jsonrpc package cannot handle messages coming through too quickly.
160200 // Lets handle the messages and close the stream only when
161201 // we have got the exit event.
162202 const readable = new PassThrough ( ) ;
163- proc . stdout . pipe ( readable , { end : false } ) ;
164- proc . stderr . on ( 'data' , ( data ) => this . outputChannel . error ( data . toString ( ) ) ) ;
165203 const writable = new PassThrough ( ) ;
166- writable . pipe ( proc . stdin , { end : false } ) ;
204+ const disposables : Disposable [ ] = [ ] ;
205+ try {
206+ const proc = ch . spawn ( PYTHON_ENV_TOOLS_PATH , [ 'server' ] , { env : process . env } ) ;
207+ proc . stdout . pipe ( readable , { end : false } ) ;
208+ proc . stderr . on ( 'data' , ( data ) => this . outputChannel . error ( data . toString ( ) ) ) ;
209+ writable . pipe ( proc . stdin , { end : false } ) ;
210+
211+ disposables . push ( {
212+ dispose : ( ) => {
213+ try {
214+ if ( proc . exitCode === null ) {
215+ proc . kill ( ) ;
216+ }
217+ } catch ( ex ) {
218+ this . outputChannel . error ( 'Error disposing finder' , ex ) ;
219+ }
220+ } ,
221+ } ) ;
222+ } catch ( ex ) {
223+ this . outputChannel . error ( `Error starting Python Finder ${ PYTHON_ENV_TOOLS_PATH } server` , ex ) ;
224+ }
167225 const disposeStreams = new Disposable ( ( ) => {
168226 readable . end ( ) ;
169227 writable . end ( ) ;
@@ -200,17 +258,6 @@ class NativeGlobalPythonFinderImpl extends DisposableBase implements NativeGloba
200258 connection . onClose ( ( ) => {
201259 disposables . forEach ( ( d ) => d . dispose ( ) ) ;
202260 } ) ,
203- {
204- dispose : ( ) => {
205- try {
206- if ( proc . exitCode === null ) {
207- proc . kill ( ) ;
208- }
209- } catch ( ex ) {
210- this . outputChannel . error ( 'Error disposing finder' , ex ) ;
211- }
212- } ,
213- } ,
214261 ) ;
215262
216263 connection . listen ( ) ;
@@ -286,7 +333,7 @@ class NativeGlobalPythonFinderImpl extends DisposableBase implements NativeGloba
286333 }
287334
288335 private sendRefreshRequest ( ) {
289- const pythonPathSettings = ( workspace . workspaceFolders || [ ] ) . map ( ( w ) =>
336+ const pythonPathSettings = ( getWorkspaceFolders ( ) || [ ] ) . map ( ( w ) =>
290337 getPythonSettingAndUntildify < string > ( DEFAULT_INTERPRETER_PATH_SETTING_KEY , w . uri ) ,
291338 ) ;
292339 pythonPathSettings . push ( getPythonSettingAndUntildify < string > ( DEFAULT_INTERPRETER_PATH_SETTING_KEY ) ) ;
@@ -308,7 +355,7 @@ class NativeGlobalPythonFinderImpl extends DisposableBase implements NativeGloba
308355 {
309356 // This has a special meaning in locator, its lot a low priority
310357 // as we treat this as workspace folders that can contain a large number of files.
311- search_paths : ( workspace . workspaceFolders || [ ] ) . map ( ( w ) => w . uri . fsPath ) ,
358+ search_paths : getWorkspaceFolderPaths ( ) ,
312359 // Also send the python paths that are configured in the settings.
313360 python_interpreter_paths : pythonSettings ,
314361 // We do not want to mix this with `search_paths`
0 commit comments