Skip to content
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
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);
}
}
15 changes: 13 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,21 @@ 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;
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