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.

@@ -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] | None = None) \
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. If not provided, the record is returned as a
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
- if wrapper_type is not None:
84
- self.__verify_data_type([record], wrapper_type)
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] | None = None) \
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. If not provided, the records are returned as
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
- if wrapper_type is not None:
99
- self.__verify_data_type(records, wrapper_type)
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] | str, field: FieldIdentifier,
104
- value_list: Iterable[FieldValue], page_limit: int | None = None, page_size: int | None = None) \
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, or the data type name of the records.
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. If a data type name was used instead of a model wrapper,
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] | str, field: FieldIdentifier,
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] | list[PyRecordModel]]:
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, or the data type name of the records.
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] | str, field: FieldIdentifier,
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 | PyRecordModel]:
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, or the data type name of the records.
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] | str, field: FieldIdentifier,
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] | list[PyRecordModel], DataRecordPojoPageCriteria]:
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, or the data type name of the records.
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. If a data type name was used
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 = AliasUtil.to_data_type_name(wrapper_type)
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] | str, ids: Iterable[int],
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, or the data type name of the records.
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. If a data type name was used instead of a model wrapper,
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] | str, ids: Iterable[int],
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] | list[PyRecordModel], DataRecordPojoPageCriteria]:
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, or the data type name of the records.
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. If a data type name was used
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 = AliasUtil.to_data_type_name(wrapper_type)
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] | str, ids: Iterable[int],
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 | PyRecordModel]:
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, or the data type name of the records.
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] | str, page_limit: int | None = None,
263
- page_size: int | None = None) -> list[WrappedType] | list[PyRecordModel]:
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, or the data type name of the records.
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. If a data type name was used instead of a model wrapper,
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] | str,
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] | list[PyRecordModel], DataRecordPojoPageCriteria]:
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, or the data type name of the records.
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. If a data type name was used
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 = AliasUtil.to_data_type_name(wrapper_type)
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] | str,
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] | list[PyRecordModel]:
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, or the data type name of the records.
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. If a data type name was used
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 = AliasUtil.to_data_type_name(wrapper_type)
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] | str) -> WrappedType | PyRecordModel:
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, or the data type name of the record.
366
- :return: The newly added record model. If a data type name was used instead of a model wrapper, then the
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] | str, num: int) -> list[WrappedType] | list[PyRecordModel]:
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, or the data type name of the records.
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. If a data type name was used instead of a model wrapper, then the
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] | str, fields: list[FieldIdentifierMap]) \
383
- -> list[WrappedType] | list[PyRecordModel]:
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, or the data type name of the records.
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. If a data type name was used instead of a model wrapper, then the returned
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] | str, primary_identifier: FieldIdentifier,
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, or the data type name of the record.
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] | str, num: int) -> list[WrappedType] | list[PyRecordModel]:
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, or the data type name of the records.
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. If a data type name was used instead of a model wrapper, then the
451
- returned records will be PyRecordModels instead of WrappedRecordModels.
415
+ :return: The newly created record models.
452
416
  """
453
- dt: str = AliasUtil.to_data_type_name(wrapper_type)
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] | str, fields: list[FieldIdentifierMap]) \
459
- -> list[WrappedType] | list[PyRecordModel]:
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, or the data type name of the records.
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. If a data type name was used instead of a model wrapper, then the
470
- returned records will be PyRecordModels instead of WrappedRecordModels.
431
+ :return: The newly created record models.
471
432
  """
472
- dt: str = AliasUtil.to_data_type_name(wrapper_type)
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] | str, primary_identifier: FieldIdentifier,
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 | PyRecordModel:
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, or the data type name of the record.
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[WrappedRecordModel], parent_type: type[WrappedType])\
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[WrappedRecordModel, WrappedType] = {}
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[WrappedRecordModel], parent_type: type[WrappedType]) \
538
- -> dict[WrappedRecordModel, list[WrappedType]]:
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[WrappedRecordModel, list[WrappedType]] = {}
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[WrappedRecordModel], parent_type: type[WrappedType]) \
554
- -> dict[WrappedType, WrappedRecordModel]:
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[WrappedRecordModel, WrappedType] = RecordHandler.map_to_parent(models, parent_type)
565
- by_parent: dict[WrappedType, WrappedRecordModel] = {}
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[WrappedRecordModel], parent_type: type[WrappedType]) \
577
- -> dict[WrappedType, list[WrappedRecordModel]]:
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[WrappedRecordModel, list[WrappedType]] = RecordHandler.map_to_parents(models, parent_type)
588
- by_parents: dict[WrappedType, list[WrappedRecordModel]] = {}
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[WrappedRecordModel], child_type: type[WrappedType])\
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[WrappedRecordModel, WrappedType] = {}
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[WrappedRecordModel], child_type: type[WrappedType]) \
612
- -> dict[WrappedRecordModel, list[WrappedType]]:
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[WrappedRecordModel, list[WrappedType]] = {}
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[WrappedRecordModel], child_type: type[WrappedType]) \
628
- -> dict[WrappedType, WrappedRecordModel]:
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[WrappedRecordModel, WrappedType] = RecordHandler.map_to_child(models, child_type)
639
- by_child: dict[WrappedType, WrappedRecordModel] = {}
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[WrappedRecordModel], child_type: type[WrappedType]) \
651
- -> dict[WrappedType, list[WrappedRecordModel]]:
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[WrappedRecordModel, list[WrappedType]] = RecordHandler.map_to_children(models, child_type)
662
- by_children: dict[WrappedType, list[WrappedRecordModel]] = {}
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] | str, primary_identifier: str, id_value: FieldValue,
1121
- secondary_identifiers: FieldIdentifierMap | None = None) -> WrappedType | PyRecordModel | None:
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] | list[PyRecordModel] = self.query_models(wrapper_type, primary_identifier,
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 | PyRecordModel | None = None
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 {AliasUtil.to_data_type_name(wrapper_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