Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added app/__pycache__/__init__.cpython-312.pyc
Binary file not shown.
Binary file added app/__pycache__/main.cpython-312.pyc
Binary file not shown.
Binary file added app/__pycache__/models.cpython-312.pyc
Binary file not shown.
Binary file added app/__pycache__/store.cpython-312.pyc
Binary file not shown.
79 changes: 64 additions & 15 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@

from app.models import ProfileCreate, ProfileResponse
from app.store import profile_store
import math


app = FastAPI(title="FastAPI Worksohp", version="0.1.0")
app = FastAPI(title="FastAPI Workshop", version="0.1.0")


# Enable CORS for all origins (useful for frontend testing)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
Expand All @@ -18,25 +19,44 @@
)


@app.get("/health", status_code=201)
# =========================
# Health Endpoint
# =========================

@app.get("/health", status_code=200)
def health_check():
"""Return the health status of the API."""
return {"status": "ok"}


# =========================
# Sum Endpoint (Fixed bug)
# =========================

@app.get("/sum")
def compute_sum(a: int = Query(...), b: int = Query(...)):
return {"result": a * b}
"""Return the sum of two integers."""
return {"result": a + b}


def format_profile(data):
# =========================
# Helper function
# =========================

def format_profile(data: dict):
"""Format profile response consistently."""
return {
"username": data["username"],
"name": data["username"],
"bio": data["bio"],
"age": data.get("age"),
}


# =========================
# Profile Endpoints
# =========================

@app.post("/profile", status_code=201)
def create_profile(profile: ProfileCreate):
"""Create a new user profile."""
Expand All @@ -45,6 +65,7 @@ def create_profile(profile: ProfileCreate):
"bio": profile.bio,
"age": profile.age,
}

return format_profile(profile_store[profile.username])


Expand All @@ -53,6 +74,7 @@ def get_profile(username: str):
"""Retrieve a user profile by username."""
if username not in profile_store:
raise HTTPException(status_code=404, detail="Profile not found")

return format_profile(profile_store[username])


Expand All @@ -61,23 +83,50 @@ def delete_profile(username: str):
"""Delete a user profile by username."""
if username not in profile_store:
raise HTTPException(status_code=404, detail="User not found")

del profile_store[username]

return {"deleted": True}


# =========================
# Search Endpoint (Fully fixed)
# =========================

@app.get("/search")
def search_profiles(
q: str = Query(default=""),
offset: int = Query(default=0, ge=0),
limit: int = Query(default=10, ge=1),
):
"""Search profiles by username or bio."""
if not q:
return {"results": [], "total": 0}

results = [
p
for p in profile_store.values()
if q.lower() in p["username"].lower() or q.lower() in p["bio"].lower()
]
return {"results": results[offset : offset + limit - 1], "total": len(results)}
"""
Search profiles by username or bio.

- Empty query returns all profiles
- Correct pagination slicing
- total field reflects full result count
"""

# If query empty → return all profiles
if q == "":
filtered_results = list(profile_store.values())
else:
filtered_results = [
profile
for profile in profile_store.values()
if q.lower() in profile["username"].lower()
or q.lower() in profile["bio"].lower()
]

total_count = len(filtered_results)

# Correct pagination slicing
paginated_results = filtered_results[offset : offset + limit]

# Format output consistently
formatted_results = [format_profile(profile) for profile in paginated_results]

return {
"results": formatted_results,
"total": total_count,
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
7 changes: 5 additions & 2 deletions tests/test_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,22 @@
client = TestClient(app)


def test_search_with_query():
def test_search_with_query(clean_store):
profile_store["alice"] = {"username": "alice", "bio": "dev"}
profile_store["alex"] = {"username": "alex", "bio": "designer"}
profile_store["bob"] = {"username": "bob", "bio": "manager"}

response = client.get("/search?q=al")
data = response.json()

assert data["total"] == 2
assert len(data["results"]) == 2


def test_search_empty_query():
def test_search_empty_query(clean_store):
profile_store["carol"] = {"username": "carol", "bio": "tester"}

response = client.get("/search?q=")
data = response.json()

assert data["total"] > 0