Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
5 changes: 5 additions & 0 deletions src/common/localize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,8 @@ export namespace ProjectCreatorString {

export const noProjectsFound = l10n.t('No projects found');
}

export namespace EnvViewStrings {
export const selectedGlobalTooltip = l10n.t('This environment is selected for non-workspace files');
export const selectedWorkspaceTooltip = l10n.t('This environment is selected for workspace files');
}
10 changes: 5 additions & 5 deletions src/common/utils/pythonPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Uri, Progress, CancellationToken } from 'vscode';
import { PythonEnvironment } from '../../api';
import { InternalEnvironmentManager } from '../../internal.api';
import { showErrorMessage } from '../errors/utils';
import { traceInfo, traceVerbose, traceError } from '../logging';
import { traceVerbose, traceError } from '../logging';
import { PYTHON_EXTENSION_ID } from '../constants';

const priorityOrder = [
Expand Down Expand Up @@ -47,10 +47,10 @@ export async function handlePythonPath(
return;
}
reporter?.report({ message: `Checking ${manager.displayName}` });
traceInfo(`Checking ${manager.displayName} (${manager.id}) for ${interpreterUri.fsPath}`);
traceVerbose(`Checking ${manager.displayName} (${manager.id}) for ${interpreterUri.fsPath}`);
const env = await manager.resolve(interpreterUri);
if (env) {
traceInfo(`Using ${manager.displayName} (${manager.id}) to handle ${interpreterUri.fsPath}`);
traceVerbose(`Using ${manager.displayName} (${manager.id}) to handle ${interpreterUri.fsPath}`);
return env;
}
traceVerbose(`Manager ${manager.displayName} (${manager.id}) cannot handle ${interpreterUri.fsPath}`);
Expand All @@ -66,10 +66,10 @@ export async function handlePythonPath(
return;
}
reporter?.report({ message: `Checking ${manager.displayName}` });
traceInfo(`Checking ${manager.displayName} (${manager.id}) for ${interpreterUri.fsPath}`);
traceVerbose(`Checking ${manager.displayName} (${manager.id}) for ${interpreterUri.fsPath}`);
const env = await manager.resolve(interpreterUri);
if (env) {
traceInfo(`Using ${manager.displayName} (${manager.id}) to handle ${interpreterUri.fsPath}`);
traceVerbose(`Using ${manager.displayName} (${manager.id}) to handle ${interpreterUri.fsPath}`);
return env;
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/common/window.apis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
CancellationToken,
Disposable,
ExtensionTerminalOptions,
FileDecorationProvider,
InputBox,
InputBoxOptions,
LogOutputChannel,
Expand Down Expand Up @@ -290,3 +291,7 @@ export function createOutputChannel(name: string, languageId?: string): OutputCh
export function createLogOutputChannel(name: string): LogOutputChannel {
return window.createOutputChannel(name, { log: true });
}

export function registerFileDecorationProvider(provider: FileDecorationProvider): Disposable {
return window.registerFileDecorationProvider(provider);
}
1 change: 1 addition & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ export async function activate(context: ExtensionContext): Promise<PythonEnviron
updateViewsAndStatus(statusBar, workspaceView, managerView, api);
}),
envManagers.onDidChangeEnvironmentFiltered(async (e) => {
managerView.environmentChanged(e);
const location = e.uri?.fsPath ?? 'global';
traceInfo(
`Internal: Changed environment from ${e.old?.displayName} to ${e.new?.displayName} for: ${location}`,
Expand Down
33 changes: 30 additions & 3 deletions src/features/views/envManagersView.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Disposable, Event, EventEmitter, ProviderResult, TreeDataProvider, TreeItem, TreeView, window } from 'vscode';
import { EnvironmentGroupInfo, PythonEnvironment } from '../../api';
import { DidChangeEnvironmentEventArgs, EnvironmentGroupInfo, PythonEnvironment } from '../../api';
import {
DidChangeEnvironmentManagerEventArgs,
DidChangePackageManagerEventArgs,
Expand Down Expand Up @@ -32,6 +32,7 @@ export class EnvManagerView implements TreeDataProvider<EnvTreeItem>, Disposable
private revealMap = new Map<string, PythonEnvTreeItem>();
private managerViews = new Map<string, EnvManagerTreeItem>();
private packageRoots = new Map<string, PackageRootTreeItem>();
private selected: Map<string, string> = new Map();
private disposables: Disposable[] = [];

public constructor(public providers: EnvironmentManagers) {
Expand All @@ -44,6 +45,7 @@ export class EnvManagerView implements TreeDataProvider<EnvTreeItem>, Disposable
this.packageRoots.clear();
this.revealMap.clear();
this.managerViews.clear();
this.selected.clear();
}),
this.treeView,
this.treeDataChanged,
Expand Down Expand Up @@ -99,7 +101,7 @@ export class EnvManagerView implements TreeDataProvider<EnvTreeItem>, Disposable
const views: EnvTreeItem[] = [];
const envs = await manager.getEnvironments('all');
envs.filter((e) => !e.group).forEach((env) => {
const view = new PythonEnvTreeItem(env, element as EnvManagerTreeItem);
const view = new PythonEnvTreeItem(env, element as EnvManagerTreeItem, this.selected.get(env.envId.id));
views.push(view);
this.revealMap.set(env.envId.id, view);
});
Expand Down Expand Up @@ -142,7 +144,7 @@ export class EnvManagerView implements TreeDataProvider<EnvTreeItem>, Disposable
});

