from fastapi import FastAPI, Depends, HTTPException, status from pathlib import Path from app.database import get_db, create_tables from app.models import Todo from app.schemas import TodoCreate, TodoResponse, HealthResponse from sqlalchemy.orm import Session from sqlalchemy.exc import SQLAlchemyError from typing import List app = FastAPI( title="SimpleTodoApp", description="A simple Todo application API", version="0.1.0" ) @app.on_event("startup") async def startup(): create_tables() @app.get("/health", response_model=HealthResponse) async def health_check(): return {"status": "healthy"} @app.post("/todos", response_model=TodoResponse, status_code=status.HTTP_201_CREATED) def create_todo(todo: TodoCreate, db: Session = Depends(get_db)): try: db_todo = Todo(title=todo.title, description=todo.description, completed=todo.completed) db.add(db_todo) db.commit() db.refresh(db_todo) return db_todo except SQLAlchemyError as e: db.rollback() raise HTTPException(status_code=500, detail=f"Database error: {str(e)}") @app.get("/todos", response_model=List[TodoResponse]) def read_todos(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): try: todos = db.query(Todo).offset(skip).limit(limit).all() return todos except SQLAlchemyError as e: raise HTTPException(status_code=500, detail=f"Database error: {str(e)}") @app.get("/todos/{todo_id}", response_model=TodoResponse) def read_todo(todo_id: int, db: Session = Depends(get_db)): try: todo = db.query(Todo).filter(Todo.id == todo_id).first() if todo is None: raise HTTPException(status_code=404, detail="Todo not found") return todo except SQLAlchemyError as e: raise HTTPException(status_code=500, detail=f"Database error: {str(e)}") @app.put("/todos/{todo_id}", response_model=TodoResponse) def update_todo(todo_id: int, todo: TodoCreate, db: Session = Depends(get_db)): try: db_todo = db.query(Todo).filter(Todo.id == todo_id).first() if db_todo is None: raise HTTPException(status_code=404, detail="Todo not found") update_data = todo.model_dump(exclude_unset=True) for key, value in update_data.items(): setattr(db_todo, key, value) db.commit() db.refresh(db_todo) return db_todo except SQLAlchemyError as e: db.rollback() raise HTTPException(status_code=500, detail=f"Database error: {str(e)}") @app.delete("/todos/{todo_id}", status_code=status.HTTP_204_NO_CONTENT) def delete_todo(todo_id: int, db: Session = Depends(get_db)): try: db_todo = db.query(Todo).filter(Todo.id == todo_id).first() if db_todo is None: raise HTTPException(status_code=404, detail="Todo not found") db.delete(db_todo) db.commit() return None except SQLAlchemyError as e: db.rollback() raise HTTPException(status_code=500, detail=f"Database error: {str(e)}") if __name__ == "__main__": import uvicorn uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)