diff --git a/README.md b/README.md index ed8b006..a0b25d7 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,38 @@ # NX AI -> Production ready Python FastAPI/Postgres app for [NX](https://goldlabel.pro?s=nx-ai) AI services and more +> FastAPI/Python/Postgres/tsvector. Production ready Python FastAPI/Postgres app for [NX](https://goldlabel.pro?s=nx-ai) AI services and more + +## Install & use + +```bash +# Create and activate a virtual environment +python -m venv venv +source venv/bin/activate # Windows: venv\Scripts\activate + +# Install dependencies +pip install -r requirements.txt + +# Start the development server +uvicorn app.main:app --reload +``` ```sh uvicorn app.main:app pytest ``` -[localhost](http://localhost:8000) -[Public RESTful API](https://nx-ai.onrender.com) +The API is at . + +[localhost](http://localhost:8000) | [Public RESTful API](https://nx-ai.onrender.com) - **Python 3.11+** +- **Postgres** +- **tsvector** - Superfast search - **FastAPI** — RESTful API framework - **Uvicorn** — ASGI server - **Pytest** — testing framework -- **HTTPX / TestClient** — HTTP testing +- **HTTPX / TestClient** -## Docs FastAPI automatically generates interactive documentation: @@ -38,21 +54,6 @@ tests/ requirements.txt ``` -## Install - -```bash -# Create and activate a virtual environment -python -m venv venv -source venv/bin/activate # Windows: venv\Scripts\activate - -# Install dependencies -pip install -r requirements.txt - -# Start the development server -uvicorn app.main:app --reload -``` - -The API will be available at . ## Endpoints @@ -62,13 +63,4 @@ The API will be available at . | GET | `/health` | Health check — returns `ok` | | POST | `/echo` | Echoes the JSON `message` field | -### Example — Echo - -```bash -curl -X POST http://localhost:8000/echo \ - -H "Content-Type: application/json" \ - -d '{"message": "hello"}' -# {"echo":"hello"} -``` - diff --git a/app/__init__.py b/app/__init__.py index fc0d7ce..95cf70f 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,4 +1,4 @@ -"""NX AI - FastAPI""" +"""NX AI - FastAPI/Python/Postgres/tsvector""" -# Version tracking -__version__ = "1.0.3" +# Current Version +__version__ = "1.0.4" diff --git a/app/api/import_csv.py b/app/api/import_csv.py new file mode 100644 index 0000000..9ed4bc1 --- /dev/null +++ b/app/api/import_csv.py @@ -0,0 +1,56 @@ +from fastapi import APIRouter, UploadFile, File, HTTPException + +import csv +import psycopg2 +import os +import io +from dotenv import load_dotenv + +router = APIRouter() + +@router.post("/import-csv") +def import_csv(file: UploadFile = File(...)): + """Import products from a CSV file into the database.""" + load_dotenv() + conn = psycopg2.connect( + host=os.getenv('DB_HOST'), + port=os.getenv('DB_PORT', '5432'), + dbname=os.getenv('DB_NAME'), + user=os.getenv('DB_USER'), + password=os.getenv('DB_PASSWORD') + ) + cur = conn.cursor() + try: + reader = csv.DictReader(io.TextIOWrapper(file.file, encoding='utf-8')) + batch = [] + batch_size = 100 + inserted = 0 + for row in reader: + batch.append(( + row.get('name'), + row.get('description'), + float(row.get('price', 0)), + int(row.get('in_stock', 0)), + )) + if len(batch) >= batch_size: + cur.executemany( + "INSERT INTO product (name, description, price, in_stock) VALUES (%s, %s, %s, %s)", + batch + ) + conn.commit() + inserted += len(batch) + batch.clear() + if batch: + cur.executemany( + "INSERT INTO product (name, description, price, in_stock) VALUES (%s, %s, %s, %s)", + batch + ) + conn.commit() + inserted += len(batch) + return {"inserted": inserted} + except Exception as e: + conn.rollback() + raise HTTPException(status_code=500, detail=str(e)) + finally: + cur.close() + conn.close() diff --git a/app/api/root.py b/app/api/root.py index 4db7d54..d161836 100644 --- a/app/api/root.py +++ b/app/api/root.py @@ -39,6 +39,6 @@ def root() -> dict: "time": time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), "epoch": epoch, "severity": "success", - "message": f"NX AI says hello. Returned {len(products)} products." + "message": f"NX AI says hello & returned {len(products)} products" } return {"meta": meta, "data": products} diff --git a/app/api/routes.py b/app/api/routes.py index 285daef..34168dd 100644 --- a/app/api/routes.py +++ b/app/api/routes.py @@ -17,8 +17,10 @@ from app.api.root import router as root_router from app.api.health import router as health_router from app.api.echo import router as echo_router +from app.api.import_csv import router as import_csv_router router.include_router(root_router) router.include_router(health_router) router.include_router(echo_router) +router.include_router(import_csv_router)