Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions news/2 Fixes/17362.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Ensure we correctly evaluate Unknown type before sending startup telemetry.
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ export class EnvsCollectionService extends PythonEnvsWatcher<PythonEnvCollection
if (cachedEnv && this.refreshPromises.size === 0) {
return cachedEnv;
}
return this.locator.resolveEnv(executablePath);
const resolved = await this.locator.resolveEnv(executablePath);
if (resolved) {
this.cache.addEnv(resolved);
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If user has selected an interpreter which is not discovery cache (maybe a new type of virtual env we do not support), this is useful.

}
return resolved;
}

public getEnvs(query?: PythonLocatorQuery): PythonEnvInfo[] {
Expand Down
2 changes: 2 additions & 0 deletions src/client/pythonEnvironments/common/environmentIdentifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { PythonEnvKind } from '../base/info';
import { getPrioritizedEnvKinds } from '../base/info/envKind';
import { isCondaEnvironment } from './environmentManagers/conda';
import { isGloballyInstalledEnv } from './environmentManagers/globalInstalledEnvs';
import { isPipenvEnvironment } from './environmentManagers/pipenv';
import { isPoetryEnvironment } from './environmentManagers/poetry';
import { isPyenvEnvironment } from './environmentManagers/pyenv';
Expand Down Expand Up @@ -31,6 +32,7 @@ function getIdentifiers(): Map<PythonEnvKind, (path: string) => Promise<boolean>
identifier.set(PythonEnvKind.VirtualEnvWrapper, isVirtualEnvWrapperEnvironment);
identifier.set(PythonEnvKind.VirtualEnv, isVirtualEnvEnvironment);
identifier.set(PythonEnvKind.Unknown, defaultTrue);
identifier.set(PythonEnvKind.OtherGlobal, isGloballyInstalledEnv);
return identifier;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import { getSearchPathEntries } from '../../../common/utils/exec';
import { getOSType, OSType } from '../../../common/utils/platform';
import { isParentPath } from '../externalDependencies';
import { commonPosixBinPaths } from '../posixUtils';
import { isPyenvShimDir } from './pyenv';

/**
* Checks if the given interpreter belongs to known globally installed types. If an global
* executable is discoverable, we consider it as global type.
* @param {string} interpreterPath: Absolute path to the python interpreter.
* @returns {boolean} : Returns true if the interpreter belongs to a venv environment.
*/
export async function isGloballyInstalledEnv(executablePath: string): Promise<boolean> {
// Identifying this type is not important, as the extension treats `Global` and `Unknown`
// types the same way. This is only required for telemetry. As windows registry is known
// to be slow, we do not want to unnecessarily block on that by default, hence skip this
// step.
// if (getOSType() === OSType.Windows) {
// if (await isFoundInWindowsRegistry(executablePath)) {
// return true;
// }
// }
return isFoundInPathEnvVar(executablePath);
}

async function isFoundInPathEnvVar(executablePath: string): Promise<boolean> {
let searchPathEntries: string[] = [];
if (getOSType() === OSType.Windows) {
searchPathEntries = getSearchPathEntries();
} else {
searchPathEntries = await commonPosixBinPaths();
}
// Filter out pyenv shims. They are not actual python binaries, they are used to launch
// the binaries specified in .python-version file in the cwd. We should not be reporting
// those binaries as environments.
searchPathEntries = searchPathEntries.filter((dirname) => !isPyenvShimDir(dirname));
for (const searchPath of searchPathEntries) {
if (isParentPath(executablePath, searchPath)) {
return true;
}
}
return false;
}
12 changes: 10 additions & 2 deletions src/client/startupTelemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,23 @@ async function getActivationTelemetryProps(serviceContainer: IServiceContainer):
? workspaceService.workspaceFolders![0].uri
: undefined;
const settings = configurationService.getSettings(mainWorkspaceUri);
const [condaVersion, interpreter, hasPython3] = await Promise.all([
const [condaVersion, hasPython3] = await Promise.all([
condaLocator
.getCondaVersion()
.then((ver) => (ver ? ver.raw : ''))
.catch<string>(() => ''),
interpreterService.getActiveInterpreter().catch<PythonEnvironment | undefined>(() => undefined),
interpreterService.hasInterpreters(async (item) => item.version?.major === 3),
]);
const workspaceFolderCount = workspaceService.hasWorkspaceFolders ? workspaceService.workspaceFolders!.length : 0;
// If an unknown type environment can be found from windows registry or path env var,
// consider them as global type instead of unknown. Such types can only be known after
// windows registry is queried. So wait for the refresh of windows registry locator to
// finish. API getActiveInterpreter() does not block on windows registry by default as
// it is slow.
await interpreterService.refreshPromise;
const interpreter = await interpreterService
.getActiveInterpreter()
.catch<PythonEnvironment | undefined>(() => undefined);
const pythonVersion = interpreter && interpreter.version ? interpreter.version.raw : undefined;
const interpreterType = interpreter ? interpreter.envType : undefined;
const usingUserDefinedInterpreter = hasUserDefinedPythonPath(mainWorkspaceUri, serviceContainer);
Expand Down