Skip to content

Commit e7add4d

Browse files
committed
refactor: streamline conda environment handling and activation commands
1 parent 9f65313 commit e7add4d

1 file changed

Lines changed: 23 additions & 33 deletions

File tree

src/managers/conda/condaUtils.ts

Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export const CONDA_GLOBAL_KEY = `${ENVS_EXTENSION_ID}:conda:GLOBAL_SELECTED`;
6666
let condaPath: string | undefined;
6767
export async function clearCondaCache(): Promise<void> {
6868
condaPath = undefined;
69+
prefixes = undefined;
6970
}
7071

7172
async function setConda(conda: string): Promise<void> {
@@ -331,26 +332,13 @@ export async function getVersion(root: string): Promise<string> {
331332
throw new Error('Python version not found');
332333
}
333334

334-
function isPrefixOf(roots: string[], e: string): boolean {
335-
if (!roots || !Array.isArray(roots)) {
336-
return false;
337-
}
338-
const t = path.normalize(e);
339-
for (let r of roots.map((r) => path.normalize(r))) {
340-
if (t.startsWith(r)) {
341-
return true;
342-
}
343-
}
344-
return false;
345-
}
346-
347335
/**
348336
* Creates a PythonEnvironmentInfo object for a named conda environment.
349337
* @param name The name of the conda environment
350338
* @param prefix The installation prefix path for the environment
351339
* @param executable The path to the Python executable
352340
* @param version The Python version string
353-
* @param _conda The path to the conda executable (TODO: currently unused)
341+
* @param conda The path to the conda executable (used for activation commands)
354342
* @param envManager The environment manager instance
355343
* @returns Promise resolving to a PythonEnvironmentInfo object
356344
*/
@@ -359,7 +347,7 @@ export async function getNamedCondaPythonInfo(
359347
prefix: string,
360348
executable: string,
361349
version: string,
362-
_conda: string, // TODO:: fix this, why is it not being used to build the info object
350+
conda: string,
363351
envManager: EnvironmentManager,
364352
): Promise<PythonEnvironmentInfo> {
365353
const { shellActivation, shellDeactivation } = await buildShellActivationMapForConda(prefix, envManager, name);
@@ -381,8 +369,8 @@ export async function getNamedCondaPythonInfo(
381369
executable: path.join(executable),
382370
args: [],
383371
},
384-
activation: [{ executable: 'conda', args: ['activate', name] }],
385-
deactivation: [{ executable: 'conda', args: ['deactivate'] }],
372+
activation: [{ executable: conda, args: ['activate', name] }],
373+
deactivation: [{ executable: conda, args: ['deactivate'] }],
386374
shellActivation,
387375
shellDeactivation,
388376
},
@@ -596,10 +584,12 @@ async function windowsExceptionGenerateConfig(
596584
traceVerbose(`PS1 hook path: ${ps1Hook ?? 'not found'}`);
597585
const activation = ps1Hook ? ps1Hook : sourceInitPath;
598586

599-
const pwshActivate = [{ executable: activation }, { executable: 'conda', args: ['activate', prefix] }];
600-
const cmdActivate = [{ executable: sourceInitPath }, { executable: 'conda', args: ['activate', prefix] }];
587+
// Quote the prefix path to handle spaces in paths (common on Windows)
588+
const quotedPrefix = quoteStringIfNecessary(prefix);
589+
const pwshActivate = [{ executable: activation }, { executable: 'conda', args: ['activate', quotedPrefix] }];
590+
const cmdActivate = [{ executable: sourceInitPath }, { executable: 'conda', args: ['activate', quotedPrefix] }];
601591

602-
const bashActivate = [{ executable: 'source', args: [sourceInitPath.replace(/\\/g, '/'), prefix] }];
592+
const bashActivate = [{ executable: 'source', args: [sourceInitPath.replace(/\\/g, '/'), quotedPrefix] }];
603593
traceVerbose(
604594
`Windows activation commands:
605595
PowerShell: ${JSON.stringify(pwshActivate)},
@@ -648,7 +638,6 @@ async function nativeToPythonEnv(
648638
manager: EnvironmentManager,
649639
log: LogOutputChannel,
650640
conda: string,
651-
condaPrefixes: string[],
652641
): Promise<PythonEnvironment | undefined> {
653642
// Defensive check: Validate NativeEnvInfo object
654643
if (!e) {
@@ -672,21 +661,24 @@ async function nativeToPythonEnv(
672661
);
673662
log.info(`Found base environment: ${e.prefix}`);
674663
return environment;
675-
} else if (!isPrefixOf(condaPrefixes, e.prefix)) {
664+
} else if (e.name) {
665+
// Server explicitly provided a name - this is a named environment (created with -n/--name)
666+
// Use name-based activation: conda activate <name>
676667
const environment = api.createPythonEnvironmentItem(
677-
await getPrefixesCondaPythonInfo(e.prefix, e.executable, e.version, conda, manager),
668+
await getNamedCondaPythonInfo(e.name, e.prefix, e.executable, e.version, conda, manager),
678669
manager,
679670
);
680-
log.info(`Found prefix environment: ${e.prefix}`);
671+
log.info(`Found named environment: ${e.name} at ${e.prefix}`);
681672
return environment;
682673
} else {
683-
const basename = path.basename(e.prefix);
684-
const name = e.name ?? basename;
674+
// Server returned undefined/null name - this is a prefix-based environment (created with -p/--prefix)
675+
// Use prefix-based activation: conda activate <full-path>
676+
// This aligns with the PR #331 fix in python-environment-tools
685677
const environment = api.createPythonEnvironmentItem(
686-
await getNamedCondaPythonInfo(name, e.prefix, e.executable, e.version, conda, manager),
678+
await getPrefixesCondaPythonInfo(e.prefix, e.executable, e.version, conda, manager),
687679
manager,
688680
);
689-
log.info(`Found named environment: ${e.prefix}`);
681+
log.info(`Found prefix environment: ${e.prefix}`);
690682
return environment;
691683
}
692684
}
@@ -704,8 +696,7 @@ export async function resolveCondaPath(
704696
return undefined;
705697
}
706698
const conda = await getConda();
707-
const condaPrefixes = await getPrefixes();
708-
return nativeToPythonEnv(e, api, manager, log, conda, condaPrefixes);
699+
return nativeToPythonEnv(e, api, manager, log, conda);
709700
} catch {
710701
return undefined;
711702
}
@@ -764,7 +755,6 @@ export async function refreshCondaEnvs(
764755
const condaPath = conda;
765756

766757
if (condaPath) {
767-
const condaPrefixes = await getPrefixes();
768758
const envs = data
769759
.filter((e) => isNativeEnvInfo(e))
770760
.map((e) => e as NativeEnvInfo)
@@ -774,7 +764,7 @@ export async function refreshCondaEnvs(
774764
await Promise.all(
775765
envs.map(async (e) => {
776766
try {
777-
const environment = await nativeToPythonEnv(e, api, manager, log, condaPath, condaPrefixes);
767+
const environment = await nativeToPythonEnv(e, api, manager, log, condaPath);
778768
if (environment) {
779769
collection.push(environment);
780770
}
@@ -1328,7 +1318,7 @@ async function installPython(
13281318
await nativeFinder.refresh(true, NativePythonEnvironmentKind.conda);
13291319
const native = await nativeFinder.resolve(environment.sysPrefix);
13301320
if (native.kind === NativePythonEnvironmentKind.conda) {
1331-
return nativeToPythonEnv(native, api, manager, log, await getConda(), await getPrefixes());
1321+
return nativeToPythonEnv(native, api, manager, log, await getConda());
13321322
}
13331323
return undefined;
13341324
}

0 commit comments

Comments
 (0)