sapiopycommons 2024.8.27a310__py3-none-any.whl → 2024.8.28a313__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 +69 -407
- sapiopycommons/chem/IndigoMolecules.py +0 -1
- sapiopycommons/chem/Molecules.py +0 -1
- sapiopycommons/datatype/attachment_util.py +10 -11
- sapiopycommons/eln/experiment_handler.py +48 -209
- sapiopycommons/files/complex_data_loader.py +4 -5
- sapiopycommons/files/file_bridge.py +24 -31
- sapiopycommons/files/file_data_handler.py +5 -2
- sapiopycommons/files/file_util.py +10 -50
- sapiopycommons/files/file_validator.py +6 -92
- sapiopycommons/files/file_writer.py +15 -44
- sapiopycommons/general/aliases.py +3 -147
- sapiopycommons/general/custom_report_util.py +37 -211
- sapiopycommons/general/popup_util.py +0 -17
- sapiopycommons/general/time_util.py +0 -40
- sapiopycommons/processtracking/endpoints.py +22 -22
- sapiopycommons/recordmodel/record_handler.py +97 -481
- sapiopycommons/rules/eln_rule_handler.py +25 -34
- sapiopycommons/rules/on_save_rule_handler.py +31 -34
- sapiopycommons/webhook/webhook_handlers.py +26 -147
- {sapiopycommons-2024.8.27a310.dist-info → sapiopycommons-2024.8.28a313.dist-info}/METADATA +2 -4
- sapiopycommons-2024.8.28a313.dist-info/RECORD +38 -0
- sapiopycommons/customreport/__init__.py +0 -0
- sapiopycommons/customreport/column_builder.py +0 -60
- sapiopycommons/customreport/custom_report_builder.py +0 -125
- sapiopycommons/customreport/term_builder.py +0 -299
- sapiopycommons/eln/experiment_report_util.py +0 -118
- sapiopycommons/files/file_bridge_handler.py +0 -340
- sapiopycommons/general/accession_service.py +0 -375
- sapiopycommons/general/audit_log.py +0 -196
- sapiopycommons/general/sapio_links.py +0 -50
- sapiopycommons/multimodal/multimodal.py +0 -146
- sapiopycommons/multimodal/multimodal_data.py +0 -486
- sapiopycommons/webhook/webservice_handlers.py +0 -67
- sapiopycommons-2024.8.27a310.dist-info/RECORD +0 -50
- {sapiopycommons-2024.8.27a310.dist-info → sapiopycommons-2024.8.28a313.dist-info}/WHEEL +0 -0
- {sapiopycommons-2024.8.27a310.dist-info → sapiopycommons-2024.8.28a313.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from weakref import WeakValueDictionary
|
|
4
|
-
|
|
5
|
-
from sapiopylib.rest.User import SapioUser
|
|
6
1
|
from sapiopylib.rest.pojo.DataRecord import DataRecord
|
|
7
|
-
from sapiopylib.rest.pojo.
|
|
2
|
+
from sapiopylib.rest.pojo.webhook.VeloxRules import VeloxRuleType, VeloxRuleParser
|
|
8
3
|
from sapiopylib.rest.pojo.webhook.WebhookContext import SapioWebhookContext
|
|
9
4
|
from sapiopylib.rest.utils.recordmodel.RecordModelManager import RecordModelManager, RecordModelInstanceManager
|
|
10
5
|
from sapiopylib.rest.utils.recordmodel.RecordModelWrapper import WrappedType
|
|
11
6
|
|
|
12
|
-
from sapiopycommons.general.aliases import FieldMap
|
|
7
|
+
from sapiopycommons.general.aliases import FieldMap
|
|
13
8
|
from sapiopycommons.general.exceptions import SapioException
|
|
14
9
|
|
|
15
10
|
|
|
@@ -17,6 +12,7 @@ from sapiopycommons.general.exceptions import SapioException
|
|
|
17
12
|
class ElnRuleHandler:
|
|
18
13
|
"""
|
|
19
14
|
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.
|
|
20
16
|
"""
|
|
21
17
|
__context: SapioWebhookContext
|
|
22
18
|
"""The context that this handler is working from."""
|
|
@@ -38,25 +34,7 @@ class ElnRuleHandler:
|
|
|
38
34
|
"""A mapping of entry name to the lists of field maps for that entry, each grouping of field maps being mapped by
|
|
39
35
|
its data type."""
|
|
40
36
|
|
|
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
|
-
|
|
55
37
|
def __init__(self, context: SapioWebhookContext):
|
|
56
|
-
if self.__initialized:
|
|
57
|
-
return
|
|
58
|
-
self.__initialized = True
|
|
59
|
-
|
|
60
38
|
if context.velox_eln_rule_result_map is None:
|
|
61
39
|
raise SapioException("No Velox ELN rule result map in context for ElnRuleHandler to parse.")
|
|
62
40
|
self.__context = context
|
|
@@ -86,8 +64,13 @@ class ElnRuleHandler:
|
|
|
86
64
|
# Get the data type of this record. If this is an ELN type, ignore the digits.
|
|
87
65
|
data_type: str = record.data_type_name
|
|
88
66
|
# PR-46331: Ensure that all ELN types are converted to their base data type name.
|
|
89
|
-
|
|
90
|
-
|
|
67
|
+
# TODO: Use ElnBaseDataType.is_eln_type when it is no longer bugged in sapiopylib.
|
|
68
|
+
if data_type.startswith("ELNExperiment_"):
|
|
69
|
+
data_type = "ELNExperiment"
|
|
70
|
+
elif data_type.startswith("ELNExperimentDetail_"):
|
|
71
|
+
data_type = "ELNExperimentDetail"
|
|
72
|
+
elif data_type.startswith("ELNSampleDetail_"):
|
|
73
|
+
data_type = "ELNSampleDetail"
|
|
91
74
|
# Update the list of records of this type that exist so far globally.
|
|
92
75
|
self.__records.setdefault(data_type, set()).add(record)
|
|
93
76
|
# Do the same for the list of records of this type for this specific entry.
|
|
@@ -102,9 +85,19 @@ class ElnRuleHandler:
|
|
|
102
85
|
entry_dict: dict[str, dict[int, FieldMap]] = {}
|
|
103
86
|
for record_result in entry_results:
|
|
104
87
|
for result in record_result.velox_type_rule_field_map_result_list:
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
88
|
+
# TODO: sapiopylib currently has a bug where this velox_type_pojo variable is stored as a dict instead
|
|
89
|
+
# of as the intended VeloxRuleType object. Parse that dict as a VeloxRuleType before use.
|
|
90
|
+
velox_type: VeloxRuleType | dict = result.velox_type_pojo
|
|
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"
|
|
108
101
|
for field_map in result.field_map_list:
|
|
109
102
|
rec_id: int = field_map.get("RecordId")
|
|
110
103
|
self.__field_maps.setdefault(data_type, {}).update({rec_id: field_map})
|
|
@@ -125,7 +118,7 @@ class ElnRuleHandler:
|
|
|
125
118
|
"""
|
|
126
119
|
return list(self.__entry_to_field_maps.keys())
|
|
127
120
|
|
|
128
|
-
def get_records(self, data_type:
|
|
121
|
+
def get_records(self, data_type: str, entry: str | None = None) -> list[DataRecord]:
|
|
129
122
|
"""
|
|
130
123
|
Get records from the cached context with the given data type. Capable of being filtered to searching within
|
|
131
124
|
the context of an entry name. If the given data type or entry does not exist in the context,
|
|
@@ -136,12 +129,11 @@ class ElnRuleHandler:
|
|
|
136
129
|
type from every entry. If an entry is provided, but it does not exist in the context, returns an empty list.
|
|
137
130
|
:return: The records from the context that match the input parameters.
|
|
138
131
|
"""
|
|
139
|
-
data_type: str = AliasUtil.to_data_type_name(data_type)
|
|
140
132
|
records: dict[str, set[DataRecord]] = self.__entry_to_records.get(entry, {}) if entry else self.__records
|
|
141
133
|
return list(records.get(data_type, []))
|
|
142
134
|
|
|
143
135
|
# FR-46701: Add functions to the rule handlers for accessing the field maps of inaccessible records in the context.
|
|
144
|
-
def get_field_maps(self, data_type:
|
|
136
|
+
def get_field_maps(self, data_type: str, entry: str | None = None) -> list[FieldMap]:
|
|
145
137
|
"""
|
|
146
138
|
Get field maps from the cached context with the given data type. Capable of being filtered to searching within
|
|
147
139
|
the context of an entry name. If the given data type or entry does not exist in the context,
|
|
@@ -157,7 +149,6 @@ class ElnRuleHandler:
|
|
|
157
149
|
list.
|
|
158
150
|
:return: The field maps from the context that match the input parameters.
|
|
159
151
|
"""
|
|
160
|
-
data_type: str = AliasUtil.to_data_type_name(data_type)
|
|
161
152
|
field_maps: dict[str, dict[int, FieldMap]] = self.__entry_to_field_maps.get(entry, {}) if entry else self.__field_maps
|
|
162
153
|
return list(field_maps.get(data_type, {}).values())
|
|
163
154
|
|
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from weakref import WeakValueDictionary
|
|
4
|
-
|
|
5
|
-
from sapiopylib.rest.User import SapioUser
|
|
6
1
|
from sapiopylib.rest.pojo.DataRecord import DataRecord
|
|
7
|
-
from sapiopylib.rest.pojo.
|
|
2
|
+
from sapiopylib.rest.pojo.webhook.VeloxRules import VeloxRuleType, VeloxRuleParser
|
|
8
3
|
from sapiopylib.rest.pojo.webhook.WebhookContext import SapioWebhookContext
|
|
9
4
|
from sapiopylib.rest.utils.recordmodel.RecordModelManager import RecordModelManager, RecordModelInstanceManager
|
|
10
5
|
from sapiopylib.rest.utils.recordmodel.RecordModelWrapper import WrappedType
|
|
11
6
|
|
|
12
|
-
from sapiopycommons.general.aliases import FieldMap
|
|
7
|
+
from sapiopycommons.general.aliases import FieldMap
|
|
13
8
|
from sapiopycommons.general.exceptions import SapioException
|
|
14
9
|
|
|
15
10
|
|
|
@@ -17,6 +12,7 @@ from sapiopycommons.general.exceptions import SapioException
|
|
|
17
12
|
class OnSaveRuleHandler:
|
|
18
13
|
"""
|
|
19
14
|
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.
|
|
20
16
|
"""
|
|
21
17
|
__context: SapioWebhookContext
|
|
22
18
|
"""The context that this handler is working from."""
|
|
@@ -38,25 +34,7 @@ class OnSaveRuleHandler:
|
|
|
38
34
|
"""A mapping of record IDs of records in the context.data_record_list to the field maps related to that
|
|
39
35
|
record, each grouping of field maps being mapped by its data type."""
|
|
40
36
|
|
|
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
|
-
|
|
55
37
|
def __init__(self, context: SapioWebhookContext):
|
|
56
|
-
if self.__initialized:
|
|
57
|
-
return
|
|
58
|
-
self.__initialized = True
|
|
59
|
-
|
|
60
38
|
if context.velox_on_save_result_map is None:
|
|
61
39
|
raise SapioException("No Velox on save rule result map in context for OnSaveRuleHandler to parse.")
|
|
62
40
|
self.__context = context
|
|
@@ -73,6 +51,9 @@ class OnSaveRuleHandler:
|
|
|
73
51
|
self.__base_id_to_records = {}
|
|
74
52
|
# Each record ID in the context has a list of results for that record.
|
|
75
53
|
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)
|
|
76
57
|
# Keep track of the records for this specific record ID.
|
|
77
58
|
id_dict: dict[str, set[DataRecord]] = {}
|
|
78
59
|
# The list of results for a record consist of a list of data records and a VeloxType that specifies
|
|
@@ -83,8 +64,13 @@ class OnSaveRuleHandler:
|
|
|
83
64
|
# Get the data type of this record. If this is an ELN type, ignore the digits.
|
|
84
65
|
data_type: str = record.data_type_name
|
|
85
66
|
# PR-46331: Ensure that all ELN types are converted to their base data type name.
|
|
86
|
-
|
|
87
|
-
|
|
67
|
+
# TODO: Use ElnBaseDataType.is_eln_type when it is no longer bugged in sapiopylib.
|
|
68
|
+
if data_type.startswith("ELNExperiment_"):
|
|
69
|
+
data_type = "ELNExperiment"
|
|
70
|
+
elif data_type.startswith("ELNExperimentDetail_"):
|
|
71
|
+
data_type = "ELNExperimentDetail"
|
|
72
|
+
elif data_type.startswith("ELNSampleDetail_"):
|
|
73
|
+
data_type = "ELNSampleDetail"
|
|
88
74
|
# Update the list of records of this type that exist so far globally.
|
|
89
75
|
self.__records.setdefault(data_type, set()).add(record)
|
|
90
76
|
# Do the same for the list of records of this type that relate to this record ID.
|
|
@@ -96,11 +82,24 @@ class OnSaveRuleHandler:
|
|
|
96
82
|
self.__base_id_to_field_maps = {}
|
|
97
83
|
# Repeat the same thing for the field map results.
|
|
98
84
|
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)
|
|
99
88
|
id_dict: dict[str, dict[int, FieldMap]] = {}
|
|
100
89
|
for record_result in rule_results:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
90
|
+
# TODO: sapiopylib currently has a bug where this velox_type_pojo variable is stored as a dict instead
|
|
91
|
+
# of as the intended VeloxRuleType object. Parse that dict as a VeloxRuleType before use.
|
|
92
|
+
velox_type: VeloxRuleType | dict = record_result.velox_type_pojo
|
|
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"
|
|
104
103
|
for field_map in record_result.field_map_list:
|
|
105
104
|
rec_id: int = field_map.get("RecordId")
|
|
106
105
|
self.__field_maps.setdefault(data_type, {}).update({rec_id: field_map})
|
|
@@ -121,7 +120,7 @@ class OnSaveRuleHandler:
|
|
|
121
120
|
"""
|
|
122
121
|
return list(self.__base_id_to_field_maps.keys())
|
|
123
122
|
|
|
124
|
-
def get_records(self, data_type:
|
|
123
|
+
def get_records(self, data_type: str, record_id: int | None = None) -> list[DataRecord]:
|
|
125
124
|
"""
|
|
126
125
|
Get records from the cached context with the given data type. Capable of being filtered to searching within
|
|
127
126
|
the context of a record ID. If the given data type or record ID does not exist in the context,
|
|
@@ -132,12 +131,11 @@ class OnSaveRuleHandler:
|
|
|
132
131
|
data type from every ID. If an ID is provided, but it does not exist in the context, returns an empty list.
|
|
133
132
|
:return: The records from the context that match the input parameters.
|
|
134
133
|
"""
|
|
135
|
-
data_type: str = AliasUtil.to_data_type_name(data_type)
|
|
136
134
|
records: dict[str, set[DataRecord]] = self.__base_id_to_records.get(record_id, {}) if record_id else self.__records
|
|
137
135
|
return list(records.get(data_type, []))
|
|
138
136
|
|
|
139
137
|
# FR-46701: Add functions to the rule handlers for accessing the field maps of inaccessible records in the context.
|
|
140
|
-
def get_field_maps(self, data_type:
|
|
138
|
+
def get_field_maps(self, data_type: str, record_id: int | None = None) -> list[FieldMap]:
|
|
141
139
|
"""
|
|
142
140
|
Get field maps from the cached context with the given data type. Capable of being filtered to searching within
|
|
143
141
|
the context of a record ID. If the given data type or record ID does not exist in the context,
|
|
@@ -153,7 +151,6 @@ class OnSaveRuleHandler:
|
|
|
153
151
|
list.
|
|
154
152
|
:return: The field maps from the context that match the input parameters.
|
|
155
153
|
"""
|
|
156
|
-
data_type: str = AliasUtil.to_data_type_name(data_type)
|
|
157
154
|
field_maps: dict[str, dict[int, FieldMap]] = self.__base_id_to_field_maps.get(record_id, {}) if record_id else self.__field_maps
|
|
158
155
|
return list(field_maps.get(data_type, {}).values())
|
|
159
156
|
|
|
@@ -4,25 +4,16 @@ from logging import Logger
|
|
|
4
4
|
|
|
5
5
|
from sapiopylib.rest.DataMgmtService import DataMgmtServer
|
|
6
6
|
from sapiopylib.rest.DataRecordManagerService import DataRecordManager
|
|
7
|
-
from sapiopylib.rest.User import SapioUser
|
|
8
7
|
from sapiopylib.rest.WebhookService import AbstractWebhookHandler
|
|
9
|
-
from sapiopylib.rest.pojo.Message import VeloxLogMessage, VeloxLogLevel
|
|
10
8
|
from sapiopylib.rest.pojo.webhook.WebhookContext import SapioWebhookContext
|
|
11
9
|
from sapiopylib.rest.pojo.webhook.WebhookEnums import WebhookEndpointType
|
|
12
10
|
from sapiopylib.rest.pojo.webhook.WebhookResult import SapioWebhookResult
|
|
13
|
-
from sapiopylib.rest.utils.DataTypeCacheManager import DataTypeCacheManager
|
|
14
11
|
from sapiopylib.rest.utils.recordmodel.RecordModelManager import RecordModelManager, RecordModelInstanceManager, \
|
|
15
12
|
RecordModelRelationshipManager
|
|
16
13
|
from sapiopylib.rest.utils.recordmodel.ancestry import RecordModelAncestorManager
|
|
17
14
|
|
|
18
|
-
from sapiopycommons.callbacks.callback_util import CallbackUtil
|
|
19
|
-
from sapiopycommons.eln.experiment_handler import ExperimentHandler
|
|
20
15
|
from sapiopycommons.general.exceptions import SapioUserErrorException, SapioCriticalErrorException, \
|
|
21
|
-
SapioUserCancelledException
|
|
22
|
-
from sapiopycommons.general.sapio_links import SapioNavigationLinker
|
|
23
|
-
from sapiopycommons.recordmodel.record_handler import RecordHandler
|
|
24
|
-
from sapiopycommons.rules.eln_rule_handler import ElnRuleHandler
|
|
25
|
-
from sapiopycommons.rules.on_save_rule_handler import OnSaveRuleHandler
|
|
16
|
+
SapioUserCancelledException
|
|
26
17
|
|
|
27
18
|
|
|
28
19
|
# FR-46064 - Initial port of PyWebhookUtils to sapiopycommons.
|
|
@@ -34,7 +25,6 @@ class CommonsWebhookHandler(AbstractWebhookHandler):
|
|
|
34
25
|
"""
|
|
35
26
|
logger: Logger
|
|
36
27
|
|
|
37
|
-
user: SapioUser
|
|
38
28
|
context: SapioWebhookContext
|
|
39
29
|
|
|
40
30
|
dr_man: DataRecordManager
|
|
@@ -44,46 +34,20 @@ class CommonsWebhookHandler(AbstractWebhookHandler):
|
|
|
44
34
|
# FR-46329: Add the ancestor manager to CommonsWebhookHandler.
|
|
45
35
|
an_man: RecordModelAncestorManager
|
|
46
36
|
|
|
47
|
-
dt_cache: DataTypeCacheManager
|
|
48
|
-
rec_handler: RecordHandler
|
|
49
|
-
callback: CallbackUtil
|
|
50
|
-
exp_handler: ExperimentHandler | None
|
|
51
|
-
rule_handler: OnSaveRuleHandler | ElnRuleHandler | None
|
|
52
|
-
|
|
53
37
|
def run(self, context: SapioWebhookContext) -> SapioWebhookResult:
|
|
54
|
-
self.user = context.user
|
|
55
38
|
self.context = context
|
|
56
|
-
|
|
57
|
-
self.logger = self.user.logger
|
|
39
|
+
self.logger = context.user.logger
|
|
58
40
|
|
|
59
41
|
self.dr_man = context.data_record_manager
|
|
60
|
-
self.rec_man = RecordModelManager(
|
|
42
|
+
self.rec_man = RecordModelManager(context.user)
|
|
61
43
|
self.inst_man = self.rec_man.instance_manager
|
|
62
44
|
self.rel_man = self.rec_man.relationship_manager
|
|
63
45
|
self.an_man = RecordModelAncestorManager(self.rec_man)
|
|
64
46
|
|
|
65
|
-
self.dt_cache = DataTypeCacheManager(self.user)
|
|
66
|
-
self.rec_handler = RecordHandler(context)
|
|
67
|
-
self.callback = CallbackUtil(context)
|
|
68
|
-
if context.eln_experiment is not None:
|
|
69
|
-
self.exp_handler = ExperimentHandler(context)
|
|
70
|
-
else:
|
|
71
|
-
self.exp_handler = None
|
|
72
|
-
if self.is_on_save_rule():
|
|
73
|
-
self.rule_handler = OnSaveRuleHandler(context)
|
|
74
|
-
elif self.is_eln_rule():
|
|
75
|
-
self.rule_handler = ElnRuleHandler(context)
|
|
76
|
-
else:
|
|
77
|
-
self.rule_handler = None
|
|
78
|
-
|
|
79
47
|
# Wrap the execution of each webhook in a try/catch. If an exception occurs, handle any special sapiopycommons
|
|
80
48
|
# exceptions. Otherwise, return a generic message stating that an error occurred.
|
|
81
49
|
try:
|
|
82
|
-
self.
|
|
83
|
-
result = self.execute(context)
|
|
84
|
-
if result is None:
|
|
85
|
-
raise SapioException("Your execute function returned a None result! Don't forget your return statement!")
|
|
86
|
-
return result
|
|
50
|
+
return self.execute(context)
|
|
87
51
|
except SapioUserErrorException as e:
|
|
88
52
|
return self.handle_user_error_exception(e)
|
|
89
53
|
except SapioCriticalErrorException as e:
|
|
@@ -93,13 +57,6 @@ class CommonsWebhookHandler(AbstractWebhookHandler):
|
|
|
93
57
|
except Exception as e:
|
|
94
58
|
return self.handle_unexpected_exception(e)
|
|
95
59
|
|
|
96
|
-
def initialize(self, context: SapioWebhookContext) -> None:
|
|
97
|
-
"""
|
|
98
|
-
A function that can be optionally overridden by your webhooks to initialize additional instance variables,
|
|
99
|
-
or set up whatever else you wish to set up before the execute function is ran. Default behavior does nothing.
|
|
100
|
-
"""
|
|
101
|
-
pass
|
|
102
|
-
|
|
103
60
|
@abstractmethod
|
|
104
61
|
def execute(self, context: SapioWebhookContext) -> SapioWebhookResult:
|
|
105
62
|
"""
|
|
@@ -134,8 +91,7 @@ class CommonsWebhookHandler(AbstractWebhookHandler):
|
|
|
134
91
|
if result is not None:
|
|
135
92
|
return result
|
|
136
93
|
self.log_error(traceback.format_exc())
|
|
137
|
-
|
|
138
|
-
DataMgmtServer.get_client_callback(self.user).display_error(e.args[0])
|
|
94
|
+
DataMgmtServer.get_client_callback(self.context.user).display_error(e.args[0])
|
|
139
95
|
return SapioWebhookResult(False)
|
|
140
96
|
|
|
141
97
|
def handle_unexpected_exception(self, e: Exception) -> SapioWebhookResult:
|
|
@@ -149,10 +105,7 @@ class CommonsWebhookHandler(AbstractWebhookHandler):
|
|
|
149
105
|
result: SapioWebhookResult | None = self.handle_any_exception(e)
|
|
150
106
|
if result is not None:
|
|
151
107
|
return result
|
|
152
|
-
|
|
153
|
-
self.log_error(msg)
|
|
154
|
-
# FR-47079: Also log all unexpected exception messages to the webhook execution log within the platform.
|
|
155
|
-
self.log_error_to_webhook_execution_log(msg)
|
|
108
|
+
self.log_error(traceback.format_exc())
|
|
156
109
|
return SapioWebhookResult(False, display_text="Unexpected error occurred during webhook execution. "
|
|
157
110
|
"Please contact Sapio support.")
|
|
158
111
|
|
|
@@ -167,7 +120,7 @@ class CommonsWebhookHandler(AbstractWebhookHandler):
|
|
|
167
120
|
result: SapioWebhookResult | None = self.handle_any_exception(e)
|
|
168
121
|
if result is not None:
|
|
169
122
|
return result
|
|
170
|
-
return SapioWebhookResult(False)
|
|
123
|
+
return SapioWebhookResult(False, display_text="User cancelled.")
|
|
171
124
|
|
|
172
125
|
# noinspection PyMethodMayBeStatic,PyUnusedLocal
|
|
173
126
|
def handle_any_exception(self, e: Exception) -> SapioWebhookResult | None:
|
|
@@ -183,58 +136,32 @@ class CommonsWebhookHandler(AbstractWebhookHandler):
|
|
|
183
136
|
|
|
184
137
|
def log_info(self, msg: str) -> None:
|
|
185
138
|
"""
|
|
186
|
-
Write an info message to the
|
|
187
|
-
|
|
139
|
+
Write an info message to the log. Log destination is stdout. This message will be prepended with the user's
|
|
140
|
+
username and the experiment ID of the experiment they are in, if any.
|
|
188
141
|
"""
|
|
189
|
-
|
|
142
|
+
exp_id = None
|
|
143
|
+
if self.context.eln_experiment is not None:
|
|
144
|
+
exp_id = self.context.eln_experiment.notebook_experiment_id
|
|
145
|
+
# CR-46333: Add the user's group to the logging message.
|
|
146
|
+
user = self.context.user
|
|
147
|
+
username = user.username
|
|
148
|
+
group_name = user.session_additional_data.current_group_name
|
|
149
|
+
self.logger.info(f"(User: {username}, Group: {group_name}, Experiment: {exp_id}):\n{msg}")
|
|
190
150
|
|
|
191
151
|
def log_error(self, msg: str) -> None:
|
|
192
152
|
"""
|
|
193
|
-
Write an error message to the
|
|
194
|
-
|
|
195
|
-
"""
|
|
196
|
-
# PR-46209: Use logger.error instead of logger.info when logging errors.
|
|
197
|
-
self.logger.error(self._format_log(msg, "log_error call"))
|
|
198
|
-
|
|
199
|
-
def log_error_to_webhook_execution_log(self, msg: str) -> None:
|
|
200
|
-
"""
|
|
201
|
-
Write an error message to the platform's webhook execution log. This can be reviewed by navigating to the
|
|
202
|
-
webhook configuration where the webhook that called this function is defined and clicking the "View Log"
|
|
203
|
-
button. From there, select one of the rows for the webhook executions and click "Download Log" from the right
|
|
204
|
-
side table.
|
|
153
|
+
Write an error message to the log. Log destination is stderr. This message will be prepended with the user's
|
|
154
|
+
username and the experiment ID of the experiment they are in, if any.
|
|
205
155
|
"""
|
|
206
|
-
|
|
207
|
-
messenger.log_message(VeloxLogMessage(message=self._format_log(msg, "Error occurred during webhook execution."),
|
|
208
|
-
log_level=VeloxLogLevel.ERROR,
|
|
209
|
-
originating_class=self.__class__.__name__))
|
|
210
|
-
|
|
211
|
-
def _format_log(self, msg: str, prefix: str | None = None) -> str:
|
|
212
|
-
"""
|
|
213
|
-
Given a message to log, populate it with some metadata about this particular webhook execution, including
|
|
214
|
-
the group of the user and the invocation type of the webhook call.
|
|
215
|
-
"""
|
|
216
|
-
# If we're able to, provide a link to the location that the error occurred at.
|
|
217
|
-
navigator = SapioNavigationLinker(self.context)
|
|
156
|
+
exp_id = None
|
|
218
157
|
if self.context.eln_experiment is not None:
|
|
219
|
-
|
|
220
|
-
elif self.context.data_record and not self.context.data_record_list:
|
|
221
|
-
link = navigator.data_record(self.context.data_record)
|
|
222
|
-
elif self.context.base_data_record:
|
|
223
|
-
link = navigator.data_record(self.context.base_data_record)
|
|
224
|
-
else:
|
|
225
|
-
link = None
|
|
226
|
-
|
|
227
|
-
message: str = ""
|
|
228
|
-
if prefix:
|
|
229
|
-
message += prefix + "\n"
|
|
230
|
-
message += f"Webhook invocation type: {self.context.end_point_type.display_name}\n"
|
|
231
|
-
message += f"Username: {self.user.username}\n"
|
|
158
|
+
exp_id = self.context.eln_experiment.notebook_experiment_id
|
|
232
159
|
# CR-46333: Add the user's group to the logging message.
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
160
|
+
user = self.context.user
|
|
161
|
+
username = user.username
|
|
162
|
+
group_name = user.session_additional_data.current_group_name
|
|
163
|
+
# PR-46209: Use logger.error instead of logger.info when logging errors.
|
|
164
|
+
self.logger.error(f"(User: {username}, Group: {group_name}, Experiment: {exp_id}):\n{msg}")
|
|
238
165
|
|
|
239
166
|
def is_main_toolbar(self) -> bool:
|
|
240
167
|
"""
|
|
@@ -310,51 +237,3 @@ class CommonsWebhookHandler(AbstractWebhookHandler):
|
|
|
310
237
|
:return: True if this endpoint was invoked as a scheduled action.
|
|
311
238
|
"""
|
|
312
239
|
return self.context.end_point_type == WebhookEndpointType.SCHEDULEDPLUGIN
|
|
313
|
-
|
|
314
|
-
def is_action_button_field(self) -> bool:
|
|
315
|
-
"""
|
|
316
|
-
:return: True if this endpoint was invoked as an action button field.
|
|
317
|
-
"""
|
|
318
|
-
return self.context.end_point_type == WebhookEndpointType.ACTIONDATAFIELD
|
|
319
|
-
|
|
320
|
-
def is_action_text_field(self) -> bool:
|
|
321
|
-
"""
|
|
322
|
-
:return: True if this endpoint was invoked as an action text field.
|
|
323
|
-
"""
|
|
324
|
-
return self.context.end_point_type == WebhookEndpointType.ACTION_TEXT_FIELD
|
|
325
|
-
|
|
326
|
-
def is_custom(self) -> bool:
|
|
327
|
-
"""
|
|
328
|
-
:return: True if this endpoint was invoked from a custom point, such as a custom queue.
|
|
329
|
-
"""
|
|
330
|
-
return self.context.end_point_type == WebhookEndpointType.CUSTOM
|
|
331
|
-
|
|
332
|
-
def is_calendar_event_click_handler(self) -> bool:
|
|
333
|
-
"""
|
|
334
|
-
:return: True if this endpoint was invoked from a calendar event click handler.
|
|
335
|
-
"""
|
|
336
|
-
return self.context.end_point_type == WebhookEndpointType.CALENDAR_EVENT_CLICK_HANDLER
|
|
337
|
-
|
|
338
|
-
def is_eln_menu_grabber(self) -> bool:
|
|
339
|
-
"""
|
|
340
|
-
:return: True if this endpoint was invoked as a notebook entry grabber.
|
|
341
|
-
"""
|
|
342
|
-
return self.context.end_point_type == WebhookEndpointType.NOTEBOOKEXPERIMENTGRABBER
|
|
343
|
-
|
|
344
|
-
def is_conversation_bot(self) -> bool:
|
|
345
|
-
"""
|
|
346
|
-
:return: True if this endpoint was invoked as from a conversation bot.
|
|
347
|
-
"""
|
|
348
|
-
return self.context.end_point_type == WebhookEndpointType.CONVERSATION_BOT
|
|
349
|
-
|
|
350
|
-
def is_multi_data_type_table_toolbar(self) -> bool:
|
|
351
|
-
"""
|
|
352
|
-
:return: True if this endpoint was invoked as a multi data type table toolbar button.
|
|
353
|
-
"""
|
|
354
|
-
return self.context.end_point_type == WebhookEndpointType.REPORTTOOLBAR
|
|
355
|
-
|
|
356
|
-
def can_send_client_callback(self) -> bool:
|
|
357
|
-
"""
|
|
358
|
-
:return: Whether client callbacks and directives can be sent from this webhook's endpoint type.
|
|
359
|
-
"""
|
|
360
|
-
return self.context.is_client_callback_available
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: sapiopycommons
|
|
3
|
-
Version: 2024.8.
|
|
3
|
+
Version: 2024.8.28a313
|
|
4
4
|
Summary: Official Sapio Python API Utilities Package
|
|
5
5
|
Project-URL: Homepage, https://github.com/sapiosciences
|
|
6
6
|
Author-email: Jonathan Steck <jsteck@sapiosciences.com>, Yechen Qiao <yqiao@sapiosciences.com>
|
|
@@ -17,8 +17,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
17
17
|
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
18
18
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
19
|
Requires-Python: >=3.10
|
|
20
|
-
Requires-Dist:
|
|
21
|
-
Requires-Dist: sapiopylib>=2024.5.24.210
|
|
20
|
+
Requires-Dist: sapiopylib>=2023.12.13.174
|
|
22
21
|
Description-Content-Type: text/markdown
|
|
23
22
|
|
|
24
23
|
|
|
@@ -51,7 +50,6 @@ This license does not provide any rights to use any other copyrighted artifacts
|
|
|
51
50
|
## Dependencies
|
|
52
51
|
The following dependencies are required for this package:
|
|
53
52
|
- [sapiopylib - The official Sapio Informatics Platform Python API package.](https://pypi.org/project/sapiopylib/)
|
|
54
|
-
- [databind - Databind is a library inspired by jackson-databind to de-/serialize Python dataclasses.](https://pypi.org/project/databind/)
|
|
55
53
|
|
|
56
54
|
## Getting Help
|
|
57
55
|
If you have a support contract with Sapio Sciences, please use our [technical support channels](https://sapio-sciences.atlassian.net/servicedesk/customer/portals).
|
|
@@ -0,0 +1,38 @@
|
|
|
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=D6whWxYWvs5rXOG2Slpi1icC18SLKmG9-MP9f0YDDNE,43256
|
|
4
|
+
sapiopycommons/chem/IndigoMolecules.py,sha256=ukZcX6TMEgkNdD1L1GnH3tp5rGplFNPlGoChAHXbsxw,1945
|
|
5
|
+
sapiopycommons/chem/Molecules.py,sha256=tOkn3fg4QizgqjkRLuvRdVy0JpTD3QEOSvZPxmIyT4c,8607
|
|
6
|
+
sapiopycommons/chem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
sapiopycommons/datatype/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
sapiopycommons/datatype/attachment_util.py,sha256=YlnMprj5IGBbAZDLG2khS1P7JIYTw_NYfpJAfRZfP3M,3219
|
|
9
|
+
sapiopycommons/eln/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
sapiopycommons/eln/experiment_handler.py,sha256=v1pG4qtZb8OSNWfKtFo6NjnEkReqnu5R9i_hqWh_xxg,57198
|
|
11
|
+
sapiopycommons/eln/plate_designer.py,sha256=FYJfhhNq8hdfuXgDYOYHy6g0m2zNwQXZWF_MTPzElDg,7184
|
|
12
|
+
sapiopycommons/files/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
sapiopycommons/files/complex_data_loader.py,sha256=XSJOl676mIklJo78v07-70u1b015a5DI4sqZPI3C-Tw,1475
|
|
14
|
+
sapiopycommons/files/file_bridge.py,sha256=6yjUi0ejypb1nvcEvn21EuquB-SmEjB-fCZiMaNZg7Q,5757
|
|
15
|
+
sapiopycommons/files/file_data_handler.py,sha256=3-guAdhJdeJWAFq1a27ijspkO7uMMZ6CapMCD_6o4jA,36746
|
|
16
|
+
sapiopycommons/files/file_util.py,sha256=92SzwRif4dOcGqZ9ri90QeC20NOCenT8DxQjdSH5Uyc,25556
|
|
17
|
+
sapiopycommons/files/file_validator.py,sha256=5DUI_h0WB1AvfoPgx8En3-sC5xlzm5Z2deoSf9qviKQ,24499
|
|
18
|
+
sapiopycommons/files/file_writer.py,sha256=5u_iZXTQvuUU7ceHZr8Q001_tvgJhOqBwAnB_pxcAbQ,16027
|
|
19
|
+
sapiopycommons/general/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
+
sapiopycommons/general/aliases.py,sha256=i6af5o2oVFGNcyk7GkvTWXQs0H9xTbFKc_GIah8NKVU,3594
|
|
21
|
+
sapiopycommons/general/custom_report_util.py,sha256=Yrq-Ize1M1jh9g3BmQT9Egedufi3Nl9xNmgNI_LGiho,4828
|
|
22
|
+
sapiopycommons/general/exceptions.py,sha256=DOlLKnpCatxQF-lVCToa8ryJgusWLvip6N_1ALN00QE,1679
|
|
23
|
+
sapiopycommons/general/popup_util.py,sha256=-mN5IgYPrLrOEHJ4CHPi2rec4_WAN6X0yMxHwD5h3Bs,30126
|
|
24
|
+
sapiopycommons/general/storage_util.py,sha256=ovmK_jN7v09BoX07XxwShpBUC5WYQOM7dbKV_VeLXJU,8892
|
|
25
|
+
sapiopycommons/general/time_util.py,sha256=jiJUh7jc1ZRCOem880S3HaLPZ4RboBtSl4_U9sqAQuM,7290
|
|
26
|
+
sapiopycommons/processtracking/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
|
+
sapiopycommons/processtracking/endpoints.py,sha256=g5h_uCVByqacYm9zWAz8TyAdRsGfaO2o0b5RSJdOaSA,10926
|
|
28
|
+
sapiopycommons/recordmodel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
|
+
sapiopycommons/recordmodel/record_handler.py,sha256=VYUJ0bgZbyc6-XYRKvsxrpWHLdCwxzhv13Ce2tZpAQQ,39348
|
|
30
|
+
sapiopycommons/rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
|
+
sapiopycommons/rules/eln_rule_handler.py,sha256=qfkBZtck0KK1i9s9Xe2UZqkzQOgPCzDxRkhxE8Si1xk,10671
|
|
32
|
+
sapiopycommons/rules/on_save_rule_handler.py,sha256=JY9F30IcHwFVdgPAMQtTYuRastV1jeezhVktyrzNASU,10763
|
|
33
|
+
sapiopycommons/webhook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
34
|
+
sapiopycommons/webhook/webhook_handlers.py,sha256=K_K7CEAMZ-bNb2LCIKdt0CxHsBKkwSBzfnp0JSdGJUM,11102
|
|
35
|
+
sapiopycommons-2024.8.28a313.dist-info/METADATA,sha256=xb9YgxmbGyTKDDaq4vOrxEk5wNz-8KQ_-6WPBgMFexg,3009
|
|
36
|
+
sapiopycommons-2024.8.28a313.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
37
|
+
sapiopycommons-2024.8.28a313.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
|
|
38
|
+
sapiopycommons-2024.8.28a313.dist-info/RECORD,,
|
|
File without changes
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
from sapiopylib.rest.pojo.CustomReport import ReportColumn
|
|
2
|
-
from sapiopylib.rest.pojo.datatype.FieldDefinition import FieldType
|
|
3
|
-
|
|
4
|
-
from sapiopycommons.general.aliases import DataTypeIdentifier, FieldIdentifier, AliasUtil
|
|
5
|
-
from sapiopycommons.general.exceptions import SapioException
|
|
6
|
-
|
|
7
|
-
# The system fields that every record has and their field types. System fields aren't generated as record model fields
|
|
8
|
-
# for all platform version, hence the need to create a dict for them in the off chance that they're not present on
|
|
9
|
-
# the model wrapper.
|
|
10
|
-
SYSTEM_FIELDS: dict[str, FieldType] = {
|
|
11
|
-
"DataRecordName": FieldType.IDENTIFIER,
|
|
12
|
-
"RecordId": FieldType.LONG,
|
|
13
|
-
"DateCreated": FieldType.DATE,
|
|
14
|
-
"CreatedBy": FieldType.STRING,
|
|
15
|
-
"VeloxLastModifiedDate": FieldType.DATE,
|
|
16
|
-
"VeloxLastModifiedBy": FieldType.STRING
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class ColumnBuilder:
|
|
21
|
-
"""
|
|
22
|
-
A class for building report columns for custom reports.
|
|
23
|
-
"""
|
|
24
|
-
@staticmethod
|
|
25
|
-
def build_column(data_type: DataTypeIdentifier, field: FieldIdentifier, field_type: FieldType | None = None) \
|
|
26
|
-
-> ReportColumn:
|
|
27
|
-
"""
|
|
28
|
-
Build a ReportColumn from a variety of possible inputs.
|
|
29
|
-
|
|
30
|
-
:param data_type: An object that can be used to identify a data type.
|
|
31
|
-
:param field: An object that can be used to identify a data field.
|
|
32
|
-
:param field_type: The field type of the provided field. This is only required if the field type cannot be
|
|
33
|
-
determined from the given data type and field, which occurs when the given field is a string and the
|
|
34
|
-
given data type is not a wrapped record model or record model wrapper.
|
|
35
|
-
:return: A ReportColumn for the inputs.
|
|
36
|
-
"""
|
|
37
|
-
# Get the data type and field names from the inputs.
|
|
38
|
-
data_type_name = AliasUtil.to_data_type_name(data_type)
|
|
39
|
-
field_name = AliasUtil.to_data_field_name(field)
|
|
40
|
-
if field_type is None:
|
|
41
|
-
field_type = ColumnBuilder.__field_type(data_type, field)
|
|
42
|
-
if field_type is None:
|
|
43
|
-
raise SapioException("The field_type parameter is required for the provided data_type and field inputs.")
|
|
44
|
-
return ReportColumn(data_type_name, field_name, field_type)
|
|
45
|
-
|
|
46
|
-
@staticmethod
|
|
47
|
-
def __field_type(data_type: DataTypeIdentifier, field: FieldIdentifier) -> FieldType | None:
|
|
48
|
-
"""
|
|
49
|
-
Given a record model wrapper and a field name, return the field type for that field. Accounts for system fields.
|
|
50
|
-
|
|
51
|
-
:param data_type: The record model wrapper that the field is on.
|
|
52
|
-
:param field: The field name to return the type of.
|
|
53
|
-
:return: The field type of the given field name.
|
|
54
|
-
"""
|
|
55
|
-
# Check if the field name is a system field. If it us, use the field type defined in this file.
|
|
56
|
-
field_name: str = AliasUtil.to_data_field_name(field)
|
|
57
|
-
if field_name in SYSTEM_FIELDS:
|
|
58
|
-
return SYSTEM_FIELDS.get(field_name)
|
|
59
|
-
# Otherwise, check if the field type can be found from the wrapper.
|
|
60
|
-
return AliasUtil.to_field_type(field_name, data_type)
|