Skip to content

Commit 9b6ae37

Browse files
committed
Revert environment manager work
1 parent f1f409f commit 9b6ae37

29 files changed

Lines changed: 323 additions & 500 deletions

‎README.md‎

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,6 @@ The following environment managers are supported out of the box:
6565

6666
Environment managers are responsible for specifying which package manager will be used by default to install and manage Python packages within the environment (`venv` uses `pip` by default). This ensures that packages are managed consistently according to the preferred tools and settings of the chosen environment manager.
6767

68-
The built-in `venv` environment manager uses separate standard-library venv and uv creation
69-
backends. Creation automatically uses uv when the existing uv policy allows it and uv is available
70-
to the creation scope; otherwise it uses `python -m venv`. Backend execution errors are reported
71-
without retrying through the other backend. Both kinds of virtual environment retain the same
72-
`ms-python.python:venv` manager identity, discovery, selection, and removal behavior. Backend
73-
selection does not hide existing environments when uv availability or `python-envs.alwaysUseUv` changes.
74-
7568
### Package Management
7669

7770
The extension also provides an interface to install and uninstall Python packages, and provides APIs for extension developers to contribute package managers of their choice.
@@ -95,6 +88,7 @@ manager explicitly always uses uv, independently of that setting. The uv package
9588
uv from PATH, a current-session installation, or the requesting trusted workspace's `.pyprojectx/main/uv`
9689
(`uv.exe` on Windows). If uv is unavailable, it reports an error rather than falling back to pip.
9790
Scoped requests use the project to discover uv even when the target environment is outside the workspace.
91+
Explicit uv selection also retains this scope for project-tree package operations.
9892
Package mutations invalidate both built-in backends' cached inventory for the target environment,
9993
so switching between pip and uv does not reuse a snapshot from before the mutation.
10094

‎src/managers/builtin/environmentCreation.ts‎

Lines changed: 0 additions & 45 deletions
This file was deleted.

‎src/managers/builtin/main.ts‎

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ import { BuiltInPackageManager } from './builtInPackageManager';
88
import { PipPackageManager } from './pipPackageManager';
99
import { SysPythonManager } from './sysPythonManager';
1010
import { UvPackageManager } from './uvPackageManager';
11-
import { VenvEnvironmentManager } from './venvEnvironmentManager';
12-
import { BuiltInEnvironmentManager } from './builtInEnvironmentManager';
13-
import { UvEnvironmentManager } from './uvEnvironmentManager';
11+
import { VenvManager } from './venvManager';
1412

