import os from sqlalchemy import create_engine from sqlalchemy.engine import URL from sqlalchemy.orm import DeclarativeBase, Session, sessionmaker def build_database_url() -> URL | str: """Prefer DATABASE_URL; otherwise build a safely escaped URL from parts. Passwords are passed as URL components (not string interpolation), so characters like '@', ':', '/', '#' and '%' cannot corrupt the hostname. """ database_url = os.environ.get("DATABASE_URL") if database_url: return database_url return URL.create( "postgresql+psycopg", username=os.environ.get("POSTGRES_USER", "time_track"), password=os.environ.get("POSTGRES_PASSWORD", ""), host=os.environ.get("POSTGRES_HOST", "localhost"), port=int(os.environ.get("POSTGRES_PORT", "5432")), database=os.environ.get("POSTGRES_DB", "time_track"), ) engine = create_engine(build_database_url(), pool_pre_ping=True) SessionLocal = sessionmaker(bind=engine, autocommit=False, autoflush=False) class Base(DeclarativeBase): pass def get_db(): db: Session = SessionLocal() try: yield db finally: db.close()