Skip to content

Commit d01ebb3

Browse files
committed
updates based on feedback
1 parent e2c2541 commit d01ebb3

3 files changed

Lines changed: 109 additions & 161 deletions

File tree

src/managers/builtin/venvUtils.ts

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import * as fsapi from 'fs-extra';
22
import * as os from 'os';
33
import * as path from 'path';
4-
import { l10n, LogOutputChannel, ProgressLocation, QuickPickItem, QuickPickItemKind, Uri } from 'vscode';
5-
import { EnvironmentManager, PythonEnvironment, PythonEnvironmentApi } from '../../api';
4+
import { l10n, LogOutputChannel, ProgressLocation, QuickPickItem, QuickPickItemKind, ThemeIcon, Uri } from 'vscode';
5+
import { EnvironmentManager, PythonEnvironment, PythonEnvironmentApi, PythonEnvironmentInfo } from '../../api';
66
import { ENVS_EXTENSION_ID } from '../../common/constants';
77
import { Common, VenvManagerStrings } from '../../common/localize';
88
import { traceInfo } from '../../common/logging';
@@ -25,7 +25,7 @@ import {
2525
NativePythonEnvironmentKind,
2626
NativePythonFinder,
2727
} from '../common/nativePythonFinder';
28-
import { getPythonInfo, sortEnvironments } from '../common/utils';
28+
import { getShellActivationCommands, shortVersion, sortEnvironments } from '../common/utils';
2929
import { isUvInstalled, runPython, runUV } from './helpers';
3030
import { getProjectInstallable, getWorkspacePackagesToInstall, PipPackages } from './pipUtils';
3131
import { resolveSystemPythonEnvironmentPath } from './utils';
@@ -98,7 +98,42 @@ export async function setVenvForGlobal(envPath: string | undefined): Promise<voi
9898
await state.set(VENV_GLOBAL_KEY, envPath);
9999
}
100100

101-
101+
export async function getPythonInfo(env: NativeEnvInfo): Promise<PythonEnvironmentInfo> {
102+
if (env.executable && env.version && env.prefix) {
103+
const venvName = env.name;
104+
const sv = shortVersion(env.version);
105+
const name = `${venvName} (${sv})`;
106+
107+
const binDir = path.dirname(env.executable);
108+
109+
const { shellActivation, shellDeactivation } = await getShellActivationCommands(binDir);
110+
111+
return {
112+
name: name,
113+
displayName: name,
114+
shortDisplayName: `${sv} (${venvName})`,
115+
displayPath: env.executable,
116+
version: env.version,
117+
description: undefined,
118+
tooltip: env.executable,
119+
environmentPath: Uri.file(env.executable),
120+
iconPath: new ThemeIcon('python'),
121+
sysPrefix: env.prefix,
122+
execInfo: {
123+
run: {
124+
executable: env.executable,
125+
},
126+
activatedRun: {
127+
executable: env.executable,
128+
},
129+
shellActivation,
130+
shellDeactivation,
131+
},
132+
};
133+
} else {
134+
throw new Error(`Invalid python info: ${JSON.stringify(env)}`);
135+
}
136+
}
102137

