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
52 changes: 50 additions & 2 deletions examples/sample1/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,18 @@ export type DidChangeEnvironmentsEventArgs = {
*/
export type ResolveEnvironmentContext = Uri;

export interface QuickCreateConfig {
/**
* The description of the quick create step.
*/
readonly description: string;

/**
* The detail of the quick create step.
*/
readonly detail?: string;
}

/**
* Interface representing an environment manager.
*/
Expand Down Expand Up @@ -360,12 +372,19 @@ export interface EnvironmentManager {
*/
readonly log?: LogOutputChannel;

/**
* The quick create details for the environment manager. Having this method also enables the quick create feature
* for the environment manager.
*/
quickCreateConfig?(): QuickCreateConfig | undefined;

/**
* Creates a new Python environment within the specified scope.
* @param scope - The scope within which to create the environment.
* @param options - Optional parameters for creating the Python environment.
* @returns A promise that resolves to the created Python environment, or undefined if creation failed.
*/
create?(scope: CreateEnvironmentScope): Promise<PythonEnvironment | undefined>;
create?(scope: CreateEnvironmentScope, options?: CreateEnvironmentOptions): Promise<PythonEnvironment | undefined>;

/**
* Removes the specified Python environment.
Expand Down Expand Up @@ -705,6 +724,9 @@ export interface DidChangePythonProjectsEventArgs {
removed: PythonProject[];
}

/**
* Options for package management.
*/
export type PackageManagementOptions =
| {
/**
Expand Down Expand Up @@ -747,6 +769,28 @@ export type PackageManagementOptions =
uninstall: string[];
};

/**
* Options for creating a Python environment.
*/
export interface CreateEnvironmentOptions {
/**
* Provides some context about quick create based on user input.
* - if true, the environment should be created without any user input or prompts.
* - if false, the environment creation can show user input or prompts.
* This also means user explicitly skipped the quick create option.
* - if undefined, the environment creation can show user input or prompts.
* You can show quick create option to the user if you support it.
*/
quickCreate?: boolean;
/**
* Packages to install in addition to the automatically picked packages as a part of creating environment.
*/
additionalPackages?: string[];
}

/**
* Object representing the process started using run in background API.
*/
export interface PythonProcess {
/**
* The process ID of the Python process.
Expand Down Expand Up @@ -807,9 +851,13 @@ export interface PythonEnvironmentManagementApi {
* Create a Python environment using environment manager associated with the scope.
*
* @param scope Where the environment is to be created.
* @param options Optional parameters for creating the Python environment.
* @returns The Python environment created. `undefined` if not created.
*/
createEnvironment(scope: CreateEnvironmentScope): Promise<PythonEnvironment | undefined>;
createEnvironment(
scope: CreateEnvironmentScope,
options?: CreateEnvironmentOptions,
): Promise<PythonEnvironment | undefined>;

/**
* Remove a Python environment.
Expand Down
10 changes: 9 additions & 1 deletion examples/sample1/src/sampleEnvManager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { MarkdownString, LogOutputChannel, Event } from 'vscode';
import {
CreateEnvironmentOptions,
CreateEnvironmentScope,
DidChangeEnvironmentEventArgs,
DidChangeEnvironmentsEventArgs,
Expand All @@ -8,6 +9,7 @@ import {
GetEnvironmentsScope,
IconPath,
PythonEnvironment,
QuickCreateConfig,
RefreshEnvironmentsScope,
ResolveEnvironmentContext,
SetEnvironmentScope,
Expand All @@ -31,7 +33,13 @@ export class SampleEnvManager implements EnvironmentManager {
this.log = log;
}

create?(scope: CreateEnvironmentScope): Promise<PythonEnvironment | undefined> {
quickCreateConfig(): QuickCreateConfig | undefined {
// Code to provide quick create configuration goes here

throw new Error('Method not implemented.');
}

create?(scope: CreateEnvironmentScope, options?: CreateEnvironmentOptions): Promise<PythonEnvironment | undefined> {
// Code to handle creating environments goes here

throw new Error('Method not implemented.');
Expand Down
49 changes: 47 additions & 2 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,18 @@ export type DidChangeEnvironmentsEventArgs = {
*/
export type ResolveEnvironmentContext = Uri;

export interface QuickCreateConfig {
/**
* The description of the quick create step.
*/
readonly description: string;

/**
* The detail of the quick create step.
*/
readonly detail?: string;
}

/**
* Interface representing an environment manager.
*/
Expand Down Expand Up @@ -360,12 +372,19 @@ export interface EnvironmentManager {
*/
readonly log?: LogOutputChannel;

/**
* The quick create details for the environment manager. Having this method also enables the quick create feature
* for the environment manager.
*/
quickCreateConfig?(): QuickCreateConfig | undefined;

/**
* Creates a new Python environment within the specified scope.
* @param scope - The scope within which to create the environment.
* @param options - Optional parameters for creating the Python environment.
* @returns A promise that resolves to the created Python environment, or undefined if creation failed.
*/
create?(scope: CreateEnvironmentScope): Promise<PythonEnvironment | undefined>;
create?(scope: CreateEnvironmentScope, options?: CreateEnvironmentOptions): Promise<PythonEnvironment | undefined>;

/**
* Removes the specified Python environment.
Expand Down Expand Up @@ -747,6 +766,28 @@ export type PackageManagementOptions =
uninstall: string[];
};

/**
* Options for creating a Python environment.
*/
export interface CreateEnvironmentOptions {
/**
* Provides some context about quick create based on user input.
* - if true, the environment should be created without any user input or prompts.
* - if false, the environment creation can show user input or prompts.
* This also means user explicitly skipped the quick create option.
* - if undefined, the environment creation can show user input or prompts.
* You can show quick create option to the user if you support it.
*/
quickCreate?: boolean;
/**
* Packages to install in addition to the automatically picked packages as a part of creating environment.
*/
additionalPackages?: string[];
}

/**
* Object representing the process started using run in background API.
*/
export interface PythonProcess {
/**
* The process ID of the Python process.
Expand Down Expand Up @@ -807,9 +848,13 @@ export interface PythonEnvironmentManagementApi {
* Create a Python environment using environment manager associated with the scope.
*
* @param scope Where the environment is to be created.
* @param options Optional parameters for creating the Python environment.
* @returns The Python environment created. `undefined` if not created.
*/
createEnvironment(scope: CreateEnvironmentScope): Promise<PythonEnvironment | undefined>;
createEnvironment(
scope: CreateEnvironmentScope,
options?: CreateEnvironmentOptions,
): Promise<PythonEnvironment | undefined>;

/**
* Remove a Python environment.
Expand Down
4 changes: 4 additions & 0 deletions src/common/localize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export namespace Common {
export const viewLogs = l10n.t('View Logs');
export const yes = l10n.t('Yes');
export const no = l10n.t('No');
export const quickCreate = l10n.t('Quick Create');
}

export namespace Interpreter {
Expand Down Expand Up @@ -134,6 +135,9 @@ export namespace CondaStrings {
export const condaCreateFailed = l10n.t('Failed to create conda environment');
export const condaRemoveFailed = l10n.t('Failed to remove conda environment');
export const condaExists = l10n.t('Environment already exists');

export const quickCreateCondaNoEnvRoot = l10n.t('No conda environment root found');
export const quickCreateCondaNoName = l10n.t('Could not generate a name for env');
}

export namespace ProjectCreatorString {
Expand Down
5 changes: 4 additions & 1 deletion src/common/pickers/environments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ async function createEnvironment(
const manager = managers.find((m) => m.id === managerId);
if (manager) {
try {
const env = await manager.create(options.projects.map((p) => p.uri));
const env = await manager.create(
options.projects.map((p) => p.uri),
undefined,
);
return env;
} catch (ex) {
if (ex === QuickInputButtons.Back) {
Expand Down
41 changes: 33 additions & 8 deletions src/common/pickers/managers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ import { InternalEnvironmentManager, InternalPackageManager } from '../../intern
import { Common, Pickers } from '../localize';
import { showQuickPickWithButtons, showQuickPick } from '../window.apis';

function getDescription(mgr: InternalEnvironmentManager | InternalPackageManager): string | undefined {
if (mgr.description) {
return mgr.description;
}
if (mgr.tooltip) {
const tooltip = mgr.tooltip;
if (typeof tooltip === 'string') {
return tooltip;
}
return tooltip.value;
}
return undefined;
}

export async function pickEnvironmentManager(
managers: InternalEnvironmentManager[],
defaultManagers?: InternalEnvironmentManager[],
Expand All @@ -18,14 +32,25 @@ export async function pickEnvironmentManager(

const items: (QuickPickItem | (QuickPickItem & { id: string }))[] = [];
if (defaultManagers && defaultManagers.length > 0) {
items.push({
label: Common.recommended,
kind: QuickPickItemKind.Separator,
});
if (defaultManagers.length === 1 && defaultManagers[0].supportsQuickCreate) {
const details = defaultManagers[0].quickCreateConfig();
if (details) {
items.push({
label: Common.quickCreate,
description: details.description,
detail: details.detail,
id: `QuickCreate#${defaultManagers[0].id}`,
});
}
}
items.push(
{
label: Common.recommended,
kind: QuickPickItemKind.Separator,
},
...defaultManagers.map((defaultMgr) => ({
label: defaultMgr.displayName,
description: defaultMgr.description,
description: getDescription(defaultMgr),
id: defaultMgr.id,
})),
{
Expand All @@ -39,7 +64,7 @@ export async function pickEnvironmentManager(
.filter((m) => !defaultManagers?.includes(m))
.map((m) => ({
label: m.displayName,
description: m.description,
description: getDescription(m),
id: m.id,
})),
);
Expand Down Expand Up @@ -71,7 +96,7 @@ export async function pickPackageManager(
},
...defaultManagers.map((defaultMgr) => ({
label: defaultMgr.displayName,
description: defaultMgr.description,
description: getDescription(defaultMgr),
id: defaultMgr.id,
})),
{
Expand All @@ -85,7 +110,7 @@ export async function pickPackageManager(
.filter((m) => !defaultManagers?.includes(m))
.map((m) => ({
label: m.displayName,
description: m.description,
description: getDescription(m),
id: m.id,
})),
);
Expand Down
Loading