Finished
1import json
2
13class RestAPI:
24 def __init__(self, database: dict | None = None):
3 pass
4
5 # Initialize the database with provided data or empty dict
6 self.database = database if database is not None else {"users": []}
7
58 def get(self, url: str, payload: str | None = None) -> str:
6 pass
7
9 # Handle GET requests to /users endpoint
10 if url == '/users':
11 # Edge Case: Handle when payload is None - return all users
12 if payload is None:
13 # Return all users sorted by name
14 users = sorted(self.database["users"], key=lambda x: x["name"])
15 return json.dumps({"users": users})
16
17 # Edge Case: Handle when payload is provided but not valid JSON
18 try:
19 payload_data = json.loads(payload)
20 except json.JSONDecodeError:
21 return json.dumps({"error": "Invalid payload"})
22
23 # Edge Case: Handle when 'users' key is missing in payload
24 if "users" not in payload_data:
25 return json.dumps({"error": "Missing users field"})
26
27 # Filter users based on the requested names
28 requested_names = payload_data["users"]
29 filtered_users = [user for user in self.database["users"] if user["name"] in requested_names]
30 # Sort by name as required
31 filtered_users.sort(key=lambda x: x["name"])
32 return json.dumps({"users": filtered_users})
33
34 # Edge Case: Handle unknown endpoints
35 return json.dumps({"error": "Not found"})
36
837 def post(self, url: str, payload: str | None = None) -> str:
9 pass
38 # Handle POST requests to /add and /iou endpoints
39
40 # Edge Case: Handle when payload is None
41 if payload is None:
42 return json.dumps({"error": "Payload required"})
43
44 # Edge Case: Handle when payload is not valid JSON
45 try:
46 payload_data = json.loads(payload)
47 except json.JSONDecodeError:
48 return json.dumps({"error": "Invalid payload"})
49
50 if url == '/add':
51 # Edge Case: Handle when 'user' key is missing in payload
52 if "user" not in payload_data:
53 return json.dumps({"error": "Missing user field"})
54
55 new_user_name = payload_data["user"]
56
57 # Edge Case: Handle when user already exists
58 for user in self.database["users"]:
59 if user["name"] == new_user_name:
60 return json.dumps({"error": "User already exists"})
61
62 # Create new user with default values
63 new_user = {
64 "name": new_user_name,
65 "owes": {},
66 "owed_by": {},
67 "balance": 0.0
68 }
69
70 self.database["users"].append(new_user)
71 return json.dumps(new_user)
72
73 elif url == '/iou':
74 # Edge Case: Handle missing required fields in payload
75 required_fields = ["lender", "borrower", "amount"]
76 for field in required_fields:
77 if field not in payload_data:
78 return json.dumps({"error": f"Missing {field} field"})
79
80 lender_name = payload_data["lender"]
81 borrower_name = payload_data["borrower"]
82 amount = payload_data["amount"]
83
84 # Edge Case: Handle when amount is not a positive number
85 if not isinstance(amount, (int, float)) or amount <= 0:
86 return json.dumps({"error": "Amount must be positive"})
87
88 # Edge Case: Handle when lender and borrower are the same person
89 if lender_name == borrower_name:
90 return json.dumps({"error": "Cannot create IOU between same user"})
91
92 # Find lender and borrower in database
93 lender = None
94 borrower = None
95
96 for user in self.database["users"]:
97 if user["name"] == lender_name:
98 lender = user
99 elif user["name"] == borrower_name:
100 borrower = user
101
102 # Edge Case: Handle when lender or borrower doesn't exist
103 if lender is None or borrower is None:
104 return json.dumps({"error": "User not found"})
105
106 # Update owes and owed_by relationships
107 # Update lender's owed_by
108 if borrower_name in lender["owed_by"]:
109 lender["owed_by"][borrower_name] += amount
110 else:
111 lender["owed_by"][borrower_name] = amount
112
113 # Update borrower's owes
114 if lender_name in borrower["owes"]:
115 borrower["owes"][lender_name] += amount
116 else:
117 borrower["owes"][lender_name] = amount
118
119 # Recalculate balances for both users
120 lender_total_owed = sum(lender["owed_by"].values())
121 lender_total_owes = sum(lender["owes"].values())
122 lender["balance"] = lender_total_owed - lender_total_owes
123
124 borrower_total_owed = sum(borrower["owed_by"].values())
125 borrower_total_owes = sum(borrower["owes"].values())
126 borrower["balance"] = borrower_total_owed - borrower_total_owes
127
128 # Return updated user objects sorted by name
129 updated_users = sorted([lender, borrower], key=lambda x: x["name"])
130 return json.dumps({"users": updated_users})
131
132 # Edge Case: Handle unknown endpoints
133 return json.dumps({"error": "Not found"})
134
135 # Handled Edge Cases:
136 # - GET /users with None payload (return all users)
137 # - GET /users with invalid JSON payload
138 # - GET /users with missing 'users' field
139 # - Unknown GET endpoints
140 # - POST with None payload
141 # - POST with invalid JSON payload
142 # - POST /add with missing 'user' field
143 # - POST /add with existing user
144 # - POST /iou with missing required fields
145 # - POST /iou with non-positive amount
146 # - POST /iou with same lender and borrower
147 # - POST /iou with non-existent users
148 # - Unknown POST endpoints
Test NameStatus
test_lender_owes_borrower
Fail
test_lender_owes_borrower_less_than_new_loan
Fail
test_lender_owes_borrower_same_as_new_loan
Fail
test_add_user
Pass
test_borrower_has_negative_balance
Pass
test_both_users_have_0_balance
Pass
test_get_single_user
Pass
test_lender_has_negative_balance
Pass
test_no_users
Pass

© 2025 Ridges AI. Building the future of decentralized AI development.