sapiopycommons 2025.3.6a451__py3-none-any.whl → 2025.3.6a454__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.
Potentially problematic release.
This version of sapiopycommons might be problematic. Click here for more details.
- sapiopycommons/customreport/auto_pagers.py +17 -25
- sapiopycommons/general/sapio_links.py +4 -12
- sapiopycommons/recordmodel/record_handler.py +101 -137
- {sapiopycommons-2025.3.6a451.dist-info → sapiopycommons-2025.3.6a454.dist-info}/METADATA +1 -1
- {sapiopycommons-2025.3.6a451.dist-info → sapiopycommons-2025.3.6a454.dist-info}/RECORD +7 -10
- sapiopycommons/ai/__init__.py +0 -0
- sapiopycommons/ai/tool_of_tools.py +0 -905
- sapiopycommons/general/html_formatter.py +0 -456
- {sapiopycommons-2025.3.6a451.dist-info → sapiopycommons-2025.3.6a454.dist-info}/WHEEL +0 -0
- {sapiopycommons-2025.3.6a451.dist-info → sapiopycommons-2025.3.6a454.dist-info}/licenses/LICENSE +0 -0
|
@@ -70,66 +70,56 @@ class RecordHandler:
|
|
|
70
70
|
self.rel_man = self.rec_man.relationship_manager
|
|
71
71
|
self.an_man = RecordModelAncestorManager(self.rec_man)
|
|
72
72
|
|
|
73
|
-
def wrap_model(self, record: DataRecord, wrapper_type: type[WrappedType]
|
|
74
|
-
-> WrappedType | PyRecordModel:
|
|
73
|
+
def wrap_model(self, record: DataRecord, wrapper_type: type[WrappedType]) -> WrappedType:
|
|
75
74
|
"""
|
|
76
75
|
Shorthand for adding a single data record as a record model.
|
|
77
76
|
|
|
78
77
|
:param record: The data record to wrap.
|
|
79
|
-
:param wrapper_type: The record model wrapper to use.
|
|
80
|
-
PyRecordModel instead of WrappedRecordModels.
|
|
78
|
+
:param wrapper_type: The record model wrapper to use.
|
|
81
79
|
:return: The record model for the input.
|
|
82
80
|
"""
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return self.inst_man.add_existing_record_of_type(record, wrapper_type)
|
|
86
|
-
return self.inst_man.add_existing_record(record)
|
|
81
|
+
self.__verify_data_type([record], wrapper_type)
|
|
82
|
+
return self.inst_man.add_existing_record_of_type(record, wrapper_type)
|
|
87
83
|
|
|
88
|
-
def wrap_models(self, records: Iterable[DataRecord], wrapper_type: type[WrappedType]
|
|
89
|
-
-> list[WrappedType] | list[PyRecordModel]:
|
|
84
|
+
def wrap_models(self, records: Iterable[DataRecord], wrapper_type: type[WrappedType]) -> list[WrappedType]:
|
|
90
85
|
"""
|
|
91
86
|
Shorthand for adding a list of data records as record models.
|
|
92
87
|
|
|
93
88
|
:param records: The data records to wrap.
|
|
94
|
-
:param wrapper_type: The record model wrapper to use.
|
|
95
|
-
PyRecordModels instead of WrappedRecordModels.
|
|
89
|
+
:param wrapper_type: The record model wrapper to use.
|
|
96
90
|
:return: The record models for the input.
|
|
97
91
|
"""
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return self.inst_man.add_existing_records_of_type(list(records), wrapper_type)
|
|
101
|
-
return self.inst_man.add_existing_records(list(records))
|
|
92
|
+
self.__verify_data_type(records, wrapper_type)
|
|
93
|
+
return self.inst_man.add_existing_records_of_type(list(records), wrapper_type)
|
|
102
94
|
|
|
103
|
-
def query_models(self, wrapper_type: type[WrappedType]
|
|
104
|
-
|
|
105
|
-
-> list[WrappedType] | list[PyRecordModel]:
|
|
95
|
+
def query_models(self, wrapper_type: type[WrappedType], field: FieldIdentifier, value_list: Iterable[FieldValue],
|
|
96
|
+
page_limit: int | None = None, page_size: int | None = None) -> list[WrappedType]:
|
|
106
97
|
"""
|
|
107
98
|
Shorthand for using the data record manager to query for a list of data records by field value
|
|
108
99
|
and then converting the results into a list of record models.
|
|
109
100
|
|
|
110
|
-
:param wrapper_type: The record model wrapper to use
|
|
101
|
+
:param wrapper_type: The record model wrapper to use.
|
|
111
102
|
:param field: The field to query on.
|
|
112
103
|
:param value_list: The values of the field to query on.
|
|
113
104
|
:param page_limit: The maximum number of pages to query. If None, exhausts all possible pages. This parameter
|
|
114
105
|
only functions if you set a page size or the platform enforces a page size.
|
|
115
106
|
:param page_size: The size of the pages to query. If None, the page size may be limited by the platform.
|
|
116
|
-
:return: The record models for the queried records.
|
|
117
|
-
then the returned records will be PyRecordModels instead of WrappedRecordModels.
|
|
107
|
+
:return: The record models for the queried records.
|
|
118
108
|
"""
|
|
119
109
|
criteria: DataRecordPojoPageCriteria | None = None
|
|
120
110
|
if page_size is not None:
|
|
121
111
|
criteria = DataRecordPojoPageCriteria(page_size=page_size)
|
|
122
112
|
return self.query_models_with_criteria(wrapper_type, field, value_list, criteria, page_limit)[0]
|
|
123
113
|
|
|
124
|
-
def query_and_map_models(self, wrapper_type: type[WrappedType]
|
|
114
|
+
def query_and_map_models(self, wrapper_type: type[WrappedType], field: FieldIdentifier,
|
|
125
115
|
value_list: Iterable[FieldValue], page_limit: int | None = None,
|
|
126
116
|
page_size: int | None = None, *, mapping_field: FieldIdentifier | None = None) \
|
|
127
|
-
-> dict[FieldValue, list[WrappedType]
|
|
117
|
+
-> dict[FieldValue, list[WrappedType]]:
|
|
128
118
|
"""
|
|
129
119
|
Shorthand for using query_models to search for records given values on a specific field and then using
|
|
130
120
|
map_by_field to turn the returned list into a dictionary mapping field values to records.
|
|
131
121
|
|
|
132
|
-
:param wrapper_type: The record model wrapper to use
|
|
122
|
+
:param wrapper_type: The record model wrapper to use.
|
|
133
123
|
:param field: The field to query and map on.
|
|
134
124
|
:param value_list: The values of the field to query on.
|
|
135
125
|
:param page_limit: The maximum number of pages to query. If None, exhausts all possible pages. This parameter
|
|
@@ -137,24 +127,22 @@ class RecordHandler:
|
|
|
137
127
|
:param page_size: The size of the pages to query. If None, the page size may be limited by the platform.
|
|
138
128
|
:param mapping_field: If provided, use this field to map against instead of the field that was queried on.
|
|
139
129
|
:return: The record models for the queried records mapped by field values to the records with that value.
|
|
140
|
-
If a data type name was used instead of a model wrapper, then the returned records will be PyRecordModels
|
|
141
|
-
instead of WrappedRecordModels.
|
|
142
130
|
"""
|
|
143
131
|
if mapping_field is None:
|
|
144
132
|
mapping_field = field
|
|
145
133
|
return self.map_by_field(self.query_models(wrapper_type, field, value_list, page_limit, page_size),
|
|
146
134
|
mapping_field)
|
|
147
135
|
|
|
148
|
-
def query_and_unique_map_models(self, wrapper_type: type[WrappedType]
|
|
136
|
+
def query_and_unique_map_models(self, wrapper_type: type[WrappedType], field: FieldIdentifier,
|
|
149
137
|
value_list: Iterable[FieldValue], page_limit: int | None = None,
|
|
150
138
|
page_size: int | None = None, *, mapping_field: FieldIdentifier | None = None) \
|
|
151
|
-
-> dict[FieldValue, WrappedType
|
|
139
|
+
-> dict[FieldValue, WrappedType]:
|
|
152
140
|
"""
|
|
153
141
|
Shorthand for using query_models to search for records given values on a specific field and then using
|
|
154
142
|
map_by_unique_field to turn the returned list into a dictionary mapping field values to records.
|
|
155
143
|
If any two records share the same field value, throws an exception.
|
|
156
144
|
|
|
157
|
-
:param wrapper_type: The record model wrapper to use
|
|
145
|
+
:param wrapper_type: The record model wrapper to use.
|
|
158
146
|
:param field: The field to query and map on.
|
|
159
147
|
:param value_list: The values of the field to query on.
|
|
160
148
|
:param page_limit: The maximum number of pages to query. If None, exhausts all possible pages. This parameter
|
|
@@ -162,32 +150,29 @@ class RecordHandler:
|
|
|
162
150
|
:param page_size: The size of the pages to query. If None, the page size may be limited by the platform.
|
|
163
151
|
:param mapping_field: If provided, use this field to map against instead of the field that was queried on.
|
|
164
152
|
:return: The record models for the queried records mapped by field values to the record with that value.
|
|
165
|
-
If a data type name was used instead of a model wrapper, then the returned records will be PyRecordModels
|
|
166
|
-
instead of WrappedRecordModels.
|
|
167
153
|
"""
|
|
168
154
|
if mapping_field is None:
|
|
169
155
|
mapping_field = field
|
|
170
156
|
return self.map_by_unique_field(self.query_models(wrapper_type, field, value_list, page_limit, page_size),
|
|
171
157
|
mapping_field)
|
|
172
158
|
|
|
173
|
-
def query_models_with_criteria(self, wrapper_type: type[WrappedType]
|
|
159
|
+
def query_models_with_criteria(self, wrapper_type: type[WrappedType], field: FieldIdentifier,
|
|
174
160
|
value_list: Iterable[FieldValue],
|
|
175
161
|
paging_criteria: DataRecordPojoPageCriteria | None = None,
|
|
176
162
|
page_limit: int | None = None) \
|
|
177
|
-
-> tuple[list[WrappedType]
|
|
163
|
+
-> tuple[list[WrappedType], DataRecordPojoPageCriteria]:
|
|
178
164
|
"""
|
|
179
165
|
Shorthand for using the data record manager to query for a list of data records by field value
|
|
180
166
|
and then converting the results into a list of record models.
|
|
181
167
|
|
|
182
|
-
:param wrapper_type: The record model wrapper to use
|
|
168
|
+
:param wrapper_type: The record model wrapper to use.
|
|
183
169
|
:param field: The field to query on.
|
|
184
170
|
:param value_list: The values of the field to query on.
|
|
185
171
|
:param paging_criteria: The paging criteria to start the query with.
|
|
186
172
|
:param page_limit: The maximum number of pages to query from the starting criteria. If None, exhausts all
|
|
187
173
|
possible pages. This parameter only functions if you set a page size in the paging criteria or the platform
|
|
188
174
|
enforces a page size.
|
|
189
|
-
:return: The record models for the queried records and the final paging criteria.
|
|
190
|
-
instead of a model wrapper, then the returned records will be PyRecordModels instead of WrappedRecordModels.
|
|
175
|
+
:return: The record models for the queried records and the final paging criteria.
|
|
191
176
|
"""
|
|
192
177
|
dt: str = wrapper_type.get_wrapper_data_type_name()
|
|
193
178
|
field: str = AliasUtil.to_data_field_name(field)
|
|
@@ -195,111 +180,104 @@ class RecordHandler:
|
|
|
195
180
|
pager.max_page = page_limit
|
|
196
181
|
return self.wrap_models(pager.get_all_at_once(), wrapper_type), pager.next_page_criteria
|
|
197
182
|
|
|
198
|
-
def query_models_by_id(self, wrapper_type: type[WrappedType]
|
|
199
|
-
page_limit: int | None = None, page_size: int | None = None)
|
|
200
|
-
-> list[WrappedType] | list[PyRecordModel]:
|
|
183
|
+
def query_models_by_id(self, wrapper_type: type[WrappedType], ids: Iterable[int],
|
|
184
|
+
page_limit: int | None = None, page_size: int | None = None) -> list[WrappedType]:
|
|
201
185
|
"""
|
|
202
186
|
Shorthand for using the data record manager to query for a list of data records by record ID
|
|
203
187
|
and then converting the results into a list of record models.
|
|
204
188
|
|
|
205
|
-
:param wrapper_type: The record model wrapper to use
|
|
189
|
+
:param wrapper_type: The record model wrapper to use.
|
|
206
190
|
:param ids: The list of record IDs to query.
|
|
207
191
|
:param page_limit: The maximum number of pages to query. If None, exhausts all possible pages. This parameter
|
|
208
192
|
only functions if you set a page size or the platform enforces a page size.
|
|
209
193
|
:param page_size: The size of the pages to query. If None, the page size may be limited by the platform.
|
|
210
|
-
:return: The record models for the queried records.
|
|
211
|
-
then the returned records will be PyRecordModels instead of WrappedRecordModels.
|
|
194
|
+
:return: The record models for the queried records.
|
|
212
195
|
"""
|
|
213
196
|
criteria: DataRecordPojoPageCriteria | None = None
|
|
214
197
|
if page_size is not None:
|
|
215
198
|
criteria = DataRecordPojoPageCriteria(page_size=page_size)
|
|
216
199
|
return self.query_models_by_id_with_criteria(wrapper_type, ids, criteria, page_limit)[0]
|
|
217
200
|
|
|
218
|
-
def query_models_by_id_with_criteria(self, wrapper_type: type[WrappedType]
|
|
201
|
+
def query_models_by_id_with_criteria(self, wrapper_type: type[WrappedType], ids: Iterable[int],
|
|
219
202
|
paging_criteria: DataRecordPojoPageCriteria | None = None,
|
|
220
203
|
page_limit: int | None = None) \
|
|
221
|
-
-> tuple[list[WrappedType]
|
|
204
|
+
-> tuple[list[WrappedType], DataRecordPojoPageCriteria]:
|
|
222
205
|
"""
|
|
223
206
|
Shorthand for using the data record manager to query for a list of data records by record ID
|
|
224
207
|
and then converting the results into a list of record models.
|
|
225
208
|
|
|
226
|
-
:param wrapper_type: The record model wrapper to use
|
|
209
|
+
:param wrapper_type: The record model wrapper to use.
|
|
227
210
|
:param ids: The list of record IDs to query.
|
|
228
211
|
:param paging_criteria: The paging criteria to start the query with.
|
|
229
212
|
:param page_limit: The maximum number of pages to query from the starting criteria. If None, exhausts all
|
|
230
213
|
possible pages. This parameter only functions if you set a page size in the paging criteria or the platform
|
|
231
214
|
enforces a page size.
|
|
232
|
-
:return: The record models for the queried records and the final paging criteria.
|
|
233
|
-
instead of a model wrapper, then the returned records will be PyRecordModels instead of WrappedRecordModels.
|
|
215
|
+
:return: The record models for the queried records and the final paging criteria.
|
|
234
216
|
"""
|
|
235
|
-
dt: str =
|
|
217
|
+
dt: str = wrapper_type.get_wrapper_data_type_name()
|
|
236
218
|
pager = QueryDataRecordByIdListAutoPager(dt, list(ids), self.user, paging_criteria)
|
|
237
219
|
pager.max_page = page_limit
|
|
238
220
|
return self.wrap_models(pager.get_all_at_once(), wrapper_type), pager.next_page_criteria
|
|
239
221
|
|
|
240
|
-
def query_models_by_id_and_map(self, wrapper_type: type[WrappedType]
|
|
222
|
+
def query_models_by_id_and_map(self, wrapper_type: type[WrappedType], ids: Iterable[int],
|
|
241
223
|
page_limit: int | None = None, page_size: int | None = None) \
|
|
242
|
-
-> dict[int, WrappedType
|
|
224
|
+
-> dict[int, WrappedType]:
|
|
243
225
|
"""
|
|
244
226
|
Shorthand for using the data record manager to query for a list of data records by record ID
|
|
245
227
|
and then converting the results into a dictionary of record ID to the record model for that ID.
|
|
246
228
|
|
|
247
|
-
:param wrapper_type: The record model wrapper to use
|
|
229
|
+
:param wrapper_type: The record model wrapper to use.
|
|
248
230
|
:param ids: The list of record IDs to query.
|
|
249
231
|
:param page_limit: The maximum number of pages to query. If None, exhausts all possible pages. This parameter
|
|
250
232
|
only functions if you set a page size or the platform enforces a page size.
|
|
251
233
|
:param page_size: The size of the pages to query. If None, the page size may be limited by the platform.
|
|
252
234
|
:return: The record models for the queried records mapped in a dictionary by their record ID.
|
|
253
|
-
If a data type name was used instead of a model wrapper, then the returned records will be PyRecordModels
|
|
254
|
-
instead of WrappedRecordModels.
|
|
255
235
|
"""
|
|
256
236
|
return {AliasUtil.to_record_id(x): x for x in self.query_models_by_id(wrapper_type, ids, page_limit, page_size)}
|
|
257
237
|
|
|
258
|
-
def query_all_models(self, wrapper_type: type[WrappedType]
|
|
259
|
-
page_size: int | None = None) -> list[WrappedType]
|
|
238
|
+
def query_all_models(self, wrapper_type: type[WrappedType], page_limit: int | None = None,
|
|
239
|
+
page_size: int | None = None) -> list[WrappedType]:
|
|
260
240
|
"""
|
|
261
241
|
Shorthand for using the data record manager to query for all data records of a given type
|
|
262
242
|
and then converting the results into a list of record models.
|
|
263
243
|
|
|
264
|
-
:param wrapper_type: The record model wrapper to use
|
|
244
|
+
:param wrapper_type: The record model wrapper to use.
|
|
265
245
|
:param page_limit: The maximum number of pages to query. If None, exhausts all possible pages. This parameter
|
|
266
246
|
only functions if you set a page size or the platform enforces a page size.
|
|
267
247
|
:param page_size: The size of the pages to query. If None, the page size may be limited by the platform.
|
|
268
|
-
:return: The record models for the queried records.
|
|
269
|
-
then the returned records will be PyRecordModels instead of WrappedRecordModels.
|
|
248
|
+
:return: The record models for the queried records.
|
|
270
249
|
"""
|
|
271
250
|
criteria: DataRecordPojoPageCriteria | None = None
|
|
272
251
|
if page_size is not None:
|
|
273
252
|
criteria = DataRecordPojoPageCriteria(page_size=page_size)
|
|
274
253
|
return self.query_all_models_with_criteria(wrapper_type, criteria, page_limit)[0]
|
|
275
254
|
|
|
276
|
-
def query_all_models_with_criteria(self, wrapper_type: type[WrappedType]
|
|
255
|
+
def query_all_models_with_criteria(self, wrapper_type: type[WrappedType],
|
|
277
256
|
paging_criteria: DataRecordPojoPageCriteria | None = None,
|
|
278
257
|
page_limit: int | None = None) \
|
|
279
|
-
-> tuple[list[WrappedType]
|
|
258
|
+
-> tuple[list[WrappedType], DataRecordPojoPageCriteria]:
|
|
280
259
|
"""
|
|
281
260
|
Shorthand for using the data record manager to query for all data records of a given type
|
|
282
261
|
and then converting the results into a list of record models.
|
|
283
262
|
|
|
284
|
-
:param wrapper_type: The record model wrapper to use
|
|
263
|
+
:param wrapper_type: The record model wrapper to use.
|
|
285
264
|
:param paging_criteria: The paging criteria to start the query with.
|
|
286
265
|
:param page_limit: The maximum number of pages to query from the starting criteria. If None, exhausts all
|
|
287
266
|
possible pages. This parameter only functions if you set a page size in the paging criteria or the platform
|
|
288
267
|
enforces a page size.
|
|
289
|
-
:return: The record models for the queried records and the final paging criteria.
|
|
290
|
-
instead of a model wrapper, then the returned records will be PyRecordModels instead of WrappedRecordModels.
|
|
268
|
+
:return: The record models for the queried records and the final paging criteria.
|
|
291
269
|
"""
|
|
292
270
|
dt: str = wrapper_type.get_wrapper_data_type_name()
|
|
293
271
|
pager = QueryAllRecordsOfTypeAutoPager(dt, self.user, paging_criteria)
|
|
294
272
|
pager.max_page = page_limit
|
|
295
273
|
return self.wrap_models(pager.get_all_at_once(), wrapper_type), pager.next_page_criteria
|
|
296
274
|
|
|
297
|
-
def query_models_by_report(self, wrapper_type: type[WrappedType]
|
|
275
|
+
def query_models_by_report(self, wrapper_type: type[WrappedType],
|
|
298
276
|
report_name: str | RawReportTerm | CustomReportCriteria,
|
|
299
277
|
filters: dict[FieldIdentifierKey, Iterable[FieldValue]] | None = None,
|
|
300
278
|
page_limit: int | None = None,
|
|
301
279
|
page_size: int | None = None,
|
|
302
|
-
page_number: int | None = None) -> list[WrappedType]
|
|
280
|
+
page_number: int | None = None) -> list[WrappedType]:
|
|
303
281
|
"""
|
|
304
282
|
Run a report and use the results of that report to query for and return the records in the report results.
|
|
305
283
|
First runs the report, then runs a data record manager query on the results of the custom report.
|
|
@@ -309,7 +287,7 @@ class RecordHandler:
|
|
|
309
287
|
|
|
310
288
|
Any given custom report criteria should only have columns from a single data type.
|
|
311
289
|
|
|
312
|
-
:param wrapper_type: The record model wrapper to use
|
|
290
|
+
:param wrapper_type: The record model wrapper to use.
|
|
313
291
|
:param report_name: The name of a system report, or a raw report term for a quick report, or custom report
|
|
314
292
|
criteria for a custom report.
|
|
315
293
|
:param filters: If provided, filter the results of the report using the given mapping of headers to values to
|
|
@@ -321,8 +299,7 @@ class RecordHandler:
|
|
|
321
299
|
:param page_number: The page number to start the search from, If None, starts on the first page.
|
|
322
300
|
If the input report is a custom report criteria, uses the value from the criteria, unless this value is
|
|
323
301
|
not None, in which case it overwrites the given report's value. Note that the number of the first page is 0.
|
|
324
|
-
:return: The record models for the queried records that matched the given report.
|
|
325
|
-
instead of a model wrapper, then the returned records will be PyRecordModels instead of WrappedRecordModels.
|
|
302
|
+
:return: The record models for the queried records that matched the given report.
|
|
326
303
|
"""
|
|
327
304
|
warnings.warn("Deprecated in favor of the [System/Custom/Quick]ReportRecordAutoPager classes.", DeprecationWarning)
|
|
328
305
|
if isinstance(report_name, str):
|
|
@@ -332,7 +309,7 @@ class RecordHandler:
|
|
|
332
309
|
results: list[dict[str, FieldValue]] = CustomReportUtil.run_quick_report(self.user, report_name, filters,
|
|
333
310
|
page_limit, page_size, page_number)
|
|
334
311
|
elif isinstance(report_name, CustomReportCriteria):
|
|
335
|
-
dt: str =
|
|
312
|
+
dt: str = wrapper_type.get_wrapper_data_type_name()
|
|
336
313
|
# Ensure that the root data type is the one we're looking for.
|
|
337
314
|
report_name.root_data_type = dt
|
|
338
315
|
# Raise an exception if any column in the report doesn't match the given data type.
|
|
@@ -352,38 +329,35 @@ class RecordHandler:
|
|
|
352
329
|
ids: list[int] = [row["RecordId"] for row in results]
|
|
353
330
|
return self.query_models_by_id(wrapper_type, ids)
|
|
354
331
|
|
|
355
|
-
def add_model(self, wrapper_type: type[WrappedType]
|
|
332
|
+
def add_model(self, wrapper_type: type[WrappedType]) -> WrappedType:
|
|
356
333
|
"""
|
|
357
334
|
Shorthand for using the instance manager to add a new record model of the given type.
|
|
358
335
|
|
|
359
|
-
:param wrapper_type: The record model wrapper to use
|
|
360
|
-
:return: The newly added record model.
|
|
361
|
-
returned record will be a PyRecordModel instead of a WrappedRecordModel.
|
|
336
|
+
:param wrapper_type: The record model wrapper to use.
|
|
337
|
+
:return: The newly added record model.
|
|
362
338
|
"""
|
|
363
339
|
return self.inst_man.add_new_record_of_type(wrapper_type)
|
|
364
340
|
|
|
365
|
-
def add_models(self, wrapper_type: type[WrappedType]
|
|
341
|
+
def add_models(self, wrapper_type: type[WrappedType], num: int) -> list[WrappedType]:
|
|
366
342
|
"""
|
|
367
343
|
Shorthand for using the instance manager to add new record models of the given type.
|
|
368
344
|
|
|
369
|
-
:param wrapper_type: The record model wrapper to use
|
|
345
|
+
:param wrapper_type: The record model wrapper to use.
|
|
370
346
|
:param num: The number of models to create.
|
|
371
|
-
:return: The newly added record models.
|
|
372
|
-
returned records will be PyRecordModels instead of WrappedRecordModels.
|
|
347
|
+
:return: The newly added record models.
|
|
373
348
|
"""
|
|
374
349
|
return self.inst_man.add_new_records_of_type(num, wrapper_type)
|
|
375
350
|
|
|
376
|
-
def add_models_with_data(self, wrapper_type: type[WrappedType]
|
|
377
|
-
-> list[WrappedType]
|
|
351
|
+
def add_models_with_data(self, wrapper_type: type[WrappedType], fields: list[FieldIdentifierMap]) \
|
|
352
|
+
-> list[WrappedType]:
|
|
378
353
|
"""
|
|
379
354
|
Shorthand for using the instance manager to add new models of the given type, and then initializing all those
|
|
380
355
|
models with the given fields.
|
|
381
356
|
|
|
382
|
-
:param wrapper_type: The record model wrapper to use
|
|
357
|
+
:param wrapper_type: The record model wrapper to use.
|
|
383
358
|
:param fields: A list of field maps to initialize the record models with.
|
|
384
359
|
:return: The newly added record models with the provided fields set. The records will be in the same order as
|
|
385
|
-
the fields in the fields list.
|
|
386
|
-
records will be PyRecordModels instead of WrappedRecordModels.
|
|
360
|
+
the fields in the fields list.
|
|
387
361
|
"""
|
|
388
362
|
fields: list[FieldMap] = AliasUtil.to_data_field_names_list_dict(fields)
|
|
389
363
|
models: list[WrappedType] = self.add_models(wrapper_type, len(fields))
|
|
@@ -391,9 +365,8 @@ class RecordHandler:
|
|
|
391
365
|
model.set_field_values(field_list)
|
|
392
366
|
return models
|
|
393
367
|
|
|
394
|
-
def find_or_add_model(self, wrapper_type: type[WrappedType]
|
|
395
|
-
id_value: FieldValue, secondary_identifiers: FieldIdentifierMap | None = None)
|
|
396
|
-
-> WrappedType | PyRecordModel:
|
|
368
|
+
def find_or_add_model(self, wrapper_type: type[WrappedType], primary_identifier: FieldIdentifier,
|
|
369
|
+
id_value: FieldValue, secondary_identifiers: FieldIdentifierMap | None = None) -> WrappedType:
|
|
397
370
|
"""
|
|
398
371
|
Find a unique record that matches the given field values. If no such records exist, add a record model to the
|
|
399
372
|
cache with the identifying fields set to the desired values. This record will be created in the system when
|
|
@@ -404,14 +377,12 @@ class RecordHandler:
|
|
|
404
377
|
|
|
405
378
|
Makes a webservice call to query for the existing record.
|
|
406
379
|
|
|
407
|
-
:param wrapper_type: The record model wrapper to use
|
|
380
|
+
:param wrapper_type: The record model wrapper to use.
|
|
408
381
|
:param primary_identifier: The data field name of the field to search on.
|
|
409
382
|
:param id_value: The value of the identifying field to search for.
|
|
410
383
|
:param secondary_identifiers: Optional fields used to filter the records that are returned after searching on
|
|
411
384
|
the primary identifier.
|
|
412
385
|
:return: The record model with the identifying field value, either pulled from the system or newly created.
|
|
413
|
-
If a data type name was used instead of a model wrapper, then the returned record will be a PyRecordModel
|
|
414
|
-
instead of a WrappedRecordModel.
|
|
415
386
|
"""
|
|
416
387
|
# PR-46335: Initialize the secondary identifiers parameter if None is provided to avoid an exception.
|
|
417
388
|
# If no secondary identifiers were provided, use an empty dictionary.
|
|
@@ -432,23 +403,22 @@ class RecordHandler:
|
|
|
432
403
|
secondary_identifiers.update({primary_identifier: id_value})
|
|
433
404
|
return self.add_models_with_data(wrapper_type, [secondary_identifiers])[0]
|
|
434
405
|
|
|
435
|
-
def create_models(self, wrapper_type: type[WrappedType]
|
|
406
|
+
def create_models(self, wrapper_type: type[WrappedType], num: int) -> list[WrappedType]:
|
|
436
407
|
"""
|
|
437
408
|
Shorthand for creating new records via the data record manager and then returning them as wrapped
|
|
438
409
|
record models. Useful in cases where your record model needs to have a valid record ID.
|
|
439
410
|
|
|
440
411
|
Makes a webservice call to create the data records.
|
|
441
412
|
|
|
442
|
-
:param wrapper_type: The record model wrapper to use
|
|
413
|
+
:param wrapper_type: The record model wrapper to use.
|
|
443
414
|
:param num: The number of new records to create.
|
|
444
|
-
:return: The newly created record models.
|
|
445
|
-
returned records will be PyRecordModels instead of WrappedRecordModels.
|
|
415
|
+
:return: The newly created record models.
|
|
446
416
|
"""
|
|
447
417
|
dt: str = wrapper_type.get_wrapper_data_type_name()
|
|
448
418
|
return self.wrap_models(self.dr_man.add_data_records(dt, num), wrapper_type)
|
|
449
419
|
|
|
450
|
-
def create_models_with_data(self, wrapper_type: type[WrappedType]
|
|
451
|
-
-> list[WrappedType]
|
|
420
|
+
def create_models_with_data(self, wrapper_type: type[WrappedType], fields: list[FieldIdentifierMap]) \
|
|
421
|
+
-> list[WrappedType]:
|
|
452
422
|
"""
|
|
453
423
|
Shorthand for creating new records via the data record manager with field data to initialize the records with
|
|
454
424
|
and then returning them as wrapped record models. Useful in cases where your record model needs to have a valid
|
|
@@ -456,18 +426,17 @@ class RecordHandler:
|
|
|
456
426
|
|
|
457
427
|
Makes a webservice call to create the data records.
|
|
458
428
|
|
|
459
|
-
:param wrapper_type: The record model wrapper to use
|
|
429
|
+
:param wrapper_type: The record model wrapper to use.
|
|
460
430
|
:param fields: The field map list to initialize the new data records with.
|
|
461
|
-
:return: The newly created record models.
|
|
462
|
-
returned records will be PyRecordModels instead of WrappedRecordModels.
|
|
431
|
+
:return: The newly created record models.
|
|
463
432
|
"""
|
|
464
433
|
dt: str = wrapper_type.get_wrapper_data_type_name()
|
|
465
434
|
fields: list[FieldMap] = AliasUtil.to_data_field_names_list_dict(fields)
|
|
466
435
|
return self.wrap_models(self.dr_man.add_data_records_with_data(dt, fields), wrapper_type)
|
|
467
436
|
|
|
468
|
-
def find_or_create_model(self, wrapper_type: type[WrappedType]
|
|
437
|
+
def find_or_create_model(self, wrapper_type: type[WrappedType], primary_identifier: FieldIdentifier,
|
|
469
438
|
id_value: FieldValue, secondary_identifiers: FieldIdentifierMap | None = None) \
|
|
470
|
-
-> WrappedType
|
|
439
|
+
-> WrappedType:
|
|
471
440
|
"""
|
|
472
441
|
Find a unique record that matches the given field values. If no such records exist, create one with the
|
|
473
442
|
identifying fields set to the desired values. If more than one record with the identifying values exists,
|
|
@@ -479,14 +448,12 @@ class RecordHandler:
|
|
|
479
448
|
Makes a webservice call to query for the existing record. Makes an additional webservice call if the record
|
|
480
449
|
needs to be created.
|
|
481
450
|
|
|
482
|
-
:param wrapper_type: The record model wrapper to use
|
|
451
|
+
:param wrapper_type: The record model wrapper to use.
|
|
483
452
|
:param primary_identifier: The data field name of the field to search on.
|
|
484
453
|
:param id_value: The value of the identifying field to search for.
|
|
485
454
|
:param secondary_identifiers: Optional fields used to filter the records that are returned after searching on
|
|
486
455
|
the primary identifier.
|
|
487
456
|
:return: The record model with the identifying field value, either pulled from the system or newly created.
|
|
488
|
-
If a data type name was used instead of a model wrapper, then the returned record will be a PyRecordModel
|
|
489
|
-
instead of a WrappedRecordModel.
|
|
490
457
|
"""
|
|
491
458
|
# PR-46335: Initialize the secondary identifiers parameter if None is provided to avoid an exception.
|
|
492
459
|
# If no secondary identifiers were provided, use an empty dictionary.
|
|
@@ -508,8 +475,7 @@ class RecordHandler:
|
|
|
508
475
|
return self.create_models_with_data(wrapper_type, [secondary_identifiers])[0]
|
|
509
476
|
|
|
510
477
|
@staticmethod
|
|
511
|
-
def map_to_parent(models: Iterable[
|
|
512
|
-
-> dict[WrappedRecordModel, WrappedType]:
|
|
478
|
+
def map_to_parent(models: Iterable[RecordModel], parent_type: type[WrappedType]) -> dict[RecordModel, WrappedType]:
|
|
513
479
|
"""
|
|
514
480
|
Map a list of record models to a single parent of a given type. The parents must already be loaded.
|
|
515
481
|
|
|
@@ -518,14 +484,14 @@ class RecordHandler:
|
|
|
518
484
|
:return: A dict[ModelType, ParentType]. If an input model doesn't have a parent of the given parent type, then
|
|
519
485
|
it will map to None.
|
|
520
486
|
"""
|
|
521
|
-
return_dict: dict[
|
|
487
|
+
return_dict: dict[RecordModel, WrappedType] = {}
|
|
522
488
|
for model in models:
|
|
523
489
|
return_dict[model] = model.get_parent_of_type(parent_type)
|
|
524
490
|
return return_dict
|
|
525
491
|
|
|
526
492
|
@staticmethod
|
|
527
|
-
def map_to_parents(models: Iterable[
|
|
528
|
-
-> dict[
|
|
493
|
+
def map_to_parents(models: Iterable[RecordModel], parent_type: type[WrappedType]) \
|
|
494
|
+
-> dict[RecordModel, list[WrappedType]]:
|
|
529
495
|
"""
|
|
530
496
|
Map a list of record models to a list parents of a given type. The parents must already be loaded.
|
|
531
497
|
|
|
@@ -534,14 +500,14 @@ class RecordHandler:
|
|
|
534
500
|
:return: A dict[ModelType, list[ParentType]]. If an input model doesn't have a parent of the given parent type,
|
|
535
501
|
then it will map to an empty list.
|
|
536
502
|
"""
|
|
537
|
-
return_dict: dict[
|
|
503
|
+
return_dict: dict[RecordModel, list[WrappedType]] = {}
|
|
538
504
|
for model in models:
|
|
539
505
|
return_dict[model] = model.get_parents_of_type(parent_type)
|
|
540
506
|
return return_dict
|
|
541
507
|
|
|
542
508
|
@staticmethod
|
|
543
|
-
def map_by_parent(models: Iterable[
|
|
544
|
-
-> dict[WrappedType,
|
|
509
|
+
def map_by_parent(models: Iterable[RecordModel], parent_type: type[WrappedType]) \
|
|
510
|
+
-> dict[WrappedType, RecordModel]:
|
|
545
511
|
"""
|
|
546
512
|
Take a list of record models and map them by their parent. Essentially an inversion of map_to_parent.
|
|
547
513
|
If two records share the same parent, an exception will be thrown. The parents must already be loaded.
|
|
@@ -551,8 +517,8 @@ class RecordHandler:
|
|
|
551
517
|
:return: A dict[ParentType, ModelType]. If an input model doesn't have a parent of the given parent type,
|
|
552
518
|
then it will not be in the resulting dictionary.
|
|
553
519
|
"""
|
|
554
|
-
to_parent: dict[
|
|
555
|
-
by_parent: dict[WrappedType,
|
|
520
|
+
to_parent: dict[RecordModel, WrappedType] = RecordHandler.map_to_parent(models, parent_type)
|
|
521
|
+
by_parent: dict[WrappedType, RecordModel] = {}
|
|
556
522
|
for record, parent in to_parent.items():
|
|
557
523
|
if parent is None:
|
|
558
524
|
continue
|
|
@@ -563,8 +529,8 @@ class RecordHandler:
|
|
|
563
529
|
return by_parent
|
|
564
530
|
|
|
565
531
|
@staticmethod
|
|
566
|
-
def map_by_parents(models: Iterable[
|
|
567
|
-
-> dict[WrappedType, list[
|
|
532
|
+
def map_by_parents(models: Iterable[RecordModel], parent_type: type[WrappedType]) \
|
|
533
|
+
-> dict[WrappedType, list[RecordModel]]:
|
|
568
534
|
"""
|
|
569
535
|
Take a list of record models and map them by their parents. Essentially an inversion of map_to_parents. Input
|
|
570
536
|
models that share a parent will end up in the same list. The parents must already be loaded.
|
|
@@ -574,16 +540,15 @@ class RecordHandler:
|
|
|
574
540
|
:return: A dict[ParentType, list[ModelType]]. If an input model doesn't have a parent of the given parent type,
|
|
575
541
|
then it will not be in the resulting dictionary.
|
|
576
542
|
"""
|
|
577
|
-
to_parents: dict[
|
|
578
|
-
by_parents: dict[WrappedType, list[
|
|
543
|
+
to_parents: dict[RecordModel, list[WrappedType]] = RecordHandler.map_to_parents(models, parent_type)
|
|
544
|
+
by_parents: dict[WrappedType, list[RecordModel]] = {}
|
|
579
545
|
for record, parents in to_parents.items():
|
|
580
546
|
for parent in parents:
|
|
581
547
|
by_parents.setdefault(parent, []).append(record)
|
|
582
548
|
return by_parents
|
|
583
549
|
|
|
584
550
|
@staticmethod
|
|
585
|
-
def map_to_child(models: Iterable[
|
|
586
|
-
-> dict[WrappedRecordModel, WrappedType]:
|
|
551
|
+
def map_to_child(models: Iterable[RecordModel], child_type: type[WrappedType]) -> dict[RecordModel, WrappedType]:
|
|
587
552
|
"""
|
|
588
553
|
Map a list of record models to a single child of a given type. The children must already be loaded.
|
|
589
554
|
|
|
@@ -592,14 +557,14 @@ class RecordHandler:
|
|
|
592
557
|
:return: A dict[ModelType, ChildType]. If an input model doesn't have a child of the given child type, then
|
|
593
558
|
it will map to None.
|
|
594
559
|
"""
|
|
595
|
-
return_dict: dict[
|
|
560
|
+
return_dict: dict[RecordModel, WrappedType] = {}
|
|
596
561
|
for model in models:
|
|
597
562
|
return_dict[model] = model.get_child_of_type(child_type)
|
|
598
563
|
return return_dict
|
|
599
564
|
|
|
600
565
|
@staticmethod
|
|
601
|
-
def map_to_children(models: Iterable[
|
|
602
|
-
-> dict[
|
|
566
|
+
def map_to_children(models: Iterable[RecordModel], child_type: type[WrappedType]) \
|
|
567
|
+
-> dict[RecordModel, list[WrappedType]]:
|
|
603
568
|
"""
|
|
604
569
|
Map a list of record models to a list children of a given type. The children must already be loaded.
|
|
605
570
|
|
|
@@ -608,14 +573,14 @@ class RecordHandler:
|
|
|
608
573
|
:return: A dict[ModelType, list[ChildType]]. If an input model doesn't have children of the given child type,
|
|
609
574
|
then it will map to an empty list.
|
|
610
575
|
"""
|
|
611
|
-
return_dict: dict[
|
|
576
|
+
return_dict: dict[RecordModel, list[WrappedType]] = {}
|
|
612
577
|
for model in models:
|
|
613
578
|
return_dict[model] = model.get_children_of_type(child_type)
|
|
614
579
|
return return_dict
|
|
615
580
|
|
|
616
581
|
@staticmethod
|
|
617
|
-
def map_by_child(models: Iterable[
|
|
618
|
-
-> dict[WrappedType,
|
|
582
|
+
def map_by_child(models: Iterable[RecordModel], child_type: type[WrappedType]) \
|
|
583
|
+
-> dict[WrappedType, RecordModel]:
|
|
619
584
|
"""
|
|
620
585
|
Take a list of record models and map them by their children. Essentially an inversion of map_to_child.
|
|
621
586
|
If two records share the same child, an exception will be thrown. The children must already be loaded.
|
|
@@ -625,8 +590,8 @@ class RecordHandler:
|
|
|
625
590
|
:return: A dict[ChildType, ModelType]. If an input model doesn't have a child of the given child type,
|
|
626
591
|
then it will not be in the resulting dictionary.
|
|
627
592
|
"""
|
|
628
|
-
to_child: dict[
|
|
629
|
-
by_child: dict[WrappedType,
|
|
593
|
+
to_child: dict[RecordModel, WrappedType] = RecordHandler.map_to_child(models, child_type)
|
|
594
|
+
by_child: dict[WrappedType, RecordModel] = {}
|
|
630
595
|
for record, child in to_child.items():
|
|
631
596
|
if child is None:
|
|
632
597
|
continue
|
|
@@ -637,8 +602,8 @@ class RecordHandler:
|
|
|
637
602
|
return by_child
|
|
638
603
|
|
|
639
604
|
@staticmethod
|
|
640
|
-
def map_by_children(models: Iterable[
|
|
641
|
-
-> dict[WrappedType, list[
|
|
605
|
+
def map_by_children(models: Iterable[RecordModel], child_type: type[WrappedType]) \
|
|
606
|
+
-> dict[WrappedType, list[RecordModel]]:
|
|
642
607
|
"""
|
|
643
608
|
Take a list of record models and map them by their children. Essentially an inversion of map_to_children. Input
|
|
644
609
|
models that share a child will end up in the same list. The children must already be loaded.
|
|
@@ -648,8 +613,8 @@ class RecordHandler:
|
|
|
648
613
|
:return: A dict[ChildType, list[ModelType]]. If an input model doesn't have children of the given child type,
|
|
649
614
|
then it will not be in the resulting dictionary.
|
|
650
615
|
"""
|
|
651
|
-
to_children: dict[
|
|
652
|
-
by_children: dict[WrappedType, list[
|
|
616
|
+
to_children: dict[RecordModel, list[WrappedType]] = RecordHandler.map_to_children(models, child_type)
|
|
617
|
+
by_children: dict[WrappedType, list[RecordModel]] = {}
|
|
653
618
|
for record, children in to_children.items():
|
|
654
619
|
for child in children:
|
|
655
620
|
by_children.setdefault(child, []).append(record)
|
|
@@ -1107,19 +1072,18 @@ class RecordHandler:
|
|
|
1107
1072
|
ret_dict.update({model: self.inst_man.wrap(current[0], wrapper_type) if current else None})
|
|
1108
1073
|
return ret_dict
|
|
1109
1074
|
|
|
1110
|
-
def __find_model(self, wrapper_type: type[WrappedType]
|
|
1111
|
-
secondary_identifiers: FieldIdentifierMap | None = None) -> WrappedType |
|
|
1075
|
+
def __find_model(self, wrapper_type: type[WrappedType], primary_identifier: str, id_value: FieldValue,
|
|
1076
|
+
secondary_identifiers: FieldIdentifierMap | None = None) -> WrappedType | None:
|
|
1112
1077
|
"""
|
|
1113
1078
|
Find a record from the system that matches the given field values. The primary identifier and value is used
|
|
1114
1079
|
to query for the record, then the secondary identifiers may be optionally provided to further filter the
|
|
1115
1080
|
returned results. If no record is found with these filters, returns None.
|
|
1116
1081
|
"""
|
|
1117
1082
|
# Query for all records that match the primary identifier.
|
|
1118
|
-
results: list[WrappedType]
|
|
1119
|
-
[id_value])
|
|
1083
|
+
results: list[WrappedType] = self.query_models(wrapper_type, primary_identifier, [id_value])
|
|
1120
1084
|
|
|
1121
1085
|
# Find the one record, if any, that matches the secondary identifiers.
|
|
1122
|
-
unique_record: WrappedType |
|
|
1086
|
+
unique_record: WrappedType | None = None
|
|
1123
1087
|
for result in results:
|
|
1124
1088
|
matches_all: bool = True
|
|
1125
1089
|
for field, value in secondary_identifiers.items():
|
|
@@ -1129,7 +1093,7 @@ class RecordHandler:
|
|
|
1129
1093
|
if matches_all:
|
|
1130
1094
|
# If a previous record in the results already matched all identifiers, then throw an exception.
|
|
1131
1095
|
if unique_record is not None:
|
|
1132
|
-
raise SapioException(f"More than one record of type {
|
|
1096
|
+
raise SapioException(f"More than one record of type {wrapper_type.get_wrapper_data_type_name()} "
|
|
1133
1097
|
f"encountered in system that matches all provided identifiers.")
|
|
1134
1098
|
unique_record = result
|
|
1135
1099
|
return unique_record
|