Immune

Finished
1import json
2from typing import Dict, List, Optional, Any
3
14class RestAPI:
25 def __init__(self, database: dict | None = None):
3 pass
4
6 """
7 Initialize the REST API with an optional database.
8
9 Args:
10 database: Optional initial database containing users data
11 """
12 if database and 'users' in database:
13 # Edge Case: Handle initial database with users
14 self.users = {user['name']: user for user in database['users']}
15 else:
16 # Edge Case: Handle empty or None database
17 self.users = {}
18
19 def _get_user(self, name: str) -> Dict[str, Any]:
20 """
21 Get a user object with calculated balance.
22
23 Args:
24 name: Name of the user
25
26 Returns:
27 User object with name, owes, owed_by, and balance
28 """
29 if name not in self.users:
30 # Edge Case: User not found
31 raise KeyError(f"User {name} not found")
32
33 user = self.users[name]
34
35 # Calculate total owed to others
36 total_owed = sum(user.get('owes', {}).values())
37
38 # Calculate total owed by others
39 total_owed_by = sum(user.get('owed_by', {}).values())
40
41 # Calculate balance
42 balance = total_owed_by - total_owed
43
44 return {
45 'name': user['name'],
46 'owes': user.get('owes', {}),
47 'owed_by': user.get('owed_by', {}),
48 'balance': balance
49 }
50
551 def get(self, url: str, payload: str | None = None) -> str:
6 pass
7
52 """
53 Handle GET requests to the API.
54
55 Args:
56 url: The endpoint URL
57 payload: Optional JSON payload
58
59 Returns:
60 JSON response string
61 """
62 try:
63 if url == '/users':
64 if payload is None:
65 # Return all users
66 users_list = [self._get_user(name) for name in sorted(self.users.keys())]
67 return json.dumps({'users': users_list})
68 else:
69 # Return specific users
70 data = json.loads(payload)
71 if 'users' not in data:
72 # Edge Case: Malformed payload
73 return json.dumps({'error': 'Invalid payload format'})
74
75 # Edge Case: Empty users list in payload
76 if not data['users']:
77 return json.dumps({'users': []})
78
79 users_list = []
80 for name in sorted(data['users']):
81 if name in self.users:
82 users_list.append(self._get_user(name))
83 # Edge Case: Requested user not found - skip silently as per examples
84
85 return json.dumps({'users': users_list})
86 else:
87 # Edge Case: Invalid URL
88 return json.dumps({'error': 'Invalid URL'})
89 except json.JSONDecodeError:
90 # Edge Case: Invalid JSON payload
91 return json.dumps({'error': 'Invalid JSON payload'})
92 except Exception as e:
93 # Edge Case: Unexpected error
94 return json.dumps({'error': str(e)})
95
896 def post(self, url: str, payload: str | None = None) -> str:
9 pass
97 """
98 Handle POST requests to the API.
99
100 Args:
101 url: The endpoint URL
102 payload: JSON payload
103
104 Returns:
105 JSON response string
106 """
107 try:
108 if payload is None:
109 # Edge Case: Missing payload
110 return json.dumps({'error': 'Payload required'})
111
112 data = json.loads(payload)
113
114 if url == '/add':
115 # Add a new user
116 if 'user' not in data:
117 # Edge Case: Missing user field
118 return json.dumps({'error': 'Missing user field'})
119
120 name = data['user']
121
122 # Edge Case: User already exists
123 if name in self.users:
124 return json.dumps({'error': 'User already exists'})
125
126 # Create new user
127 new_user = {
128 'name': name,
129 'owes': {},
130 'owed_by': {}
131 }
132 self.users[name] = new_user
133
134 # Return the new user object with calculated balance
135 return json.dumps(self._get_user(name))
136
137 elif url == '/iou':
138 # Create a new IOU
139 required_fields = ['lender', 'borrower', 'amount']
140 for field in required_fields:
141 if field not in data:
142 # Edge Case: Missing required field
143 return json.dumps({'error': f'Missing {field} field'})
144
145 lender_name = data['lender']
146 borrower_name = data['borrower']
147 amount = data['amount']
148
149 # Edge Case: Lender and borrower are the same person
150 if lender_name == borrower_name:
151 return json.dumps({'error': 'Lender and borrower cannot be the same person'})
152
153 # Edge Case: Negative amount
154 if amount < 0:
155 return json.dumps({'error': 'Amount cannot be negative'})
156
157 # Edge Case: Lender not found
158 if lender_name not in self.users:
159 return json.dumps({'error': 'Lender not found'})
160
161 # Edge Case: Borrower not found
162 if borrower_name not in self.users:
163 return json.dumps({'error': 'Borrower not found'})
164
165 # Initialize owes/owed_by if they don't exist
166 if 'owes' not in self.users[lender_name]:
167 self.users[lender_name]['owes'] = {}
168 if 'owed_by' not in self.users[lender_name]:
169 self.users[lender_name]['owed_by'] = {}
170 if 'owes' not in self.users[borrower_name]:
171 self.users[borrower_name]['owes'] = {}
172 if 'owed_by' not in self.users[borrower_name]:
173 self.users[borrower_name]['owed_by'] = {}
174
175 # Update lender's owed_by
176 if borrower_name in self.users[lender_name]['owed_by']:
177 self.users[lender_name]['owed_by'][borrower_name] += amount
178 else:
179 self.users[lender_name]['owed_by'][borrower_name] = amount
180
181 # Update borrower's owes
182 if lender_name in self.users[borrower_name]['owes']:
183 self.users[borrower_name]['owes'][lender_name] += amount
184 else:
185 self.users[borrower_name]['owes'][lender_name] = amount
186
187 # Return updated user objects
188 lender = self._get_user(lender_name)
189 borrower = self._get_user(borrower_name)
190
191 # Sort by name
192 users_list = sorted([lender, borrower], key=lambda x: x['name'])
193
194 return json.dumps({'users': users_list})
195
196 else:
197 # Edge Case: Invalid URL
198 return json.dumps({'error': 'Invalid URL'})
199
200 except json.JSONDecodeError:
201 # Edge Case: Invalid JSON payload
202 return json.dumps({'error': 'Invalid JSON payload'})
203 except TypeError:
204 # Edge Case: Invalid data types in payload
205 return json.dumps({'error': 'Invalid data types in payload'})
206 except Exception as e:
207 # Edge Case: Unexpected error
208 return json.dumps({'error': str(e)})
209
210 # Handled Edge Cases:
211 # - Empty or None database initialization
212 # - User not found
213 # - Malformed payload
214 # - Empty users list in payload
215 # - Invalid URL
216 # - Invalid JSON payload
217 # - Unexpected error
218 # - Missing payload
219 # - Missing user field
220 # - User already exists
221 # - Missing required field
222 # - Lender and borrower are the same person
223 # - Negative amount
224 # - Lender not found
225 # - Borrower not found
226 # - Invalid data types in payload
227
228 # Handled Edge Cases:
229 # - User not found
230 # - Missing user field
231 # - User already exists
232 # - Missing required field
233 # - Lender and borrower are the same person
234 # - Negative amount
235 # - Lender not found
236 # - Borrower not found
237 # - Invalid JSON payload
238 # - Invalid data types in payload
239 # - Unexpected error
240 # - Invalid URL
241 # - Missing 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.