grouped.forEach((env) => {
const view = new PythonEnvTreeItem(env, groupItem);
const view = new PythonEnvTreeItem(env, groupItem, this.selected.get(env.envId.id));
views.push(view);
this.revealMap.set(env.envId.id, view);
});
Expand Down Expand Up @@ -227,4 +229,29 @@ export class EnvManagerView implements TreeDataProvider<EnvTreeItem>, Disposable
const roots = Array.from(this.packageRoots.values()).filter((r) => r.manager.id === args.manager.id);
this.fireDataChanged(roots);
}

public environmentChanged(e: DidChangeEnvironmentEventArgs) {
const views = [];
if (e.old) {
this.selected.delete(e.old.envId.id);
let view: EnvTreeItem | undefined = this.packageRoots.get(e.old.envId.id);
if (!view) {
view = this.managerViews.get(e.old.envId.managerId);
}
if (view) {
views.push(view);
}
}
if (e.new) {
this.selected.set(e.new.envId.id, e.uri === undefined ? 'global' : e.uri.fsPath);
let view: EnvTreeItem | undefined = this.packageRoots.get(e.new.envId.id);
if (!view) {
view = this.managerViews.get(e.new.envId.managerId);
}
if (view && !views.includes(view)) {
views.push(view);
}
}
this.fireDataChanged(views);
}
}
19 changes: 17 additions & 2 deletions src/features/views/treeViewItems.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { InternalEnvironmentManager, InternalPackageManager } from '../../intern
import { PythonEnvironment, IconPath, Package, PythonProject, EnvironmentGroupInfo } from '../../api';
import { removable } from './utils';
import { isActivatableEnvironment } from '../common/activation';
import { EnvViewStrings } from '../../common/localize';

export enum EnvTreeItemKind {
manager = 'python-env-manager',
Expand Down Expand Up @@ -66,11 +67,25 @@ export class PythonEnvTreeItem implements EnvTreeItem {
constructor(
public readonly environment: PythonEnvironment,
public readonly parent: EnvManagerTreeItem | PythonGroupEnvTreeItem,
public readonly selected?: string,
) {
const item = new TreeItem(environment.displayName ?? environment.name, TreeItemCollapsibleState.Collapsed);
let name = environment.displayName ?? environment.name;
if (selected) {
name = `★ ${name}`;
}

let tooltip = environment.tooltip;
if (selected) {
const tooltipEnd = environment.tooltip ?? environment.description;
tooltip =
selected === 'global' ? EnvViewStrings.selectedGlobalTooltip : EnvViewStrings.selectedWorkspaceTooltip;
tooltip = tooltipEnd ? `${tooltip} ● ${tooltipEnd}` : tooltip;
}

const item = new TreeItem(name, TreeItemCollapsibleState.Collapsed);
item.contextValue = this.getContextValue();
item.description = environment.description;
item.tooltip = environment.tooltip;
item.tooltip = tooltip;
item.iconPath = environment.iconPath;
this.treeItem = item;
}
Expand Down
18 changes: 18 additions & 0 deletions src/internal.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,26 @@ export interface EnvironmentManagers extends Disposable {
registerEnvironmentManager(manager: EnvironmentManager): Disposable;
registerPackageManager(manager: PackageManager): Disposable;

/**
* This event is fired when any environment manager changes its collection of environments.
* This can be any environment manager even if it is not the one selected by the user for the workspace.
*/
onDidChangeEnvironments: Event<InternalDidChangeEnvironmentsEventArgs>;

/**
* This event is fired when an environment manager changes the environment for
* a particular scope (global, uri, workspace, etc). This can be any environment manager even if it is not the
* one selected by the user for the workspace. It is also fired if the change
* involves unselected to selected or selected to unselected.
*/
onDidChangeEnvironment: Event<DidChangeEnvironmentEventArgs>;

/**
* This event is fired when a selected environment manager changes the environment
* for a particular scope (global, uri, workspace, etc). This is also only fired if
* the previous and current environments are different. It is also fired if the change
* involves unselected to selected or selected to unselected.
*/
onDidChangeEnvironmentFiltered: Event<DidChangeEnvironmentEventArgs>;
onDidChangePackages: Event<InternalDidChangePackagesEventArgs>;

Expand Down
Loading