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 or None to start with an empty database.
10 """
11 if database is None:
12 self.database = {"users": []}
13 else:
14 self.database = database
15
516 def get(self, url: str, payload: str | None = None) -> str:
6 pass
7
17 """
18 Handle GET requests to the API.
19
20 Args:
21 url: The endpoint URL.
22 payload: Optional JSON payload.
23
24 Returns:
25 A JSON string response.
26
27 Raises:
28 ValueError: If the URL is not recognized.
29 """
30 if url == "/users":
31 if payload is None:
32 # Return all users
33 users = [self._create_user_object(user) for user in self.database["users"]]
34 return json.dumps({"users": users})
35 else:
36 # Return specific users
37 data = json.loads(payload)
38 user_names = data.get("users", [])
39
40 # Edge Case: Empty user list in payload
41 if not user_names:
42 return json.dumps({"users": []})
43
44 # Edge Case: Non-existent users in payload
45 result_users = []
46 for name in user_names:
47 user = self._find_user(name)
48 if user is not None:
49 result_users.append(self._create_user_object(user))
50
51 # Sort by name
52 result_users.sort(key=lambda u: u["name"])
53 return json.dumps({"users": result_users})
54 else:
55 # Edge Case: Invalid URL
56 raise ValueError(f"Invalid URL: {url}")
57
858 def post(self, url: str, payload: str | None = None) -> str:
9 pass
59 """
60 Handle POST requests to the API.
61
62 Args:
63 url: The endpoint URL.
64 payload: JSON payload.
65
66 Returns:
67 A JSON string response.
68
69 Raises:
70 ValueError: If the URL is not recognized or if there are validation errors.
71 """
72 if url == "/add":
73 if payload is None:
74 # Edge Case: Missing payload
75 raise ValueError("Payload required for /add endpoint")
76
77 data = json.loads(payload)
78 user_name = data.get("user")
79
80 # Edge Case: Missing user field
81 if user_name is None:
82 raise ValueError("'user' field is required")
83
84 # Edge Case: User already exists
85 existing_user = self._find_user(user_name)
86 if existing_user is not None:
87 return json.dumps(self._create_user_object(existing_user))
88
89 new_user = {
90 "name": user_name,
91 "owes": {},
92 "owed_by": {},
93 "balance": 0.0
94 }
95
96 self.database["users"].append(new_user)
97 return json.dumps(self._create_user_object(new_user))
98
99 elif url == "/iou":
100 if payload is None:
101 # Edge Case: Missing payload
102 raise ValueError("Payload required for /iou endpoint")
103
104 data = json.loads(payload)
105 lender_name = data.get("lender")
106 borrower_name = data.get("borrower")
107 amount = data.get("amount")
108
109 # Edge Case: Missing required fields
110 if lender_name is None or borrower_name is None or amount is None:
111 raise ValueError("'lender', 'borrower', and 'amount' fields are required")
112
113 # Edge Case: Lender and borrower are the same person
114 if lender_name == borrower_name:
115 raise ValueError("Lender and borrower cannot be the same person")
116
117 lender = self._find_user(lender_name)
118 borrower = self._find_user(borrower_name)
119
120 # Edge Case: Lender or borrower does not exist
121 if lender is None:
122 raise ValueError(f"User {lender_name} does not exist")
123 if borrower is None:
124 raise ValueError(f"User {borrower_name} does not exist")
125
126 # Edge Case: Negative amount
127 if amount < 0:
128 raise ValueError("Amount must be non-negative")
129
130 # Update lender's owed_by
131 if borrower_name in lender["owed_by"]:
132 lender["owed_by"][borrower_name] += amount
133 else:
134 lender["owed_by"][borrower_name] = amount
135
136 # Update borrower's owes
137 if lender_name in borrower["owes"]:
138 borrower["owes"][lender_name] += amount
139 else:
140 borrower["owes"][lender_name] = amount
141
142 # Update balances
143 lender["balance"] += amount
144 borrower["balance"] -= amount
145
146 # Return updated user objects
147 updated_users = [
148 self._create_user_object(lender),
149 self._create_user_object(borrower)
150 ]
151 updated_users.sort(key=lambda u: u["name"])
152 return json.dumps({"users": updated_users})
153
154 else:
155 # Edge Case: Invalid URL
156 raise ValueError(f"Invalid URL: {url}")
157
158 def _find_user(self, name: str):
159 """
160 Find a user by name in the database.
161
162 Args:
163 name: The name of the user to find.
164
165 Returns:
166 The user dictionary if found, otherwise None.
167 """
168 for user in self.database["users"]:
169 if user["name"] == name:
170 return user
171 return None
172
173 def _create_user_object(self, user):
174 """
175 Create a user object for API responses.
176
177 Args:
178 user: The user dictionary from the database.
179
180 Returns:
181 A dictionary representing the user object.
182 """
183 # Make sure we don't modify the original user object
184 return {
185 "name": user["name"],
186 "owes": user["owes"].copy(),
187 "owed_by": user["owed_by"].copy(),
188 "balance": user["balance"]
189 }
190# Handled Edge Cases: Invalid URL, Missing payload, Missing user field, User already exists, Missing required fields, Lender and borrower are the same person, Lender or borrower does not exist, Negative amount, Empty user list in payload, Non-existent users in payload
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.