diff --git a/src/client/pythonEnvironments/base/locators/lowLevel/filesLocator.ts b/src/client/pythonEnvironments/base/locators/lowLevel/filesLocator.ts index db246af2ec79..301625ea1ac0 100644 --- a/src/client/pythonEnvironments/base/locators/lowLevel/filesLocator.ts +++ b/src/client/pythonEnvironments/base/locators/lowLevel/filesLocator.ts @@ -5,6 +5,7 @@ /* eslint-disable max-classes-per-file */ import { Event, EventEmitter } from 'vscode'; +import { traceError } from '../../../../common/logger'; import { DirEntry } from '../../../../common/utils/filesystem'; import { iterPythonExecutablesInDir } from '../../../common/commonUtils'; import { resolvePath } from '../../../common/externalDependencies'; @@ -65,7 +66,11 @@ async function* iterMinimalEnvsFromExecutables( for await (const executable of executables) { const filename = typeof executable === 'string' ? executable : executable.filename; const normFile = resolvePath(filename); - yield getFastEnvInfo(defaultKind, normFile); + try { + yield getFastEnvInfo(defaultKind, normFile); + } catch (ex) { + traceError(`Failed to process environment: ${normFile}`, ex); + } } } diff --git a/src/client/pythonEnvironments/base/locators/lowLevel/workspaceVirtualEnvLocator.ts b/src/client/pythonEnvironments/base/locators/lowLevel/workspaceVirtualEnvLocator.ts index 6c3420d3fc09..3bf0dfa60d4f 100644 --- a/src/client/pythonEnvironments/base/locators/lowLevel/workspaceVirtualEnvLocator.ts +++ b/src/client/pythonEnvironments/base/locators/lowLevel/workspaceVirtualEnvLocator.ts @@ -4,7 +4,7 @@ import { uniq } from 'lodash'; import * as path from 'path'; import { Uri } from 'vscode'; -import { traceVerbose } from '../../../../common/logger'; +import { traceError, traceVerbose } from '../../../../common/logger'; import { chain, iterable } from '../../../../common/utils/async'; import { findInterpretersInDir, @@ -126,8 +126,12 @@ export class WorkspaceVirtualEnvironmentLocator extends FSWatchingLocator { // We don't know the environment type so skip this one. traceVerbose(`Workspace Virtual Environment: [skipped] ${filename}`); } else { - yield buildSimpleVirtualEnvInfo(filename, kind); - traceVerbose(`Workspace Virtual Environment: [added] ${filename}`); + try { + yield buildSimpleVirtualEnvInfo(filename, kind); + traceVerbose(`Workspace Virtual Environment: [added] ${filename}`); + } catch (ex) { + traceError(`Failed to process environment: ${filename}`, ex); + } } } else { traceVerbose(`Workspace Virtual Environment: [skipped] ${filename}`); diff --git a/src/client/pythonEnvironments/discovery/locators/services/condaLocator.ts b/src/client/pythonEnvironments/discovery/locators/services/condaLocator.ts index 6a4b72d5dc9a..b1d77b64d20b 100644 --- a/src/client/pythonEnvironments/discovery/locators/services/condaLocator.ts +++ b/src/client/pythonEnvironments/discovery/locators/services/condaLocator.ts @@ -7,7 +7,7 @@ import { IPythonEnvsIterator, Locator } from '../../../base/locator'; import { getInterpreterPathFromDir, getPythonVersionFromPath } from '../../../common/commonUtils'; import { AnacondaCompanyName, Conda } from './conda'; import { resolveEnvFromIterator } from '../../../base/locatorUtils'; -import { traceVerbose } from '../../../../common/logger'; +import { traceError, traceVerbose } from '../../../../common/logger'; export class CondaEnvironmentLocator extends Locator { // Locating conda binary is expensive, since it potentially involves spawning or @@ -54,8 +54,12 @@ export class CondaEnvironmentLocator extends Locator { if (name) { info.name = name; } - traceVerbose(`Found conda environment: ${info}`); - yield info; + traceVerbose(`Found conda environment: ${executable}`); + try { + yield info; + } catch (ex) { + traceError(`Failed to process environment: ${executable}`, ex); + } } } } diff --git a/src/client/pythonEnvironments/discovery/locators/services/customVirtualEnvLocator.ts b/src/client/pythonEnvironments/discovery/locators/services/customVirtualEnvLocator.ts index 34693efd9760..44d1866314fd 100644 --- a/src/client/pythonEnvironments/discovery/locators/services/customVirtualEnvLocator.ts +++ b/src/client/pythonEnvironments/discovery/locators/services/customVirtualEnvLocator.ts @@ -3,7 +3,7 @@ import { uniq } from 'lodash'; import * as path from 'path'; -import { traceVerbose } from '../../../../common/logger'; +import { traceError, traceVerbose } from '../../../../common/logger'; import { chain, iterable } from '../../../../common/utils/async'; import { getUserHomeDir } from '../../../../common/utils/platform'; import { PythonEnvInfo, PythonEnvKind, PythonEnvSource } from '../../../base/info'; @@ -134,12 +134,16 @@ export class CustomVirtualEnvironmentLocator extends FSWatchingLocator { // python.exe or python in the same directory in the case of virtual // environments. if (await looksLikeBasicVirtualPython(entry)) { - // We should extract the kind here to avoid doing is*Environment() - // check multiple times. Those checks are file system heavy and - // we can use the kind to determine this anyway. - const kind = await getVirtualEnvKind(filename); - yield buildSimpleVirtualEnvInfo(filename, kind); - traceVerbose(`Custom Virtual Environment: [added] ${filename}`); + try { + // We should extract the kind here to avoid doing is*Environment() + // check multiple times. Those checks are file system heavy and + // we can use the kind to determine this anyway. + const kind = await getVirtualEnvKind(filename); + yield buildSimpleVirtualEnvInfo(filename, kind); + traceVerbose(`Custom Virtual Environment: [added] ${filename}`); + } catch (ex) { + traceError(`Failed to process environment: ${filename}`, ex); + } } else { traceVerbose(`Custom Virtual Environment: [skipped] ${filename}`); } diff --git a/src/client/pythonEnvironments/discovery/locators/services/globalVirtualEnvronmentLocator.ts b/src/client/pythonEnvironments/discovery/locators/services/globalVirtualEnvronmentLocator.ts index 8a73c681e99f..d58d435c024a 100644 --- a/src/client/pythonEnvironments/discovery/locators/services/globalVirtualEnvronmentLocator.ts +++ b/src/client/pythonEnvironments/discovery/locators/services/globalVirtualEnvronmentLocator.ts @@ -3,7 +3,7 @@ import { uniq } from 'lodash'; import * as path from 'path'; -import { traceVerbose } from '../../../../common/logger'; +import { traceError, traceVerbose } from '../../../../common/logger'; import { chain, iterable } from '../../../../common/utils/async'; import { getEnvironmentVariable, getOSType, getUserHomeDir, OSType } from '../../../../common/utils/platform'; import { PythonEnvInfo, PythonEnvKind, PythonEnvSource } from '../../../base/info'; @@ -138,8 +138,12 @@ export class GlobalVirtualEnvironmentLocator extends FSWatchingLocator { // We don't know the environment type so skip this one. traceVerbose(`Global Virtual Environment: [skipped] ${filename}`); } else { - yield buildSimpleVirtualEnvInfo(filename, kind); - traceVerbose(`Global Virtual Environment: [added] ${filename}`); + try { + yield buildSimpleVirtualEnvInfo(filename, kind); + traceVerbose(`Global Virtual Environment: [added] ${filename}`); + } catch (ex) { + traceError(`Failed to process environment: ${filename}`, ex); + } } } else { traceVerbose(`Global Virtual Environment: [skipped] ${filename}`); diff --git a/src/client/pythonEnvironments/discovery/locators/services/poetryLocator.ts b/src/client/pythonEnvironments/discovery/locators/services/poetryLocator.ts index ceea52de2d67..a0c7a03d8ed7 100644 --- a/src/client/pythonEnvironments/discovery/locators/services/poetryLocator.ts +++ b/src/client/pythonEnvironments/discovery/locators/services/poetryLocator.ts @@ -6,7 +6,7 @@ import { uniq } from 'lodash'; import * as path from 'path'; import { Uri } from 'vscode'; -import { traceVerbose } from '../../../../common/logger'; +import { traceError, traceVerbose } from '../../../../common/logger'; import { chain, iterable } from '../../../../common/utils/async'; import { PythonEnvInfo, PythonEnvKind, PythonEnvSource } from '../../../base/info'; import { buildEnvInfo } from '../../../base/info/env'; @@ -118,11 +118,15 @@ export class PoetryLocator extends FSWatchingLocator { `Poetry Virtual Environment: [skipped] ${filename} (reason: Not poetry environment)`, ); } else { - // We should extract the kind here to avoid doing is*Environment() - // check multiple times. Those checks are file system heavy and - // we can use the kind to determine this anyway. - yield buildVirtualEnvInfo(filename, kind, undefined, isLocal); - traceVerbose(`Poetry Virtual Environment: [added] ${filename}`); + try { + // We should extract the kind here to avoid doing is*Environment() + // check multiple times. Those checks are file system heavy and + // we can use the kind to determine this anyway. + yield buildVirtualEnvInfo(filename, kind, undefined, isLocal); + traceVerbose(`Poetry Virtual Environment: [added] ${filename}`); + } catch (ex) { + traceError(`Failed to process environment: ${filename}`, ex); + } } } } diff --git a/src/client/pythonEnvironments/discovery/locators/services/posixKnownPathsLocator.ts b/src/client/pythonEnvironments/discovery/locators/services/posixKnownPathsLocator.ts index c2a4ddcda29d..25813832d047 100644 --- a/src/client/pythonEnvironments/discovery/locators/services/posixKnownPathsLocator.ts +++ b/src/client/pythonEnvironments/discovery/locators/services/posixKnownPathsLocator.ts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import * as path from 'path'; -import { traceError } from '../../../../common/logger'; +import { traceError, traceVerbose } from '../../../../common/logger'; import { Architecture } from '../../../../common/utils/platform'; import { PythonEnvInfo, PythonEnvKind, PythonEnvSource, PythonReleaseLevel, PythonVersion } from '../../../base/info'; import { buildEnvInfo } from '../../../base/info/env'; @@ -22,8 +22,14 @@ export class PosixKnownPathsLocator extends Locator { // the binaries specified in .python-version file in the cwd. We should not be reporting // those binaries as environments. const knownDirs = (await commonPosixBinPaths()).filter((dirname) => !isPyenvShimDir(dirname)); - const exes = await getPythonBinFromPosixPaths(knownDirs); - yield* exes.map(buildPathEnvInfo); + const pythonBinaries = await getPythonBinFromPosixPaths(knownDirs); + for (const bin of pythonBinaries) { + try { + yield buildPathEnvInfo(bin); + } catch (ex) { + traceError(`Failed to process environment: ${bin}`, ex); + } + } }; return iterator(); } @@ -38,7 +44,7 @@ export class PosixKnownPathsLocator extends Locator { try { version = parseVersion(path.basename(bin)); } catch (ex) { - traceError(`Failed to parse version from path: ${bin}`, ex); + traceVerbose(`Failed to parse version from path: ${bin}`, ex); version = { major: -1, minor: -1, diff --git a/src/client/pythonEnvironments/discovery/locators/services/pyenvLocator.ts b/src/client/pythonEnvironments/discovery/locators/services/pyenvLocator.ts index 929158ef296f..ffc835271b7b 100644 --- a/src/client/pythonEnvironments/discovery/locators/services/pyenvLocator.ts +++ b/src/client/pythonEnvironments/discovery/locators/services/pyenvLocator.ts @@ -3,6 +3,7 @@ import { uniq } from 'lodash'; import * as path from 'path'; +import { traceError } from '../../../../common/logger'; import { getEnvironmentVariable, getOSType, getUserHomeDir, OSType } from '../../../../common/utils/platform'; import { PythonEnvInfo, PythonEnvKind, PythonEnvSource } from '../../../base/info'; import { buildEnvInfo } from '../../../base/info/env'; @@ -266,50 +267,53 @@ async function* getPyenvEnvironments(): AsyncIterableIterator { const interpreterPath = await getInterpreterPathFromDir(subDirPath); if (interpreterPath) { - // The sub-directory name sometimes can contain distro and python versions. - // here we attempt to extract the texts out of the name. - const versionStrings = await parsePyenvVersion(envDirName); - - // Here we look for near by files, or config files to see if we can get python version info - // without running python itself. - const pythonVersion = await getPythonVersionFromPath(interpreterPath, versionStrings?.pythonVer); - - // Pyenv environments can fall in to these three categories: - // 1. Global Installs : These are environments that are created when you install - // a supported python distribution using `pyenv install ` command. - // These behave similar to globally installed version of python or distribution. - // - // 2. Virtual Envs : These are environments that are created when you use - // `pyenv virtualenv `. These are similar to environments - // created using `python -m venv `. - // - // 3. Conda Envs : These are environments that are created when you use - // `pyenv virtualenv `. These are similar to - // environments created using `conda create -n . - // - // All these environments are fully handled by `pyenv` and should be activated using - // `pyenv local|global ` or `pyenv shell ` - // - // For the display name we are going to treat these as `pyenv` environments. - const display = `${envDirName}:pyenv`; - - const org = versionStrings && versionStrings.distro ? versionStrings.distro : ''; - - const fileInfo = await getFileInfo(interpreterPath); - - const envInfo = buildEnvInfo({ - kind: PythonEnvKind.Pyenv, - executable: interpreterPath, - location: subDirPath, - version: pythonVersion, - source: [PythonEnvSource.Pyenv], - display, - org, - fileInfo, - }); - envInfo.name = envDirName; - - yield envInfo; + try { + // The sub-directory name sometimes can contain distro and python versions. + // here we attempt to extract the texts out of the name. + const versionStrings = await parsePyenvVersion(envDirName); + + // Here we look for near by files, or config files to see if we can get python version info + // without running python itself. + const pythonVersion = await getPythonVersionFromPath(interpreterPath, versionStrings?.pythonVer); + + // Pyenv environments can fall in to these three categories: + // 1. Global Installs : These are environments that are created when you install + // a supported python distribution using `pyenv install ` command. + // These behave similar to globally installed version of python or distribution. + // + // 2. Virtual Envs : These are environments that are created when you use + // `pyenv virtualenv `. These are similar to environments + // created using `python -m venv `. + // + // 3. Conda Envs : These are environments that are created when you use + // `pyenv virtualenv `. These are similar to + // environments created using `conda create -n . + // + // All these environments are fully handled by `pyenv` and should be activated using + // `pyenv local|global ` or `pyenv shell ` + // + // For the display name we are going to treat these as `pyenv` environments. + const display = `${envDirName}:pyenv`; + + const org = versionStrings && versionStrings.distro ? versionStrings.distro : ''; + + const fileInfo = await getFileInfo(interpreterPath); + + const envInfo = buildEnvInfo({ + kind: PythonEnvKind.Pyenv, + executable: interpreterPath, + location: subDirPath, + version: pythonVersion, + source: [PythonEnvSource.Pyenv], + display, + org, + fileInfo, + }); + envInfo.name = envDirName; + yield envInfo; + } catch (ex) { + traceError(`Failed to process environment: ${interpreterPath}`, ex); + } } } } diff --git a/src/client/pythonEnvironments/discovery/locators/services/windowsRegistryLocator.ts b/src/client/pythonEnvironments/discovery/locators/services/windowsRegistryLocator.ts index 26efc7891cdc..4227c8571d0e 100644 --- a/src/client/pythonEnvironments/discovery/locators/services/windowsRegistryLocator.ts +++ b/src/client/pythonEnvironments/discovery/locators/services/windowsRegistryLocator.ts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import { uniq } from 'lodash'; -import { traceVerbose } from '../../../../common/logger'; +import { traceError, traceVerbose } from '../../../../common/logger'; import { Architecture } from '../../../../common/utils/platform'; import { PythonEnvInfo, @@ -32,7 +32,13 @@ export class WindowsRegistryLocator extends Locator { const buildRegistryEnvInfo = (data: IRegistryInterpreterData) => this.buildRegistryEnvInfo(data); const iterator = async function* () { const interpreters = await getRegistryInterpreters(); - yield* interpreters.map(buildRegistryEnvInfo); + for (const interpreter of interpreters) { + try { + yield buildRegistryEnvInfo(interpreter); + } catch (ex) { + traceError(`Failed to process environment: ${interpreter}`, ex); + } + } }; return iterator(); }