Skip to content

switch new project add to create method #336

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
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
4 changes: 2 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { AutoFindProjects } from './features/creators/autoFindProjects';
import { ExistingProjects } from './features/creators/existingProjects';
import { ProjectCreatorsImpl } from './features/creators/projectCreators';
import {
addPythonProject,
addPythonProjectCommand,
copyPathToClipboard,
createAnyEnvironmentCommand,
createEnvironmentCommand,
Expand Down Expand Up @@ -185,7 +185,7 @@ export async function activate(context: ExtensionContext): Promise<PythonEnviron
await setPackageManagerCommand(envManagers, projectManager);
}),
commands.registerCommand('python-envs.addPythonProject', async (resource) => {
await addPythonProject(resource, projectManager, envManagers, projectCreators);
await addPythonProjectCommand(resource, projectManager, envManagers, projectCreators);
}),
commands.registerCommand('python-envs.removePythonProject', async (item) => {
await resetEnvironmentCommand(item, envManagers, projectManager);
Expand Down
11 changes: 7 additions & 4 deletions src/features/creators/autoFindProjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,19 @@ export class AutoFindProjects implements PythonProjectCreator {

traceInfo(`Found ${filtered.length} new potential projects that aren't already registered`);

const projects = await pickProjects(filtered);
if (!projects || projects.length === 0) {
const projectUris = await pickProjects(filtered);
if (!projectUris || projectUris.length === 0) {
// User cancelled the selection.
traceInfo('User cancelled project selection.');
return;
}

return projects.map((uri) => ({
const projects = projectUris.map((uri) => ({
name: path.basename(uri.fsPath),
uri,
}));
})) as PythonProject[];
// Add the projects to the project manager
this.pm.add(projects);
return projects;
}
}
5 changes: 4 additions & 1 deletion src/features/creators/existingProjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,13 @@ export class ExistingProjects implements PythonProjectCreator {
}
return;
} else {
return resultsInWorkspace.map((uri) => ({
const projects = resultsInWorkspace.map((uri) => ({
name: path.basename(uri.fsPath),
uri,
})) as PythonProject[];
// Add the projects to the project manager
this.pm.add(projects);
return projects;
}
}
}
174 changes: 66 additions & 108 deletions src/features/envCommands.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,43 @@
import { QuickInputButtons, TaskExecution, TaskRevealKind, Terminal, Uri } from 'vscode';
import {
EnvironmentManagers,
InternalEnvironmentManager,
InternalPackageManager,
ProjectCreators,
PythonProjectManager,
} from '../internal.api';
import { traceError, traceInfo, traceVerbose } from '../common/logging';
import {
CreateEnvironmentOptions,
PythonEnvironment,
PythonEnvironmentApi,
PythonProject,
PythonProjectCreator,
PythonProjectCreatorOptions,
} from '../api';
import * as path from 'path';
import { traceError, traceInfo, traceVerbose } from '../common/logging';
import {
setEnvironmentManager,
setPackageManager,
addPythonProjectSetting,
removePythonProjectSetting,
getDefaultEnvManagerSetting,
getDefaultPkgManagerSetting,
EditProjectSettings,
} from './settings/settingHelpers';

import { getAbsolutePath } from '../common/utils/fileNameUtils';
EnvironmentManagers,
InternalEnvironmentManager,
InternalPackageManager,
ProjectCreators,
PythonProjectManager,
} from '../internal.api';
import { removePythonProjectSetting, setEnvironmentManager, setPackageManager } from './settings/settingHelpers';

import { clipboardWriteText } from '../common/env.apis';
import {} from '../common/errors/utils';
import { pickEnvironment } from '../common/pickers/environments';
import { pickCreator, pickEnvironmentManager, pickPackageManager } from '../common/pickers/managers';
import { pickProject, pickProjectMany } from '../common/pickers/projects';
import { activeTextEditor, showErrorMessage } from '../common/window.apis';
import { quoteArgs } from './execution/execUtils';
import { runAsTask } from './execution/runAsTask';
import { runInTerminal } from './terminal/runInTerminal';
import { TerminalManager } from './terminal/terminalManager';
import {
EnvManagerTreeItem,
PackageRootTreeItem,
PythonEnvTreeItem,
ProjectItem,
ProjectEnvironment,
ProjectPackageRootTreeItem,
GlobalProjectItem,
EnvTreeItemKind,
GlobalProjectItem,
PackageRootTreeItem,
PackageTreeItem,
ProjectEnvironment,
ProjectItem,
ProjectPackage,
ProjectPackageRootTreeItem,
PythonEnvTreeItem,
} from './views/treeViewItems';
import { pickEnvironment } from '../common/pickers/environments';
import { pickEnvironmentManager, pickPackageManager, pickCreator } from '../common/pickers/managers';
import { pickProject, pickProjectMany } from '../common/pickers/projects';
import { TerminalManager } from './terminal/terminalManager';
import { runInTerminal } from './terminal/runInTerminal';
import { quoteArgs } from './execution/execUtils';
import {} from '../common/errors/utils';
import { activeTextEditor, showErrorMessage } from '../common/window.apis';
import { clipboardWriteText } from '../common/env.apis';

export async function refreshManagerCommand(context: unknown): Promise<void> {
if (context instanceof EnvManagerTreeItem) {
Expand Down Expand Up @@ -338,93 +328,61 @@ export async function setPackageManagerCommand(em: EnvironmentManagers, wm: Pyth
}
}

export async function addPythonProject(
/**
* Creates a new Python project using a selected PythonProjectCreator.
*
* This function calls create on the selected creator and handles the creation process. Will return
* without doing anything if the resource is a ProjectItem, as the project is already created.
*
* @param resource - The resource to use for project creation (can be a Uri(s), ProjectItem(s), or undefined).
* @param wm - The PythonProjectManager instance for managing projects.
* @param em - The EnvironmentManagers instance for managing environments.
* @param pc - The ProjectCreators instance for accessing available project creators.
* @returns A promise that resolves when the project has been created, or void if cancelled or invalid.
*/
export async function addPythonProjectCommand(
resource: unknown,
wm: PythonProjectManager,
em: EnvironmentManagers,
pc: ProjectCreators,
): Promise<PythonProject | PythonProject[] | undefined> {
): Promise<void> {
if (wm.getProjects().length === 0) {
showErrorMessage('Please open a folder/project before adding a workspace');
return;
}

if (resource instanceof Uri) {
const uri = resource as Uri;
const envManagerId = getDefaultEnvManagerSetting(wm, uri);
const pkgManagerId = getDefaultPkgManagerSetting(
wm,
uri,
em.getEnvironmentManager(envManagerId)?.preferredPackageManagerId,
);
const pw = wm.create(path.basename(uri.fsPath), uri);
await addPythonProjectSetting([{ project: pw, envManager: envManagerId, packageManager: pkgManagerId }]);
return pw;
}

if (resource === undefined || resource instanceof ProjectItem) {
const creator: PythonProjectCreator | undefined = await pickCreator(pc.getProjectCreators());
if (!creator) {
if (resource instanceof Array) {
for (const r of resource) {
await addPythonProjectCommand(r, wm, em, pc);
return;
}
}
if (resource instanceof ProjectItem) {
// If the context is a ProjectItem, project is already created. Just add it to the package manager project list.
wm.add(resource.project);
return;
}
let options: PythonProjectCreatorOptions | undefined;

let results: PythonProject | PythonProject[] | Uri | Uri[] | undefined;
try {
results = await creator.create();
if (results === undefined) {
return;
}
} catch (ex) {
if (ex === QuickInputButtons.Back) {
return addPythonProject(resource, wm, em, pc);
}
throw ex;
}

if (
results instanceof Uri ||
(Array.isArray(results) && results.length > 0 && results.every((r) => r instanceof Uri))
) {
// the results are Uris, which means they aren't projects and shouldn't be added
return;
}
results = results as PythonProject | PythonProject[];

if (!Array.isArray(results)) {
results = [results];
}

if (Array.isArray(results)) {
if (results.length === 0) {
return;
}
}

const projects: PythonProject[] = [];
const edits: EditProjectSettings[] = [];
if (resource instanceof Uri) {
// Use resource as the URI for the project if it is a URI.
options = {
name: resource.fsPath,
rootUri: resource,
};
}

for (const result of results) {
const uri = await getAbsolutePath(result.uri.fsPath);
if (!uri) {
traceError(`Path does not belong to any opened workspace: ${result.uri.fsPath}`);
continue;
}
const creator: PythonProjectCreator | undefined = await pickCreator(pc.getProjectCreators());
if (!creator) {
return;
}

const envManagerId = getDefaultEnvManagerSetting(wm, uri);
const pkgManagerId = getDefaultPkgManagerSetting(
wm,
uri,
em.getEnvironmentManager(envManagerId)?.preferredPackageManagerId,
);
const pw = wm.create(path.basename(uri.fsPath), uri);
projects.push(pw);
edits.push({ project: pw, envManager: envManagerId, packageManager: pkgManagerId });
try {
await creator.create(options);
} catch (ex) {
if (ex === QuickInputButtons.Back) {
return addPythonProjectCommand(resource, wm, em, pc);
}
await addPythonProjectSetting(edits);
return projects;
} else {
// If the context is not a Uri or ProjectItem, rerun function with undefined context
await addPythonProject(undefined, wm, em, pc);
throw ex;
}
}

Expand Down
20 changes: 18 additions & 2 deletions src/features/projectManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ import {
onDidChangeWorkspaceFolders,
} from '../common/workspace.apis';
import { createSimpleDebounce } from '../common/utils/debounce';
import {
addPythonProjectSetting,
EditProjectSettings,
getDefaultEnvManagerSetting,
getDefaultPkgManagerSetting,
} from './settings/settingHelpers';

type ProjectArray = PythonProject[];

Expand Down Expand Up @@ -92,14 +98,24 @@ export class PythonProjectManagerImpl implements PythonProjectManager {
return new PythonProjectsImpl(name, uri, options);
}

add(projects: PythonProject | ProjectArray): void {
async add(projects: PythonProject | ProjectArray): Promise<void> {
const _projects = Array.isArray(projects) ? projects : [projects];
if (_projects.length === 0) {
return;
}
const edits: EditProjectSettings[] = [];

const envManagerId = getDefaultEnvManagerSetting(this);
const pkgManagerId = getDefaultPkgManagerSetting(this);

_projects.forEach((w) => this._projects.set(w.uri.toString(), w));
_projects.forEach((w) => {
edits.push({ project: w, envManager: envManagerId, packageManager: pkgManagerId });
return this._projects.set(w.uri.toString(), w);
});
this._onDidChangeProjects.fire(Array.from(this._projects.values()));

// handle bulk edits to avoid multiple calls to the setting
await addPythonProjectSetting(edits);
}

remove(projects: PythonProject | ProjectArray): void {
Expand Down
2 changes: 1 addition & 1 deletion src/internal.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ export interface PythonProjectManager extends Disposable {
uri: Uri,
options?: { description?: string; tooltip?: string | MarkdownString; iconPath?: IconPath },
): PythonProject;
add(pyWorkspace: PythonProject | PythonProject[]): void;
add(pyWorkspace: PythonProject | PythonProject[]): Promise<void>;
remove(pyWorkspace: PythonProject | PythonProject[]): void;
getProjects(uris?: Uri[]): ReadonlyArray<PythonProject>;
get(uri: Uri): PythonProject | undefined;
Expand Down