feat: add homepage
This commit is contained in:
118
src/plesna_gerance/database/connection.py
Normal file
118
src/plesna_gerance/database/connection.py
Normal file
@@ -0,0 +1,118 @@
|
||||
"""Database connection management for SQLite."""
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Generator
|
||||
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import Session, sessionmaker
|
||||
|
||||
from .models import Base
|
||||
|
||||
|
||||
# Default database path - relative to project root
|
||||
def _get_project_root() -> Path:
|
||||
"""Find project root by looking for pyproject.toml."""
|
||||
current = Path(__file__).resolve()
|
||||
for parent in current.parents:
|
||||
if (parent / "pyproject.toml").exists():
|
||||
return parent
|
||||
# Fallback to home directory if not found
|
||||
return Path.home() / ".plesna_gerance"
|
||||
|
||||
|
||||
DEFAULT_DB_PATH = _get_project_root() / "data" / "database.sqlite"
|
||||
|
||||
# Global engine instance
|
||||
_engine = None
|
||||
_SessionLocal = None
|
||||
|
||||
|
||||
def get_db_path() -> Path:
|
||||
"""Get database path from environment or default."""
|
||||
env_path = os.environ.get("PLESNA_DB_PATH")
|
||||
if env_path:
|
||||
return Path(env_path)
|
||||
return DEFAULT_DB_PATH
|
||||
|
||||
|
||||
def get_engine(db_path: Path | None = None):
|
||||
"""Get or create SQLAlchemy engine (singleton pattern)."""
|
||||
global _engine
|
||||
|
||||
if _engine is None:
|
||||
if db_path is None:
|
||||
db_path = get_db_path()
|
||||
|
||||
# Create parent directory if needed
|
||||
db_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Create engine with SQLite
|
||||
_engine = create_engine(
|
||||
f"sqlite:///{db_path}",
|
||||
echo=False, # Set to True for SQL debugging
|
||||
connect_args={"check_same_thread": False}, # Required for FastAPI
|
||||
)
|
||||
|
||||
return _engine
|
||||
|
||||
|
||||
def get_session_factory(engine=None):
|
||||
"""Get or create session factory."""
|
||||
global _SessionLocal
|
||||
|
||||
if _SessionLocal is None:
|
||||
if engine is None:
|
||||
engine = get_engine()
|
||||
_SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
|
||||
return _SessionLocal
|
||||
|
||||
|
||||
def get_session() -> Generator[Session, None, None]:
|
||||
"""Dependency for FastAPI to get database session."""
|
||||
SessionLocal = get_session_factory()
|
||||
session = SessionLocal()
|
||||
try:
|
||||
yield session
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
|
||||
def init_db(db_path: Path | None = None) -> Path:
|
||||
"""Initialize database: create all tables.
|
||||
|
||||
Returns the path to the database file.
|
||||
"""
|
||||
if db_path is None:
|
||||
db_path = get_db_path()
|
||||
|
||||
# Reset globals to use new path
|
||||
global _engine, _SessionLocal
|
||||
_engine = None
|
||||
_SessionLocal = None
|
||||
|
||||
# Create parent directory
|
||||
db_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Create engine and tables
|
||||
engine = create_engine(
|
||||
f"sqlite:///{db_path}", echo=False, connect_args={"check_same_thread": False}
|
||||
)
|
||||
|
||||
Base.metadata.create_all(bind=engine)
|
||||
|
||||
# Update globals
|
||||
_engine = engine
|
||||
_SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
|
||||
return db_path
|
||||
|
||||
|
||||
def reset_connection():
|
||||
"""Reset global connection (useful for testing)."""
|
||||
global _engine, _SessionLocal
|
||||
if _engine is not None:
|
||||
_engine.dispose()
|
||||
_engine = None
|
||||
_SessionLocal = None
|
||||
Reference in New Issue
Block a user