Skip to content

Commit

Permalink
Fix for prefix conda environments (#24553)
Browse files Browse the repository at this point in the history
For #24472
  • Loading branch information
karthiknadig authored Dec 11, 2024
1 parent 33b5e97 commit 32512b1
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 7 deletions.
14 changes: 14 additions & 0 deletions src/client/pythonEnvironments/common/environmentManagers/conda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,15 @@ export class Conda {
);
}

/**
* Retrieves list of directories where conda environments are stored.
*/
@cache(30_000, true, 10_000)
public async getEnvDirs(): Promise<string[]> {
const info = await this.getInfo();
return info.envs_dirs ?? [];
}

public async getName(prefix: string, info?: CondaInfo): Promise<string | undefined> {
info = info ?? (await this.getInfo(true));
if (info.root_prefix && arePathsSame(prefix, info.root_prefix)) {
Expand Down Expand Up @@ -619,3 +628,8 @@ export class Conda {
export function setCondaBinary(executable: string): void {
Conda.setConda(executable);
}

export async function getCondaEnvDirs(): Promise<string[] | undefined> {
const conda = await Conda.getConda();
return conda?.getEnvDirs();
}
49 changes: 42 additions & 7 deletions src/client/pythonEnvironments/nativeAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ import { createDeferred, Deferred } from '../common/utils/async';
import { Architecture, getUserHomeDir } from '../common/utils/platform';
import { parseVersion } from './base/info/pythonVersion';
import { cache } from '../common/utils/decorators';
import { traceError, traceLog, traceWarn } from '../logging';
import { traceError, traceInfo, traceLog, traceWarn } from '../logging';
import { StopWatch } from '../common/utils/stopWatch';
import { FileChangeType } from '../common/platform/fileSystemWatcher';
import { categoryToKind, NativePythonEnvironmentKind } from './base/locators/common/nativePythonUtils';
import { setCondaBinary } from './common/environmentManagers/conda';
import { getCondaEnvDirs, setCondaBinary } from './common/environmentManagers/conda';
import { setPyEnvBinary } from './common/environmentManagers/pyenv';
import {
createPythonWatcher,
Expand Down Expand Up @@ -157,26 +157,53 @@ function getEnvType(kind: PythonEnvKind): PythonEnvType | undefined {
}
}

function getName(nativeEnv: NativeEnvInfo, kind: PythonEnvKind): string {
function isSubDir(pathToCheck: string | undefined, parents: string[]): boolean {
return parents.some((prefix) => {
if (pathToCheck) {
return path.normalize(pathToCheck).startsWith(path.normalize(prefix));
}
return false;
});
}

function getName(nativeEnv: NativeEnvInfo, kind: PythonEnvKind, condaEnvDirs: string[]): string {
if (nativeEnv.name) {
return nativeEnv.name;
}

const envType = getEnvType(kind);
if (nativeEnv.prefix && (envType === PythonEnvType.Conda || envType === PythonEnvType.Virtual)) {
if (nativeEnv.prefix && envType === PythonEnvType.Virtual) {
return path.basename(nativeEnv.prefix);
}

if (nativeEnv.prefix && envType === PythonEnvType.Conda) {
if (nativeEnv.name === 'base') {
return 'base';
}

const workspaces = (getWorkspaceFolders() ?? []).map((wf) => wf.uri.fsPath);
if (isSubDir(nativeEnv.prefix, workspaces)) {
traceInfo(`Conda env is --prefix environment: ${nativeEnv.prefix}`);
return '';
}

if (condaEnvDirs.length > 0 && isSubDir(nativeEnv.prefix, condaEnvDirs)) {
traceInfo(`Conda env is --named environment: ${nativeEnv.prefix}`);
return path.basename(nativeEnv.prefix);
}
}

return '';
}

function toPythonEnvInfo(nativeEnv: NativeEnvInfo): PythonEnvInfo | undefined {
function toPythonEnvInfo(nativeEnv: NativeEnvInfo, condaEnvDirs: string[]): PythonEnvInfo | undefined {
if (!validEnv(nativeEnv)) {
return undefined;
}
const kind = categoryToKind(nativeEnv.kind);
const arch = toArch(nativeEnv.arch);
const version: PythonVersion = parseVersion(nativeEnv.version ?? '');
const name = getName(nativeEnv, kind);
const name = getName(nativeEnv, kind, condaEnvDirs);
const displayName = nativeEnv.version
? getDisplayName(version, kind, arch, name)
: nativeEnv.displayName ?? 'Python';
Expand Down Expand Up @@ -211,6 +238,9 @@ function toPythonEnvInfo(nativeEnv: NativeEnvInfo): PythonEnvInfo | undefined {
}

function hasChanged(old: PythonEnvInfo, newEnv: PythonEnvInfo): boolean {
if (old.name !== newEnv.name) {
return true;
}
if (old.executable.filename !== newEnv.executable.filename) {
return true;
}
Expand Down Expand Up @@ -247,6 +277,8 @@ class NativePythonEnvironments implements IDiscoveryAPI, Disposable {

private _disposables: Disposable[] = [];

private _condaEnvDirs: string[] = [];

constructor(private readonly finder: NativePythonFinder) {
this._onProgress = new EventEmitter<ProgressNotificationEvent>();
this._onChanged = new EventEmitter<PythonEnvCollectionChangedEvent>();
Expand Down Expand Up @@ -381,7 +413,7 @@ class NativePythonEnvironments implements IDiscoveryAPI, Disposable {
}

private addEnv(native: NativeEnvInfo, searchLocation?: Uri): PythonEnvInfo | undefined {
const info = toPythonEnvInfo(native);
const info = toPythonEnvInfo(native, this._condaEnvDirs);
if (info) {
const old = this._envs.find((item) => item.executable.filename === info.executable.filename);
if (old) {
Expand Down Expand Up @@ -417,6 +449,9 @@ class NativePythonEnvironments implements IDiscoveryAPI, Disposable {
}
const native = await this.finder.resolve(envPath);
if (native) {
if (native.kind === NativePythonEnvironmentKind.Conda && this._condaEnvDirs.length === 0) {
this._condaEnvDirs = (await getCondaEnvDirs()) ?? [];
}
return this.addEnv(native);
}
return undefined;
Expand Down

0 comments on commit 32512b1

Please sign in to comment.