Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/common/localize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export namespace WorkbenchStrings {
export namespace Interpreter {
export const statusBarSelect = l10n.t('Select Interpreter');
export const browsePath = l10n.t('Browse...');
export const enterPath = l10n.t('Enter Path...');
export const createVirtualEnvironment = l10n.t('Create Virtual Environment...');
}

Expand Down
43 changes: 42 additions & 1 deletion src/common/pickers/environments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { EventNames } from '../telemetry/constants';
import { sendTelemetryEvent } from '../telemetry/sender';
import { isWindows } from '../utils/platformUtils';
import { handlePythonPath } from '../utils/pythonPath';
import { showOpenDialog, showQuickPick, showQuickPickWithButtons, withProgress } from '../window.apis';
import { showInputBoxWithButtons, showOpenDialog, showQuickPick, showQuickPickWithButtons, withProgress } from '../window.apis';
import { pickEnvironmentManager } from './managers';

type QuickPickIcon =
Expand Down Expand Up @@ -69,6 +69,41 @@ async function browseForPython(
return environment;
}

async function enterPythonPath(
managers: InternalEnvironmentManager[],
projectEnvManagers: InternalEnvironmentManager[],
): Promise<PythonEnvironment | undefined> {
const placeholder = isWindows() ? 'C:\\path\\to\\python\\executable' : '/path/to/python/executable';
const inputPath = await showInputBoxWithButtons({
prompt: 'Enter the path to the Python executable',
placeHolder: placeholder,
ignoreFocusOut: true,
validateInput: (value) => {
if (!value || value.trim().length === 0) {
return 'Please enter a valid path';
}
return null;
},
});

if (!inputPath) {
return; // User cancelled
}

const uri = Uri.file(inputPath.trim());
const environment = await withProgress(
{
location: ProgressLocation.Notification,
cancellable: false,
},
async (reporter, token) => {
const env = await handlePythonPath(uri, managers, projectEnvManagers, reporter, token);
return env;
},
);
return environment;
}

async function createEnvironment(
managers: InternalEnvironmentManager[],
projectEnvManagers: InternalEnvironmentManager[],
Expand Down Expand Up @@ -124,6 +159,8 @@ async function pickEnvironmentImpl(
if (selected && !Array.isArray(selected)) {
if (selected.label === Interpreter.browsePath) {
return browseForPython(managers, projectEnvManagers);
} else if (selected.label === Interpreter.enterPath) {
return enterPythonPath(managers, projectEnvManagers);
} else if (selected.label === Interpreter.createVirtualEnvironment) {
sendTelemetryEvent(EventNames.CREATE_ENVIRONMENT, undefined, {
manager: 'none',
Expand All @@ -146,6 +183,10 @@ export async function pickEnvironment(
label: Interpreter.browsePath,
iconPath: new ThemeIcon('folder'),
},
{
label: Interpreter.enterPath,
iconPath: new ThemeIcon('edit'),
},
{
label: '',
kind: QuickPickItemKind.Separator,
Expand Down
18 changes: 18 additions & 0 deletions src/test/common/environmentPicker.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import assert from 'node:assert';
import { Uri } from 'vscode';
import { PythonEnvironment } from '../../api';
import { Interpreter } from '../../common/localize';

/**
* Test the logic used in environment pickers to include interpreter paths in descriptions
Expand Down Expand Up @@ -84,4 +85,21 @@ suite('Environment Picker Description Logic', () => {
assert.strictEqual(description, 'System Python (C:\\Python39\\python.exe)');
});
});

suite('Picker options availability', () => {
test('should have Browse option available', () => {
assert.strictEqual(typeof Interpreter.browsePath, 'string');
assert.strictEqual(Interpreter.browsePath, 'Browse...');
});

test('should have Enter Path option available', () => {
assert.strictEqual(typeof Interpreter.enterPath, 'string');
assert.strictEqual(Interpreter.enterPath, 'Enter Path...');
});

test('should have Create Virtual Environment option available', () => {
assert.strictEqual(typeof Interpreter.createVirtualEnvironment, 'string');
assert.strictEqual(Interpreter.createVirtualEnvironment, 'Create Virtual Environment...');
});
});
});
Loading