From 7f3b71b69c33d186846ff5ceeb6e55b63421b179 Mon Sep 17 00:00:00 2001 From: demo-bot Date: Thu, 7 May 2026 14:55:52 +0000 Subject: [PATCH] feat(scaffold): add app/main.py [skip ci] --- app/main.py | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 app/main.py diff --git a/app/main.py b/app/main.py new file mode 100644 index 0000000..2bfac15 --- /dev/null +++ b/app/main.py @@ -0,0 +1,90 @@ +from __future__ import annotations + +from threading import Lock +from typing import Optional + +from fastapi import FastAPI, HTTPException +from prometheus_fastapi_instrumentator import Instrumentator +from pydantic import BaseModel + +app = FastAPI( + title="sonar-test-pyt2", + description="sonar-test-pyt2", + version="0.1.0", +) + +# Expose /metrics for Prometheus scraping +Instrumentator().instrument(app).expose(app) + + +# --------------------------------------------------------------------------- +# Domain model +# --------------------------------------------------------------------------- +class ItemRequest(BaseModel): + name: str + description: str = "" + + +class Item(BaseModel): + id: int + name: str + description: str + + +# --------------------------------------------------------------------------- +# In-memory store (thread-safe) +# --------------------------------------------------------------------------- +_store: dict[int, Item] = {} +_counter = 0 +_lock = Lock() + + +def _next_id() -> int: + global _counter + with _lock: + _counter += 1 + return _counter + + +# --------------------------------------------------------------------------- +# Routes +# --------------------------------------------------------------------------- +@app.get("/health", tags=["observability"]) +def health() -> dict: + return {"status": "UP"} + + +@app.get("/api/items", response_model=list[Item], tags=["items"]) +def list_items(): + return list(_store.values()) + + +@app.post("/api/items", response_model=Item, status_code=201, tags=["items"]) +def create_item(body: ItemRequest): + item = Item(id=_next_id(), name=body.name, description=body.description) + _store[item.id] = item + return item + + +@app.get("/api/items/{item_id}", response_model=Item, tags=["items"]) +def get_item(item_id: int): + item = _store.get(item_id) + if item is None: + raise HTTPException(status_code=404, detail="Item not found") + return item + + +@app.put("/api/items/{item_id}", response_model=Item, tags=["items"]) +def update_item(item_id: int, body: ItemRequest): + item = _store.get(item_id) + if item is None: + raise HTTPException(status_code=404, detail="Item not found") + updated = Item(id=item_id, name=body.name, description=body.description) + _store[item_id] = updated + return updated + + +@app.delete("/api/items/{item_id}", tags=["items"]) +def delete_item(item_id: int): + _store.pop(item_id, None) + return {"deleted": item_id}