* Run `uv python install 3.12` once with the given environment. * Returns on success, throws with captured stderr on failure.
( uvBin: string, env: Record<string, string | undefined>, label: string, )
| 110 | * Returns on success, throws with captured stderr on failure. |
| 111 | */ |
| 112 | async function runPythonInstall( |
| 113 | uvBin: string, |
| 114 | env: Record<string, string | undefined>, |
| 115 | label: string, |
| 116 | ): Promise<void> { |
| 117 | const useShell = needsWinShell(uvBin); |
| 118 | return new Promise<void>((resolve, reject) => { |
| 119 | const stderrChunks: string[] = []; |
| 120 | const stdoutChunks: string[] = []; |
| 121 | |
| 122 | const child = spawn(useShell ? quoteForCmd(uvBin) : uvBin, ['python', 'install', '3.12'], { |
| 123 | shell: useShell, |
| 124 | env, |
| 125 | windowsHide: true, |
| 126 | }); |
| 127 | |
| 128 | child.stdout?.on('data', (data) => { |
| 129 | const line = data.toString().trim(); |
| 130 | if (line) { |
| 131 | stdoutChunks.push(line); |
| 132 | logger.debug(`[python-setup:${label}] stdout: ${line}`); |
| 133 | } |
| 134 | }); |
| 135 | |
| 136 | child.stderr?.on('data', (data) => { |
| 137 | const line = data.toString().trim(); |
| 138 | if (line) { |
| 139 | stderrChunks.push(line); |
| 140 | logger.info(`[python-setup:${label}] stderr: ${line}`); |
| 141 | } |
| 142 | }); |
| 143 | |
| 144 | child.on('close', (code) => { |
| 145 | if (code === 0) { |
| 146 | resolve(); |
| 147 | } else { |
| 148 | const stderr = stderrChunks.join('\n'); |
| 149 | const stdout = stdoutChunks.join('\n'); |
| 150 | const detail = stderr || stdout || '(no output captured)'; |
| 151 | reject(new Error( |
| 152 | `Python installation failed with code ${code} [${label}]\n` + |
| 153 | ` uv binary: ${uvBin}\n` + |
| 154 | ` platform: ${process.platform}/${process.arch}\n` + |
| 155 | ` output: ${detail}` |
| 156 | )); |
| 157 | } |
| 158 | }); |
| 159 | |
| 160 | child.on('error', (err) => { |
| 161 | reject(new Error( |
| 162 | `Python installation spawn error [${label}]: ${err.message}\n` + |
| 163 | ` uv binary: ${uvBin}\n` + |
| 164 | ` platform: ${process.platform}/${process.arch}` |
| 165 | )); |
| 166 | }); |
| 167 | }); |
| 168 | } |
| 169 |
no test coverage detected