Skip to content

Commit 547243f

Browse files
authored
Fix issue with sys.prefix when getting environment details. (#16386)
* Fix issue with sys.prefix when getting environment details. * Fix typo * Fix typo again
1 parent 2411004 commit 547243f

File tree

6 files changed

+53
-17
lines changed

6 files changed

+53
-17
lines changed

news/2 Fixes/16355.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix issue with sys.prefix when getting environment details.

src/client/pythonEnvironments/index.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { PosixKnownPathsLocator } from './discovery/locators/services/posixKnown
2525
import { PyenvLocator } from './discovery/locators/services/pyenvLocator';
2626
import { WindowsRegistryLocator } from './discovery/locators/services/windowsRegistryLocator';
2727
import { WindowsStoreLocator } from './discovery/locators/services/windowsStoreLocator';
28-
import { EnvironmentInfoService } from './info/environmentInfoService';
28+
import { getEnvironmentInfoService } from './info/environmentInfoService';
2929
import { isComponentEnabled, registerLegacyDiscoveryForIOC, registerNewDiscoveryForIOC } from './legacyIOC';
3030
import { EnvironmentsSecurity, IEnvironmentsSecurity } from './security';
3131
import { PoetryLocator } from './discovery/locators/services/poetryLocator';
@@ -37,7 +37,7 @@ export async function initialize(ext: ExtensionState): Promise<PythonEnvironment
3737
const environmentsSecurity = new EnvironmentsSecurity();
3838
const api = new PythonEnvironments(
3939
() => createLocators(ext, environmentsSecurity),
40-
// Other sub-commonents (e.g. config, "current" env) will go here.
40+
// Other sub-components (e.g. config, "current" env) will go here.
4141
);
4242
ext.disposables.push(api);
4343

@@ -94,8 +94,7 @@ async function createLocators(
9494
);
9595

9696
// Create the env info service used by ResolvingLocator and CachingLocator.
97-
const envInfoService = new EnvironmentInfoService();
98-
ext.disposables.push(envInfoService);
97+
const envInfoService = getEnvironmentInfoService(ext.disposables);
9998

10099
// Build the stack of composite locators.
101100
locators = new PythonEnvsReducer(locators);

src/client/pythonEnvironments/info/environmentInfoService.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
import { traceVerbose } from '../../common/logger';
5+
import { IDisposableRegistry } from '../../common/types';
56
import { createDeferred, Deferred } from '../../common/utils/async';
67
import { createRunningWorkerPool, IWorkerPool, QueuePosition } from '../../common/utils/workerPool';
78
import { getInterpreterInfo, InterpreterInformation } from '../base/info/interpreter';
@@ -32,7 +33,7 @@ async function buildEnvironmentInfo(interpreterPath: string): Promise<Interprete
3233
return interpreterInfo;
3334
}
3435