103138
export async function findVirtualEnvironments(
104139
hardRefresh: boolean,

src/managers/common/utils.ts

Lines changed: 64 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import * as fs from 'fs-extra';
22
import path from 'path';
3-
import { ThemeIcon, Uri } from 'vscode';
4-
import { PythonCommandRunConfiguration, PythonEnvironment, PythonEnvironmentInfo } from '../../api';
3+
import { PythonCommandRunConfiguration, PythonEnvironment } from '../../api';
54
import { isWindows } from '../../common/utils/platformUtils';
65
import { ShellConstants } from '../../features/common/shellConstants';
7-
import { NativeEnvInfo } from './nativePythonFinder';
86
import { Installable } from './types';
97

108
export function noop() {
@@ -118,111 +116,81 @@ export function compareVersions(version1: string, version2: string): number {
118116
return 0;
119117
}
120118

121-
export async function getPythonInfo(env: NativeEnvInfo): Promise<PythonEnvironmentInfo> {
122-
if (env.executable && env.version && env.prefix) {
123-
const venvName = env.name;
124-
const sv = shortVersion(env.version);
125-
const name = `${venvName} (${sv})`;
119+
export async function getShellActivationCommands(binDir: string): Promise<{
120+
shellActivation: Map<string, PythonCommandRunConfiguration[]>;
121+
shellDeactivation: Map<string, PythonCommandRunConfiguration[]>;
122+
}> {
123+
const shellActivation: Map<string, PythonCommandRunConfiguration[]> = new Map();
124+
const shellDeactivation: Map<string, PythonCommandRunConfiguration[]> = new Map();
126125

127-
const binDir = path.dirname(env.executable);
128-
129-
const shellActivation: Map<string, PythonCommandRunConfiguration[]> = new Map();
130-
const shellDeactivation: Map<string, PythonCommandRunConfiguration[]> = new Map();
131-
132-
if (isWindows()) {
133-
shellActivation.set('unknown', [{ executable: path.join(binDir, `activate`) }]);
134-
shellDeactivation.set('unknown', [{ executable: path.join(binDir, `deactivate`) }]);
135-
} else {
136-
shellActivation.set('unknown', [{ executable: 'source', args: [path.join(binDir, `activate`)] }]);
137-
shellDeactivation.set('unknown', [{ executable: 'deactivate' }]);
138-
}
126+
if (isWindows()) {
127+
shellActivation.set('unknown', [{ executable: path.join(binDir, `activate`) }]);
128+
shellDeactivation.set('unknown', [{ executable: path.join(binDir, `deactivate`) }]);
129+
} else {
130+
shellActivation.set('unknown', [{ executable: 'source', args: [path.join(binDir, `activate`)] }]);
131+
shellDeactivation.set('unknown', [{ executable: 'deactivate' }]);
132+
}
139133

140-
shellActivation.set(ShellConstants.SH, [{ executable: 'source', args: [path.join(binDir, `activate`)] }]);
141-
shellDeactivation.set(ShellConstants.SH, [{ executable: 'deactivate' }]);
134+
shellActivation.set(ShellConstants.SH, [{ executable: 'source', args: [path.join(binDir, `activate`)] }]);
135+
shellDeactivation.set(ShellConstants.SH, [{ executable: 'deactivate' }]);
142136

143-
shellActivation.set(ShellConstants.BASH, [{ executable: 'source', args: [path.join(binDir, `activate`)] }]);
144-
shellDeactivation.set(ShellConstants.BASH, [{ executable: 'deactivate' }]);
137+
shellActivation.set(ShellConstants.BASH, [{ executable: 'source', args: [path.join(binDir, `activate`)] }]);
138+
shellDeactivation.set(ShellConstants.BASH, [{ executable: 'deactivate' }]);
145139

146-
shellActivation.set(ShellConstants.GITBASH, [
147-
{ executable: 'source', args: [pathForGitBash(path.join(binDir, `activate`))] },
148-
]);
149-
shellDeactivation.set(ShellConstants.GITBASH, [{ executable: 'deactivate' }]);
140+
shellActivation.set(ShellConstants.GITBASH, [
141+
{ executable: 'source', args: [pathForGitBash(path.join(binDir, `activate`))] },
142+
]);
143+
shellDeactivation.set(ShellConstants.GITBASH, [{ executable: 'deactivate' }]);
150144

151-
shellActivation.set(ShellConstants.ZSH, [{ executable: 'source', args: [path.join(binDir, `activate`)] }]);
152-
shellDeactivation.set(ShellConstants.ZSH, [{ executable: 'deactivate' }]);
145+
shellActivation.set(ShellConstants.ZSH, [{ executable: 'source', args: [path.join(binDir, `activate`)] }]);
146+
shellDeactivation.set(ShellConstants.ZSH, [{ executable: 'deactivate' }]);
153147

154-
shellActivation.set(ShellConstants.KSH, [{ executable: '.', args: [path.join(binDir, `activate`)] }]);
155-
shellDeactivation.set(ShellConstants.KSH, [{ executable: 'deactivate' }]);
148+
shellActivation.set(ShellConstants.KSH, [{ executable: '.', args: [path.join(binDir, `activate`)] }]);
149+
shellDeactivation.set(ShellConstants.KSH, [{ executable: 'deactivate' }]);
156150

157-
if (await fs.pathExists(path.join(binDir, 'Activate.ps1'))) {
158-
shellActivation.set(ShellConstants.PWSH, [{ executable: '&', args: [path.join(binDir, `Activate.ps1`)] }]);
159-
shellDeactivation.set(ShellConstants.PWSH, [{ executable: 'deactivate' }]);
160-
} else if (await fs.pathExists(path.join(binDir, 'activate.ps1'))) {
161-
shellActivation.set(ShellConstants.PWSH, [{ executable: '&', args: [path.join(binDir, `activate.ps1`)] }]);
162-
shellDeactivation.set(ShellConstants.PWSH, [{ executable: 'deactivate' }]);
163-
}
164-
165-
if (await fs.pathExists(path.join(binDir, 'activate.bat'))) {
166-
shellActivation.set(ShellConstants.CMD, [{ executable: path.join(binDir, `activate.bat`) }]);
167-
shellDeactivation.set(ShellConstants.CMD, [{ executable: path.join(binDir, `deactivate.bat`) }]);
168-
}
151+
if (await fs.pathExists(path.join(binDir, 'Activate.ps1'))) {
152+
shellActivation.set(ShellConstants.PWSH, [{ executable: '&', args: [path.join(binDir, `Activate.ps1`)] }]);
153+
shellDeactivation.set(ShellConstants.PWSH, [{ executable: 'deactivate' }]);
154+
} else if (await fs.pathExists(path.join(binDir, 'activate.ps1'))) {
155+
shellActivation.set(ShellConstants.PWSH, [{ executable: '&', args: [path.join(binDir, `activate.ps1`)] }]);
156+
shellDeactivation.set(ShellConstants.PWSH, [{ executable: 'deactivate' }]);
157+
}
169158

170-
if (await fs.pathExists(path.join(binDir, 'activate.csh'))) {
171-
shellActivation.set(ShellConstants.CSH, [
172-
{ executable: 'source', args: [path.join(binDir, `activate.csh`)] },
173-
]);
174-
shellDeactivation.set(ShellConstants.CSH, [{ executable: 'deactivate' }]);
159+
if (await fs.pathExists(path.join(binDir, 'activate.bat'))) {
160+
shellActivation.set(ShellConstants.CMD, [{ executable: path.join(binDir, `activate.bat`) }]);
161+
shellDeactivation.set(ShellConstants.CMD, [{ executable: path.join(binDir, `deactivate.bat`) }]);
162+
}
175163

176-
shellActivation.set(ShellConstants.FISH, [
177-
{ executable: 'source', args: [path.join(binDir, `activate.csh`)] },
178-
]);
179-
shellDeactivation.set(ShellConstants.FISH, [{ executable: 'deactivate' }]);
180-
}
164+
if (await fs.pathExists(path.join(binDir, 'activate.csh'))) {
165+
shellActivation.set(ShellConstants.CSH, [{ executable: 'source', args: [path.join(binDir, `activate.csh`)] }]);
166+
shellDeactivation.set(ShellConstants.CSH, [{ executable: 'deactivate' }]);
181167

182-
if (await fs.pathExists(path.join(binDir, 'activate.fish'))) {
183-
shellActivation.set(ShellConstants.FISH, [
184-
{ executable: 'source', args: [path.join(binDir, `activate.fish`)] },
185-
]);
186-
shellDeactivation.set(ShellConstants.FISH, [{ executable: 'deactivate' }]);
187-
}
168+
shellActivation.set(ShellConstants.FISH, [{ executable: 'source', args: [path.join(binDir, `activate.csh`)] }]);
169+
shellDeactivation.set(ShellConstants.FISH, [{ executable: 'deactivate' }]);
170+
}
188171

189-
if (await fs.pathExists(path.join(binDir, 'activate.xsh'))) {
190-
shellActivation.set(ShellConstants.XONSH, [
191-
{ executable: 'source', args: [path.join(binDir, `activate.xsh`)] },
192-
]);
193-
shellDeactivation.set(ShellConstants.XONSH, [{ executable: 'deactivate' }]);
194-
}
172+
if (await fs.pathExists(path.join(binDir, 'activate.fish'))) {
173+
shellActivation.set(ShellConstants.FISH, [
174+
{ executable: 'source', args: [path.join(binDir, `activate.fish`)] },
175+
]);
176+
shellDeactivation.set(ShellConstants.FISH, [{ executable: 'deactivate' }]);
177+
}
195178

196-
if (await fs.pathExists(path.join(binDir, 'activate.nu'))) {
197-
shellActivation.set(ShellConstants.NU, [
198-
{ executable: 'overlay', args: ['use', path.join(binDir, 'activate.nu')] },
199-
]);
200-
shellDeactivation.set(ShellConstants.NU, [{ executable: 'overlay', args: ['hide', 'activate'] }]);
201-
}
179+
if (await fs.pathExists(path.join(binDir, 'activate.xsh'))) {
180+
shellActivation.set(ShellConstants.XONSH, [
181+
{ executable: 'source', args: [path.join(binDir, `activate.xsh`)] },
182+
]);
183+
shellDeactivation.set(ShellConstants.XONSH, [{ executable: 'deactivate' }]);
184+
}
202185

203-
return {
204-
name: name,
205-
displayName: name,
206-
shortDisplayName: `${sv} (${venvName})`,
207-
displayPath: env.executable,
208-
version: env.version,
209-
description: undefined,
210-
tooltip: env.executable,
211-
environmentPath: Uri.file(env.executable),
212-
iconPath: new ThemeIcon('python'),
213-
sysPrefix: env.prefix,
214-
execInfo: {
215-
run: {
216-
executable: env.executable,
217-
},
218-
activatedRun: {
219-
executable: env.executable,
220-
},
221-
shellActivation,
222-
shellDeactivation,
223-
},
224-
};
225-
} else {
226-
throw new Error(`Invalid python info: ${JSON.stringify(env)}`);
186+
if (await fs.pathExists(path.join(binDir, 'activate.nu'))) {
187+
shellActivation.set(ShellConstants.NU, [
188+
{ executable: 'overlay', args: ['use', path.join(binDir, 'activate.nu')] },
189+
]);
190+
shellDeactivation.set(ShellConstants.NU, [{ executable: 'overlay', args: ['hide', 'activate'] }]);
227191
}
192+
return {
193+
shellActivation,
194+
shellDeactivation,
195+
};
228196
}

src/managers/poetry/poetryUtils.ts

Lines changed: 6 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,20 @@ import * as fs from 'fs-extra';
22
import * as path from 'path';
33
import { Uri } from 'vscode';
44
import which from 'which';
5-
import {
6-
EnvironmentManager,
7-
PythonCommandRunConfiguration,
8-
PythonEnvironment,
9-
PythonEnvironmentApi,
10-
PythonEnvironmentInfo,
11-
} from '../../api';
5+
import { EnvironmentManager, PythonEnvironment, PythonEnvironmentApi, PythonEnvironmentInfo } from '../../api';
126
import { ENVS_EXTENSION_ID } from '../../common/constants';
137
import { traceError, traceInfo } from '../../common/logging';
148
import { getWorkspacePersistentState } from '../../common/persistentState';
159
import { getUserHomeDir, untildify } from '../../common/utils/pathUtils';
1610
import { isWindows } from '../../common/utils/platformUtils';
17-
import { ShellConstants } from '../../features/common/shellConstants';
1811
import {
1912
isNativeEnvInfo,
2013
NativeEnvInfo,
2114
NativeEnvManagerInfo,
2215
NativePythonEnvironmentKind,
2316
NativePythonFinder,
2417
} from '../common/nativePythonFinder';
25-
import { getPythonInfo, shortVersion, sortEnvironments } from '../common/utils';
18+
import { getShellActivationCommands, shortVersion, sortEnvironments } from '../common/utils';
2619

2720
async function findPoetry(): Promise<string | undefined> {
2821
try {
@@ -229,45 +222,6 @@ export async function getPoetryVersion(poetry: string): Promise<string | undefin
229222
return undefined;
230223
}
231224
}
232-
function createShellActivation(
233-
poetry: string,
234-
_prefix: string,
235-
): Map<string, PythonCommandRunConfiguration[]> | undefined {
236-
const shellActivation: Map<string, PythonCommandRunConfiguration[]> = new Map();
237-
238-
shellActivation.set(ShellConstants.BASH, [{ executable: poetry, args: ['shell'] }]);
239-
shellActivation.set(ShellConstants.ZSH, [{ executable: poetry, args: ['shell'] }]);
240-
shellActivation.set(ShellConstants.SH, [{ executable: poetry, args: ['shell'] }]);
241-
shellActivation.set(ShellConstants.GITBASH, [{ executable: poetry, args: ['shell'] }]);
242-
shellActivation.set(ShellConstants.FISH, [{ executable: poetry, args: ['shell'] }]);
243-
shellActivation.set(ShellConstants.PWSH, [{ executable: poetry, args: ['shell'] }]);
244-
if (isWindows()) {
245-
shellActivation.set(ShellConstants.CMD, [{ executable: poetry, args: ['shell'] }]);
246-
}
247-
shellActivation.set(ShellConstants.NU, [{ executable: poetry, args: ['shell'] }]);
248-
shellActivation.set('unknown', [{ executable: poetry, args: ['shell'] }]);
249-
return shellActivation;
250-
}
251-
252-
function createShellDeactivation(): Map<string, PythonCommandRunConfiguration[]> {
253-
const shellDeactivation: Map<string, PythonCommandRunConfiguration[]> = new Map();
254-
255-
// Poetry doesn't have a standard deactivation command like venv does
256-
// The best approach is to exit the shell or start a new one
257-
shellDeactivation.set('unknown', [{ executable: 'exit' }]);
258-
259-
shellDeactivation.set(ShellConstants.BASH, [{ executable: 'exit' }]);
260-
shellDeactivation.set(ShellConstants.ZSH, [{ executable: 'exit' }]);
261-
shellDeactivation.set(ShellConstants.SH, [{ executable: 'exit' }]);
262-
shellDeactivation.set(ShellConstants.GITBASH, [{ executable: 'exit' }]);
263-
shellDeactivation.set(ShellConstants.FISH, [{ executable: 'exit' }]);
264-
shellDeactivation.set(ShellConstants.PWSH, [{ executable: 'exit' }]);
265-
shellDeactivation.set(ShellConstants.CMD, [{ executable: 'exit' }]);
266-
shellDeactivation.set(ShellConstants.NU, [{ executable: 'exit' }]);
267-
268-
return shellDeactivation;
269-
}
270-
271225
async function nativeToPythonEnv(
272226
info: NativeEnvInfo,
273227
api: PythonEnvironmentApi,
@@ -283,11 +237,6 @@ async function nativeToPythonEnv(
283237
const name = info.name || info.displayName || path.basename(info.prefix);
284238
const displayName = info.displayName || `poetry (${sv})`;
285239

286-
const shellActivation = createShellActivation(_poetry, info.prefix);
287-
const shellDeactivation = createShellDeactivation();
288-
console.log('shellActivation', shellActivation);
289-
console.log('shellDeactivation', shellDeactivation);
290-
291240
// Check if this is a global Poetry virtualenv by checking if it's in Poetry's virtualenvs directory
292241
// We need to use path.normalize() to ensure consistent path format comparison
293242
const normalizedPrefix = path.normalize(info.prefix);
@@ -311,12 +260,8 @@ async function nativeToPythonEnv(
311260
}
312261

313262
// Get generic python environment info to access shell activation/deactivation commands following Poetry 2.0+ dropping the `shell` command
314-
const nativeEnvironmentInfo: NativeEnvInfo = {
315-
executable: info.executable,
316-
version: info.version,
317-
prefix: info.prefix,
318-
};
319-
const pythonInfo: PythonEnvironmentInfo = await getPythonInfo(nativeEnvironmentInfo);
263+
const binDir = path.dirname(info.executable);
264+
const { shellActivation, shellDeactivation } = await getShellActivationCommands(binDir);
320265

321266
const environment: PythonEnvironmentInfo = {
322267
name: name,
@@ -329,8 +274,8 @@ async function nativeToPythonEnv(
329274
tooltip: info.prefix,
330275
execInfo: {
331276
run: { executable: info.executable },
332-
shellActivation: pythonInfo.execInfo.shellActivation,
333-
shellDeactivation: pythonInfo.execInfo.shellDeactivation,
277+
shellActivation,
278+
shellDeactivation,
334279
},
335280
sysPrefix: info.prefix,
336281
group: isGlobalPoetryEnv ? POETRY_GLOBAL : undefined,

0 commit comments

Comments
 (0)