sapiopycommons 2025.3.6a453__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 +105 -151
- {sapiopycommons-2025.3.6a453.dist-info → sapiopycommons-2025.3.6a454.dist-info}/METADATA +1 -1
- {sapiopycommons-2025.3.6a453.dist-info → sapiopycommons-2025.3.6a454.dist-info}/RECORD +7 -10
- sapiopycommons/ai/__init__.py +0 -0
- sapiopycommons/ai/tool_of_tools.py +0 -917
- sapiopycommons/general/html_formatter.py +0 -456
- {sapiopycommons-2025.3.6a453.dist-info → sapiopycommons-2025.3.6a454.dist-info}/WHEEL +0 -0
- {sapiopycommons-2025.3.6a453.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,150 +150,134 @@ 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
|
-
dt: str =
|
|
193
|
-
if isinstance(wrapper_type, str):
|
|
194
|
-
wrapper_type = None
|
|
177
|
+
dt: str = wrapper_type.get_wrapper_data_type_name()
|
|
195
178
|
field: str = AliasUtil.to_data_field_name(field)
|
|
196
179
|
pager = QueryDataRecordsAutoPager(dt, field, list(value_list), self.user, paging_criteria)
|
|
197
180
|
pager.max_page = page_limit
|
|
198
181
|
return self.wrap_models(pager.get_all_at_once(), wrapper_type), pager.next_page_criteria
|
|
199
182
|
|
|
200
|
-
def query_models_by_id(self, wrapper_type: type[WrappedType]
|
|
201
|
-
page_limit: int | None = None, page_size: int | None = None)
|
|
202
|
-
-> 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]:
|
|
203
185
|
"""
|
|
204
186
|
Shorthand for using the data record manager to query for a list of data records by record ID
|
|
205
187
|
and then converting the results into a list of record models.
|
|
206
188
|
|
|
207
|
-
:param wrapper_type: The record model wrapper to use
|
|
189
|
+
:param wrapper_type: The record model wrapper to use.
|
|
208
190
|
:param ids: The list of record IDs to query.
|
|
209
191
|
:param page_limit: The maximum number of pages to query. If None, exhausts all possible pages. This parameter
|
|
210
192
|
only functions if you set a page size or the platform enforces a page size.
|
|
211
193
|
:param page_size: The size of the pages to query. If None, the page size may be limited by the platform.
|
|
212
|
-
:return: The record models for the queried records.
|
|
213
|
-
then the returned records will be PyRecordModels instead of WrappedRecordModels.
|
|
194
|
+
:return: The record models for the queried records.
|
|
214
195
|
"""
|
|
215
196
|
criteria: DataRecordPojoPageCriteria | None = None
|
|
216
197
|
if page_size is not None:
|
|
217
198
|
criteria = DataRecordPojoPageCriteria(page_size=page_size)
|
|
218
199
|
return self.query_models_by_id_with_criteria(wrapper_type, ids, criteria, page_limit)[0]
|
|
219
200
|
|
|
220
|
-
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],
|
|
221
202
|
paging_criteria: DataRecordPojoPageCriteria | None = None,
|
|
222
203
|
page_limit: int | None = None) \
|
|
223
|
-
-> tuple[list[WrappedType]
|
|
204
|
+
-> tuple[list[WrappedType], DataRecordPojoPageCriteria]:
|
|
224
205
|
"""
|
|
225
206
|
Shorthand for using the data record manager to query for a list of data records by record ID
|
|
226
207
|
and then converting the results into a list of record models.
|
|
227
208
|
|
|
228
|
-
:param wrapper_type: The record model wrapper to use
|
|
209
|
+
:param wrapper_type: The record model wrapper to use.
|
|
229
210
|
:param ids: The list of record IDs to query.
|
|
230
211
|
:param paging_criteria: The paging criteria to start the query with.
|
|
231
212
|
:param page_limit: The maximum number of pages to query from the starting criteria. If None, exhausts all
|
|
232
213
|
possible pages. This parameter only functions if you set a page size in the paging criteria or the platform
|
|
233
214
|
enforces a page size.
|
|
234
|
-
:return: The record models for the queried records and the final paging criteria.
|
|
235
|
-
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.
|
|
236
216
|
"""
|
|
237
|
-
dt: str =
|
|
238
|
-
if isinstance(wrapper_type, str):
|
|
239
|
-
wrapper_type = None
|
|
217
|
+
dt: str = wrapper_type.get_wrapper_data_type_name()
|
|
240
218
|
pager = QueryDataRecordByIdListAutoPager(dt, list(ids), self.user, paging_criteria)
|
|
241
219
|
pager.max_page = page_limit
|
|
242
220
|
return self.wrap_models(pager.get_all_at_once(), wrapper_type), pager.next_page_criteria
|
|
243
221
|
|
|
244
|
-
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],
|
|
245
223
|
page_limit: int | None = None, page_size: int | None = None) \
|
|
246
|
-
-> dict[int, WrappedType
|
|
224
|
+
-> dict[int, WrappedType]:
|
|
247
225
|
"""
|
|
248
226
|
Shorthand for using the data record manager to query for a list of data records by record ID
|
|
249
227
|
and then converting the results into a dictionary of record ID to the record model for that ID.
|
|
250
228
|
|
|
251
|
-
:param wrapper_type: The record model wrapper to use
|
|
229
|
+
:param wrapper_type: The record model wrapper to use.
|
|
252
230
|
:param ids: The list of record IDs to query.
|
|
253
231
|
:param page_limit: The maximum number of pages to query. If None, exhausts all possible pages. This parameter
|
|
254
232
|
only functions if you set a page size or the platform enforces a page size.
|
|
255
233
|
:param page_size: The size of the pages to query. If None, the page size may be limited by the platform.
|
|
256
234
|
:return: The record models for the queried records mapped in a dictionary by their record ID.
|
|
257
|
-
If a data type name was used instead of a model wrapper, then the returned records will be PyRecordModels
|
|
258
|
-
instead of WrappedRecordModels.
|
|
259
235
|
"""
|
|
260
236
|
return {AliasUtil.to_record_id(x): x for x in self.query_models_by_id(wrapper_type, ids, page_limit, page_size)}
|
|
261
237
|
|
|
262
|
-
def query_all_models(self, wrapper_type: type[WrappedType]
|
|
263
|
-
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]:
|
|
264
240
|
"""
|
|
265
241
|
Shorthand for using the data record manager to query for all data records of a given type
|
|
266
242
|
and then converting the results into a list of record models.
|
|
267
243
|
|
|
268
|
-
:param wrapper_type: The record model wrapper to use
|
|
244
|
+
:param wrapper_type: The record model wrapper to use.
|
|
269
245
|
:param page_limit: The maximum number of pages to query. If None, exhausts all possible pages. This parameter
|
|
270
246
|
only functions if you set a page size or the platform enforces a page size.
|
|
271
247
|
:param page_size: The size of the pages to query. If None, the page size may be limited by the platform.
|
|
272
|
-
:return: The record models for the queried records.
|
|
273
|
-
then the returned records will be PyRecordModels instead of WrappedRecordModels.
|
|
248
|
+
:return: The record models for the queried records.
|
|
274
249
|
"""
|
|
275
250
|
criteria: DataRecordPojoPageCriteria | None = None
|
|
276
251
|
if page_size is not None:
|
|
277
252
|
criteria = DataRecordPojoPageCriteria(page_size=page_size)
|
|
278
253
|
return self.query_all_models_with_criteria(wrapper_type, criteria, page_limit)[0]
|
|
279
254
|
|
|
280
|
-
def query_all_models_with_criteria(self, wrapper_type: type[WrappedType]
|
|
255
|
+
def query_all_models_with_criteria(self, wrapper_type: type[WrappedType],
|
|
281
256
|
paging_criteria: DataRecordPojoPageCriteria | None = None,
|
|
282
257
|
page_limit: int | None = None) \
|
|
283
|
-
-> tuple[list[WrappedType]
|
|
258
|
+
-> tuple[list[WrappedType], DataRecordPojoPageCriteria]:
|
|
284
259
|
"""
|
|
285
260
|
Shorthand for using the data record manager to query for all data records of a given type
|
|
286
261
|
and then converting the results into a list of record models.
|
|
287
262
|
|
|
288
|
-
:param wrapper_type: The record model wrapper to use
|
|
263
|
+
:param wrapper_type: The record model wrapper to use.
|
|
289
264
|
:param paging_criteria: The paging criteria to start the query with.
|
|
290
265
|
:param page_limit: The maximum number of pages to query from the starting criteria. If None, exhausts all
|
|
291
266
|
possible pages. This parameter only functions if you set a page size in the paging criteria or the platform
|
|
292
267
|
enforces a page size.
|
|
293
|
-
:return: The record models for the queried records and the final paging criteria.
|
|
294
|
-
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.
|
|
295
269
|
"""
|
|
296
|
-
dt: str =
|
|
297
|
-
if isinstance(wrapper_type, str):
|
|
298
|
-
wrapper_type = None
|
|
270
|
+
dt: str = wrapper_type.get_wrapper_data_type_name()
|
|
299
271
|
pager = QueryAllRecordsOfTypeAutoPager(dt, self.user, paging_criteria)
|
|
300
272
|
pager.max_page = page_limit
|
|
301
273
|
return self.wrap_models(pager.get_all_at_once(), wrapper_type), pager.next_page_criteria
|
|
302
274
|
|
|
303
|
-
def query_models_by_report(self, wrapper_type: type[WrappedType]
|
|
275
|
+
def query_models_by_report(self, wrapper_type: type[WrappedType],
|
|
304
276
|
report_name: str | RawReportTerm | CustomReportCriteria,
|
|
305
277
|
filters: dict[FieldIdentifierKey, Iterable[FieldValue]] | None = None,
|
|
306
278
|
page_limit: int | None = None,
|
|
307
279
|
page_size: int | None = None,
|
|
308
|
-
page_number: int | None = None) -> list[WrappedType]
|
|
280
|
+
page_number: int | None = None) -> list[WrappedType]:
|
|
309
281
|
"""
|
|
310
282
|
Run a report and use the results of that report to query for and return the records in the report results.
|
|
311
283
|
First runs the report, then runs a data record manager query on the results of the custom report.
|
|
@@ -315,7 +287,7 @@ class RecordHandler:
|
|
|
315
287
|
|
|
316
288
|
Any given custom report criteria should only have columns from a single data type.
|
|
317
289
|
|
|
318
|
-
:param wrapper_type: The record model wrapper to use
|
|
290
|
+
:param wrapper_type: The record model wrapper to use.
|
|
319
291
|
:param report_name: The name of a system report, or a raw report term for a quick report, or custom report
|
|
320
292
|
criteria for a custom report.
|
|
321
293
|
:param filters: If provided, filter the results of the report using the given mapping of headers to values to
|
|
@@ -327,8 +299,7 @@ class RecordHandler:
|
|
|
327
299
|
:param page_number: The page number to start the search from, If None, starts on the first page.
|
|
328
300
|
If the input report is a custom report criteria, uses the value from the criteria, unless this value is
|
|
329
301
|
not None, in which case it overwrites the given report's value. Note that the number of the first page is 0.
|
|
330
|
-
:return: The record models for the queried records that matched the given report.
|
|
331
|
-
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.
|
|
332
303
|
"""
|
|
333
304
|
warnings.warn("Deprecated in favor of the [System/Custom/Quick]ReportRecordAutoPager classes.", DeprecationWarning)
|
|
334
305
|
if isinstance(report_name, str):
|
|
@@ -338,7 +309,7 @@ class RecordHandler:
|
|
|
338
309
|
results: list[dict[str, FieldValue]] = CustomReportUtil.run_quick_report(self.user, report_name, filters,
|
|
339
310
|
page_limit, page_size, page_number)
|
|
340
311
|
elif isinstance(report_name, CustomReportCriteria):
|
|
341
|
-
dt: str =
|
|
312
|
+
dt: str = wrapper_type.get_wrapper_data_type_name()
|
|
342
313
|
# Ensure that the root data type is the one we're looking for.
|
|
343
314
|
report_name.root_data_type = dt
|
|
344
315
|
# Raise an exception if any column in the report doesn't match the given data type.
|
|
@@ -358,38 +329,35 @@ class RecordHandler:
|
|
|
358
329
|
ids: list[int] = [row["RecordId"] for row in results]
|
|
359
330
|
return self.query_models_by_id(wrapper_type, ids)
|
|
360
331
|
|
|
361
|
-
def add_model(self, wrapper_type: type[WrappedType]
|
|
332
|
+
def add_model(self, wrapper_type: type[WrappedType]) -> WrappedType:
|
|
362
333
|
"""
|
|
363
334
|
Shorthand for using the instance manager to add a new record model of the given type.
|
|
364
335
|
|
|
365
|
-
:param wrapper_type: The record model wrapper to use
|
|
366
|
-
:return: The newly added record model.
|
|
367
|
-
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.
|
|
368
338
|
"""
|
|
369
339
|
return self.inst_man.add_new_record_of_type(wrapper_type)
|
|
370
340
|
|
|
371
|
-
def add_models(self, wrapper_type: type[WrappedType]
|
|
341
|
+
def add_models(self, wrapper_type: type[WrappedType], num: int) -> list[WrappedType]:
|
|
372
342
|
"""
|
|
373
343
|
Shorthand for using the instance manager to add new record models of the given type.
|
|
374
344
|
|
|
375
|
-
:param wrapper_type: The record model wrapper to use
|
|
345
|
+
:param wrapper_type: The record model wrapper to use.
|
|
376
346
|
:param num: The number of models to create.
|
|
377
|
-
:return: The newly added record models.
|
|
378
|
-
returned records will be PyRecordModels instead of WrappedRecordModels.
|
|
347
|
+
:return: The newly added record models.
|
|
379
348
|
"""
|
|
380
349
|
return self.inst_man.add_new_records_of_type(num, wrapper_type)
|
|
381
350
|
|
|
382
|
-
def add_models_with_data(self, wrapper_type: type[WrappedType]
|
|
383
|
-
-> list[WrappedType]
|
|
351
|
+
def add_models_with_data(self, wrapper_type: type[WrappedType], fields: list[FieldIdentifierMap]) \
|
|
352
|
+
-> list[WrappedType]:
|
|
384
353
|
"""
|
|
385
354
|
Shorthand for using the instance manager to add new models of the given type, and then initializing all those
|
|
386
355
|
models with the given fields.
|
|
387
356
|
|
|
388
|
-
:param wrapper_type: The record model wrapper to use
|
|
357
|
+
:param wrapper_type: The record model wrapper to use.
|
|
389
358
|
:param fields: A list of field maps to initialize the record models with.
|
|
390
359
|
:return: The newly added record models with the provided fields set. The records will be in the same order as
|
|
391
|
-
the fields in the fields list.
|
|
392
|
-
records will be PyRecordModels instead of WrappedRecordModels.
|
|
360
|
+
the fields in the fields list.
|
|
393
361
|
"""
|
|
394
362
|
fields: list[FieldMap] = AliasUtil.to_data_field_names_list_dict(fields)
|
|
395
363
|
models: list[WrappedType] = self.add_models(wrapper_type, len(fields))
|
|
@@ -397,9 +365,8 @@ class RecordHandler:
|
|
|
397
365
|
model.set_field_values(field_list)
|
|
398
366
|
return models
|
|
399
367
|
|
|
400
|
-
def find_or_add_model(self, wrapper_type: type[WrappedType]
|
|
401
|
-
id_value: FieldValue, secondary_identifiers: FieldIdentifierMap | None = None)
|
|
402
|
-
-> 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:
|
|
403
370
|
"""
|
|
404
371
|
Find a unique record that matches the given field values. If no such records exist, add a record model to the
|
|
405
372
|
cache with the identifying fields set to the desired values. This record will be created in the system when
|
|
@@ -410,14 +377,12 @@ class RecordHandler:
|
|
|
410
377
|
|
|
411
378
|
Makes a webservice call to query for the existing record.
|
|
412
379
|
|
|
413
|
-
:param wrapper_type: The record model wrapper to use
|
|
380
|
+
:param wrapper_type: The record model wrapper to use.
|
|
414
381
|
:param primary_identifier: The data field name of the field to search on.
|
|
415
382
|
:param id_value: The value of the identifying field to search for.
|
|
416
383
|
:param secondary_identifiers: Optional fields used to filter the records that are returned after searching on
|
|
417
384
|
the primary identifier.
|
|
418
385
|
:return: The record model with the identifying field value, either pulled from the system or newly created.
|
|
419
|
-
If a data type name was used instead of a model wrapper, then the returned record will be a PyRecordModel
|
|
420
|
-
instead of a WrappedRecordModel.
|
|
421
386
|
"""
|
|
422
387
|
# PR-46335: Initialize the secondary identifiers parameter if None is provided to avoid an exception.
|
|
423
388
|
# If no secondary identifiers were provided, use an empty dictionary.
|
|
@@ -438,25 +403,22 @@ class RecordHandler:
|
|
|
438
403
|
secondary_identifiers.update({primary_identifier: id_value})
|
|
439
404
|
return self.add_models_with_data(wrapper_type, [secondary_identifiers])[0]
|
|
440
405
|
|
|
441
|
-
def create_models(self, wrapper_type: type[WrappedType]
|
|
406
|
+
def create_models(self, wrapper_type: type[WrappedType], num: int) -> list[WrappedType]:
|
|
442
407
|
"""
|
|
443
408
|
Shorthand for creating new records via the data record manager and then returning them as wrapped
|
|
444
409
|
record models. Useful in cases where your record model needs to have a valid record ID.
|
|
445
410
|
|
|
446
411
|
Makes a webservice call to create the data records.
|
|
447
412
|
|
|
448
|
-
:param wrapper_type: The record model wrapper to use
|
|
413
|
+
:param wrapper_type: The record model wrapper to use.
|
|
449
414
|
:param num: The number of new records to create.
|
|
450
|
-
:return: The newly created record models.
|
|
451
|
-
returned records will be PyRecordModels instead of WrappedRecordModels.
|
|
415
|
+
:return: The newly created record models.
|
|
452
416
|
"""
|
|
453
|
-
dt: str =
|
|
454
|
-
if isinstance(wrapper_type, str):
|
|
455
|
-
wrapper_type = None
|
|
417
|
+
dt: str = wrapper_type.get_wrapper_data_type_name()
|
|
456
418
|
return self.wrap_models(self.dr_man.add_data_records(dt, num), wrapper_type)
|
|
457
419
|
|
|
458
|
-
def create_models_with_data(self, wrapper_type: type[WrappedType]
|
|
459
|
-
-> list[WrappedType]
|
|
420
|
+
def create_models_with_data(self, wrapper_type: type[WrappedType], fields: list[FieldIdentifierMap]) \
|
|
421
|
+
-> list[WrappedType]:
|
|
460
422
|
"""
|
|
461
423
|
Shorthand for creating new records via the data record manager with field data to initialize the records with
|
|
462
424
|
and then returning them as wrapped record models. Useful in cases where your record model needs to have a valid
|
|
@@ -464,20 +426,17 @@ class RecordHandler:
|
|
|
464
426
|
|
|
465
427
|
Makes a webservice call to create the data records.
|
|
466
428
|
|
|
467
|
-
:param wrapper_type: The record model wrapper to use
|
|
429
|
+
:param wrapper_type: The record model wrapper to use.
|
|
468
430
|
:param fields: The field map list to initialize the new data records with.
|
|
469
|
-
:return: The newly created record models.
|
|
470
|
-
returned records will be PyRecordModels instead of WrappedRecordModels.
|
|
431
|
+
:return: The newly created record models.
|
|
471
432
|
"""
|
|
472
|
-
dt: str =
|
|
473
|
-
if isinstance(wrapper_type, str):
|
|
474
|
-
wrapper_type = None
|
|
433
|
+
dt: str = wrapper_type.get_wrapper_data_type_name()
|
|
475
434
|
fields: list[FieldMap] = AliasUtil.to_data_field_names_list_dict(fields)
|
|
476
435
|
return self.wrap_models(self.dr_man.add_data_records_with_data(dt, fields), wrapper_type)
|
|
477
436
|
|
|
478
|
-
def find_or_create_model(self, wrapper_type: type[WrappedType]
|
|
437
|
+
def find_or_create_model(self, wrapper_type: type[WrappedType], primary_identifier: FieldIdentifier,
|
|
479
438
|
id_value: FieldValue, secondary_identifiers: FieldIdentifierMap | None = None) \
|
|
480
|
-
-> WrappedType
|
|
439
|
+
-> WrappedType:
|
|
481
440
|
"""
|
|
482
441
|
Find a unique record that matches the given field values. If no such records exist, create one with the
|
|
483
442
|
identifying fields set to the desired values. If more than one record with the identifying values exists,
|
|
@@ -489,14 +448,12 @@ class RecordHandler:
|
|
|
489
448
|
Makes a webservice call to query for the existing record. Makes an additional webservice call if the record
|
|
490
449
|
needs to be created.
|
|
491
450
|
|
|
492
|
-
:param wrapper_type: The record model wrapper to use
|
|
451
|
+
:param wrapper_type: The record model wrapper to use.
|
|
493
452
|
:param primary_identifier: The data field name of the field to search on.
|
|
494
453
|
:param id_value: The value of the identifying field to search for.
|
|
495
454
|
:param secondary_identifiers: Optional fields used to filter the records that are returned after searching on
|
|
496
455
|
the primary identifier.
|
|
497
456
|
:return: The record model with the identifying field value, either pulled from the system or newly created.
|
|
498
|
-
If a data type name was used instead of a model wrapper, then the returned record will be a PyRecordModel
|
|
499
|
-
instead of a WrappedRecordModel.
|
|
500
457
|
"""
|
|
501
458
|
# PR-46335: Initialize the secondary identifiers parameter if None is provided to avoid an exception.
|
|
502
459
|
# If no secondary identifiers were provided, use an empty dictionary.
|
|
@@ -518,8 +475,7 @@ class RecordHandler:
|
|
|
518
475
|
return self.create_models_with_data(wrapper_type, [secondary_identifiers])[0]
|
|
519
476
|
|
|
520
477
|
@staticmethod
|
|
521
|
-
def map_to_parent(models: Iterable[
|
|
522
|
-
-> dict[WrappedRecordModel, WrappedType]:
|
|
478
|
+
def map_to_parent(models: Iterable[RecordModel], parent_type: type[WrappedType]) -> dict[RecordModel, WrappedType]:
|
|
523
479
|
"""
|
|
524
480
|
Map a list of record models to a single parent of a given type. The parents must already be loaded.
|
|
525
481
|
|
|
@@ -528,14 +484,14 @@ class RecordHandler:
|
|
|
528
484
|
:return: A dict[ModelType, ParentType]. If an input model doesn't have a parent of the given parent type, then
|
|
529
485
|
it will map to None.
|
|
530
486
|
"""
|
|
531
|
-
return_dict: dict[
|
|
487
|
+
return_dict: dict[RecordModel, WrappedType] = {}
|
|
532
488
|
for model in models:
|
|
533
489
|
return_dict[model] = model.get_parent_of_type(parent_type)
|
|
534
490
|
return return_dict
|
|
535
491
|
|
|
536
492
|
@staticmethod
|
|
537
|
-
def map_to_parents(models: Iterable[
|
|
538
|
-
-> dict[
|
|
493
|
+
def map_to_parents(models: Iterable[RecordModel], parent_type: type[WrappedType]) \
|
|
494
|
+
-> dict[RecordModel, list[WrappedType]]:
|
|
539
495
|
"""
|
|
540
496
|
Map a list of record models to a list parents of a given type. The parents must already be loaded.
|
|
541
497
|
|
|
@@ -544,14 +500,14 @@ class RecordHandler:
|
|
|
544
500
|
:return: A dict[ModelType, list[ParentType]]. If an input model doesn't have a parent of the given parent type,
|
|
545
501
|
then it will map to an empty list.
|
|
546
502
|
"""
|
|
547
|
-
return_dict: dict[
|
|
503
|
+
return_dict: dict[RecordModel, list[WrappedType]] = {}
|
|
548
504
|
for model in models:
|
|
549
505
|
return_dict[model] = model.get_parents_of_type(parent_type)
|
|
550
506
|
return return_dict
|
|
551
507
|
|
|
552
508
|
@staticmethod
|
|
553
|
-
def map_by_parent(models: Iterable[
|
|
554
|
-
-> dict[WrappedType,
|
|
509
|
+
def map_by_parent(models: Iterable[RecordModel], parent_type: type[WrappedType]) \
|
|
510
|
+
-> dict[WrappedType, RecordModel]:
|
|
555
511
|
"""
|
|
556
512
|
Take a list of record models and map them by their parent. Essentially an inversion of map_to_parent.
|
|
557
513
|
If two records share the same parent, an exception will be thrown. The parents must already be loaded.
|
|
@@ -561,8 +517,8 @@ class RecordHandler:
|
|
|
561
517
|
:return: A dict[ParentType, ModelType]. If an input model doesn't have a parent of the given parent type,
|
|
562
518
|
then it will not be in the resulting dictionary.
|
|
563
519
|
"""
|
|
564
|
-
to_parent: dict[
|
|
565
|
-
by_parent: dict[WrappedType,
|
|
520
|
+
to_parent: dict[RecordModel, WrappedType] = RecordHandler.map_to_parent(models, parent_type)
|
|
521
|
+
by_parent: dict[WrappedType, RecordModel] = {}
|
|
566
522
|
for record, parent in to_parent.items():
|
|
567
523
|
if parent is None:
|
|
568
524
|
continue
|
|
@@ -573,8 +529,8 @@ class RecordHandler:
|
|
|
573
529
|
return by_parent
|
|
574
530
|
|
|
575
531
|
@staticmethod
|
|
576
|
-
def map_by_parents(models: Iterable[
|
|
577
|
-
-> dict[WrappedType, list[
|
|
532
|
+
def map_by_parents(models: Iterable[RecordModel], parent_type: type[WrappedType]) \
|
|
533
|
+
-> dict[WrappedType, list[RecordModel]]:
|
|
578
534
|
"""
|
|
579
535
|
Take a list of record models and map them by their parents. Essentially an inversion of map_to_parents. Input
|
|
580
536
|
models that share a parent will end up in the same list. The parents must already be loaded.
|
|
@@ -584,16 +540,15 @@ class RecordHandler:
|
|
|
584
540
|
:return: A dict[ParentType, list[ModelType]]. If an input model doesn't have a parent of the given parent type,
|
|
585
541
|
then it will not be in the resulting dictionary.
|
|
586
542
|
"""
|
|
587
|
-
to_parents: dict[
|
|
588
|
-
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]] = {}
|
|
589
545
|
for record, parents in to_parents.items():
|
|
590
546
|
for parent in parents:
|
|
591
547
|
by_parents.setdefault(parent, []).append(record)
|
|
592
548
|
return by_parents
|
|
593
549
|
|
|
594
550
|
@staticmethod
|
|
595
|
-
def map_to_child(models: Iterable[
|
|
596
|
-
-> dict[WrappedRecordModel, WrappedType]:
|
|
551
|
+
def map_to_child(models: Iterable[RecordModel], child_type: type[WrappedType]) -> dict[RecordModel, WrappedType]:
|
|
597
552
|
"""
|
|
598
553
|
Map a list of record models to a single child of a given type. The children must already be loaded.
|
|
599
554
|
|
|
@@ -602,14 +557,14 @@ class RecordHandler:
|
|
|
602
557
|
:return: A dict[ModelType, ChildType]. If an input model doesn't have a child of the given child type, then
|
|
603
558
|
it will map to None.
|
|
604
559
|
"""
|
|
605
|
-
return_dict: dict[
|
|
560
|
+
return_dict: dict[RecordModel, WrappedType] = {}
|
|
606
561
|
for model in models:
|
|
607
562
|
return_dict[model] = model.get_child_of_type(child_type)
|
|
608
563
|
return return_dict
|
|
609
564
|
|
|
610
565
|
@staticmethod
|
|
611
|
-
def map_to_children(models: Iterable[
|
|
612
|
-
-> dict[
|
|
566
|
+
def map_to_children(models: Iterable[RecordModel], child_type: type[WrappedType]) \
|
|
567
|
+
-> dict[RecordModel, list[WrappedType]]:
|
|
613
568
|
"""
|
|
614
569
|
Map a list of record models to a list children of a given type. The children must already be loaded.
|
|
615
570
|
|
|
@@ -618,14 +573,14 @@ class RecordHandler:
|
|
|
618
573
|
:return: A dict[ModelType, list[ChildType]]. If an input model doesn't have children of the given child type,
|
|
619
574
|
then it will map to an empty list.
|
|
620
575
|
"""
|
|
621
|
-
return_dict: dict[
|
|
576
|
+
return_dict: dict[RecordModel, list[WrappedType]] = {}
|
|
622
577
|
for model in models:
|
|
623
578
|
return_dict[model] = model.get_children_of_type(child_type)
|
|
624
579
|
return return_dict
|
|
625
580
|
|
|
626
581
|
@staticmethod
|
|
627
|
-
def map_by_child(models: Iterable[
|
|
628
|
-
-> dict[WrappedType,
|
|
582
|
+
def map_by_child(models: Iterable[RecordModel], child_type: type[WrappedType]) \
|
|
583
|
+
-> dict[WrappedType, RecordModel]:
|
|
629
584
|
"""
|
|
630
585
|
Take a list of record models and map them by their children. Essentially an inversion of map_to_child.
|
|
631
586
|
If two records share the same child, an exception will be thrown. The children must already be loaded.
|
|
@@ -635,8 +590,8 @@ class RecordHandler:
|
|
|
635
590
|
:return: A dict[ChildType, ModelType]. If an input model doesn't have a child of the given child type,
|
|
636
591
|
then it will not be in the resulting dictionary.
|
|
637
592
|
"""
|
|
638
|
-
to_child: dict[
|
|
639
|
-
by_child: dict[WrappedType,
|
|
593
|
+
to_child: dict[RecordModel, WrappedType] = RecordHandler.map_to_child(models, child_type)
|
|
594
|
+
by_child: dict[WrappedType, RecordModel] = {}
|
|
640
595
|
for record, child in to_child.items():
|
|
641
596
|
if child is None:
|
|
642
597
|
continue
|
|
@@ -647,8 +602,8 @@ class RecordHandler:
|
|
|
647
602
|
return by_child
|
|
648
603
|
|
|
649
604
|
@staticmethod
|
|
650
|
-
def map_by_children(models: Iterable[
|
|
651
|
-
-> dict[WrappedType, list[
|
|
605
|
+
def map_by_children(models: Iterable[RecordModel], child_type: type[WrappedType]) \
|
|
606
|
+
-> dict[WrappedType, list[RecordModel]]:
|
|
652
607
|
"""
|
|
653
608
|
Take a list of record models and map them by their children. Essentially an inversion of map_to_children. Input
|
|
654
609
|
models that share a child will end up in the same list. The children must already be loaded.
|
|
@@ -658,8 +613,8 @@ class RecordHandler:
|
|
|
658
613
|
:return: A dict[ChildType, list[ModelType]]. If an input model doesn't have children of the given child type,
|
|
659
614
|
then it will not be in the resulting dictionary.
|
|
660
615
|
"""
|
|
661
|
-
to_children: dict[
|
|
662
|
-
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]] = {}
|
|
663
618
|
for record, children in to_children.items():
|
|
664
619
|
for child in children:
|
|
665
620
|
by_children.setdefault(child, []).append(record)
|
|
@@ -1117,19 +1072,18 @@ class RecordHandler:
|
|
|
1117
1072
|
ret_dict.update({model: self.inst_man.wrap(current[0], wrapper_type) if current else None})
|
|
1118
1073
|
return ret_dict
|
|
1119
1074
|
|
|
1120
|
-
def __find_model(self, wrapper_type: type[WrappedType]
|
|
1121
|
-
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:
|
|
1122
1077
|
"""
|
|
1123
1078
|
Find a record from the system that matches the given field values. The primary identifier and value is used
|
|
1124
1079
|
to query for the record, then the secondary identifiers may be optionally provided to further filter the
|
|
1125
1080
|
returned results. If no record is found with these filters, returns None.
|
|
1126
1081
|
"""
|
|
1127
1082
|
# Query for all records that match the primary identifier.
|
|
1128
|
-
results: list[WrappedType]
|
|
1129
|
-
[id_value])
|
|
1083
|
+
results: list[WrappedType] = self.query_models(wrapper_type, primary_identifier, [id_value])
|
|
1130
1084
|
|
|
1131
1085
|
# Find the one record, if any, that matches the secondary identifiers.
|
|
1132
|
-
unique_record: WrappedType |
|
|
1086
|
+
unique_record: WrappedType | None = None
|
|
1133
1087
|
for result in results:
|
|
1134
1088
|
matches_all: bool = True
|
|
1135
1089
|
for field, value in secondary_identifiers.items():
|
|
@@ -1139,7 +1093,7 @@ class RecordHandler:
|
|
|
1139
1093
|
if matches_all:
|
|
1140
1094
|
# If a previous record in the results already matched all identifiers, then throw an exception.
|
|
1141
1095
|
if unique_record is not None:
|
|
1142
|
-
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()} "
|
|
1143
1097
|
f"encountered in system that matches all provided identifiers.")
|
|
1144
1098
|
unique_record = result
|
|
1145
1099
|
return unique_record
|