-
Notifications
You must be signed in to change notification settings - Fork 42
Expand file tree
/
Copy pathhelpers.ts
More file actions
140 lines (130 loc) · 4.79 KB
/
helpers.ts
File metadata and controls
140 lines (130 loc) · 4.79 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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import { CancellationError, CancellationToken, LogOutputChannel } from 'vscode';
import { spawnProcess } from '../../common/childProcess.apis';
import { EventNames } from '../../common/telemetry/constants';
import { sendTelemetryEvent } from '../../common/telemetry/sender';
import { createDeferred } from '../../common/utils/deferred';
import { getConfiguration } from '../../common/workspace.apis';
import { getUvEnvironments } from './uvEnvironments';
let available = createDeferred<boolean>();
/**
* Reset the UV installation cache.
*/
export function resetUvInstallationCache(): void {
available = createDeferred<boolean>();
}
export async function isUvInstalled(log?: LogOutputChannel): Promise<boolean> {
console.log('into isUvInstalled function');
if (available.completed) {
console.log('UV installation status already determined');
return available.promise;
}
log?.info(`Running: uv --version`);
const proc = spawnProcess('uv', ['--version']);
proc.on('error', () => {
available.resolve(false);
});
proc.stdout?.on('data', (d) => log?.info(d.toString()));
proc.on('exit', (code) => {
if (code === 0) {
sendTelemetryEvent(EventNames.VENV_USING_UV);
}
available.resolve(code === 0);
});
return available.promise;
}
/**
* Determines if uv should be used for managing a virtual environment.
* @param log - Optional log output channel for logging operations
* @param envPath - Optional environment path to check against UV environments list
* @returns True if uv should be used, false otherwise. For UV environments, returns true if uv is installed. For other environments, checks the 'python-envs.alwaysUseUv' setting and uv availability.
*/
export async function shouldUseUv(log?: LogOutputChannel, envPath?: string): Promise<boolean> {
if (envPath) {
// always use uv if the given environment is stored as a uv env
const uvEnvs = await getUvEnvironments();
console.log(`UV Environments: ${uvEnvs.join(', ')}`);
console.log(`Checking if envPath ${envPath} is in UV environments`);
console.log(`isUVinstalled function: ${isUvInstalled(log)}`);
if (uvEnvs.includes(envPath)) {
return await isUvInstalled(log);
}
}
// For other environments, check the user setting
const config = getConfiguration('python-envs');
const alwaysUseUv = config.get<boolean>('alwaysUseUv', true);
console.log(`alwaysUseUv setting is ${alwaysUseUv}`);
console.log(config.inspect<boolean>('alwaysUseUv'));
console.log(config.inspect<boolean>('alwaysUseUv')?.globalValue);
if (alwaysUseUv) {
console.log(`alwaysUseUv is true, checking if UV is installed`);
return await isUvInstalled(log);
}
return false;
}
export async function runUV(
args: string[],
cwd?: string,
log?: LogOutputChannel,
token?: CancellationToken,
): Promise<string> {
log?.info(`Running: uv ${args.join(' ')}`);
return new Promise<string>((resolve, reject) => {
const proc = spawnProcess('uv', args, { cwd: cwd });
token?.onCancellationRequested(() => {
proc.kill();
reject(new CancellationError());
});
let builder = '';
proc.stdout?.on('data', (data) => {
const s = data.toString('utf-8');
builder += s;
log?.append(s);
});
proc.stderr?.on('data', (data) => {
log?.append(data.toString('utf-8'));
});
proc.on('close', () => {
resolve(builder);
});
proc.on('exit', (code) => {
if (code !== 0) {
reject(new Error(`Failed to run uv ${args.join(' ')}`));
}
});
});
}
export async function runPython(
python: string,
args: string[],
cwd?: string,
log?: LogOutputChannel,
token?: CancellationToken,
): Promise<string> {
log?.info(`Running: ${python} ${args.join(' ')}`);
return new Promise<string>((resolve, reject) => {
const proc = spawnProcess(python, args, { cwd: cwd });
token?.onCancellationRequested(() => {
proc.kill();
reject(new CancellationError());
});
let builder = '';
proc.stdout?.on('data', (data) => {
const s = data.toString('utf-8');
builder += s;
log?.append(`python: ${s}`);
});
proc.stderr?.on('data', (data) => {
const s = data.toString('utf-8');
builder += s;
log?.append(`python: ${s}`);
});
proc.on('close', () => {
resolve(builder);
});
proc.on('exit', (code) => {
if (code !== 0) {
reject(new Error(`Failed to run python ${args.join(' ')}`));
}
});
});
}