Skip to content

Commit e7860a5

Browse files
authored
Restore pixi functionality only when Pixi is available (#24319)
Fixes #24310
1 parent 5e5a7ce commit e7860a5

File tree

12 files changed

+266
-199
lines changed

12 files changed

+266
-199
lines changed

src/client/common/process/pythonExecutionFactory.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {
2525
import { IInterpreterAutoSelectionService } from '../../interpreter/autoSelection/types';
2626
import { sleep } from '../utils/async';
2727
import { traceError } from '../../logging';
28-
import { getPixiEnvironmentFromInterpreter } from '../../pythonEnvironments/common/environmentManagers/pixi';
28+
import { getPixi, getPixiEnvironmentFromInterpreter } from '../../pythonEnvironments/common/environmentManagers/pixi';
2929

3030
@injectable()
3131
export class PythonExecutionFactory implements IPythonExecutionFactory {
@@ -80,16 +80,18 @@ export class PythonExecutionFactory implements IPythonExecutionFactory {
8080
}
8181
const processService: IProcessService = await this.processServiceFactory.create(options.resource);
8282

83+
if (await getPixi()) {
84+
const pixiExecutionService = await this.createPixiExecutionService(pythonPath, processService);
85+
if (pixiExecutionService) {
86+
return pixiExecutionService;
87+
}
88+
}
89+
8390
const condaExecutionService = await this.createCondaExecutionService(pythonPath, processService);
8491
if (condaExecutionService) {
8592
return condaExecutionService;
8693
}
8794

88-
const pixiExecutionService = await this.createPixiExecutionService(pythonPath, processService);
89-
if (pixiExecutionService) {
90-
return pixiExecutionService;
91-
}
92-
9395
const windowsStoreInterpreterCheck = this.pyenvs.isMicrosoftStoreInterpreter.bind(this.pyenvs);
9496

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

127+
if (await getPixi()) {
128+
const pixiExecutionService = await this.createPixiExecutionService(pythonPath, processService);
129+
if (pixiExecutionService) {
130+
return pixiExecutionService;
131+
}
132+
}
133+
125134
const condaExecutionService = await this.createCondaExecutionService(pythonPath, processService);
126135
if (condaExecutionService) {
127136
return condaExecutionService;
128137
}
129138

130-
const pixiExecutionService = await this.createPixiExecutionService(pythonPath, processService);
131-
if (pixiExecutionService) {
132-
return pixiExecutionService;
133-
}
134-
135139
const env = createPythonEnv(pythonPath, processService, this.fileSystem);
136140
return createPythonService(processService, env);
137141
}

src/client/common/terminal/environmentActivationProviders/pixiActivationProvider.ts

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,7 @@ import { inject, injectable } from 'inversify';
88
import { Uri } from 'vscode';
99
import { IInterpreterService } from '../../../interpreter/contracts';
1010
import { ITerminalActivationCommandProvider, TerminalShellType } from '../types';
11-
import { traceError } from '../../../logging';
12-
import {
13-
getPixiEnvironmentFromInterpreter,
14-
isNonDefaultPixiEnvironmentName,
15-
} from '../../../pythonEnvironments/common/environmentManagers/pixi';
16-
import { exec } from '../../../pythonEnvironments/common/externalDependencies';
17-
import { splitLines } from '../../stringUtils';
11+
import { getPixiActivationCommands } from '../../../pythonEnvironments/common/environmentManagers/pixi';
1812

1913
@injectable()
2014
export class PixiActivationCommandProvider implements ITerminalActivationCommandProvider {
@@ -37,38 +31,11 @@ export class PixiActivationCommandProvider implements ITerminalActivationCommand
3731
return this.getActivationCommandsForInterpreter(interpreter.path, targetShell);
3832
}
3933

40-
public async getActivationCommandsForInterpreter(
34+
public getActivationCommandsForInterpreter(
4135
pythonPath: string,
4236
targetShell: TerminalShellType,
4337
): Promise<string[] | undefined> {
44-
const pixiEnv = await getPixiEnvironmentFromInterpreter(pythonPath);
45-
if (!pixiEnv) {
46-
return undefined;
47-
}
48-
49-
const command = ['shell-hook', '--manifest-path', pixiEnv.manifestPath];
50-
if (isNonDefaultPixiEnvironmentName(pixiEnv.envName)) {
51-
command.push('--environment');
52-
command.push(pixiEnv.envName);
53-
}
54-
55-
const pixiTargetShell = shellTypeToPixiShell(targetShell);
56-
if (pixiTargetShell) {
57-
command.push('--shell');
58-
command.push(pixiTargetShell);
59-
}
60-
61-
const shellHookOutput = await exec(pixiEnv.pixi.command, command, {
62-
throwOnStdErr: false,
63-
}).catch(traceError);
64-
if (!shellHookOutput) {
65-
return undefined;
66-
}
67-
68-
return splitLines(shellHookOutput.stdout, {
69-
removeEmptyEntries: true,
70-
trim: true,
71-
});
38+
return getPixiActivationCommands(pythonPath, targetShell);
7239
}
7340
}
7441

src/client/common/terminal/helper.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
TerminalActivationProviders,
2323
TerminalShellType,
2424
} from './types';
25+
import { isPixiEnvironment } from '../../pythonEnvironments/common/environmentManagers/pixi';
2526

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

147+
const isPixiEnv = interpreter
148+
? interpreter.envType === EnvironmentType.Pixi
149+
: await isPixiEnvironment(settings.pythonPath);
150+
if (isPixiEnv) {
151+
const activationCommands = interpreter
152+
? await this.pixi.getActivationCommandsForInterpreter(interpreter.path, terminalShellType)
153+
: await this.pixi.getActivationCommands(resource, terminalShellType);
154+
155+
if (Array.isArray(activationCommands)) {
156+
return activationCommands;
157+
}
158+
}
159+
146160
const condaService = this.serviceContainer.get<IComponentAdapter>(IComponentAdapter);
147161
// If we have a conda environment, then use that.
148162
const isCondaEnvironment = interpreter

src/client/extensionActivation.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import { StopWatch } from './common/utils/stopWatch';
5454
import { registerReplCommands, registerReplExecuteOnEnter, registerStartNativeReplCommand } from './repl/replCommands';
5555
import { registerTriggerForTerminalREPL } from './terminals/codeExecution/terminalReplWatcher';
5656
import { registerPythonStartup } from './terminals/pythonStartup';
57+
import { registerPixiFeatures } from './pythonEnvironments/common/environmentManagers/pixi';
5758

5859
export async function activateComponents(
5960
// `ext` is passed to any extra activation funcs.
@@ -100,6 +101,7 @@ export function activateFeatures(ext: ExtensionState, _components: Components):
100101
IInterpreterService,
101102
);
102103
const pathUtils = ext.legacyIOC.serviceContainer.get<IPathUtils>(IPathUtils);
104+
registerPixiFeatures(ext.disposables);
103105
registerAllCreateEnvironmentFeatures(
104106
ext.disposables,
105107
interpreterQuickPick,

src/client/interpreter/activation/service.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import { StopWatch } from '../../common/utils/stopWatch';
3939
import { identifyShellFromShellPath } from '../../common/terminal/shellDetectors/baseShellDetector';
4040
import { getSearchPathEnvVarNames } from '../../common/utils/exec';
4141
import { cache } from '../../common/utils/decorators';
42+
import { getRunPixiPythonCommand } from '../../pythonEnvironments/common/environmentManagers/pixi';
4243

4344
const ENVIRONMENT_PREFIX = 'e8b39361-0157-4923-80e1-22d70d46dee6';
4445
const CACHE_DURATION = 10 * 60 * 1000;
@@ -252,6 +253,11 @@ export class EnvironmentActivationService implements IEnvironmentActivationServi
252253
// Using environment prefix isn't needed as the marker script already takes care of it.
253254
command = [...pythonArgv, ...args].map((arg) => arg.toCommandArgumentForPythonExt()).join(' ');
254255
}
256+
} else if (interpreter?.envType === EnvironmentType.Pixi) {
257+
const pythonArgv = await getRunPixiPythonCommand(interpreter.path);
258+
if (pythonArgv) {
259+
command = [...pythonArgv, ...args].map((arg) => arg.toCommandArgumentForPythonExt()).join(' ');
260+
}
255261
}
256262
if (!command) {
257263
const activationCommands = await this.helper.getEnvironmentActivationShellCommands(

src/client/pythonEnvironments/base/locators/lowLevel/pixiLocator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@ import { asyncFilter } from '../../../../common/utils/arrayUtils';
66
import { chain, iterable } from '../../../../common/utils/async';
77
import { traceError, traceVerbose } from '../../../../logging';
88
import { getCondaInterpreterPath } from '../../../common/environmentManagers/conda';
9-
import { Pixi } from '../../../common/environmentManagers/pixi';
109
import { pathExists } from '../../../common/externalDependencies';
1110
import { PythonEnvKind } from '../../info';
1211
import { IPythonEnvsIterator, BasicEnvInfo } from '../../locator';
1312
import { FSWatcherKind, FSWatchingLocator } from './fsWatchingLocator';
13+
import { getPixi } from '../../../common/environmentManagers/pixi';
1414

1515
/**
1616
* Returns all virtual environment locations to look for in a workspace.
1717
*/
1818
async function getVirtualEnvDirs(root: string): Promise<string[]> {
19-
const pixi = await Pixi.getPixi();
19+
const pixi = await getPixi();
2020
const envDirs = (await pixi?.getEnvList(root)) ?? [];
2121
return asyncFilter(envDirs, pathExists);
2222
}

0 commit comments

Comments
 (0)