sapiopycommons 2025.7.8a581__py3-none-any.whl → 2025.7.9a582__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.

Files changed (60) hide show
  1. sapiopycommons/ai/__init__.py +0 -0
  2. sapiopycommons/ai/api/fielddefinitions/proto/fields_pb2.py +43 -0
  3. sapiopycommons/ai/api/fielddefinitions/proto/fields_pb2.pyi +31 -0
  4. sapiopycommons/ai/api/fielddefinitions/proto/fields_pb2_grpc.py +24 -0
  5. sapiopycommons/ai/api/fielddefinitions/proto/velox_field_def_pb2.py +123 -0
  6. sapiopycommons/ai/api/fielddefinitions/proto/velox_field_def_pb2.pyi +598 -0
  7. sapiopycommons/ai/api/fielddefinitions/proto/velox_field_def_pb2_grpc.py +24 -0
  8. sapiopycommons/ai/api/plan/proto/step_output_pb2.py +45 -0
  9. sapiopycommons/ai/api/plan/proto/step_output_pb2.pyi +42 -0
  10. sapiopycommons/ai/api/plan/proto/step_output_pb2_grpc.py +24 -0
  11. sapiopycommons/ai/api/plan/proto/step_pb2.py +43 -0
  12. sapiopycommons/ai/api/plan/proto/step_pb2.pyi +43 -0
  13. sapiopycommons/ai/api/plan/proto/step_pb2_grpc.py +24 -0
  14. sapiopycommons/ai/api/plan/script/proto/script_pb2.py +55 -0
  15. sapiopycommons/ai/api/plan/script/proto/script_pb2.pyi +115 -0
  16. sapiopycommons/ai/api/plan/script/proto/script_pb2_grpc.py +153 -0
  17. sapiopycommons/ai/api/plan/tool/proto/entry_pb2.py +57 -0
  18. sapiopycommons/ai/api/plan/tool/proto/entry_pb2.pyi +96 -0
  19. sapiopycommons/ai/api/plan/tool/proto/entry_pb2_grpc.py +24 -0
  20. sapiopycommons/ai/api/plan/tool/proto/tool_pb2.py +67 -0
  21. sapiopycommons/ai/api/plan/tool/proto/tool_pb2.pyi +220 -0
  22. sapiopycommons/ai/api/plan/tool/proto/tool_pb2_grpc.py +154 -0
  23. sapiopycommons/ai/api/session/proto/sapio_conn_info_pb2.py +39 -0
  24. sapiopycommons/ai/api/session/proto/sapio_conn_info_pb2.pyi +32 -0
  25. sapiopycommons/ai/api/session/proto/sapio_conn_info_pb2_grpc.py +24 -0
  26. sapiopycommons/ai/protobuf_utils.py +508 -0
  27. sapiopycommons/ai/test_client.py +251 -0
  28. sapiopycommons/ai/tool_service_base.py +798 -0
  29. sapiopycommons/callbacks/callback_util.py +332 -665
  30. sapiopycommons/callbacks/field_builder.py +0 -2
  31. sapiopycommons/chem/IndigoMolecules.py +1 -31
  32. sapiopycommons/chem/Molecules.py +3 -3
  33. sapiopycommons/customreport/auto_pagers.py +1 -26
  34. sapiopycommons/customreport/term_builder.py +1 -1
  35. sapiopycommons/datatype/pseudo_data_types.py +326 -349
  36. sapiopycommons/eln/experiment_handler.py +767 -408
  37. sapiopycommons/eln/experiment_report_util.py +6 -11
  38. sapiopycommons/eln/plate_designer.py +2 -7
  39. sapiopycommons/files/file_util.py +5 -7
  40. sapiopycommons/general/accession_service.py +2 -2
  41. sapiopycommons/general/aliases.py +1 -3
  42. sapiopycommons/general/audit_log.py +0 -7
  43. sapiopycommons/general/custom_report_util.py +0 -12
  44. sapiopycommons/processtracking/custom_workflow_handler.py +1 -11
  45. sapiopycommons/processtracking/endpoints.py +0 -27
  46. sapiopycommons/recordmodel/record_handler.py +317 -657
  47. sapiopycommons/rules/eln_rule_handler.py +1 -8
  48. sapiopycommons/rules/on_save_rule_handler.py +1 -8
  49. sapiopycommons/webhook/webhook_handlers.py +0 -3
  50. sapiopycommons/webhook/webservice_handlers.py +2 -2
  51. {sapiopycommons-2025.7.8a581.dist-info → sapiopycommons-2025.7.9a582.dist-info}/METADATA +2 -2
  52. sapiopycommons-2025.7.9a582.dist-info/RECORD +92 -0
  53. sapiopycommons/chem/ps_commons.py +0 -455
  54. sapiopycommons/eln/experiment_cache.py +0 -188
  55. sapiopycommons/eln/experiment_step_factory.py +0 -476
  56. sapiopycommons/eln/step_creation.py +0 -236
  57. sapiopycommons/general/data_structure_util.py +0 -115
  58. sapiopycommons-2025.7.8a581.dist-info/RECORD +0 -69
  59. {sapiopycommons-2025.7.8a581.dist-info → sapiopycommons-2025.7.9a582.dist-info}/WHEEL +0 -0
  60. {sapiopycommons-2025.7.8a581.dist-info → sapiopycommons-2025.7.9a582.dist-info}/licenses/LICENSE +0 -0
