Skip to content

Commit c50f13d

Browse files
author
Kartik Raj
committed
Add support for deprecated API types
1 parent db83f3e commit c50f13d

File tree

3 files changed

+309
-36
lines changed

3 files changed

+309
-36
lines changed

src/client/deprecatedProposedApi.ts

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
import { ConfigurationTarget, EventEmitter } from 'vscode';
5+
import { arePathsSame } from './common/platform/fs-paths';
6+
import { IInterpreterPathService, Resource } from './common/types';
7+
import {
8+
EnvironmentsChangedParams,
9+
ActiveEnvironmentChangedParams,
10+
EnvironmentDetailsOptions,
11+
EnvironmentDetails,
12+
DeprecatedProposedAPI,
13+
} from './deprecatedProposedApiTypes';
14+
import { IInterpreterService } from './interpreter/contracts';
15+
import { IServiceContainer } from './ioc/types';
16+
import { PythonEnvInfo } from './pythonEnvironments/base/info';
17+
import { getEnvPath } from './pythonEnvironments/base/info/env';
18+
import { GetRefreshEnvironmentsOptions, IDiscoveryAPI } from './pythonEnvironments/base/locator';
19+
20+
const onDidInterpretersChangedEvent = new EventEmitter<EnvironmentsChangedParams[]>();
21+
/**
22+
* @deprecated Will be removed soon.
23+
*/
24+
export function reportInterpretersChanged(e: EnvironmentsChangedParams[]): void {
25+
onDidInterpretersChangedEvent.fire(e);
26+
}
27+
28+
const onDidActiveInterpreterChangedEvent = new EventEmitter<ActiveEnvironmentChangedParams>();
29+
/**
30+
* @deprecated Will be removed soon.
31+
*/
32+
export function reportActiveInterpreterChangedDeprecated(e: ActiveEnvironmentChangedParams): void {
33+
onDidActiveInterpreterChangedEvent.fire(e);
34+
}
35+
36+
function getVersionString(env: PythonEnvInfo): string[] {
37+
const ver = [`${env.version.major}`, `${env.version.minor}`, `${env.version.micro}`];
38+
if (env.version.release) {
39+
ver.push(`${env.version.release}`);
40+
if (env.version.sysVersion) {
41+
ver.push(`${env.version.release}`);
42+
}
43+
}
44+
return ver;
45+
}
46+
47+
/**
48+
* Returns whether the path provided matches the environment.
49+
* @param path Path to environment folder or path to interpreter that uniquely identifies an environment.
50+
* @param env Environment to match with.
51+
*/
52+
function isEnvSame(path: string, env: PythonEnvInfo) {
53+
return arePathsSame(path, env.location) || arePathsSame(path, env.executable.filename);
54+
}
55+
56+
export function buildDeprecatedProposedApi(
57+
discoveryApi: IDiscoveryAPI,
58+
serviceContainer: IServiceContainer,
59+
): DeprecatedProposedAPI {
60+
const interpreterPathService = serviceContainer.get<IInterpreterPathService>(IInterpreterPathService);
61+
const interpreterService = serviceContainer.get<IInterpreterService>(IInterpreterService);
62+
63+
const proposed: DeprecatedProposedAPI = {
64+
environment: {
65+
async getExecutionDetails(resource?: Resource) {
66+
const env = await interpreterService.getActiveInterpreter(resource);
67+
return env ? { execCommand: [env.path] } : { execCommand: undefined };
68+
},
69+
async getActiveEnvironmentPath(resource?: Resource) {
70+
const env = await interpreterService.getActiveInterpreter(resource);
71+
if (!env) {
72+
return undefined;
73+
}
74+
return getEnvPath(env.path, env.envPath);
75+
},
76+
async getEnvironmentDetails(
77+
path: string,
78+
options?: EnvironmentDetailsOptions,
79+
): Promise<EnvironmentDetails | undefined> {
80+
let env: PythonEnvInfo | undefined;
81+
if (options?.useCache) {
82+
env = discoveryApi.getEnvs().find((v) => isEnvSame(path, v));
83+
}
84+
if (!env) {
85+
env = await discoveryApi.resolveEnv(path);
86+
if (!env) {
87+
return undefined;
88+
}
89+
}
90+
return {
91+
interpreterPath: env.executable.filename,
92+
envFolderPath: env.location.length ? env.location : undefined,
93+
version: getVersionString(env),
94+
environmentType: [env.kind],
95+
metadata: {
96+
sysPrefix: env.executable.sysPrefix,
97+
bitness: env.arch,
98+
project: env.searchLocation,
99+
},
100+
};
101+
},
102+
getEnvironmentPaths() {
103+
const paths = discoveryApi.getEnvs().map((e) => getEnvPath(e.executable.filename, e.location));
104+
return Promise.resolve(paths);
105+
},
106+
setActiveEnvironment(path: string, resource?: Resource): Promise<void> {
107+
return interpreterPathService.update(resource, ConfigurationTarget.WorkspaceFolder, path);
108+
},
109+
async refreshEnvironment() {
110+
await discoveryApi.triggerRefresh();
111+
const paths = discoveryApi.getEnvs().map((e) => getEnvPath(e.executable.filename, e.location));
112+
return Promise.resolve(paths);
113+
},
114+
getRefreshPromise(options?: GetRefreshEnvironmentsOptions): Promise<void> | undefined {
115+
return discoveryApi.getRefreshPromise(options);
116+
},
117+
onDidChangeExecutionDetails: interpreterService.onDidChangeInterpreterConfiguration,
118+
onDidEnvironmentsChanged: onDidInterpretersChangedEvent.event,
119+
onDidActiveEnvironmentChanged: onDidActiveInterpreterChangedEvent.event,
120+
onRefreshProgress: discoveryApi.onProgress,
121+
},
122+
};
123+
return proposed;
124+
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/* eslint-disable @typescript-eslint/no-unused-vars */
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
// Licensed under the MIT License.
4+
5+
import { Uri, Event } from 'vscode';
6+
import { ProposedExtensionAPI, Resource } from './proposedApiTypes';
7+
import { PythonEnvKind, EnvPathType } from './pythonEnvironments/base/info';
8+
import { ProgressNotificationEvent, GetRefreshEnvironmentsOptions } from './pythonEnvironments/base/locator';
9+
10+
export interface EnvironmentDetailsOptions {
11+
useCache: boolean;
12+
}
13+
14+
export interface EnvironmentDetails {
15+
interpreterPath: string;
16+
envFolderPath?: string;
17+
version: string[];
18+
environmentType: PythonEnvKind[];
19+
metadata: Record<string, unknown>;
20+
}
21+
22+
export interface EnvironmentsChangedParams {
23+
/**
24+
* Path to environment folder or path to interpreter that uniquely identifies an environment.
25+
* Virtual environments lacking an interpreter are identified by environment folder paths,
26+
* whereas other envs can be identified using interpreter path.
27+
*/
28+
path?: string;
29+
type: 'add' | 'remove' | 'update' | 'clear-all';
30+
}
31+
32+
export interface ActiveEnvironmentChangedParams {
33+
/**
34+
* Path to environment folder or path to interpreter that uniquely identifies an environment.
35+
* Virtual environments lacking an interpreter are identified by environment folder paths,
36+
* whereas other envs can be identified using interpreter path.
37+
*/
38+
path: string;
39+
resource?: Uri;
40+
}
41+
42+
/**
43+
* @deprecated Use {@link ProposedExtensionAPI} instead.
44+
*/
45+
export interface DeprecatedProposedAPI {
46+
/**
47+
* @deprecated Use {@link ProposedExtensionAPI.environment} instead. This will soon be removed.
48+
*/
49+
environment: {
50+
/**
51+
* An event that is emitted when execution details (for a resource) change. For instance, when interpreter configuration changes.
52+
*/
53+
readonly onDidChangeExecutionDetails: Event<Uri | undefined>;
54+
/**
55+
* Returns all the details the consumer needs to execute code within the selected environment,
56+
* corresponding to the specified resource taking into account any workspace-specific settings
57+
* for the workspace to which this resource belongs.
58+
* @param {Resource} [resource] A resource for which the setting is asked for.
59+
* * When no resource is provided, the setting scoped to the first workspace folder is returned.
60+
* * If no folder is present, it returns the global setting.
61+
* @returns {({ execCommand: string[] | undefined })}
62+
*/
63+
getExecutionDetails(
64+
resource?: Resource,
65+
): Promise<{
66+
/**
67+
* E.g of execution commands returned could be,
68+
* * `['<path to the interpreter set in settings>']`
69+
* * `['<path to the interpreter selected by the extension when setting is not set>']`
70+
* * `['conda', 'run', 'python']` which is used to run from within Conda environments.
71+
* or something similar for some other Python environments.
72+
*
73+
* @type {(string[] | undefined)} When return value is `undefined`, it means no interpreter is set.
74+
* Otherwise, join the items returned using space to construct the full execution command.
75+
*/
76+
execCommand: string[] | undefined;
77+
}>;
78+
/**
79+
* @deprecated Use {@link getActiveEnvironmentId} instead. This will soon be removed.
80+
*/
81+
getActiveEnvironmentPath(resource?: Resource): Promise<EnvPathType | undefined>;
82+
/**
83+
* Returns details for the given interpreter. Details such as absolute interpreter path,
84+
* version, type (conda, pyenv, etc). Metadata such as `sysPrefix` can be found under
85+
* metadata field.
86+
* @param path : Full path to environment folder or interpreter whose details you need.
87+
* @param options : [optional]
88+
* * useCache : When true, cache is checked first for any data, returns even if there
89+
* is partial data.
90+
*/
91+
getEnvironmentDetails(
92+
path: string,
93+
options?: EnvironmentDetailsOptions,
94+
): Promise<EnvironmentDetails | undefined>;
95+
/**
96+
* Returns paths to environments that uniquely identifies an environment found by the extension
97+
* at the time of calling. This API will *not* trigger a refresh. If a refresh is going on it
98+
* will *not* wait for the refresh to finish. This will return what is known so far. To get
99+
* complete list `await` on promise returned by `getRefreshPromise()`.
100+
*
101+
* Virtual environments lacking an interpreter are identified by environment folder paths,
102+
* whereas other envs can be identified using interpreter path.
103+
*/
104+
getEnvironmentPaths(): Promise<EnvPathType[] | undefined>;
105+
/**
106+
* Sets the active environment path for the python extension for the resource. Configuration target
107+
* will always be the workspace folder.
108+
* @param path : Full path to environment folder or interpreter to set.
109+
* @param resource : [optional] Uri of a file ro workspace to scope to a particular workspace
110+
* folder.
111+
*/
112+
setActiveEnvironment(path: string, resource?: Resource): Promise<void>;
113+
/**
114+
* This API will re-trigger environment discovery. Extensions can wait on the returned
115+
* promise to get the updated environment list. If there is a refresh already going on
116+
* then it returns the promise for that refresh.
117+
* @param options : [optional]
118+
* * clearCache : When true, this will clear the cache before environment refresh
119+
* is triggered.
120+
*/
121+
refreshEnvironment(): Promise<EnvPathType[] | undefined>;
122+
/**
123+
* Tracks discovery progress for current list of known environments, i.e when it starts, finishes or any other relevant
124+
* stage. Note the progress for a particular query is currently not tracked or reported, this only indicates progress of
125+
* the entire collection.
126+
*/
127+
readonly onRefreshProgress: Event<ProgressNotificationEvent>;
128+
/**
129+
* Returns a promise for the ongoing refresh. Returns `undefined` if there are no active
130+
* refreshes going on.
131+
*/
132+
getRefreshPromise(options?: GetRefreshEnvironmentsOptions): Promise<void> | undefined;
133+
/**
134+
* This event is triggered when the known environment list changes, like when a environment
135+
* is found, existing environment is removed, or some details changed on an environment.
136+
*/
137+
onDidEnvironmentsChanged: Event<EnvironmentsChangedParams[]>;
138+
/**
139+
* @deprecated Use {@link ProposedExtensionAPI.environment} `onDidChangeActiveEnvironmentId` instead. This will soon be removed.
140+
*/
141+
onDidActiveEnvironmentChanged: Event<ActiveEnvironmentChangedParams>;
142+
};
143+
}

0 commit comments

Comments
 (0)