Skip to content

Commit 832c187

Browse files
authored
Enhance Pipenv manager registration and configuration (#1170)
Fixes #590 Improve the Pipenv manager to support existing environments even when the CLI is not available. Update the configuration to include the Pipenv executable path for better integration.
1 parent 462976c commit 832c187

File tree

3 files changed

+43
-13
lines changed

3 files changed

+43
-13
lines changed

src/managers/common/nativePythonFinder.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,7 @@ class NativePythonFinderImpl implements NativePythonFinder {
568568
workspaceDirectories: this.api.getPythonProjects().map((item) => item.uri.fsPath),
569569
environmentDirectories: extraSearchPaths,
570570
condaExecutable: getPythonSettingAndUntildify<string>('condaPath'),
571+
pipenvExecutable: getPythonSettingAndUntildify<string>('pipenvPath'),
571572
poetryExecutable: getPythonSettingAndUntildify<string>('poetryPath'),
572573
cacheDirectory: this.cacheDirectory?.fsPath,
573574
};
@@ -602,6 +603,9 @@ class NativePythonFinderImpl implements NativePythonFinder {
602603
if (a.condaExecutable !== b.condaExecutable) {
603604
return false;
604605
}
606+
if (a.pipenvExecutable !== b.pipenvExecutable) {
607+
return false;
608+
}
605609
if (a.poetryExecutable !== b.poetryExecutable) {
606610
return false;
607611
}
@@ -634,6 +638,7 @@ type ConfigurationOptions = {
634638
workspaceDirectories: string[];
635639
environmentDirectories: string[];
636640
condaExecutable: string | undefined;
641+
pipenvExecutable: string | undefined;
637642
poetryExecutable: string | undefined;
638643
cacheDirectory?: string;
639644
};

src/managers/pipenv/main.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { getPythonApi } from '../../features/pythonApi';
55
import { PythonProjectManager } from '../../internal.api';
66
import { NativePythonFinder } from '../common/nativePythonFinder';
77
import { PipenvManager } from './pipenvManager';
8-
import { getPipenv } from './pipenvUtils';
8+
import { getPipenv, hasPipenvEnvironments } from './pipenvUtils';
99

1010
import { notifyMissingManagerIfDefault } from '../common/utils';
1111

@@ -19,15 +19,29 @@ export async function registerPipenvFeatures(
1919
try {
2020
const pipenv = await getPipenv(nativeFinder);
2121

22-
if (pipenv) {
22+
// Register the manager if the CLI is found, or if there are existing pipenv environments.
23+
// This allows users with existing pipenv environments to still see and use them.
24+
const hasPipenvEnvs = !pipenv && (await hasPipenvEnvironments(nativeFinder));
25+
26+
if (pipenv || hasPipenvEnvs) {
2327
const mgr = new PipenvManager(nativeFinder, api);
2428
disposables.push(mgr, api.registerEnvironmentManager(mgr));
29+
if (!pipenv) {
30+
traceInfo(
31+
'Pipenv CLI not found, but pipenv environments were discovered. Registering manager for read-only environment management. To enable full pipenv features, set the "python.pipenvPath" setting to the path of your pipenv executable.',
32+
);
33+
}
2534
} else {
26-
traceInfo('Pipenv not found, turning off pipenv features.');
35+
traceInfo(
36+
'Pipenv not found, turning off pipenv features. If you have pipenv installed in a non-standard location, set the "python.pipenvPath" setting.',
37+
);
2738
await notifyMissingManagerIfDefault('ms-python.python:pipenv', projectManager, api);
2839
}
2940
} catch (ex) {
30-
traceInfo('Pipenv not found, turning off pipenv features.', ex);
41+
traceInfo(
42+
'Pipenv not found, turning off pipenv features. If you have pipenv installed in a non-standard location, set the "python.pipenvPath" setting.',
43+
ex,
44+
);
3145
await notifyMissingManagerIfDefault('ms-python.python:pipenv', projectManager, api);
3246
}
3347
}

src/managers/pipenv/pipenvUtils.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@ export async function clearPipenvCache(): Promise<void> {
4949
pipenvPath = undefined;
5050
}
5151

52+
/**
53+
* Check if any pipenv environments exist without requiring the pipenv CLI.
54+
* This allows the manager to be registered even if the CLI is not found.
55+
*/
56+
export async function hasPipenvEnvironments(nativeFinder: NativePythonFinder): Promise<boolean> {
57+
const data = await nativeFinder.refresh(false);
58+
return data
59+
.filter((e) => isNativeEnvInfo(e))
60+
.some((e) => (e as NativeEnvInfo).kind === NativePythonEnvironmentKind.pipenv);
61+
}
62+
5263
function getPipenvPathFromSettings(): string | undefined {
5364
const pipenvPath = getSettingWorkspaceScope<string>('python', 'pipenvPath');
5465
return pipenvPath ? pipenvPath : undefined;
@@ -191,12 +202,13 @@ export async function refreshPipenv(
191202

192203
const collection: PythonEnvironment[] = [];
193204

205+
// Add environments even if pipenv CLI is not found.
206+
// This allows users with existing pipenv environments to still see them
207+
// for read-only management (e.g., selecting the environment, viewing info).
194208
for (const e of envs) {
195-
if (pipenv) {
196-
const environment = await nativeToPythonEnv(e, api, manager);
197-
if (environment) {
198-
collection.push(environment);
199-
}
209+
const environment = await nativeToPythonEnv(e, api, manager);
210+
if (environment) {
211+
collection.push(environment);
200212
}
201213
}
202214

@@ -212,11 +224,10 @@ export async function resolvePipenvPath(
212224
): Promise<PythonEnvironment | undefined> {
213225
const resolved = await nativeFinder.resolve(fsPath);
214226

227+
// Resolve pipenv environments even if the pipenv CLI is not found.
228+
// This allows proper environment identification for read-only scenarios.
215229
if (resolved.kind === NativePythonEnvironmentKind.pipenv) {
216-
const pipenv = await getPipenv(nativeFinder);
217-
if (pipenv) {
218-
return await nativeToPythonEnv(resolved, api, manager);
219-
}
230+
return await nativeToPythonEnv(resolved, api, manager);
220231
}
221232

222233
return undefined;

0 commit comments

Comments
 (0)