forked from DonJayamanne/pythonVSCode
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Expand file tree
/
Copy pathconfigurePythonEnvTool.ts
More file actions
124 lines (116 loc) · 4.99 KB
/
configurePythonEnvTool.ts
File metadata and controls
124 lines (116 loc) · 4.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import {
CancellationToken,
LanguageModelTool,
LanguageModelToolInvocationOptions,
LanguageModelToolInvocationPrepareOptions,
LanguageModelToolResult,
PreparedToolInvocation,
Uri,
workspace,
lm,
} from 'vscode';
import { PythonExtension } from '../api/types';
import { IServiceContainer } from '../ioc/types';
import { ICodeExecutionService } from '../terminals/types';
import { TerminalCodeExecutionProvider } from '../terminals/codeExecution/terminalCodeExecution';
import {
getEnvDetailsForResponse,
getToolResponseIfNotebook,
IResourceReference,
isCancellationError,
raceCancellationError,
} from './utils';
import { resolveFilePath } from './utils';
import { ITerminalHelper } from '../common/terminal/types';
import { IRecommendedEnvironmentService } from '../interpreter/configuration/types';
import { CreateVirtualEnvTool } from './createVirtualEnvTool';
import { ISelectPythonEnvToolArguments, SelectPythonEnvTool } from './selectEnvTool';
import { useEnvExtension } from '../envExt/api.internal';
export class ConfigurePythonEnvTool implements LanguageModelTool<IResourceReference> {
private readonly terminalExecutionService: TerminalCodeExecutionProvider;
private readonly terminalHelper: ITerminalHelper;
private readonly recommendedEnvService: IRecommendedEnvironmentService;
public static readonly toolName = 'configure_python_environment';
constructor(
private readonly api: PythonExtension['environments'],
private readonly serviceContainer: IServiceContainer,
private readonly createEnvTool: CreateVirtualEnvTool,
) {
this.terminalExecutionService = this.serviceContainer.get<TerminalCodeExecutionProvider>(
ICodeExecutionService,
'standard',
);
this.terminalHelper = this.serviceContainer.get<ITerminalHelper>(ITerminalHelper);
this.recommendedEnvService = this.serviceContainer.get<IRecommendedEnvironmentService>(
IRecommendedEnvironmentService,
);
}
async invoke(
options: LanguageModelToolInvocationOptions<IResourceReference>,
token: CancellationToken,
): Promise<LanguageModelToolResult> {
const resource = resolveFilePath(options.input.resourcePath);
const notebookResponse = getToolResponseIfNotebook(resource);
if (notebookResponse) {
return notebookResponse;
}
const workspaceSpecificEnv = await raceCancellationError(
this.hasAlreadyGotAWorkspaceSpecificEnvironment(resource),
token,
);
if (workspaceSpecificEnv) {
return getEnvDetailsForResponse(
workspaceSpecificEnv,
this.api,
this.terminalExecutionService,
this.terminalHelper,
resource,
token,
);
}
if (await this.createEnvTool.shouldCreateNewVirtualEnv(resource, token)) {
try {
// If the Python Env extension is available, then use that.
// create_quick_virtual_environment
const toolName = useEnvExtension() ? 'create_quick_virtual_environment' : CreateVirtualEnvTool.toolName;
return await lm.invokeTool(toolName, options, token);
} catch (ex) {
if (isCancellationError(ex)) {
const input: ISelectPythonEnvToolArguments = {
...options.input,
reason: 'cancelled',
};
// If the user cancelled the tool, then we should invoke the select env tool.
return lm.invokeTool(SelectPythonEnvTool.toolName, { ...options, input }, token);
}
throw ex;
}
} else {
const input: ISelectPythonEnvToolArguments = {
...options.input,
};
return lm.invokeTool(SelectPythonEnvTool.toolName, { ...options, input }, token);
}
}
async prepareInvocation?(
_options: LanguageModelToolInvocationPrepareOptions<IResourceReference>,
_token: CancellationToken,
): Promise<PreparedToolInvocation> {
return {
invocationMessage: 'Configuring a Python Environment',
};
}
async hasAlreadyGotAWorkspaceSpecificEnvironment(resource: Uri | undefined) {
const recommededEnv = await this.recommendedEnvService.getRecommededEnvironment(resource);
// Already selected workspace env, hence nothing to do.
if (recommededEnv?.reason === 'workspaceUserSelected' && workspace.workspaceFolders?.length) {
return recommededEnv.environment;
}
// No workspace folders, and the user selected a global environment.
if (recommededEnv?.reason === 'globalUserSelected' && !workspace.workspaceFolders?.length) {
return recommededEnv.environment;
}
}
}