Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,28 @@ import * as path from 'path';
export const ENVS_EXTENSION_ID = 'ms-python.vscode-python-envs';
export const PYTHON_EXTENSION_ID = 'ms-python.python';
export const PYLANCE_EXTENSION_ID = 'ms-python.vscode-pylance';

// Manager IDs
export const CONDA_MANAGER_ID = `${PYTHON_EXTENSION_ID}:conda`;
export const INLINE_SCRIPT_MANAGER_ID = `${PYTHON_EXTENSION_ID}:inline-script`;
export const INLINE_SCRIPT_ENVS_KEY = `${ENVS_EXTENSION_ID}:inline-script:SCRIPT_ENVIRONMENTS`;
export const PYENV_MANAGER_ID = `${PYTHON_EXTENSION_ID}:pyenv`;
export const PIPENV_MANAGER_ID = `${PYTHON_EXTENSION_ID}:pipenv`;
export const POETRY_MANAGER_ID = `${PYTHON_EXTENSION_ID}:poetry`;
export const PIXI_MANAGER_ID = `${PYTHON_EXTENSION_ID}:pixi`;
export const HATCH_MANAGER_ID = `${PYTHON_EXTENSION_ID}:hatch`;
export const PIP_MANAGER_ID = `${PYTHON_EXTENSION_ID}:pip`;
export const UV_MANAGER_ID = `${PYTHON_EXTENSION_ID}:uv`;
export const VENV_MANAGER_ID = `${PYTHON_EXTENSION_ID}:venv`;
export const SYSTEM_MANAGER_ID = `${PYTHON_EXTENSION_ID}:system`;

export const DEFAULT_PACKAGE_MANAGER_ID = PIP_MANAGER_ID;
export const DEFAULT_ENV_MANAGER_ID = VENV_MANAGER_ID;

export const JUPYTER_EXTENSION_ID = 'ms-toolsai.jupyter';
export const EXTENSION_ROOT_DIR = path.dirname(__dirname);
export const ISSUES_URL = 'https://github.com/microsoft/vscode-python-environments/issues';

export const DEFAULT_PACKAGE_MANAGER_ID = 'ms-python.python:pip';
export const DEFAULT_ENV_MANAGER_ID = 'ms-python.python:venv';
export const VENV_MANAGER_ID = 'ms-python.python:venv';
export const SYSTEM_MANAGER_ID = 'ms-python.python:system';

