# scripts/setup_dev.py # !/usr/bin/env python3 """Development environment setup script""" import os import sys import subprocess 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_models 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()