uv

Finished
1import json
2
13class RestAPI:
24 def __init__(self, database: dict | None = None):
3 pass
4
5 """
6 Initialize the REST API with a database.
7
8 Args:
9 database: A dictionary containing user data.
10 """
11 # Edge Case: Handle None database by initializing empty structure
12 if database is None:
13 self.database = {"users": []}
14 else:
15 self.database = database
16
517 def get(self, url: str, payload: str | None = None) -> str:
6 pass
7
18 """
19 Handle GET requests to the API.
20
21 Args:
22 url: The endpoint being accessed.
23 payload: Optional JSON payload with request parameters.
24
25 Returns:
26 JSON string response.
27
28 Raises:
29 ValueError: If the URL is not recognized.
30 """
31 # Edge Case: Handle /users endpoint
32 if url == "/users":
33 # Edge Case: Handle payload with specific users requested
34 if payload is not None:
35 data = json.loads(payload)
36 if "users" in data:
37 # Filter users by requested names
38 requested_users = data["users"]
39 filtered_users = [user for user in self.database["users"] if user["name"] in requested_users]
40 # Sort by name
41 filtered_users.sort(key=lambda x: x["name"])
42 return json.dumps({"users": filtered_users})
43 # Edge Case: Handle no payload (return all users)
44 else:
45 # Sort all users by name
46 sorted_users = sorted(self.database["users"], key=lambda x: x["name"])
47 return json.dumps({"users": sorted_users})
48 # Edge Case: Handle unknown URL
49 else:
50 raise ValueError(f"Unknown GET endpoint: {url}")
51
52 # Handled Edge Cases: /users endpoint with and without payload, unknown URL
53
854 def post(self, url: str, payload: str | None = None) -> str:
9 pass
55 """
56 Handle POST requests to the API.
57
58 Args:
59 url: The endpoint being accessed.
60 payload: JSON payload with request data.
61
62 Returns:
63 JSON string response.
64
65 Raises:
66 ValueError: If the URL is not recognized or if data is invalid.
67 """
68 # Edge Case: Handle None payload
69 if payload is None:
70 raise ValueError("Payload is required for POST requests")
71
72 data = json.loads(payload)
73
74 # Edge Case: Handle /add endpoint
75 if url == "/add":
76 # Edge Case: Check if user field exists in payload
77 if "user" not in data:
78 raise ValueError("Missing 'user' field in payload")
79
80 new_user_name = data["user"]
81
82 # Edge Case: Check if user already exists
83 for user in self.database["users"]:
84 if user["name"] == new_user_name:
85 # Return existing user instead of raising error
86 return json.dumps(user)
87
88 # Create new user
89 new_user = {
90 "name": new_user_name,
91 "owes": {},
92 "owed_by": {},
93 "balance": 0.0
94 }
95
96 self.database["users"].append(new_user)
97
98 # Sort users by name before returning
99 self.database["users"].sort(key=lambda x: x["name"])
100
101 return json.dumps(new_user)
102
103 # Edge Case: Handle /iou endpoint
104 elif url == "/iou":
105 # Edge Case: Validate required fields in payload
106 required_fields = ["lender", "borrower", "amount"]
107 for field in required_fields:
108 if field not in data:
109 raise ValueError(f"Missing '{field}' field in payload")
110
111 lender_name = data["lender"]
112 borrower_name = data["borrower"]
113 amount = data["amount"]
114
115 # Edge Case: Validate amount is a positive number
116 if not isinstance(amount, (int, float)) or amount <= 0:
117 raise ValueError("Amount must be a positive number")
118
119 # Edge Case: Validate lender and borrower are different
120 if lender_name == borrower_name:
121 raise ValueError("Lender and borrower cannot be the same person")
122
123 # Find lender and borrower in database
124 lender = None
125 borrower = None
126
127 for user in self.database["users"]:
128 if user["name"] == lender_name:
129 lender = user
130 elif user["name"] == borrower_name:
131 borrower = user
132
133 # Edge Case: Validate both users exist
134 if lender is None:
135 raise ValueError(f"User '{lender_name}' does not exist")
136 if borrower is None:
137 raise ValueError(f"User '{borrower_name}' does not exist")
138
139 # Update debts between lender and borrower
140 # Handle the case where they might already have debts in both directions
141
142 # Get current amounts
143 lender_owed_by_borrower = lender["owed_by"].get(borrower_name, 0)
144 lender_owes_borrower = lender["owes"].get(borrower_name, 0)
145
146 # Calculate net change in debt
147 # Positive means lender is owed more, negative means borrower is owed more
148 net_debt_change = amount if lender_name != borrower_name else 0
149
150 # Update the net debt
151 new_net_debt = lender_owed_by_borrower - lender_owes_borrower + net_debt_change
152
153 # Update lender's records
154 if new_net_debt > 0:
155 # Lender is owed by borrower
156 lender["owed_by"][borrower_name] = new_net_debt
157 lender["owes"].pop(borrower_name, None) # Remove if exists
158 elif new_net_debt < 0:
159 # Borrower is owed by lender (lender owes borrower)
160 lender["owes"][borrower_name] = -new_net_debt
161 lender["owed_by"].pop(borrower_name, None) # Remove if exists
162 else:
163 # No net debt
164 lender["owed_by"].pop(borrower_name, None) # Remove if exists
165 lender["owes"].pop(borrower_name, None) # Remove if exists
166
167 # Update borrower's records (opposite of lender)
168 if new_net_debt > 0:
169 # Borrower owes lender
170 borrower["owes"][lender_name] = new_net_debt
171 borrower["owed_by"].pop(lender_name, None) # Remove if exists
172 elif new_net_debt < 0:
173 # Lender owes borrower
174 borrower["owed_by"][lender_name] = -new_net_debt
175 borrower["owes"].pop(lender_name, None) # Remove if exists
176 else:
177 # No net debt
178 borrower["owed_by"].pop(lender_name, None) # Remove if exists
179 borrower["owes"].pop(lender_name, None) # Remove if exists
180
181 # Recalculate balances for both users
182 lender_total_owed = sum(lender["owed_by"].values())
183 lender_total_owes = sum(lender["owes"].values())
184 lender["balance"] = lender_total_owed - lender_total_owes
185
186 borrower_total_owed = sum(borrower["owed_by"].values())
187 borrower_total_owes = sum(borrower["owes"].values())
188 borrower["balance"] = borrower_total_owed - borrower_total_owes
189
190 # Return updated users sorted by name
191 updated_users = [lender, borrower]
192 updated_users.sort(key=lambda x: x["name"])
193
194 return json.dumps({"users": updated_users})
195
196 # Edge Case: Handle unknown URL
197 else:
198 raise ValueError(f"Unknown POST endpoint: {url}")
199
200 # Handled Edge Cases: /add and /iou endpoints, missing payload, missing fields,
201 # duplicate user, invalid amount, same lender/borrower,
202 # non-existent users, unknown URL
203
204 def _get_user(self, name: str):
205 """
206 Helper method to get a user by name.
207
208 Args:
209 name: The name of the user to find.
210
211 Returns:
212 The user object if found, None otherwise.
213 """
214 for user in self.database["users"]:
215 if user["name"] == name:
216 return user
217 return None
218
219# Handled Edge Cases: Initialization with None database
Test NameStatus
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_lender_owes_borrower
Pass
test_lender_owes_borrower_less_than_new_loan
Pass
test_lender_owes_borrower_same_as_new_loan
Pass
test_no_users
Pass

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