From 6769b767a49c5ef7dce9495eb6fa717cdb5ffba9 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 3 Sep 2020 16:35:43 -0600 Subject: [PATCH 01/23] Stub out ComponentAdapter. --- src/client/pythonEnvironments/legacyIOC.ts | 76 +++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index 5a3aee2741a1..5330bb5ac0ac 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -2,6 +2,7 @@ // Licensed under the MIT License. import { injectable } from 'inversify'; +import { Uri } from 'vscode'; import { CONDA_ENV_FILE_SERVICE, CONDA_ENV_SERVICE, @@ -22,11 +23,13 @@ import { WORKSPACE_VIRTUAL_ENV_SERVICE, } from '../interpreter/contracts'; import { IPipEnvServiceHelper, IPythonInPathCommandProvider } from '../interpreter/locators/types'; +//import { GetInterpreterOptions } from '../interpreter/interpreterService'; import { IServiceContainer, IServiceManager } from '../ioc/types'; import { initializeExternalDependencies } from './common/externalDependencies'; import { PythonInterpreterLocatorService } from './discovery/locators'; import { InterpreterLocatorHelper } from './discovery/locators/helpers'; import { InterpreterLocatorProgressService } from './discovery/locators/progressService'; +import { CondaEnvironmentInfo } from './discovery/locators/services/conda'; import { CondaEnvFileService } from './discovery/locators/services/condaEnvFileService'; import { CondaEnvService } from './discovery/locators/services/condaEnvService'; import { CondaService } from './discovery/locators/services/condaService'; @@ -48,13 +51,28 @@ import { WorkspaceVirtualEnvService, } from './discovery/locators/services/workspaceVirtualEnvService'; import { WorkspaceVirtualEnvWatcherService } from './discovery/locators/services/workspaceVirtualEnvWatcherService'; +import { GetInterpreterLocatorOptions } from './discovery/locators/types'; +import { PythonEnvironment } from './info'; import { EnvironmentInfoService, IEnvironmentInfoService } from './info/environmentInfoService'; import { PythonEnvironments } from '.'; export const IComponentAdapter = Symbol('IComponentAdapter'); export interface IComponentAdapter { - // We will fill in the API separately. + // IInterpreterService + hasInterpreters: Promise; + //getInterpreters(_resource?: vscode.Uri, _options?: GetInterpreterOptions): Promise; + getInterpreterDetails(pythonPath: string, _resource?: vscode.Uri): Promise; + // IInterpreterLocatorService + getInterpreters(resource?: vscode.Uri, options?: GetInterpreterLocatorOptions): Promise; + // IInterpreterHelper + getInterpreterInformation(pythonPath: string): Promise>; + isMacDefaultPythonPath(pythonPath: string): Promise; + // ICondaService + isCondaEnvironment(interpreterPath: string): Promise; + getCondaEnvironment(interpreterPath: string): Promise; + // IWindowsStoreInterpreter + isWindowsStoreInterpreter(pythonPath: string): Promise; } @injectable() @@ -70,6 +88,62 @@ class ComponentAdapter implements IComponentAdapter { }); } } + + // IInterpreterHelper + + public async getInterpreterInformation(_pythonPath: string): Promise> { + return undefined; + // ... + } + + public async isMacDefaultPythonPath(_pythonPath: string): Promise { + return false; + // ... + } + + // IInterpreterService + + public get hasInterpreters(): Promise { + return Promise.resolve(false); + // ... + } + + //public async getInterpreters(_resource?: Uri, _options?: GetInterpreterOptions): Promise; + + public async getInterpreterDetails(_pythonPath: string, _resource?: Uri): Promise { + return undefined; + // ... + } + + // ICondaService + + public async isCondaEnvironment(_interpreterPath: string): Promise { + return false; + // ... + } + + public async getCondaEnvironment(_interpreterPath: string): Promise { + return undefined; + // ... + } + + // IWindowsStoreInterpreter + + public isWindowsStoreInterpreter(_pythonPath: string): boolean { + return false; + // ... + } + + // IInterpreterLocatorService + + public async getInterpreters(_resource?: Uri, _options?: GetInterpreterLocatorOptions): Promise { + //{ + // ignoreCache?: boolean + // onSuggestion?: boolean; + //} + return []; + // ... + } } export function registerForIOC(serviceManager: IServiceManager, serviceContainer: IServiceContainer, api: PythonEnvironments): void { From 192c4b0e49395061ddd9741f71aabbee3c35bec3 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 8 Sep 2020 16:41:05 -0600 Subject: [PATCH 02/23] Implement ComponentAdapter.isMacDefaultPythonPath(). --- src/client/pythonEnvironments/legacyIOC.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index 5330bb5ac0ac..5910144d5b6b 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -25,6 +25,7 @@ import { import { IPipEnvServiceHelper, IPythonInPathCommandProvider } from '../interpreter/locators/types'; //import { GetInterpreterOptions } from '../interpreter/interpreterService'; import { IServiceContainer, IServiceManager } from '../ioc/types'; +import { PythonEnvKind } from './base/info'; import { initializeExternalDependencies } from './common/externalDependencies'; import { PythonInterpreterLocatorService } from './discovery/locators'; import { InterpreterLocatorHelper } from './discovery/locators/helpers'; @@ -96,9 +97,12 @@ class ComponentAdapter implements IComponentAdapter { // ... } - public async isMacDefaultPythonPath(_pythonPath: string): Promise { - return false; - // ... + public async isMacDefaultPythonPath(pythonPath: string): Promise { + const env = await this.api.resolveEnv(pythonPath); + if (env === undefined) { + return undefined; + } + return env.kind === PythonEnvKind.MacDefault; } // IInterpreterService From 0009f46116b6997fae6629b7668a740252ffe504 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 8 Sep 2020 16:46:53 -0600 Subject: [PATCH 03/23] Implement ComponentAdapter.isWindowsStoreInterpreter(). --- src/client/pythonEnvironments/legacyIOC.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index 5910144d5b6b..1a12951bed93 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -133,9 +133,12 @@ class ComponentAdapter implements IComponentAdapter { // IWindowsStoreInterpreter - public isWindowsStoreInterpreter(_pythonPath: string): boolean { - return false; - // ... + public async isWindowsStoreInterpreter(pythonPath: string): Promise { + const env = await this.api.resolveEnv(pythonPath); + if (env === undefined) { + return undefined; + } + return env.kind === PythonEnvKind.WindowsStore; } // IInterpreterLocatorService From 8034272316a5ac027b5f218c3b3fb214ad829188 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 8 Sep 2020 16:58:56 -0600 Subject: [PATCH 04/23] Implement ComponentAdapter.isCondaEnvironment(). --- src/client/pythonEnvironments/legacyIOC.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index 1a12951bed93..82e762b9b066 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -121,9 +121,12 @@ class ComponentAdapter implements IComponentAdapter { // ICondaService - public async isCondaEnvironment(_interpreterPath: string): Promise { - return false; - // ... + public async isCondaEnvironment(interpreterPath: string): Promise { + const env = await this.api.resolveEnv(interpreterPath); + if (env === undefined) { + return undefined; + } + return env.kind === PythonEnvKind.Conda; } public async getCondaEnvironment(_interpreterPath: string): Promise { From 26e3736e202ffb2ead45ac6b01871767dbf3084c Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 8 Sep 2020 17:03:40 -0600 Subject: [PATCH 05/23] Implement ComponentAdapter.hasInterpreters(). --- src/client/pythonEnvironments/legacyIOC.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index 82e762b9b066..090604096fcc 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -108,8 +108,10 @@ class ComponentAdapter implements IComponentAdapter { // IInterpreterService public get hasInterpreters(): Promise { - return Promise.resolve(false); - // ... + const iterator = this.api.iterEnvs(); + return iterator.next().then((res) => { + return !res.done; + }); } //public async getInterpreters(_resource?: Uri, _options?: GetInterpreterOptions): Promise; From 2889a207cb635fe39e7dc60f3e1766021e40f9fb Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 8 Sep 2020 17:52:28 -0600 Subject: [PATCH 06/23] Add a convertEnvInfo() helper. --- src/client/pythonEnvironments/legacyIOC.ts | 57 +++++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index 090604096fcc..eeb8515e9fff 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -3,6 +3,7 @@ import { injectable } from 'inversify'; import { Uri } from 'vscode'; +import { getVersionString, parseVersion } from '../common/utils/version'; import { CONDA_ENV_FILE_SERVICE, CONDA_ENV_SERVICE, @@ -25,7 +26,7 @@ import { import { IPipEnvServiceHelper, IPythonInPathCommandProvider } from '../interpreter/locators/types'; //import { GetInterpreterOptions } from '../interpreter/interpreterService'; import { IServiceContainer, IServiceManager } from '../ioc/types'; -import { PythonEnvKind } from './base/info'; +import { PythonEnvInfo, PythonEnvKind, PythonReleaseLevel } from './base/info'; import { initializeExternalDependencies } from './common/externalDependencies'; import { PythonInterpreterLocatorService } from './discovery/locators'; import { InterpreterLocatorHelper } from './discovery/locators/helpers'; @@ -53,11 +54,63 @@ import { } from './discovery/locators/services/workspaceVirtualEnvService'; import { WorkspaceVirtualEnvWatcherService } from './discovery/locators/services/workspaceVirtualEnvWatcherService'; import { GetInterpreterLocatorOptions } from './discovery/locators/types'; -import { PythonEnvironment } from './info'; +import { EnvironmentType, PythonEnvironment } from './info'; import { EnvironmentInfoService, IEnvironmentInfoService } from './info/environmentInfoService'; import { PythonEnvironments } from '.'; +function convertEnvInfo(info: PythonEnvInfo): PythonEnvironment { + const env: PythonEnvironment = { + envType: EnvironmentType.Unknown, + envName: info.name, + envPath: info.location, + path: info.executable.filename, + architecture: info.arch, + sysPrefix: info.executable.sysPrefix + }; + + if (info.kind === PythonEnvKind.System) { + env.envType = EnvironmentType.System; + } else if (info.kind === PythonEnvKind.MacDefault) { + env.envType = EnvironmentType.System; + } else if (info.kind === PythonEnvKind.WindowsStore) { + env.envType = EnvironmentType.WindowsStore; + } else if (info.kind === PythonEnvKind.Pyenv) { + env.envType = EnvironmentType.Pyenv; + } else if (info.kind === PythonEnvKind.Conda) { + env.envType = EnvironmentType.Conda; + } else if (info.kind === PythonEnvKind.CondaBase) { + env.envType = EnvironmentType.Conda; + } else if (info.kind === PythonEnvKind.VirtualEnv) { + env.envType = EnvironmentType.VirtualEnv; + } else if (info.kind === PythonEnvKind.Pipenv) { + env.envType = EnvironmentType.Pipenv; + if (info.searchLocation !== undefined) { + env.pipEnvWorkspaceFolder = info.searchLocation.fsPath; + } + } else if (info.kind === PythonEnvKind.Venv) { + env.envType = EnvironmentType.Venv; + } + // Otherwise it stays Unknown. + + if (info.version !== undefined) { + const releaseStr = info.version.release.level === PythonReleaseLevel.Final + ? 'final' + : `${info.version.release.level}${info.version.release.serial}`; + const versionStr = `${getVersionString(info.version)}-${releaseStr}`; + env.version = parseVersion(versionStr); + env.sysVersion = info.version.sysVersion; + } + + if (info.distro !== undefined && info.distro.org !== '') { + env.companyDisplayName = info.distro.org; + } + // We do not worry about using info.distro.defaultDisplayName + // or info.defaultDisplayName. + + return env; +} + export const IComponentAdapter = Symbol('IComponentAdapter'); export interface IComponentAdapter { // IInterpreterService From 2394160e42e13649e3b4683535c0ac7bd7b7fa9d Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 8 Sep 2020 17:53:35 -0600 Subject: [PATCH 07/23] Implement ComponentAdapter.getInterpreterInformation(). --- src/client/pythonEnvironments/legacyIOC.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index eeb8515e9fff..4eb5140288b8 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -145,9 +145,12 @@ class ComponentAdapter implements IComponentAdapter { // IInterpreterHelper - public async getInterpreterInformation(_pythonPath: string): Promise> { - return undefined; - // ... + public async getInterpreterInformation(pythonPath: string): Promise> { + const env = await this.api.resolveEnv(pythonPath); + if (env === undefined) { + return undefined; + } + return convertEnvInfo(env); } public async isMacDefaultPythonPath(pythonPath: string): Promise { From 200595de0db00d8074a5b696e4a8cea27129ed93 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 8 Sep 2020 17:56:49 -0600 Subject: [PATCH 08/23] Implement ComponentAdapter.getInterpreterDetails(). --- src/client/pythonEnvironments/legacyIOC.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index 4eb5140288b8..c5ced79c6c70 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -172,9 +172,12 @@ class ComponentAdapter implements IComponentAdapter { //public async getInterpreters(_resource?: Uri, _options?: GetInterpreterOptions): Promise; - public async getInterpreterDetails(_pythonPath: string, _resource?: Uri): Promise { - return undefined; - // ... + public async getInterpreterDetails(pythonPath: string, _resource?: Uri): Promise { + const env = await this.api.resolveEnv(pythonPath); + if (env === undefined) { + return undefined; + } + return convertEnvInfo(env); } // ICondaService From 4837898b81355a9238b9efb1cb07a4a0ca0c50c5 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 8 Sep 2020 18:06:14 -0600 Subject: [PATCH 09/23] Implement ComponentAdapter.getCondaEnvironment(). --- src/client/pythonEnvironments/legacyIOC.ts | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index c5ced79c6c70..f3f80bbe5305 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -190,9 +190,19 @@ class ComponentAdapter implements IComponentAdapter { return env.kind === PythonEnvKind.Conda; } - public async getCondaEnvironment(_interpreterPath: string): Promise { - return undefined; - // ... + public async getCondaEnvironment(interpreterPath: string): Promise { + const env = await this.api.resolveEnv(interpreterPath); + if (env === undefined) { + return undefined; + } + if (env.kind !== PythonEnvKind.Conda) { + return undefined; + } + if (env.name !== '') { + return { name: env.name, path: '' }; + } else { + return { name: '', path: env.location }; + } } // IWindowsStoreInterpreter From cfd1796ab7350ee0695547ab786427c5a873126f Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 8 Sep 2020 18:17:33 -0600 Subject: [PATCH 10/23] Implement ComponentAdapter.getInterpreters(). --- src/client/pythonEnvironments/legacyIOC.ts | 31 +++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index f3f80bbe5305..623ebd4b2ce0 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import { injectable } from 'inversify'; -import { Uri } from 'vscode'; +import * as vscode from 'vscode'; import { getVersionString, parseVersion } from '../common/utils/version'; import { CONDA_ENV_FILE_SERVICE, @@ -27,6 +27,7 @@ import { IPipEnvServiceHelper, IPythonInPathCommandProvider } from '../interpret //import { GetInterpreterOptions } from '../interpreter/interpreterService'; import { IServiceContainer, IServiceManager } from '../ioc/types'; import { PythonEnvInfo, PythonEnvKind, PythonReleaseLevel } from './base/info'; +import { PythonLocatorQuery } from './base/locator'; import { initializeExternalDependencies } from './common/externalDependencies'; import { PythonInterpreterLocatorService } from './discovery/locators'; import { InterpreterLocatorHelper } from './discovery/locators/helpers'; @@ -170,9 +171,9 @@ class ComponentAdapter implements IComponentAdapter { }); } - //public async getInterpreters(_resource?: Uri, _options?: GetInterpreterOptions): Promise; + //public async getInterpreters(_resource?: vscode.Uri, _options?: GetInterpreterOptions): Promise; - public async getInterpreterDetails(pythonPath: string, _resource?: Uri): Promise { + public async getInterpreterDetails(pythonPath: string, _resource?: vscode.Uri): Promise { const env = await this.api.resolveEnv(pythonPath); if (env === undefined) { return undefined; @@ -217,13 +218,31 @@ class ComponentAdapter implements IComponentAdapter { // IInterpreterLocatorService - public async getInterpreters(_resource?: Uri, _options?: GetInterpreterLocatorOptions): Promise { + public async getInterpreters( + resource?: vscode.Uri, + _options?: GetInterpreterLocatorOptions + ): Promise { + // We ignore the options: //{ // ignoreCache?: boolean // onSuggestion?: boolean; //} - return []; - // ... + const query: PythonLocatorQuery = {}; + if (resource !== undefined) { + const wsFolder = vscode.workspace.getWorkspaceFolder(resource); + if (wsFolder !== undefined) { + query.searchLocations = [wsFolder.uri]; + } + } + + const envs: PythonEnvironment[] = []; + const iterator = this.api.iterEnvs(query); + let res = await iterator.next(); + while (!res.done) { + envs.push(convertEnvInfo(res.value)); + res = await iterator.next(); + } + return envs; } } From 424aa09b2717c97cc0c6f840911d914572dafc1c Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 8 Sep 2020 18:20:09 -0600 Subject: [PATCH 11/23] Drop a dead line of code. --- src/client/pythonEnvironments/legacyIOC.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index 623ebd4b2ce0..a4c622142bd8 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -24,7 +24,6 @@ import { WORKSPACE_VIRTUAL_ENV_SERVICE, } from '../interpreter/contracts'; import { IPipEnvServiceHelper, IPythonInPathCommandProvider } from '../interpreter/locators/types'; -//import { GetInterpreterOptions } from '../interpreter/interpreterService'; import { IServiceContainer, IServiceManager } from '../ioc/types'; import { PythonEnvInfo, PythonEnvKind, PythonReleaseLevel } from './base/info'; import { PythonLocatorQuery } from './base/locator'; From 63b5e831d791eac9760ca2526a8e3879e1bc57df Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 10 Sep 2020 11:42:57 -0600 Subject: [PATCH 12/23] Move IComponentAdapter to interpreter/contracts.ts. --- src/client/interpreter/contracts.ts | 17 +++++++++++++++++ src/client/pythonEnvironments/legacyIOC.ts | 19 +------------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/client/interpreter/contracts.ts b/src/client/interpreter/contracts.ts index ded0c0ffa00e..9be523db0a74 100644 --- a/src/client/interpreter/contracts.ts +++ b/src/client/interpreter/contracts.ts @@ -31,6 +31,23 @@ export interface IVirtualEnvironmentsSearchPathProvider { getSearchPaths(resource?: Uri): Promise; } +export const IComponentAdapter = Symbol('IComponentAdapter'); +export interface IComponentAdapter { + // IInterpreterLocatorService + hasInterpreters: Promise; + getInterpreters(resource?: Uri, options?: GetInterpreterLocatorOptions): Promise; + // IInterpreterService + getInterpreterDetails(pythonPath: string, _resource?: Uri): Promise; + // IInterpreterHelper + getInterpreterInformation(pythonPath: string): Promise>; + isMacDefaultPythonPath(pythonPath: string): Promise; + // ICondaService + isCondaEnvironment(interpreterPath: string): Promise; + getCondaEnvironment(interpreterPath: string): Promise; + // IWindowsStoreInterpreter + isWindowsStoreInterpreter(pythonPath: string): Promise; +} + export const IInterpreterLocatorService = Symbol('IInterpreterLocatorService'); export interface IInterpreterLocatorService extends Disposable { diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index a4c622142bd8..a525966fefd8 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -9,6 +9,7 @@ import { CONDA_ENV_SERVICE, CURRENT_PATH_SERVICE, GLOBAL_VIRTUAL_ENV_SERVICE, + IComponentAdapter, ICondaService, IInterpreterLocatorHelper, IInterpreterLocatorProgressService, @@ -111,24 +112,6 @@ function convertEnvInfo(info: PythonEnvInfo): PythonEnvironment { return env; } -export const IComponentAdapter = Symbol('IComponentAdapter'); -export interface IComponentAdapter { - // IInterpreterService - hasInterpreters: Promise; - //getInterpreters(_resource?: vscode.Uri, _options?: GetInterpreterOptions): Promise; - getInterpreterDetails(pythonPath: string, _resource?: vscode.Uri): Promise; - // IInterpreterLocatorService - getInterpreters(resource?: vscode.Uri, options?: GetInterpreterLocatorOptions): Promise; - // IInterpreterHelper - getInterpreterInformation(pythonPath: string): Promise>; - isMacDefaultPythonPath(pythonPath: string): Promise; - // ICondaService - isCondaEnvironment(interpreterPath: string): Promise; - getCondaEnvironment(interpreterPath: string): Promise; - // IWindowsStoreInterpreter - isWindowsStoreInterpreter(pythonPath: string): Promise; -} - @injectable() class ComponentAdapter implements IComponentAdapter { constructor( From e9589d2ccbcac8899cfcf2aabddda4604f05220c Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 10 Sep 2020 15:08:25 -0600 Subject: [PATCH 13/23] Drop the ComponentAdapter constructor placeholder code. --- src/client/pythonEnvironments/legacyIOC.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index a525966fefd8..1b0cc965e5c5 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -117,14 +117,7 @@ class ComponentAdapter implements IComponentAdapter { constructor( // The adapter only wraps one thing: the component API. private readonly api: PythonEnvironments - ) { - // For the moment we use this placeholder to exercise the property. - if (this.api.onChanged) { - this.api.onChanged((_event) => { - // do nothing - }); - } - } + ) {} // IInterpreterHelper From 6972c7c0ccd6d99545811bd3b780ead91efd818b Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 10 Sep 2020 15:25:18 -0600 Subject: [PATCH 14/23] Start out with the adapter disabled. --- src/client/interpreter/contracts.ts | 4 +-- src/client/pythonEnvironments/legacyIOC.ts | 32 ++++++++++++++++++++-- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/client/interpreter/contracts.ts b/src/client/interpreter/contracts.ts index 9be523db0a74..69e68928e16d 100644 --- a/src/client/interpreter/contracts.ts +++ b/src/client/interpreter/contracts.ts @@ -34,8 +34,8 @@ export interface IVirtualEnvironmentsSearchPathProvider { export const IComponentAdapter = Symbol('IComponentAdapter'); export interface IComponentAdapter { // IInterpreterLocatorService - hasInterpreters: Promise; - getInterpreters(resource?: Uri, options?: GetInterpreterLocatorOptions): Promise; + hasInterpreters: Promise | undefined; + getInterpreters(resource?: Uri, options?: GetInterpreterLocatorOptions): Promise; // IInterpreterService getInterpreterDetails(pythonPath: string, _resource?: Uri): Promise; // IInterpreterHelper diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index 1b0cc965e5c5..b67502461fee 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -116,12 +116,17 @@ function convertEnvInfo(info: PythonEnvInfo): PythonEnvironment { class ComponentAdapter implements IComponentAdapter { constructor( // The adapter only wraps one thing: the component API. - private readonly api: PythonEnvironments + private readonly api: PythonEnvironments, + // For now we effecitvely disable the component. + private readonly enabled = false ) {} // IInterpreterHelper public async getInterpreterInformation(pythonPath: string): Promise> { + if (!this.enabled) { + return undefined; + } const env = await this.api.resolveEnv(pythonPath); if (env === undefined) { return undefined; @@ -130,6 +135,9 @@ class ComponentAdapter implements IComponentAdapter { } public async isMacDefaultPythonPath(pythonPath: string): Promise { + if (!this.enabled) { + return undefined; + } const env = await this.api.resolveEnv(pythonPath); if (env === undefined) { return undefined; @@ -139,7 +147,10 @@ class ComponentAdapter implements IComponentAdapter { // IInterpreterService - public get hasInterpreters(): Promise { + public get hasInterpreters(): Promise | undefined { + if (!this.enabled) { + return undefined; + } const iterator = this.api.iterEnvs(); return iterator.next().then((res) => { return !res.done; @@ -149,6 +160,9 @@ class ComponentAdapter implements IComponentAdapter { //public async getInterpreters(_resource?: vscode.Uri, _options?: GetInterpreterOptions): Promise; public async getInterpreterDetails(pythonPath: string, _resource?: vscode.Uri): Promise { + if (!this.enabled) { + return undefined; + } const env = await this.api.resolveEnv(pythonPath); if (env === undefined) { return undefined; @@ -159,6 +173,9 @@ class ComponentAdapter implements IComponentAdapter { // ICondaService public async isCondaEnvironment(interpreterPath: string): Promise { + if (!this.enabled) { + return undefined; + } const env = await this.api.resolveEnv(interpreterPath); if (env === undefined) { return undefined; @@ -167,6 +184,9 @@ class ComponentAdapter implements IComponentAdapter { } public async getCondaEnvironment(interpreterPath: string): Promise { + if (!this.enabled) { + return undefined; + } const env = await this.api.resolveEnv(interpreterPath); if (env === undefined) { return undefined; @@ -184,6 +204,9 @@ class ComponentAdapter implements IComponentAdapter { // IWindowsStoreInterpreter public async isWindowsStoreInterpreter(pythonPath: string): Promise { + if (!this.enabled) { + return undefined; + } const env = await this.api.resolveEnv(pythonPath); if (env === undefined) { return undefined; @@ -196,7 +219,10 @@ class ComponentAdapter implements IComponentAdapter { public async getInterpreters( resource?: vscode.Uri, _options?: GetInterpreterLocatorOptions - ): Promise { + ): Promise { + if (!this.enabled) { + return undefined; + } // We ignore the options: //{ // ignoreCache?: boolean From 941f8c04c9855e6b4b21075807a04bc2cc11cba9 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 15 Sep 2020 17:18:27 -0600 Subject: [PATCH 15/23] lint --- src/client/pythonEnvironments/legacyIOC.ts | 37 ++++++++++++---------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index b67502461fee..f3cd30fa4edc 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -67,7 +67,7 @@ function convertEnvInfo(info: PythonEnvInfo): PythonEnvironment { envPath: info.location, path: info.executable.filename, architecture: info.arch, - sysPrefix: info.executable.sysPrefix + sysPrefix: info.executable.sysPrefix, }; if (info.kind === PythonEnvKind.System) { @@ -118,7 +118,7 @@ class ComponentAdapter implements IComponentAdapter { // The adapter only wraps one thing: the component API. private readonly api: PythonEnvironments, // For now we effecitvely disable the component. - private readonly enabled = false + private readonly enabled = false, ) {} // IInterpreterHelper @@ -152,14 +152,15 @@ class ComponentAdapter implements IComponentAdapter { return undefined; } const iterator = this.api.iterEnvs(); - return iterator.next().then((res) => { - return !res.done; - }); + return iterator.next().then((res) => !res.done); } - //public async getInterpreters(_resource?: vscode.Uri, _options?: GetInterpreterOptions): Promise; + // We use the same getInterpreters() here as for IInterpreterLocatorService. - public async getInterpreterDetails(pythonPath: string, _resource?: vscode.Uri): Promise { + public async getInterpreterDetails( + pythonPath: string, + _resource?: vscode.Uri, // eslint-disable-line @typescript-eslint/no-unused-vars + ): Promise { if (!this.enabled) { return undefined; } @@ -196,9 +197,9 @@ class ComponentAdapter implements IComponentAdapter { } if (env.name !== '') { return { name: env.name, path: '' }; - } else { - return { name: '', path: env.location }; } + // else + return { name: '', path: env.location }; } // IWindowsStoreInterpreter @@ -218,16 +219,16 @@ class ComponentAdapter implements IComponentAdapter { public async getInterpreters( resource?: vscode.Uri, - _options?: GetInterpreterLocatorOptions + _options?: GetInterpreterLocatorOptions, // eslint-disable-line @typescript-eslint/no-unused-vars ): Promise { if (!this.enabled) { return undefined; } // We ignore the options: - //{ - // ignoreCache?: boolean - // onSuggestion?: boolean; - //} + // { + // ignoreCache?: boolean + // onSuggestion?: boolean; + // } const query: PythonLocatorQuery = {}; if (resource !== undefined) { const wsFolder = vscode.workspace.getWorkspaceFolder(resource); @@ -241,13 +242,17 @@ class ComponentAdapter implements IComponentAdapter { let res = await iterator.next(); while (!res.done) { envs.push(convertEnvInfo(res.value)); - res = await iterator.next(); + res = await iterator.next(); // eslint-disable-line no-await-in-loop } return envs; } } -export function registerForIOC(serviceManager: IServiceManager, serviceContainer: IServiceContainer, api: PythonEnvironments): void { +export function registerForIOC( + serviceManager: IServiceManager, + serviceContainer: IServiceContainer, + api: PythonEnvironments, +): void { const adapter = new ComponentAdapter(api); serviceManager.addSingletonInstance(IComponentAdapter, adapter); From 3f79e87f4b6a650ccc531f2c44ff482530a2bd3c Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 15 Sep 2020 17:22:03 -0600 Subject: [PATCH 16/23] Avoid an import cycle. --- src/client/pythonEnvironments/legacyIOC.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index f3cd30fa4edc..60a841068c8c 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -27,7 +27,7 @@ import { import { IPipEnvServiceHelper, IPythonInPathCommandProvider } from '../interpreter/locators/types'; import { IServiceContainer, IServiceManager } from '../ioc/types'; import { PythonEnvInfo, PythonEnvKind, PythonReleaseLevel } from './base/info'; -import { PythonLocatorQuery } from './base/locator'; +import { ILocator, PythonLocatorQuery } from './base/locator'; import { initializeExternalDependencies } from './common/externalDependencies'; import { PythonInterpreterLocatorService } from './discovery/locators'; import { InterpreterLocatorHelper } from './discovery/locators/helpers'; @@ -58,8 +58,6 @@ import { GetInterpreterLocatorOptions } from './discovery/locators/types'; import { EnvironmentType, PythonEnvironment } from './info'; import { EnvironmentInfoService, IEnvironmentInfoService } from './info/environmentInfoService'; -import { PythonEnvironments } from '.'; - function convertEnvInfo(info: PythonEnvInfo): PythonEnvironment { const env: PythonEnvironment = { envType: EnvironmentType.Unknown, @@ -112,11 +110,13 @@ function convertEnvInfo(info: PythonEnvInfo): PythonEnvironment { return env; } +interface IPythonEnvironments extends ILocator {} + @injectable() class ComponentAdapter implements IComponentAdapter { constructor( // The adapter only wraps one thing: the component API. - private readonly api: PythonEnvironments, + private readonly api: IPythonEnvironments, // For now we effecitvely disable the component. private readonly enabled = false, ) {} @@ -251,7 +251,7 @@ class ComponentAdapter implements IComponentAdapter { export function registerForIOC( serviceManager: IServiceManager, serviceContainer: IServiceContainer, - api: PythonEnvironments, + api: IPythonEnvironments, ): void { const adapter = new ComponentAdapter(api); serviceManager.addSingletonInstance(IComponentAdapter, adapter); From 7769f092d4a17036f41ced5fb59cd5fb134388cb Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 15 Sep 2020 17:32:46 -0600 Subject: [PATCH 17/23] Use object destructuring for convertEnvInfo(). --- src/client/pythonEnvironments/legacyIOC.ts | 61 +++++++++++++--------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index 60a841068c8c..019803ffefab 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -59,52 +59,65 @@ import { EnvironmentType, PythonEnvironment } from './info'; import { EnvironmentInfoService, IEnvironmentInfoService } from './info/environmentInfoService'; function convertEnvInfo(info: PythonEnvInfo): PythonEnvironment { + const { + name, + location, + executable, + arch, + kind, + searchLocation, + version, + distro, + } = info; + const { filename, sysPrefix } = executable; const env: PythonEnvironment = { + sysPrefix, envType: EnvironmentType.Unknown, - envName: info.name, - envPath: info.location, - path: info.executable.filename, - architecture: info.arch, - sysPrefix: info.executable.sysPrefix, + envName: name, + envPath: location, + path: filename, + architecture: arch, }; - if (info.kind === PythonEnvKind.System) { + if (kind === PythonEnvKind.System) { env.envType = EnvironmentType.System; - } else if (info.kind === PythonEnvKind.MacDefault) { + } else if (kind === PythonEnvKind.MacDefault) { env.envType = EnvironmentType.System; - } else if (info.kind === PythonEnvKind.WindowsStore) { + } else if (kind === PythonEnvKind.WindowsStore) { env.envType = EnvironmentType.WindowsStore; - } else if (info.kind === PythonEnvKind.Pyenv) { + } else if (kind === PythonEnvKind.Pyenv) { env.envType = EnvironmentType.Pyenv; - } else if (info.kind === PythonEnvKind.Conda) { + } else if (kind === PythonEnvKind.Conda) { env.envType = EnvironmentType.Conda; - } else if (info.kind === PythonEnvKind.CondaBase) { + } else if (kind === PythonEnvKind.CondaBase) { env.envType = EnvironmentType.Conda; - } else if (info.kind === PythonEnvKind.VirtualEnv) { + } else if (kind === PythonEnvKind.VirtualEnv) { env.envType = EnvironmentType.VirtualEnv; - } else if (info.kind === PythonEnvKind.Pipenv) { + } else if (kind === PythonEnvKind.Pipenv) { env.envType = EnvironmentType.Pipenv; - if (info.searchLocation !== undefined) { - env.pipEnvWorkspaceFolder = info.searchLocation.fsPath; + if (searchLocation !== undefined) { + env.pipEnvWorkspaceFolder = searchLocation.fsPath; } - } else if (info.kind === PythonEnvKind.Venv) { + } else if (kind === PythonEnvKind.Venv) { env.envType = EnvironmentType.Venv; } // Otherwise it stays Unknown. - if (info.version !== undefined) { - const releaseStr = info.version.release.level === PythonReleaseLevel.Final + if (version !== undefined) { + const { release, sysVersion } = version; + const { level, serial } = release; + const releaseStr = level === PythonReleaseLevel.Final ? 'final' - : `${info.version.release.level}${info.version.release.serial}`; - const versionStr = `${getVersionString(info.version)}-${releaseStr}`; + : `${level}${serial}`; + const versionStr = `${getVersionString(version)}-${releaseStr}`; env.version = parseVersion(versionStr); - env.sysVersion = info.version.sysVersion; + env.sysVersion = sysVersion; } - if (info.distro !== undefined && info.distro.org !== '') { - env.companyDisplayName = info.distro.org; + if (distro !== undefined && distro.org !== '') { + env.companyDisplayName = distro.org; } - // We do not worry about using info.distro.defaultDisplayName + // We do not worry about using distro.defaultDisplayName // or info.defaultDisplayName. return env; From 99add1f4f41fa9602806cc11d195d330d2b3a13b Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 16 Sep 2020 12:58:57 -0600 Subject: [PATCH 18/23] Use the "resource" arg in getInterpreterDetails(). --- src/client/pythonEnvironments/legacyIOC.ts | 41 ++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index 019803ffefab..b99d4c76e030 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -3,6 +3,7 @@ import { injectable } from 'inversify'; import * as vscode from 'vscode'; +import { Architecture } from '../common/utils/platform'; import { getVersionString, parseVersion } from '../common/utils/version'; import { CONDA_ENV_FILE_SERVICE, @@ -123,6 +124,34 @@ function convertEnvInfo(info: PythonEnvInfo): PythonEnvironment { return env; } +function buildEmptyEnvInfo(): PythonEnvInfo { + return { + id: '', + kind: PythonEnvKind.Unknown, + executable: { + filename: '', + sysPrefix: '', + ctime: -1, + mtime: -1, + }, + name: '', + location: '', + version: { + major: -1, + minor: -1, + micro: -1, + release: { + level: PythonReleaseLevel.Final, + serial: 0, + }, + }, + arch: Architecture.Unknown, + distro: { + org: '', + }, + }; +} + interface IPythonEnvironments extends ILocator {} @injectable() @@ -172,12 +201,20 @@ class ComponentAdapter implements IComponentAdapter { public async getInterpreterDetails( pythonPath: string, - _resource?: vscode.Uri, // eslint-disable-line @typescript-eslint/no-unused-vars + resource?: vscode.Uri, ): Promise { if (!this.enabled) { return undefined; } - const env = await this.api.resolveEnv(pythonPath); + const info = buildEmptyEnvInfo(); + info.executable.filename = pythonPath; + if (resource !== undefined) { + const wsFolder = vscode.workspace.getWorkspaceFolder(resource); + if (wsFolder !== undefined) { + info.searchLocation = wsFolder.uri; + } + } + const env = await this.api.resolveEnv(info); if (env === undefined) { return undefined; } From ed94edfea62ceb2bffcd4eef027669cad7a1f345 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 16 Sep 2020 13:02:44 -0600 Subject: [PATCH 19/23] Drop "options" from the adapter getInterpreters(). --- src/client/interpreter/contracts.ts | 2 +- src/client/pythonEnvironments/legacyIOC.ts | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/client/interpreter/contracts.ts b/src/client/interpreter/contracts.ts index 69e68928e16d..2ca715db6cb1 100644 --- a/src/client/interpreter/contracts.ts +++ b/src/client/interpreter/contracts.ts @@ -35,7 +35,7 @@ export const IComponentAdapter = Symbol('IComponentAdapter'); export interface IComponentAdapter { // IInterpreterLocatorService hasInterpreters: Promise | undefined; - getInterpreters(resource?: Uri, options?: GetInterpreterLocatorOptions): Promise; + getInterpreters(resource?: Uri): Promise; // IInterpreterService getInterpreterDetails(pythonPath: string, _resource?: Uri): Promise; // IInterpreterHelper diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index b99d4c76e030..47ed29e8c9d7 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -55,7 +55,6 @@ import { WorkspaceVirtualEnvService, } from './discovery/locators/services/workspaceVirtualEnvService'; import { WorkspaceVirtualEnvWatcherService } from './discovery/locators/services/workspaceVirtualEnvWatcherService'; -import { GetInterpreterLocatorOptions } from './discovery/locators/types'; import { EnvironmentType, PythonEnvironment } from './info'; import { EnvironmentInfoService, IEnvironmentInfoService } from './info/environmentInfoService'; @@ -269,16 +268,15 @@ class ComponentAdapter implements IComponentAdapter { public async getInterpreters( resource?: vscode.Uri, - _options?: GetInterpreterLocatorOptions, // eslint-disable-line @typescript-eslint/no-unused-vars - ): Promise { - if (!this.enabled) { - return undefined; - } - // We ignore the options: + // Currently we have no plans to support GetInterpreterLocatorOptions: // { // ignoreCache?: boolean // onSuggestion?: boolean; // } + ): Promise { + if (!this.enabled) { + return undefined; + } const query: PythonLocatorQuery = {}; if (resource !== undefined) { const wsFolder = vscode.workspace.getWorkspaceFolder(resource); From 5e380ffb30e88e9dd2f6bbcbe09a7bdc14b53e68 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 16 Sep 2020 13:03:44 -0600 Subject: [PATCH 20/23] Fix a typo. --- src/client/pythonEnvironments/legacyIOC.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index 47ed29e8c9d7..877a2e7872d5 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -158,7 +158,7 @@ class ComponentAdapter implements IComponentAdapter { constructor( // The adapter only wraps one thing: the component API. private readonly api: IPythonEnvironments, - // For now we effecitvely disable the component. + // For now we effectively disable the component. private readonly enabled = false, ) {} From 6667d60e68d544af4da6c5c34957736131ed81bd Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 16 Sep 2020 13:12:35 -0600 Subject: [PATCH 21/23] Clarify about when `undefined` is returned from the adapter methods. --- src/client/interpreter/contracts.ts | 2 +- src/client/pythonEnvironments/legacyIOC.ts | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/client/interpreter/contracts.ts b/src/client/interpreter/contracts.ts index 2ca715db6cb1..c1ad838a9e10 100644 --- a/src/client/interpreter/contracts.ts +++ b/src/client/interpreter/contracts.ts @@ -34,7 +34,7 @@ export interface IVirtualEnvironmentsSearchPathProvider { export const IComponentAdapter = Symbol('IComponentAdapter'); export interface IComponentAdapter { // IInterpreterLocatorService - hasInterpreters: Promise | undefined; + hasInterpreters: Promise; getInterpreters(resource?: Uri): Promise; // IInterpreterService getInterpreterDetails(pythonPath: string, _resource?: Uri): Promise; diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index 877a2e7872d5..d306f20d7817 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -164,6 +164,7 @@ class ComponentAdapter implements IComponentAdapter { // IInterpreterHelper + // A result of `undefined` means "Fall back to the old code!" public async getInterpreterInformation(pythonPath: string): Promise> { if (!this.enabled) { return undefined; @@ -175,6 +176,7 @@ class ComponentAdapter implements IComponentAdapter { return convertEnvInfo(env); } + // A result of `undefined` means "Fall back to the old code!" public async isMacDefaultPythonPath(pythonPath: string): Promise { if (!this.enabled) { return undefined; @@ -188,9 +190,10 @@ class ComponentAdapter implements IComponentAdapter { // IInterpreterService - public get hasInterpreters(): Promise | undefined { + // A result of `undefined` means "Fall back to the old code!" + public get hasInterpreters(): Promise { if (!this.enabled) { - return undefined; + return Promise.resolve(undefined); } const iterator = this.api.iterEnvs(); return iterator.next().then((res) => !res.done); @@ -198,6 +201,7 @@ class ComponentAdapter implements IComponentAdapter { // We use the same getInterpreters() here as for IInterpreterLocatorService. + // A result of `undefined` means "Fall back to the old code!" public async getInterpreterDetails( pythonPath: string, resource?: vscode.Uri, @@ -222,6 +226,7 @@ class ComponentAdapter implements IComponentAdapter { // ICondaService + // A result of `undefined` means "Fall back to the old code!" public async isCondaEnvironment(interpreterPath: string): Promise { if (!this.enabled) { return undefined; @@ -233,6 +238,7 @@ class ComponentAdapter implements IComponentAdapter { return env.kind === PythonEnvKind.Conda; } + // A result of `undefined` means "Fall back to the old code!" public async getCondaEnvironment(interpreterPath: string): Promise { if (!this.enabled) { return undefined; @@ -253,6 +259,7 @@ class ComponentAdapter implements IComponentAdapter { // IWindowsStoreInterpreter + // A result of `undefined` means "Fall back to the old code!" public async isWindowsStoreInterpreter(pythonPath: string): Promise { if (!this.enabled) { return undefined; @@ -266,6 +273,7 @@ class ComponentAdapter implements IComponentAdapter { // IInterpreterLocatorService + // A result of `undefined` means "Fall back to the old code!" public async getInterpreters( resource?: vscode.Uri, // Currently we have no plans to support GetInterpreterLocatorOptions: From 4271fd4ee378bc587c4625520238f01a8d396e02 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 16 Sep 2020 13:28:42 -0600 Subject: [PATCH 22/23] Use a map for converting the env kinds. --- src/client/pythonEnvironments/legacyIOC.ts | 40 +++++++++++----------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index d306f20d7817..24cf4e357ece 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -58,6 +58,18 @@ import { WorkspaceVirtualEnvWatcherService } from './discovery/locators/services import { EnvironmentType, PythonEnvironment } from './info'; import { EnvironmentInfoService, IEnvironmentInfoService } from './info/environmentInfoService'; +const convertedKinds = new Map(Object.entries({ + [PythonEnvKind.System]: EnvironmentType.System, + [PythonEnvKind.MacDefault]: EnvironmentType.System, + [PythonEnvKind.WindowsStore]: EnvironmentType.WindowsStore, + [PythonEnvKind.Pyenv]: EnvironmentType.Pyenv, + [PythonEnvKind.Conda]: EnvironmentType.Conda, + [PythonEnvKind.CondaBase]: EnvironmentType.Conda, + [PythonEnvKind.VirtualEnv]: EnvironmentType.VirtualEnv, + [PythonEnvKind.Pipenv]: EnvironmentType.Pipenv, + [PythonEnvKind.Venv]: EnvironmentType.Venv, +})); + function convertEnvInfo(info: PythonEnvInfo): PythonEnvironment { const { name, @@ -79,29 +91,17 @@ function convertEnvInfo(info: PythonEnvInfo): PythonEnvironment { architecture: arch, }; - if (kind === PythonEnvKind.System) { - env.envType = EnvironmentType.System; - } else if (kind === PythonEnvKind.MacDefault) { - env.envType = EnvironmentType.System; - } else if (kind === PythonEnvKind.WindowsStore) { - env.envType = EnvironmentType.WindowsStore; - } else if (kind === PythonEnvKind.Pyenv) { - env.envType = EnvironmentType.Pyenv; - } else if (kind === PythonEnvKind.Conda) { - env.envType = EnvironmentType.Conda; - } else if (kind === PythonEnvKind.CondaBase) { - env.envType = EnvironmentType.Conda; - } else if (kind === PythonEnvKind.VirtualEnv) { - env.envType = EnvironmentType.VirtualEnv; - } else if (kind === PythonEnvKind.Pipenv) { - env.envType = EnvironmentType.Pipenv; - if (searchLocation !== undefined) { + const envType = convertedKinds.get(kind); + if (envType !== undefined) { + env.envType = envType; + } + // Otherwise it stays Unknown. + + if (searchLocation !== undefined) { + if (kind === PythonEnvKind.Pipenv) { env.pipEnvWorkspaceFolder = searchLocation.fsPath; } - } else if (kind === PythonEnvKind.Venv) { - env.envType = EnvironmentType.Venv; } - // Otherwise it stays Unknown. if (version !== undefined) { const { release, sysVersion } = version; From c04c6f51e6a7bfa2201bbfbc74509e118d911e61 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 16 Sep 2020 15:33:39 -0600 Subject: [PATCH 23/23] Handle iterator.onUpdated in ComponentAdapter.getInterpreters(). --- src/client/pythonEnvironments/legacyIOC.ts | 30 ++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index 24cf4e357ece..49abb879ccbf 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -3,6 +3,7 @@ import { injectable } from 'inversify'; import * as vscode from 'vscode'; +import { createDeferred } from '../common/utils/async'; import { Architecture } from '../common/utils/platform'; import { getVersionString, parseVersion } from '../common/utils/version'; import { @@ -293,14 +294,39 @@ class ComponentAdapter implements IComponentAdapter { } } + const deferred = createDeferred(); const envs: PythonEnvironment[] = []; + const executableToLegacy: Record = {}; const iterator = this.api.iterEnvs(query); + + if (iterator.onUpdated !== undefined) { + iterator.onUpdated((event) => { + if (event === null) { + deferred.resolve(envs); + } else { + // Replace the old one. + const old = executableToLegacy[event.old.executable.filename]; + if (old !== undefined) { + const index = envs.indexOf(old); + if (index !== -1) { + envs[index] = convertEnvInfo(event.new); + } + } + } + }); + } else { + deferred.resolve(envs); + } + let res = await iterator.next(); while (!res.done) { - envs.push(convertEnvInfo(res.value)); + const env = convertEnvInfo(res.value); + envs.push(env); + executableToLegacy[env.path] = env; res = await iterator.next(); // eslint-disable-line no-await-in-loop } - return envs; + + return deferred.promise; } }