Skip to content

Commit

Permalink
Restore pixi functionality only when Pixi is available (#24319)
Browse files Browse the repository at this point in the history
Fixes #24310
  • Loading branch information
karthiknadig authored Oct 21, 2024
1 parent 5e5a7ce commit e7860a5
Show file tree
Hide file tree
Showing 12 changed files with 266 additions and 199 deletions.
26 changes: 15 additions & 11 deletions src/client/common/process/pythonExecutionFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
import { IInterpreterAutoSelectionService } from '../../interpreter/autoSelection/types';
import { sleep } from '../utils/async';
import { traceError } from '../../logging';
import { getPixiEnvironmentFromInterpreter } from '../../pythonEnvironments/common/environmentManagers/pixi';
import { getPixi, getPixiEnvironmentFromInterpreter } from '../../pythonEnvironments/common/environmentManagers/pixi';

@injectable()
export class PythonExecutionFactory implements IPythonExecutionFactory {
Expand Down Expand Up @@ -80,16 +80,18 @@ export class PythonExecutionFactory implements IPythonExecutionFactory {
}
const processService: IProcessService = await this.processServiceFactory.create(options.resource);

if (await getPixi()) {
const pixiExecutionService = await this.createPixiExecutionService(pythonPath, processService);
if (pixiExecutionService) {
return pixiExecutionService;
}
}

const condaExecutionService = await this.createCondaExecutionService(pythonPath, processService);
if (condaExecutionService) {
return condaExecutionService;
}

const pixiExecutionService = await this.createPixiExecutionService(pythonPath, processService);
if (pixiExecutionService) {
return pixiExecutionService;
}

const windowsStoreInterpreterCheck = this.pyenvs.isMicrosoftStoreInterpreter.bind(this.pyenvs);

const env = (await windowsStoreInterpreterCheck(pythonPath))
Expand Down Expand Up @@ -122,16 +124,18 @@ export class PythonExecutionFactory implements IPythonExecutionFactory {
processService.on('exec', this.logger.logProcess.bind(this.logger));
this.disposables.push(processService);

if (await getPixi()) {
const pixiExecutionService = await this.createPixiExecutionService(pythonPath, processService);
if (pixiExecutionService) {
return pixiExecutionService;
}
}

const condaExecutionService = await this.createCondaExecutionService(pythonPath, processService);
if (condaExecutionService) {
return condaExecutionService;
}

const pixiExecutionService = await this.createPixiExecutionService(pythonPath, processService);
if (pixiExecutionService) {
return pixiExecutionService;
}

const env = createPythonEnv(pythonPath, processService, this.fileSystem);
return createPythonService(processService, env);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,7 @@ import { inject, injectable } from 'inversify';
import { Uri } from 'vscode';
import { IInterpreterService } from '../../../interpreter/contracts';
import { ITerminalActivationCommandProvider, TerminalShellType } from '../types';
import { traceError } from '../../../logging';
import {
getPixiEnvironmentFromInterpreter,
isNonDefaultPixiEnvironmentName,
} from '../../../pythonEnvironments/common/environmentManagers/pixi';
import { exec } from '../../../pythonEnvironments/common/externalDependencies';
import { splitLines } from '../../stringUtils';
import { getPixiActivationCommands } from '../../../pythonEnvironments/common/environmentManagers/pixi';

@injectable()
export class PixiActivationCommandProvider implements ITerminalActivationCommandProvider {
Expand All @@ -37,38 +31,11 @@ export class PixiActivationCommandProvider implements ITerminalActivationCommand
return this.getActivationCommandsForInterpreter(interpreter.path, targetShell);
}

public async getActivationCommandsForInterpreter(
public getActivationCommandsForInterpreter(
pythonPath: string,
targetShell: TerminalShellType,
): Promise<string[] | undefined> {
const pixiEnv = await getPixiEnvironmentFromInterpreter(pythonPath);
if (!pixiEnv) {
return undefined;
}

const command = ['shell-hook', '--manifest-path', pixiEnv.manifestPath];
if (isNonDefaultPixiEnvironmentName(pixiEnv.envName)) {
command.push('--environment');
command.push(pixiEnv.envName);
}

const pixiTargetShell = shellTypeToPixiShell(targetShell);
if (pixiTargetShell) {
command.push('--shell');
command.push(pixiTargetShell);
}

const shellHookOutput = await exec(pixiEnv.pixi.command, command, {
throwOnStdErr: false,
}).catch(traceError);
if (!shellHookOutput) {
return undefined;
}

return splitLines(shellHookOutput.stdout, {
removeEmptyEntries: true,
trim: true,
});
return getPixiActivationCommands(pythonPath, targetShell);
}
}

Expand Down
14 changes: 14 additions & 0 deletions src/client/common/terminal/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
TerminalActivationProviders,
TerminalShellType,
} from './types';
import { isPixiEnvironment } from '../../pythonEnvironments/common/environmentManagers/pixi';

@injectable()
export class TerminalHelper implements ITerminalHelper {
Expand Down Expand Up @@ -143,6 +144,19 @@ export class TerminalHelper implements ITerminalHelper {
): Promise<string[] | undefined> {
const settings = this.configurationService.getSettings(resource);

const isPixiEnv = interpreter
? interpreter.envType === EnvironmentType.Pixi
: await isPixiEnvironment(settings.pythonPath);
if (isPixiEnv) {
const activationCommands = interpreter
? await this.pixi.getActivationCommandsForInterpreter(interpreter.path, terminalShellType)
: await this.pixi.getActivationCommands(resource, terminalShellType);

if (Array.isArray(activationCommands)) {
return activationCommands;
}
}

const condaService = this.serviceContainer.get<IComponentAdapter>(IComponentAdapter);
// If we have a conda environment, then use that.
const isCondaEnvironment = interpreter
Expand Down
2 changes: 2 additions & 0 deletions src/client/extensionActivation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import { StopWatch } from './common/utils/stopWatch';
import { registerReplCommands, registerReplExecuteOnEnter, registerStartNativeReplCommand } from './repl/replCommands';
import { registerTriggerForTerminalREPL } from './terminals/codeExecution/terminalReplWatcher';
import { registerPythonStartup } from './terminals/pythonStartup';
import { registerPixiFeatures } from './pythonEnvironments/common/environmentManagers/pixi';

export async function activateComponents(
// `ext` is passed to any extra activation funcs.
Expand Down Expand Up @@ -100,6 +101,7 @@ export function activateFeatures(ext: ExtensionState, _components: Components):
IInterpreterService,
);
const pathUtils = ext.legacyIOC.serviceContainer.get<IPathUtils>(IPathUtils);
registerPixiFeatures(ext.disposables);
registerAllCreateEnvironmentFeatures(
ext.disposables,
interpreterQuickPick,
Expand Down
6 changes: 6 additions & 0 deletions src/client/interpreter/activation/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { StopWatch } from '../../common/utils/stopWatch';
import { identifyShellFromShellPath } from '../../common/terminal/shellDetectors/baseShellDetector';
import { getSearchPathEnvVarNames } from '../../common/utils/exec';
import { cache } from '../../common/utils/decorators';
import { getRunPixiPythonCommand } from '../../pythonEnvironments/common/environmentManagers/pixi';

const ENVIRONMENT_PREFIX = 'e8b39361-0157-4923-80e1-22d70d46dee6';
const CACHE_DURATION = 10 * 60 * 1000;
Expand Down Expand Up @@ -252,6 +253,11 @@ export class EnvironmentActivationService implements IEnvironmentActivationServi
// Using environment prefix isn't needed as the marker script already takes care of it.
command = [...pythonArgv, ...args].map((arg) => arg.toCommandArgumentForPythonExt()).join(' ');
}
} else if (interpreter?.envType === EnvironmentType.Pixi) {
const pythonArgv = await getRunPixiPythonCommand(interpreter.path);
if (pythonArgv) {
command = [...pythonArgv, ...args].map((arg) => arg.toCommandArgumentForPythonExt()).join(' ');
}
}
if (!command) {
const activationCommands = await this.helper.getEnvironmentActivationShellCommands(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ import { asyncFilter } from '../../../../common/utils/arrayUtils';
import { chain, iterable } from '../../../../common/utils/async';
import { traceError, traceVerbose } from '../../../../logging';
import { getCondaInterpreterPath } from '../../../common/environmentManagers/conda';
import { Pixi } from '../../../common/environmentManagers/pixi';
import { pathExists } from '../../../common/externalDependencies';
import { PythonEnvKind } from '../../info';
import { IPythonEnvsIterator, BasicEnvInfo } from '../../locator';
import { FSWatcherKind, FSWatchingLocator } from './fsWatchingLocator';
import { getPixi } from '../../../common/environmentManagers/pixi';

/**
* Returns all virtual environment locations to look for in a workspace.
*/
async function getVirtualEnvDirs(root: string): Promise<string[]> {
const pixi = await Pixi.getPixi();
const pixi = await getPixi();
const envDirs = (await pixi?.getEnvList(root)) ?? [];
return asyncFilter(envDirs, pathExists);
}
Expand Down
Loading

0 comments on commit e7860a5

Please sign in to comment.