Skip to content

Commit f34f14c

Browse files
authored
switch new project add to create method (#336)
- renamed `addPythonProject` in src/features/envCommands.ts to `addPythonProjectCommand` (as it is only a command entry point) - moved responsibility so ProjectCreators are responsible for adding their created projects to the ProjectManager list - updated `addPythonProjectCommand` so it calls the selected ProjectCreator create method OR (if the resource param already a ProjectItem) just add it to the ProjectManager list
1 parent c24c4d1 commit f34f14c

File tree

6 files changed

+98
-118
lines changed

6 files changed

+98
-118
lines changed

src/extension.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { AutoFindProjects } from './features/creators/autoFindProjects';
2222
import { ExistingProjects } from './features/creators/existingProjects';
2323
import { ProjectCreatorsImpl } from './features/creators/projectCreators';
2424
import {
25-
addPythonProject,
25+
addPythonProjectCommand,
2626
copyPathToClipboard,
2727
createAnyEnvironmentCommand,
2828
createEnvironmentCommand,
@@ -187,7 +187,7 @@ export async function activate(context: ExtensionContext): Promise<PythonEnviron
187187
await setPackageManagerCommand(envManagers, projectManager);
188188
}),
189189
commands.registerCommand('python-envs.addPythonProject', async (resource) => {
190-
await addPythonProject(resource, projectManager, envManagers, projectCreators);
190+
await addPythonProjectCommand(resource, projectManager, envManagers, projectCreators);
191191
}),
192192
commands.registerCommand('python-envs.removePythonProject', async (item) => {
193193
await resetEnvironmentCommand(item, envManagers, projectManager);

src/features/creators/autoFindProjects.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -90,16 +90,19 @@ export class AutoFindProjects implements PythonProjectCreator {
9090

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

93-
const projects = await pickProjects(filtered);
94-
if (!projects || projects.length === 0) {
93+
const projectUris = await pickProjects(filtered);
94+
if (!projectUris || projectUris.length === 0) {
9595
// User cancelled the selection.
9696
traceInfo('User cancelled project selection.');
9797
return;
9898
}
9999

100-
return projects.map((uri) => ({
100+
const projects = projectUris.map((uri) => ({
101101
name: path.basename(uri.fsPath),
102102
uri,
103-
}));
103+
})) as PythonProject[];
104+
// Add the projects to the project manager
105+
this.pm.add(projects);
106+
return projects;
104107
}
105108
}

src/features/creators/existingProjects.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,13 @@ export class ExistingProjects implements PythonProjectCreator {
9090
}
9191
return;
9292
} else {
93-
return resultsInWorkspace.map((uri) => ({
93+
const projects = resultsInWorkspace.map((uri) => ({
9494
name: path.basename(uri.fsPath),
9595
uri,
9696
})) as PythonProject[];
97+
// Add the projects to the project manager
98+
this.pm.add(projects);
99+
return projects;
97100
}
98101
}
99102
}

src/features/envCommands.ts

+66-108
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,43 @@
11
import { QuickInputButtons, TaskExecution, TaskRevealKind, Terminal, Uri } from 'vscode';
2-
import {
3-
EnvironmentManagers,
4-
InternalEnvironmentManager,
5-
InternalPackageManager,
6-
ProjectCreators,
7-
PythonProjectManager,
8-
} from '../internal.api';
9-
import { traceError, traceInfo, traceVerbose } from '../common/logging';
102
import {
113
CreateEnvironmentOptions,
124
PythonEnvironment,
135
PythonEnvironmentApi,
14-
PythonProject,
156
PythonProjectCreator,
7+
PythonProjectCreatorOptions,
168
} from '../api';
17-
import * as path from 'path';
9+
import { traceError, traceInfo, traceVerbose } from '../common/logging';
1810
import {
19-
setEnvironmentManager,
20-
setPackageManager,
21-
addPythonProjectSetting,
22-
removePythonProjectSetting,
23-
getDefaultEnvManagerSetting,
24-
getDefaultPkgManagerSetting,
25-
EditProjectSettings,
26-
} from './settings/settingHelpers';
27-
28-
import { getAbsolutePath } from '../common/utils/fileNameUtils';
11+
EnvironmentManagers,
12+
InternalEnvironmentManager,
13+
InternalPackageManager,
14+
ProjectCreators,
15+
PythonProjectManager,
16+
} from '../internal.api';
17+
import { removePythonProjectSetting, setEnvironmentManager, setPackageManager } from './settings/settingHelpers';
18+
19+
import { clipboardWriteText } from '../common/env.apis';
20+
import {} from '../common/errors/utils';
21+
import { pickEnvironment } from '../common/pickers/environments';
22+
import { pickCreator, pickEnvironmentManager, pickPackageManager } from '../common/pickers/managers';
23+
import { pickProject, pickProjectMany } from '../common/pickers/projects';
24+
import { activeTextEditor, showErrorMessage } from '../common/window.apis';
25+
import { quoteArgs } from './execution/execUtils';
2926
import { runAsTask } from './execution/runAsTask';
27+
import { runInTerminal } from './terminal/runInTerminal';
28+
import { TerminalManager } from './terminal/terminalManager';
3029
import {
3130
EnvManagerTreeItem,
32-
PackageRootTreeItem,
33-
PythonEnvTreeItem,
34-
ProjectItem,
35-
ProjectEnvironment,
36-
ProjectPackageRootTreeItem,
37-
GlobalProjectItem,
3831
EnvTreeItemKind,
32+
GlobalProjectItem,
33+
PackageRootTreeItem,
3934
PackageTreeItem,
35+
ProjectEnvironment,
36+
ProjectItem,
4037
ProjectPackage,
38+
ProjectPackageRootTreeItem,
39+
PythonEnvTreeItem,
4140
} from './views/treeViewItems';
42-
import { pickEnvironment } from '../common/pickers/environments';
43-
import { pickEnvironmentManager, pickPackageManager, pickCreator } from '../common/pickers/managers';
44-
import { pickProject, pickProjectMany } from '../common/pickers/projects';
45-
import { TerminalManager } from './terminal/terminalManager';
46-
import { runInTerminal } from './terminal/runInTerminal';
47-
import { quoteArgs } from './execution/execUtils';
48-
import {} from '../common/errors/utils';
49-
import { activeTextEditor, showErrorMessage } from '../common/window.apis';
50-
import { clipboardWriteText } from '../common/env.apis';
5141

5242
export async function refreshManagerCommand(context: unknown): Promise<void> {
5343
if (context instanceof EnvManagerTreeItem) {
@@ -338,93 +328,61 @@ export async function setPackageManagerCommand(em: EnvironmentManagers, wm: Pyth
338328
}
339329
}
340330

341-
export async function addPythonProject(
331+
/**
332+
* Creates a new Python project using a selected PythonProjectCreator.
333+
*
334+
* This function calls create on the selected creator and handles the creation process. Will return
335+
* without doing anything if the resource is a ProjectItem, as the project is already created.
336+
*
337+
* @param resource - The resource to use for project creation (can be a Uri(s), ProjectItem(s), or undefined).
338+
* @param wm - The PythonProjectManager instance for managing projects.
339+
* @param em - The EnvironmentManagers instance for managing environments.
340+
* @param pc - The ProjectCreators instance for accessing available project creators.
341+
* @returns A promise that resolves when the project has been created, or void if cancelled or invalid.
342+
*/
343+
export async function addPythonProjectCommand(
342344
resource: unknown,
343345
wm: PythonProjectManager,
344346
em: EnvironmentManagers,
345347
pc: ProjectCreators,
346-
): Promise<PythonProject | PythonProject[] | undefined> {
348+
): Promise<void> {
347349
if (wm.getProjects().length === 0) {
348350
showErrorMessage('Please open a folder/project before adding a workspace');
349351
return;
350352
}
351-
352-
if (resource instanceof Uri) {
353-
const uri = resource as Uri;
354-
const envManagerId = getDefaultEnvManagerSetting(wm, uri);
355-
const pkgManagerId = getDefaultPkgManagerSetting(
356-
wm,
357-
uri,
358-
em.getEnvironmentManager(envManagerId)?.preferredPackageManagerId,
359-
);
360-
const pw = wm.create(path.basename(uri.fsPath), uri);
361-
await addPythonProjectSetting([{ project: pw, envManager: envManagerId, packageManager: pkgManagerId }]);
362-
return pw;
363-
}
364-
365-
if (resource === undefined || resource instanceof ProjectItem) {
366-
const creator: PythonProjectCreator | undefined = await pickCreator(pc.getProjectCreators());
367-
if (!creator) {
353+
if (resource instanceof Array) {
354+
for (const r of resource) {
355+
await addPythonProjectCommand(r, wm, em, pc);
368356
return;
369357
}
358+
}
359+
if (resource instanceof ProjectItem) {
360+
// If the context is a ProjectItem, project is already created. Just add it to the package manager project list.
361+
wm.add(resource.project);
362+
return;
363+
}
364+
let options: PythonProjectCreatorOptions | undefined;
370365

371-
let results: PythonProject | PythonProject[] | Uri | Uri[] | undefined;
372-
try {
373-
results = await creator.create();
374-
if (results === undefined) {
375-
return;
376-
}
377-
} catch (ex) {
378-
if (ex === QuickInputButtons.Back) {
379-
return addPythonProject(resource, wm, em, pc);
380-
}
381-
throw ex;
382-
}
383-
384-
if (
385-
results instanceof Uri ||
386-
(Array.isArray(results) && results.length > 0 && results.every((r) => r instanceof Uri))
387-
) {
388-
// the results are Uris, which means they aren't projects and shouldn't be added
389-
return;
390-
}
391-
results = results as PythonProject | PythonProject[];
392-
393-
if (!Array.isArray(results)) {
394-
results = [results];
395-
}
396-
397-
if (Array.isArray(results)) {
398-
if (results.length === 0) {
399-
return;
400-
}
401-
}
402-
403-
const projects: PythonProject[] = [];
404-
const edits: EditProjectSettings[] = [];
366+
if (resource instanceof Uri) {
367+
// Use resource as the URI for the project if it is a URI.
368+
options = {
369+
name: resource.fsPath,
370+
rootUri: resource,
371+
};
372+
}
405373

406-
for (const result of results) {
407-
const uri = await getAbsolutePath(result.uri.fsPath);
408-
if (!uri) {
409-
traceError(`Path does not belong to any opened workspace: ${result.uri.fsPath}`);
410-
continue;
411-
}
374+
const creator: PythonProjectCreator | undefined = await pickCreator(pc.getProjectCreators());
375+
if (!creator) {
376+
return;
377+
}
412378

413-
const envManagerId = getDefaultEnvManagerSetting(wm, uri);
414-
const pkgManagerId = getDefaultPkgManagerSetting(
415-
wm,
416-
uri,
417-
em.getEnvironmentManager(envManagerId)?.preferredPackageManagerId,
418-
);
419-
const pw = wm.create(path.basename(uri.fsPath), uri);
420-
projects.push(pw);
421-
edits.push({ project: pw, envManager: envManagerId, packageManager: pkgManagerId });
379+
try {
380+
await creator.create(options);
381+
} catch (ex) {
382+
if (ex === QuickInputButtons.Back) {
383+
return addPythonProjectCommand(resource, wm, em, pc);
422384
}
423-
await addPythonProjectSetting(edits);
424-
return projects;
425-
} else {
426-
// If the context is not a Uri or ProjectItem, rerun function with undefined context
427-
await addPythonProject(undefined, wm, em, pc);
385+
throw ex;
428386
}
429387
}
430388

src/features/projectManager.ts

+18-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ import {
99
onDidChangeWorkspaceFolders,
1010
} from '../common/workspace.apis';
1111
import { createSimpleDebounce } from '../common/utils/debounce';
12+
import {
13+
addPythonProjectSetting,
14+
EditProjectSettings,
15+
getDefaultEnvManagerSetting,
16+
getDefaultPkgManagerSetting,
17+
} from './settings/settingHelpers';
1218

1319
type ProjectArray = PythonProject[];
1420

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

95-
add(projects: PythonProject | ProjectArray): void {
101+
async add(projects: PythonProject | ProjectArray): Promise<void> {
96102
const _projects = Array.isArray(projects) ? projects : [projects];
97103
if (_projects.length === 0) {
98104
return;
99105
}
106+
const edits: EditProjectSettings[] = [];
107+
108+
const envManagerId = getDefaultEnvManagerSetting(this);
109+
const pkgManagerId = getDefaultPkgManagerSetting(this);
100110

101-
_projects.forEach((w) => this._projects.set(w.uri.toString(), w));
111+
_projects.forEach((w) => {
112+
edits.push({ project: w, envManager: envManagerId, packageManager: pkgManagerId });
113+
return this._projects.set(w.uri.toString(), w);
114+
});
102115
this._onDidChangeProjects.fire(Array.from(this._projects.values()));
116+
117+
// handle bulk edits to avoid multiple calls to the setting
118+
await addPythonProjectSetting(edits);
103119
}
104120

105121
remove(projects: PythonProject | ProjectArray): void {

src/internal.api.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ export interface PythonProjectManager extends Disposable {
284284
uri: Uri,
285285
options?: { description?: string; tooltip?: string | MarkdownString; iconPath?: IconPath },
286286
): PythonProject;
287-
add(pyWorkspace: PythonProject | PythonProject[]): void;
287+
add(pyWorkspace: PythonProject | PythonProject[]): Promise<void>;
288288
remove(pyWorkspace: PythonProject | PythonProject[]): void;
289289
getProjects(uris?: Uri[]): ReadonlyArray<PythonProject>;
290290
get(uri: Uri): PythonProject | undefined;

0 commit comments

Comments
 (0)