validate-setup.mjs
1 import { execSync } from 'child_process'; 2 import { ErrorWithRemedy } from '../error-with-remedy.mjs'; 3 import { formatExample } from '../format.mjs'; 4 import { getPythonPath } from './python-path.mjs'; 5 import { logInfo } from '../log.mjs'; 6 import { validateExecutable } from './validate-executable.mjs'; 7 8 /** 9 * On macOS, this script checks if Python 3.10 is installed and accessible to node-gyp. 10 * 11 * I ran into a problem trying to `yarn` install, with a system Python version of `3.12.2`, 12 * but ran into the error `ModuleNotFoundError: No module named 'distutils'`. 13 * Since node-gyp relies on `distutils`, which is removed in Python `3.12`, 14 * you need to use a Python version that still includes `distutils`. 15 */ 16 export function validateMacSetup() { 17 logInfo('Installing on macOS'); 18 const pythonPath = getPythonPath(); 19 validateExecutable(pythonPath); 20 21 let error; 22 try { 23 const pythonVersionOutput = execSync(`${pythonPath} --version`).toString().trim(); 24 logInfo(`${pythonPath} == (${pythonVersionOutput})`); 25 26 const pythonVersion = pythonVersionOutput.split(' ')[1].trim(); 27 const majorVersion = parseInt(pythonVersion.split('.')[0]); 28 const minorVersion = parseInt(pythonVersion.split('.')[1]); 29 const noCompatiblePythonVersionFound = !(majorVersion === 3 && (minorVersion >= 10 && minorVersion < 12)); 30 31 if (noCompatiblePythonVersionFound) { 32 error = `Incompatible Python version ${pythonVersion} found. Python 3.10 is required.`; 33 } 34 35 } catch (caughtError) { 36 error = `Python 3.10 was not found with error: ${caughtError?.message || caughtError}`; 37 } 38 if (error) { 39 const checkForPythonInstall = 'Check for versions of python installed on your system. For example, if you use brew:'; 40 const displayBrewPythonVersionsExample = formatExample('brew list --versions | grep python'); 41 42 const pleaseInstallPython = 'If python 3.10 was not found, install it. For example:'; 43 const installPythonExample = formatExample('brew install python@3.10'); 44 45 const configureNodeGypPython = 'Ensure you have an environment variable for NODE_GYP_FORCE_PYTHON pointing to your python 3.10 path.\n For example, assuming you installed python@3.10 with brew:'; 46 const exportNodeGypPythonEnvVariable = formatExample('export NODE_GYP_FORCE_PYTHON=$(brew --prefix python@3.10)/bin/python3.10'); 47 48 throw new ErrorWithRemedy(error, ` STEP 1: ${checkForPythonInstall} ${displayBrewPythonVersionsExample} 49 \n STEP 2: ${pleaseInstallPython} ${installPythonExample} 50 \n STEP 3: ${configureNodeGypPython} ${exportNodeGypPythonEnvVariable}` 51 ); 52 } 53 }