11import * as fs from 'fs-extra' ;
22import * as path from 'path' ;
3- import { commands , QuickInputButtons , TaskExecution , TaskRevealKind , Terminal , Uri , workspace } from 'vscode' ;
3+ import {
4+ commands ,
5+ ProgressLocation ,
6+ QuickInputButtons ,
7+ TaskExecution ,
8+ TaskRevealKind ,
9+ Terminal ,
10+ Uri ,
11+ workspace ,
12+ } from 'vscode' ;
413import {
514 CreateEnvironmentOptions ,
615 PythonEnvironment ,
@@ -21,15 +30,25 @@ import { removePythonProjectSetting, setEnvironmentManager, setPackageManager }
2130
2231import { clipboardWriteText } from '../common/env.apis' ;
2332import { } from '../common/errors/utils' ;
33+ import { Pickers } from '../common/localize' ;
2434import { pickEnvironment } from '../common/pickers/environments' ;
2535import {
36+ ENTER_INTERPRETER_PATH_ID ,
2637 pickCreator ,
2738 pickEnvironmentManager ,
2839 pickPackageManager ,
2940 pickWorkspaceFolder ,
3041} from '../common/pickers/managers' ;
3142import { pickProject , pickProjectMany } from '../common/pickers/projects' ;
32- import { activeTextEditor , showErrorMessage , showInformationMessage } from '../common/window.apis' ;
43+ import { isWindows } from '../common/utils/platformUtils' ;
44+ import { handlePythonPath } from '../common/utils/pythonPath' ;
45+ import {
46+ activeTextEditor ,
47+ showErrorMessage ,
48+ showInformationMessage ,
49+ showOpenDialog ,
50+ withProgress ,
51+ } from '../common/window.apis' ;
3352import { runAsTask } from './execution/runAsTask' ;
3453import { runInTerminal } from './terminal/runInTerminal' ;
3554import { TerminalManager } from './terminal/terminalManager' ;
@@ -44,6 +63,46 @@ import {
4463 PythonEnvTreeItem ,
4564} from './views/treeViewItems' ;
4665
66+ /**
67+ * Opens a file dialog to browse for a Python interpreter and resolves it using available managers.
68+ */
69+ async function browseAndResolveInterpreter (
70+ em : EnvironmentManagers ,
71+ projectUris ?: Uri [ ] ,
72+ ) : Promise < PythonEnvironment | undefined > {
73+ const filters = isWindows ( ) ? { python : [ 'exe' ] } : undefined ;
74+ const uris = await showOpenDialog ( {
75+ canSelectFiles : true ,
76+ canSelectFolders : false ,
77+ canSelectMany : false ,
78+ filters,
79+ title : Pickers . Environments . selectExecutable ,
80+ } ) ;
81+ if ( ! uris || uris . length === 0 ) {
82+ return ;
83+ }
84+ const interpreterUri = uris [ 0 ] ;
85+
86+ // Get project-specific managers if projectUris are provided
87+ const projectEnvManagers = projectUris
88+ ? projectUris
89+ . map ( ( uri ) => em . getEnvironmentManager ( uri ) )
90+ . filter ( ( m ) : m is InternalEnvironmentManager => m !== undefined )
91+ : [ ] ;
92+
93+ const environment = await withProgress (
94+ {
95+ location : ProgressLocation . Notification ,
96+ cancellable : false ,
97+ } ,
98+ async ( reporter , token ) => {
99+ return await handlePythonPath ( interpreterUri , em . managers , projectEnvManagers , reporter , token ) ;
100+ } ,
101+ ) ;
102+
103+ return environment ;
104+ }
105+
47106export async function refreshManagerCommand ( context : unknown ) : Promise < void > {
48107 if ( context instanceof EnvManagerTreeItem ) {
49108 const manager = ( context as EnvManagerTreeItem ) . manager ;
@@ -133,7 +192,22 @@ export async function createAnyEnvironmentCommand(
133192 const select = options ?. selectEnvironment ;
134193 const projects = pm . getProjects ( options ?. uri ? [ options ?. uri ] : undefined ) ;
135194 if ( projects . length === 0 ) {
136- const managerId = await pickEnvironmentManager ( em . managers . filter ( ( m ) => m . supportsCreate ) ) ;
195+ const managerId = await pickEnvironmentManager (
196+ em . managers . filter ( ( m ) => m . supportsCreate ) ,
197+ undefined ,
198+ undefined ,
199+ true , // showEnterInterpreterPath
200+ ) ;
201+
202+ // Handle "Enter Interpreter Path" selection
203+ if ( managerId === ENTER_INTERPRETER_PATH_ID ) {
204+ const env = await browseAndResolveInterpreter ( em ) ;
205+ if ( select && env ) {
206+ await em . setEnvironments ( 'global' , env ) ;
207+ }
208+ return env ;
209+ }
210+
137211 const manager = em . managers . find ( ( m ) => m . id === managerId ) ;
138212 if ( manager ) {
139213 const env = await manager . create ( 'global' , { ...options } ) ;
@@ -165,7 +239,19 @@ export async function createAnyEnvironmentCommand(
165239 em . managers . filter ( ( m ) => m . supportsCreate ) ,
166240 defaultManagers ,
167241 options ?. showBackButton ,
242+ true , // showEnterInterpreterPath
168243 ) ;
244+
245+ // Handle "Enter Interpreter Path" selection
246+ if ( managerId === ENTER_INTERPRETER_PATH_ID ) {
247+ const projectUris = selected . map ( ( p ) => p . uri ) ;
248+ const env = await browseAndResolveInterpreter ( em , projectUris ) ;
249+ if ( select && env ) {
250+ await em . setEnvironments ( projectUris , env ) ;
251+ }
252+ return env ;
253+ }
254+
169255 if ( managerId ?. startsWith ( 'QuickCreate#' ) ) {
170256 quickCreate = true ;
171257 managerId = managerId . replace ( 'QuickCreate#' , '' ) ;
0 commit comments