@@ -2,7 +2,7 @@ from sapiopylib.rest.ELNService import ElnManager
2
2
  from sapiopylib.rest.User import SapioUser
3
3
  from sapiopylib.rest.pojo.CustomReport import CustomReportCriteria, AbstractReportTerm, RawReportTerm
4
4
  from sapiopylib.rest.pojo.datatype.FieldDefinition import FieldType
5
- from sapiopylib.rest.pojo.eln.ElnExperiment import ElnExperiment, ElnExperimentQueryCriteria, ElnTemplate
5
+ from sapiopylib.rest.pojo.eln.ElnExperiment import ElnExperiment, ElnExperimentQueryCriteria
6
6
  from sapiopylib.rest.pojo.eln.SapioELNEnums import ElnExperimentStatus, ElnBaseDataType
7
7
  from sapiopylib.rest.utils.recordmodel.PyRecordModel import PyRecordModel
8
8
  from sapiopylib.rest.utils.recordmodel.RecordModelWrapper import WrappedType
@@ -250,22 +250,17 @@ class ExperimentReportUtil:
250
250
  return {exp: list(records) for exp, records in exp_to_records.items()}
251
251
 
252
252
  @staticmethod
253
- def get_experiment_options(context: UserIdentifier, experiments: list[ExperimentIdentifier | ElnTemplate]) \
253
+ def get_experiment_options(context: UserIdentifier, experiments: list[ExperimentIdentifier]) \
254
254
  -> dict[int, dict[str, str]]:
255
255
  """
256
- Run a custom report to retrieve the experiment options for all the provided experiments or experiment templates.
257
- Effectively a batched version of the get_notebook_experiment_options function of ElnManager.
256
+ Run a custom report to retrieve the experiment options for all the provided experiments. Effectively a batched
257
+ version of the get_notebook_experiment_options function of ElnManager.
258
258
 
259
259
  :param context: The current webhook context or a user object to send requests from.
260
- :param experiments: The experiment/template identifiers to retrieve the experiment options for.
260
+ :param experiments: The experiment identifiers to retrieve the experiment options for.
261
261
  :return: A dictionary mapping the notebook experiment ID to the options for that experiment.
262
262
  """
263
- exp_ids: list[int] = []
264
- for exp in experiments:
265
- if isinstance(exp, ElnTemplate):
266
- exp_ids.append(exp.template_id)
267
- else:
268
- exp_ids.append(AliasUtil.to_notebook_id(exp))
263
+ exp_ids: list[int] = AliasUtil.to_notebook_ids(experiments)
269
264
 
270
265
  report_builder = CustomReportBuilder(NotebookExperimentOptionPseudoDef.DATA_TYPE_NAME)
271
266
  tb = report_builder.get_term_builder()
