database-wrapper 0.1.86__py3-none-any.whl → 0.2.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- database_wrapper/config.py +3 -3
- database_wrapper/db_backend.py +41 -40
- database_wrapper/db_data_model.py +102 -102
- database_wrapper/db_wrapper.py +179 -159
- database_wrapper/db_wrapper_async.py +177 -165
- database_wrapper/db_wrapper_mixin.py +72 -72
- database_wrapper/serialization.py +15 -17
- database_wrapper/utils/dataclass_addons.py +5 -5
- {database_wrapper-0.1.86.dist-info → database_wrapper-0.2.4.dist-info}/METADATA +10 -7
- database_wrapper-0.2.4.dist-info/RECORD +17 -0
- {database_wrapper-0.1.86.dist-info → database_wrapper-0.2.4.dist-info}/WHEEL +1 -1
- database_wrapper-0.1.86.dist-info/RECORD +0 -17
- {database_wrapper-0.1.86.dist-info → database_wrapper-0.2.4.dist-info}/top_level.txt +0 -0
|
@@ -17,208 +17,218 @@ class DBWrapperAsync(DBWrapperMixin):
|
|
|
17
17
|
#####################
|
|
18
18
|
|
|
19
19
|
# Action methods
|
|
20
|
-
async def
|
|
20
|
+
async def get_one(
|
|
21
21
|
self,
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
empty_data_class: DataModelType,
|
|
23
|
+
custom_query: Any = None,
|
|
24
24
|
) -> DataModelType | None:
|
|
25
25
|
"""
|
|
26
26
|
Retrieves a single record from the database by class defined id.
|
|
27
27
|
|
|
28
28
|
Args:
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
empty_data_class (DataModelType): The data model to use for the query.
|
|
30
|
+
custom_query (Any, optional): The custom query to use for the query. Defaults to None.
|
|
31
31
|
|
|
32
32
|
Returns:
|
|
33
33
|
DataModelType | None: The result of the query.
|
|
34
34
|
"""
|
|
35
35
|
# Figure out the id key and value
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if not
|
|
36
|
+
id_key = empty_data_class.id_key
|
|
37
|
+
id_value = empty_data_class.id
|
|
38
|
+
if not id_key:
|
|
39
39
|
raise ValueError("Id key is not set")
|
|
40
|
-
if not
|
|
40
|
+
if not id_value:
|
|
41
41
|
raise ValueError("Id value is not set")
|
|
42
42
|
|
|
43
43
|
# Get the record
|
|
44
|
-
res = self.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
res = self.fetch_all_records(
|
|
45
|
+
empty_data_class,
|
|
46
|
+
id_key,
|
|
47
|
+
id_value,
|
|
48
48
|
limit=1,
|
|
49
|
-
|
|
49
|
+
custom_query=custom_query,
|
|
50
50
|
)
|
|
51
51
|
async for row in res:
|
|
52
52
|
return row
|
|
53
53
|
else:
|
|
54
54
|
return None
|
|
55
55
|
|
|
56
|
-
async def
|
|
56
|
+
async def get_by_key(
|
|
57
57
|
self,
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
empty_data_class: DataModelType,
|
|
59
|
+
id_key: str,
|
|
60
|
+
id_value: Any,
|
|
61
|
+
custom_query: Any = None,
|
|
62
62
|
) -> DataModelType | None:
|
|
63
63
|
"""
|
|
64
64
|
Retrieves a single record from the database using the given key.
|
|
65
65
|
|
|
66
66
|
Args:
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
empty_data_class (DataModelType): The data model to use for the query.
|
|
68
|
+
id_key (str): The name of the key to use for the query.
|
|
69
|
+
id_value (Any): The value of the key to use for the query.
|
|
70
|
+
custom_query (Any, optional): The custom query to use for the query. Defaults to None.
|
|
71
71
|
|
|
72
72
|
Returns:
|
|
73
73
|
DataModelType | None: The result of the query.
|
|
74
74
|
"""
|
|
75
75
|
# Get the record
|
|
76
|
-
res = self.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
res = self.fetch_all_records(
|
|
77
|
+
empty_data_class,
|
|
78
|
+
id_key,
|
|
79
|
+
id_value,
|
|
80
80
|
limit=1,
|
|
81
|
-
|
|
81
|
+
custom_query=custom_query,
|
|
82
82
|
)
|
|
83
83
|
async for row in res:
|
|
84
84
|
return row
|
|
85
85
|
else:
|
|
86
86
|
return None
|
|
87
87
|
|
|
88
|
-
async def
|
|
88
|
+
async def fetch_all_records(
|
|
89
89
|
self,
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
90
|
+
empty_data_class: DataModelType,
|
|
91
|
+
id_key: str | None = None,
|
|
92
|
+
id_value: Any | None = None,
|
|
93
|
+
order_by: OrderByItem | None = None,
|
|
94
94
|
offset: int = 0,
|
|
95
95
|
limit: int = 100,
|
|
96
|
-
|
|
96
|
+
custom_query: Any = None,
|
|
97
97
|
) -> AsyncGenerator[DataModelType, None]:
|
|
98
98
|
"""
|
|
99
99
|
Retrieves all records from the database.
|
|
100
100
|
|
|
101
101
|
Args:
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
empty_data_class (DataModelType): The data model to use for the query.
|
|
103
|
+
id_key (str | None, optional): The name of the key to use for filtering. Defaults to None.
|
|
104
|
+
id_value (Any | None, optional): The value of the key to use for filtering. Defaults to None.
|
|
105
|
+
order_by (OrderByItem | None, optional): The order by item to use for sorting. Defaults to None.
|
|
106
106
|
offset (int, optional): The number of results to skip. Defaults to 0.
|
|
107
107
|
limit (int, optional): The maximum number of results to return. Defaults to 100.
|
|
108
|
-
|
|
108
|
+
custom_query (Any, optional): The custom query to use for the query. Defaults to None.
|
|
109
109
|
|
|
110
110
|
Returns:
|
|
111
111
|
AsyncGenerator[DataModelType, None]: The result of the query.
|
|
112
112
|
"""
|
|
113
113
|
# Query and filter
|
|
114
114
|
_query = (
|
|
115
|
-
|
|
116
|
-
or
|
|
117
|
-
or self.
|
|
115
|
+
custom_query
|
|
116
|
+
or empty_data_class.query_base()
|
|
117
|
+
or self.filter_query(
|
|
118
|
+
empty_data_class.schema_name,
|
|
119
|
+
empty_data_class.table_name,
|
|
120
|
+
)
|
|
118
121
|
)
|
|
119
122
|
_params: tuple[Any, ...] = ()
|
|
120
123
|
_filter = None
|
|
121
124
|
|
|
122
125
|
# TODO: Rewrite this so that filter method with loop is not used here
|
|
123
|
-
if
|
|
124
|
-
(_filter, _params) = self.
|
|
126
|
+
if id_key and id_value:
|
|
127
|
+
(_filter, _params) = self.create_filter({id_key: id_value})
|
|
125
128
|
|
|
126
129
|
# Order and limit
|
|
127
|
-
_order = self.
|
|
128
|
-
_limit = self.
|
|
130
|
+
_order = self.order_query(order_by)
|
|
131
|
+
_limit = self.limit_query(offset, limit)
|
|
129
132
|
|
|
130
133
|
# Create a SQL object for the query and format it
|
|
131
|
-
|
|
134
|
+
query_sql = self._format_filter_query(_query, _filter, _order, _limit)
|
|
132
135
|
|
|
133
136
|
# Log
|
|
134
|
-
self.
|
|
137
|
+
self.log_query(self.db_cursor, query_sql, _params)
|
|
135
138
|
|
|
136
139
|
# Execute the query
|
|
137
|
-
await self.
|
|
140
|
+
await self.db_cursor.execute(query_sql, _params)
|
|
138
141
|
|
|
139
142
|
# Instead of fetchall(), we'll use a generator to yield results one by one
|
|
140
143
|
while True:
|
|
141
|
-
row = await self.
|
|
144
|
+
row = await self.db_cursor.fetchone()
|
|
142
145
|
if row is None:
|
|
143
146
|
break
|
|
144
147
|
|
|
145
|
-
yield self.
|
|
148
|
+
yield self.turn_data_into_model(empty_data_class.__class__, row)
|
|
146
149
|
|
|
147
|
-
async def
|
|
150
|
+
async def get_filtered(
|
|
148
151
|
self,
|
|
149
|
-
|
|
152
|
+
empty_data_class: DataModelType,
|
|
150
153
|
filter: dict[str, Any],
|
|
151
|
-
|
|
154
|
+
order_by: OrderByItem | None = None,
|
|
152
155
|
offset: int = 0,
|
|
153
156
|
limit: int = 100,
|
|
154
|
-
|
|
157
|
+
custom_query: Any = None,
|
|
155
158
|
) -> AsyncGenerator[DataModelType, None]:
|
|
156
159
|
# Query and filter
|
|
157
160
|
_query = (
|
|
158
|
-
|
|
159
|
-
or
|
|
160
|
-
or self.
|
|
161
|
+
custom_query
|
|
162
|
+
or empty_data_class.query_base()
|
|
163
|
+
or self.filter_query(
|
|
164
|
+
empty_data_class.schema_name,
|
|
165
|
+
empty_data_class.table_name,
|
|
166
|
+
)
|
|
161
167
|
)
|
|
162
|
-
(_filter, _params) = self.
|
|
168
|
+
(_filter, _params) = self.create_filter(filter)
|
|
163
169
|
|
|
164
170
|
# Order and limit
|
|
165
|
-
_order = self.
|
|
166
|
-
_limit = self.
|
|
171
|
+
_order = self.order_query(order_by)
|
|
172
|
+
_limit = self.limit_query(offset, limit)
|
|
167
173
|
|
|
168
174
|
# Create SQL query
|
|
169
|
-
|
|
175
|
+
query_sql = self._format_filter_query(_query, _filter, _order, _limit)
|
|
170
176
|
|
|
171
177
|
# Log
|
|
172
|
-
self.
|
|
178
|
+
self.log_query(self.db_cursor, query_sql, _params)
|
|
173
179
|
|
|
174
180
|
# Execute the query
|
|
175
|
-
await self.
|
|
181
|
+
await self.db_cursor.execute(query_sql, _params)
|
|
176
182
|
|
|
177
183
|
# Instead of fetchall(), we'll use a generator to yield results one by one
|
|
178
184
|
while True:
|
|
179
|
-
row = await self.
|
|
185
|
+
row = await self.db_cursor.fetchone()
|
|
180
186
|
if row is None:
|
|
181
187
|
break
|
|
182
188
|
|
|
183
|
-
yield self.
|
|
189
|
+
yield self.turn_data_into_model(empty_data_class.__class__, row)
|
|
184
190
|
|
|
185
191
|
async def _insert(
|
|
186
192
|
self,
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
193
|
+
empty_data_class: DBDataModel,
|
|
194
|
+
schema_name: str | None,
|
|
195
|
+
table_name: str,
|
|
196
|
+
store_data: dict[str, Any],
|
|
197
|
+
id_key: str,
|
|
192
198
|
) -> tuple[int, int]:
|
|
193
199
|
"""
|
|
194
200
|
Stores a record in the database.
|
|
195
201
|
|
|
196
202
|
Args:
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
203
|
+
empty_data_class (DBDataModel): The data model to use for the query.
|
|
204
|
+
schema_name (str | None): The name of the schema to store the record in.
|
|
205
|
+
table_name (str): The name of the table to store the record in.
|
|
206
|
+
store_data (dict[str, Any]): The data to store.
|
|
207
|
+
id_key (str): The name of the key to use for the query.
|
|
202
208
|
|
|
203
209
|
Returns:
|
|
204
210
|
tuple[int, int]: The id of the record and the number of affected rows.
|
|
205
211
|
"""
|
|
206
|
-
values = list(
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
212
|
+
values = list(store_data.values())
|
|
213
|
+
table_identifier = self.make_identifier(schema_name, table_name)
|
|
214
|
+
return_key = self.make_identifier(empty_data_class.table_alias, id_key)
|
|
215
|
+
insert_query = self._format_insert_query(
|
|
216
|
+
table_identifier,
|
|
217
|
+
store_data,
|
|
218
|
+
return_key,
|
|
219
|
+
)
|
|
210
220
|
|
|
211
221
|
# Log
|
|
212
|
-
self.
|
|
222
|
+
self.log_query(self.db_cursor, insert_query, tuple(values))
|
|
213
223
|
|
|
214
224
|
# Insert
|
|
215
|
-
await self.
|
|
216
|
-
|
|
217
|
-
result = await self.
|
|
225
|
+
await self.db_cursor.execute(insert_query, tuple(values))
|
|
226
|
+
affected_rows = self.db_cursor.rowcount
|
|
227
|
+
result = await self.db_cursor.fetchone()
|
|
218
228
|
|
|
219
229
|
return (
|
|
220
|
-
result[
|
|
221
|
-
|
|
230
|
+
result[id_key] if result and id_key in result else 0,
|
|
231
|
+
affected_rows,
|
|
222
232
|
)
|
|
223
233
|
|
|
224
234
|
@overload
|
|
@@ -245,71 +255,73 @@ class DBWrapperAsync(DBWrapperMixin):
|
|
|
245
255
|
"""
|
|
246
256
|
status: list[tuple[int, int]] = []
|
|
247
257
|
|
|
248
|
-
|
|
258
|
+
one_record = False
|
|
249
259
|
if not isinstance(records, list):
|
|
250
|
-
|
|
260
|
+
one_record = True
|
|
251
261
|
records = [records]
|
|
252
262
|
|
|
253
263
|
for row in records:
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
if not
|
|
264
|
+
store_id_key = row.id_key
|
|
265
|
+
store_data = row.store_data()
|
|
266
|
+
if not store_id_key or not store_data:
|
|
257
267
|
continue
|
|
258
268
|
|
|
259
269
|
res = await self._insert(
|
|
260
270
|
row,
|
|
261
|
-
row.
|
|
262
|
-
row.
|
|
263
|
-
|
|
264
|
-
|
|
271
|
+
row.schema_name,
|
|
272
|
+
row.table_name,
|
|
273
|
+
store_data,
|
|
274
|
+
store_id_key,
|
|
265
275
|
)
|
|
266
276
|
if res:
|
|
267
277
|
row.id = res[0] # update the id of the row
|
|
268
278
|
|
|
269
279
|
status.append(res)
|
|
270
280
|
|
|
271
|
-
if
|
|
281
|
+
if one_record:
|
|
272
282
|
return status[0]
|
|
273
283
|
|
|
274
284
|
return status
|
|
275
285
|
|
|
276
286
|
async def _update(
|
|
277
287
|
self,
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
288
|
+
empty_data_class: DBDataModel,
|
|
289
|
+
schema_name: str | None,
|
|
290
|
+
table_name: str,
|
|
291
|
+
update_data: dict[str, Any],
|
|
292
|
+
update_id: tuple[str, Any],
|
|
283
293
|
) -> int:
|
|
284
294
|
"""
|
|
285
295
|
Updates a record in the database.
|
|
286
296
|
|
|
287
297
|
Args:
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
298
|
+
empty_data_class (DBDataModel): The data model to use for the query.
|
|
299
|
+
schema_name (str | None): The name of the schema to update the record in.
|
|
300
|
+
table_name (str): The name of the table to update the record in.
|
|
301
|
+
update_data (dict[str, Any]): The data to update.
|
|
302
|
+
update_id (tuple[str, Any]): The id of the record to update.
|
|
293
303
|
|
|
294
304
|
Returns:
|
|
295
305
|
int: The number of affected rows.
|
|
296
306
|
"""
|
|
297
|
-
(
|
|
298
|
-
values = list(
|
|
299
|
-
values.append(
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
307
|
+
(id_key, id_value) = update_id
|
|
308
|
+
values = list(update_data.values())
|
|
309
|
+
values.append(id_value)
|
|
310
|
+
|
|
311
|
+
table_identifier = self.make_identifier(schema_name, table_name)
|
|
312
|
+
update_key = self.make_identifier(empty_data_class.table_alias, id_key)
|
|
313
|
+
update_query = self._format_update_query(
|
|
314
|
+
table_identifier, update_key, update_data
|
|
315
|
+
)
|
|
304
316
|
|
|
305
317
|
# Log
|
|
306
|
-
self.
|
|
318
|
+
self.log_query(self.db_cursor, update_query, tuple(values))
|
|
307
319
|
|
|
308
320
|
# Update
|
|
309
|
-
await self.
|
|
310
|
-
|
|
321
|
+
await self.db_cursor.execute(update_query, tuple(values))
|
|
322
|
+
affected_rows = self.db_cursor.rowcount
|
|
311
323
|
|
|
312
|
-
return
|
|
324
|
+
return affected_rows
|
|
313
325
|
|
|
314
326
|
@overload
|
|
315
327
|
async def update(self, records: DataModelType) -> int: # type: ignore
|
|
@@ -333,53 +345,53 @@ class DBWrapperAsync(DBWrapperMixin):
|
|
|
333
345
|
"""
|
|
334
346
|
status: list[int] = []
|
|
335
347
|
|
|
336
|
-
|
|
348
|
+
one_record = False
|
|
337
349
|
if not isinstance(records, list):
|
|
338
|
-
|
|
350
|
+
one_record = True
|
|
339
351
|
records = [records]
|
|
340
352
|
|
|
341
353
|
for row in records:
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
if not
|
|
354
|
+
update_data = row.update_data()
|
|
355
|
+
update_id_key = row.id_key
|
|
356
|
+
update_id_value = row.id
|
|
357
|
+
if not update_data or not update_id_key or not update_id_value:
|
|
346
358
|
continue
|
|
347
359
|
|
|
348
360
|
status.append(
|
|
349
361
|
await self._update(
|
|
350
362
|
row,
|
|
351
|
-
row.
|
|
352
|
-
row.
|
|
353
|
-
|
|
363
|
+
row.schema_name,
|
|
364
|
+
row.table_name,
|
|
365
|
+
update_data,
|
|
354
366
|
(
|
|
355
|
-
|
|
356
|
-
|
|
367
|
+
update_id_key,
|
|
368
|
+
update_id_value,
|
|
357
369
|
),
|
|
358
370
|
)
|
|
359
371
|
)
|
|
360
372
|
|
|
361
|
-
if
|
|
373
|
+
if one_record:
|
|
362
374
|
return status[0]
|
|
363
375
|
|
|
364
376
|
return status
|
|
365
377
|
|
|
366
|
-
async def
|
|
378
|
+
async def update_data(
|
|
367
379
|
self,
|
|
368
380
|
record: DBDataModel,
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
381
|
+
update_data: dict[str, Any],
|
|
382
|
+
update_id_key: str | None = None,
|
|
383
|
+
update_id_value: Any = None,
|
|
372
384
|
) -> int:
|
|
373
|
-
|
|
374
|
-
|
|
385
|
+
update_id_key = update_id_key or record.id_key
|
|
386
|
+
update_id_value = update_id_value or record.id
|
|
375
387
|
status = await self._update(
|
|
376
388
|
record,
|
|
377
|
-
record.
|
|
378
|
-
record.
|
|
379
|
-
|
|
389
|
+
record.schema_name,
|
|
390
|
+
record.table_name,
|
|
391
|
+
update_data,
|
|
380
392
|
(
|
|
381
|
-
|
|
382
|
-
|
|
393
|
+
update_id_key,
|
|
394
|
+
update_id_value,
|
|
383
395
|
),
|
|
384
396
|
)
|
|
385
397
|
|
|
@@ -387,35 +399,35 @@ class DBWrapperAsync(DBWrapperMixin):
|
|
|
387
399
|
|
|
388
400
|
async def _delete(
|
|
389
401
|
self,
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
402
|
+
empty_data_class: DBDataModel,
|
|
403
|
+
schema_name: str | None,
|
|
404
|
+
table_name: str,
|
|
405
|
+
delete_id: tuple[str, Any],
|
|
394
406
|
) -> int:
|
|
395
407
|
"""
|
|
396
408
|
Deletes a record from the database.
|
|
397
409
|
|
|
398
410
|
Args:
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
411
|
+
empty_data_class (DBDataModel): The data model to use for the query.
|
|
412
|
+
schema_name (str | None): The name of the schema to delete the record from.
|
|
413
|
+
table_name (str): The name of the table to delete the record from.
|
|
414
|
+
delete_id (tuple[str, Any]): The id of the record to delete.
|
|
403
415
|
|
|
404
416
|
Returns:
|
|
405
417
|
int: The number of affected rows.
|
|
406
418
|
"""
|
|
407
|
-
(
|
|
419
|
+
(id_key, id_value) = delete_id
|
|
408
420
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
delete_query = self.
|
|
421
|
+
table_identifier = self.make_identifier(schema_name, table_name)
|
|
422
|
+
delete_key = self.make_identifier(empty_data_class.table_alias, id_key)
|
|
423
|
+
delete_query = self._format_delete_query(table_identifier, delete_key)
|
|
412
424
|
|
|
413
425
|
# Log
|
|
414
|
-
self.
|
|
426
|
+
self.log_query(self.db_cursor, delete_query, (id_value,))
|
|
415
427
|
|
|
416
428
|
# Delete
|
|
417
|
-
await self.
|
|
418
|
-
affected_rows = self.
|
|
429
|
+
await self.db_cursor.execute(delete_query, (id_value,))
|
|
430
|
+
affected_rows = self.db_cursor.rowcount
|
|
419
431
|
|
|
420
432
|
return affected_rows
|
|
421
433
|
|
|
@@ -441,30 +453,30 @@ class DBWrapperAsync(DBWrapperMixin):
|
|
|
441
453
|
"""
|
|
442
454
|
status: list[int] = []
|
|
443
455
|
|
|
444
|
-
|
|
456
|
+
one_record = False
|
|
445
457
|
if not isinstance(records, list):
|
|
446
|
-
|
|
458
|
+
one_record = True
|
|
447
459
|
records = [records]
|
|
448
460
|
|
|
449
461
|
for row in records:
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
if not
|
|
462
|
+
delete_id_key = row.id_key
|
|
463
|
+
delete_id_value = row.id
|
|
464
|
+
if not delete_id_key or not delete_id_value:
|
|
453
465
|
continue
|
|
454
466
|
|
|
455
467
|
status.append(
|
|
456
468
|
await self._delete(
|
|
457
469
|
row,
|
|
458
|
-
row.
|
|
459
|
-
row.
|
|
470
|
+
row.schema_name,
|
|
471
|
+
row.table_name,
|
|
460
472
|
(
|
|
461
|
-
|
|
462
|
-
|
|
473
|
+
delete_id_key,
|
|
474
|
+
delete_id_value,
|
|
463
475
|
),
|
|
464
476
|
)
|
|
465
477
|
)
|
|
466
478
|
|
|
467
|
-
if
|
|
479
|
+
if one_record:
|
|
468
480
|
return status[0]
|
|
469
481
|
|
|
470
482
|
return status
|