sapiopycommons 2024.11.11a364__py3-none-any.whl → 2024.11.18a366__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of sapiopycommons might be problematic. Click here for more details.
- sapiopycommons/callbacks/callback_util.py +532 -83
- sapiopycommons/callbacks/field_builder.py +537 -0
- sapiopycommons/chem/IndigoMolecules.py +2 -0
- sapiopycommons/chem/Molecules.py +77 -18
- sapiopycommons/customreport/__init__.py +0 -0
- sapiopycommons/customreport/column_builder.py +60 -0
- sapiopycommons/customreport/custom_report_builder.py +130 -0
- sapiopycommons/customreport/term_builder.py +299 -0
- sapiopycommons/datatype/attachment_util.py +11 -10
- sapiopycommons/datatype/data_fields.py +61 -0
- sapiopycommons/datatype/pseudo_data_types.py +440 -0
- sapiopycommons/eln/experiment_handler.py +272 -70
- sapiopycommons/eln/experiment_report_util.py +653 -0
- sapiopycommons/files/complex_data_loader.py +5 -4
- sapiopycommons/files/file_bridge.py +31 -24
- sapiopycommons/files/file_bridge_handler.py +340 -0
- sapiopycommons/files/file_data_handler.py +2 -5
- sapiopycommons/files/file_util.py +59 -9
- sapiopycommons/files/file_validator.py +92 -6
- sapiopycommons/files/file_writer.py +44 -15
- sapiopycommons/flowcyto/flow_cyto.py +77 -0
- sapiopycommons/flowcyto/flowcyto_data.py +75 -0
- sapiopycommons/general/accession_service.py +375 -0
- sapiopycommons/general/aliases.py +207 -6
- sapiopycommons/general/audit_log.py +189 -0
- sapiopycommons/general/custom_report_util.py +212 -37
- sapiopycommons/general/exceptions.py +21 -8
- sapiopycommons/general/popup_util.py +21 -0
- sapiopycommons/general/sapio_links.py +50 -0
- sapiopycommons/general/time_util.py +8 -2
- sapiopycommons/multimodal/multimodal.py +146 -0
- sapiopycommons/multimodal/multimodal_data.py +490 -0
- sapiopycommons/processtracking/custom_workflow_handler.py +406 -0
- sapiopycommons/processtracking/endpoints.py +22 -22
- sapiopycommons/recordmodel/record_handler.py +481 -97
- sapiopycommons/rules/eln_rule_handler.py +34 -25
- sapiopycommons/rules/on_save_rule_handler.py +34 -31
- sapiopycommons/sftpconnect/__init__.py +0 -0
- sapiopycommons/sftpconnect/sftp_builder.py +69 -0
- sapiopycommons/webhook/webhook_context.py +39 -0
- sapiopycommons/webhook/webhook_handlers.py +201 -42
- sapiopycommons/webhook/webservice_handlers.py +67 -0
- {sapiopycommons-2024.11.11a364.dist-info → sapiopycommons-2024.11.18a366.dist-info}/METADATA +5 -2
- sapiopycommons-2024.11.18a366.dist-info/RECORD +59 -0
- {sapiopycommons-2024.11.11a364.dist-info → sapiopycommons-2024.11.18a366.dist-info}/WHEEL +1 -1
- sapiopycommons-2024.11.11a364.dist-info/RECORD +0 -38
- {sapiopycommons-2024.11.11a364.dist-info → sapiopycommons-2024.11.18a366.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from weakref import WeakValueDictionary
|
|
4
|
+
|
|
5
|
+
from sapiopylib.rest.User import SapioUser
|
|
1
6
|
from sapiopylib.rest.pojo.DataRecord import DataRecord
|
|
2
|
-
from sapiopylib.rest.pojo.
|
|
7
|
+
from sapiopylib.rest.pojo.eln.SapioELNEnums import ElnBaseDataType
|
|
3
8
|
from sapiopylib.rest.pojo.webhook.WebhookContext import SapioWebhookContext
|
|
4
9
|
from sapiopylib.rest.utils.recordmodel.RecordModelManager import RecordModelManager, RecordModelInstanceManager
|
|
5
10
|
from sapiopylib.rest.utils.recordmodel.RecordModelWrapper import WrappedType
|
|
6
11
|
|
|
7
|
-
from sapiopycommons.general.aliases import FieldMap
|
|
12
|
+
from sapiopycommons.general.aliases import FieldMap, AliasUtil, DataTypeIdentifier
|
|
8
13
|
from sapiopycommons.general.exceptions import SapioException
|
|
9
14
|
|
|
10
15
|
|
|
@@ -12,7 +17,6 @@ from sapiopycommons.general.exceptions import SapioException
|
|
|
12
17
|
class ElnRuleHandler:
|
|
13
18
|
"""
|
|
14
19
|
A class which helps with the parsing and navigation of the ELN rule result map of a webhook context.
|
|
15
|
-
TODO: Add functionality around the VeloxRuleType of the rule results.
|
|
16
20
|
"""
|
|
17
21
|
__context: SapioWebhookContext
|
|
18
22
|
"""The context that this handler is working from."""
|
|
@@ -34,7 +38,25 @@ class ElnRuleHandler:
|
|
|
34
38
|
"""A mapping of entry name to the lists of field maps for that entry, each grouping of field maps being mapped by
|
|
35
39
|
its data type."""
|
|
36
40
|
|
|
41
|
+
__instances: WeakValueDictionary[SapioUser, ElnRuleHandler] = WeakValueDictionary()
|
|
42
|
+
__initialized: bool
|
|
43
|
+
|
|
44
|
+
def __new__(cls, context: SapioWebhookContext):
|
|
45
|
+
if context.velox_eln_rule_result_map is None:
|
|
46
|
+
raise SapioException("No Velox ELN rule result map in context for ElnRuleHandler to parse.")
|
|
47
|
+
user = context if isinstance(context, SapioUser) else context.user
|
|
48
|
+
obj = cls.__instances.get(user)
|
|
49
|
+
if not obj:
|
|
50
|
+
obj = object.__new__(cls)
|
|
51
|
+
obj.__initialized = False
|
|
52
|
+
cls.__instances[user] = obj
|
|
53
|
+
return obj
|
|
54
|
+
|
|
37
55
|
def __init__(self, context: SapioWebhookContext):
|
|
56
|
+
if self.__initialized:
|
|
57
|
+
return
|
|
58
|
+
self.__initialized = True
|
|
59
|
+
|
|
38
60
|
if context.velox_eln_rule_result_map is None:
|
|
39
61
|
raise SapioException("No Velox ELN rule result map in context for ElnRuleHandler to parse.")
|
|
40
62
|
self.__context = context
|
|
@@ -64,13 +86,8 @@ class ElnRuleHandler:
|
|
|
64
86
|
# Get the data type of this record. If this is an ELN type, ignore the digits.
|
|
65
87
|
data_type: str = record.data_type_name
|
|
66
88
|
# PR-46331: Ensure that all ELN types are converted to their base data type name.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
data_type = "ELNExperiment"
|
|
70
|
-
elif data_type.startswith("ELNExperimentDetail_"):
|
|
71
|
-
data_type = "ELNExperimentDetail"
|
|
72
|
-
elif data_type.startswith("ELNSampleDetail_"):
|
|
73
|
-
data_type = "ELNSampleDetail"
|
|
89
|
+
if ElnBaseDataType.is_eln_type(data_type):
|
|
90
|
+
data_type = ElnBaseDataType.get_base_type(data_type).data_type_name
|
|
74
91
|
# Update the list of records of this type that exist so far globally.
|
|
75
92
|
self.__records.setdefault(data_type, set()).add(record)
|
|
76
93
|
# Do the same for the list of records of this type for this specific entry.
|
|
@@ -85,19 +102,9 @@ class ElnRuleHandler:
|
|
|
85
102
|
entry_dict: dict[str, dict[int, FieldMap]] = {}
|
|
86
103
|
for record_result in entry_results:
|
|
87
104
|
for result in record_result.velox_type_rule_field_map_result_list:
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if isinstance(velox_type, dict):
|
|
92
|
-
velox_type: VeloxRuleType = VeloxRuleParser.parse_velox_rule_type(velox_type)
|
|
93
|
-
data_type: str = velox_type.data_type_name
|
|
94
|
-
# TODO: Use ElnBaseDataType.is_eln_type when it is no longer bugged in sapiopylib.
|
|
95
|
-
if data_type.startswith("ELNExperiment_"):
|
|
96
|
-
data_type = "ELNExperiment"
|
|
97
|
-
elif data_type.startswith("ELNExperimentDetail_"):
|
|
98
|
-
data_type = "ELNExperimentDetail"
|
|
99
|
-
elif data_type.startswith("ELNSampleDetail_"):
|
|
100
|
-
data_type = "ELNSampleDetail"
|
|
105
|
+
data_type: str = result.velox_type_pojo.data_type_name
|
|
106
|
+
if ElnBaseDataType.is_eln_type(data_type):
|
|
107
|
+
data_type = ElnBaseDataType.get_base_type(data_type).data_type_name
|
|
101
108
|
for field_map in result.field_map_list:
|
|
102
109
|
rec_id: int = field_map.get("RecordId")
|
|
103
110
|
self.__field_maps.setdefault(data_type, {}).update({rec_id: field_map})
|
|
@@ -118,7 +125,7 @@ class ElnRuleHandler:
|
|
|
118
125
|
"""
|
|
119
126
|
return list(self.__entry_to_field_maps.keys())
|
|
120
127
|
|
|
121
|
-
def get_records(self, data_type:
|
|
128
|
+
def get_records(self, data_type: DataTypeIdentifier, entry: str | None = None) -> list[DataRecord]:
|
|
122
129
|
"""
|
|
123
130
|
Get records from the cached context with the given data type. Capable of being filtered to searching within
|
|
124
131
|
the context of an entry name. If the given data type or entry does not exist in the context,
|
|
@@ -129,11 +136,12 @@ class ElnRuleHandler:
|
|
|
129
136
|
type from every entry. If an entry is provided, but it does not exist in the context, returns an empty list.
|
|
130
137
|
:return: The records from the context that match the input parameters.
|
|
131
138
|
"""
|
|
139
|
+
data_type: str = AliasUtil.to_data_type_name(data_type)
|
|
132
140
|
records: dict[str, set[DataRecord]] = self.__entry_to_records.get(entry, {}) if entry else self.__records
|
|
133
141
|
return list(records.get(data_type, []))
|
|
134
142
|
|
|
135
143
|
# FR-46701: Add functions to the rule handlers for accessing the field maps of inaccessible records in the context.
|
|
136
|
-
def get_field_maps(self, data_type:
|
|
144
|
+
def get_field_maps(self, data_type: DataTypeIdentifier, entry: str | None = None) -> list[FieldMap]:
|
|
137
145
|
"""
|
|
138
146
|
Get field maps from the cached context with the given data type. Capable of being filtered to searching within
|
|
139
147
|
the context of an entry name. If the given data type or entry does not exist in the context,
|
|
@@ -149,6 +157,7 @@ class ElnRuleHandler:
|
|
|
149
157
|
list.
|
|
150
158
|
:return: The field maps from the context that match the input parameters.
|
|
151
159
|
"""
|
|
160
|
+
data_type: str = AliasUtil.to_data_type_name(data_type)
|
|
152
161
|
field_maps: dict[str, dict[int, FieldMap]] = self.__entry_to_field_maps.get(entry, {}) if entry else self.__field_maps
|
|
153
162
|
return list(field_maps.get(data_type, {}).values())
|
|
154
163
|
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from weakref import WeakValueDictionary
|
|
4
|
+
|
|
5
|
+
from sapiopylib.rest.User import SapioUser
|
|
1
6
|
from sapiopylib.rest.pojo.DataRecord import DataRecord
|
|
2
|
-
from sapiopylib.rest.pojo.
|
|
7
|
+
from sapiopylib.rest.pojo.eln.SapioELNEnums import ElnBaseDataType
|
|
3
8
|
from sapiopylib.rest.pojo.webhook.WebhookContext import SapioWebhookContext
|
|
4
9
|
from sapiopylib.rest.utils.recordmodel.RecordModelManager import RecordModelManager, RecordModelInstanceManager
|
|
5
10
|
from sapiopylib.rest.utils.recordmodel.RecordModelWrapper import WrappedType
|
|
6
11
|
|
|
7
|
-
from sapiopycommons.general.aliases import FieldMap
|
|
12
|
+
from sapiopycommons.general.aliases import FieldMap, DataTypeIdentifier, AliasUtil
|
|
8
13
|
from sapiopycommons.general.exceptions import SapioException
|
|
9
14
|
|
|
10
15
|
|
|
@@ -12,7 +17,6 @@ from sapiopycommons.general.exceptions import SapioException
|
|
|
12
17
|
class OnSaveRuleHandler:
|
|
13
18
|
"""
|
|
14
19
|
A class which helps with the parsing and navigation of the on save rule result map of a webhook context.
|
|
15
|
-
TODO: Add functionality around the VeloxRuleType of the rule results.
|
|
16
20
|
"""
|
|
17
21
|
__context: SapioWebhookContext
|
|
18
22
|
"""The context that this handler is working from."""
|
|
@@ -34,7 +38,25 @@ class OnSaveRuleHandler:
|
|
|
34
38
|
"""A mapping of record IDs of records in the context.data_record_list to the field maps related to that
|
|
35
39
|
record, each grouping of field maps being mapped by its data type."""
|
|
36
40
|
|
|
41
|
+
__instances: WeakValueDictionary[SapioUser, OnSaveRuleHandler] = WeakValueDictionary()
|
|
42
|
+
__initialized: bool
|
|
43
|
+
|
|
44
|
+
def __new__(cls, context: SapioWebhookContext):
|
|
45
|
+
if context.velox_on_save_result_map is None:
|
|
46
|
+
raise SapioException("No Velox on save rule result map in context for OnSaveRuleHandler to parse.")
|
|
47
|
+
user = context if isinstance(context, SapioUser) else context.user
|
|
48
|
+
obj = cls.__instances.get(user)
|
|
49
|
+
if not obj:
|
|
50
|
+
obj = object.__new__(cls)
|
|
51
|
+
obj.__initialized = False
|
|
52
|
+
cls.__instances[user] = obj
|
|
53
|
+
return obj
|
|
54
|
+
|
|
37
55
|
def __init__(self, context: SapioWebhookContext):
|
|
56
|
+
if self.__initialized:
|
|
57
|
+
return
|
|
58
|
+
self.__initialized = True
|
|
59
|
+
|
|
38
60
|
if context.velox_on_save_result_map is None:
|
|
39
61
|
raise SapioException("No Velox on save rule result map in context for OnSaveRuleHandler to parse.")
|
|
40
62
|
self.__context = context
|
|
@@ -51,9 +73,6 @@ class OnSaveRuleHandler:
|
|
|
51
73
|
self.__base_id_to_records = {}
|
|
52
74
|
# Each record ID in the context has a list of results for that record.
|
|
53
75
|
for record_id, rule_results in self.__context.velox_on_save_result_map.items():
|
|
54
|
-
# TODO: Record IDs are currently being stored in the map as strings instead of ints. This can be removed
|
|
55
|
-
# once sapiopylib is fixed.
|
|
56
|
-
record_id = int(record_id)
|
|
57
76
|
# Keep track of the records for this specific record ID.
|
|
58
77
|
id_dict: dict[str, set[DataRecord]] = {}
|
|
59
78
|
# The list of results for a record consist of a list of data records and a VeloxType that specifies
|
|
@@ -64,13 +83,8 @@ class OnSaveRuleHandler:
|
|
|
64
83
|
# Get the data type of this record. If this is an ELN type, ignore the digits.
|
|
65
84
|
data_type: str = record.data_type_name
|
|
66
85
|
# PR-46331: Ensure that all ELN types are converted to their base data type name.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
data_type = "ELNExperiment"
|
|
70
|
-
elif data_type.startswith("ELNExperimentDetail_"):
|
|
71
|
-
data_type = "ELNExperimentDetail"
|
|
72
|
-
elif data_type.startswith("ELNSampleDetail_"):
|
|
73
|
-
data_type = "ELNSampleDetail"
|
|
86
|
+
if ElnBaseDataType.is_eln_type(data_type):
|
|
87
|
+
data_type = ElnBaseDataType.get_base_type(data_type).data_type_name
|
|
74
88
|
# Update the list of records of this type that exist so far globally.
|
|
75
89
|
self.__records.setdefault(data_type, set()).add(record)
|
|
76
90
|
# Do the same for the list of records of this type that relate to this record ID.
|
|
@@ -82,24 +96,11 @@ class OnSaveRuleHandler:
|
|
|
82
96
|
self.__base_id_to_field_maps = {}
|
|
83
97
|
# Repeat the same thing for the field map results.
|
|
84
98
|
for record_id, rule_results in self.__context.velox_on_save_field_map_result_map.items():
|
|
85
|
-
# TODO: Record IDs are currently being stored in the map as strings instead of ints. This can be removed
|
|
86
|
-
# once sapiopylib is fixed.
|
|
87
|
-
record_id = int(record_id)
|
|
88
99
|
id_dict: dict[str, dict[int, FieldMap]] = {}
|
|
89
100
|
for record_result in rule_results:
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if isinstance(velox_type, dict):
|
|
94
|
-
velox_type: VeloxRuleType = VeloxRuleParser.parse_velox_rule_type(velox_type)
|
|
95
|
-
data_type: str = velox_type.data_type_name
|
|
96
|
-
# TODO: Use ElnBaseDataType.is_eln_type when it is no longer bugged in sapiopylib.
|
|
97
|
-
if data_type.startswith("ELNExperiment_"):
|
|
98
|
-
data_type = "ELNExperiment"
|
|
99
|
-
elif data_type.startswith("ELNExperimentDetail_"):
|
|
100
|
-
data_type = "ELNExperimentDetail"
|
|
101
|
-
elif data_type.startswith("ELNSampleDetail_"):
|
|
102
|
-
data_type = "ELNSampleDetail"
|
|
101
|
+
data_type: str = record_result.velox_type_pojo.data_type_name
|
|
102
|
+
if ElnBaseDataType.is_eln_type(data_type):
|
|
103
|
+
data_type = ElnBaseDataType.get_base_type(data_type).data_type_name
|
|
103
104
|
for field_map in record_result.field_map_list:
|
|
104
105
|
rec_id: int = field_map.get("RecordId")
|
|
105
106
|
self.__field_maps.setdefault(data_type, {}).update({rec_id: field_map})
|
|
@@ -120,7 +121,7 @@ class OnSaveRuleHandler:
|
|
|
120
121
|
"""
|
|
121
122
|
return list(self.__base_id_to_field_maps.keys())
|
|
122
123
|
|
|
123
|
-
def get_records(self, data_type:
|
|
124
|
+
def get_records(self, data_type: DataTypeIdentifier, record_id: int | None = None) -> list[DataRecord]:
|
|
124
125
|
"""
|
|
125
126
|
Get records from the cached context with the given data type. Capable of being filtered to searching within
|
|
126
127
|
the context of a record ID. If the given data type or record ID does not exist in the context,
|
|
@@ -131,11 +132,12 @@ class OnSaveRuleHandler:
|
|
|
131
132
|
data type from every ID. If an ID is provided, but it does not exist in the context, returns an empty list.
|
|
132
133
|
:return: The records from the context that match the input parameters.
|
|
133
134
|
"""
|
|
135
|
+
data_type: str = AliasUtil.to_data_type_name(data_type)
|
|
134
136
|
records: dict[str, set[DataRecord]] = self.__base_id_to_records.get(record_id, {}) if record_id else self.__records
|
|
135
137
|
return list(records.get(data_type, []))
|
|
136
138
|
|
|
137
139
|
# FR-46701: Add functions to the rule handlers for accessing the field maps of inaccessible records in the context.
|
|
138
|
-
def get_field_maps(self, data_type:
|
|
140
|
+
def get_field_maps(self, data_type: DataTypeIdentifier, record_id: int | None = None) -> list[FieldMap]:
|
|
139
141
|
"""
|
|
140
142
|
Get field maps from the cached context with the given data type. Capable of being filtered to searching within
|
|
141
143
|
the context of a record ID. If the given data type or record ID does not exist in the context,
|
|
@@ -151,6 +153,7 @@ class OnSaveRuleHandler:
|
|
|
151
153
|
list.
|
|
152
154
|
:return: The field maps from the context that match the input parameters.
|
|
153
155
|
"""
|
|
156
|
+
data_type: str = AliasUtil.to_data_type_name(data_type)
|
|
154
157
|
field_maps: dict[str, dict[int, FieldMap]] = self.__base_id_to_field_maps.get(record_id, {}) if record_id else self.__field_maps
|
|
155
158
|
return list(field_maps.get(data_type, {}).values())
|
|
156
159
|
|
|
File without changes
|
|
@@ -0,0 +1,69 @@
|
|
|
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.")
|
|
@@ -0,0 +1,39 @@
|
|
|
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"]
|