Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to skip showing recommended interpreter in quick pick API #20604

Merged
merged 1 commit into from
Jan 31, 2023
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
IInterpreterQuickPick,
IInterpreterQuickPickItem,
IInterpreterSelector,
InterpreterQuickPickParams,
IPythonPathUpdaterServiceManager,
ISpecialQuickPickItem,
} from '../../types';
Expand Down Expand Up @@ -127,12 +128,12 @@ export class SetInterpreterCommand extends BaseInterpreterSelectorCommand implem
input: IMultiStepInput<InterpreterStateArgs>,
state: InterpreterStateArgs,
filter?: (i: PythonEnvironment) => boolean,
params?: { placeholder?: string | null; title?: string | null },
params?: InterpreterQuickPickParams,
): Promise<void | InputStep<InterpreterStateArgs>> {
// If the list is refreshing, it's crucial to maintain sorting order at all
// times so that the visible items do not change.
const preserveOrderWhenFiltering = !!this.interpreterService.refreshPromise;
const suggestions = this._getItems(state.workspace, filter);
const suggestions = this._getItems(state.workspace, filter, params);
state.path = undefined;
const currentInterpreterPathDisplay = this.pathUtils.getDisplayName(
this.configurationService.getSettings(state.workspace).pythonPath,
Expand Down Expand Up @@ -183,10 +184,10 @@ export class SetInterpreterCommand extends BaseInterpreterSelectorCommand implem
// Items are in the final state as all previous callbacks have finished executing.
quickPick.busy = false;
// Ensure we set a recommended item after refresh has finished.
this.updateQuickPickItems(quickPick, {}, state.workspace, filter);
this.updateQuickPickItems(quickPick, {}, state.workspace, filter, params);
});
}
this.updateQuickPickItems(quickPick, event, state.workspace, filter);
this.updateQuickPickItems(quickPick, event, state.workspace, filter, params);
},
},
});
Expand All @@ -208,21 +209,26 @@ export class SetInterpreterCommand extends BaseInterpreterSelectorCommand implem
return undefined;
}

