Skip to content

Commit 4562e60

Browse files
Copiloteleanorjboyd
andcommitted
Add "Enter Path..." option to Python interpreter selection
Co-authored-by: eleanorjboyd <26030610+eleanorjboyd@users.noreply.github.com>
1 parent 6d76c53 commit 4562e60

3 files changed

Lines changed: 61 additions & 1 deletion

File tree

src/common/localize.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export namespace WorkbenchStrings {
2424
export namespace Interpreter {
2525
export const statusBarSelect = l10n.t('Select Interpreter');
2626
export const browsePath = l10n.t('Browse...');
27+
export const enterPath = l10n.t('Enter Path...');
2728
export const createVirtualEnvironment = l10n.t('Create Virtual Environment...');
2829
}
2930

src/common/pickers/environments.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { EventNames } from '../telemetry/constants';
77
import { sendTelemetryEvent } from '../telemetry/sender';
88
import { isWindows } from '../utils/platformUtils';
99
import { handlePythonPath } from '../utils/pythonPath';
10-
import { showOpenDialog, showQuickPick, showQuickPickWithButtons, withProgress } from '../window.apis';
10+
import { showInputBoxWithButtons, showOpenDialog, showQuickPick, showQuickPickWithButtons, withProgress } from '../window.apis';
1111
import { pickEnvironmentManager } from './managers';
1212

1313
type QuickPickIcon =
@@ -69,6 +69,41 @@ async function browseForPython(
6969
return environment;
7070
}
7171

72+
async function enterPythonPath(
73+
managers: InternalEnvironmentManager[],
74+
projectEnvManagers: InternalEnvironmentManager[],
75+
): Promise<PythonEnvironment | undefined> {
76+
const placeholder = isWindows() ? 'C:\\path\\to\\python\\executable' : '/path/to/python/executable';
77+
const inputPath = await showInputBoxWithButtons({
78+
prompt: 'Enter the path to the Python executable',
79+
placeHolder: placeholder,
80+
ignoreFocusOut: true,
81+
validateInput: (value) => {
82+
if (!value || value.trim().length === 0) {
83+
return 'Please enter a valid path';
84+
}
85+
return null;
86+
},
87+
});
88+
89+
if (!inputPath) {
90+
return; // User cancelled
91+
}
92+
93+
const uri = Uri.file(inputPath.trim());
94+
const environment = await withProgress(
95+
{
96+
location: ProgressLocation.Notification,
97+
cancellable: false,
98+
},
99+
async (reporter, token) => {
100+
const env = await handlePythonPath(uri, managers, projectEnvManagers, reporter, token);
101+
return env;
102+
},
103+
);
104+
return environment;
105+
}
106+
72107
async function createEnvironment(
73108
managers: InternalEnvironmentManager[],
74109
projectEnvManagers: InternalEnvironmentManager[],
@@ -124,6 +159,8 @@ async function pickEnvironmentImpl(
124159
if (selected && !Array.isArray(selected)) {
125160
if (selected.label === Interpreter.browsePath) {
126161
return browseForPython(managers, projectEnvManagers);
162+
} else if (selected.label === Interpreter.enterPath) {
163+
return enterPythonPath(managers, projectEnvManagers);
127164
} else if (selected.label === Interpreter.createVirtualEnvironment) {
128165
sendTelemetryEvent(EventNames.CREATE_ENVIRONMENT, undefined, {
129166
manager: 'none',
@@ -146,6 +183,10 @@ export async function pickEnvironment(
146183
label: Interpreter.browsePath,
147184
iconPath: new ThemeIcon('folder'),
148185
},
186+
{
187+
label: Interpreter.enterPath,
188+
iconPath: new ThemeIcon('edit'),
189+
},
149190
{
150191
label: '',
151192
kind: QuickPickItemKind.Separator,

src/test/common/environmentPicker.unit.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import assert from 'node:assert';
55
import { Uri } from 'vscode';
66
import { PythonEnvironment } from '../../api';
7+
import { Interpreter } from '../../common/localize';
78

89
/**
910
* Test the logic used in environment pickers to include interpreter paths in descriptions
@@ -84,4 +85,21 @@ suite('Environment Picker Description Logic', () => {
8485
assert.strictEqual(description, 'System Python (C:\\Python39\\python.exe)');
8586
});
8687
});
88+
89+
suite('Picker options availability', () => {
90+
test('should have Browse option available', () => {
91+
assert.strictEqual(typeof Interpreter.browsePath, 'string');
92+
assert.strictEqual(Interpreter.browsePath, 'Browse...');
93+
});
94+
95+
test('should have Enter Path option available', () => {
96+
assert.strictEqual(typeof Interpreter.enterPath, 'string');
97+
assert.strictEqual(Interpreter.enterPath, 'Enter Path...');
98+
});
99+
100+
test('should have Create Virtual Environment option available', () => {
101+
assert.strictEqual(typeof Interpreter.createVirtualEnvironment, 'string');
102+
assert.strictEqual(Interpreter.createVirtualEnvironment, 'Create Virtual Environment...');
103+
});
104+
});
87105
});

0 commit comments

Comments
 (0)