Skip to content
Draft
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
5 changes: 5 additions & 0 deletions extensions/positron-python/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,11 @@
"category": "Python",
"command": "python.interpreters.debugInfo",
"title": "%python.command.python.interpreterDebugInfo.title%"
},
{
"category": "Python",
"command": "python.getEnvironmentHealth",
"title": "%python.command.python.getEnvironmentHealth.title%"
}
],
"configuration": {
Expand Down
1 change: 1 addition & 0 deletions extensions/positron-python/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"python.command.python.refreshTensorBoard.title": "Refresh TensorBoard",
"python.command.python.testing.copyTestId.title": "Copy Test Id",
"python.command.python.interpreterDebugInfo.title": "Print interpreter debug information to Output",
"python.command.python.getEnvironmentHealth.title": "Print environment health report to Output",
"python.createEnvironment.contentButton.description": "Show or hide Create Environment button in the editor for `requirements.txt` or other dependency files.",
"python.createEnvironment.trigger.description": "Detect if environment creation is required for the current project",
"python.menu.createNewFile.title": "Python File",
Expand Down
1 change: 1 addition & 0 deletions extensions/positron-python/src/client/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export namespace Commands {
export const Create_Pyproject_Toml = 'python.createPyprojectToml';
export const InstallPackages = 'python.installPackages';
export const InstallPythonViaUv = 'python.installPythonViaUv';
export const Get_Environment_Health = 'python.getEnvironmentHealth';
// --- End Positron ---
export const InstallJupyter = 'python.installJupyter';
export const InstallPython = 'python.installPython';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,10 @@ function getArchitectureSortName(arch?: Architecture) {
}
}

function isBaseCondaEnvironment(environment: PythonEnvironment): boolean {
// --- Start Positron ---
// export this
export function isBaseCondaEnvironment(environment: PythonEnvironment): boolean {
// --- End Positron ---
return (
environment.envType === EnvironmentType.Conda &&
(environment.envName === 'base' || environment.envName === 'miniconda')
Expand Down
40 changes: 36 additions & 4 deletions extensions/positron-python/src/client/positron/createEnvApi.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
/*---------------------------------------------------------------------------------------------
* Copyright (C) 2024-2025 Posit Software, PBC. All rights reserved.
* Copyright (C) 2024-2026 Posit Software, PBC. All rights reserved.
* Licensed under the Elastic License 2.0. See LICENSE.txt for license information.
*--------------------------------------------------------------------------------------------*/

// eslint-disable-next-line import/no-unresolved
import * as positron from 'positron';
import { Uri, WorkspaceFolder } from 'vscode';
import { CreateEnvironmentOptionsInternal } from '../pythonEnvironments/creation/types';
import {
CreateEnvironmentOptions,
Expand All @@ -16,7 +17,7 @@ import { IPythonRuntimeManager } from './manager';
import { getExtension } from '../common/vscodeApis/extensionsApi';
import { PythonExtension } from '../api/types';
import { PVSC_EXTENSION_ID } from '../common/constants';
import { getConfiguration } from '../common/vscodeApis/workspaceApis';
import { getConfiguration, getWorkspaceFolder } from '../common/vscodeApis/workspaceApis';
import { CONDA_PROVIDER_ID } from '../pythonEnvironments/creation/provider/condaCreationProvider';
import { VenvCreationProviderId } from '../pythonEnvironments/creation/provider/venvCreationProvider';
import { UV_PROVIDER_ID } from '../pythonEnvironments/creation/provider/uvCreationProvider';
Expand All @@ -36,6 +37,33 @@ interface FlowEnvironmentProviders {
*/
type CreateEnvironmentAndRegisterResult = CreateEnvironmentResult & { metadata?: positron.LanguageRuntimeMetadata };

/**
* JSON-safe options for the `python.createEnvironmentAndRegister` command. Mirrors
* `CreateEnvironmentOptions & CreateEnvironmentOptionsInternal`, but `workspaceFolder` is a URI
* string instead of a `WorkspaceFolder` object, so callers can pass this across a command
* boundary (e.g. embedded in `fix.args`) without needing to serialize a `WorkspaceFolder`.
*/
export interface CreateEnvironmentAndRegisterOptions
extends Omit<CreateEnvironmentOptions & CreateEnvironmentOptionsInternal, 'workspaceFolder'> {
workspaceFolder?: string;
}

/**
* Rehydrates a workspace folder URI string into a `WorkspaceFolder`.
* @param workspaceFolderUri The URI string of the workspace folder, or undefined.
* @returns The corresponding `WorkspaceFolder`, or undefined if no URI was given.
*/
function rehydrateWorkspaceFolder(workspaceFolderUri: string | undefined): WorkspaceFolder | undefined {
if (!workspaceFolderUri) {
return undefined;
}
const folder = getWorkspaceFolder(Uri.parse(workspaceFolderUri));
if (!folder) {
throw new Error(`Workspace folder not found for URI: ${workspaceFolderUri}`);
}
return folder;
}

/**
* Get the list of providers that can be used in the Positron New Folder Flow
* @param providers The available environment creation providers
Expand All @@ -61,7 +89,7 @@ export async function getCreateEnvironmentProviders(
export async function createEnvironmentAndRegister(
providers: readonly CreateEnvironmentProvider[],
pythonRuntimeManager: IPythonRuntimeManager,
options: CreateEnvironmentOptions & CreateEnvironmentOptionsInternal,
options: CreateEnvironmentAndRegisterOptions,
): Promise<CreateEnvironmentAndRegisterResult | undefined> {
if (!options.providerId || (!options.interpreterPath && !options.condaPythonVersion && !options.uvPythonVersion)) {
return {
Expand All @@ -70,7 +98,11 @@ export async function createEnvironmentAndRegister(
),
};
}
const result = await handleCreateEnvironmentCommand(providers, options);
const resolvedOptions: CreateEnvironmentOptions & CreateEnvironmentOptionsInternal = {
...options,
workspaceFolder: rehydrateWorkspaceFolder(options.workspaceFolder),
};
const result = await handleCreateEnvironmentCommand(providers, resolvedOptions);
if (result?.path) {
const metadata = await pythonRuntimeManager.registerLanguageRuntimeFromPath(result.path);
return { ...result, metadata };
Expand Down
Loading
Loading