from fastapi import FastAPI, HTTPException from typing import Optional, List from pydantic import BaseModel import pandas as pd from datasets import Dataset, load_dataset from huggingface_hub import upload_file import os # Configuration - MUST come first DATASET_NAME = "Ritesh1035/Customer_Data" # Your HuggingFace dataset HF_TOKEN = os.getenv("HF_TOKEN") # Set this in HF Space secrets app = FastAPI(title="Customer API", description="Customer management API with HuggingFace Dataset storage") @app.on_event("startup") async def startup_event(): """Test connectivity on startup""" print(f"🚀 Starting Customer API...") print(f"📊 Dataset: {DATASET_NAME}") print(f"🔑 HF Token: {'✅ Set' if HF_TOKEN else '❌ Not set'}") # Test dataset connectivity try: customers = load_customers_from_dataset() print(f"✅ Successfully connected to dataset with {len(customers)} customers") except Exception as e: print(f"⚠️ Dataset connection warning: {e}") print("🎉 API is ready!") @app.get("/") def read_root(): hf_token_status = "✅ Set" if HF_TOKEN else "❌ Not set" return { "message": "Customer API is running! Visit /docs for API documentation.", "dataset": DATASET_NAME, "hf_token_status": hf_token_status } @app.get("/health") def health_check(): """Health check endpoint""" return {"status": "healthy", "service": "Customer API"} # 1 Define blueprint class Customer(BaseModel): id:int name: str email: str phone: Optional[str]=None address: Optional[str]=None # 2 HuggingFace Dataset Functions def load_customers_from_dataset() -> List[Customer]: """Load customers from HF Dataset""" try: print(f"📊 Loading dataset: {DATASET_NAME}") # Load dataset with minimal options dataset = load_dataset( DATASET_NAME, split="train", token=HF_TOKEN ) print(f"✅ Dataset loaded: {len(dataset)} rows") customers = [] for row in dataset: try: customers.append(Customer( id=int(row['id']), name=str(row['name']), email=str(row['email']), phone=str(row.get('phone', '')) if row.get('phone') and row.get('phone') != '' else None, address=str(row.get('address', '')) if row.get('address') and row.get('address') != '' else None )) except Exception as row_error: print(f"⚠️ Skipping invalid row: {row_error}") continue print(f"📋 Loaded {len(customers)} customers") return customers except Exception as e: print(f"⚠️ Load error: {e}") return [] def save_customers_to_dataset(customers: List[Customer]): """Save customers to HF Dataset""" try: # Convert to pandas DataFrame data = [] for customer in customers: data.append({ 'id': customer.id, 'name': customer.name, 'email': customer.email, 'phone': customer.phone or "", 'address': customer.address or "" }) df = pd.DataFrame(data) print(f"💾 Saving {len(customers)} customers to dataset...") # Save locally first as backup df.to_csv("customers.csv", index=False) print("📁 Local backup saved") # Upload to HF Dataset if token is available if HF_TOKEN: try: upload_file( path_or_fileobj="customers.csv", path_in_repo="customers.csv", repo_id=DATASET_NAME, repo_type="dataset", token=HF_TOKEN ) print(f"✅ Successfully saved {len(customers)} customers to dataset") # Small delay for sync import time time.sleep(1) except Exception as e: print(f"⚠️ Upload error: {e}") # Don't fail the operation, just log the error else: print("⚠️ HF_TOKEN not set - data saved locally only") except Exception as e: print(f"❌ Error in save_customers_to_dataset: {e}") # Don't raise exception to avoid breaking the API # Create @app.post("/Customer", response_model=Customer) def create_customer(customer: Customer): print(f"➕ Creating customer ID: {customer.id}") customers = load_customers_from_dataset() print(f"📊 Current customers: {len(customers)}") # Check for unique ID existing_ids = [c.id for c in customers] if customer.id in existing_ids: print(f"❌ ID {customer.id} already exists") raise HTTPException( status_code=400, detail=f"Customer ID {customer.id} already exists" ) customers.append(customer) save_customers_to_dataset(customers) print(f"✅ Created customer {customer.id}") return customer # Read @app.get("/Customer", response_model=List[Customer]) def get_customer(): print("📋 Getting all customers") customers = load_customers_from_dataset() print(f"📊 Found {len(customers)} customers") return customers # Update @app.put("/Customer/{id}", response_model=Customer) def update_customer(id: int, customer: Customer): customers = load_customers_from_dataset() for i, existing_customer in enumerate(customers): if existing_customer.id == id: customers[i] = customer save_customers_to_dataset(customers) return customer raise HTTPException(status_code=404, detail="customer not found") # Delete @app.delete("/Customer/{id}", response_model=Customer) def delete_customer(id: int): customers = load_customers_from_dataset() for i, customer_obj in enumerate(customers): if customer_obj.id == id: deleted_customer = customers.pop(i) save_customers_to_dataset(customers) return deleted_customer raise HTTPException(status_code=404, detail="customer not found") if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=7860)