69 lines
2.3 KiB
TypeScript
69 lines
2.3 KiB
TypeScript
import { existsSync } from 'node:fs';
|
|
import { delimiter, dirname, isAbsolute, join, resolve } from 'node:path';
|
|
|
|
export type PythonRuntimeSource = 'configured' | 'bundled' | 'system';
|
|
|
|
export type PythonRuntime = {
|
|
executable: string;
|
|
binDir: string;
|
|
source: PythonRuntimeSource;
|
|
};
|
|
|
|
export type PythonRuntimeOptions = {
|
|
isPackaged: boolean;
|
|
resourcesPath: string;
|
|
appPath: string;
|
|
platform: NodeJS.Platform;
|
|
arch: string;
|
|
configuredPath?: string;
|
|
};
|
|
|
|
function configuredRuntime(configuredPath: string | undefined, appPath: string): PythonRuntime | null {
|
|
const trimmed = configuredPath?.trim();
|
|
if (!trimmed) return null;
|
|
const executable = isAbsolute(trimmed) ? trimmed : resolve(appPath, trimmed);
|
|
if (!existsSync(executable)) return null;
|
|
return { executable, binDir: dirname(executable), source: 'configured' };
|
|
}
|
|
|
|
function bundledExecutable(resourcesPath: string, platform: NodeJS.Platform): string {
|
|
return platform === 'win32'
|
|
? join(resourcesPath, 'python', 'python.exe')
|
|
: join(resourcesPath, 'python', 'bin', 'python3');
|
|
}
|
|
|
|
export function resolvePythonRuntime(options: PythonRuntimeOptions): PythonRuntime {
|
|
const configured = configuredRuntime(options.configuredPath, options.appPath);
|
|
if (configured) return configured;
|
|
|
|
const executable = bundledExecutable(options.resourcesPath, options.platform);
|
|
if (existsSync(executable)) {
|
|
return { executable, binDir: dirname(executable), source: 'bundled' };
|
|
}
|
|
|
|
if (options.isPackaged) {
|
|
throw new Error(`Bundled Python runtime is missing: ${executable}`);
|
|
}
|
|
|
|
return {
|
|
executable: options.platform === 'win32' ? 'python' : 'python3',
|
|
binDir: '',
|
|
source: 'system',
|
|
};
|
|
}
|
|
|
|
export function prependPythonToPath(
|
|
environment: Record<string, string>,
|
|
runtime: PythonRuntime,
|
|
platform: NodeJS.Platform = process.platform,
|
|
): Record<string, string> {
|
|
const result = { ...environment, NIANCODE_PYTHON_PATH: runtime.executable };
|
|
if (!runtime.binDir) return result;
|
|
|
|
const existingKey = Object.keys(result).find((key) => key.toLowerCase() === 'path');
|
|
const pathKey = platform === 'win32' && existingKey ? existingKey : 'PATH';
|
|
const existingPath = result[pathKey];
|
|
result[pathKey] = existingPath ? `${runtime.binDir}${delimiter}${existingPath}` : runtime.binDir;
|
|
return result;
|
|
}
|