#!/usr/bin/env python3 """ Final verification script to ensure all changes have been properly applied to convert the project from Gradio to FastAPI and fix Hugging Face Spaces deployment issues. """ import os import re import sys def check_file_exists(filepath): """Check if a file exists""" if os.path.exists(filepath): print(f"✓ {filepath} exists") return True else: print(f"✗ {filepath} does not exist") return False def check_dockerfile_content(): """Check Dockerfile content for key fixes""" dockerfile_path = "Dockerfile" if not check_file_exists(dockerfile_path): return False with open(dockerfile_path, 'r', encoding='utf-8') as f: content = f.read() # Check for conditional script execution if 'if [ -f "arabic_fonts_setup.sh" ]' in content: print("✓ Dockerfile has conditional Arabic font setup script execution") else: print("✗ Dockerfile missing conditional Arabic font setup script execution") return False # Check for Java dependencies if 'libreoffice-java-common' in content and 'openjdk-11-jre-headless' in content: print("✓ Dockerfile includes Java dependencies for LibreOffice") else: print("✗ Dockerfile missing Java dependencies for LibreOffice") return False return True def check_dockerignore_content(): """Check .dockerignore content for key fixes""" dockerignore_path = ".dockerignore" if not check_file_exists(dockerignore_path): return False with open(dockerignore_path, 'r', encoding='utf-8') as f: content = f.read() # Check that requirements.txt is not excluded lines = content.split('\n') for line in lines: # Skip comments and empty lines if line.strip().startswith('#') or not line.strip(): continue # Check if the line excludes requirements.txt if 'requirements.txt' in line and not line.strip().startswith('#'): print("✗ .dockerignore explicitly excludes requirements.txt") return False print("✓ .dockerignore properly includes requirements.txt") return True def check_packages_content(): """Check packages.txt content for key fixes""" packages_path = "packages.txt" if not check_file_exists(packages_path): return False with open(packages_path, 'r', encoding='utf-8') as f: content = f.read() # Check for Java dependencies if 'libreoffice-java-common' in content and 'openjdk-11-jre-headless' in content: print("✓ packages.txt includes Java dependencies for LibreOffice") else: print("✗ packages.txt missing Java dependencies for LibreOffice") return False # Check for removed unavailable packages unavailable_packages = [ 'libreoffice-help-ar', 'fonts-noto-naskh', 'fonts-noto-kufi-arabic', 'fonts-amiri', 'fonts-scheherazade-new' ] removed_count = 0 for package in unavailable_packages: if package not in content: removed_count += 1 if removed_count == len(unavailable_packages): print("✓ packages.txt has removed all unavailable packages") else: print(f"✗ packages.txt still contains {len(unavailable_packages) - removed_count} unavailable packages") return False return True def check_requirements_content(): """Check requirements.txt content for FastAPI dependencies""" requirements_path = "requirements.txt" if not check_file_exists(requirements_path): return False with open(requirements_path, 'r', encoding='utf-8') as f: content = f.read() # Check for FastAPI dependencies if 'fastapi' in content and 'uvicorn' in content: print("✓ requirements.txt includes FastAPI dependencies") else: print("✗ requirements.txt missing FastAPI dependencies") return False # Check that Gradio is not present if 'gradio' not in content: print("✓ requirements.txt does not include Gradio") else: print("✗ requirements.txt still includes Gradio") return False return True def check_readme_content(): """Check README.md content for FastAPI references""" readme_path = "README.md" if not check_file_exists(readme_path): return False with open(readme_path, 'r', encoding='utf-8') as f: content = f.read() # Check that references to FastAPI are present if 'FastAPI' in content: print("✓ README.md mentions FastAPI") else: print("✗ README.md does not mention FastAPI") return False return True def check_main_py_content(): """Check main.py content for FastAPI implementation""" main_path = "main.py" if not check_file_exists(main_path): return False with open(main_path, 'r', encoding='utf-8') as f: content = f.read() # Check for FastAPI imports and implementation if 'from fastapi' in content and 'FastAPI(' in content: print("✓ main.py implements FastAPI") else: print("✗ main.py does not implement FastAPI properly") return False # Check that Gradio is not present if 'gradio' not in content.lower(): print("✓ main.py does not include Gradio") else: print("✗ main.py still includes Gradio") return False return True def check_static_files(): """Check that static files exist for HTML frontend""" static_dir = "static" if not os.path.exists(static_dir): print("✗ static directory does not exist") return False # Check for index.html index_path = os.path.join(static_dir, "index.html") if check_file_exists(index_path): print("✓ static/index.html exists") else: return False # Since CSS and JS are inline in index.html, we don't need separate files print("✓ CSS and JavaScript are included inline in index.html") return True def main(): """Main verification function""" print("Starting final verification of project conversion...\n") checks = [ ("Dockerfile content", check_dockerfile_content), (".dockerignore content", check_dockerignore_content), ("packages.txt content", check_packages_content), ("requirements.txt content", check_requirements_content), ("README.md content", check_readme_content), ("main.py content", check_main_py_content), ("Static files", check_static_files) ] all_passed = True for check_name, check_func in checks: print(f"\nChecking {check_name}:") if not check_func(): all_passed = False print("\n" + "="*50) if all_passed: print("🎉 All verification checks passed!") print("The project has been successfully converted to FastAPI") print("and should deploy correctly to Hugging Face Spaces.") else: print("❌ Some verification checks failed.") print("Please review the issues above and make necessary corrections.") return all_passed if __name__ == "__main__": success = main() sys.exit(0 if success else 1)