@@ -167,7 +167,7 @@ class PlateDesignerEntry(ElnEntryStep):
167
167
  self._designer_elements_by_plate = {}
168
168
  self._designer_elements_by_plate.clear()
169
169
  for element in self._designer_elements:
170
- plate_id: int = element.get_field_value(WellElement.PLATE_RECORD_ID__FIELD.field_name)
170
+ plate_id: int = element.get(WellElement.PLATE_RECORD_ID__FIELD)
171
171
  self._designer_elements_by_plate.setdefault(plate_id, []).append(element)
172
172
  return self._designer_elements
173
173
 
@@ -194,8 +194,7 @@ class PlateDesignerEntry(ElnEntryStep):
194
194
  return self._designer_elements_by_plate[plate]
195
195
 
196
196
  def create_well_element(self, sample: RecordModel, plate: RecordModel, location: PlateLocation | None = None,
197
- layer: int = 1, wrapper_type: type[WrappedType] | None = None) \
198
- -> WrappedType | PyRecordModel:
197
+ wrapper_type: type[WrappedType] | None = None) -> WrappedType | PyRecordModel:
199
198
  """
200
199
  Create a new plate designer well element for the input sample and plate. A record model manager store and commit
201
200
  must be called to save this new well element to the server.
@@ -204,7 +203,6 @@ class PlateDesignerEntry(ElnEntryStep):
204
203
  :param plate: The plate that the element is for. Must exist in the system (i.e. have a >0 record ID).
205
204
  :param location: The location of the well element. If not provided, the row and column position fields of the
206
205
  sample will be used.
207
- :param layer: The layer that the well element is on.
208
206
  :param wrapper_type: The record model wrapper to use for the plate designer well element. If not provided, the
209
207
  returned record will be a PyRecordModel instead of a WrappedRecordModel.
210
208
  :return: The newly created PlateDesignerWellElementModel.
@@ -218,8 +216,6 @@ class PlateDesignerEntry(ElnEntryStep):
218
216
  raise SapioException("Sample record must be of type Sample.")
219
217
  if AliasUtil.to_data_type_name(plate) != "Plate":
220
218
  raise SapioException("Plate record must be of type Plate.")
221
- if layer < 1:
222
- raise SapioException("Layer must be greater than 0.")
223
219
 
224
220
  dt: type[WrappedType] | str = wrapper_type if wrapper_type else WellElement.DATA_TYPE_NAME
225
221
  plate_id: int = AliasUtil.to_record_id(plate)
@@ -229,7 +225,6 @@ class PlateDesignerEntry(ElnEntryStep):
229
225
  WellElement.ROW_POSITION__FIELD: location.row_pos if location else sample.get_field_value("RowPosition"),
230
226
  WellElement.COL_POSITION__FIELD: str(location.col_pos) if location else sample.get_field_value("ColPosition"),
231
227
  WellElement.SOURCE_DATA_TYPE_NAME__FIELD: "Sample",
232
- WellElement.LAYER__FIELD: layer,
233
228
  }
234
229
  element = self._rec_handler.add_models_with_data(dt, [fields])[0]
235
230
 
@@ -327,13 +327,11 @@ class FileUtil:
327
327
  :param files: A dictionary of file name to file data as a string or bytes.
328
328
  :return: The bytes for a zip file containing the input files.
329
329
  """
330
- with io.BytesIO() as zip_buffer:
331
- with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_file:
332
- for file_name, file_data in files.items():
333
- zip_file.writestr(file_name, file_data)
334
- # PR-47697: Indent the getvalue call into the outer with block. Making the call outside of the with block
335
- # throws an I/O exception.
336
- return zip_buffer.getvalue()
330
+ zip_buffer: io.BytesIO = io.BytesIO()
331
+ with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_file:
332
+ for file_name, file_data in files.items():
333
+ zip_file.writestr(file_name, file_data)
334
+ return zip_buffer.getvalue()
337
335
 
338
336
  # Deprecated functions:
339
337
 
@@ -199,7 +199,7 @@ class AccessionRequestId(AbstractAccessionServiceOperator):
199
199
 
200
200
  Properties:
