campp-mlx-converter / validate_project.py
BMP's picture
Add CAM++ model implementation and conversion utilities
368806f
#!/usr/bin/env python3
"""
Pre-deployment validation script
Checks that the project is ready for HF deployment
"""
import os
import sys
from pathlib import Path
def check_file_exists(filename, description):
"""Check if a file exists and return status"""
if os.path.exists(filename):
size = os.path.getsize(filename)
print(f"โœ… {filename} ({size:,} bytes) - {description}")
return True
else:
print(f"โŒ Missing: {filename} - {description}")
return False
def check_file_content(filename, required_content):
"""Check if file contains required content"""
try:
with open(filename, 'r', encoding='utf-8') as f:
content = f.read()
missing = []
for item in required_content:
if item not in content:
missing.append(item)
if missing:
print(f"โš ๏ธ {filename} missing: {', '.join(missing)}")
return False
else:
print(f"โœ… {filename} content validated")
return True
except Exception as e:
print(f"โŒ Error reading {filename}: {e}")
return False
def validate_project():
"""Run all validation checks"""
print("Pre-Deployment Validation")
print("=" * 40)
all_good = True
# Required files
print("\n๐Ÿ“ File Structure Check:")
required_files = [
("docs/README.md", "HF Space configuration and docs"),
("src/app.py", "Main Gradio application"),
("src/mlx_campp.py", "MLX model implementation"),
("src/conversion_utils.py", "Conversion utilities"),
("requirements.txt", "Dependencies"),
("tests/test_converter.py", "Test suite"),
(".gitignore", "Git ignore patterns"),
("docs/DEPLOYMENT_GUIDE.md", "Deployment instructions")
]
for filename, desc in required_files:
if not check_file_exists(filename, desc):
all_good = False
# Check README.md has HF Space configuration
print("\n๐ŸŽ›๏ธ HF Space Configuration Check:")
readme_required = [
"title: CAM++ MLX Converter",
"emoji: ๐ŸŽค",
"sdk: gradio",
"app_file: app.py"
]
if not check_file_content("docs/README.md", readme_required):
all_good = False
# Check app.py has required components
print("\nโš™๏ธ App.py Component Check:")
app_required = [
"import gradio as gr",
"from mlx_campp import CAMPPModel",
"from conversion_utils import ConversionUtils",
"def convert_model",
"interface.launch()"
]
if not check_file_content("src/app.py", app_required):
all_good = False
# Check requirements.txt has essential packages
print("\n๐Ÿ“ฆ Dependencies Check:")
req_required = [
"mlx>=0.19.0",
"gradio>=4.44.0",
"huggingface_hub",
"torch",
"numpy"
]
if not check_file_content("requirements.txt", req_required):
all_good = False
# Check for common issues
print("\nCommon Issues Check:")
# Check if any Python files have import errors
try:
# Try importing without actually running MLX (which might not be installed)
import ast
for py_file in ["src/app.py", "src/mlx_campp.py", "src/conversion_utils.py"]:
try:
with open(py_file, 'r') as f:
ast.parse(f.read())
print(f"โœ… {py_file} syntax is valid")
except SyntaxError as e:
print(f"โŒ Syntax error in {py_file}: {e}")
all_good = False
except Exception as e:
print(f"โš ๏ธ Could not validate Python syntax: {e}")
# File size checks
print("\n๐Ÿ“ File Size Check:")
for filename in ["src/app.py", "src/mlx_campp.py", "src/conversion_utils.py"]:
if os.path.exists(filename):
size = os.path.getsize(filename)
if size < 1000: # Less than 1KB is suspicious
print(f"โš ๏ธ {filename} seems too small ({size} bytes)")
elif size > 100000: # More than 100KB is unusual for these files
print(f"โš ๏ธ {filename} seems very large ({size} bytes)")
else:
print(f"โœ… {filename} size looks good ({size:,} bytes)")
# Check for secrets/tokens in files
print("\n๐Ÿ” Security Check:")
security_ok = True
sensitive_patterns = ["hf_", "token", "password", "secret", "key"]
for py_file in ["src/app.py", "src/mlx_campp.py", "src/conversion_utils.py"]:
try:
with open(py_file, 'r') as f:
content = f.read().lower()
for pattern in sensitive_patterns:
if pattern in content and "example" not in content:
# Check if it's actually a hardcoded secret
lines = content.split('\n')
for i, line in enumerate(lines):
if pattern in line and '=' in line and len(line.split('=')[1].strip().strip('"\'')) > 10:
print(f"โš ๏ธ Possible hardcoded secret in {py_file}:{i+1}")
security_ok = False
break
except Exception:
pass
if security_ok:
print("โœ… No hardcoded secrets detected")
# Final assessment
print("\n" + "=" * 40)
if all_good:
print("๐ŸŽ‰ PROJECT IS READY FOR DEPLOYMENT!")
print("\nNext steps:")
print("1. Run: chmod +x deploy.sh && ./deploy.sh")
print("2. Or follow DEPLOYMENT_GUIDE.md for manual deployment")
print("3. Monitor your HF Space after deployment")
return True
else:
print("โŒ PROJECT NEEDS FIXES BEFORE DEPLOYMENT")
print("\nPlease fix the issues above before deploying.")
return False
def show_deployment_preview():
"""Show what the deployed space will look like"""
print("\n๐ŸŒ Deployment Preview:")
print("Your HF Space will have:")
print("โ€ข URL: https://your-username-campp-mlx-converter.hf.space")
print("โ€ข Title: ๐ŸŽค CAM++ MLX Converter")
print("โ€ข Interface: Clean Gradio form for model conversion")
print("โ€ข Features: PyTorchโ†’MLX conversion with quantization")
print("โ€ข Output: Models uploaded to mlx-community automatically")
if __name__ == "__main__":
print("CAM++ MLX Converter - Pre-Deployment Validation")
print("=" * 50)
is_valid = validate_project()
if is_valid:
show_deployment_preview()
sys.exit(0)
else:
sys.exit(1)