sapiopycommons 2024.3.19a157__py3-none-any.whl → 2025.1.17a402__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 (52) hide show
  1. sapiopycommons/callbacks/__init__.py +0 -0
  2. sapiopycommons/callbacks/callback_util.py +2041 -0
  3. sapiopycommons/callbacks/field_builder.py +545 -0
  4. sapiopycommons/chem/IndigoMolecules.py +46 -1
  5. sapiopycommons/chem/Molecules.py +100 -21
  6. sapiopycommons/customreport/__init__.py +0 -0
  7. sapiopycommons/customreport/column_builder.py +60 -0
  8. sapiopycommons/customreport/custom_report_builder.py +137 -0
  9. sapiopycommons/customreport/term_builder.py +315 -0
  10. sapiopycommons/datatype/attachment_util.py +14 -15
  11. sapiopycommons/datatype/data_fields.py +61 -0
  12. sapiopycommons/datatype/pseudo_data_types.py +440 -0
  13. sapiopycommons/eln/experiment_handler.py +355 -91
  14. sapiopycommons/eln/experiment_report_util.py +649 -0
  15. sapiopycommons/eln/plate_designer.py +152 -0
  16. sapiopycommons/files/complex_data_loader.py +31 -0
  17. sapiopycommons/files/file_bridge.py +149 -25
  18. sapiopycommons/files/file_bridge_handler.py +555 -0
  19. sapiopycommons/files/file_data_handler.py +633 -0
  20. sapiopycommons/files/file_util.py +263 -163
  21. sapiopycommons/files/file_validator.py +569 -0
  22. sapiopycommons/files/file_writer.py +377 -0
  23. sapiopycommons/flowcyto/flow_cyto.py +77 -0
  24. sapiopycommons/flowcyto/flowcyto_data.py +75 -0
  25. sapiopycommons/general/accession_service.py +375 -0
  26. sapiopycommons/general/aliases.py +250 -15
  27. sapiopycommons/general/audit_log.py +185 -0
  28. sapiopycommons/general/custom_report_util.py +251 -31
  29. sapiopycommons/general/directive_util.py +86 -0
  30. sapiopycommons/general/exceptions.py +69 -7
  31. sapiopycommons/general/popup_util.py +59 -7
  32. sapiopycommons/general/sapio_links.py +50 -0
  33. sapiopycommons/general/storage_util.py +148 -0
  34. sapiopycommons/general/time_util.py +91 -7
  35. sapiopycommons/multimodal/multimodal.py +146 -0
  36. sapiopycommons/multimodal/multimodal_data.py +490 -0
  37. sapiopycommons/processtracking/__init__.py +0 -0
  38. sapiopycommons/processtracking/custom_workflow_handler.py +406 -0
  39. sapiopycommons/processtracking/endpoints.py +192 -0
  40. sapiopycommons/recordmodel/record_handler.py +621 -148
  41. sapiopycommons/rules/eln_rule_handler.py +87 -8
  42. sapiopycommons/rules/on_save_rule_handler.py +87 -12
  43. sapiopycommons/sftpconnect/__init__.py +0 -0
  44. sapiopycommons/sftpconnect/sftp_builder.py +70 -0
  45. sapiopycommons/webhook/webhook_context.py +39 -0
  46. sapiopycommons/webhook/webhook_handlers.py +614 -71
  47. sapiopycommons/webhook/webservice_handlers.py +317 -0
  48. {sapiopycommons-2024.3.19a157.dist-info → sapiopycommons-2025.1.17a402.dist-info}/METADATA +5 -4
  49. sapiopycommons-2025.1.17a402.dist-info/RECORD +60 -0
  50. {sapiopycommons-2024.3.19a157.dist-info → sapiopycommons-2025.1.17a402.dist-info}/WHEEL +1 -1
  51. sapiopycommons-2024.3.19a157.dist-info/RECORD +0 -28
  52. {sapiopycommons-2024.3.19a157.dist-info → sapiopycommons-2025.1.17a402.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,315 @@
1
+ from typing import Iterable
2
+
3
+ from sapiopylib.rest.pojo.CustomReport import RawTermOperation, CompositeTermOperation, RawReportTerm, \
4
+ CompositeReportTerm, AbstractReportTerm, FieldCompareReportTerm
5
+
6
+ from sapiopycommons.general.aliases import DataTypeIdentifier, AliasUtil, FieldIdentifier
7
+
8
+ # Raw term operations, for comparing field values.
9
+ EQ = RawTermOperation.EQUAL_TO_OPERATOR
10
+ NEQ = RawTermOperation.NOT_EQUAL_TO_OPERATOR
11
+ LT = RawTermOperation.LESS_THAN_OPERATOR
12
+ LTE = RawTermOperation.LESS_THAN_OR_EQUAL_OPERATOR
13
+ GT = RawTermOperation.GREATER_THAN_OPERATOR
14
+ GTE = RawTermOperation.GREATER_THAN_OR_EQUAL_OPERATOR
15
+
16
+ # Composite term operations, for comparing two terms.
17
+ AND = CompositeTermOperation.AND_OPERATOR
18
+ OR = CompositeTermOperation.OR_OPERATOR
19
+
20
+ # Forms that field term values can take.
21
+ TermValue = str | int | float | bool | Iterable | None
22
+
23
+
24
+ class TermBuilder:
25
+ """
26
+ A class that allows for the easier constructions of custom report terms.
27
+ """
28
+ data_type: str
29
+
30
+ def __init__(self, data_type: DataTypeIdentifier):
31
+ """
32
+ :param data_type: An object that can be used to identify a data type name. Used as the default data type name
33
+ of the terms created from this TermBuilder.
34
+ """
35
+ self.data_type = AliasUtil.to_data_type_name(data_type)
36
+
37
+ def all_records_term(self, *, data_type: DataTypeIdentifier | None = None) -> RawReportTerm:
38
+ """
39
+ Create a raw report term that captures all records of the given data type.
40
+
41
+ :param data_type: If provided, the data type of this term. If not provided, then the data type that this term
42
+ builder was instantiated with is used.
43
+ :return: A raw report term for "data_type.RecordId >= 0".
44
+ """
45
+ data_type: str = AliasUtil.to_data_type_name(data_type) if data_type else self.data_type
46
+ return RawReportTerm(data_type, "RecordId", GTE, TermBuilder.to_term_val(0))
47
+
48
+ def is_term(self, field: FieldIdentifier, value: TermValue,
49
+ *, data_type: DataTypeIdentifier | None = None, trim: bool = False) -> RawReportTerm:
50
+ """
51
+ Create a raw report term for comparing a field value with an equals operation.
52
+
53
+ :param field: The data field of this term.
54
+ :param value: The value to compare for this term.
55
+ :param data_type: If provided, the data type of this term. If not provided, then the data type that this term
56
+ builder was instantiated with is used.
57
+ :param trim: Whether the string of the given value should be trimmed of trailing and leading whitespace.
58
+ :return: A raw report term for "data_type.field = value".
59
+ """
60
+ data_type: str = AliasUtil.to_data_type_name(data_type) if data_type else self.data_type
61
+ return RawReportTerm(AliasUtil.to_data_type_name(data_type), AliasUtil.to_data_field_name(field), EQ,
62
+ TermBuilder.to_term_val(value), trim)
63
+
64
+ def not_term(self, field: FieldIdentifier, value: TermValue,
65
+ *, data_type: DataTypeIdentifier | None = None, trim: bool = False) -> RawReportTerm:
66
+ """
67
+ Create a raw report term for comparing a field value with a not equals operation.
68
+
69
+ :param field: The data field of this term.
70
+ :param value: The value to compare for this term.
71
+ :param data_type: If provided, the data type of this term. If not provided, then the data type that this term
72
+ builder was instantiated with is used.
73
+ :param trim: Whether the string of the given value should be trimmed of trailing and leading whitespace.
74
+ :return: A raw report term for "data_type.field != value".
75
+ """
76
+ data_type: str = AliasUtil.to_data_type_name(data_type) if data_type else self.data_type
77
+ return RawReportTerm(AliasUtil.to_data_type_name(data_type), AliasUtil.to_data_field_name(field), NEQ,
78
+ TermBuilder.to_term_val(value), trim)
79
+
80
+ def lt_term(self, field: FieldIdentifier, value: TermValue,
81
+ *, data_type: DataTypeIdentifier | None = None, trim: bool = False) -> RawReportTerm:
82
+ """
83
+ Create a raw report term for comparing a field value with a less than operation.
84
+
85
+ :param field: The data field of this term.
86
+ :param value: The value to compare for this term.
87
+ :param data_type: If provided, the data type of this term. If not provided, then the data type that this term
88
+ builder was instantiated with is used.
89
+ :param trim: Whether the string of the given value should be trimmed of trailing and leading whitespace.
90
+ :return: A raw report term for "data_type.field < value".
91
+ """
92
+ data_type: str = AliasUtil.to_data_type_name(data_type) if data_type else self.data_type
93
+ return RawReportTerm(AliasUtil.to_data_type_name(data_type), AliasUtil.to_data_field_name(field), LT,
94
+ TermBuilder.to_term_val(value), trim)
95
+
96
+ def lte_term(self, field: FieldIdentifier, value: TermValue,
97
+ *, data_type: DataTypeIdentifier | None = None, trim: bool = False) -> RawReportTerm:
98
+ """
99
+ Create a raw report term for comparing a field value with a less than or equal to operation.
100
+
101
+ :param field: The data field of this term.
102
+ :param value: The value to compare for this term.
103
+ :param data_type: If provided, the data type of this term. If not provided, then the data type that this term
104
+ builder was instantiated with is used.
105
+ :param trim: Whether the string of the given value should be trimmed of trailing and leading whitespace.
106
+ :return: A raw report term for "data_type.field <= value".
107
+ """
108
+ data_type: str = AliasUtil.to_data_type_name(data_type) if data_type else self.data_type
109
+ return RawReportTerm(AliasUtil.to_data_type_name(data_type), AliasUtil.to_data_field_name(field), LTE,
110
+ TermBuilder.to_term_val(value), trim)
111
+
112
+ def gt_term(self, field: FieldIdentifier, value: TermValue,
113
+ *, data_type: DataTypeIdentifier | None = None, trim: bool = False) -> RawReportTerm:
114
+ """
115
+ Create a raw report term for comparing a field value with a greater than operation.
116
+
117
+ :param field: The data field of this term.
118
+ :param value: The value to compare for this term.
119
+ :param data_type: If provided, the data type of this term. If not provided, then the data type that this term
120
+ builder was instantiated with is used.
121
+ :param trim: Whether the string of the given value should be trimmed of trailing and leading whitespace.
122
+ :return: A raw report term for "data_type.field > value".
123
+ """
124
+ data_type: str = AliasUtil.to_data_type_name(data_type) if data_type else self.data_type
125
+ return RawReportTerm(AliasUtil.to_data_type_name(data_type), AliasUtil.to_data_field_name(field), GT,
126
+ TermBuilder.to_term_val(value), trim)
127
+
128
+ def gte_term(self, field: FieldIdentifier, value: TermValue,
129
+ *, data_type: DataTypeIdentifier | None = None, trim: bool = False) -> RawReportTerm:
130
+ """
131
+ Create a raw report term for comparing a field value with a greater than or equal to operation.
132
+
133
+ :param field: The data field of this term.
134
+ :param value: The value to compare for this term.
135
+ :param data_type: If provided, the data type of this term. If not provided, then the data type that this term
136
+ builder was instantiated with is used.
137
+ :param trim: Whether the string of the given value should be trimmed of trailing and leading whitespace.
138
+ :return: A raw report term for "data_type.field >= value".
139
+ """
140
+ data_type: str = AliasUtil.to_data_type_name(data_type) if data_type else self.data_type
141
+ return RawReportTerm(AliasUtil.to_data_type_name(data_type), AliasUtil.to_data_field_name(field), GTE,
142
+ TermBuilder.to_term_val(value), trim)
143
+
144
+ @staticmethod
145
+ def compare_is_term(data_type_A: DataTypeIdentifier, field_A: FieldIdentifier,
146
+ data_type_B: DataTypeIdentifier, field_B: FieldIdentifier,
147
+ *, trim: bool = False) -> FieldCompareReportTerm:
148
+ """
149
+ Create a field comparison report term for comparing field values between data types with an equals operation.
150
+
151
+ :param data_type_A: The data type for the left side of this term.
152
+ :param field_A: The data field for the left side of this term.
153
+ :param data_type_B: The data type for the right side of this term.
154
+ :param field_B: The data field for the right side of this term.
155
+ :param trim: Whether the field values should be trimmed of trailing and leading whitespace for comparing.
156
+ :return: A field comparison report term for "data_type_A.field_A = data_type_B.field_B".
157
+ """
158
+ return FieldCompareReportTerm(AliasUtil.to_data_type_name(data_type_A), AliasUtil.to_data_field_name(field_A), EQ,
159
+ AliasUtil.to_data_type_name(data_type_B), AliasUtil.to_data_field_name(field_B), trim)
160
+
161
+ @staticmethod
162
+ def compare_not_term(data_type_A: DataTypeIdentifier, field_A: FieldIdentifier,
163
+ data_type_B: DataTypeIdentifier, field_B: FieldIdentifier,
164
+ *, trim: bool = False) -> FieldCompareReportTerm:
165
+ """
166
+ Create a field comparison report term for comparing field values between data types with a not equals operation.
167
+
168
+ :param data_type_A: The data type for the left side of this term.
169
+ :param field_A: The data field for the left side of this term.
170
+ :param data_type_B: The data type for the right side of this term.
171
+ :param field_B: The data field for the right side of this term.
172
+ :param trim: Whether the field values should be trimmed of trailing and leading whitespace for comparing.
173
+ :return: A field comparison report term for "data_type_A.field_A != data_type_B.field_B".
174
+ """
175
+ return FieldCompareReportTerm(AliasUtil.to_data_type_name(data_type_A), AliasUtil.to_data_field_name(field_A), NEQ,
176
+ AliasUtil.to_data_type_name(data_type_B), AliasUtil.to_data_field_name(field_B), trim)
177
+
178
+ @staticmethod
179
+ def compare_lt_term(data_type_A: DataTypeIdentifier, field_A: FieldIdentifier,
180
+ data_type_B: DataTypeIdentifier, field_B: FieldIdentifier,
181
+ *, trim: bool = False) -> FieldCompareReportTerm:
182
+ """
183
+ Create a field comparison report term for comparing field values between data types with a less than operation.
184
+
185
+ :param data_type_A: The data type for the left side of this term.
186
+ :param field_A: The data field for the left side of this term.
187
+ :param data_type_B: The data type for the right side of this term.
188
+ :param field_B: The data field for the right side of this term.
189
+ :param trim: Whether the field values should be trimmed of trailing and leading whitespace for comparing.
190
+ :return: A field comparison report term for "data_type_A.field_A < data_type_B.field_B".
191
+ """
192
+ return FieldCompareReportTerm(AliasUtil.to_data_type_name(data_type_A), AliasUtil.to_data_field_name(field_A), LT,
193
+ AliasUtil.to_data_type_name(data_type_B), AliasUtil.to_data_field_name(field_B), trim)
194
+
195
+ @staticmethod
196
+ def compare_lte_term(data_type_A: DataTypeIdentifier, field_A: FieldIdentifier,
197
+ data_type_B: DataTypeIdentifier, field_B: FieldIdentifier,
198
+ *, trim: bool = False) -> FieldCompareReportTerm:
199
+ """
200
+ Create a field comparison report term for comparing field values between data types with a less than or equal
201
+ to operation.
202
+
203
+ :param data_type_A: The data type for the left side of this term.
204
+ :param field_A: The data field for the left side of this term.
205
+ :param data_type_B: The data type for the right side of this term.
206
+ :param field_B: The data field for the right side of this term.
207
+ :param trim: Whether the field values should be trimmed of trailing and leading whitespace for comparing.
208
+ :return: A field comparison report term for "data_type_A.field_A <= data_type_B.field_B".
209
+ """
210
+ return FieldCompareReportTerm(AliasUtil.to_data_type_name(data_type_A), AliasUtil.to_data_field_name(field_A), LTE,
211
+ AliasUtil.to_data_type_name(data_type_B), AliasUtil.to_data_field_name(field_B), trim)
212
+
213
+ @staticmethod
214
+ def compare_gt_term(data_type_A: DataTypeIdentifier, field_A: FieldIdentifier,
215
+ data_type_B: DataTypeIdentifier, field_B: FieldIdentifier,
216
+ *, trim: bool = False) -> FieldCompareReportTerm:
217
+ """
218
+ Create a field comparison report term for comparing field values between data types with a greater than
219
+ operation.
220
+
221
+ :param data_type_A: The data type for the left side of this term.
222
+ :param field_A: The data field for the left side of this term.
223
+ :param data_type_B: The data type for the right side of this term.
224
+ :param field_B: The data field for the right side of this term.
225
+ :param trim: Whether the field values should be trimmed of trailing and leading whitespace for comparing.
226
+ :return: A field comparison report term for "data_type_A.field_A > data_type_B.field_B".
227
+ """
228
+ return FieldCompareReportTerm(AliasUtil.to_data_type_name(data_type_A), AliasUtil.to_data_field_name(field_A), GT,
229
+ AliasUtil.to_data_type_name(data_type_B), AliasUtil.to_data_field_name(field_B), trim)
230
+
231
+ @staticmethod
232
+ def compare_gte_term(data_type_A: DataTypeIdentifier, field_A: FieldIdentifier,
233
+ data_type_B: DataTypeIdentifier, field_B: FieldIdentifier,
234
+ *, trim: bool = False) -> FieldCompareReportTerm:
235
+ """
236
+ Create a field comparison report term for comparing field values between data types with a greater than or
237
+ equal to operation.
238
+
239
+ :param data_type_A: The data type for the left side of this term.
240
+ :param field_A: The data field for the left side of this term.
241
+ :param data_type_B: The data type for the right side of this term.
242
+ :param field_B: The data field for the right side of this term.
243
+ :param trim: Whether the field values should be trimmed of trailing and leading whitespace for comparing.
244
+ :return: A field comparison report term for "data_type_A.field_A >= data_type_B.field_B".
245
+ """
246
+ return FieldCompareReportTerm(AliasUtil.to_data_type_name(data_type_A), AliasUtil.to_data_field_name(field_A), GTE,
247
+ AliasUtil.to_data_type_name(data_type_B), AliasUtil.to_data_field_name(field_B), trim)
248
+
249
+ @staticmethod
250
+ def or_terms(a: AbstractReportTerm, b: AbstractReportTerm, *, is_negated: bool = False) -> CompositeReportTerm:
251
+ """
252
+ Combine two report terms with an OR operation.
253
+
254
+ :param a: The first term in the operation.
255
+ :param b: The second term in the operation.
256
+ :param is_negated: Whether the returned term should be negated (i.e. turn this into a nor operation).
257
+ :return: A composite report term for "A or B".
258
+ """
259
+ return CompositeReportTerm(a, OR, b, is_negated)
260
+
261
+ @staticmethod
262
+ def and_terms(a: AbstractReportTerm, b: AbstractReportTerm, *, is_negated: bool = False) -> CompositeReportTerm:
263
+ """
264
+ Combine two report terms with an AND operation.
265
+
266
+ :param a: The first term in the operation.
267
+ :param b: The second term in the operation.
268
+ :param is_negated: Whether the returned term should be negated (i.e. turn this into a nand operation).
269
+ :return: A composite report term for "A and B".
270
+ """
271
+ return CompositeReportTerm(a, AND, b, is_negated)
272
+
273
+ @staticmethod
274
+ def xor_terms(a: AbstractReportTerm, b: AbstractReportTerm, *, is_negated: bool = False) -> CompositeReportTerm:
275
+ """
276
+ Combine two report terms with a XOR operation. Note that a XOR operation doesn't actually exist for custom
277
+ reports. This instead constructs a term that is "(A or B) and !(A and B)", which is equivalent to a XOR
278
+ operation.
279
+
280
+ :param a: The first term in the operation.
281
+ :param b: The second term in the operation.
282
+ :param is_negated: Whether the returned term should be negated (i.e. turn this into an xnor operation).
283
+ :return: A composite report term for "A xor B".
284
+ """
285
+ return TermBuilder.and_terms(TermBuilder.or_terms(a, b),
286
+ TermBuilder.and_terms(a, b, is_negated=True),
287
+ is_negated=is_negated)
288
+
289
+ @staticmethod
290
+ def to_term_val(value: TermValue) -> str:
291
+ """
292
+ Convert the given value to be used in a custom report term to a string. Term values may be strings, integers,
293
+ floats, booleans, or lists of values.
294
+
295
+ :param value: A value to be used in a custom report term.
296
+ :return: The provided value formatted as a string that can be used
297
+ """
298
+ # If the given value is already a string, then nothing needs to be done with it.
299
+ if not isinstance(value, str):
300
+ # If the given value is None, then use an empty string for the search instead.
301
+ if value is None:
302
+ value = ""
303
+ # If the given value is an iterable object, then the return value is the contents of that iterable
304
+ # in a comma separated list surrounded by curly braces.
305
+ elif isinstance(value, Iterable):
306
+ # When converting a list of values to a string, values in the list which are already strings should be
307
+ # put in quotation marks so that strings that contain commas do not get split up. All other value
308
+ # types can be simply converted to a string, though.
309
+ def convert_list_value(val: TermValue) -> str:
310
+ return f"'{val}'" if isinstance(val, str) else str(val)
311
+ value = "{" + ",".join([convert_list_value(x) for x in value]) + "}"
312
+ else:
313
+ # Otherwise, the value is simply cast to a string.
314
+ value = str(value)
315
+ return value
@@ -1,42 +1,42 @@
1
1
  import io
2
2
 
3
- from sapiopylib.rest.pojo.DataRecord import DataRecord
4
- from sapiopylib.rest.pojo.webhook.WebhookContext import SapioWebhookContext
5
- from sapiopylib.rest.utils.recordmodel.RecordModelManager import RecordModelManager
3
+ from sapiopylib.rest.DataMgmtService import DataMgmtServer
6
4
  from sapiopylib.rest.utils.recordmodel.RecordModelWrapper import WrappedType
7
5
 
8
- from sapiopycommons.general.aliases import AliasUtil, SapioRecord
6
+ from sapiopycommons.general.aliases import AliasUtil, SapioRecord, UserIdentifier
9
7
  from sapiopycommons.general.exceptions import SapioException
8
+ from sapiopycommons.recordmodel.record_handler import RecordHandler
10
9
 
11
10
 
12
11
  # FR-46064 - Initial port of PyWebhookUtils to sapiopycommons.
13
12
  class AttachmentUtil:
14
13
  @staticmethod
15
- def get_attachment_bytes(context: SapioWebhookContext, attachment: SapioRecord) -> bytes:
14
+ def get_attachment_bytes(context: UserIdentifier, attachment: SapioRecord) -> bytes:
16
15
  """
17
16
  Get the data bytes for the given attachment record. Makes a webservice call to retrieve the data.
18
17
 
19
- :param context: The current webhook context.
18
+ :param context: The current webhook context or a user object to send requests from.
20
19
  :param attachment: The attachment record.
21
20
  :return: The bytes for the attachment's file data.
22
21
  """
23
22
  attachment = AliasUtil.to_data_record(attachment)
23
+ dr_man = DataMgmtServer.get_data_record_manager(AliasUtil.to_sapio_user(context))
24
24
  with io.BytesIO() as data_sink:
25
25
  def consume_data(chunk: bytes):
26
26
  data_sink.write(chunk)
27
- context.data_record_manager.get_attachment_data(attachment, consume_data)
27
+ dr_man.get_attachment_data(attachment, consume_data)
28
28
  data_sink.flush()
29
29
  data_sink.seek(0)
30
30
  file_bytes = data_sink.read()
31
31
  return file_bytes
32
32
 
33
33
  @staticmethod
34
- def set_attachment_bytes(context: SapioWebhookContext, attachment: SapioRecord,
34
+ def set_attachment_bytes(context: UserIdentifier, attachment: SapioRecord,
35
35
  file_name: str, file_bytes: bytes) -> None:
36
36
  """
37
37
  Set the attachment data for a given attachment record. Makes a webservice call to set the data.
38
38
 
39
- :param context: The current webhook context.
39
+ :param context: The current webhook context or a user object to send requests from.
40
40
  :param attachment: The attachment record. Must be an existing data record that is an attachment type.
41
41
  :param file_name: The name of the attachment.
42
42
  :param file_bytes: The bytes of the attachment data.
@@ -45,24 +45,23 @@ class AttachmentUtil:
45
45
  raise SapioException("Provided record cannot have its attachment data set, as it does not exist in the "
46
46
  "system yet.")
47
47
  attachment = AliasUtil.to_data_record(attachment)
48
+ dr_man = DataMgmtServer.get_data_record_manager(AliasUtil.to_sapio_user(context))
48
49
  with io.BytesIO(file_bytes) as stream:
49
- context.data_record_manager.set_attachment_data(attachment, file_name, stream)
50
+ dr_man.set_attachment_data(attachment, file_name, stream)
50
51
 
51
52
  @staticmethod
52
- def create_attachment(context: SapioWebhookContext, file_name: str, file_bytes: bytes,
53
+ def create_attachment(context: UserIdentifier, file_name: str, file_bytes: bytes,
53
54
  wrapper_type: type[WrappedType]) -> WrappedType:
54
55
  """
55
56
  Create an attachment data type and initialize its attachment bytes at the same time.
56
57
  Makes a webservice call to create the attachment record and a second to set its bytes.
57
58
 
58
- :param context: The current webhook context.
59
+ :param context: The current webhook context or a user object to send requests from.
59
60
  :param file_name: The name of the attachment.
60
61
  :param file_bytes: THe bytes of the attachment data.
61
62
  :param wrapper_type: The attachment type to create.
62
63
  :return: A record model for the newly created attachment.
63
64
  """
64
- inst_man = RecordModelManager(context.user).instance_manager
65
- attachment: DataRecord = context.data_record_manager.add_data_record(wrapper_type.DATA_TYPE_NAME)
66
- attachment: WrappedType = inst_man.add_existing_record_of_type(attachment, wrapper_type)
65
+ attachment: WrappedType = RecordHandler(context).create_models(wrapper_type, 1)[0]
67
66
  AttachmentUtil.set_attachment_bytes(context, attachment, file_name, file_bytes)
68
67
  return attachment
@@ -0,0 +1,61 @@
1
+ from sapiopylib.rest.pojo.datatype.FieldDefinition import FieldType
2
+ from sapiopylib.rest.utils.recordmodel.RecordModelWrapper import WrapperField
3
+
4
+
5
+ class SystemFields:
6
+ RECORD_ID__FIELD = WrapperField("RecordId", FieldType.LONG)
7
+ DATA_RECORD_NAME__FIELD = WrapperField("DataRecordName", FieldType.IDENTIFIER)
8
+ CREATED_BY__FIELD = WrapperField("CreatedBy", FieldType.STRING)
9
+ DATE_CREATED__FIELD = WrapperField("DateCreated", FieldType.DATE)
10
+ LAST_MODIFIED_BY__FIELD = WrapperField("VeloxLastModifiedBy", FieldType.STRING)
11
+ LAST_MODIFIED_DATE__FIELD = WrapperField("VeloxLastModifiedDate", FieldType.DATE)
12
+
13
+
14
+ class ProcessQueueItemFields:
15
+ DATA_TYPE_NAME: str = 'ProcessQueueItem'
16
+ ASSIGNED_TO__FIELD = WrapperField('AssignedTo', FieldType.SELECTION)
17
+ DATA_RECORD_ID__FIELD = WrapperField('DataRecordId', FieldType.LONG)
18
+ DATA_TYPE_NAME__FIELD = WrapperField('DataTypeName', FieldType.STRING)
19
+ DURATION_IN_QUEUE__FIELD = WrapperField('DurationInQueue', FieldType.LONG)
20
+ EXPERIMENT__FIELD = WrapperField('Experiment', FieldType.SIDE_LINK)
21
+ LAUNCHED_DATE__FIELD = WrapperField('LaunchedDate', FieldType.DATE)
22
+ PROCESS_HEADER_NAME__FIELD = WrapperField('ProcessHeaderName', FieldType.STRING)
23
+ SCHEDULED_DATE__FIELD = WrapperField('ScheduledDate', FieldType.DATE)
24
+ SHOW_IN_QUEUE__FIELD = WrapperField('ShowInQueue', FieldType.BOOLEAN)
25
+ WORKFLOW_HEADER_NAME__FIELD = WrapperField('WorkflowHeaderName', FieldType.STRING)
26
+
27
+
28
+ class ProcessWorkflowTrackingFields:
29
+ DATA_TYPE_NAME: str = 'ProcessWorkflowTracking'
30
+ ACTIVE_WORKFLOW_ID__FIELD = WrapperField("ActiveWorkflowId", FieldType.LONG)
31
+ BRANCH_LONG_ID__FIELD = WrapperField("BranchLongId", FieldType.LONG)
32
+ END_DATE__FIELD = WrapperField("EndDate", FieldType.DATE)
33
+ END_HOUR__FIELD = WrapperField("EndHour", FieldType.LONG)
34
+ END_MINUTE_TIME__FIELD = WrapperField("EndMinuteTime", FieldType.LONG)
35
+ EXPECTED_QUEUE_TIME__FIELD = WrapperField("ExpectedQueueTime", FieldType.DOUBLE)
36
+ EXPECTED_TAT__FIELD = WrapperField("ExpectedTAT", FieldType.DOUBLE)
37
+ PROCESS_QUEUE_ITEM__FIELD = WrapperField("ProcessQueueItem", FieldType.SIDE_LINK)
38
+ PROCESS_STEP_NUMBER__FIELD = WrapperField("ProcessStepNumber", FieldType.LONG)
39
+ QUEUED_HOURS__FIELD = WrapperField("QueuedHours", FieldType.LONG)
40
+ QUEUED_MINUTES__FIELD = WrapperField("QueuedMinutes", FieldType.LONG)
41
+ QUEUED_TIME__FIELD = WrapperField("QueuedTime", FieldType.DOUBLE)
42
+ QUEUE_START_DATE__FIELD = WrapperField("QueueStartDate", FieldType.DATE)
43
+ QUEUE_START_HOUR__FIELD = WrapperField("QueueStartHour", FieldType.LONG)
44
+ QUEUE_START_MINUTE_TIME__FIELD = WrapperField("QueueStartMinuteTime", FieldType.LONG)
45
+ SAMPLE_RECORD_ID__FIELD = WrapperField("SampleRecordId", FieldType.LONG)
46
+ START_DATE__FIELD = WrapperField("StartDate", FieldType.DATE)
47
+ START_HOUR__FIELD = WrapperField("StartHour", FieldType.LONG)
48
+ START_MINUTE_TIME__FIELD = WrapperField("StartMinuteTime", FieldType.LONG)
49
+ STATUS__FIELD = WrapperField("Status", FieldType.PICKLIST)
50
+ TURN_AROUND_HOURS__FIELD = WrapperField("TurnAroundHours", FieldType.LONG)
51
+ TURN_AROUND_MINUTES__FIELD = WrapperField("TurnAroundMinutes", FieldType.LONG)
52
+ WORKFLOW_END_USER_ID__FIELD = WrapperField("WorkflowEndUserId", FieldType.STRING)
53
+ WORKFLOW_EXPECTED_QUEUE_TIME__FIELD = WrapperField("WorkflowExpectedQueueTime", FieldType.STRING)
54
+ WORKFLOW_EXPECTED_TAT__FIELD = WrapperField("WorkflowExpectedTAT", FieldType.STRING)
55
+ WORKFLOW_EXPECTED_TOTAL_TAT__FIELD = WrapperField("WorkflowExpectedTotalTAT", FieldType.DOUBLE)
56
+ WORKFLOW_ID_NUMBER__FIELD = WrapperField("WorkflowIdNumber", FieldType.LONG)
57
+ WORKFLOW_NAME__FIELD = WrapperField("WorkflowName", FieldType.STRING)
58
+ WORKFLOW_PROCESS_TAT__FIELD = WrapperField("WorkflowProcessTAT", FieldType.DOUBLE)
59
+ WORKFLOW_START_USER_ID__FIELD = WrapperField("WorkflowStartUserId", FieldType.STRING)
60
+ WORKFLOW_TAT__FIELD = WrapperField("WorkflowTAT", FieldType.DOUBLE)
61
+ WORKFLOW_VERSION__FIELD = WrapperField("WorkflowVersion", FieldType.LONG)