export const KNOWN_FILES = [
'requirements.txt',
'requirements.in',
Expand Down
28 changes: 19 additions & 9 deletions src/common/utils/pythonPath.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
import { CancellationToken, Progress, Uri } from 'vscode';
import { PythonEnvironment } from '../../api';
import type { InternalEnvironmentManager } from '../../managers/common/registeredManagers';
import { PYTHON_EXTENSION_ID } from '../constants';
import {
CONDA_MANAGER_ID,
HATCH_MANAGER_ID,
PIPENV_MANAGER_ID,
PIXI_MANAGER_ID,
POETRY_MANAGER_ID,
PYENV_MANAGER_ID,
PYTHON_EXTENSION_ID,
SYSTEM_MANAGER_ID,
VENV_MANAGER_ID,
} from '../constants';
import { traceVerbose, traceWarn } from '../logging';

const priorityOrder = [
`${PYTHON_EXTENSION_ID}:pyenv`,
`${PYTHON_EXTENSION_ID}:pixi`,
`${PYTHON_EXTENSION_ID}:conda`,
`${PYTHON_EXTENSION_ID}:pipenv`,
`${PYTHON_EXTENSION_ID}:poetry`,
PYENV_MANAGER_ID,
PIXI_MANAGER_ID,
CONDA_MANAGER_ID,
PIPENV_MANAGER_ID,
POETRY_MANAGER_ID,
`${PYTHON_EXTENSION_ID}:activestate`,
`${PYTHON_EXTENSION_ID}:hatch`,
`${PYTHON_EXTENSION_ID}:venv`,
`${PYTHON_EXTENSION_ID}:system`,
HATCH_MANAGER_ID,
VENV_MANAGER_ID,
SYSTEM_MANAGER_ID,
];
function sortManagersByPriority(managers: InternalEnvironmentManager[]): InternalEnvironmentManager[] {
const systemId = priorityOrder[priorityOrder.length - 1];
Expand Down
3 changes: 2 additions & 1 deletion src/features/creators/creationHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { traceError, traceVerbose } from '../../common/logging';
import { showQuickPickWithButtons } from '../../common/window.apis';
import type { EnvironmentManagers } from '../envManagers';
import type { InternalEnvironmentManager } from '../../managers/common/registeredManagers';
import { VENV_MANAGER_ID } from '../../common/constants';

/**
* Prompts the user to choose whether to create a new virtual environment (venv) for a project, with a clearer return and early exit.
Expand Down Expand Up @@ -74,7 +75,7 @@ export async function promptForCopilotInstructions(): Promise<boolean | undefine
export async function quickCreateNewVenv(envManagers: EnvironmentManagers, destFolder: string) {
// get the environment manager for venv, should always exist
const envManager: InternalEnvironmentManager | undefined = envManagers.managers.find(
(m) => m.id === 'ms-python.python:venv',
(m) => m.id === VENV_MANAGER_ID,
);
const destinationUri = Uri.parse(destFolder);
if (envManager?.supportsQuickCreate) {
Expand Down
4 changes: 2 additions & 2 deletions src/features/creators/newPackageProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as fs from 'fs-extra';
import * as path from 'path';
import { commands, l10n, MarkdownString, QuickInputButtons, Uri, window, workspace } from 'vscode';
import { PythonEnvironment, PythonProject, PythonProjectCreator, PythonProjectCreatorOptions } from '../../api';
import { NEW_PROJECT_TEMPLATES_FOLDER } from '../../common/constants';
import { NEW_PROJECT_TEMPLATES_FOLDER, VENV_MANAGER_ID } from '../../common/constants';
import { traceError } from '../../common/logging';
import { showInputBoxWithButtons } from '../../common/window.apis';
import type { EnvironmentManagers } from '../envManagers';
Expand Down Expand Up @@ -134,7 +134,7 @@ export class NewPackageProject implements PythonProjectCreator {
} else {
// get venv manager or any manager that supports quick creating environments
const venvManager = this.envManagers.managers.find(
(m) => m.id === 'ms-python.python:venv' || m.supportsQuickCreate,
(m) => m.id === VENV_MANAGER_ID || m.supportsQuickCreate,
);
if (venvManager) {
createdEnv = await venvManager.create(Uri.file(projectDestinationFolder), {
Expand Down
6 changes: 3 additions & 3 deletions src/managers/builtin/builtInEnvironmentManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
} from '../../api';
import { Capabilities, EnvironmentManagerCapability, supportedCapability, EnvironmentCapability } from '../../capabilities';
import { executeCommand } from '../../common/command.api';
import { PYTHON_EXTENSION_ID } from '../../common/constants';
import { DEFAULT_PACKAGE_MANAGER_ID, VENV_MANAGER_ID } from '../../common/constants';
import { PythonInstallStrings, VenvManagerStrings } from '../../common/localize';
import { traceError, traceWarn } from '../../common/logging';
import { createDeferred, Deferred } from '../../common/utils/deferred';
Expand Down Expand Up @@ -119,7 +119,7 @@ export class BuiltInEnvironmentManager implements EnvironmentManager {
// https://github.com/microsoft/vscode-python-environments/issues/167
this.description = undefined;
this.tooltip = new MarkdownString(VenvManagerStrings.venvManagerDescription, true);
this.preferredPackageManagerId = 'ms-python.python:pip';
this.preferredPackageManagerId = DEFAULT_PACKAGE_MANAGER_ID;
this.iconPath = new ThemeIcon('python');
}

Expand Down Expand Up @@ -728,7 +728,7 @@ export class BuiltInEnvironmentManager implements EnvironmentManager {
this.backends,
);
if (resolved) {
if (resolved.envId.managerId === `${PYTHON_EXTENSION_ID}:venv`) {
if (resolved.envId.managerId === VENV_MANAGER_ID) {
// We should only return the resolved env if it is a venv.
// Fall through an return undefined if it is not a venv
this.addEnvironment(resolved, true);
Expand Down
9 changes: 2 additions & 7 deletions src/managers/builtin/inlineScript/envManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,7 @@ import {
SetEnvironmentScope,
} from '../../../api';
import { Capabilities, EnvironmentManagerCapability, supportedCapability, EnvironmentCapability } from '../../../capabilities';
import {
CONDA_MANAGER_ID,
INLINE_SCRIPT_MANAGER_ID,
PYENV_MANAGER_ID,
SYSTEM_MANAGER_ID,
} from '../../../common/constants';
import { CONDA_MANAGER_ID, INLINE_SCRIPT_MANAGER_ID, PYENV_MANAGER_ID, SYSTEM_MANAGER_ID, DEFAULT_PACKAGE_MANAGER_ID } from '../../../common/constants';
import { getErrorMessage } from '../../../common/errors/utils';
import { computeCacheKey, normalizeDependency } from '../../../common/inlineScript/cacheKey';
import { InlineScriptEnvironmentModifiedError } from '../../../common/inlineScript/errors';
Expand Down Expand Up @@ -371,7 +366,7 @@ export class InlineScriptEnvManager implements EnvironmentManager, Disposable {

public readonly name = 'inline-script';
public readonly displayName = l10n.t('Inline scripts');
public readonly preferredPackageManagerId = 'ms-python.python:pip';
public readonly preferredPackageManagerId = DEFAULT_PACKAGE_MANAGER_ID;
public readonly description: string | undefined = undefined;
public readonly tooltip: string | MarkdownString = new MarkdownString(
l10n.t('Environments built from PEP 723 inline script metadata.'),
Expand Down
3 changes: 2 additions & 1 deletion src/managers/builtin/sysPythonManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
SetEnvironmentScope,
} from '../../api';
import { Capabilities, EnvironmentManagerCapability, supportedCapability, EnvironmentCapability } from '../../capabilities';
import { DEFAULT_PACKAGE_MANAGER_ID } from '../../common/constants';
import { PythonInstallStrings, SysManagerStrings } from '../../common/localize';
import { createDeferred, Deferred } from '../../common/utils/deferred';
import { isFileNotFoundError } from '../../common/utils/filesystem';
Expand Down Expand Up @@ -92,7 +93,7 @@ export class SysPythonManager implements EnvironmentManager {
) {
this.name = 'system';
this.displayName = 'Global';
this.preferredPackageManagerId = 'ms-python.python:pip';
this.preferredPackageManagerId = DEFAULT_PACKAGE_MANAGER_ID;
this.description = undefined;
this.tooltip = new MarkdownString(SysManagerStrings.sysManagerDescription, true);
this.iconPath = new ThemeIcon('globe');
Expand Down
5 changes: 3 additions & 2 deletions src/managers/conda/condaEnvManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import {
setCondaForWorkspace,
setCondaForWorkspaces,
} from './condaUtils';
import { CONDA_MANAGER_ID } from '../../common/constants';

export class CondaEnvManager implements EnvironmentManager, Disposable {
readonly capabilities: Capabilities<EnvironmentManagerCapability> = {
Expand Down Expand Up @@ -102,7 +103,7 @@ export class CondaEnvManager implements EnvironmentManager, Disposable {
) {
this.name = 'conda';
this.displayName = 'Conda';
this.preferredPackageManagerId = 'ms-python.python:conda';
this.preferredPackageManagerId = CONDA_MANAGER_ID;
this.tooltip = new MarkdownString(CondaStrings.condaManager, true);
}

Expand Down Expand Up @@ -251,7 +252,7 @@ export class CondaEnvManager implements EnvironmentManager, Disposable {
result = 'tool_not_found';
traceInfo('Conda not found, conda features will be inactive.');
if (this.projectManager) {
await notifyMissingManagerIfDefault('ms-python.python:conda', this.projectManager, this.api);
await notifyMissingManagerIfDefault(CONDA_MANAGER_ID, this.projectManager, this.api);
}
} else if (condaTool) {
// Conda was found — populate sourcing information for activation/shell support.
Expand Down
44 changes: 26 additions & 18 deletions src/managers/pipenv/pipenvManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ import {
ResolveEnvironmentContext,
SetEnvironmentScope,
} from '../../api';
import { Capabilities, EnvironmentManagerCapability, supportedCapability, EnvironmentCapability } from '../../capabilities';
import {
Capabilities,
EnvironmentCapability,
EnvironmentManagerCapability,
supportedCapability,
} from '../../capabilities';
import { PIPENV_MANAGER_ID, DEFAULT_PACKAGE_MANAGER_ID } from '../../common/constants';
import { PipenvStrings } from '../../common/localize';
import { traceError, traceInfo } from '../../common/logging';
import { StopWatch } from '../../common/stopWatch';
Expand All @@ -28,14 +34,14 @@ import { normalizePath } from '../../common/utils/pathUtils';
import { withProgress } from '../../common/window.apis';
import { getConfiguration } from '../../common/workspace.apis';
import type { PythonProjectManager } from '../../features/projectManager';
import { getProjectFsPathForScope, tryFastPathGet } from '../common/fastPath';
import { NativePythonEnvironmentKind, NativePythonFinder } from '../common/nativePythonFinder';
import { notifyMissingManagerIfDefault } from '../common/utils';
import {
EnvironmentToolSupport,
pythonToolSupport,
resolveToolProjectEnvironment,
} from '../../internal/pythonToolSupport';
import { getProjectFsPathForScope, tryFastPathGet } from '../common/fastPath';
import { NativePythonEnvironmentKind, NativePythonFinder } from '../common/nativePythonFinder';
import { notifyMissingManagerIfDefault } from '../common/utils';
import {
clearPipenvCache,
getPipenv,
Expand Down Expand Up @@ -91,7 +97,7 @@ export class PipenvManager implements EnvironmentManager, Disposable {
) {
this.name = 'pipenv';
this.displayName = 'Pipenv';
this.preferredPackageManagerId = 'ms-python.python:pip';
this.preferredPackageManagerId = DEFAULT_PACKAGE_MANAGER_ID;
this.tooltip = new MarkdownString(PipenvStrings.pipenvManager, true);
}

Expand Down Expand Up @@ -161,7 +167,7 @@ export class PipenvManager implements EnvironmentManager, Disposable {
if (toolSource === 'none') {
result = 'tool_not_found';
if (this.projectManager) {
await notifyMissingManagerIfDefault('ms-python.python:pipenv', this.projectManager, this.api);
await notifyMissingManagerIfDefault(PIPENV_MANAGER_ID, this.projectManager, this.api);
}
}
} catch (ex) {
Expand Down Expand Up @@ -369,18 +375,20 @@ export class PipenvManager implements EnvironmentManager, Disposable {
}

async get(scope: GetEnvironmentScope, toolExecution = false): Promise<PythonEnvironment | undefined> {
const fastResult = toolExecution ? undefined : await tryFastPathGet({
initialized: this._initialized,
setInitialized: (deferred) => {
this._initialized = deferred;
},
scope,
label: 'pipenv',
getProjectFsPath: (s) => getProjectFsPathForScope(this.api, s),
getPersistedPath: (fsPath) => getPipenvForWorkspace(fsPath),
resolve: (p) => resolvePipenvPath(p, this.nativeFinder, this.api, this),
startBackgroundInit: () => this.initializeDiscovery(),
});
const fastResult = toolExecution
? undefined
: await tryFastPathGet({
initialized: this._initialized,
setInitialized: (deferred) => {
this._initialized = deferred;
},
scope,
label: 'pipenv',
getProjectFsPath: (s) => getProjectFsPathForScope(this.api, s),
getPersistedPath: (fsPath) => getPipenvForWorkspace(fsPath),
resolve: (p) => resolvePipenvPath(p, this.nativeFinder, this.api, this),
startBackgroundInit: () => this.initializeDiscovery(),
});
if (fastResult) {
return fastResult.env;
}
Expand Down
5 changes: 3 additions & 2 deletions src/managers/poetry/poetryManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
setPoetryForWorkspaces,
} from './poetryUtils';
import { PoetryVersionCommand } from './commands/version';
import { POETRY_MANAGER_ID } from '../../common/constants';

export class PoetryManager implements EnvironmentManager, Disposable {
readonly capabilities: Capabilities<EnvironmentManagerCapability> = {
Expand Down Expand Up @@ -82,7 +83,7 @@ export class PoetryManager implements EnvironmentManager, Disposable {
) {
this.name = 'poetry';
this.displayName = 'Poetry';
this.preferredPackageManagerId = 'ms-python.python:poetry';
this.preferredPackageManagerId = POETRY_MANAGER_ID;
this.tooltip = new MarkdownString(PoetryStrings.poetryManager, true);
}

Expand Down Expand Up @@ -157,7 +158,7 @@ export class PoetryManager implements EnvironmentManager, Disposable {
if (toolSource === 'none') {
result = 'tool_not_found';
if (this.projectManager) {
await notifyMissingManagerIfDefault('ms-python.python:poetry', this.projectManager, this.api);
await notifyMissingManagerIfDefault(POETRY_MANAGER_ID, this.projectManager, this.api);
}
}
} catch (ex) {
Expand Down
4 changes: 2 additions & 2 deletions src/managers/pyenv/pyenvManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
SetEnvironmentScope,
} from '../../api';
import { Capabilities, EnvironmentManagerCapability, supportedCapability, EnvironmentCapability } from '../../capabilities';
import { PYENV_MANAGER_ID } from '../../common/constants';
import { PYENV_MANAGER_ID, DEFAULT_PACKAGE_MANAGER_ID } from '../../common/constants';
import { PyenvStrings } from '../../common/localize';
import { traceError, traceInfo } from '../../common/logging';
import { StopWatch } from '../../common/stopWatch';
Expand Down Expand Up @@ -80,7 +80,7 @@ export class PyEnvManager implements EnvironmentManager, Disposable {
) {
this.name = 'pyenv';
this.displayName = 'PyEnv';
this.preferredPackageManagerId = 'ms-python.python:pip';
this.preferredPackageManagerId = DEFAULT_PACKAGE_MANAGER_ID;
this.tooltip = new MarkdownString(PyenvStrings.pyenvManager, true);
}

Expand Down
5 changes: 3 additions & 2 deletions src/test/common/inlineScript/cacheLayout.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import * as logging from '../../../common/logging';
import { createDeferred } from '../../../common/utils/deferred';
import * as platformUtils from '../../../common/utils/platformUtils';
import { getVenvPythonPath } from '../../../common/utils/virtualEnvironment';
import { INLINE_SCRIPT_MANAGER_ID, SYSTEM_MANAGER_ID } from '../../../common/constants';

// `import * as` would copy the module, leaving the spy unable to observe the real rename that
// cacheLayout calls.
Expand Down Expand Up @@ -857,7 +858,7 @@ suite('inlineScriptCacheLayout', () => {
const pythonPath = getVenvPythonPath(envDir.fsPath);
await fs.outputFile(pythonPath, '');
environment = {
envId: { id: 'inline-env', managerId: 'ms-python.python:inline-script' },
envId: { id: 'inline-env', managerId: INLINE_SCRIPT_MANAGER_ID },
name: 'Python 3.12.4',
displayName: 'Python 3.12.4',
displayPath: pythonPath,
Expand All @@ -879,7 +880,7 @@ suite('inlineScriptCacheLayout', () => {
test('does not claim environments owned by another manager', async () => {
const otherManager = {
...environment,
envId: { ...environment.envId, managerId: 'ms-python.python:system' },
envId: { ...environment.envId, managerId: SYSTEM_MANAGER_ID },
};
assert.strictEqual(await inspectOwnedCacheEntry(otherManager, cacheRoot, envDir), 'uncertain');
});
Expand Down
3 changes: 2 additions & 1 deletion src/test/common/inlineScript/interpreter.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import { Uri } from 'vscode';
import { PythonEnvironment } from '../../../api';
import { extractLowerBoundVersion, pickCompatibleInterpreter } from '../../../common/inlineScript/interpreter';
import * as logging from '../../../common/logging';
import { SYSTEM_MANAGER_ID } from '../../../common/constants';

function makeEnv(version: string, name = `Python ${version}`, error?: string): PythonEnvironment {
return {
envId: { id: name, managerId: 'ms-python.python:system' },
envId: { id: name, managerId: SYSTEM_MANAGER_ID },
name,
displayName: name,
displayPath: `/usr/bin/${name}`,
Expand Down
Loading
Loading