1
1
// Copyright (c) Microsoft Corporation. All rights reserved.
2
2
// Licensed under the MIT License.
3
3
4
- import { Disposable , EventEmitter , Event , workspace , window , Uri } from 'vscode' ;
4
+ import { Disposable , EventEmitter , Event , Uri } from 'vscode' ;
5
5
import * as ch from 'child_process' ;
6
6
import * as path from 'path' ;
7
7
import * as rpc from 'vscode-jsonrpc/node' ;
@@ -12,10 +12,16 @@ import { createDeferred, createDeferredFrom } from '../../../../common/utils/asy
12
12
import { DisposableBase , DisposableStore } from '../../../../common/utils/resourceLifecycle' ;
13
13
import { DEFAULT_INTERPRETER_PATH_SETTING_KEY } from '../lowLevel/customWorkspaceLocator' ;
14
14
import { 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' ;
16
20
import { CONDAPATH_SETTING_KEY } from '../../../common/environmentManagers/conda' ;
17
21
import { VENVFOLDERS_SETTING_KEY , VENVPATH_SETTING_KEY } from '../lowLevel/customVirtualEnvLocator' ;
18
22
import { getUserHomeDir } from '../../../../common/utils/platform' ;
23
+ import { createLogOutputChannel } from '../../../../common/vscodeApis/windowApis' ;
24
+ import { PythonEnvKind } from '../../info' ;
19
25
20
26
const untildify = require ( 'untildify' ) ;
21
27
@@ -48,6 +54,7 @@ export interface NativeEnvManagerInfo {
48
54
export interface NativeGlobalPythonFinder extends Disposable {
49
55
resolve ( executable : string ) : Promise < NativeEnvInfo > ;
50
56
refresh ( ) : AsyncIterable < NativeEnvInfo > ;
57
+ categoryToKind ( category : string ) : PythonEnvKind ;
51
58
}
52
59
53
60
interface NativeLog {
@@ -60,7 +67,7 @@ class NativeGlobalPythonFinderImpl extends DisposableBase implements NativeGloba
60
67
61
68
private firstRefreshResults : undefined | ( ( ) => AsyncGenerator < NativeEnvInfo , void , unknown > ) ;
62
69
63
- private readonly outputChannel = this . _register ( window . createOutputChannel ( 'Python Locator' , { log : true } ) ) ;
70
+ private readonly outputChannel = this . _register ( createLogOutputChannel ( 'Python Locator' , { log : true } ) ) ;
64
71
65
72
constructor ( ) {
66
73
super ( ) ;
@@ -80,6 +87,40 @@ class NativeGlobalPythonFinderImpl extends DisposableBase implements NativeGloba
80
87
return environment ;
81
88
}
82
89
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
+
83
124
async * refresh ( ) : AsyncIterable < NativeEnvInfo > {
84
125
if ( this . firstRefreshResults ) {
85
126
// If this is the first time we are refreshing,
@@ -154,16 +195,33 @@ class NativeGlobalPythonFinderImpl extends DisposableBase implements NativeGloba
154
195
// eslint-disable-next-line class-methods-use-this
155
196
private start ( ) : rpc . MessageConnection {
156
197
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
+
159
199
// jsonrpc package cannot handle messages coming through too quickly.
160
200
// Lets handle the messages and close the stream only when
161
201
// we have got the exit event.
162
202
const readable = new PassThrough ( ) ;
163
- proc . stdout . pipe ( readable , { end : false } ) ;
164
- proc . stderr . on ( 'data' , ( data ) => this . outputChannel . error ( data . toString ( ) ) ) ;
165
203
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
+ }
167
225
const disposeStreams = new Disposable ( ( ) => {
168
226
readable . end ( ) ;
169
227
writable . end ( ) ;
@@ -200,17 +258,6 @@ class NativeGlobalPythonFinderImpl extends DisposableBase implements NativeGloba
200
258
connection . onClose ( ( ) => {
201
259
disposables . forEach ( ( d ) => d . dispose ( ) ) ;
202
260
} ) ,
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
- } ,
214
261
) ;
215
262
216
263
connection . listen ( ) ;
@@ -286,7 +333,7 @@ class NativeGlobalPythonFinderImpl extends DisposableBase implements NativeGloba
286
333
}
287
334
288
335
private sendRefreshRequest ( ) {
289
- const pythonPathSettings = ( workspace . workspaceFolders || [ ] ) . map ( ( w ) =>
336
+ const pythonPathSettings = ( getWorkspaceFolders ( ) || [ ] ) . map ( ( w ) =>
290
337
getPythonSettingAndUntildify < string > ( DEFAULT_INTERPRETER_PATH_SETTING_KEY , w . uri ) ,
291
338
) ;
292
339
pythonPathSettings . push ( getPythonSettingAndUntildify < string > ( DEFAULT_INTERPRETER_PATH_SETTING_KEY ) ) ;
@@ -308,7 +355,7 @@ class NativeGlobalPythonFinderImpl extends DisposableBase implements NativeGloba
308
355
{
309
356
// This has a special meaning in locator, its lot a low priority
310
357
// 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 ( ) ,
312
359
// Also send the python paths that are configured in the settings.
313
360
python_interpreter_paths : pythonSettings ,
314
361
// We do not want to mix this with `search_paths`
0 commit comments