Update code via agent code generation

This commit is contained in:
Automated Action 2025-06-19 17:47:24 +00:00
parent 5dca451d03
commit 8d9d157c14
14 changed files with 245 additions and 35 deletions

97
alembic.ini Normal file
View File

@ -0,0 +1,97 @@
# A generic, single database configuration.
[alembic]
# path to migration scripts
script_location = alembic
# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
# Uncomment the line below if you want the files to be prepended with date and time
# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s
# sys.path path, will be prepended to sys.path if present.
# defaults to the current working directory.
prepend_sys_path = .
# timezone to use when rendering the date within the migration file
# as well as the filename.
# If specified, requires the python-dateutil library that can be
# installed by adding `alembic[tz]` to the pip requirements
# string value is passed to dateutil.tz.gettz()
# leave blank for localtime
# timezone =
# max length of characters to apply to the
# "slug" field
# truncate_slug_length = 40
# set to 'true' to run the environment during
# the 'revision' command, regardless of autogenerate
# revision_environment = false
# set to 'true' to allow .pyc and .pyo files without
# a source .py file to be detected as revisions in the
# versions/ directory
# sourceless = false
# version path separator; As mentioned above, this is the character used to split
# version_locations. The default within new alembic.ini files is "os", which uses
# os.pathsep. If this key is omitted entirely, it falls back to the legacy
# behavior of splitting on spaces and/or commas.
# Valid values for version_path_separator are:
#
# version_path_separator = :
# version_path_separator = ;
# version_path_separator = space
version_path_separator = os
# the output encoding used when revision files
# are written from script.py.mako
# output_encoding = utf-8
sqlalchemy.url = sqlite:////app/storage/db/db.sqlite
[post_write_hooks]
# post_write_hooks defines scripts or Python functions that are run
# on newly generated revision scripts. See the documentation for further
# detail and examples
# format using "black" - use the console_scripts runner, against the "black" entrypoint
# hooks = black
# black.type = console_scripts
# black.entrypoint = black
# black.options = -l 79 REVISION_SCRIPT_FILENAME
# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = WARN
handlers = console
qualname =
[logger_sqlalchemy]
level = WARN
handlers =
qualname = sqlalchemy.engine
[logger_alembic]
level = INFO
handlers =
qualname = alembic
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S

0
app/api/__init__.py Normal file
View File

View File

0
app/api/v1/__init__.py Normal file
View File

12
app/api/v1/api.py Normal file
View File

@ -0,0 +1,12 @@
from fastapi import APIRouter
# Create the main API router
api_router = APIRouter()
# For now, just include a basic health endpoint under API
@api_router.get("/health")
async def api_health():
"""
API health check endpoint.
"""
return {"status": "healthy", "api_version": "v1"}

0
app/core/__init__.py Normal file
View File

18
app/core/config.py Normal file
View File

@ -0,0 +1,18 @@
from pydantic_settings import BaseSettings
from pathlib import Path
class Settings(BaseSettings):
PROJECT_NAME: str = "Todo API"
PROJECT_VERSION: str = "1.0.0"
# Database settings
DB_DIR: Path = Path("/app/storage/db")
SQLALCHEMY_DATABASE_URL: str = f"sqlite:///{DB_DIR}/db.sqlite"
class Config:
env_file = ".env"
case_sensitive = True
settings = Settings()

0
app/crud/__init__.py Normal file
View File

63
app/crud/todo.py Normal file
View File

@ -0,0 +1,63 @@
from sqlalchemy.orm import Session
from app.models.todo import Todo
from app.schemas.todo import TodoCreate, TodoUpdate
from typing import List, Optional
def get_todo(db: Session, todo_id: int) -> Optional[Todo]:
"""
Get a single todo by ID.
"""
return db.query(Todo).filter(Todo.id == todo_id).first()
def get_todos(db: Session, skip: int = 0, limit: int = 100) -> List[Todo]:
"""
Get all todos with pagination.
"""
return db.query(Todo).offset(skip).limit(limit).all()
def create_todo(db: Session, todo: TodoCreate) -> Todo:
"""
Create a new todo.
"""
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
def update_todo(db: Session, todo_id: int, todo_update: TodoUpdate) -> Optional[Todo]:
"""
Update an existing todo.
"""
db_todo = db.query(Todo).filter(Todo.id == todo_id).first()
if not db_todo:
return None
update_data = todo_update.model_dump(exclude_unset=True)
for field, value in update_data.items():
setattr(db_todo, field, value)
db.commit()
db.refresh(db_todo)
return db_todo
def delete_todo(db: Session, todo_id: int) -> bool:
"""
Delete a todo by ID.
"""
db_todo = db.query(Todo).filter(Todo.id == todo_id).first()
if not db_todo:
return False
db.delete(db_todo)
db.commit()
return True

View File

@ -1,19 +1,7 @@
from sqlalchemy import create_engine
"""
Database base configuration.
"""
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from pathlib import Path
# Database setup
DB_DIR = Path("/app/storage/db")
DB_DIR.mkdir(parents=True, exist_ok=True)
SQLALCHEMY_DATABASE_URL = f"sqlite:///{DB_DIR}/db.sqlite"
engine = create_engine(
SQLALCHEMY_DATABASE_URL,
connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
# SQLAlchemy Base class for all models
Base = declarative_base()

View File

@ -1,13 +1,18 @@
from sqlalchemy.orm import Session
from app.db.base import SessionLocal
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from pathlib import Path
from app.core.config import settings
def get_db() -> Session:
"""
Dependency to get database session.
"""
db = SessionLocal()
try:
yield db
finally:
db.close()
# Create storage directory if it doesn't exist
DB_DIR = Path("/app/storage/db")
DB_DIR.mkdir(parents=True, exist_ok=True)
SQLALCHEMY_DATABASE_URL = f"sqlite:///{DB_DIR}/db.sqlite"
engine = create_engine(
SQLALCHEMY_DATABASE_URL,
connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

View File

@ -1,15 +1,14 @@
from datetime import datetime
from sqlalchemy import Column, Integer, String, Text, Boolean, DateTime
from sqlalchemy import Column, Integer, String, Boolean, DateTime
from sqlalchemy.sql import func
from app.db.base import Base
class Todo(Base):
__tablename__ = "todos"
id = Column(Integer, primary_key=True, index=True)
title = Column(String(255), nullable=False)
description = Column(Text, nullable=True)
title = Column(String(255), nullable=False, index=True)
description = Column(String(1000), nullable=True)
completed = Column(Boolean, default=False, nullable=False)
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())

0
app/schemas/__init__.py Normal file
View File

28
app/schemas/todo.py Normal file
View File

@ -0,0 +1,28 @@
from pydantic import BaseModel, Field
from datetime import datetime
from typing import Optional
class TodoBase(BaseModel):
title: str = Field(..., min_length=1, max_length=255, description="Title of the todo item")
description: Optional[str] = Field(None, max_length=1000, description="Description of the todo item")
completed: bool = Field(False, description="Whether the todo item is completed")
class TodoCreate(TodoBase):
pass
class TodoUpdate(BaseModel):
title: Optional[str] = Field(None, min_length=1, max_length=255, description="Title of the todo item")
description: Optional[str] = Field(None, max_length=1000, description="Description of the todo item")
completed: Optional[bool] = Field(None, description="Whether the todo item is completed")
class TodoResponse(TodoBase):
id: int
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True