"""Utility to reset development Postgres schema artifacts. This script drops managed tables and enum types created by `scripts.init_db`. It is intended for local development only; it refuses to run if CALMINER_ENV indicates production or staging. The operation is idempotent: missing objects are ignored. Use with caution. """ from __future__ import annotations import logging import os from dataclasses import dataclass from typing import Iterable from sqlalchemy import text from sqlalchemy.engine import Engine from config.database import DATABASE_URL from scripts.init_db import ENUM_DEFINITIONS, _create_engine logger = logging.getLogger(__name__) @dataclass(slots=True) class ResetOptions: drop_tables: bool = True drop_enums: bool = True MANAGED_TABLES: tuple[str, ...] = ( "simulation_parameters", "financial_inputs", "scenarios", "projects", "pricing_impurity_settings", "pricing_metal_settings", "pricing_settings", "user_roles", "users", "roles", ) FORBIDDEN_ENVIRONMENTS: set[str] = {"production", "staging", "prod", "stage"} def _ensure_safe_environment() -> None: env = os.getenv("CALMINER_ENV", "development").lower() if env in FORBIDDEN_ENVIRONMENTS: raise RuntimeError( f"Refusing to reset database in environment '{env}'. " "Set CALMINER_ENV to 'development' to proceed." ) def _drop_tables(engine: Engine, tables: Iterable[str]) -> None: if not tables: return with engine.begin() as conn: for table in tables: logger.info("Dropping table if exists: %s", table) conn.execute(text(f"DROP TABLE IF EXISTS {table} CASCADE")) def _drop_enums(engine: Engine, enum_names: Iterable[str]) -> None: if not enum_names: return with engine.begin() as conn: for enum_name in enum_names: logger.info("Dropping enum type if exists: %s", enum_name) conn.execute(text(f"DROP TYPE IF EXISTS {enum_name} CASCADE")) def reset_database(*, options: ResetOptions | None = None, database_url: str | None = None) -> None: """Drop managed tables and enums for a clean slate.""" _ensure_safe_environment() opts = options or ResetOptions() engine = _create_engine(database_url or DATABASE_URL) if opts.drop_tables: _drop_tables(engine, MANAGED_TABLES) if opts.drop_enums: _drop_enums(engine, ENUM_DEFINITIONS.keys()) logger.info("Database reset complete") if __name__ == "__main__": logging.basicConfig(level=logging.INFO) reset_database()