UNPKG

py-run

Version:

CLI tool to run Python scripts in isolated environments with automatic dependency management

124 lines (108 loc) 4.06 kB
#!/usr/bin/env node const { execSync } = require('child_process'); const fs = require('fs'); const path = require('path'); const chalk = require('chalk'); const ora = require('ora'); const boxen = require('boxen'); function runCommand(command, silent = false) { try { return execSync(command, { stdio: silent ? 'pipe' : 'inherit', encoding: 'utf-8' }); } catch (error) { console.error(chalk.red.bold('✖ Error executing command:'), chalk.dim(command)); console.error(chalk.red(error.message)); process.exit(1); } } function extractImports(filePath) { const content = fs.readFileSync(filePath, 'utf8'); const importRegex = /^(?:import|from)\s+([a-zA-Z0-9_\.]+)/gm; const stdLibs = new Set(['sys', 'os', 'time', 'datetime', 'json', 're']); const packages = new Set(); let match; while ((match = importRegex.exec(content)) !== null) { let pkg = match[1].split('.')[0]; if (!stdLibs.has(pkg)) { packages.add(pkg); } } return Array.from(packages); } function displayHeader(pythonFile) { console.log(boxen( chalk.blue.bold('Python Environment Manager') + '\n\n' + chalk.white(`File: ${chalk.green(pythonFile)}`), { padding: 1, margin: 1, borderStyle: 'round', borderColor: 'blue' } )); } async function main() { const pythonFile = process.argv[2]; if (!pythonFile || !fs.existsSync(pythonFile)) { console.error(chalk.red.bold('✖ Error:'), 'Please provide a valid Python file path'); process.exit(1); } displayHeader(pythonFile); // Try to determine which Python command is available let pythonCommand; try { runCommand('python3 --version', true); pythonCommand = 'python3'; } catch { try { runCommand('python --version', true); pythonCommand = 'python'; } catch { console.error(chalk.red.bold('✖ Error: Neither python nor python3 command was found')); process.exit(1); } } const venvPath = 'venv'; const venvSpinner = ora('Checking virtual environment...').start(); if (!fs.existsSync(venvPath)) { venvSpinner.text = 'Creating virtual environment...'; runCommand(`${pythonCommand} -m venv venv`, true); venvSpinner.succeed(chalk.green('Virtual environment created successfully')); } else { venvSpinner.succeed(chalk.green('Virtual environment already exists')); } const activateCmd = process.platform === 'win32' ? `${venvPath}\\Scripts\\activate` : `source ${venvPath}/bin/activate`; const packagesSpinner = ora('Analyzing Python imports...').start(); const packages = extractImports(pythonFile); if (packages.length > 0) { packagesSpinner.succeed(chalk.green(`Found ${packages.length} package(s) to install`)); for (const pkg of packages) { const installSpinner = ora(`Installing ${pkg}...`).start(); try { runCommand(`${activateCmd} && pip install ${pkg}`, true); installSpinner.succeed(chalk.green(`Package ${pkg} installed successfully`)); } catch (error) { installSpinner.fail(chalk.red(`Failed to install ${pkg}`)); throw error; } } } else { packagesSpinner.succeed(chalk.green('No external packages required')); } console.log('\n' + chalk.cyan.bold('🚀 Launching Python script...') + '\n'); try { runCommand(`${activateCmd} && ${pythonCommand} ${pythonFile}`); console.log('\n' + chalk.green.bold('✨ Script execution completed successfully') + '\n'); } catch (error) { console.log('\n' + chalk.red.bold('❌ Script execution failed') + '\n'); throw error; } } main().catch(error => { console.error(chalk.red.bold('❌ Process terminated with error')); process.exit(1); });