sapiopycommons 2024.11.7a354__py3-none-any.whl → 2024.11.8a359__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 (47) hide show
  1. sapiopycommons/callbacks/callback_util.py +83 -532
  2. sapiopycommons/chem/IndigoMolecules.py +0 -2
  3. sapiopycommons/chem/Molecules.py +18 -77
  4. sapiopycommons/datatype/attachment_util.py +10 -11
  5. sapiopycommons/eln/experiment_handler.py +70 -272
  6. sapiopycommons/files/complex_data_loader.py +4 -5
  7. sapiopycommons/files/file_bridge.py +24 -31
  8. sapiopycommons/files/file_data_handler.py +5 -2
  9. sapiopycommons/files/file_util.py +9 -59
  10. sapiopycommons/files/file_validator.py +6 -92
  11. sapiopycommons/files/file_writer.py +15 -44
  12. sapiopycommons/general/aliases.py +6 -207
  13. sapiopycommons/general/custom_report_util.py +37 -212
  14. sapiopycommons/general/exceptions.py +8 -21
  15. sapiopycommons/general/popup_util.py +0 -21
  16. sapiopycommons/general/time_util.py +2 -8
  17. sapiopycommons/processtracking/endpoints.py +22 -22
  18. sapiopycommons/recordmodel/record_handler.py +97 -481
  19. sapiopycommons/rules/eln_rule_handler.py +25 -34
  20. sapiopycommons/rules/on_save_rule_handler.py +31 -34
  21. sapiopycommons/webhook/webhook_handlers.py +42 -201
  22. {sapiopycommons-2024.11.7a354.dist-info → sapiopycommons-2024.11.8a359.dist-info}/METADATA +2 -4
  23. sapiopycommons-2024.11.8a359.dist-info/RECORD +38 -0
  24. sapiopycommons/callbacks/field_builder.py +0 -537
  25. sapiopycommons/customreport/__init__.py +0 -0
  26. sapiopycommons/customreport/column_builder.py +0 -60
  27. sapiopycommons/customreport/custom_report_builder.py +0 -130
  28. sapiopycommons/customreport/term_builder.py +0 -299
  29. sapiopycommons/datatype/data_fields.py +0 -61
  30. sapiopycommons/datatype/pseudo_data_types.py +0 -440
  31. sapiopycommons/eln/experiment_report_util.py +0 -653
  32. sapiopycommons/files/file_bridge_handler.py +0 -340
  33. sapiopycommons/flowcyto/flow_cyto.py +0 -77
  34. sapiopycommons/flowcyto/flowcyto_data.py +0 -75
  35. sapiopycommons/general/accession_service.py +0 -375
  36. sapiopycommons/general/audit_log.py +0 -189
  37. sapiopycommons/general/sapio_links.py +0 -50
  38. sapiopycommons/multimodal/multimodal.py +0 -146
  39. sapiopycommons/multimodal/multimodal_data.py +0 -489
  40. sapiopycommons/processtracking/custom_workflow_handler.py +0 -406
  41. sapiopycommons/sftpconnect/__init__.py +0 -0
  42. sapiopycommons/sftpconnect/sftp_builder.py +0 -69
  43. sapiopycommons/webhook/webhook_context.py +0 -39
  44. sapiopycommons/webhook/webservice_handlers.py +0 -67
  45. sapiopycommons-2024.11.7a354.dist-info/RECORD +0 -59
  46. {sapiopycommons-2024.11.7a354.dist-info → sapiopycommons-2024.11.8a359.dist-info}/WHEEL +0 -0
  47. {sapiopycommons-2024.11.7a354.dist-info → sapiopycommons-2024.11.8a359.dist-info}/licenses/LICENSE +0 -0
