🐛 Prebuilt terminal venv found but Python executable missing (#1056)

Co-authored-by: Tao Sun <168447269+fengju0213@users.noreply.github.com>
This commit is contained in:
Tong Chen 2026-01-23 19:36:18 +08:00 committed by GitHub
parent 6d2876bee6
commit 4af1a8664e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 178 additions and 4 deletions

View file

@ -169,6 +169,56 @@ export function getPrebuiltVenvPath(): string | null {
return null;
}
/**
* Find Python executable in prebuilt Python directory for terminal venv
*/
function findPythonForTerminalVenv(): string | null {
const prebuiltPythonDir = getPrebuiltPythonDir();
if (!prebuiltPythonDir) {
return null;
}
// Look for Python executable in the prebuilt directory
// UV stores Python in subdirectories like: cpython-3.10.19+.../install/bin/python
const possiblePaths: string[] = [];
// First, try common direct paths
possiblePaths.push(
path.join(prebuiltPythonDir, 'install', 'bin', 'python'),
path.join(prebuiltPythonDir, 'install', 'python.exe'),
path.join(prebuiltPythonDir, 'bin', 'python'),
path.join(prebuiltPythonDir, 'python.exe'),
);
// Then, search in subdirectories (UV stores Python in versioned directories)
try {
if (fs.existsSync(prebuiltPythonDir)) {
const entries = fs.readdirSync(prebuiltPythonDir, { withFileTypes: true });
for (const entry of entries) {
if (entry.isDirectory() && entry.name.startsWith('cpython-')) {
const subDir = path.join(prebuiltPythonDir, entry.name);
possiblePaths.push(
path.join(subDir, 'install', 'bin', 'python'),
path.join(subDir, 'install', 'python.exe'),
path.join(subDir, 'bin', 'python'),
path.join(subDir, 'python.exe'),
);
}
}
}
} catch (error) {
log.warn('[PROCESS] Error searching for prebuilt Python:', error);
}
for (const pythonPath of possiblePaths) {
if (fs.existsSync(pythonPath)) {
return pythonPath;
}
}
return null;
}
/**
* Get path to prebuilt terminal venv (if available in packaged app)
*/
@ -191,10 +241,42 @@ export function getPrebuiltTerminalVenvPath(): string | null {
log.info(`Using prebuilt terminal venv: ${prebuiltTerminalVenvPath}`);
return prebuiltTerminalVenvPath;
} else {
// Try to fix the missing Python executable by creating a symlink to prebuilt Python
log.warn(
`Prebuilt terminal venv found but Python executable missing at: ${pythonExePath}. ` +
`Falling back to user terminal venv.`
`Attempting to fix...`
);
const prebuiltPython = findPythonForTerminalVenv();
if (prebuiltPython && fs.existsSync(prebuiltPython)) {
try {
const binDir = isWindows
? path.join(prebuiltTerminalVenvPath, 'Scripts')
: path.join(prebuiltTerminalVenvPath, 'bin');
// Ensure bin directory exists
if (!fs.existsSync(binDir)) {
fs.mkdirSync(binDir, { recursive: true });
}
// Create symlink to prebuilt Python
if (fs.existsSync(pythonExePath)) {
// Remove existing broken symlink or file
fs.unlinkSync(pythonExePath);
}
// Calculate relative path for symlink
const relativePath = path.relative(binDir, prebuiltPython);
fs.symlinkSync(relativePath, pythonExePath);
log.info(`Fixed terminal venv Python symlink: ${pythonExePath} -> ${prebuiltPython}`);
return prebuiltTerminalVenvPath;
} catch (error) {
log.warn(`Failed to fix terminal venv Python symlink: ${error}`);
}
}
log.warn(`Falling back to user terminal venv.`);
}
}
}