Skip to content

Commit e19d9d3

Browse files
authored
Bug fixes and API tweaks (#25)
Fixes #26
1 parent 34d9328 commit e19d9d3

File tree

12 files changed

+340
-203
lines changed

12 files changed

+340
-203
lines changed

src/api.ts

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
1-
import { Uri, Disposable, MarkdownString, Event, LogOutputChannel, ThemeIcon, Terminal, TaskExecution } from 'vscode';
1+
import {
2+
Uri,
3+
Disposable,
4+
MarkdownString,
5+
Event,
6+
LogOutputChannel,
7+
ThemeIcon,
8+
Terminal,
9+
TaskExecution,
10+
TerminalOptions,
11+
} from 'vscode';
212

313
/**
414
* The path to an icon, or a theme-specific configuration of icons.
@@ -954,7 +964,7 @@ export interface PythonPackageManagementApi {
954964
* @param packages The packages to install.
955965
* @param options Options for installing packages.
956966
*/
957-
installPackages(environment: PythonEnvironment, packages: string[], options: PackageInstallOptions): Promise<void>;
967+
installPackages(environment: PythonEnvironment, packages: string[], options?: PackageInstallOptions): Promise<void>;
958968

959969
/**
960970
* Uninstall packages from a Python Environment.
@@ -1027,25 +1037,27 @@ export interface PythonProjectModifyApi {
10271037
*/
10281038
export interface PythonProjectApi extends PythonProjectCreationApi, PythonProjectGetterApi, PythonProjectModifyApi {}
10291039

1040+
export interface PythonTerminalOptions extends TerminalOptions {
1041+
/**
1042+
* Whether to show the terminal.
1043+
*/
1044+
disableActivation?: boolean;
1045+
}
1046+
10301047
export interface PythonTerminalCreateApi {
1031-
createTerminal(
1032-
environment: PythonEnvironment,
1033-
cwd: string | Uri,
1034-
envVars?: { [key: string]: string },
1035-
): Promise<Terminal>;
1048+
createTerminal(environment: PythonEnvironment, options: PythonTerminalOptions): Promise<Terminal>;
10361049
}
10371050

10381051
export interface PythonTerminalExecutionOptions {
10391052
cwd: string | Uri;
10401053
args?: string[];
1041-
10421054
show?: boolean;
10431055
}
10441056

10451057
export interface PythonTerminalRunApi {
10461058
runInTerminal(environment: PythonEnvironment, options: PythonTerminalExecutionOptions): Promise<Terminal>;
10471059
runInDedicatedTerminal(
1048-
terminalKey: Uri,
1060+
terminalKey: Uri | string,
10491061
environment: PythonEnvironment,
10501062
options: PythonTerminalExecutionOptions,
10511063
): Promise<Terminal>;
@@ -1082,7 +1094,7 @@ export interface PythonTaskRunApi {
10821094
export interface PythonBackgroundRunOptions {
10831095
args: string[];
10841096
cwd?: string;
1085-
env?: { [key: string]: string };
1097+
env?: { [key: string]: string | undefined };
10861098
}
10871099
export interface PythonBackgroundRunApi {
10881100
runInBackground(environment: PythonEnvironment, options: PythonBackgroundRunOptions): Promise<PythonProcess>;

src/common/pickers/projects.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import path from 'path';
22
import { QuickPickItem } from 'vscode';
33
import { PythonProject } from '../../api';
4-
import { showQuickPick } from '../window.apis';
4+
import { showQuickPick, showQuickPickWithButtons } from '../window.apis';
55

66
interface ProjectQuickPickItem extends QuickPickItem {
77
project: PythonProject;
@@ -27,17 +27,21 @@ export async function pickProject(projects: ReadonlyArray<PythonProject>): Promi
2727
return undefined;
2828
}
2929

30-
export async function pickProjectMany(projects: ReadonlyArray<PythonProject>): Promise<PythonProject[] | undefined> {
30+
export async function pickProjectMany(
31+
projects: readonly PythonProject[],
32+
showBackButton?: boolean,
33+
): Promise<PythonProject[] | undefined> {
3134
if (projects.length > 1) {
3235
const items: ProjectQuickPickItem[] = projects.map((pw) => ({
3336
label: path.basename(pw.uri.fsPath),
3437
description: pw.uri.fsPath,
3538
project: pw,
3639
}));
37-
const item = await showQuickPick(items, {
40+
const item = await showQuickPickWithButtons(items, {
3841
placeHolder: 'Select a project, folder or script',
3942
ignoreFocusOut: true,
4043
canPickMany: true,
44+
showBackButton: showBackButton,
4145
});
4246
if (Array.isArray(item)) {
4347
return item.map((p) => p.project);

src/extension.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { commands, ExtensionContext, LogOutputChannel } from 'vscode';
22

33
import { PythonEnvironmentManagers } from './features/envManagers';
4-
import { registerLogger } from './common/logging';
4+
import { registerLogger, traceInfo } from './common/logging';
55
import { EnvManagerView } from './features/views/envManagersView';
66
import {
77
addPythonProject,
@@ -120,18 +120,10 @@ export async function activate(context: ExtensionContext): Promise<PythonEnviron
120120
await handlePackagesCommand(packageManager, environment);
121121
}),
122122
commands.registerCommand('python-envs.set', async (item) => {
123-
const result = await setEnvironmentCommand(item, envManagers, projectManager);
124-
if (result) {
125-
workspaceView.updateProject();
126-
await updateActivateMenuButtonContext(terminalManager, projectManager, envManagers);
127-
}
123+
await setEnvironmentCommand(item, envManagers, projectManager);
128124
}),
129125
commands.registerCommand('python-envs.setEnv', async (item) => {
130-
const result = await setEnvironmentCommand(item, envManagers, projectManager);
131-
if (result) {
132-
workspaceView.updateProject();
133-
await updateActivateMenuButtonContext(terminalManager, projectManager, envManagers);
134-
}
126+
await setEnvironmentCommand(item, envManagers, projectManager);
135127
}),
136128
commands.registerCommand('python-envs.reset', async (item) => {
137129
await resetEnvironmentCommand(item, envManagers, projectManager);
@@ -194,9 +186,19 @@ export async function activate(context: ExtensionContext): Promise<PythonEnviron
194186
updateViewsAndStatus(statusBar, workspaceView, managerView, api);
195187
}),
196188
envManagers.onDidChangeEnvironment(async () => {
189+
await updateActivateMenuButtonContext(terminalManager, projectManager, envManagers);
197190
updateViewsAndStatus(statusBar, workspaceView, managerView, api);
198191
}),
199192
envManagers.onDidChangeEnvironments(async () => {
193+
await updateActivateMenuButtonContext(terminalManager, projectManager, envManagers);
194+
updateViewsAndStatus(statusBar, workspaceView, managerView, api);
195+
}),
196+
envManagers.onDidChangeEnvironmentFiltered(async (e) => {
197+
const location = e.uri?.fsPath ?? 'global';
198+
traceInfo(
199+
`Internal: Changed environment from ${e.old?.displayName} to ${e.new?.displayName} for: ${location}`,
200+
);
201+
await updateActivateMenuButtonContext(terminalManager, projectManager, envManagers);
200202
updateViewsAndStatus(statusBar, workspaceView, managerView, api);
201203
}),
202204
);

src/features/envCommands.ts

Lines changed: 47 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ import {
1717
getDefaultEnvManagerSetting,
1818
getDefaultPkgManagerSetting,
1919
EditProjectSettings,
20-
setAllManagerSettings,
21-
EditAllManagerSettings,
2220
} from './settings/settingHelpers';
2321

2422
import { getAbsolutePath } from '../common/utils/fileNameUtils';
@@ -168,95 +166,62 @@ export async function handlePackagesCommand(
168166
}
169167
}
170168

171-
export interface EnvironmentSetResult {
172-
project?: PythonProject;
173-
environment: PythonEnvironment;
174-
}
175-
176169
export async function setEnvironmentCommand(
177170
context: unknown,
178171
em: EnvironmentManagers,
179172
wm: PythonProjectManager,
180-
): Promise<EnvironmentSetResult[] | undefined> {
173+
): Promise<void> {
181174
if (context instanceof PythonEnvTreeItem) {
182-
const view = context as PythonEnvTreeItem;
183-
const manager = view.parent.manager;
184-
const projects = await pickProjectMany(wm.getProjects());
185-
if (projects && projects.length > 0) {
186-
await Promise.all(projects.map((p) => manager.set(p.uri, view.environment)));
187-
await setAllManagerSettings(
188-
projects.map((p) => ({
189-
project: p,
190-
envManager: manager.id,
191-
packageManager: manager.preferredPackageManagerId,
192-
})),
193-
);
194-
return projects.map((p) => ({ project: p, environment: view.environment }));
175+
try {
176+
const view = context as PythonEnvTreeItem;
177+
const projects = await pickProjectMany(wm.getProjects());
178+
if (projects && projects.length > 0) {
179+
const uris = projects.map((p) => p.uri);
180+
await em.setEnvironments(uris, view.environment);
181+
}
182+
} catch (ex) {
183+
if (ex === QuickInputButtons.Back) {
184+
await setEnvironmentCommand(context, em, wm);
185+
}
186+
throw ex;
195187
}
196-
return;
197188
} else if (context instanceof ProjectItem) {
198189
const view = context as ProjectItem;
199-
return setEnvironmentCommand([view.project.uri], em, wm);
190+
await setEnvironmentCommand([view.project.uri], em, wm);
200191
} else if (context instanceof Uri) {
201-
return setEnvironmentCommand([context], em, wm);
192+
await setEnvironmentCommand([context], em, wm);
202193
} else if (context === undefined) {
203-
const project = await pickProjectMany(wm.getProjects());
204-
if (project && project.length > 0) {
205-
try {
206-
const result = setEnvironmentCommand(project, em, wm);
207-
return result;
208-
} catch (ex) {
209-
if (ex === QuickInputButtons.Back) {
210-
return setEnvironmentCommand(context, em, wm);
211-
}
194+
try {
195+
const projects = await pickProjectMany(wm.getProjects());
196+
if (projects && projects.length > 0) {
197+
const uris = projects.map((p) => p.uri);
198+
await setEnvironmentCommand(uris, em, wm);
199+
}
200+
} catch (ex) {
201+
if (ex === QuickInputButtons.Back) {
202+
await setEnvironmentCommand(context, em, wm);
212203
}
204+
throw ex;
213205
}
214-
return;
215206
} else if (Array.isArray(context) && context.length > 0 && context.every((c) => c instanceof Uri)) {
216207
const uris = context as Uri[];
217-
const projects: PythonProject[] = [];
218-
const projectEnvManagers: InternalEnvironmentManager[] = [];
219-
uris.forEach((uri) => {
220-
const project = wm.get(uri);
221-
if (project) {
222-
projects.push(project);
223-
const manager = em.getEnvironmentManager(uri);
224-
if (manager && !projectEnvManagers.includes(manager)) {
225-
projectEnvManagers.push(manager);
226-
}
227-
}
228-
});
229-
208+
const projects = wm.getProjects(uris).map((p) => p);
209+
const projectEnvManagers = em.getProjectEnvManagers(uris);
230210
const recommended =
231211
projectEnvManagers.length === 1 && uris.length === 1 ? await projectEnvManagers[0].get(uris[0]) : undefined;
232212
const selected = await pickEnvironment(em.managers, projectEnvManagers, {
233213
projects,
234214
recommended,
235215
showBackButton: uris.length > 1,
236216
});
237-
const manager = em.managers.find((m) => m.id === selected?.envId.managerId);
238-
if (selected && manager) {
239-
const promises: Thenable<void>[] = [];
240-
const settings: EditAllManagerSettings[] = [];
241-
uris.forEach((uri) => {
242-
const m = em.getEnvironmentManager(uri);
243-
promises.push(manager.set(uri, selected));
244-
if (manager.id !== m?.id) {
245-
settings.push({
246-
project: wm.get(uri),
247-
envManager: manager.id,
248-
packageManager: manager.preferredPackageManagerId,
249-
});
250-
}
251-
});
252-
await Promise.all(promises);
253-
await setAllManagerSettings(settings);
254-
return projects.map((p) => ({ project: p, environment: selected }));
217+
218+
if (selected) {
219+
await em.setEnvironments(uris, selected);
255220
}
256-
return;
221+
} else {
222+
traceError(`Invalid context for setting environment command: ${context}`);
223+
window.showErrorMessage('Invalid context for setting environment');
257224
}
258-
traceError(`Invalid context for setting environment command: ${context}`);
259-
window.showErrorMessage('Invalid context for setting environment');
260225
}
261226

262227
export async function resetEnvironmentCommand(
@@ -338,9 +303,17 @@ export async function addPythonProject(
338303
return;
339304
}
340305

341-
let results = await creator.create();
342-
if (results === undefined) {
343-
return;
306+
let results: PythonProject | PythonProject[] | undefined;
307+
try {
308+
results = await creator.create();
309+
if (results === undefined) {
310+
return;
311+
}
312+
} catch (ex: any) {
313+
if (ex === QuickInputButtons.Back) {
314+
return addPythonProject(resource, wm, em, pc);
315+
}
316+
throw ex;
344317
}
345318

346319
if (!Array.isArray(results)) {
@@ -435,21 +408,21 @@ export async function createTerminalCommand(
435408
const env = await api.getEnvironment(uri);
436409
const pw = api.getPythonProject(uri);
437410
if (env && pw) {
438-
return await tm.create(env, pw.uri);
411+
return await tm.create(env, { cwd: pw.uri });
439412
}
440413
} else if (context instanceof ProjectItem) {
441414
const view = context as ProjectItem;
442415
const env = await api.getEnvironment(view.project.uri);
443416
if (env) {
444-
const terminal = await tm.create(env, view.project.uri);
417+
const terminal = await tm.create(env, { cwd: view.project.uri });
445418
terminal.show();
446419
return terminal;
447420
}
448421
} else if (context instanceof PythonEnvTreeItem) {
449422
const view = context as PythonEnvTreeItem;
450423
const pw = await pickProject(api.getPythonProjects());
451424
if (pw) {
452-
const terminal = await tm.create(view.environment, pw.uri);
425+
const terminal = await tm.create(view.environment, { cwd: pw.uri });
453426
terminal.show();
454427
return terminal;
455428
}

0 commit comments

Comments
 (0)