@@ -1,406 +0,0 @@
1
- from typing import Iterable
2
-
3
- from sapiopylib.rest.User import SapioUser
4
- from sapiopylib.rest.pojo.CustomReport import CustomReportCriteria
5
- from sapiopylib.rest.pojo.webhook.WebhookContext import SapioWebhookContext
6
- from sapiopylib.rest.utils.recordmodel.RecordModelWrapper import WrappedType
7
-
8
- from sapiopycommons.customreport.custom_report_builder import CustomReportBuilder
9
- from sapiopycommons.customreport.term_builder import TermBuilder
10
- from sapiopycommons.datatype.data_fields import ProcessQueueItemFields, SystemFields, ProcessWorkflowTrackingFields
11
- from sapiopycommons.general.aliases import UserIdentifier, AliasUtil, SapioRecord
12
- from sapiopycommons.general.custom_report_util import CustomReportUtil
13
- from sapiopycommons.general.exceptions import SapioException
14
- from sapiopycommons.general.time_util import TimeUtil
15
- from sapiopycommons.recordmodel.record_handler import RecordHandler
16
- from sapiopycommons.webhook.webhook_context import ProcessQueueContext
17
-
18
-
19
- class QueueItemReportCriteria:
20
- """
21
- Queue item report criteria is used to restrict the results of searches for queue item records.
22
- """
23
- process_names: list[str] | None
24
- not_process_names: list[str] | None
25
- step_names: list[str] | None
26
- not_step_names: list[str] | None
27
- data_type_names: list[str] | None
28
- not_data_type_names: list[str] | None
29
- data_record_ids: list[int] | None
30
- not_data_record_ids: list[int] | None
31
- assigned_to: list[str] | None
32
- not_assigned_to: list[str] | None
33
- launched_after: int | None
34
- launched_before: int | None
35
- scheduled_after: int | None
36
- scheduled_before: int | None
37
- shown_in_queue: bool | None
38
- has_experiment: bool | None
39
-
40
- def __init__(self, *,
41
- process_names: list[str] | None = None,
42
- not_process_names: list[str] | None = None,
43
- step_names: list[str] | None = None,
44
- not_step_names: list[str] | None = None,
45
- data_type_names: list[str] | None = None,
46
- not_data_type_names: list[str] | None = None,
47
- data_record_ids: list[int] | None = None,
48
- not_data_record_ids: list[int] | None = None,
49
- assigned_to: list[str] | None = None,
50
- not_assigned_to: list[str] | None = None,
51
- launched_after: int | None = None,
52
- launched_before: int | None = None,
53
- scheduled_after: int | None = None,
54
- scheduled_before: int | None = None,
55
- shown_in_queue: bool | None = None,
56
- has_experiment: bool | None = None):
57
- """
58
- :param process_names: The allowed process name(s).
59
- :param not_process_names: The disallowed process name(s).
60
- :param step_names: The allowed step name(s).
61
- :param not_step_names: The disallowed step name(s).
62
- :param data_type_names: The allowed data type name(s).
63
- :param not_data_type_names: The disallowed dta type name(s).
64
- :param data_record_ids: The allowed record ID(s).
65
- :param not_data_record_ids: The disallowed record ID(s).
66
- :param assigned_to: The allowed username(s) of the user(s) that the queue items are assigned to.
67
- :param not_assigned_to: The disallowed username(s) of the user(s) that the queue items are assigned to.
68
- :param launched_after: A timestamp after which the queue item was launched.
69
- :param launched_before: A timestamp before which the queue item was launched.
70
- :param scheduled_after: A timestamp after which the queue item was scheduled.
71
- :param scheduled_before: A timestamp before which the queue item was scheduled.
72
- :param shown_in_queue: Whether the queue item is currently being shown in a queue.
73
- :param has_experiment: Whether the queue item is linked to an experiment record.
74
- """
75
- self.process_names = process_names
76
- self.not_process_names = not_process_names
77
- self.step_names = step_names
78
- self.not_step_names = not_step_names
79
- self.data_type_names = data_type_names
80
- self.not_data_type_names = not_data_type_names
81
- self.data_record_ids = data_record_ids
82
- self.not_data_record_ids = not_data_record_ids
83
- self.assigned_to = assigned_to
84
- self.not_assigned_to = not_assigned_to
85
- self.launched_after = launched_after
86
- self.launched_before = launched_before
87
- self.scheduled_after = scheduled_after
88
- self.scheduled_before = scheduled_before
89
- self.shown_in_queue = shown_in_queue
90
- self.has_experiment = has_experiment
91
-
92
-
93
- class QueueItemHandler:
94
- """
95
- A class used for handling the display of records in custom process queues, which are controlled in the system by
96
- ProcessQueueItem data types.
97
- """
98
- user: SapioUser
99
- context: ProcessQueueContext | None
100
- rec_handler: RecordHandler
101
-
102
- def __init__(self, context: UserIdentifier):
103
- """
104
- :param context: The current webhook context or a user object to send requests from.
105
- """
106
- self.user = AliasUtil.to_sapio_user(context)
107
- self.rec_handler = RecordHandler(self.user)
108
- if isinstance(context, SapioWebhookContext):
109
- self.context = ProcessQueueContext(context)
110
- else:
111
- self.context = None
112
-
113
- def get_process_queue_items_from_context(self, wrapper: type[WrappedType],
114
- context: SapioWebhookContext | ProcessQueueContext | None = None) \
115
- -> list[WrappedType]:
116
- """
117
- When you launch records from a custom process queue, the process queue items related to the selected records
118
- are provided as record IDs to the process queue context. Using these record IDs, query for the queue item
119
- records and wrap them as record models.
120
-
121
- :param wrapper: The record model wrapper for the process queue items.
122
- :param context: If this handler was not initialized with a context object, or you wish to retrieve
123
- data from a different context object than the initializing context, then provide the context to retrieve the
124
- record IDs from.
125
- :return: The process queue items corresponding to the record IDs from the context wrapped as record models.
126
- """
127
- if context is None and self.context is not None:
128
- record_ids: list[int] = self.context.process_queue_item_record_ids
129
- elif context is not None:
130
- if isinstance(context, SapioWebhookContext):
131
- record_ids: list[int] = ProcessQueueContext(context).process_queue_item_record_ids
132
- else:
133
- record_ids: list[int] = context.process_queue_item_record_ids
134
- else:
135
- raise SapioException("A context object must be provided to this function call, as the handler "
136
- "was not initialized with one.")
137
- return self.rec_handler.query_models_by_id(wrapper, record_ids)
138
-
139
- def map_records_to_queue_items(self, records: Iterable[SapioRecord], queue_items: Iterable[SapioRecord]) \
140
- -> dict[SapioRecord, list[SapioRecord]]:
141
- """
142
- Given a list of records and a list of queue items, create a dictionary mapping the records to the queue items
143
- that refer to them.
144
-
145
- :param records: The records to map to the queue items.
146
- :param queue_items: The queue items to map to the records.
147
- :return: A dictionary of record to the queue items that refer to them. Input queue items that don't refer to
148
- any provided records will not be in this dictionary.
149
- """
150
- ret_val: dict[SapioRecord, list[SapioRecord]] = {}
151
- id_to_queue_items: dict[int, list[SapioRecord]] = self.rec_handler.map_by_field(queue_items,
152
- ProcessQueueItemFields.DATA_RECORD_ID__FIELD)
153
- id_to_record: dict[int, SapioRecord] = self.rec_handler.map_by_id(records)
154
- for record_id, record in id_to_record.items():
155
- ret_val[record] = id_to_queue_items[record_id]
156
- return ret_val
157
-
158
- def map_queue_items_to_records(self, queue_items: Iterable[SapioRecord], records: Iterable[SapioRecord]) \
159
- -> dict[SapioRecord, SapioRecord]:
160
- """
161
- Given a list of queue items and a list of records, create a dictionary mapping the queue items to the record
162
- that they refer to.
163
-
164
- :param queue_items: The queue items to map to the records.
165
- :param records: The records to map to the queue items.
166
- :return: A dictionary of queue items to the records that the refer to. Input record that aren't referred to by
167
- any provided queue items will not be in this dictionary.
168
- """
169
- ret_val: dict[SapioRecord, SapioRecord] = {}
170
- id_to_queue_items: dict[int, list[SapioRecord]] = self.rec_handler.map_by_field(queue_items,
171
- ProcessQueueItemFields.DATA_RECORD_ID__FIELD)
172
- id_to_record: dict[int, SapioRecord] = self.rec_handler.map_by_id(records)
173
- for record_id, queue_items in id_to_queue_items.items():
174
- record: SapioRecord = id_to_record[record_id]
175
- for queue_item in queue_items:
176
- ret_val[queue_item] = record
177
- return ret_val
178
-
179
- def get_queue_items_from_report(self, wrapper: type[WrappedType], criteria: QueueItemReportCriteria) \
180
- -> list[WrappedType]:
181
- """
182
- Run a custom report that retrieves every queue item in the system for the given search criteria.
183
-
184
- :param wrapper: The record model wrapper for the process queue items.
185
- :param criteria: The search criteria to query for queue items with.
186
- :return: A list of every queue item in the system that matches the search criteria.
187
- """
188
- report = self.build_queue_item_report(criteria)
189
- return self.rec_handler.query_models_by_report(wrapper, report)
190
-
191
- def get_records_from_item_report(self, wrapper: type[WrappedType],
192
- criteria: QueueItemReportCriteria = QueueItemReportCriteria()) -> list[WrappedType]:
193
- """
194
- Run a custom report that retrieves for queue items that match the given search criteria, then query for the
195
- data records that those queue items refer to.
196
-
197
- :param wrapper: The record model wrapper for the records being queried for.
198
- :param criteria: Additional search criteria to filter the results. This function forces the data_type_names
199
- parameter of the criteria to match the data type of the given record model wrapper.
200
- :return: A list of all records related to the queue items in the system that match the search criteria.
201
- """
202
- # Don't try to query for process queue items that don't match the data type of this wrapper.
203
- criteria.data_type_names = [wrapper.get_wrapper_data_type_name()]
204
- criteria.not_data_type_names = None
205
- report = self.build_queue_item_report(criteria)
206
- record_ids: list[int] = [x[ProcessQueueItemFields.DATA_RECORD_ID__FIELD.field_name]
207
- for x in CustomReportUtil.run_custom_report(self.user, report)]
208
- return self.rec_handler.query_models_by_id(wrapper, record_ids)
209
-
210
- def get_queue_items_for_records(self, records: Iterable[SapioRecord], wrapper: type[WrappedType],
211
- criteria: QueueItemReportCriteria = QueueItemReportCriteria()) \
212
- -> dict[SapioRecord, list[WrappedType]]:
213
- """
214
- Given a list of records, query the system for every process queue item that refers to those records and matches
215
- the provided search criteria.
216
-
217
- :param records: The queued records to query for the process queue items of.
218
- :param wrapper: The record model wrapper for the returned process queue item records.
219
- :param criteria: Additional search criteria to filter the results. This function forces the data_record_ids and
220
- data_type_names parameters on the criteria to match the given records.
221
- :return: A dictionary mapping the input records to a list of the process queue items that refer to them. If a
222
- record does not have any queue items that refer to it that match the given search criteria, then it will
223
- map to an empty list.
224
- """
225
- # Query for only those process queue items that have a record ID from the provided records.
226
- criteria.data_record_ids = AliasUtil.to_record_ids(records)
227
- criteria.not_data_record_ids = None
228
- criteria.data_type_names = AliasUtil.to_data_type_names(records)
229
- criteria.not_data_type_names = None
230
- items: list[WrappedType] = self.get_queue_items_from_report(wrapper, criteria)
231
- return self.map_records_to_queue_items(records, items)
232
-
233
- def get_records_for_queue_items(self, queue_items: Iterable[SapioRecord], wrapper: type[WrappedType]) \
234
- -> dict[SapioRecord, WrappedType]:
235
- """
236
- Given a list of process queue items, query the system for the records that those queue items refer to.
237
-
238
- :param queue_items: The process queue items to query for the referenced records of.
239
- :param wrapper: The record model wrapper for the records being queried.
240
- :return: A dictionary mapping the input process queue items to the record tht they refer to.
241
- """
242
- record_ids: set[int] = {x.get_field_value(ProcessQueueItemFields.DATA_RECORD_ID__FIELD) for x in queue_items}
243
- records: list[WrappedType] = self.rec_handler.query_models_by_id(wrapper, record_ids)
244
- return self.map_queue_items_to_records(queue_items, records)
245
-
246
- def queue_records_for_process(self, records: Iterable[SapioRecord], process: str, step: str,
247
- wrapper: type[WrappedType]) -> dict[SapioRecord, WrappedType]:
248
- """
249
- Given a list of records, create process queue item records for them at the provided process and step names.
250
- You must store and commit using the record model manager in order for these changes to take effect.
251
-
252
- :param records: The records to create process queue items for.
253
- :param wrapper: The record model wrapper for the process queue items being created.
254
- :param process: The name of the process to queue for.
255
- :param step: The name of the step in the above process to queue for. This is the "Workflow Name" field of the
256
- Process Workflow record corresponding to the step you want to assign these records to. For steps that
257
- launch an experiment, this is the name of the template that will be launched. For the other types of custom
258
- process steps, this is the "Workflow Name" as defined in the process manager config.
259
- :return: A dictionary mapping each input record to the newly created process queue item for that record.
260
- """
261
- ret_val: dict[SapioRecord, WrappedType] = {}
262
- for record in records:
263
- item = self.rec_handler.add_model(wrapper)
264
- item.set_field_values({
265
- ProcessQueueItemFields.PROCESS_HEADER_NAME__FIELD.field_name: process,
266
- ProcessQueueItemFields.WORKFLOW_HEADER_NAME__FIELD.field_name: step,
267
- ProcessQueueItemFields.SHOW_IN_QUEUE__FIELD.field_name: True,
268
- ProcessQueueItemFields.SCHEDULED_DATE__FIELD.field_name: TimeUtil.now_in_millis(),
269
- ProcessQueueItemFields.DATA_RECORD_ID__FIELD.field_name: AliasUtil.to_record_id(record),
270
- ProcessQueueItemFields.DATA_TYPE_NAME__FIELD.field_name: AliasUtil.to_data_type_name(record)
271
- })
272
- ret_val[record] = item
273
- return ret_val
274
-
275
- def dequeue_records_for_process(self, records: Iterable[SapioRecord], wrapper: type[WrappedType],
276
- criteria: QueueItemReportCriteria = QueueItemReportCriteria()) \
277
- -> dict[SapioRecord, list[WrappedType]]:
278
- """
279
- Given a list of records, locate the process queue items that refer to them and that match the given search
280
- criteria and remove them from the queue by setting the ShowInQueue field on the process queue items to false.
281
- You must store and commit using the record model manager in order for these changes to take effect.
282
-
283
- :param records: The records to remove from the queue.
284
- :param wrapper: The record model wrapper for the process queue items being updated.
285
- :param criteria: Additional search criteria to filter the results. This function forces the show_in_queue
286
- parameter on the criteria to True.
287
- :return: A dictionary mapping each input record to the queue item records that refer to that record and were
288
- updated. If a record does not have any queue items that refer to it that match the given search criteria,
289
- then it will map to an empty list.
290
- """
291
- # Only locate queue items that are currently visible in the queue.
292
- criteria.shown_in_queue = True
293
- dequeue: dict[SapioRecord, list[WrappedType]] = self.get_queue_items_for_records(records, wrapper, criteria)
294
- for record, items in dequeue.items():
295
- for item in items:
296
- item.set_field_value(ProcessQueueItemFields.SHOW_IN_QUEUE__FIELD.field_name, False)
297
- return dequeue
298
-
299
- @staticmethod
300
- def assigned_queue_items(queue_items: Iterable[SapioRecord], assign_to: list[str]) -> None:
301
- """
302
- Given a collection of queue items, assign them to a list of usernames or group names. Only those users in the
303
- listed groups or those users with the matching username will be able to see these related records in the process
304
- queue.
305
- You must store and commit using the record model manager in order for these changes to take effect.
306
-
307
- :param queue_items: The queue items to assign.
308
- :param assign_to: A list of usernames and/or group names to assign these items to.
309
- """
310
- for item in queue_items:
311
- item.set_field_value(ProcessQueueItemFields.ASSIGNED_TO__FIELD, ",".join(assign_to))
312
-
313
- def get_queue_item_workflow_trackers(self, items: Iterable[SapioRecord], wrapper: type[WrappedType]) \
314
- -> dict[SapioRecord, list[WrappedType]]:
315
- """
316
- When a queue item is launched into a process step, a ProcessWorkflowTracking record is created by the system
317
- with a side link to the process queue item. This record records information about how long the record ws in
318
- the queue, among other details.
319
-
320
- Retrieve the workflow tracker records for the input queue items.
321
-
322
- :param items: The queue items to load the workflow trackers of.
323
- :param wrapper: The record model wrapper for the ProcessWorkflowTracking records.
324
- :return: A dictionary mapping each queue item to the workflow trackers that side link to that item. If an input
325
- queue item doesn't have any workflow trackers, then it will map to an empty list.
326
- """
327
- field: str = ProcessWorkflowTrackingFields.PROCESS_QUEUE_ITEM__FIELD.field_name
328
- self.rec_handler.rel_man.load_reverse_side_links_of_type(list(items), wrapper, field)
329
- return self.rec_handler.map_to_reverse_side_links(items, field, wrapper)
330
-
331
- @staticmethod
332
- def build_queue_item_report(criteria: QueueItemReportCriteria) -> CustomReportCriteria:
333
- """
334
- Construct a custom report using the provided QueueItemReportCriteria.
335
-
336
- :param criteria: The criteria to construct a custom report from.
337
- :return: A custom report that can be used to search for queue items that match the given criteria.
338
- """
339
- dt: str = ProcessQueueItemFields.DATA_TYPE_NAME
340
- report_builder = CustomReportBuilder(dt)
341
- report_builder.add_column(SystemFields.RECORD_ID__FIELD)
342
- report_builder.add_column(ProcessQueueItemFields.DATA_RECORD_ID__FIELD)
343
-
344
- root = TermBuilder.all_records_term(dt)
345
-
346
- if criteria.process_names is not None:
347
- term = TermBuilder.is_term(dt, ProcessQueueItemFields.PROCESS_HEADER_NAME__FIELD, criteria.process_names)
348
- root = TermBuilder.and_terms(root, term)
349
- if criteria.not_process_names is not None:
350
- term = TermBuilder.not_term(dt, ProcessQueueItemFields.PROCESS_HEADER_NAME__FIELD, criteria.not_process_names)
351
- root = TermBuilder.and_terms(root, term)
352
-
353
- if criteria.step_names is not None:
354
- term = TermBuilder.is_term(dt, ProcessQueueItemFields.WORKFLOW_HEADER_NAME__FIELD, criteria.step_names)
355
- root = TermBuilder.and_terms(root, term)
356
- if criteria.not_step_names is not None:
357
- term = TermBuilder.not_term(dt, ProcessQueueItemFields.WORKFLOW_HEADER_NAME__FIELD, criteria.not_step_names)
358
- root = TermBuilder.and_terms(root, term)
359
-
360
- if criteria.data_type_names is not None:
361
- term = TermBuilder.is_term(dt, ProcessQueueItemFields.DATA_TYPE_NAME__FIELD, criteria.data_type_names)
362
- root = TermBuilder.and_terms(root, term)
363
- if criteria.not_data_type_names is not None:
364
- term = TermBuilder.not_term(dt, ProcessQueueItemFields.DATA_TYPE_NAME__FIELD, criteria.not_data_type_names)
365
- root = TermBuilder.and_terms(root, term)
366
-
367
- if criteria.data_record_ids is not None:
368
- term = TermBuilder.is_term(dt, ProcessQueueItemFields.DATA_RECORD_ID__FIELD, criteria.data_record_ids)
369
- root = TermBuilder.and_terms(root, term)
370
- if criteria.not_data_record_ids is not None:
371
- term = TermBuilder.not_term(dt, ProcessQueueItemFields.DATA_RECORD_ID__FIELD, criteria.not_data_record_ids)
372
- root = TermBuilder.and_terms(root, term)
373
-
374
- if criteria.assigned_to is not None:
375
- term = TermBuilder.is_term(dt, ProcessQueueItemFields.ASSIGNED_TO__FIELD, criteria.assigned_to)
376
- root = TermBuilder.and_terms(root, term)
377
- if criteria.not_assigned_to is not None:
378
- term = TermBuilder.not_term(dt, ProcessQueueItemFields.ASSIGNED_TO__FIELD, criteria.not_assigned_to)
379
- root = TermBuilder.and_terms(root, term)
380
-
381
- if criteria.launched_after is not None:
382
- term = TermBuilder.gte_term(dt, ProcessQueueItemFields.LAUNCHED_DATE__FIELD, criteria.launched_after)
383
- root = TermBuilder.and_terms(root, term)
384
- if criteria.launched_before is not None:
385
- term = TermBuilder.lte_term(dt, ProcessQueueItemFields.LAUNCHED_DATE__FIELD, criteria.launched_before)
386
- root = TermBuilder.and_terms(root, term)
387
-
388
- if criteria.scheduled_after is not None:
389
- term = TermBuilder.gte_term(dt, ProcessQueueItemFields.LAUNCHED_DATE__FIELD, criteria.scheduled_after)
390
- root = TermBuilder.and_terms(root, term)
391
- if criteria.scheduled_before is not None:
392
- term = TermBuilder.lte_term(dt, ProcessQueueItemFields.LAUNCHED_DATE__FIELD, criteria.scheduled_before)
393
- root = TermBuilder.and_terms(root, term)
394
-
395
- if criteria.shown_in_queue is not None:
396
- term = TermBuilder.is_term(dt, ProcessQueueItemFields.SHOW_IN_QUEUE__FIELD, criteria.shown_in_queue)
397
- root = TermBuilder.and_terms(root, term)
398
- if criteria.has_experiment is not None:
399
- if criteria.has_experiment:
400
- term = TermBuilder.not_term(dt, ProcessQueueItemFields.EXPERIMENT__FIELD, None)
401
- else:
402
- term = TermBuilder.is_term(dt, ProcessQueueItemFields.EXPERIMENT__FIELD, None)
403
- root = TermBuilder.and_terms(root, term)
404
-
405
- report_builder.set_root_term(root)
406
- return report_builder.build_report_criteria()
File without changes
@@ -1,69 +0,0 @@
1
- import io
2
- from enum import Enum
3
-
4
- import paramiko
5
- from paramiko import pkey
6
- from paramiko.sftp_client import SFTPClient
7
- from sapiopycommons.general.exceptions import SapioException
8
-
9
-
10
- class SFTPAuthMethod(Enum):
11
- """
12
- An enum being used to specify connection type to the target server.
13
- """
14
- PASSWORD = 0
15
- """Connection is being done via Password."""
16
- FILEPATH = 1
17
- """Connection is being done using a private key file in the codebase."""
18
- KEY_STRING = 2
19
- """Connection is being done using a private key in string form."""
20
-
21
-
22
- class SFTPBuilder:
23
- """
24
- A class for making SFTP connections.
25
- """
26
-
27
- @staticmethod
28
- def open_sftp(username: str, host: str, port: int, authentication: str,
29
- connection_type: SFTPAuthMethod = SFTPAuthMethod.PASSWORD) -> SFTPClient:
30
- """
31
- Builds a SFTP client from user input.
32
-
33
- :param username: The username of the individual trying to connect to the target server.
34
- :param host: The hostname/IP address of the target server.
35
- :param port: The port number used to connect to the target server.
36
- :param authentication: The string used to connect to the target server. This could hold a filepath, a password
37
- or a private key in string form depending on the connection_type parameter.
38
-
39
- If authentication is a private key string, they are generally formated like this:
40
- -----BEGIN OPENSSH PRIVATE KEY-----\n
41
- asdfh;hjadfh;jghajdg54646+5fasdfadlajklgajd'gj'ajg654564\n
42
- asdkjfhj;kghj;ahj;wh41234hjadjkhhdsgadshjkdghjshdlsds468\n
43
- ....
44
-
45
- :param connection_type: This enum is used to specify how the connection to the target server is being made.
46
- The options are:
47
- (0) PASSWORD: This means that the authentication parameter contains a password that will be used to connect to the server
48
- (1) FILEPATH: This means that the authentication parameter contains a filepath leading to a private key file stored in the codebase
49
- (2) KEY_STRING: This means that the authentication parameter contains the private key in string form
50
-
51
- """
52
-
53
- client = paramiko.SSHClient()
54
- client.set_missing_host_key_policy(paramiko.MissingHostKeyPolicy)
55
-
56
- if connection_type == SFTPAuthMethod.FILEPATH:
57
- client.connect(host, username=username, port=port, key_filename=authentication)
58
- return client.open_sftp()
59
-
60
- if connection_type == SFTPAuthMethod.KEY_STRING:
61
- private_key: pkey = paramiko.RSAKey.from_private_key(io.StringIO(authentication))
62
- client.connect(host, username=username, port=port, pkey=private_key)
63
- return client.open_sftp()
64
-
65
- if connection_type == SFTPAuthMethod.PASSWORD:
66
- client.connect(host, username=username, password=authentication, port=port)
67
- return client.open_sftp()
68
-
69
- raise SapioException("The SFTPAuthMethod enumerator was not properly specified.")
@@ -1,39 +0,0 @@
1
- import json
2
- from typing import Any
3
-
4
- from sapiopylib.rest.pojo.webhook.WebhookContext import SapioWebhookContext
5
-
6
-
7
- class CustomWebhookContext(SapioWebhookContext):
8
- """
9
- CustomWebhookContext is a wrapper for the default SapioWebhookContext to be used by custom invocation types to
10
- convert the context_data that the server sends from a JSON string to usable parameters. This class works as a
11
- middleman to cleanly convert a SapioWebhookContext object into a CustomWebhookContext by copying all the parameters
12
- of the given context into the custom context.
13
- """
14
- def __init__(self, context: SapioWebhookContext):
15
- # Use __dict__ so that we don't need t maintain this class due to future changes to SapioWebhookContext.
16
- self.__dict__ = context.__dict__
17
- super().__init__(self.user, self.end_point_type)
18
-
19
-
20
- class ProcessQueueContext(CustomWebhookContext):
21
- """
22
- When a custom process queue endpoint is invoked, the context from the queue is sent in a context_data parameter
23
- on the SapioWebhookContext object, stored as a JSON string. This class parses that JSON into fields for the
24
- caller to make use of.
25
- """
26
- process_name: str
27
- """The name of the process that the user invoked this webhook from."""
28
- step_name: str
29
- """The name of the step in the process that the user invoked this webhook from."""
30
- process_queue_item_record_ids: list[int]
31
- """The record IDs of the process queue items related to the records that were selected by the user when this
32
- webhook was invoked."""
33
-
34
- def __init__(self, context: SapioWebhookContext):
35
- super().__init__(context)
36
- context_data: dict[str, Any] = json.loads(self.context_data)
37
- self.process_name = context_data["processName"]
38
- self.step_name = context_data["workflowName"]
39
- self.process_queue_item_record_ids = context_data["processQueueItemRecordIds"]
@@ -1,67 +0,0 @@
1
- import sys
2
- import traceback
3
- from abc import abstractmethod
4
- from typing import Any
5
-
6
- from flask import request
7
- from sapiopylib.rest.User import SapioUser
8
- from sapiopylib.rest.WebhookService import AbstractWebhookHandler
9
- from sapiopylib.rest.pojo.webhook.WebhookResult import SapioWebhookResult
10
-
11
-
12
- class AbstractWebserviceHandler(AbstractWebhookHandler):
13
- """
14
- A base class for constructing "webservice" endpoints on your webhook server. These are endpoints that can be
15
- communicated with by external sources without needing to format the payload JSON in the webhook context format that
16
- webhook handlers expect.
17
-
18
- The entire payload JSON is sent to the run method of this class. It is up to the run method to determine how
19
- this JSON should be parsed. In order to communicate with a Sapio system, a SapioUser object must be able to be
20
- defined using the payload. Functions have been provided for constructing users with various authentication methods.
21
-
22
- Since this extends AbstractWebhookHandler, you can still register endpoints from this class in the same way you
23
- would normal webhook endpoints.
24
- """
25
- def post(self) -> dict[str, Any]:
26
- """
27
- Internal method to be executed to translate incoming requests.
28
- """
29
- # noinspection PyBroadException
30
- try:
31
- return self.run(request.json).to_json()
32
- except Exception:
33
- print('Error occurred while running webservice custom logic. See traceback.', file=sys.stderr)
34
- traceback.print_exc()
35
- return SapioWebhookResult(False, display_text="Error occurred during webservice execution.").to_json()
36
-
37
- @abstractmethod
38
- def run(self, payload: dict[str, Any]) -> SapioWebhookResult:
39
- pass
40
-
41
- def basic_auth(self, url: str, username: str, password: str) -> SapioUser:
42
- """
43
- :param url: The URL of the Sapio system that requests from this user will be sent to.
44
- Must end in /webservice/api
45
- :param username: The username to authenticate requests with.
46
- :param password: The password to authenticate requests with.
47
- :return: A SapioUser that will authenticate requests using basic auth.
48
- """
49
- return SapioUser(url, self.verify_sapio_cert, self.client_timeout_seconds, username=username, password=password)
50
-
51
- def api_token_auth(self, url: str, api_token: str) -> SapioUser:
52
- """
53
- :param url: The URL of the Sapio system that requests from this user will be sent to.
54
- Must end in /webservice/api
55
- :param api_token: The API token to authenticate requests with.
56
- :return: A SapioUser that will authenticate requests using an API token.
57
- """
58
- return SapioUser(url, self.verify_sapio_cert, self.client_timeout_seconds, api_token=api_token)
59
-
60
- def bearer_token_auth(self, url: str, bearer_token: str) -> SapioUser:
61
- """
62
- :param url: The URL of the Sapio system that requests from this user will be sent to.
63
- Must end in /webservice/api
64
- :param bearer_token: The bearer token to authenticate requests with.
65
- :return: A SapioUser that will authenticate requests using a bearer token.
66
- """
67
- return SapioUser(url, self.verify_sapio_cert, self.client_timeout_seconds, bearer_token=bearer_token)
@@ -1,59 +0,0 @@
1
- sapiopycommons/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- sapiopycommons/callbacks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- sapiopycommons/callbacks/callback_util.py,sha256=nb6cXK8yFq96gtG0Z2NiK-qdNaRh88bavUH-ZoBjh18,67953
4
- sapiopycommons/callbacks/field_builder.py,sha256=8n0jcbMgtMUHjie4C1-IkpAuHz4zBxbZtWpr4y0kABU,36868
5
- sapiopycommons/chem/IndigoMolecules.py,sha256=3f-aig3AJkKJhRmhlQ0cI-5G8oeaQk_3foJTDZCvoko,2040
6
- sapiopycommons/chem/Molecules.py,sha256=SQKnqdZnhYj_6HGtEZmE_1DormonRR1-nBAQ__z4gms,11485
7
- sapiopycommons/chem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- sapiopycommons/customreport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- sapiopycommons/customreport/column_builder.py,sha256=0RO53e9rKPZ07C--KcepN6_tpRw_FxF3O9vdG0ilKG8,3014
10
- sapiopycommons/customreport/custom_report_builder.py,sha256=Lsy8DQryb7wC9RmEVVLQ6Q74JiNxU-ywFX-m5zL5CSk,6896
11
- sapiopycommons/customreport/term_builder.py,sha256=oVsr7iFPnug2TrZUCcAMhyps-b62kDodPcBxyQeneUY,16763
12
- sapiopycommons/datatype/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- sapiopycommons/datatype/attachment_util.py,sha256=_l2swuP8noIGAl4bwzBUEhr6YlN_OVZl3-gi1XqFHYA,3364
14
- sapiopycommons/datatype/data_fields.py,sha256=g8Ib6LH8ikNu9AzeVJs8Z2qS8A-cplACeFU7vYguNEY,4063
15
- sapiopycommons/datatype/pseudo_data_types.py,sha256=Fe75Rnq5evyeJM1nC0sLkLGKAC74g2-GEeTdMeId80o,27649
16
- sapiopycommons/eln/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- sapiopycommons/eln/experiment_handler.py,sha256=VJPBQSP_4QmhSGDCRDOb5neOjGM6sZ9krvJEmDkpVV8,69282
18
- sapiopycommons/eln/experiment_report_util.py,sha256=9wWV6oEdKtfn2rI5V0BtmuW9OJlGFd9U07FIf889Gjw,37679
19
- sapiopycommons/eln/plate_designer.py,sha256=FYJfhhNq8hdfuXgDYOYHy6g0m2zNwQXZWF_MTPzElDg,7184
20
- sapiopycommons/files/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
- sapiopycommons/files/complex_data_loader.py,sha256=T39veNhvYl6j_uZjIIJ8Mk5Aa7otR5RB-g8XlAdkksA,1421
22
- sapiopycommons/files/file_bridge.py,sha256=WwCVegk0OGA8eqho8chsOsLlqg1nXctO75zfh-rHF-g,5950
23
- sapiopycommons/files/file_bridge_handler.py,sha256=bt2IfIsxJ4lcJYo_NHvCQ17ZV6C4fSAEa8Zcgixh7B4,14263
24
- sapiopycommons/files/file_data_handler.py,sha256=SCsjODMJIPEBSsahzXUeOM7CfSCmYwPPoGAM6aOfelo,36743
25
- sapiopycommons/files/file_util.py,sha256=wbL3rxcFc-t2mXaPWWkoFWYGopvTcQts9Wf-L5GkhT8,29498
26
- sapiopycommons/files/file_validator.py,sha256=4OvY98ueJWPJdpndwnKv2nqVvLP9S2W7Il_dM0Y0ojo,28709
27
- sapiopycommons/files/file_writer.py,sha256=96Xl8TTT46Krxe_J8rmmlEMtel4nzZB961f5Yqtl1-I,17616
28
- sapiopycommons/flowcyto/flow_cyto.py,sha256=YlkKJR_zEHYRuNW0bnTqlTyZeXs0lOaeSCfG2fnfD7E,3227
29
- sapiopycommons/flowcyto/flowcyto_data.py,sha256=mYKFuLbtpJ-EsQxLGtu4tNHVlygTxKixgJxJqD68F58,2596
30
- sapiopycommons/general/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
- sapiopycommons/general/accession_service.py,sha256=HYgyOsH_UaoRnoury-c2yTW8SeG4OtjLemdpCzoV4R8,13484
32
- sapiopycommons/general/aliases.py,sha256=tdDBNWSGx6s39eHJ3n2kscc4xxW3ZYaUfDftct6FmJE,12910
33
- sapiopycommons/general/audit_log.py,sha256=KQI0AGgN9WLwKqnHE4Tm0xeBCfpVBf8rIQ2HFmnyFGI,8956
34
- sapiopycommons/general/custom_report_util.py,sha256=BGu9Ki0wn3m4Nk-LKM6inDSfe8ULUSG9d-HJJNOTtGc,15653
35
- sapiopycommons/general/exceptions.py,sha256=GY7fe0qOgoy4kQVn_Pn3tdzHsJZyNIpa6VCChg6tzuM,1813
36
- sapiopycommons/general/popup_util.py,sha256=L-4qpTemSZdlD6_6oEsDYIzLOCiZgDK6wC6DqUwzOYA,31925
37
- sapiopycommons/general/sapio_links.py,sha256=o9Z-8y2rz6AI0Cy6tq58ElPge9RBnisGc9NyccbaJxs,2610
38
- sapiopycommons/general/storage_util.py,sha256=ovmK_jN7v09BoX07XxwShpBUC5WYQOM7dbKV_VeLXJU,8892
39
- sapiopycommons/general/time_util.py,sha256=jUAWmQLNcLHZa4UYB4ht_I3d6uoi63VxYdo7T80Ydw0,7458
40
- sapiopycommons/multimodal/multimodal.py,sha256=A1QsC8QTPmgZyPr7KtMbPRedn2Ie4WIErodUvQ9otgU,6724
41
- sapiopycommons/multimodal/multimodal_data.py,sha256=t-0uY4cVgm88uXaSOL4ZeB6zmdHufowXuLFlMk61wFg,15087
42
- sapiopycommons/processtracking/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
- sapiopycommons/processtracking/custom_workflow_handler.py,sha256=0Si5RQ1YFmqmcZWV8jNDKTffix2iZnQJ6b97fn31pbc,23859
44
- sapiopycommons/processtracking/endpoints.py,sha256=w5bziI2xC7450M95rCF8JpRwkoni1kEDibyAux9B12Q,10848
45
- sapiopycommons/recordmodel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
- sapiopycommons/recordmodel/record_handler.py,sha256=Uxjrq6f_cWFbqi7KRLySdOvmQGtbIBrCNyStRewqzx8,64751
47
- sapiopycommons/rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
- sapiopycommons/rules/eln_rule_handler.py,sha256=JYzDA_14D2nLnlqwbpIxVOrfKWzbOS27AYf4TQfGr4Q,10469
49
- sapiopycommons/rules/on_save_rule_handler.py,sha256=Rkqvph20RbNq6m-RF4fbvCP-YfD2CZYBM2iTr3nl0eY,10236
50
- sapiopycommons/sftpconnect/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
- sapiopycommons/sftpconnect/sftp_builder.py,sha256=eKYMiyBc10DNTfbeidQUcfZgFTwhu5ZU-nNJMCK_eos,3014
52
- sapiopycommons/webhook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
- sapiopycommons/webhook/webhook_context.py,sha256=D793uLsb1691SalaPnBUk3rOSxn_hYLhdvkaIxjNXss,1909
54
- sapiopycommons/webhook/webhook_handlers.py,sha256=JTquLBln49L1pJ9txJ4oc4Hpzy9kYtMKs0m4SLaFx78,18363
55
- sapiopycommons/webhook/webservice_handlers.py,sha256=1J56zFI0pWl5MHoNTznvcZumITXgAHJMluj8-2BqYEw,3315
56
- sapiopycommons-2024.11.7a354.dist-info/METADATA,sha256=n4E46KTnsKNHfAy2cPXalibDb5jALEdZVfaveMktPfc,3176
57
- sapiopycommons-2024.11.7a354.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
58
- sapiopycommons-2024.11.7a354.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
59
- sapiopycommons-2024.11.7a354.dist-info/RECORD,,