v.0.11.0 ap-server & pico-client

This commit is contained in:
tiijay
2025-11-20 19:42:50 +01:00
parent 00c24110ee
commit 2233be7987
11 changed files with 213 additions and 21 deletions

View File

@@ -0,0 +1,36 @@
FROM python:3.13-alpine
# Install system dependencies
RUN apk add --no-cache \
git \
curl \
wget \
bash \
build-base \
linux-headers \
fish
# Install uv from official image
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
RUN uv --version
# Create non-root user with fish shell
RUN adduser -D -s /usr/bin/fish vscode
# Create workspace and set permissions
RUN mkdir -p /workspace && chown vscode:vscode /workspace
USER vscode
WORKDIR /workspace
# Set fish as default shell
SHELL ["/usr/bin/fish", "-c"]
# Install packages directly to system Python (container-isolated)
ENV UV_PROJECT_ENVIRONMENT=""
ENV UV_PYTHON=python
# Verify everything works
RUN echo "Python: $(python --version)" && \
echo "UV: $(uv --version)" && \
echo "Fish: $(fish --version)"

View File

@@ -0,0 +1,44 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/python
{
"name": "API-Server",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"build": {
"dockerfile": "Dockerfile"
},
// "image": "mcr.microsoft.com/devcontainers/python:1-3.12",
// "image": "python:latest",
//"image": "python:3.13-slim",
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
// Configure tool-specific properties.
"customizations": {
// Configure properties specific to VS Code.
"vscode": {
"settings": {},
"extensions": [
"ms-python.python",
"frhtylcn.pythonsnippets",
"kevinrose.vsc-python-indent",
"wayou.vscode-todo-highlight",
"charliermarsh.ruff",
"tamasfe.even-better-toml"
]
}
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [9000],
// Use 'portsAttributes' to set default properties for specific forwarded ports.
// More info: https://containers.dev/implementors/json_reference/#port-attributes
"portsAttributes": {
"9000": {
"label": "API-Server Application",
"onAutoForward": "notify"
}
},
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "uv sync"
// "postCreateCommand": "apt-get update && apt-get install -y git && pip3 install -r requirements.txt"
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}

75
api-server/app/main.py Normal file
View File

@@ -0,0 +1,75 @@
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import List, Optional
app = FastAPI(title="FastAPI Server", version="1.0.0")
# CORS middleware to allow client requests
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000", "http://client:3000"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
class Item(BaseModel):
id: int
name: str
description: Optional[str] = None
price: float
# In-memory database
items_db = [
Item(id=1, name="Laptop", description="High-performance laptop", price=999.99),
Item(id=2, name="Mouse", description="Wireless mouse", price=29.99),
Item(id=3, name="Keyboard", description="Mechanical keyboard", price=79.99),
]
@app.get("/")
async def root():
return {"message": "FastAPI Server is running!"}
@app.get("/items", response_model=List[Item])
async def get_items():
return items_db
@app.get("/items/{item_id}", response_model=Item)
async def get_item(item_id: int):
item = next((item for item in items_db if item.id == item_id), None)
if item is None:
raise HTTPException(status_code=404, detail="Item not found")
return item
@app.post("/items", response_model=Item)
async def create_item(item: Item):
if any(existing_item.id == item.id for existing_item in items_db):
raise HTTPException(status_code=400, detail="Item ID already exists")
items_db.append(item)
return item
@app.put("/items/{item_id}", response_model=Item)
async def update_item(item_id: int, item: Item):
if item.id != item_id:
raise HTTPException(status_code=400, detail="Item ID mismatch")
for idx, existing_item in enumerate(items_db):
if existing_item.id == item_id:
items_db[idx] = item
return item
raise HTTPException(status_code=404, detail="Item not found")
@app.delete("/items/{item_id}")
async def delete_item(item_id: int):
for idx, item in enumerate(items_db):
if item.id == item_id:
deleted_item = items_db.pop(idx)
return {"message": f"Item {deleted_item.name} deleted successfully"}
raise HTTPException(status_code=404, detail="Item not found")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)

12
api-server/pyproject.toml Normal file
View File

@@ -0,0 +1,12 @@
[project]
name = "api-server"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
"fastapi>=0.104.0",
"uvicorn[standard]>=0.24.0",
]
# [build-system]
# requires = ["hatchling"]
# build-backend = "hatchling.build"