1513
export async function registerSystemPythonFeatures(
1614
nativeFinder: NativePythonFinder,
@@ -19,14 +17,7 @@ export async function registerSystemPythonFeatures(
1917
envManager: SysPythonManager,
2018
): Promise<void> {
2119
const api: PythonEnvironmentApi = await getPythonApi();
22-
const venvManager = new BuiltInEnvironmentManager(
23-
nativeFinder,
24-
api,
25-
envManager,
26-
log,
27-
new VenvEnvironmentManager(),
28-
new UvEnvironmentManager(),
29-
);
20+
const venvManager = new VenvManager(nativeFinder, api, envManager, log);
3021
const uvPackageManager = new UvPackageManager(api, log, venvManager);
3122
const pipPackageManager = new PipPackageManager(api, log, venvManager);
3223
const pkgManager = new BuiltInPackageManager(pipPackageManager, uvPackageManager);

‎src/managers/builtin/pipPackageManager.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ import {
4949
PipVersionCommand,
5050
} from './commands/index';
5151
import { getWorkspacePackagesToInstall } from './pipUtils';
52-
import { BuiltInEnvironmentManager } from './builtInEnvironmentManager';
52+
import { VenvManager } from './venvManager';
5353

5454
/** Manages packages using only the selected environment's pip installation. */
5555
export class PipPackageManager implements PackageManager, Disposable {
@@ -98,7 +98,7 @@ export class PipPackageManager implements PackageManager, Disposable {
9898
constructor(
9999
private readonly api: PythonEnvironmentApi,
100100
public readonly log: LogOutputChannel,
101-
private readonly venv: BuiltInEnvironmentManager,
101+
private readonly venv: VenvManager,
102102
) {}
103103
readonly name = 'pip';
104104
readonly displayName = 'Pip';

‎src/managers/builtin/uvEnvironmentManager.ts‎

Lines changed: 0 additions & 31 deletions
This file was deleted.

‎src/managers/builtin/uvPackageManager.ts‎

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@ import {
2525
PackageManagerCapability,
2626
PythonEnvironment,
2727
PythonEnvironmentApi,
28+
PythonProject,
2829
} from '../../api';
2930
import { showErrorMessageWithLogs } from '../../common/errors/utils';
3031
import { PythonVersion } from '../../common/pythonVersion';
3132
import { showErrorMessage, withProgress } from '../../common/window.apis';
32-
import { PackageToolSupport, pythonToolSupport, throwIfCancelled } from '../../internal/pythonToolSupport';
33+
import { PackageToolSupport, pythonToolSupport, throwIfCancelled, ToolPackageManager } from '../../internal/pythonToolSupport';
3334
import { CommandConstructorOptions } from '../base/commands/index';
3435
import { updatePackagesAndNotify } from '../common/packageChanges';
3536
import { parsePackageSpecs } from '../common/packageUtils';
@@ -43,7 +44,7 @@ import {
4344
} from './commands/index';
4445
import { getUvExecutable } from './helpers';
4546
import { getWorkspacePackagesToInstall } from './pipUtils';
46-
import { BuiltInEnvironmentManager } from './builtInEnvironmentManager';
47+
import { VenvManager } from './venvManager';
4748

4849
/** Manages packages using only uv, without requiring pip in the environment. */
4950
export class UvPackageManager implements PackageManager, Disposable {
@@ -79,9 +80,36 @@ export class UvPackageManager implements PackageManager, Disposable {
7980
constructor(
8081
private readonly api: PythonEnvironmentApi,
8182
public readonly log: LogOutputChannel,
82-
private readonly venv: BuiltInEnvironmentManager,
83+
private readonly venv: VenvManager,
8384
) {}
8485

86+
/**
87+
* Binds UI operations to a project while retaining this manager's cache and registered identity.
88+
* @param project Project whose workspace-local uv executable should be used.
89+
*/
90+
createForProject(project: PythonProject): ToolPackageManager {
91+
return this.withScope(project.uri);
92+
}
93+
94+
private withScope(scope: Uri): ToolPackageManager {
95+
return {
96+
name: this.name,
97+
displayName: this.displayName,
98+
description: this.description,
99+
tooltip: this.tooltip,
100+
iconPath: this.iconPath,
101+
log: this.log,
102+
capabilities: this.capabilities,
103+
[pythonToolSupport]: this[pythonToolSupport],
104+
manage: (environment, options) => this.manage(environment, options, undefined, scope),
105+
refresh: (environment) => this.refresh(environment, scope),
106+
getPackages: (environment, options) => this.getPackages(environment, options, scope),
107+
getVersion: (environment) => this.getVersion(environment, scope),
108+
getPackageAvailableVersions: (environment, name) => this.getPackageAvailableVersions(environment, name, scope),
109+
getDirectPackageNames: (environment) => this.getDirectPackageNames(environment, scope),
110+
};
111+
}
112+
85113
/**
86114
* Evicts cached inventory and prevents older reads from restoring it.
87115
* @param environment Environment whose inventory may have changed.
@@ -192,7 +220,7 @@ export class UvPackageManager implements PackageManager, Disposable {
192220
}
193221
}
194222
await updatePackagesAndNotify(
195-
this,
223+
scope ? this.withScope(scope) : this,
196224
environment,
197225
before,
198226
(changes) => this._onDidChangePackages.fire({ environment, manager: this, changes }),
@@ -232,13 +260,13 @@ export class UvPackageManager implements PackageManager, Disposable {
232260
}
233261

234262
/** Refreshes cached packages and emits changes for the target environment. */
235-
async refresh(environment: PythonEnvironment): Promise<void> {
263+
async refresh(environment: PythonEnvironment, scope?: Uri): Promise<void> {
236264
await withProgress(
237265
{ location: ProgressLocation.Window, title: l10n.t('Refreshing packages') },
238266
async () => {
239267
const revision = this.packageCacheRevisions.get(environment.envId.id);
240268
const packages = await updatePackagesAndNotify(
241-
this, environment, this.packages.get(environment.envId.id),
269+
scope ? this.withScope(scope) : this, environment, this.packages.get(environment.envId.id),
242270
(changes) => this._onDidChangePackages.fire({ environment, manager: this, changes }),
243271
);
244272
if (packages !== undefined && revision === this.packageCacheRevisions.get(environment.envId.id)) {
@@ -249,9 +277,13 @@ export class UvPackageManager implements PackageManager, Disposable {
249277
}
250278

251279
/** Lists installed packages, using the cache unless options request a fresh snapshot. */
252-
async getPackages(environment: PythonEnvironment, options?: GetPackagesOptions): Promise<Package[] | undefined> {
280+
async getPackages(
281+
environment: PythonEnvironment,
282+
options?: GetPackagesOptions,
283+
scope?: Uri,
284+
): Promise<Package[] | undefined> {
253285
if (options?.skipCache || !this.packages.has(environment.envId.id)) {
254-
return this.fetchPackages(environment);
286+
return this.fetchPackages(environment, true, undefined, scope);
255287
}
256288
return this.packages.get(environment.envId.id);
257289
}
@@ -292,31 +324,35 @@ export class UvPackageManager implements PackageManager, Disposable {
292324
}
293325

294326
/** Returns the uv version, logging failures when it cannot be determined. */
295-
async getVersion(environment: PythonEnvironment): Promise<Pep440Version | undefined> {
327+
async getVersion(environment: PythonEnvironment, scope?: Uri): Promise<Pep440Version | undefined> {
296328
try {
297-
return await new UvVersionCommand(await this.getCommandOptions(environment)).execute();
329+
return await new UvVersionCommand(await this.getCommandOptions(environment, { cwd: scope?.fsPath })).execute();
298330
} catch (error) {
299331
this.log.error('Error determining uv version', error);
300332
return undefined;
301333
}
302334
}
303335

304336
/** Lists compatible versions of packageName, newest first, without querying the environment's pip. */
305-
async getPackageAvailableVersions(environment: PythonEnvironment, packageName: string): Promise<Pep440Version[]> {
337+
async getPackageAvailableVersions(
338+
environment: PythonEnvironment,
339+
packageName: string,
340+
scope?: Uri,
341+
): Promise<Pep440Version[]> {
306342
const pythonVersion = environment.version
307343
? PythonVersion.tryParse(environment.version)?.toReleaseString()
308344
: undefined;
309345
if (!pythonVersion) {
310346
throw new Error(`Python version is unavailable for environment: ${environment.envId.id}`);
311347
}
312-
const command = new UvAvailableVersionsCommand(await this.getCommandOptions(environment));
348+
const command = new UvAvailableVersionsCommand(await this.getCommandOptions(environment, { cwd: scope?.fsPath }));
313349
const versions = await command.execute({ packageName, pythonVersion });
314350
return versions.sort((a, b) => compare(b.public, a.public));
315351
}
316352

317353
/** Returns dependency-root package names, which need not reflect explicit user install intent. */
318-
async getDirectPackageNames(environment: PythonEnvironment): Promise<Set<string> | undefined> {
319-
return new UvListDirectNamesCommand(await this.getCommandOptions(environment)).execute();
354+
async getDirectPackageNames(environment: PythonEnvironment, scope?: Uri): Promise<Set<string> | undefined> {
355+
return new UvListDirectNamesCommand(await this.getCommandOptions(environment, { cwd: scope?.fsPath })).execute();
320356
}
321357

322358
/** Releases package-change listeners and cached packages. */

‎src/managers/builtin/venvEnvironmentManager.ts‎

Lines changed: 0 additions & 26 deletions
This file was deleted.

src/managers/builtin/builtInEnvironmentManager.ts renamed to src/managers/builtin/venvManager.ts

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,8 @@ import { findParentIfFile } from '../../features/envCommands';
5050
import { getProjectFsPathForScope, tryFastPathGet } from '../common/fastPath';
5151
import { NativePythonFinder } from '../common/nativePythonFinder';
5252
import { getLatest, shortenVersionString, sortEnvironments } from '../common/utils';
53-
import { getDefaultGlobalPython, resolveSystemPythonEnvironmentPath } from './utils';
54-
import { EnvironmentBackendSelector, EnvironmentCreationBackend, selectEnvironmentBackend } from './environmentCreation';
55-
import { VenvEnvironmentManager } from './venvEnvironmentManager';
56-
import { UvEnvironmentManager } from './uvEnvironmentManager';
5753
import { promptInstallPython } from './pythonInstaller';
54+
import { getDefaultGlobalPython, resolveSystemPythonEnvironmentPath } from './utils';
5855
import {
5956
clearVenvCache,
6057
CreateEnvironmentResult,
@@ -72,7 +69,7 @@ import {
7269
setVenvForWorkspaces,
7370
} from './venvUtils';
7471

75-
export class BuiltInEnvironmentManager implements EnvironmentManager {
72+
export class VenvManager implements EnvironmentManager {
7673
readonly capabilities: Capabilities<EnvironmentManagerCapability> = {
7774
[EnvironmentCapability.List]: supportedCapability,
7875
[EnvironmentCapability.Resolve]: supportedCapability,
@@ -107,8 +104,6 @@ export class BuiltInEnvironmentManager implements EnvironmentManager {
107104
private readonly api: PythonEnvironmentApi,
108105
private readonly baseManager: EnvironmentManager,
109106
public readonly log: LogOutputChannel,
110-
private readonly venv: EnvironmentCreationBackend = new VenvEnvironmentManager(),
111-
private readonly uv: EnvironmentCreationBackend = new UvEnvironmentManager(),
112107
) {
113108
this.name = 'venv';
114109
this.displayName = 'venv';
@@ -120,9 +115,6 @@ export class BuiltInEnvironmentManager implements EnvironmentManager {
120115
this.iconPath = new ThemeIcon('python');
121116
}
122117

123-
private readonly selectCreationBackend: EnvironmentBackendSelector = (base, root, token) =>
124-
selectEnvironmentBackend(this.log, base, root, token, this.venv, this.uv);
125-
126118
private _initialized: Deferred<void> | undefined;
127119
private discovery: Deferred<void> | undefined;
128120
private initializationError: unknown;
@@ -226,7 +218,6 @@ export class BuiltInEnvironmentManager implements EnvironmentManager {
226218
scope,
227219
undefined,
228220
operation,
229-
this.selectCreationBackend,
230221
);
231222
if (!result?.environment) {
232223
throw new PythonToolError(
@@ -354,23 +345,14 @@ export class BuiltInEnvironmentManager implements EnvironmentManager {
354345
this.globalEnv,
355346
venvRoot,
356347
options?.additionalPackages,
357-
undefined,
358-
this.selectCreationBackend,
359348
);
360349
}
361350
} else {
362351
// If quickCreate is not set that means the user triggered this method from
363352
// environment manager View, by selecting the venv manager.
364-
result = await createPythonVenv(
365-
this.nativeFinder,
366-
this.api,
367-
this.log,
368-
this,
369-
globals,
370-
venvRoot,
371-
{ showQuickAndCustomOptions: options?.quickCreate === undefined },
372-
this.selectCreationBackend,
373-
);
353+
result = await createPythonVenv(this.nativeFinder, this.api, this.log, this, globals, venvRoot, {
354+
showQuickAndCustomOptions: options?.quickCreate === undefined,
355+
});
374356
}
375357

376358
if (result?.environment) {

0 commit comments

Comments
 (0)