......................... [100%] 25 passed in 0.66s score: 25/25 (100%)
import os
import uuid
from typing import List, Optional, Dict
from fastapi import FastAPI, HTTPException, Depends, Query, status, Header
from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field, validator
# --- Models ---
class User(BaseModel):
username: str
password: str
class LoginRequest(BaseModel):
username: str
password: str
class LoginResponse(BaseModel):
token: str
class Product(BaseModel):
id: int
name: str
price: float
stock: int
class OrderRequest(BaseModel):
product_id: int
quantity: int
@validator('quantity')
def quantity_must_be_positive(cls, v):
if v < 1:
raise ValueError('quantity must be at least 1')
return v
class Order(BaseModel):
id: int
product_id: int
quantity: int
total: float
username: str # Internal field to track owner
class OrderResponse(BaseModel):
id: int
product_id: int
quantity: int
total: float
# --- In-memory Data ---
users_db = {
"alice": "password123",
"bob": "hunter2"
}
# token -> username
tokens_db: Dict[str, str] = {}
products_db = [
{"id": 1, "name": "Laptop", "price": 999.99, "stock": 10},
{"id": 2, "name": "Mouse", "price": 25.50, "stock": 50},
{"id": 3, "name": "Keyboard", "price": 75.00, "stock": 15},
]
orders_db = []
order_id_counter = 1
# --- App Setup ---
app = FastAPI()
# --- Dependencies ---
def get_current_user(authorization: Optional[str] = Header(None)) -> str:
if not authorization or not authorization.startswith("Bearer "):
raise HTTPException(status_code=401, detail="Invalid or missing token")
token = authorization.split(" ")[1]
username = tokens_db.get(token)
if not username:
raise HTTPException(status_code=401, detail="Invalid or expired token")
return username
# Custom exception handler for validation errors to match requirements (400 with JSON)
@app.exception_handler(Exception)
async def universal_exception_handler(request, exc):
# This is a bit broad, let's refine it.
# FastAPI's default RequestValidationError returns 422.
# The prompt asks for 400 for malformed body.
return JSONResponse(
status_code=500,
content={"error": str(exc)},
)
# Overriding RequestValidationError to return 400 instead of 422
from fastapi.exceptions import RequestValidationError
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
return JSONResponse(
status_code=400,
content={"error": "Malformed request body or parameters"},
)
# --- Routes ---
@app.post("/login", response_model=LoginResponse, status_code=200)
async def login(request: LoginRequest):
if users_db.get(request.username) == request.password:
token = str(uuid.uuid4())
tokens_db[token] = request.username
return {"token": token}
else:
raise HTTPException(status_code=401, detail="Invalid credentials")
@app.get("/products", response_model=List[Product])
async def get_products(max_price: Optional[float] = Query(None)):
results = products_db
if max_price is not None:
# If max_price is not a valid float, FastAPI will raise RequestValidationError
# which we handle as 400.
results = [p for p in products_db if p["price"] <= max_price]
return results
@app.get("/products/{product_id}", response_model=Product)
async def get_product(product_id: int):
product = next((p for p in products_db if p["id"] == product_id), None)
if not product:
raise HTTPException(status_code=404, detail="Product not found")
return product
@app.post("/orders", response_model=OrderResponse, status_code=201)
async def create_order(order_req: OrderRequest, username: str = Depends(get_current_user)):
global order_id_counter
# Find product
product = next((p for p in products_db if p["id"] == order_req.product_id), None)
if not product:
raise HTTPException(status_code=404, detail="Product not found")
# Check stock
if product["stock"] < order_req.quantity:
raise HTTPException(status_code=409, detail="Insufficient stock")
# Process order
total = product["price"] * order_req.quantity
new_order = {
"id": order_id_counter,
"product_id": order_req.product_id,
"quantity": order_req.quantity,
"total": total,
"username": username
}
# Update stock
product["stock"] -= order_req.quantity
orders_db.append(new_order)
order_id_counter += 1
return new_order
@app.get("/orders", response_model=List[OrderResponse])
async def get_orders(username: str = Depends(get_current_user)):
user_orders = [o for o in orders_db if o["username"] == username]
return user_orders
@app.get("/orders/{order_id}", response_model=OrderResponse)
async def get_order(order_id: int, username: str = Depends(get_current_user)):
order = next((o for o in orders_db if o["id"] == order_id), None)
if not order or order["username"] != username:
raise HTTPException(status_code=404, detail="Order not found")
return order
# --- Error handling for 401/404/400 to ensure JSON response ---
@app.exception_handler(HTTPException)
async def http_exception_handler(request, exc):
return JSONResponse(
status_code=exc.status_code,
content={"error": exc.detail},
)
if __name__ == "__main__":
import uvicorn
host = os.environ.get("HOST", "127.0.0.1")
port = int(os.environ.get("PORT", 8000))
uvicorn.run(app, host=host, port=port)
fastapi uvicorn
EEEEEEEEEEEEEEEEEEEEEEEEE [100%]
==================================== ERRORS ====================================
_____________________ ERROR at setup of test_login_success _____________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
___________________ ERROR at setup of test_login_second_user ___________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
__________________ ERROR at setup of test_login_bad_password ___________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
__________________ ERROR at setup of test_login_unknown_user ___________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
_____________________ ERROR at setup of test_list_products _____________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
______________________ ERROR at setup of test_get_product ______________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
__________________ ERROR at setup of test_get_missing_product __________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
_________________ ERROR at setup of test_orders_requires_auth __________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
_______________ ERROR at setup of test_orders_rejects_bad_token ________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
________________ ERROR at setup of test_create_order_and_total _________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
_____________ ERROR at setup of test_create_order_missing_product ______________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
__________________ ERROR at setup of test_orders_are_per_user __________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
_________________ ERROR at setup of test_login_malformed_json __________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
_________________ ERROR at setup of test_login_missing_fields __________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
_________________ ERROR at setup of test_order_malformed_json __________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
_________________ ERROR at setup of test_order_missing_fields __________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
_______________ ERROR at setup of test_order_non_integer_fields ________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
____________ ERROR at setup of test_order_zero_or_negative_quantity ____________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
__________________ ERROR at setup of test_products_have_stock __________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
________________ ERROR at setup of test_order_decrements_stock _________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
____________ ERROR at setup of test_order_exceeding_stock_conflict _____________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
_____________________ ERROR at setup of test_get_own_order _____________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
___________________ ERROR at setup of test_get_missing_order ___________________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
_____________ ERROR at setup of test_get_other_users_order_is_404 ______________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
_______________ ERROR at setup of test_products_max_price_filter _______________
@pytest.fixture(scope="session")
def base_url():
app_py = os.path.join(APP_DIR, "app.py")
if not os.path.isfile(app_py):
> pytest.fail(f"app.py not found in {APP_DIR} (the model did not create it)")
E Failed: app.py not found in /tmp/bench-ws-it75eqa8 (the model did not create it)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:99: Failed
=========================== short test summary info ============================
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_login_success
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_login_second_user
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_login_bad_password
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_login_unknown_user
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_list_products
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_get_product
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_get_missing_product
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_orders_requires_auth
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_orders_rejects_bad_token
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_create_order_and_total
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_create_order_missing_product
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_orders_are_per_user
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_login_malformed_json
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_login_missing_fields
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_order_malformed_json
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_order_missing_fields
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_order_non_integer_fields
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_order_zero_or_negative_quantity
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_products_have_stock
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_order_decrements_stock
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_order_exceeding_stock_conflict
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_get_own_order
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_get_missing_order
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_get_other_users_order_is_404
ERROR ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_products_max_price_filter
25 errors in 0.12s
score: 0/25 (0%)
fastapi uvicorn
......................... [100%] 25 passed in 0.60s score: 25/25 (100%)
import os
import secrets
from typing import List, Optional, Dict
from fastapi import FastAPI, Header, HTTPException, Query, status, Request
from fastapi.responses import JSONResponse
from pydantic import BaseModel, ValidationError
import uvicorn
# --- Models ---
class LoginRequest(BaseModel):
username: str
password: str
class LoginResponse(BaseModel):
token: str
class Product(BaseModel):
id: int
name: str
price: float
stock: int
class OrderRequest(BaseModel):
product_id: int
quantity: int
class Order(BaseModel):
id: int
product_id: int
quantity: int
total: float
username: str # Internal use for tracking ownership
class OrderResponse(BaseModel):
id: int
product_id: int
quantity: int
total: float
# --- In-memory Data Store ---
users_db = {
"alice": "password123",
"bob": "hunter2"
}
# tokens maps token -> username
tokens_db: Dict[str, str] = {}
products_db = [
{"id": 1, "name": "Laptop", "price": 999.99, "stock": 10},
{"id": 2, "name": "Mouse", "price": 25.50, "stock": 50},
{"id": 3, "name": "Keyboard", "price": 75.00, "stock": 20},
]
orders_db: List[Order] = []
order_counter = 1
# --- App Setup ---
app = FastAPI()
# --- Helpers ---
def get_user_from_token(authorization: str = Header(None)) -> str:
if not authorization or not authorization.startswith("Bearer "):
raise HTTPException(status_code=401, detail="Missing or invalid token")
token = authorization.split(" ")[1]
username = tokens_db.get(token)
if not username:
raise HTTPException(status_code=401, detail="Invalid token")
return username
# --- Endpoints ---
@app.post("/login")
async def login(request: Request):
try:
body = await request.json()
except Exception:
return JSONResponse(status_code=400, content={"error": "Malformed JSON"})
if not isinstance(body, dict) or "username" not in body or "password" not in body:
return JSONResponse(status_code=400, content={"error": "Missing username or password"})
username = body["username"]
password = body["password"]
if users_db.get(username) == password:
token = secrets.token_hex(16)
tokens_db[token] = username
return JSONResponse(status_code=200, content={"token": token})
else:
return JSONResponse(status_code=401, content={"error": "Invalid credentials"})
@app.get("/products")
async def get_products(max_price: Optional[str] = Query(None)):
filtered_products = products_db
if max_price is not None:
try:
mp = float(max_price)
filtered_products = [p for p in products_db if p["price"] <= mp]
except ValueError:
pass
return filtered_products
@app.get("/products/{product_id}")
async def get_product(product_id: int):
product = next((p for p in products_db if p["id"] == product_id), None)
if not product:
return JSONResponse(status_code=404, content={"error": "Product not found"})
return product
@app.post("/orders")
async def create_order(request: Request, authorization: str = Header(None)):
try:
username = get_user_from_token(authorization)
except HTTPException as e:
return JSONResponse(status_code=e.status_code, content={"error": e.detail})
try:
body = await request.json()
except Exception:
return JSONResponse(status_code=400, content={"error": "Malformed JSON"})
if not isinstance(body, dict) or "product_id" not in body or "quantity" not in body:
return JSONResponse(status_code=400, content={"error": "Missing product_id or quantity"})
if not isinstance(body["product_id"], int) or not isinstance(body["quantity"], int):
return JSONResponse(status_code=400, content={"error": "product_id and quantity must be integers"})
product_id = body["product_id"]
quantity = body["quantity"]
if quantity < 1:
return JSONResponse(status_code=400, content={"error": "quantity must be at least 1"})
# Find product
product = next((p for p in products_db if p["id"] == product_id), None)
if not product:
return JSONResponse(status_code=404, content={"error": "Product not found"})
# Check stock
if product["stock"] < quantity:
return JSONResponse(status_code=409, content={"error": "Insufficient stock"})
# Create order
global order_counter
total = product["price"] * quantity
new_order = Order(
id=order_counter,
product_id=product_id,
quantity=quantity,
total=total,
username=username
)
# Update stock
product["stock"] -= quantity
# Save order
orders_db.append(new_order)
order_counter += 1
return JSONResponse(status_code=201, content={
"id": new_order.id,
"product_id": new_order.product_id,
"quantity": new_order.quantity,
"total": new_order.total
})
@app.get("/orders")
async def get_orders(authorization: str = Header(None)):
try:
username = get_user_from_token(authorization)
except HTTPException as e:
return JSONResponse(status_code=e.status_code, content={"error": e.detail})
user_orders = [
{"id": o.id, "product_id": o.product_id, "quantity": o.quantity, "total": o.total}
for o in orders_db if o.username == username
]
return user_orders
@app.get("/orders/{order_id}")
async def get_order(order_id: int, authorization: str = Header(None)):
try:
username = get_user_from_token(authorization)
except HTTPException as e:
return JSONResponse(status_code=e.status_code, content={"error": e.detail})
order = next((o for o in orders_db if o.id == order_id), None)
if not order or order.username != username:
return JSONResponse(status_code=404, content={"error": "Order not found"})
return {"id": order.id, "product_id": order.product_id, "quantity": order.quantity, "total": order.total}
if __name__ == "__main__":
host = os.environ.get("HOST", "127.0.0.1")
port = int(os.environ.get("PORT", 8000))
uvicorn.run(app, host=host, port=port)
fastapi uvicorn
import os
import time
import subprocess
import signal
import requests
def test_api():
base_url = "http://127.0.0.1:8000"
print("--- Starting Test Suite ---")
# 1. Test GET /products (Public)
print("Testing GET /products...")
resp = requests.get(f"{base_url}/products")
assert resp.status_code == 200
products = resp.json()
assert len(products) >= 3
print(" PASSED")
# 2. Test GET /products?max_price=50
print("Testing GET /products?max_price=50...")
resp = requests.get(f"{base_url}/products", params={"max_price": 50})
assert resp.status_code == 200
products = resp.json()
for p in products:
assert p["price"] <= 50
print(" PASSED")
# 3. Test GET /products/1
print("Testing GET /products/1...")
resp = requests.get(f"{base_url}/products/1")
assert resp.status_code == 200
assert resp.json()["id"] == 1
print(" PASSED")
# 4. Test GET /products/999 (Non-existent)
print("Testing GET /products/999...")
resp = requests.get(f"{base_url}/products/999")
assert resp.status_code == 404
assert "error" in resp.json()
print(" PASSED")
# 5. Test /login (Valid)
print("Testing /login (Valid)...")
resp = requests.post(f"{base_url}/login", json={"username": "alice", "password": "password123"})
assert resp.status_code == 200
token = resp.json()["token"]
assert len(token) > 0
print(" PASSED")
# 6. Test /login (Invalid)
print("Testing /login (Invalid)...")
resp = requests.post(f"{base_url}/login", json={"username": "alice", "password": "wrong"})
assert resp.status_code == 401
print(" PASSED")
# 7. Test /login (Malformed)
print("Testing /login (Malformed)...")
resp = requests.post(f"{base_url}/login", data="not a json")
assert resp.status_code == 400
print(" PASSED")
# 8. Test /orders (Protected - Valid)
print("Testing POST /orders (Valid)...")
headers = {"Authorization": f"Bearer {token}"}
resp = requests.post(f"{base_url}/orders", json={"product_id": 1, "quantity": 2}, headers=headers)
assert resp.status_code == 201
order = resp.json()
assert order["product_id"] == 1
assert order["quantity"] == 2
assert order["total"] == 999.99 * 2
print(" PASSED")
# 9. Test /orders (Protected - Insufficient Stock)
print("Testing POST /orders (Insufficient Stock)...")
resp = requests.post(f"{base_url}/orders", json={"product_id": 1, "quantity": 100}, headers=headers)
assert resp.status_code == 409
print(" PASSED")
# 10. Test /orders (Protected - Invalid Product)
print("Testing POST /orders (Invalid Product)...")
resp = requests.post(f"{base_url}/orders", json={"product_id": 999, "quantity": 1}, headers=headers)
assert resp.status_code == 404
print(" PASSED")
# 11. Test GET /orders (Protected - User's own orders)
print("Testing GET /orders (User's own orders)...")
resp = requests.get(f"{base_url}/orders", headers=headers)
assert resp.status_code == 200
orders = resp.json()
assert len(orders) > 0
assert orders[0]["id"] == order["id"]
print(" PASSED")
# 12. Test GET /orders/{id} (Protected - Own order)
print("Testing GET /orders/{id} (Own order)...")
resp = requests.get(f"{base_url}/orders/{order['id']}", headers=headers)
assert resp.status_code == 200
print(" PASSED")
# 13. Test GET /orders/{id} (Protected - Another user's order)
print("Testing GET /orders/{id} (Another user's order)...")
# Login as bob
resp_bob = requests.post(f"{base_url}/login", json={"username": "bob", "password": "hunter2"})
token_bob = resp_bob.json()["token"]
headers_bob = {"Authorization": f"Bearer {token_bob}"}
resp = requests.get(f"{base_url}/orders/{order['id']}", headers=headers_bob)
assert resp.status_code == 404
print(" PASSED")
print("\n--- ALL TESTS PASSED ---")
if __name__ == "__main__":
# Start server in a subprocess
print("Starting server...")
server_proc = subprocess.Popen(["python3", "app.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# Wait for server to start
time.sleep(3)
try:
test_api()
except Exception as e:
print(f"\nTEST FAILED: {e}")
import traceback
traceback.print_exc()
finally:
print("Shutting down server...")
server_proc.terminate()
server_proc.wait()
............FFFFF........ [100%]
=================================== FAILURES ===================================
__________________________ test_login_malformed_json ___________________________
base_url = 'http://127.0.0.1:58759'
def test_login_malformed_json(base_url):
status, parsed, ct = _request_h("POST", f"{base_url}/login", raw_body="{not valid json")
> _assert_json_error(status, parsed, ct, 400)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:261:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
status = 422
parsed = {'detail': [{'ctx': {'error': 'Expecting property name enclosed in double quotes'}, 'input': {}, 'loc': ['body', 1], 'msg': 'JSON decode error', ...}]}
ct = 'application/json', expect_status = 400
def _assert_json_error(status, parsed, ct, expect_status):
"""A 4xx response must be JSON with an error/message field (see task.md 'Notes')."""
> assert status == expect_status, f"expected {expect_status}, got {status} (body={parsed!r})"
E AssertionError: expected 400, got 422 (body={'detail': [{'type': 'json_invalid', 'loc': ['body', 1], 'msg': 'JSON decode error', 'input': {}, 'ctx': {'error': 'Expecting property name enclosed in double quotes'}}]})
E assert 422 == 400
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:89: AssertionError
__________________________ test_login_missing_fields ___________________________
base_url = 'http://127.0.0.1:58759'
def test_login_missing_fields(base_url):
status, parsed, ct = _request_h("POST", f"{base_url}/login", body={"username": "alice"})
> _assert_json_error(status, parsed, ct, 400)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:266:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
status = 422
parsed = {'detail': [{'input': {'username': 'alice'}, 'loc': ['body', 'password'], 'msg': 'Field required', 'type': 'missing'}]}
ct = 'application/json', expect_status = 400
def _assert_json_error(status, parsed, ct, expect_status):
"""A 4xx response must be JSON with an error/message field (see task.md 'Notes')."""
> assert status == expect_status, f"expected {expect_status}, got {status} (body={parsed!r})"
E AssertionError: expected 400, got 422 (body={'detail': [{'type': 'missing', 'loc': ['body', 'password'], 'msg': 'Field required', 'input': {'username': 'alice'}}]})
E assert 422 == 400
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:89: AssertionError
__________________________ test_order_malformed_json ___________________________
base_url = 'http://127.0.0.1:58759'
alice_token = '266bce8b-f3b2-4ffa-a0e4-c860ff61fa74'
def test_order_malformed_json(base_url, alice_token):
status, parsed, ct = _request_h("POST", f"{base_url}/orders", token=alice_token,
raw_body="definitely not json")
> _assert_json_error(status, parsed, ct, 400)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:272:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
status = 422
parsed = {'detail': [{'ctx': {'error': 'Expecting value'}, 'input': {}, 'loc': ['body', 0], 'msg': 'JSON decode error', ...}]}
ct = 'application/json', expect_status = 400
def _assert_json_error(status, parsed, ct, expect_status):
"""A 4xx response must be JSON with an error/message field (see task.md 'Notes')."""
> assert status == expect_status, f"expected {expect_status}, got {status} (body={parsed!r})"
E AssertionError: expected 400, got 422 (body={'detail': [{'type': 'json_invalid', 'loc': ['body', 0], 'msg': 'JSON decode error', 'input': {}, 'ctx': {'error': 'Expecting value'}}]})
E assert 422 == 400
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:89: AssertionError
__________________________ test_order_missing_fields ___________________________
base_url = 'http://127.0.0.1:58759'
alice_token = '266bce8b-f3b2-4ffa-a0e4-c860ff61fa74'
def test_order_missing_fields(base_url, alice_token):
status, parsed, ct = _request_h("POST", f"{base_url}/orders", token=alice_token,
body={"product_id": 1})
> _assert_json_error(status, parsed, ct, 400)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:278:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
status = 422
parsed = {'detail': [{'input': {'product_id': 1}, 'loc': ['body', 'quantity'], 'msg': 'Field required', 'type': 'missing'}]}
ct = 'application/json', expect_status = 400
def _assert_json_error(status, parsed, ct, expect_status):
"""A 4xx response must be JSON with an error/message field (see task.md 'Notes')."""
> assert status == expect_status, f"expected {expect_status}, got {status} (body={parsed!r})"
E AssertionError: expected 400, got 422 (body={'detail': [{'type': 'missing', 'loc': ['body', 'quantity'], 'msg': 'Field required', 'input': {'product_id': 1}}]})
E assert 422 == 400
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:89: AssertionError
________________________ test_order_non_integer_fields _________________________
base_url = 'http://127.0.0.1:58759'
alice_token = '266bce8b-f3b2-4ffa-a0e4-c860ff61fa74'
def test_order_non_integer_fields(base_url, alice_token):
status, parsed, ct = _request_h("POST", f"{base_url}/orders", token=alice_token,
body={"product_id": "abc", "quantity": "two"})
> _assert_json_error(status, parsed, ct, 400)
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:284:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
status = 422
parsed = {'detail': [{'input': 'abc', 'loc': ['body', 'product_id'], 'msg': 'Input should be a valid integer, unable to parse s..., 'quantity'], 'msg': 'Input should be a valid integer, unable to parse string as an integer', 'type': 'int_parsing'}]}
ct = 'application/json', expect_status = 400
def _assert_json_error(status, parsed, ct, expect_status):
"""A 4xx response must be JSON with an error/message field (see task.md 'Notes')."""
> assert status == expect_status, f"expected {expect_status}, got {status} (body={parsed!r})"
E AssertionError: expected 400, got 422 (body={'detail': [{'type': 'int_parsing', 'loc': ['body', 'product_id'], 'msg': 'Input should be a valid integer, unable to parse string as an integer', 'input': 'abc'}, {'type': 'int_parsing', 'loc': ['body', 'quantity'], 'msg': 'Input should be a valid integer, unable to parse string as an integer', 'input': 'two'}]})
E assert 422 == 400
/home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py:89: AssertionError
=========================== short test summary info ============================
FAILED ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_login_malformed_json
FAILED ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_login_missing_fields
FAILED ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_order_malformed_json
FAILED ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_order_missing_fields
FAILED ../../home/lzieniew/Documents/my_local_llm_benchmarks/tasks/py-store-api/tests/test_store_api.py::test_order_non_integer_fields
5 failed, 20 passed in 0.64s
score: 20/25 (80%)
import os
import uuid
from typing import List, Optional, Dict
from fastapi import FastAPI, HTTPException, Depends, Query, status, Request
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from fastapi.responses import JSONResponse
from pydantic import BaseModel, ValidationError
# --- Models ---
class User:
def __init__(self, username, password):
self.username = username
self.password = password
class Product(BaseModel):
id: int
name: str
price: float
stock: int
class Order(BaseModel):
id: int
product_id: int
quantity: int
total: float
username: str # Internal use to track who made the order
class LoginRequest(BaseModel):
username: str
password: str
class OrderCreateRequest(BaseModel):
product_id: int
quantity: int
# --- In-Memory Database ---
users = {
"alice": User("alice", "password123"),
"bob": User("bob", "hunter2"),
}
products = [
Product(id=1, name="Laptop", price=999.99, stock=10),
Product(id=2, name="Mouse", price=25.50, stock=50),
Product(id=3, name="Keyboard", price=75.00, stock=20),
]
orders: List[Order] = []
order_id_counter = 1
# Token mapping: token -> username
tokens: Dict[str, str] = {}
# --- App Setup ---
app = FastAPI()
security = HTTPBearer()
# --- Helpers ---
def get_current_user(auth: HTTPAuthorizationCredentials = Depends(security)) -> str:
token = auth.credentials
if token not in tokens:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail={"error": "Invalid or missing token"}
)
return tokens[token]
# Custom exception handlers to ensure error responses are JSON with "error" field
@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
if isinstance(exc.detail, dict):
content = exc.detail
else:
content = {"error": exc.detail}
return JSONResponse(
status_code=exc.status_code,
content=content
)
@app.exception_handler(ValidationError)
async def validation_exception_handler(request: Request, exc: ValidationError):
return JSONResponse(
status_code=status.HTTP_400_BAD_REQUEST,
content={"error": str(exc.errors())}
)
@app.exception_handler(422)
async def validation_exception_handler_422(request: Request, exc: Exception):
return JSONResponse(
status_code=status.HTTP_400_BAD_REQUEST,
content={"error": "Malformed request body or parameters"}
)
# --- Endpoints ---
@app.post("/login")
async def login(login_data: LoginRequest):
user = users.get(login_data.username)
if not user or user.password != login_data.password:
raise HTTPException(status_code=401, detail="Invalid username or password")
token = str(uuid.uuid4())
tokens[token] = login_data.username
return {"token": token}
@app.get("/products")
async def get_products(max_price: Optional[str] = Query(None)):
filtered_products = products
if max_price is not None:
try:
mp = float(max_price)
filtered_products = [p for p in products if p.price <= mp]
except ValueError:
# Not a valid number, return all products
filtered_products = products
return filtered_products
@app.get("/products/{product_id}")
async def get_product(product_id: int):
product = next((p for p in products if p.id == product_id), None)
if not product:
raise HTTPException(status_code=404, detail="Product not found")
return product
@app.post("/orders", status_code=201)
async def create_order(order_req: OrderCreateRequest, username: str = Depends(get_current_user)):
if order_req.quantity < 1:
raise HTTPException(status_code=400, detail="Quantity must be at least 1")
product = next((p for p in products if p.id == order_req.product_id), None)
if not product:
raise HTTPException(status_code=404, detail="Product not found")
if product.stock < order_req.quantity:
raise HTTPException(status_code=409, detail="Insufficient stock")
total = product.price * order_req.quantity
global order_id_counter
new_order = Order(
id=order_id_counter,
product_id=product.id,
quantity=order_req.quantity,
total=total,
username=username
)
product.stock -= order_req.quantity
orders.append(new_order)
order_id_counter += 1
return {
"id": new_order.id,
"product_id": new_order.product_id,
"quantity": new_order.quantity,
"total": new_order.total
}
@app.get("/orders")
async def get_orders(username: str = Depends(get_current_user)):
user_orders = [
{
"id": o.id,
"product_id": o.product_id,
"quantity": o.quantity,
"total": o.total
}
for o in orders if o.username == username
]
return user_orders
@app.get("/orders/{order_id}")
async def get_order(order_id: int, username: str = Depends(get_current_user)):
order = next((o for o in orders if o.id == order_id), None)
if not order or order.username != username:
raise HTTPException(status_code=404, detail="Order not found")
return {
"id": order.id,
"product_id": order.product_id,
"quantity": order.quantity,
"total": order.total
}
# --- Main Execution ---
if __name__ == "__main__":
import uvicorn
host = os.getenv("HOST", "127.0.0.1")
port = int(os.getenv("PORT", 8000))
uvicorn.run(app, host=host, port=port)
fastapi uvicorn
......................... [100%] 25 passed in 0.60s score: 25/25 (100%)
import os
import uvicorn
from fastapi import FastAPI, Depends, HTTPException, status, Query
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from pydantic import BaseModel, Field, validator
from typing import List, Optional, Dict
import uuid
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
# --- Data Models ---
class User:
def __init__(self, username, password):
self.username = username
self.password = password
class Product:
def __init__(self, id: int, name: str, price: float, stock: int):
self.id = id
self.name = name
self.price = price
self.stock = stock
def to_dict(self):
return {"id": self.id, "name": self.name, "price": self.price, "stock": self.stock}
class Order:
def __init__(self, id: int, username: str, product_id: int, quantity: int, total: float):
self.id = id
self.username = username
self.product_id = product_id
self.quantity = quantity
self.total = total
def to_dict(self):
return {"id": self.id, "product_id": self.product_id, "quantity": self.quantity, "total": self.total}
# --- API Request/Response Schemas ---
class LoginRequest(BaseModel):
username: str
password: str
class LoginResponse(BaseModel):
token: str
class OrderRequest(BaseModel):
product_id: int
quantity: int
@validator('quantity')
def quantity_must_be_positive(cls, v):
if v < 1:
raise ValueError('quantity must be at least 1')
return v
class OrderResponse(BaseModel):
id: int
product_id: int
quantity: int
total: float
# --- In-memory Database ---
users: Dict[str, User] = {
"alice": User("alice", "password123"),
"bob": User("bob", "hunter2")
}
# token -> username
active_tokens: Dict[str, str] = {}
products: Dict[int, Product] = {
1: Product(1, "Laptop", 999.99, 10),
2: Product(2, "Mouse", 25.50, 50),
3: Product(3, "Keyboard", 75.00, 15)
}
orders: List[Order] = []
order_id_counter = 1
# --- App Setup ---
app = FastAPI()
security = HTTPBearer()
# --- Helpers ---
def get_current_user(auth: HTTPAuthorizationCredentials = Depends(security)) -> str:
token = auth.credentials
if token not in active_tokens:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail={"error": "Invalid or missing token"}
)
return active_tokens[token]
# --- Endpoints ---
@app.post("/login")
async def login(req: LoginRequest):
user = users.get(req.username)
if not user or user.password != req.password:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail={"error": "Invalid credentials"}
)
token = str(uuid.uuid4())
active_tokens[token] = req.username
return {"token": token}
@app.get("/products")
async def get_products(max_price: Optional[float] = Query(None)):
product_list = list(products.values())
if max_price is not None:
product_list = [p for p in product_list if p.price <= max_price]
return [p.to_dict() for p in product_list]
@app.get("/products/{product_id}")
async def get_product(product_id: int):
product = products.get(product_id)
if not product:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail={"error": "Product not found"}
)
return product.to_dict()
@app.post("/orders", status_code=status.HTTP_201_CREATED)
async def create_order(req: OrderRequest, username: str = Depends(get_current_user)):
global order_id_counter
product = products.get(req.product_id)
if not product:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail={"error": "Product not found"}
)
if product.stock < req.quantity:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail={"error": "Not enough stock available"}
)
total = product.price * req.quantity
new_order = Order(order_id_counter, username, product.id, req.quantity, total)
# Deduct stock
product.stock -= req.quantity
orders.append(new_order)
order_id_counter += 1
return new_order.to_dict()
@app.get("/orders")
async def get_orders(username: str = Depends(get_current_user)):
user_orders = [o.to_dict() for o in orders if o.username == username]
return user_orders
@app.get("/orders/{order_id}")
async def get_order(order_id: int, username: str = Depends(get_current_user)):
for o in orders:
if o.id == order_id:
if o.username == username:
return o.to_dict()
else:
# Do not reveal existence of orders belonging to others
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail={"error": "Order not found"}
)
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail={"error": "Order not found"}
)
# --- Exception Handlers ---
@app.exception_handler(HTTPException)
async def http_exception_handler(request, exc):
if isinstance(exc.detail, dict):
content = exc.detail
else:
content = {"error": exc.detail}
return JSONResponse(
status_code=exc.status_code,
content=content
)
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
return JSONResponse(
status_code=400,
content={"error": "Malformed request body"}
)
@app.exception_handler(Exception)
async def generic_exception_handler(request, exc):
return JSONResponse(
status_code=500,
content={"error": str(exc)}
)
if __name__ == "__main__":
host = os.environ.get("HOST", "127.0.0.1")
port = int(os.environ.get("PORT", 8000))
uvicorn.run(app, host=host, port=port)
fastapi uvicorn