201
201
  numberOfCharacters: Number of characters maximum in the request ID.
202
- accessorName: This is a legacy variable from drum.getNextIdListByMapName(), which allows setting different "accessorName" from old system. We need this for compatibility patch for converting these to the new preference format.
202
+ accessorName: This is a legacy variable from drum.getNextIdListByMapName(), which allows setting different "accessorName" from old system. We need this for compability patch for converting these to the new preference format.
203
203
  """
204
204
  _num_of_characters: int
205
205
  _accessor_name: str
@@ -341,7 +341,7 @@ class AccessionService:
341
341
  def get_affixed_id_in_batch(self, data_type_name: str, data_field_name: str, num_ids: int, prefix: str | None,
342
342
  suffix: str | None, num_digits: int | None, start_num: int = 1) -> list[str]:
343
343
  """
344
- Get the batch affixed IDs that are maximal in cache and contiguous for a particular datatype.datafield under a given format.
344
+ Get the batch affixed IDs that are maximal in cache and contiguious for a particular datatype.datafield under a given format.
345
345
  :param data_type_name: The datatype name to look for max ID
346
346
  :param data_field_name: The datafield name to look for max ID
347
347
  :param num_ids: The number of IDs to accession.
@@ -219,9 +219,7 @@ class AliasUtil:
219
219
  # noinspection PyTypeChecker
220
220
  fields: FieldMap = record.get_fields()
221
221
  else:
222
- # TI-47593: Copy the record's fields by using the get() method instead of copy_to_dict() so that date
223
- # macros get translated to valid field values.
224
- fields: FieldMap = {f: record.fields.get(f) for f in record.fields}
222
+ fields: FieldMap = record.fields.copy_to_dict()
225
223
  # PR-47457: Only include the record ID if the caller requests it, since including the record ID can break
226
224
  # callbacks in certain circumstances if the record ID is negative.
227
225
  if include_record_id:
@@ -8,7 +8,6 @@ from sapiopycommons.customreport.column_builder import ColumnBuilder
8
8
  from sapiopycommons.customreport.term_builder import TermBuilder
9
9
  from sapiopycommons.datatype.pseudo_data_types import AuditLogPseudoDef
10
10
  from sapiopycommons.general.aliases import RecordIdentifier, AliasUtil, UserIdentifier, FieldIdentifier, FieldValue
11
- from sapiopycommons.general.exceptions import SapioException
12
11
 
13
12
 
14
13
  class EventType(Enum):
@@ -135,9 +134,6 @@ class AuditLogUtil:
135
134
  :param fields: The data field names to include changes for.
136
135
  :return: The constructed CustomReportCriteria object, which can be used to run a report on the audit log.
137
136
  """
138
- # PR-47701: Throw an exception if no records are provided.
139
- if not records:
140
- raise SapioException("No records provided. Please provide at least one record to build a report for.")
141
137
  # Build the raw report term querying for any entry with a matching record ID value to the record ID's
142
138
  # passed in.
143
139
  record_ids = AliasUtil.to_record_ids(records)
@@ -164,9 +160,6 @@ class AuditLogUtil:
164
160
  :return: A dictionary where the keys are the record identifiers passed in, and the values are a list of
165
161
  AuditLogEntry objects which match the record id value of those records.
166
162
  """
167
- # PR-47701: Return an empty dictionary if no records are provided.
168
- if not records:
169
- return {}
170
163
  # First, we must build our report criteria for running the Custom Report.
171
164
  criteria = AuditLogUtil.create_data_record_audit_log_report(records, fields)
172
165
 
@@ -24,12 +24,6 @@ class CustomReportUtil:
24
24
  System reports are also known as predefined searches in the system and must be defined in the data designer for
25
25
  a specific data type. That is, saved searches created by users cannot be run using this function.
26
26
 
27
- IMPORTANT NOTICE: Custom reports that are not single data type (i.e. they have terms or columns from multiple
28
- data types) may not be 100% time accurate. Such reports use the system's ancestor table to retrieve the
29
- relationships, and this table takes some time to update after relationships are updated, especially for more
30
- populous data types. If you need 100% time accurate results to the current state of the records and
31
- relationships in the database, you should query for the records directly instead of using a custom report.
32
-
33
27
  :param context: The current webhook context or a user object to send requests from.