public _getItems(resource: Resource, filter: ((i: PythonEnvironment) => boolean) | undefined): QuickPickType[] {
public _getItems(
resource: Resource,
filter: ((i: PythonEnvironment) => boolean) | undefined,
params?: InterpreterQuickPickParams,
): QuickPickType[] {
const suggestions: QuickPickType[] = [this.manualEntrySuggestion];
const defaultInterpreterPathSuggestion = this.getDefaultInterpreterPathSuggestion(resource);
if (defaultInterpreterPathSuggestion) {
suggestions.push(defaultInterpreterPathSuggestion);
}
const interpreterSuggestions = this.getSuggestions(resource, filter);
this.finalizeItems(interpreterSuggestions, resource);
const interpreterSuggestions = this.getSuggestions(resource, filter, params);
this.finalizeItems(interpreterSuggestions, resource, params);
suggestions.push(...interpreterSuggestions);
return suggestions;
}

private getSuggestions(
resource: Resource,
filter: ((i: PythonEnvironment) => boolean) | undefined,
params?: InterpreterQuickPickParams,
): QuickPickType[] {
const workspaceFolder = this.workspaceService.getWorkspaceFolder(resource);
const items = this.interpreterSelector
Expand All @@ -235,10 +241,13 @@ export class SetInterpreterCommand extends BaseInterpreterSelectorCommand implem
const itemsWithFullName = this.interpreterSelector
.getSuggestions(resource, true)
.filter((i) => !filter || filter(i.interpreter));
const recommended = this.interpreterSelector.getRecommendedSuggestion(
itemsWithFullName,
this.workspaceService.getWorkspaceFolder(resource)?.uri,
);
let recommended: IInterpreterQuickPickItem | undefined;
if (!params?.skipRecommended) {
recommended = this.interpreterSelector.getRecommendedSuggestion(
itemsWithFullName,
this.workspaceService.getWorkspaceFolder(resource)?.uri,
);
}
if (recommended && items[0].interpreter.id === recommended.interpreter.id) {
items.shift();
}
Expand Down Expand Up @@ -289,10 +298,11 @@ export class SetInterpreterCommand extends BaseInterpreterSelectorCommand implem
event: PythonEnvironmentsChangedEvent,
resource: Resource,
filter: ((i: PythonEnvironment) => boolean) | undefined,
params?: InterpreterQuickPickParams,
) {
// Active items are reset once we replace the current list with updated items, so save it.
const activeItemBeforeUpdate = quickPick.activeItems.length > 0 ? quickPick.activeItems[0] : undefined;
quickPick.items = this.getUpdatedItems(quickPick.items, event, resource, filter);
quickPick.items = this.getUpdatedItems(quickPick.items, event, resource, filter, params);
// Ensure we maintain the same active item as before.
const activeItem = activeItemBeforeUpdate
? quickPick.items.find((item) => {
Expand All @@ -317,6 +327,7 @@ export class SetInterpreterCommand extends BaseInterpreterSelectorCommand implem
event: PythonEnvironmentsChangedEvent,
resource: Resource,
filter: ((i: PythonEnvironment) => boolean) | undefined,
params?: InterpreterQuickPickParams,
): QuickPickType[] {
const updatedItems = [...items.values()];
const areItemsGrouped = items.find((item) => isSeparatorItem(item));
Expand Down Expand Up @@ -364,16 +375,18 @@ export class SetInterpreterCommand extends BaseInterpreterSelectorCommand implem
if (envIndex !== -1 && event.new === undefined) {
updatedItems.splice(envIndex, 1);
}
this.finalizeItems(updatedItems, resource);
this.finalizeItems(updatedItems, resource, params);
return updatedItems;
}

private finalizeItems(items: QuickPickType[], resource: Resource) {
private finalizeItems(items: QuickPickType[], resource: Resource, params?: InterpreterQuickPickParams) {
const interpreterSuggestions = this.interpreterSelector.getSuggestions(resource, true);
const r = this.interpreterService.refreshPromise;
if (!r) {
if (interpreterSuggestions.length) {
this.setRecommendedItem(interpreterSuggestions, items, resource);
if (!params?.skipRecommended) {
this.setRecommendedItem(interpreterSuggestions, items, resource);
}
// Add warning label to certain environments
items.forEach((item, i) => {
if (isInterpreterQuickPickItem(item) && isProblematicCondaEnvironment(item.interpreter)) {
Expand Down Expand Up @@ -513,7 +526,7 @@ export class SetInterpreterCommand extends BaseInterpreterSelectorCommand implem
public async getInterpreterViaQuickPick(
workspace: Resource,
filter: ((i: PythonEnvironment) => boolean) | undefined,
params?: { placeholder?: string | null; title?: string | null },
params?: InterpreterQuickPickParams,
): Promise<string | undefined> {
const interpreterState: InterpreterStateArgs = { path: undefined, workspace };
const multiStep = this.multiStepFactory.create<InterpreterStateArgs>();
Expand Down
26 changes: 16 additions & 10 deletions src/client/interpreter/configuration/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,26 @@ export interface IInterpreterComparer {
getRecommended(interpreters: PythonEnvironment[], resource: Resource): PythonEnvironment | undefined;
}

export interface InterpreterQuickPickParams {
/**
* Specify `null` if a placeholder is not required.
*/
placeholder?: string | null;
/**
* Specify `null` if a title is not required.
*/
title?: string | null;
/**
* Specify `true` to skip showing recommended python interpreter.
*/
skipRecommended?: boolean;
}

export const IInterpreterQuickPick = Symbol('IInterpreterQuickPick');
export interface IInterpreterQuickPick {
getInterpreterViaQuickPick(
workspace: Resource,
filter?: (i: PythonEnvironment) => boolean,
params?: {
/**
* Specify `null` if a placeholder is not required.
*/
placeholder?: string | null;
/**
* Specify `null` if a title is not required.
*/
title?: string | null;
},
params?: InterpreterQuickPickParams,
): Promise<string | undefined>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ export class VenvCreationProvider implements CreateEnvironmentProvider {
workspace.uri,
(i: PythonEnvironment) =>
[EnvironmentType.System, EnvironmentType.MicrosoftStore, EnvironmentType.Global].includes(i.envType),
{ skipRecommended: true },
);

let addGitIgnore = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ suite('venv Creation provider tests', () => {
pickWorkspaceFolderStub.resolves(workspace1);

interpreterQuickPick
.setup((i) => i.getInterpreterViaQuickPick(typemoq.It.isAny(), typemoq.It.isAny()))
.setup((i) => i.getInterpreterViaQuickPick(typemoq.It.isAny(), typemoq.It.isAny(), typemoq.It.isAny()))
.returns(() => Promise.resolve(undefined))
.verifiable(typemoq.Times.once());

Expand All @@ -83,7 +83,7 @@ suite('venv Creation provider tests', () => {
pickWorkspaceFolderStub.resolves(workspace1);

interpreterQuickPick
.setup((i) => i.getInterpreterViaQuickPick(typemoq.It.isAny(), typemoq.It.isAny()))
.setup((i) => i.getInterpreterViaQuickPick(typemoq.It.isAny(), typemoq.It.isAny(), typemoq.It.isAny()))
.returns(() => Promise.resolve('/usr/bin/python'))
.verifiable(typemoq.Times.once());

Expand All @@ -97,7 +97,7 @@ suite('venv Creation provider tests', () => {
pickWorkspaceFolderStub.resolves(workspace1);

interpreterQuickPick
.setup((i) => i.getInterpreterViaQuickPick(typemoq.It.isAny(), typemoq.It.isAny()))
.setup((i) => i.getInterpreterViaQuickPick(typemoq.It.isAny(), typemoq.It.isAny(), typemoq.It.isAny()))
.returns(() => Promise.resolve('/usr/bin/python'))
.verifiable(typemoq.Times.once());

Expand Down Expand Up @@ -160,7 +160,7 @@ suite('venv Creation provider tests', () => {
pickWorkspaceFolderStub.resolves(workspace1);

interpreterQuickPick
.setup((i) => i.getInterpreterViaQuickPick(typemoq.It.isAny(), typemoq.It.isAny()))
.setup((i) => i.getInterpreterViaQuickPick(typemoq.It.isAny(), typemoq.It.isAny(), typemoq.It.isAny()))
.returns(() => Promise.resolve('/usr/bin/python'))
.verifiable(typemoq.Times.once());

Expand Down Expand Up @@ -217,7 +217,7 @@ suite('venv Creation provider tests', () => {
pickWorkspaceFolderStub.resolves(workspace1);

interpreterQuickPick
.setup((i) => i.getInterpreterViaQuickPick(typemoq.It.isAny(), typemoq.It.isAny()))
.setup((i) => i.getInterpreterViaQuickPick(typemoq.It.isAny(), typemoq.It.isAny(), typemoq.It.isAny()))
.returns(() => Promise.resolve('/usr/bin/python'))
.verifiable(typemoq.Times.once());

Expand Down