Skip to content

Commit 1c33fd9

Browse files
author
Kartik Raj
authored
Cherry pick changes related to environment APIs (#19950)
- Rename proposed api environment namespace to environments (#19938) - Fix deprecated API bug (#19944)
1 parent e28b10d commit 1c33fd9

File tree

5 files changed

+68
-57
lines changed

5 files changed

+68
-57
lines changed

src/client/deprecatedProposedApi.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -86,15 +86,23 @@ export function buildDeprecatedProposedApi(
8686
const proposed: DeprecatedProposedAPI = {
8787
environment: {
8888
async getExecutionDetails(resource?: Resource) {
89-
sendApiTelemetry('getExecutionDetails');
89+
sendApiTelemetry('deprecated.getExecutionDetails');
9090
const env = await interpreterService.getActiveInterpreter(resource);
9191
return env ? { execCommand: [env.path] } : { execCommand: undefined };
9292
},
93+
async getActiveEnvironmentPath(resource?: Resource) {
94+
sendApiTelemetry('deprecated.getActiveEnvironmentPath');
95+
const env = await interpreterService.getActiveInterpreter(resource);
96+
if (!env) {
97+
return undefined;
98+
}
99+
return getEnvPath(env.path, env.envPath);
100+
},
93101
async getEnvironmentDetails(
94102
path: string,
95103
options?: EnvironmentDetailsOptions,
96104
): Promise<EnvironmentDetails | undefined> {
97-
sendApiTelemetry('getEnvironmentDetails');
105+
sendApiTelemetry('deprecated.getEnvironmentDetails');
98106
let env: PythonEnvInfo | undefined;
99107
if (options?.useCache) {
100108
env = discoveryApi.getEnvs().find((v) => isEnvSame(path, v));
@@ -118,38 +126,38 @@ export function buildDeprecatedProposedApi(
118126
};
119127
},
120128
getEnvironmentPaths() {
121-
sendApiTelemetry('getEnvironmentPaths');
129+
sendApiTelemetry('deprecated.getEnvironmentPaths');
122130
const paths = discoveryApi.getEnvs().map((e) => getEnvPath(e.executable.filename, e.location));
123131
return Promise.resolve(paths);
124132
},
125133
setActiveEnvironment(path: string, resource?: Resource): Promise<void> {
126-
sendApiTelemetry('setActiveEnvironment');
134+
sendApiTelemetry('deprecated.setActiveEnvironment');
127135
return interpreterPathService.update(resource, ConfigurationTarget.WorkspaceFolder, path);
128136
},
129137
async refreshEnvironment() {
130-
sendApiTelemetry('refreshEnvironment');
138+
sendApiTelemetry('deprecated.refreshEnvironment');
131139
await discoveryApi.triggerRefresh();
132140
const paths = discoveryApi.getEnvs().map((e) => getEnvPath(e.executable.filename, e.location));
133141
return Promise.resolve(paths);
134142
},
135143
getRefreshPromise(options?: GetRefreshEnvironmentsOptions): Promise<void> | undefined {
136-
sendApiTelemetry('getRefreshPromise');
144+
sendApiTelemetry('deprecated.getRefreshPromise');
137145
return discoveryApi.getRefreshPromise(options);
138146
},
139147
get onDidChangeExecutionDetails() {
140-
sendApiTelemetry('onDidChangeExecutionDetails', false);
148+
sendApiTelemetry('deprecated.onDidChangeExecutionDetails', false);
141149
return interpreterService.onDidChangeInterpreterConfiguration;
142150
},
143151
get onDidEnvironmentsChanged() {
144-
sendApiTelemetry('onDidEnvironmentsChanged', false);
152+
sendApiTelemetry('deprecated.onDidEnvironmentsChanged', false);
145153
return onDidInterpretersChangedEvent.event;
146154
},
147155
get onDidActiveEnvironmentChanged() {
148-
sendApiTelemetry('onDidActiveEnvironmentChanged', false);
156+
sendApiTelemetry('deprecated.onDidActiveEnvironmentChanged', false);
149157
return onDidActiveInterpreterChangedEvent.event;
150158
},
151159
get onRefreshProgress() {
152-
sendApiTelemetry('onRefreshProgress', false);
160+
sendApiTelemetry('deprecated.onRefreshProgress', false);
153161
return discoveryApi.onProgress;
154162
},
155163
},

src/client/deprecatedProposedApiTypes.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export interface ActiveEnvironmentChangedParams {
4343
*/
4444
export interface DeprecatedProposedAPI {
4545
/**
46-
* @deprecated Use {@link ProposedExtensionAPI.environment} instead. This will soon be removed.
46+
* @deprecated Use {@link ProposedExtensionAPI.environments} instead. This will soon be removed.
4747
*/
4848
environment: {
4949
/**
@@ -74,6 +74,15 @@ export interface DeprecatedProposedAPI {
7474
*/
7575
execCommand: string[] | undefined;
7676
}>;
77+
/**
78+
* Returns the path to the python binary selected by the user or as in the settings.
79+
* This is just the path to the python binary, this does not provide activation or any
80+
* other activation command. The `resource` if provided will be used to determine the
81+
* python binary in a multi-root scenario. If resource is `undefined` then the API
82+
* returns what ever is set for the workspace.
83+
* @param resource : Uri of a file or workspace
84+
*/
85+
getActiveEnvironmentPath(resource?: Resource): Promise<EnvPathType | undefined>;
7786
/**
7887
* Returns details for the given interpreter. Details such as absolute interpreter path,
7988
* version, type (conda, pyenv, etc). Metadata such as `sysPrefix` can be found under
@@ -131,7 +140,7 @@ export interface DeprecatedProposedAPI {
131140
*/
132141
onDidEnvironmentsChanged: Event<EnvironmentsChangedParams[]>;
133142
/**
134-
* @deprecated Use {@link ProposedExtensionAPI.environment} `onDidChangeActiveEnvironmentPath` instead. This will soon be removed.
143+
* @deprecated Use {@link ProposedExtensionAPI.environments} `onDidChangeActiveEnvironmentPath` instead. This will soon be removed.
135144
*/
136145
onDidActiveEnvironmentChanged: Event<ActiveEnvironmentChangedParams>;
137146
};

src/client/proposedApi.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
reportActiveInterpreterChangedDeprecated,
3333
reportInterpretersChanged,
3434
} from './deprecatedProposedApi';
35+
import { DeprecatedProposedAPI } from './deprecatedProposedApiTypes';
3536

3637
type ActiveEnvironmentChangeEvent = {
3738
resource: WorkspaceFolder | undefined;
@@ -151,19 +152,20 @@ export function buildProposedApi(
151152
);
152153

153154
/**
154-
* @deprecated Will be removed soon. Use {@link ProposedExtensionAPI.environment} instead.
155+
* @deprecated Will be removed soon. Use {@link ProposedExtensionAPI} instead.
155156
*/
156-
let deprecatedEnvironmentsApi;
157+
let deprecatedProposedApi;
157158
try {
158-
deprecatedEnvironmentsApi = { ...buildDeprecatedProposedApi(discoveryApi, serviceContainer).environment };
159+
deprecatedProposedApi = { ...buildDeprecatedProposedApi(discoveryApi, serviceContainer) };
159160
} catch (ex) {
160-
deprecatedEnvironmentsApi = {};
161+
deprecatedProposedApi = {} as DeprecatedProposedAPI;
161162
// Errors out only in case of testing.
162163
// Also, these APIs no longer supported, no need to log error.
163164
}
164165

165-
const proposed: ProposedExtensionAPI = {
166-
environment: {
166+
const proposed: ProposedExtensionAPI & DeprecatedProposedAPI = {
167+
...deprecatedProposedApi,
168+
environments: {
167169
getActiveEnvironmentPath(resource?: Resource) {
168170
sendApiTelemetry('getActiveEnvironmentPath');
169171
resource = resource && 'uri' in resource ? resource.uri : resource;
@@ -172,10 +174,6 @@ export function buildProposedApi(
172174
return {
173175
id,
174176
path,
175-
/**
176-
* @deprecated Only provided for backwards compatibility and will soon be removed.
177-
*/
178-
pathType: 'interpreterPath',
179177
};
180178
},
181179
updateActiveEnvironmentPath(
@@ -213,8 +211,8 @@ export function buildProposedApi(
213211
sendApiTelemetry('resolveEnvironment');
214212
return resolveEnvironment(path, discoveryApi);
215213
},
216-
get all(): Environment[] {
217-
sendApiTelemetry('all');
214+
get known(): Environment[] {
215+
sendApiTelemetry('known');
218216
return discoveryApi.getEnvs().map((e) => convertEnvInfoAndGetReference(e));
219217
},
220218
async refreshEnvironments(options?: RefreshOptions) {
@@ -227,7 +225,6 @@ export function buildProposedApi(
227225
sendApiTelemetry('onDidChangeEnvironments');
228226
return onEnvironmentsChanged.event;
229227
},
230-
...deprecatedEnvironmentsApi,
231228
},
232229
};
233230
return proposed;

src/client/proposedApiTypes.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ import { CancellationToken, Event, Uri, WorkspaceFolder } from 'vscode';
66
// https://github.com/microsoft/vscode-python/wiki/Proposed-Environment-APIs
77

88
export interface ProposedExtensionAPI {
9-
readonly environment: {
9+
readonly environments: {
1010
/**
11-
* Returns the environment configured by user in settings.
11+
* Returns the environment configured by user in settings. Note that this can be an invalid environment, use
12+
* {@link resolveEnvironment} to get full details.
1213
* @param resource : Uri of a file or workspace folder. This is used to determine the env in a multi-root
1314
* scenario. If `undefined`, then the API returns what ever is set for the workspace.
1415
*/
@@ -29,10 +30,10 @@ export interface ProposedExtensionAPI {
2930
*/
3031
readonly onDidChangeActiveEnvironmentPath: Event<ActiveEnvironmentPathChangeEvent>;
3132
/**
32-
* Carries environments found by the extension at the time of fetching the property. Note this may not
33+
* Carries environments known to the extension at the time of fetching the property. Note this may not
3334
* contain all environments in the system as a refresh might be going on.
3435
*/
35-
readonly all: readonly Environment[];
36+
readonly known: readonly Environment[];
3637
/**
3738
* This event is triggered when the known environment list changes, like when a environment
3839
* is found, existing environment is removed, or some details changed on an environment.
@@ -53,7 +54,7 @@ export interface ProposedExtensionAPI {
5354
/**
5455
* Returns details for the given environment, or `undefined` if the env is invalid.
5556
* @param environment : Full path to environment folder or python executable for the environment. Can also pass
56-
* the environment id or the environment itself.
57+
* the environment itself.
5758
*/
5859
resolveEnvironment(
5960
environment: Environment | EnvironmentPath | string,
@@ -63,7 +64,7 @@ export interface ProposedExtensionAPI {
6364

6465
export type RefreshOptions = {
6566
/**
66-
* Force trigger a refresh regardless of whether a refresh was already triggered. Note this can be expensive so
67+
* When `true`, force trigger a refresh regardless of whether a refresh was already triggered. Note this can be expensive so
6768
* it's best to only use it if user manually triggers a refresh.
6869
*/
6970
forceRefresh?: boolean;

src/test/proposedApi.unit.test.ts

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import { PythonEnvCollectionChangedEvent } from '../client/pythonEnvironments/ba
2929
import { normCasePath } from '../client/common/platform/fs-paths';
3030
import {
3131
ActiveEnvironmentPathChangeEvent,
32-
EnvironmentPath,
3332
EnvironmentsChangeEvent,
3433
ProposedExtensionAPI,
3534
} from '../client/proposedApiTypes';
@@ -76,7 +75,7 @@ suite('Proposed Extension API', () => {
7675

7776
test('Provide an event to track when active environment details change', async () => {
7877
const events: ActiveEnvironmentPathChangeEvent[] = [];
79-
proposed.environment.onDidChangeActiveEnvironmentPath((e) => {
78+
proposed.environments.onDidChangeActiveEnvironmentPath((e) => {
8079
events.push(e);
8180
});
8281
reportActiveInterpreterChanged({ path: 'path/to/environment', resource: undefined });
@@ -91,25 +90,23 @@ suite('Proposed Extension API', () => {
9190
configService
9291
.setup((c) => c.getSettings(undefined))
9392
.returns(() => (({ pythonPath } as unknown) as IPythonSettings));
94-
const actual = proposed.environment.getActiveEnvironmentPath();
95-
assert.deepEqual(actual, ({
93+
const actual = proposed.environments.getActiveEnvironmentPath();
94+
assert.deepEqual(actual, {
9695
id: normCasePath(pythonPath),
9796
path: pythonPath,
98-
pathType: 'interpreterPath',
99-
} as unknown) as EnvironmentPath);
97+
});
10098
});
10199

102100
test('getActiveEnvironmentPath: default python', () => {
103101
const pythonPath = 'python';
104102
configService
105103
.setup((c) => c.getSettings(undefined))
106104
.returns(() => (({ pythonPath } as unknown) as IPythonSettings));
107-
const actual = proposed.environment.getActiveEnvironmentPath();
108-
assert.deepEqual(actual, ({
105+
const actual = proposed.environments.getActiveEnvironmentPath();
106+
assert.deepEqual(actual, {
109107
id: 'DEFAULT_PYTHON',
110108
path: pythonPath,
111-
pathType: 'interpreterPath',
112-
} as unknown) as EnvironmentPath);
109+
});
113110
});
114111

115112
test('getActiveEnvironmentPath: With resource', () => {
@@ -118,19 +115,18 @@ suite('Proposed Extension API', () => {
118115
configService
119116
.setup((c) => c.getSettings(resource))
120117
.returns(() => (({ pythonPath } as unknown) as IPythonSettings));
121-
const actual = proposed.environment.getActiveEnvironmentPath(resource);
122-
assert.deepEqual(actual, ({
118+
const actual = proposed.environments.getActiveEnvironmentPath(resource);
119+
assert.deepEqual(actual, {
123120
id: normCasePath(pythonPath),
124121
path: pythonPath,
125-
pathType: 'interpreterPath',
126-
} as unknown) as EnvironmentPath);
122+
});
127123
});
128124

129125
test('resolveEnvironment: invalid environment (when passed as string)', async () => {
130126
const pythonPath = 'this/is/a/test/path';
131127
discoverAPI.setup((p) => p.resolveEnv(pythonPath)).returns(() => Promise.resolve(undefined));
132128

133-
const actual = await proposed.environment.resolveEnvironment(pythonPath);
129+
const actual = await proposed.environments.resolveEnvironment(pythonPath);
134130
expect(actual).to.be.equal(undefined);
135131
});
136132

@@ -150,7 +146,7 @@ suite('Proposed Extension API', () => {
150146
});
151147
discoverAPI.setup((p) => p.resolveEnv(pythonPath)).returns(() => Promise.resolve(env));
152148

153-
const actual = await proposed.environment.resolveEnvironment(pythonPath);
149+
const actual = await proposed.environments.resolveEnvironment(pythonPath);
154150
assert.deepEqual((actual as EnvironmentReference).internal, convertCompleteEnvInfo(env));
155151
});
156152

@@ -176,13 +172,13 @@ suite('Proposed Extension API', () => {
176172
});
177173
discoverAPI.setup((p) => p.resolveEnv(pythonPath)).returns(() => Promise.resolve(env));
178174

179-
const actual = await proposed.environment.resolveEnvironment(convertCompleteEnvInfo(partialEnv));
175+
const actual = await proposed.environments.resolveEnvironment(convertCompleteEnvInfo(partialEnv));
180176
assert.deepEqual((actual as EnvironmentReference).internal, convertCompleteEnvInfo(env));
181177
});
182178

183179
test('environments: no pythons found', () => {
184180
discoverAPI.setup((d) => d.getEnvs()).returns(() => []);
185-
const actual = proposed.environment.all;
181+
const actual = proposed.environments.known;
186182
expect(actual).to.be.deep.equal([]);
187183
});
188184

@@ -232,7 +228,7 @@ suite('Proposed Extension API', () => {
232228
},
233229
];
234230
discoverAPI.setup((d) => d.getEnvs()).returns(() => envs);
235-
const actual = proposed.environment.all;
231+
const actual = proposed.environments.known;
236232
const actualEnvs = actual?.map((a) => (a as EnvironmentReference).internal);
237233
assert.deepEqual(
238234
actualEnvs?.sort((a, b) => a.id.localeCompare(b.id)),
@@ -244,7 +240,7 @@ suite('Proposed Extension API', () => {
244240
let events: EnvironmentsChangeEvent[] = [];
245241
let eventValues: EnvironmentsChangeEvent[] = [];
246242
let expectedEvents: EnvironmentsChangeEvent[] = [];
247-
proposed.environment.onDidChangeEnvironments((e) => {
243+
proposed.environments.onDidChangeEnvironments((e) => {
248244
events.push(e);
249245
});
250246
const envs = [
@@ -336,7 +332,7 @@ suite('Proposed Extension API', () => {
336332
.returns(() => Promise.resolve())
337333
.verifiable(typemoq.Times.once());
338334

339-
await proposed.environment.updateActiveEnvironmentPath('this/is/a/test/python/path');
335+
await proposed.environments.updateActiveEnvironmentPath('this/is/a/test/python/path');
340336

341337
interpreterPathService.verifyAll();
342338
});
@@ -347,7 +343,7 @@ suite('Proposed Extension API', () => {
347343
.returns(() => Promise.resolve())
348344
.verifiable(typemoq.Times.once());
349345

350-
await proposed.environment.updateActiveEnvironmentPath({
346+
await proposed.environments.updateActiveEnvironmentPath({
351347
id: normCasePath('this/is/a/test/python/path'),
352348
path: 'this/is/a/test/python/path',
353349
});
@@ -362,7 +358,7 @@ suite('Proposed Extension API', () => {
362358
.returns(() => Promise.resolve())
363359
.verifiable(typemoq.Times.once());
364360

365-
await proposed.environment.updateActiveEnvironmentPath('this/is/a/test/python/path', uri);
361+
await proposed.environments.updateActiveEnvironmentPath('this/is/a/test/python/path', uri);
366362

367363
interpreterPathService.verifyAll();
368364
});
@@ -379,7 +375,7 @@ suite('Proposed Extension API', () => {
379375
index: 0,
380376
};
381377

382-
await proposed.environment.updateActiveEnvironmentPath('this/is/a/test/python/path', workspace);
378+
await proposed.environments.updateActiveEnvironmentPath('this/is/a/test/python/path', workspace);
383379

384380
interpreterPathService.verifyAll();
385381
});
@@ -390,7 +386,7 @@ suite('Proposed Extension API', () => {
390386
.returns(() => Promise.resolve())
391387
.verifiable(typemoq.Times.once());
392388

393-
await proposed.environment.refreshEnvironments();
389+
await proposed.environments.refreshEnvironments();
394390

395391
discoverAPI.verifyAll();
396392
});
@@ -401,7 +397,7 @@ suite('Proposed Extension API', () => {
401397
.returns(() => Promise.resolve())
402398
.verifiable(typemoq.Times.once());
403399

404-
await proposed.environment.refreshEnvironments({ forceRefresh: true });
400+
await proposed.environments.refreshEnvironments({ forceRefresh: true });
405401

406402
discoverAPI.verifyAll();
407403
});

0 commit comments

Comments
 (0)