34
28
  :param report_name: The name of the system report to run.
35
29
  :param filters: If provided, filter the results of the report using the given mapping of headers to values to
@@ -69,12 +63,6 @@ class CustomReportUtil:
69
63
  results. They are like advanced or predefined searches from the system, except they are constructed from
70
64
  within the webhook instead of from within the system.
71
65
 
72
- IMPORTANT NOTICE: Custom reports that are not single data type (i.e. they have terms or columns from multiple
73
- data types) may not be 100% time accurate. Such reports use the system's ancestor table to retrieve the
74
- relationships, and this table takes some time to update after relationships are updated, especially for more
75
- populous data types. If you need 100% time accurate results to the current state of the records and
76
- relationships in the database, you should query for the records directly instead of using a custom report.
77
-
78
66
  :param context: The current webhook context or a user object to send requests from.
79
67
  :param report_criteria: The custom report criteria to run.
80
68
  :param filters: If provided, filter the results of the report using the given mapping of headers to values to
@@ -94,9 +94,6 @@ class QueueItemHandler:
94
94
  """
95
95
  A class used for handling the display of records in custom process queues, which are controlled in the system by
96
96
  ProcessQueueItem data types.
97
-
98
- IMPORTANT NOTICE: This is only for custom processes that make use of ProcessQueueItem records. For experiment
99
- processes that use AssignedProcess records, see the ProcessTracking class.
100
97
  """
101
98
  user: SapioUser
102
99
  context: ProcessQueueContext | None