35-
export class EnvironmentInfoService implements IEnvironmentInfoService {
36+
class EnvironmentInfoService implements IEnvironmentInfoService {
3637
// Caching environment here in-memory. This is so that we don't have to run this on the same
3738
// path again and again in a given session. This information will likely not change in a given
3839
// session. There are definitely cases where this will change. But a simple reload should address
@@ -84,3 +85,18 @@ export class EnvironmentInfoService implements IEnvironmentInfoService {
8485
return !!(result && result.completed);
8586
}
8687
}
88+
89+
let envInfoService: IEnvironmentInfoService | undefined;
90+
export function getEnvironmentInfoService(disposables?: IDisposableRegistry): IEnvironmentInfoService {
91+
if (envInfoService === undefined) {
92+
const service = new EnvironmentInfoService();
93+
disposables?.push({
94+
dispose: () => {
95+
service.dispose();
96+
envInfoService = undefined;
97+
},
98+
});
99+
envInfoService = service;
100+
}
101+
return envInfoService;
102+
}

src/client/pythonEnvironments/legacyIOC.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import { EnvironmentsSecurity, IEnvironmentsSecurity } from './security';
6969
import { toSemverLikeVersion } from './base/info/pythonVersion';
7070
import { PythonVersion } from './info/pythonVersion';
7171
import { IExtensionSingleActivationService } from '../activation/types';
72+
import { EnvironmentInfoServiceQueuePriority, getEnvironmentInfoService } from './info/environmentInfoService';
7273

7374
const convertedKinds = new Map(
7475
Object.entries({
@@ -195,14 +196,23 @@ class ComponentAdapter implements IComponentAdapter {
195196

196197
// We use the same getInterpreters() here as for IInterpreterLocatorService.
197198
public async getInterpreterDetails(pythonPath: string, resource?: vscode.Uri): Promise<PythonEnvironment> {
198-
const info = buildEnvInfo({ executable: pythonPath });
199+
const envInfo = buildEnvInfo({ executable: pythonPath });
199200
if (resource !== undefined) {
200201
const wsFolder = vscode.workspace.getWorkspaceFolder(resource);
201202
if (wsFolder !== undefined) {
202-
info.searchLocation = wsFolder.uri;
203+
envInfo.searchLocation = wsFolder.uri;
204+
}
205+
}
206+
207+
const env = (await this.api.resolveEnv(envInfo)) ?? envInfo;
208+
if (env.executable.sysPrefix) {
209+
const execInfoService = getEnvironmentInfoService();
210+
const info = await execInfoService.getEnvironmentInfo(pythonPath, EnvironmentInfoServiceQueuePriority.High);
211+
if (info) {
212+
env.executable.sysPrefix = info.executable.sysPrefix;
213+
env.version = info.version;
203214
}
204215
}
205-
const env = await this.api.resolveEnv(info);
206216
return convertEnvInfo(env ?? buildEnvInfo({ executable: pythonPath }));
207217
}
208218

src/test/pythonEnvironments/base/locators/composite/environmentsResolver.unit.test.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import * as sinon from 'sinon';
88
import { ImportMock } from 'ts-mock-imports';
99
import { EventEmitter } from 'vscode';
1010
import { ExecutionResult } from '../../../../../client/common/process/types';
11+
import { IDisposableRegistry } from '../../../../../client/common/types';
1112
import { createDeferred } from '../../../../../client/common/utils/async';
1213
import { Architecture } from '../../../../../client/common/utils/platform';
1314
import { PythonEnvInfo, PythonEnvKind } from '../../../../../client/pythonEnvironments/base/info';
@@ -17,19 +18,24 @@ import { PythonEnvsResolver } from '../../../../../client/pythonEnvironments/bas
1718
import { getEnvs as getEnvsWithUpdates } from '../../../../../client/pythonEnvironments/base/locatorUtils';
1819
import { PythonEnvsChangedEvent } from '../../../../../client/pythonEnvironments/base/watcher';
1920
import * as ExternalDep from '../../../../../client/pythonEnvironments/common/externalDependencies';
20-
import { EnvironmentInfoService } from '../../../../../client/pythonEnvironments/info/environmentInfoService';
21+
import {
22+
getEnvironmentInfoService,
23+
IEnvironmentInfoService,
24+
} from '../../../../../client/pythonEnvironments/info/environmentInfoService';
2125
import { sleep } from '../../../../core';
2226
import { createNamedEnv, getEnvs, SimpleLocator } from '../../common';
2327

2428
suite('Python envs locator - Environments Resolver', () => {
25-
let envInfoService: EnvironmentInfoService;
29+
let envInfoService: IEnvironmentInfoService;
30+
let disposables: IDisposableRegistry;
2631

2732
setup(() => {
28-
envInfoService = new EnvironmentInfoService();
33+
disposables = [];
34+
envInfoService = getEnvironmentInfoService(disposables);
2935
});
3036
teardown(() => {
3137
sinon.restore();
32-
envInfoService.dispose();
38+
disposables.forEach((d) => d.dispose());
3339
});
3440

3541
/**

src/test/pythonEnvironments/info/environmentInfoService.functional.test.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,19 @@ import * as assert from 'assert';
77
import * as sinon from 'sinon';
88
import { ImportMock } from 'ts-mock-imports';
99
import { ExecutionResult } from '../../../client/common/process/types';
10+
import { IDisposableRegistry } from '../../../client/common/types';
1011
import { Architecture } from '../../../client/common/utils/platform';
1112
import { InterpreterInformation } from '../../../client/pythonEnvironments/base/info/interpreter';
1213
import { parseVersion } from '../../../client/pythonEnvironments/base/info/pythonVersion';
1314
import * as ExternalDep from '../../../client/pythonEnvironments/common/externalDependencies';
1415
import {
15-
EnvironmentInfoService,
1616
EnvironmentInfoServiceQueuePriority,
17+
getEnvironmentInfoService,
1718
} from '../../../client/pythonEnvironments/info/environmentInfoService';
1819

1920
suite('Environment Info Service', () => {
2021
let stubShellExec: sinon.SinonStub;
22+
let disposables: IDisposableRegistry;
2123

2224
function createExpectedEnvInfo(executable: string): InterpreterInformation {
2325
return {
@@ -36,6 +38,7 @@ suite('Environment Info Service', () => {
3638
}
3739

3840
setup(() => {
41+
disposables = [];
3942
stubShellExec = ImportMock.mockFunction(
4043
ExternalDep,
4144
'shellExecute',
@@ -49,9 +52,10 @@ suite('Environment Info Service', () => {
4952
});
5053
teardown(() => {
5154
stubShellExec.restore();
55+
disposables.forEach((d) => d.dispose());
5256
});
5357
test('Add items to queue and get results', async () => {
54-
const envService = new EnvironmentInfoService();
58+
const envService = getEnvironmentInfoService(disposables);
5559
const promises: Promise<InterpreterInformation | undefined>[] = [];
5660
const expected: InterpreterInformation[] = [];
5761
for (let i = 0; i < 10; i = i + 1) {
@@ -74,7 +78,7 @@ suite('Environment Info Service', () => {
7478
});
7579

7680
test('Add same item to queue', async () => {
77-
const envService = new EnvironmentInfoService();
81+
const envService = getEnvironmentInfoService(disposables);
7882
const promises: Promise<InterpreterInformation | undefined>[] = [];
7983
const expected: InterpreterInformation[] = [];
8084

@@ -96,7 +100,7 @@ suite('Environment Info Service', () => {
96100
});
97101

98102
test('isInfoProvided() returns true for items already processed', async () => {
99-
const envService = new EnvironmentInfoService();
103+
const envService = getEnvironmentInfoService(disposables);
100104
let result: boolean;
101105
const promises: Promise<InterpreterInformation | undefined>[] = [];
102106
const path1 = 'any-path1';
@@ -113,7 +117,7 @@ suite('Environment Info Service', () => {
113117
});
114118

115119
test('isInfoProvided() returns false otherwise', async () => {
116-
const envService = new EnvironmentInfoService();
120+
const envService = getEnvironmentInfoService(disposables);
117121
const promises: Promise<InterpreterInformation | undefined>[] = [];
118122
const path1 = 'any-path1';
119123
const path2 = 'any-path2';

0 commit comments

Comments
 (0)