176 lines
5.1 KiB
Python
176 lines
5.1 KiB
Python
# scripts/setup_dev.py
|
|
# !/usr/bin/env python3
|
|
"""Development environment setup script."""
|
|
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
def run_command(command, description):
|
|
"""Run a shell command and handle errors."""
|
|
print(f"Running: {description}")
|
|
try:
|
|
subprocess.run(command, shell=True, check=True)
|
|
print(f"✅ {description} completed successfully")
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"❌ {description} failed: {e}")
|
|
return False
|
|
return True
|
|
|
|
|
|
def setup_alembic():
|
|
"""Set up Alembic for database migrations."""
|
|
alembic_dir = Path("alembic")
|
|
|
|
# Check if alembic directory exists and has necessary files
|
|
if not alembic_dir.exists() or not (alembic_dir / "script.py.mako").exists():
|
|
print("📝 Initializing Alembic...")
|
|
if alembic_dir.exists():
|
|
# Remove incomplete alembic directory
|
|
import shutil
|
|
|
|
shutil.rmtree(alembic_dir)
|
|
|
|
if not run_command("alembic init alembic", "Initializing Alembic"):
|
|
return False
|
|
|
|
# Update alembic/env.py with proper configuration
|
|
env_py_content = '''from logging.config import fileConfig
|
|
from sqlalchemy import engine_from_config, pool
|
|
from alembic import context
|
|
import os
|
|
import sys
|
|
|
|
# Add your project directory to the Python path
|
|
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
|
|
|
|
from models.database import Base
|
|
from config.settings import settings
|
|
|
|
# Alembic Config object
|
|
config = context.config
|
|
|
|
# Override sqlalchemy.url with our settings
|
|
config.set_main_option("sqlalchemy.url", settings.database_url)
|
|
|
|
if config.config_file_name is not None:
|
|
fileConfig(config.config_file_name)
|
|
|
|
target_metadata = Base.metadata
|
|
|
|
def run_migrations_offline() -> None:
|
|
"""Run migrations in 'offline' mode."""
|
|
url = config.get_main_option("sqlalchemy.url")
|
|
context.configure(
|
|
url=url,
|
|
target_metadata=target_metadata,
|
|
literal_binds=True,
|
|
dialect_opts={"paramstyle": "named"},
|
|
)
|
|
|
|
with context.begin_transaction():
|
|
context.run_migrations()
|
|
|
|
def run_migrations_online() -> None:
|
|
"""Run migrations in 'online' mode."""
|
|
connectable = engine_from_config(
|
|
config.get_section(config.config_ini_section, {}),
|
|
prefix="sqlalchemy.",
|
|
poolclass=pool.NullPool,
|
|
)
|
|
|
|
with connectable.connect() as connection:
|
|
context.configure(
|
|
connection=connection, target_metadata=target_metadata
|
|
)
|
|
|
|
with context.begin_transaction():
|
|
context.run_migrations()
|
|
|
|
if context.is_offline_mode():
|
|
run_migrations_offline()
|
|
else:
|
|
run_migrations_online()
|
|
'''
|
|
|
|
env_py_path = alembic_dir / "env.py"
|
|
env_py_path.write_text(env_py_content)
|
|
print("✅ Updated alembic/env.py with project configuration")
|
|
|
|
return True
|
|
|
|
|
|
def setup_environment():
|
|
"""Set up the development environment."""
|
|
print("🚀 Setting up ecommerce API development environment...")
|
|
|
|
# Check Python version
|
|
if sys.version_info < (3, 8):
|
|
print("❌ Python 3.8+ is required")
|
|
return False
|
|
|
|
# Create .env file if it doesn't exist
|
|
env_file = Path(".env")
|
|
env_example = Path(".env.example")
|
|
|
|
if not env_file.exists() and env_example.exists():
|
|
print("📝 Creating .env file from .env.example...")
|
|
env_file.write_text(env_example.read_text())
|
|
elif not env_file.exists():
|
|
print("📝 Creating default .env file...")
|
|
default_env = """DATABASE_URL=sqlite:///./ecommerce.db
|
|
JWT_SECRET_KEY=development-secret-key-change-in-production
|
|
JWT_EXPIRE_HOURS=24
|
|
API_HOST=0.0.0.0
|
|
API_PORT=8000
|
|
DEBUG=True
|
|
RATE_LIMIT_ENABLED=True
|
|
DEFAULT_RATE_LIMIT=100
|
|
DEFAULT_WINDOW_SECONDS=3600
|
|
LOG_LEVEL=INFO
|
|
"""
|
|
env_file.write_text(default_env)
|
|
|
|
# Install dependencies
|
|
if not run_command("pip install -r requirements.txt", "Installing dependencies"):
|
|
return False
|
|
|
|
# Set up Alembic
|
|
if not setup_alembic():
|
|
print(
|
|
"⚠️ Alembic setup failed. You'll need to set up database migrations manually."
|
|
)
|
|
return False
|
|
|
|
# Create initial migration
|
|
if not run_command(
|
|
'alembic revision --autogenerate -m "Initial migration"',
|
|
"Creating initial migration",
|
|
):
|
|
print("⚠️ Initial migration creation failed. Check your database models.")
|
|
|
|
# Apply migrations
|
|
if not run_command("alembic upgrade head", "Setting up database"):
|
|
print(
|
|
"⚠️ Database setup failed. Make sure your DATABASE_URL is correct in .env"
|
|
)
|
|
|
|
# Run tests
|
|
if not run_command("pytest", "Running tests"):
|
|
print("⚠️ Some tests failed. Check the output above.")
|
|
|
|
print("\n🎉 Development environment setup complete!")
|
|
print("To start the development server, run:")
|
|
print(" uvicorn main:app --reload")
|
|
print("\nDatabase commands:")
|
|
print(' alembic revision --autogenerate -m "Description" # Create migration')
|
|
print(" alembic upgrade head # Apply migrations")
|
|
print(" alembic current # Check status")
|
|
|
|
return True
|
|
|
|
|
|
if __name__ == "__main__":
|
|
setup_environment()
|