@@ -108,8 +105,7 @@ class QueueItemHandler:
108
105
  """
109
106
  self.user = AliasUtil.to_sapio_user(context)
110
107
  self.rec_handler = RecordHandler(self.user)
111
- # PR-47565: Only initialize a ProcessQueueContext if the given context object has context_data.
112
- if isinstance(context, SapioWebhookContext) and context.context_data:
108
+ if isinstance(context, SapioWebhookContext):
113
109
  self.context = ProcessQueueContext(context)
114
110
  else:
115
111
  self.context = None
@@ -264,9 +260,6 @@ class QueueItemHandler:
264
260
  Given a list of records, create process queue item records for them at the provided process and step names.
265
261
  You must store and commit using the record model manager in order for these changes to take effect.
266
262
 
267
- IMPORTANT NOTICE: This is only for custom processes that make use of ProcessQueueItem records. For experiment
268
- processes that use AssignedProcess records, see the ProcessTracking class.
269
-
270
263
  :param records: The records to create process queue items for.
271
264
  :param process: The name of the process to queue for.
272
265
  :param step: The name of the step in the above process to queue for. This is the "Workflow Name" field of the
@@ -299,9 +292,6 @@ class QueueItemHandler:
299
292
  criteria and remove them from the queue by setting the ShowInQueue field on the process queue items to false.
300
293
  You must store and commit using the record model manager in order for these changes to take effect.
301
294
 
302
- IMPORTANT NOTICE: This is only for custom processes that make use of ProcessQueueItem records. For experiment
303
- processes that use AssignedProcess records, see the ProcessTracking class.
304
-
305
295
  :param records: The records to remove from the queue.
306
296
  :param wrapper: The record model wrapper for the process queue items being updated. If not provided, the
307
297
  returned records will be PyRecordModels instead of WrappedRecordModels.
@@ -5,12 +5,6 @@ from sapiopycommons.general.aliases import RecordIdentifier, AliasUtil, Experime
5
5
 
6
6
 
7
7
  class ProcessTracking:
8
- """
9
- A class for calling the Foundations process tracking endpoints.
10
-
11
- IMPORTANT NOTICE: This is only for experiment processes that make use of AssignedProcess records. For custom
12
- processes that use ProcessQueueItem records, see the QueueItemHandler class.
13
- """
14
8
  @staticmethod
15
9
  def assign_to_process(context: UserIdentifier, data_type: DataTypeIdentifier, records: list[RecordIdentifier],
16
10
  process_name: str, step_number: int | None = None, branch_id: int | None = None,
@@ -20,9 +14,6 @@ class ProcessTracking:
20
14
  at that step.
21
15
  Synonymous with what occurs during request creation or when using the assign to process button.
22
16
 
23
- IMPORTANT NOTICE: This is only for experiment processes that make use of AssignedProcess records. For custom
24
- processes that use ProcessQueueItem records, see the QueueItemHandler class.
25
-
26
17
  :param context: The current webhook context or a user object to send requests from.
27
18
  :param data_type: The data type of the tracked records.
28
19
  :param records: A list of the tracked records.
@@ -55,9 +46,6 @@ class ProcessTracking:
55
46
  tracked records from "Ready for -" to "In Process -" for their current step.
56
47
  Synonymous with what occurs when starting a process step in the system.
57
48
 
58
- IMPORTANT NOTICE: This is only for experiment processes that make use of AssignedProcess records. For custom
59
- processes that use ProcessQueueItem records, see the QueueItemHandler class.
60
-
61
49
  :param context: The current webhook context or a user object to send requests from.
62
50
  :param data_type: The data type of the tracked records.
63
51
  :param records: A list of the tracked records.
@@ -85,9 +73,6 @@ class ProcessTracking:
85
73
  Moves the assigned process down to the descendant sample(s) if both samples are provided in the records list.
86
74
  Synonymous with what occurs when completing an experiment in the system.
87
75
 
88
- IMPORTANT NOTICE: This is only for experiment processes that make use of AssignedProcess records. For custom
89
- processes that use ProcessQueueItem records, see the QueueItemHandler class.
90
-
91
76
  :param context: The current webhook context or a user object to send requests from.
92
77
  :param data_type: The data type of the tracked records.
93
78
  :param records: A list of the tracked records.
@@ -111,9 +96,6 @@ class ProcessTracking:
111
96
  records must be "In Process -" for the given step.
112
97
  Synonymous with what occurs when failing a sample due to a QC failure in a process in the system.
113
98
 
114
- IMPORTANT NOTICE: This is only for experiment processes that make use of AssignedProcess records. For custom
115
- processes that use ProcessQueueItem records, see the QueueItemHandler class.
116
-
117
99
  :param context: The current webhook context or a user object to send requests from.
118
100
  :param data_type: The data type of the tracked records.
119
101
  :param records: A list of the tracked records.
@@ -140,9 +122,6 @@ class ProcessTracking:
140
122
  will move their status to "Ready for -" for the next step in the process, or "Completed -" if this was the
141
123
  last step.
142
124
 
143
- IMPORTANT NOTICE: This is only for experiment processes that make use of AssignedProcess records. For custom
144
- processes that use ProcessQueueItem records, see the QueueItemHandler class.
145
-
146
125
  :param context: The current webhook context or a user object to send requests from.
147
126
  :param data_type: The data type of the tracked records.
148
127
  :param records: A list of the tracked records.
@@ -170,9 +149,6 @@ class ProcessTracking:
170
149
  step will move their status to "Ready for -" for the next step in the process, or "Completed -" if this was the
171
150
  last step.
172
151
 
173
- IMPORTANT NOTICE: This is only for experiment processes that make use of AssignedProcess records. For custom
174
- processes that use ProcessQueueItem records, see the QueueItemHandler class.
175
-
176
152
  :param context: The current webhook context or a user object to send requests from.
177
153
  :param data_type: The data type of the tracked records.
178
154
  :param records: A list of the tracked records.
@@ -204,9 +180,6 @@ class ProcessTracking:
204
180
  Synonymous with what occurs when reprocessing records to a previous step due to QC failures in a process in the
205
181
  system.
206
182
 
207
- IMPORTANT NOTICE: This is only for experiment processes that make use of AssignedProcess records. For custom
208
- processes that use ProcessQueueItem records, see the QueueItemHandler class.
209
-
210
183
  :param context: The current webhook context or a user object to send requests from.
211
184
  :param records: A list of ReturnPoint records to reprocess to.
212
185
  """