#!/bin/bash # ============================================================================= # UV Migration Script (Robust Version) # ============================================================================= # Migrates from pip/venv to uv package manager # Enhanced error handling for production environments # ============================================================================= # Don't exit on errors - handle them gracefully set +e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Script version VERSION="1.1.0-robust" # Print header echo -e "${BLUE}=================================${NC}" echo -e "${BLUE} UV Migration Script v${VERSION}${NC}" echo -e "${BLUE}=================================${NC}" echo "" # Function to print colored output print_success() { echo -e "${GREEN}✅ $1${NC}" } print_warning() { echo -e "${YELLOW}⚠️ $1${NC}" } print_error() { echo -e "${RED}❌ $1${NC}" } print_info() { echo -e "${BLUE}ℹ️ $1${NC}" } # Function to check if command exists command_exists() { command -v "$1" >/dev/null 2>&1 } # Function to get file size in human readable format get_size() { if [[ "$OSTYPE" == "darwin"* ]]; then # macOS du -h "$1" 2>/dev/null | cut -f1 || echo "0B" else # Linux du -sh "$1" 2>/dev/null | cut -f1 || echo "0B" fi } # Check if we're in the project root if [[ ! -f "pyproject.toml" && ! -f "requirements.txt" ]]; then print_error "Neither pyproject.toml nor requirements.txt found. Please run this script from the project root." exit 1 fi print_info "Starting migration process..." echo "" # ============================================================================= # Step 1: Pre-migration Analysis # ============================================================================= echo -e "${BLUE}📊 Pre-migration Analysis${NC}" echo "----------------------------" # Count cache files before cleanup (with timeout to prevent hanging) print_info "Analyzing project files (this may take a moment)..." PYCACHE_DIRS=$(timeout 30 find . -path "./.venv" -prune -o -path "./venv" -prune -o -name "__pycache__" -type d -print 2>/dev/null | wc -l | tr -d ' ') PYC_FILES=$(timeout 30 find . -path "./.venv" -prune -o -path "./venv" -prune -o -name "*.pyc" -type f -print 2>/dev/null | wc -l | tr -d ' ') echo "📁 Cache directories found: $PYCACHE_DIRS" echo "📄 .pyc files found: $PYC_FILES" # Check if pytest cache exists if [[ -d ".pytest_cache" ]]; then PYTEST_SIZE=$(get_size ".pytest_cache") echo "🧪 Pytest cache size: $PYTEST_SIZE" else echo "🧪 No pytest cache found" fi # Check for old venv if [[ -d "venv" ]]; then print_warning "Old 'venv' directory still exists!" VENV_SIZE=$(get_size "venv") echo "📦 Old venv size: $VENV_SIZE" else print_success "No old 'venv' directory found" fi # Check for requirements.txt if [[ -f "requirements.txt" ]]; then print_warning "requirements.txt still exists (should be removed after migration)" else print_success "requirements.txt already removed" fi echo "" # ============================================================================= # Step 2: UV Installation Check # ============================================================================= echo -e "${BLUE}🔧 UV Installation Check${NC}" echo "----------------------------" # Add UV to PATH if it exists export PATH="$HOME/.local/bin:$PATH" if command_exists uv; then UV_VERSION=$(uv --version 2>/dev/null | head -1) print_success "UV installed: $UV_VERSION" else print_error "UV not found! Installing UV..." if command_exists curl; then curl -LsSf https://astral.sh/uv/install.sh | sh # Add to PATH for this session export PATH="$HOME/.local/bin:$PATH" if command_exists uv; then UV_VERSION=$(uv --version 2>/dev/null | head -1) print_success "UV installed successfully: $UV_VERSION" else print_error "UV installation failed!" exit 1 fi else print_error "curl not found! Please install UV manually." exit 1 fi fi echo "" # ============================================================================= # Step 3: Cache Cleanup (Robust Version) # ============================================================================= echo -e "${BLUE}🧹 Cache Cleanup${NC}" echo "-------------------" # Ask for confirmation unless --force flag is provided if [[ "$1" != "--force" ]]; then echo "This will delete:" echo " - $PYCACHE_DIRS __pycache__ directories" echo " - $PYC_FILES .pyc files" echo " - .pytest_cache directory (if exists)" echo "" read -p "Continue with cleanup? (y/N): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then print_warning "Cleanup cancelled by user" exit 0 fi fi print_info "Starting cleanup (using robust method for large file counts)..." # Method 1: Use xargs for better handling of large file lists DELETED_DIRS=0 DELETED_FILES=0 # Clean __pycache__ directories in batches print_info "Cleaning __pycache__ directories..." if find . -path "./.venv" -prune -o -path "./venv" -prune -o -name "__pycache__" -type d -print0 2>/dev/null | xargs -0 -r rm -rf; then DELETED_DIRS=$(echo "$PYCACHE_DIRS") print_success "Cleaned $DELETED_DIRS cache directories" else print_warning "Some cache directories could not be deleted (may be permission issues)" fi # Clean .pyc files in batches print_info "Cleaning .pyc files..." if find . -path "./.venv" -prune -o -path "./venv" -prune -o -name "*.pyc" -type f -print0 2>/dev/null | xargs -0 -r rm -f; then DELETED_FILES=$(echo "$PYC_FILES") print_success "Cleaned $DELETED_FILES .pyc files" else print_warning "Some .pyc files could not be deleted" fi # Clean .pyo files print_info "Cleaning .pyo files..." find . -path "./.venv" -prune -o -path "./venv" -prune -o -name "*.pyo" -type f -print0 2>/dev/null | xargs -0 -r rm -f # Remove pytest cache if [[ -d ".pytest_cache" ]]; then if rm -rf ".pytest_cache" 2>/dev/null; then print_success "Removed .pytest_cache directory" else print_warning "Could not remove .pytest_cache directory" fi fi print_success "Cleanup phase completed!" echo "" # ============================================================================= # Step 4: UV Environment Setup # ============================================================================= echo -e "${BLUE}🔍 UV Environment Setup${NC}" echo "------------------------" # Check if pyproject.toml exists if [[ ! -f "pyproject.toml" ]]; then print_warning "No pyproject.toml found. Creating basic one..." cat > pyproject.toml << 'EOF' [project] name = "trading-bot" version = "1.0.0" requires-python = ">=3.8" dependencies = [] [build-system] requires = ["hatchling"] build-backend = "hatchling.build" EOF print_info "Created basic pyproject.toml - you may need to add your dependencies" fi # Create/sync UV environment print_info "Setting up UV environment..." if uv sync; then print_success "UV environment ready" else print_error "UV sync failed!" print_info "Trying alternative setup..." if uv venv && uv pip install -r requirements.txt 2>/dev/null; then print_success "UV environment created with fallback method" else print_error "Could not create UV environment" exit 1 fi fi # Test imports print_info "Testing environment..." if uv run python -c "print('UV environment working!')" 2>/dev/null; then print_success "UV environment functional" else print_warning "UV environment may have issues" fi echo "" # ============================================================================= # Step 5: Old Files Cleanup (Optional) # ============================================================================= echo -e "${BLUE}🗑️ Old Files Cleanup${NC}" echo "-----------------------" # Check for old venv directory if [[ -d "venv" ]]; then VENV_SIZE=$(get_size "venv") print_warning "Old 'venv' directory found (${VENV_SIZE})" if [[ "$1" != "--force" ]]; then read -p "Delete old 'venv' directory? (y/N): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then if rm -rf "venv" 2>/dev/null; then print_success "Removed old 'venv' directory" else print_warning "Could not remove old 'venv' directory (check permissions)" fi else print_warning "Keeping old 'venv' directory" fi else if rm -rf "venv" 2>/dev/null; then print_success "Removed old 'venv' directory" else print_warning "Could not remove old 'venv' directory" fi fi else print_success "No old 'venv' directory found" fi echo "" # ============================================================================= # Final Summary # ============================================================================= echo -e "${GREEN}🎉 Migration Summary${NC}" echo "=====================" echo "" print_success "UV migration completed!" echo "" echo "📋 What was done:" echo " ✅ Cleaned up cache files and directories" echo " ✅ Installed UV package manager" echo " ✅ Set up UV environment" echo "" echo "🚀 Next steps:" echo " • Test: uv run python --version" echo " • Run bot: uv run python trading_bot.py" echo " • Add packages: uv add package_name" echo "" echo "🔧 UV Quick Commands:" echo " uv sync # Sync dependencies" echo " uv add requests # Add package" echo " uv run python script.py # Run with UV" echo "" print_success "Migration complete! 🚀"