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
11 changes: 9 additions & 2 deletions src/client/application/diagnostics/checks/pythonInterpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
IDiagnosticHandlerService,
IDiagnosticMessageOnCloseHandler,
} from '../types';
import { Common } from '../../../common/utils/localize';
import { Common, Interpreters } from '../../../common/utils/localize';
import { Commands } from '../../../common/constants';
import { ICommandManager, IWorkspaceService } from '../../../common/application/types';
import { sendTelemetryEvent } from '../../../telemetry';
Expand All @@ -30,11 +30,12 @@ import { cache } from '../../../common/utils/decorators';
import { noop } from '../../../common/utils/misc';
import { getEnvironmentVariable, getOSType, OSType } from '../../../common/utils/platform';
import { IFileSystem } from '../../../common/platform/types';
import { traceError } from '../../../logging';
import { traceError, traceWarn } from '../../../logging';
import { getExecutable } from '../../../common/process/internal/python';
import { getSearchPathEnvVarNames } from '../../../common/utils/exec';
import { IProcessServiceFactory } from '../../../common/process/types';
import { normCasePath } from '../../../common/platform/fs-paths';
import { useEnvExtension } from '../../../envExt/api.internal';

const messages = {
[DiagnosticCodes.NoPythonInterpretersDiagnostic]: l10n.t(
Expand Down Expand Up @@ -144,6 +145,9 @@ export class InvalidPythonInterpreterService extends BaseDiagnosticsService
const isInterpreterSetToDefault = interpreterPathService.get(resource) === 'python';

if (!hasInterpreters && isInterpreterSetToDefault) {
if (useEnvExtension()) {
traceWarn(Interpreters.envExtDiscoveryNoEnvironments);
}
return [
new InvalidPythonInterpreterDiagnostic(
DiagnosticCodes.NoPythonInterpretersDiagnostic,
Expand All @@ -156,6 +160,9 @@ export class InvalidPythonInterpreterService extends BaseDiagnosticsService

const currentInterpreter = await interpreterService.getActiveInterpreter(resource);
if (!currentInterpreter) {
if (useEnvExtension()) {
traceWarn(Interpreters.envExtNoActiveEnvironment);
}
return [
new InvalidPythonInterpreterDiagnostic(
DiagnosticCodes.InvalidPythonInterpreterDiagnostic,
Expand Down
18 changes: 18 additions & 0 deletions src/client/common/utils/localize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,24 @@ export namespace Interpreters {
export const installingPython = l10n.t('Installing Python into Environment...');
export const discovering = l10n.t('Discovering Python Interpreters');
export const refreshing = l10n.t('Refreshing Python Interpreters');
export const envExtDiscoveryAttribution = l10n.t(
'Environment discovery is managed by the Python Environments extension (ms-python.vscode-python-envs). Check the "Python Environments" output channel for environment-specific logs.',
);
export const envExtDiscoveryFailed = l10n.t(
'Environment discovery failed. Check the "Python Environments" output channel for details. The Python Environments extension (ms-python.vscode-python-envs) manages environment discovery.',
);
export const envExtDiscoverySlow = l10n.t(
'Environment discovery is taking longer than expected. Check the "Python Environments" output channel for progress. The Python Environments extension (ms-python.vscode-python-envs) manages environment discovery.',
);
export const envExtActivationFailed = l10n.t(
'Failed to activate the Python Environments extension (ms-python.vscode-python-envs), which is required for environment discovery. Please ensure it is installed and enabled.',
);
export const envExtDiscoveryNoEnvironments = l10n.t(
'Environment discovery completed but no Python environments were found. Check the "Python Environments" output channel for details.',
);
export const envExtNoActiveEnvironment = l10n.t(
'No Python environment is set for this resource. Check the "Python Environments" output channel for details, or select an interpreter.',
);
export const condaInheritEnvMessage = l10n.t(
'We noticed you\'re using a conda environment. If you are experiencing issues with this environment in the integrated terminal, we recommend that you let the Python extension change "terminal.integrated.inheritEnv" to false in your user settings. [Learn more](https://aka.ms/AA66i8f).',
);
Expand Down
21 changes: 18 additions & 3 deletions src/client/envExt/api.internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
} from './types';
import { executeCommand } from '../common/vscodeApis/commandApis';
import { getConfiguration } from '../common/vscodeApis/workspaceApis';
import { traceError, traceLog } from '../logging';
import { Interpreters } from '../common/utils/localize';

export const ENVS_EXTENSION_ID = 'ms-python.vscode-python-envs';

Expand All @@ -22,7 +24,8 @@ export function useEnvExtension(): boolean {
if (_useExt !== undefined) {
return _useExt;
}
const inExpSetting = getConfiguration('python').get<boolean>('useEnvironmentsExtension', false);
const config = getConfiguration('python');
const inExpSetting = config?.get<boolean>('useEnvironmentsExtension', false) ?? false;
// If extension is installed and in experiment, then use it.
_useExt = !!getExtension(ENVS_EXTENSION_ID) && inExpSetting;
return _useExt;
Expand All @@ -46,12 +49,20 @@ export async function getEnvExtApi(): Promise<PythonEnvironmentApi> {
}
const extension = getExtension(ENVS_EXTENSION_ID);
if (!extension) {
traceError(Interpreters.envExtActivationFailed);
throw new Error('Python Environments extension not found.');
}
if (!extension?.isActive) {
await extension.activate();
try {
await extension.activate();
} catch (ex) {
traceError(Interpreters.envExtActivationFailed, ex);
throw ex;
}
}

traceLog(Interpreters.envExtDiscoveryAttribution);

_extApi = extension.exports as PythonEnvironmentApi;
_extApi.onDidChangeEnvironment((e) => {
onDidChangeEnvironmentEnvExtEmitter.fire(e);
Expand All @@ -70,7 +81,11 @@ export async function runInBackground(

export async function getEnvironment(scope: GetEnvironmentScope): Promise<PythonEnvironment | undefined> {
const envExtApi = await getEnvExtApi();
return envExtApi.getEnvironment(scope);
const env = await envExtApi.getEnvironment(scope);
if (!env) {
traceLog(Interpreters.envExtNoActiveEnvironment);
}
return env;
}

export async function resolveEnvironment(pythonPath: string): Promise<PythonEnvironment | undefined> {
Expand Down
26 changes: 22 additions & 4 deletions src/client/envExt/envExtApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { PythonEnvCollectionChangedEvent } from '../pythonEnvironments/base/watc
import { getEnvExtApi } from './api.internal';
import { createDeferred, Deferred } from '../common/utils/async';
import { StopWatch } from '../common/utils/stopWatch';
import { traceLog } from '../logging';
import { traceError, traceLog, traceWarn } from '../logging';
import {
DidChangeEnvironmentsEventArgs,
EnvironmentChangeKind,
Expand All @@ -27,6 +27,7 @@ import {
import { FileChangeType } from '../common/platform/fileSystemWatcher';
import { Architecture, isWindows } from '../common/utils/platform';
import { parseVersion } from '../pythonEnvironments/base/info/pythonVersion';
import { Interpreters } from '../common/utils/localize';

function getKind(pythonEnv: PythonEnvironment): PythonEnvKind {
if (pythonEnv.envId.managerId.toLowerCase().endsWith('system')) {
Expand Down Expand Up @@ -242,13 +243,23 @@ class EnvExtApis implements IDiscoveryAPI, Disposable {
this._onProgress.fire({ stage: this.refreshState });
this._refreshPromise = createDeferred();

const SLOW_DISCOVERY_THRESHOLD_MS = 25_000;
const slowDiscoveryTimer = setTimeout(() => {
traceWarn(Interpreters.envExtDiscoverySlow);
}, SLOW_DISCOVERY_THRESHOLD_MS);

setImmediate(async () => {
try {
await this.envExtApi.refreshEnvironments(undefined);
if (this._envs.length === 0) {
traceWarn(Interpreters.envExtDiscoveryNoEnvironments);
}
this._refreshPromise?.resolve();
} catch (error) {
traceError(Interpreters.envExtDiscoveryFailed, error);
this._refreshPromise?.reject(error);
} finally {
clearTimeout(slowDiscoveryTimer);
traceLog(`Native locator: Refresh finished in ${stopwatch.elapsedTime} ms`);
this.refreshState = ProgressReportStage.discoveryFinished;
this._refreshPromise = undefined;
Expand Down Expand Up @@ -297,9 +308,16 @@ class EnvExtApis implements IDiscoveryAPI, Disposable {
if (envPath === undefined) {
return undefined;
}
const pythonEnv = await this.envExtApi.resolveEnvironment(Uri.file(envPath));
if (pythonEnv) {
return this.addEnv(pythonEnv);
try {
const pythonEnv = await this.envExtApi.resolveEnvironment(Uri.file(envPath));
if (pythonEnv) {
return this.addEnv(pythonEnv);
}
} catch (error) {
traceError(
`Failed to resolve environment "${envPath}" via the Python Environments extension (ms-python.vscode-python-envs). Check the "Python Environments" output channel for details.`,
error,
);
}
return undefined;
}
Expand Down