#!/usr/bin/env python3 """ PetBot Prerequisites Installation Script (Fixed for externally-managed-environment) This script handles the externally-managed-environment error by using virtual environments. """ import subprocess import sys import os import importlib.util import venv from pathlib import Path def print_header(): """Print installation header.""" print("=" * 60) print("๐Ÿพ PetBot Prerequisites Installation Script (Fixed)") print("=" * 60) print() def check_python_version(): """Check if Python version is compatible.""" print("๐Ÿ” Checking Python version...") version = sys.version_info required_major = 3 required_minor = 7 if version.major < required_major or (version.major == required_major and version.minor < required_minor): print(f"โŒ Python {required_major}.{required_minor}+ required. Current version: {version.major}.{version.minor}.{version.micro}") print("Please upgrade Python and try again.") return False print(f"โœ… Python {version.major}.{version.minor}.{version.micro} is compatible") return True def check_venv_available(): """Check if venv module is available.""" print("\n๐Ÿ” Checking venv availability...") try: import venv print("โœ… venv module is available") return True except ImportError: print("โŒ venv module is not available") print("Please install python3-venv:") print(" Ubuntu/Debian: sudo apt install python3-venv") print(" CentOS/RHEL: sudo yum install python3-venv") return False def create_virtual_environment(): """Create a virtual environment for the project.""" print("\n๐Ÿ”ง Creating virtual environment...") venv_path = Path("venv") if venv_path.exists(): print("โœ… Virtual environment already exists") return str(venv_path) try: venv.create(venv_path, with_pip=True) print("โœ… Virtual environment created successfully") return str(venv_path) except Exception as e: print(f"โŒ Failed to create virtual environment: {e}") return None def get_venv_python_path(venv_path): """Get the Python executable path in the virtual environment.""" if os.name == 'nt': # Windows return os.path.join(venv_path, 'Scripts', 'python.exe') else: # Linux/macOS return os.path.join(venv_path, 'bin', 'python') def get_venv_pip_path(venv_path): """Get the pip executable path in the virtual environment.""" if os.name == 'nt': # Windows return os.path.join(venv_path, 'Scripts', 'pip.exe') else: # Linux/macOS return os.path.join(venv_path, 'bin', 'pip') def install_packages_in_venv(venv_path): """Install packages in the virtual environment.""" print("\n๐Ÿ“ฆ Installing packages in virtual environment...") venv_pip = get_venv_pip_path(venv_path) if not os.path.exists(venv_pip): print("โŒ pip not found in virtual environment") return False # Upgrade pip first print("๐Ÿ”„ Upgrading pip...") try: subprocess.run([venv_pip, "install", "--upgrade", "pip"], check=True, capture_output=True) print("โœ… pip upgraded successfully") except subprocess.CalledProcessError as e: print(f"โš ๏ธ pip upgrade failed: {e}") # Install from requirements.txt requirements_file = Path("requirements.txt") if requirements_file.exists(): print("๐Ÿ“‹ Installing from requirements.txt...") try: result = subprocess.run([venv_pip, "install", "-r", "requirements.txt"], check=True, capture_output=True, text=True) print("โœ… Successfully installed packages from requirements.txt") return True except subprocess.CalledProcessError as e: print(f"โŒ Failed to install from requirements.txt: {e.stderr}") # Install individual packages print("๐Ÿ“ฆ Installing individual packages...") packages = [ "irc>=20.3.0", "aiosqlite>=0.19.0", "python-dotenv>=1.0.0" ] success = True for package in packages: print(f"Installing {package}...") try: subprocess.run([venv_pip, "install", package], check=True, capture_output=True) print(f"โœ… Successfully installed {package}") except subprocess.CalledProcessError as e: print(f"โŒ Failed to install {package}") success = False return success def verify_installation_in_venv(venv_path): """Verify installation in virtual environment.""" print("\n๐Ÿ” Verifying installation in virtual environment...") venv_python = get_venv_python_path(venv_path) test_modules = [ "irc", "aiosqlite", "dotenv", "asyncio", "sqlite3", "json", "socket" ] all_good = True for module in test_modules: try: result = subprocess.run([venv_python, "-c", f"import {module}"], check=True, capture_output=True) print(f"โœ… {module}: Available") except subprocess.CalledProcessError: print(f"โŒ {module}: Not available") all_good = False return all_good def create_activation_script(): """Create a script to activate the virtual environment.""" print("\n๐Ÿ”ง Creating activation script...") activation_script = """#!/bin/bash # PetBot Virtual Environment Activation Script echo "๐Ÿพ Activating PetBot virtual environment..." if [ -d "venv" ]; then source venv/bin/activate echo "โœ… Virtual environment activated" echo "๐Ÿš€ You can now run:" echo " python run_bot_with_reconnect.py" echo " python test_backup_simple.py" echo " python test_reconnection.py" echo "" echo "๐Ÿ’ก To deactivate: deactivate" else echo "โŒ Virtual environment not found" echo "Run: python3 install_prerequisites_fixed.py" fi """ try: with open("activate_petbot.sh", "w") as f: f.write(activation_script) os.chmod("activate_petbot.sh", 0o755) print("โœ… Created activate_petbot.sh") return True except Exception as e: print(f"โŒ Failed to create activation script: {e}") return False def create_run_scripts(): """Create wrapper scripts that use the virtual environment.""" print("\n๐Ÿ”ง Creating wrapper scripts...") scripts = { "run_petbot.sh": """#!/bin/bash # PetBot Runner Script (uses virtual environment) if [ -d "venv" ]; then source venv/bin/activate echo "๐Ÿš€ Starting PetBot with auto-reconnect..." python run_bot_with_reconnect.py else echo "โŒ Virtual environment not found" echo "Run: python3 install_prerequisites_fixed.py" fi """, "run_petbot_debug.sh": """#!/bin/bash # PetBot Debug Runner Script (uses virtual environment) if [ -d "venv" ]; then source venv/bin/activate echo "๐Ÿš€ Starting PetBot in debug mode..." python run_bot_debug.py else echo "โŒ Virtual environment not found" echo "Run: python3 install_prerequisites_fixed.py" fi """, "test_petbot.sh": """#!/bin/bash # PetBot Test Script (uses virtual environment) if [ -d "venv" ]; then source venv/bin/activate echo "๐Ÿงช Running PetBot tests..." echo "1. Testing backup system..." python test_backup_simple.py echo "" echo "2. Testing reconnection system..." python test_reconnection.py else echo "โŒ Virtual environment not found" echo "Run: python3 install_prerequisites_fixed.py" fi """ } success = True for script_name, script_content in scripts.items(): try: with open(script_name, "w") as f: f.write(script_content) os.chmod(script_name, 0o755) print(f"โœ… Created {script_name}") except Exception as e: print(f"โŒ Failed to create {script_name}: {e}") success = False return success def create_directories(): """Create required directories.""" print("\n๐Ÿ”ง Creating required directories...") directories = ["data", "backups", "logs"] for directory in directories: dir_path = Path(directory) if not dir_path.exists(): try: dir_path.mkdir() print(f"โœ… Created {directory}/ directory") except Exception as e: print(f"โŒ Failed to create {directory}/ directory: {e}") return False else: print(f"โœ… {directory}/ directory already exists") return True def show_usage_instructions(): """Show usage instructions after installation.""" print("\n๐ŸŽ‰ Installation completed successfully!") print("\n๐Ÿ“‹ How to use PetBot:") print("\n๐Ÿ”ง Method 1: Using activation script (recommended)") print(" ./activate_petbot.sh") print(" python run_bot_with_reconnect.py") print("\n๐Ÿ”ง Method 2: Using wrapper scripts") print(" ./run_petbot.sh # Start bot with auto-reconnect") print(" ./run_petbot_debug.sh # Start bot in debug mode") print(" ./test_petbot.sh # Run tests") print("\n๐Ÿ”ง Method 3: Manual activation") print(" source venv/bin/activate") print(" python run_bot_with_reconnect.py") print(" deactivate # when done") print("\n๐Ÿ“š Documentation:") print(" QUICKSTART.md # Quick start guide") print(" INSTALLATION.md # Detailed installation guide") print(" CLAUDE.md # Development guidelines") print("\n๐ŸŒ Web Interface:") print(" http://localhost:8080 # Access after starting bot") print("\nโš ๏ธ Important Notes:") print(" - Always activate the virtual environment before running Python scripts") print(" - Use the wrapper scripts for convenience") print(" - The virtual environment is in the 'venv' directory") def main(): """Main installation function.""" print_header() # Check prerequisites if not check_python_version(): return False if not check_venv_available(): return False # Create virtual environment venv_path = create_virtual_environment() if not venv_path: return False # Install packages in virtual environment if not install_packages_in_venv(venv_path): print("\nโŒ Package installation failed") return False # Verify installation if not verify_installation_in_venv(venv_path): print("\nโŒ Installation verification failed") return False # Create directories if not create_directories(): return False # Create helper scripts if not create_activation_script(): return False if not create_run_scripts(): return False # Show usage instructions show_usage_instructions() return True if __name__ == "__main__": try: success = main() if success: print("\nโœ… PetBot virtual environment setup completed successfully!") print("๐Ÿš€ Use './run_petbot.sh' to start the bot") sys.exit(0) else: print("\nโŒ Installation failed. Please check the errors above.") sys.exit(1) except KeyboardInterrupt: print("\n๐Ÿ›‘ Installation interrupted by user") sys.exit(1) except Exception as e: print(f"\n๐Ÿ’ฅ Unexpected error: {e}") import traceback traceback.print_exc() sys.exit(1)