corpus

Finished
1import json
2from typing import Dict, List, Optional, Any
3
14class RestAPI:
5 """
6 A RESTful API for tracking IOUs between users.
7
8 This class manages user data and IOU transactions in memory.
9 It supports creating users, creating IOUs, and retrieving user information.
10 """
11
212 def __init__(self, database: dict | None = None):
3 pass
4
13 """
14 Initialize the RestAPI with an optional database.
15
16 Args:
17 database: Optional initial database with users data
18 """
19 if database and 'users' in database:
20 # Edge Case: Handle initialization with existing database
21 self.users = {}
22 for user_data in database['users']:
23 self.users[user_data['name']] = {
24 'name': user_data['name'],
25 'owes': user_data.get('owes', {}),
26 'owed_by': user_data.get('owed_by', {}),
27 'balance': user_data.get('balance', 0.0)
28 }
29 else:
30 # Edge Case: Handle initialization with no database
31 self.users = {}
32
533 def get(self, url: str, payload: str | None = None) -> str:
6 pass
7
34 """
35 Handle GET requests to the API.
36
37 Args:
38 url: The endpoint URL
39 payload: Optional JSON payload
40
41 Returns:
42 JSON string response
43
44 Raises:
45 ValueError: If URL is not recognized
46 """
47 if url == '/users':
48 # Edge Case: Handle GET /users with no payload (list all users)
49 if payload is None:
50 user_list = [self._get_user_info(name) for name in sorted(self.users.keys())]
51 return json.dumps({'users': user_list})
52 else:
53 # Edge Case: Handle GET /users with payload (list specific users)
54 try:
55 data = json.loads(payload)
56 if 'users' in data:
57 user_list = [self._get_user_info(name) for name in sorted(data['users']) if name in self.users]
58 return json.dumps({'users': user_list})
59 else:
60 # Edge Case: Handle malformed payload
61 return json.dumps({'users': []})
62 except json.JSONDecodeError:
63 # Edge Case: Handle invalid JSON payload
64 return json.dumps({'users': []})
65 else:
66 # Edge Case: Handle unknown URL
67 raise ValueError(f"Unknown GET endpoint: {url}")
68
69 # Handled Edge Cases: GET /users with no payload, GET /users with valid payload,
70 # GET /users with invalid payload, GET /users with malformed payload, unknown URL
71
872 def post(self, url: str, payload: str | None = None) -> str:
9 pass
73 """
74 Handle POST requests to the API.
75
76 Args:
77 url: The endpoint URL
78 payload: JSON payload
79
80 Returns:
81 JSON string response
82
83 Raises:
84 ValueError: If URL is not recognized or payload is invalid
85 """
86 if payload is None:
87 # Edge Case: Handle POST with no payload
88 raise ValueError("Payload is required for POST requests")
89
90 try:
91 data = json.loads(payload)
92 except json.JSONDecodeError:
93 # Edge Case: Handle invalid JSON payload
94 raise ValueError("Invalid JSON payload")
95
96 if url == '/add':
97 # Edge Case: Handle POST /add
98 if 'user' not in data:
99 # Edge Case: Handle missing user field
100 raise ValueError("Missing 'user' field in payload")
101
102 user_name = data['user']
103
104 # Edge Case: Handle duplicate user creation
105 if user_name in self.users:
106 raise ValueError(f"User '{user_name}' already exists")
107
108 # Create new user
109 new_user = {
110 'name': user_name,
111 'owes': {},
112 'owed_by': {},
113 'balance': 0.0
114 }
115 self.users[user_name] = new_user
116 return json.dumps(new_user)
117
118 elif url == '/iou':
119 # Edge Case: Handle POST /iou
120 required_fields = ['lender', 'borrower', 'amount']
121 for field in required_fields:
122 if field not in data:
123 # Edge Case: Handle missing required fields
124 raise ValueError(f"Missing '{field}' field in payload")
125
126 lender_name = data['lender']
127 borrower_name = data['borrower']
128 amount = data['amount']
129
130 # Edge Case: Handle lender and borrower are the same person
131 if lender_name == borrower_name:
132 raise ValueError("Lender and borrower cannot be the same person")
133
134 # Edge Case: Handle non-existent lender
135 if lender_name not in self.users:
136 raise ValueError(f"Lender '{lender_name}' does not exist")
137
138 # Edge Case: Handle non-existent borrower
139 if borrower_name not in self.users:
140 raise ValueError(f"Borrower '{borrower_name}' does not exist")
141
142 # Edge Case: Handle negative or zero amount
143 if amount <= 0:
144 raise ValueError("Amount must be positive")
145
146 # Update lender's owed_by
147 if borrower_name in self.users[lender_name]['owed_by']:
148 self.users[lender_name]['owed_by'][borrower_name] += amount
149 else:
150 self.users[lender_name]['owed_by'][borrower_name] = amount
151
152 # Update borrower's owes
153 if lender_name in self.users[borrower_name]['owes']:
154 self.users[borrower_name]['owes'][lender_name] += amount
155 else:
156 self.users[borrower_name]['owes'][lender_name] = amount
157
158 # Update balances
159 self.users[lender_name]['balance'] += amount
160 self.users[borrower_name]['balance'] -= amount
161
162 # Return updated user info
163 updated_users = [
164 self._get_user_info(lender_name),
165 self._get_user_info(borrower_name)
166 ]
167 updated_users.sort(key=lambda u: u['name'])
168
169 return json.dumps({'users': updated_users})
170 else:
171 # Edge Case: Handle unknown URL
172 raise ValueError(f"Unknown POST endpoint: {url}")
173
174 # Handled Edge Cases: POST with no payload, invalid JSON payload, POST /add with missing user field,
175 # POST /add with duplicate user, POST /iou with missing fields, POST /iou with same lender and borrower,
176 # POST /iou with non-existent lender, POST /iou with non-existent borrower, POST /iou with negative amount,
177 # unknown URL
178
179 def _get_user_info(self, name: str) -> Dict[str, Any]:
180 """
181 Get a user's information with calculated balance.
182
183 Args:
184 name: The user's name
185
186 Returns:
187 User information dictionary
188 """
189 user = self.users[name].copy()
190
191 # Calculate balance as (total owed by others) - (total owed to others)
192 total_owed_by = sum(user['owed_by'].values())
193 total_owes = sum(user['owes'].values())
194 user['balance'] = round(total_owed_by - total_owes, 2)
195
196 return user
197
198 # Handled Edge Cases: All cases related to balance calculation and user data retrieval
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.