sapiopycommons 2024.7.25a299__py3-none-any.whl → 2024.8.2a301__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.

@@ -4,7 +4,9 @@ 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
7
8
  from sapiopylib.rest.WebhookService import AbstractWebhookHandler
9
+ from sapiopylib.rest.pojo.Message import VeloxLogMessage, VeloxLogLevel
8
10
  from sapiopylib.rest.pojo.webhook.WebhookContext import SapioWebhookContext
9
11
  from sapiopylib.rest.pojo.webhook.WebhookEnums import WebhookEndpointType
10
12
  from sapiopylib.rest.pojo.webhook.WebhookResult import SapioWebhookResult
@@ -14,6 +16,7 @@ from sapiopylib.rest.utils.recordmodel.ancestry import RecordModelAncestorManage
14
16
 
15
17
  from sapiopycommons.general.exceptions import SapioUserErrorException, SapioCriticalErrorException, \
16
18
  SapioUserCancelledException
19
+ from sapiopycommons.general.sapio_links import SapioNavigationLinker
17
20
 
18
21
 
19
22
  # FR-46064 - Initial port of PyWebhookUtils to sapiopycommons.
@@ -25,6 +28,7 @@ class CommonsWebhookHandler(AbstractWebhookHandler):
25
28
  """
26
29
  logger: Logger
27
30
 
31
+ user: SapioUser
28
32
  context: SapioWebhookContext
29
33
 
30
34
  dr_man: DataRecordManager
@@ -35,11 +39,13 @@ class CommonsWebhookHandler(AbstractWebhookHandler):
35
39
  an_man: RecordModelAncestorManager
36
40
 
37
41
  def run(self, context: SapioWebhookContext) -> SapioWebhookResult:
42
+ self.user = context.user
38
43
  self.context = context
39
- self.logger = context.user.logger
44
+
45
+ self.logger = self.user.logger
40
46
 
41
47
  self.dr_man = context.data_record_manager
42
- self.rec_man = RecordModelManager(context.user)
48
+ self.rec_man = RecordModelManager(self.user)
43
49
  self.inst_man = self.rec_man.instance_manager
44
50
  self.rel_man = self.rec_man.relationship_manager
45
51
  self.an_man = RecordModelAncestorManager(self.rec_man)
@@ -100,7 +106,7 @@ class CommonsWebhookHandler(AbstractWebhookHandler):
100
106
  return result
101
107
  self.log_error(traceback.format_exc())
102
108
  if self.can_send_client_callback():
103
- DataMgmtServer.get_client_callback(self.context.user).display_error(e.args[0])
109
+ DataMgmtServer.get_client_callback(self.user).display_error(e.args[0])
104
110
  return SapioWebhookResult(False)
105
111
 
106
112
  def handle_unexpected_exception(self, e: Exception) -> SapioWebhookResult:
@@ -114,7 +120,10 @@ class CommonsWebhookHandler(AbstractWebhookHandler):
114
120
  result: SapioWebhookResult | None = self.handle_any_exception(e)
115
121
  if result is not None:
116
122
  return result
117
- self.log_error(traceback.format_exc())
123
+ msg: str = traceback.format_exc()
124
+ self.log_error(msg)
125
+ # FR-47079: Also log all unexpected exception messages to the webhook execution log within the platform.
126
+ self.log_error_to_webhook_execution_log(msg)
118
127
  return SapioWebhookResult(False, display_text="Unexpected error occurred during webhook execution. "
119
128
  "Please contact Sapio support.")
120
129
 
@@ -145,32 +154,58 @@ class CommonsWebhookHandler(AbstractWebhookHandler):
145
154
 
146
155
  def log_info(self, msg: str) -> None:
147
156
  """
148
- Write an info message to the log. Log destination is stdout. This message will be prepended with the user's
149
- username and the experiment ID of the experiment they are in, if any.
157
+ Write an info message to the webhook server log. Log destination is stdout. This message will be prepended with
158
+ the user's username and the experiment ID of the experiment they are in, if any.
150
159
  """
151
- exp_id = None
152
- if self.context.eln_experiment is not None:
153
- exp_id = self.context.eln_experiment.notebook_experiment_id
154
- # CR-46333: Add the user's group to the logging message.
155
- user = self.context.user
156
- username = user.username
157
- group_name = user.session_additional_data.current_group_name
158
- self.logger.info(f"(User: {username}, Group: {group_name}, Experiment: {exp_id}):\n{msg}")
160
+ self.logger.info(self._format_log(msg, "log_info call"))
159
161
 
160
162
  def log_error(self, msg: str) -> None:
161
163
  """
162
- Write an error message to the log. Log destination is stderr. This message will be prepended with the user's
163
- username and the experiment ID of the experiment they are in, if any.
164
+ Write an error message to the webhook server log. Log destination is stderr. This message will be prepended with
165
+ the user's username and the experiment ID of the experiment they are in, if any.
166
+ """
167
+ # PR-46209: Use logger.error instead of logger.info when logging errors.
168
+ self.logger.error(self._format_log(msg, "log_error call"))
169
+
170
+ def log_error_to_webhook_execution_log(self, msg: str) -> None:
171
+ """
172
+ Write an error message to the platform's webhook execution log. This can be reviewed by navigating to the
173
+ webhook configuration where the webhook that called this function is defined and clicking the "View Log"
174
+ button. From there, select one of the rows for the webhook executions and click "Download Log" from the right
175
+ side table.
176
+ """
177
+ messenger = DataMgmtServer.get_messenger(self.user)
178
+ messenger.log_message(VeloxLogMessage(message=self._format_log(msg, "Error occurred during webhook execution."),
179
+ log_level=VeloxLogLevel.ERROR,
180
+ originating_class=self.__class__.__name__))
181
+
182
+ def _format_log(self, msg: str, prefix: str | None = None) -> str:
183
+ """
184
+ Given a message to log, populate it with some metadata about this particular webhook execution, including
185
+ the group of the user and the invocation type of the webhook call.
164
186
  """
165
- exp_id = None
187
+ # If we're able to, provide a link to the location that the error occurred at.
188
+ navigator = SapioNavigationLinker(self.context)
166
189
  if self.context.eln_experiment is not None:
167
- exp_id = self.context.eln_experiment.notebook_experiment_id
190
+ link = navigator.experiment(self.context.eln_experiment)
191
+ elif self.context.data_record and not self.context.data_record_list:
192
+ link = navigator.data_record(self.context.data_record)
193
+ elif self.context.base_data_record:
194
+ link = navigator.data_record(self.context.base_data_record)
195
+ else:
196
+ link = None
197
+
198
+ message: str = ""
199
+ if prefix:
200
+ message += prefix + "\n"
201
+ message += f"Webhook invocation type: {self.context.end_point_type.display_name}\n"
202
+ message += f"Username: {self.user.username}\n"
168
203
  # CR-46333: Add the user's group to the logging message.
169
- user = self.context.user
170
- username = user.username
171
- group_name = user.session_additional_data.current_group_name
172
- # PR-46209: Use logger.error instead of logger.info when logging errors.
173
- self.logger.error(f"(User: {username}, Group: {group_name}, Experiment: {exp_id}):\n{msg}")
204
+ message += f"User group: {self.user.session_additional_data.current_group_name}\n"
205
+ if link:
206
+ message += f"User location: {link}\n"
207
+ message += msg
208
+ return message
174
209
 
175
210
  def is_main_toolbar(self) -> bool:
176
211
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sapiopycommons
3
- Version: 2024.7.25a299
3
+ Version: 2024.8.2a301
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>
@@ -1,29 +1,31 @@
1
1
  sapiopycommons/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  sapiopycommons/callbacks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- sapiopycommons/callbacks/callback_util.py,sha256=caeIWCHvK33jDs3TRskpJv0kDe7W8NPK4MyJPjgztwo,58012
3
+ sapiopycommons/callbacks/callback_util.py,sha256=YdaN1iNnJ51EauvKfEOAUwahu1dt_YVvr4Zia29g9qc,61123
4
4
  sapiopycommons/chem/IndigoMolecules.py,sha256=QqFDi9CKERj6sn_ZwVcS2xZq4imlkaTeCrpq1iNcEJA,1992
5
5
  sapiopycommons/chem/Molecules.py,sha256=t80IsQBPJ9mwE8ZxnWomAGrZDhdsOuPvLaTPb_N6jGU,8639
6
6
  sapiopycommons/chem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  sapiopycommons/datatype/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- sapiopycommons/datatype/attachment_util.py,sha256=YlnMprj5IGBbAZDLG2khS1P7JIYTw_NYfpJAfRZfP3M,3219
8
+ sapiopycommons/datatype/attachment_util.py,sha256=23JQ4avSmBBJdCv95LVj31x8rUCclzB_DYFBijH0NII,3708
9
9
  sapiopycommons/eln/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- sapiopycommons/eln/experiment_handler.py,sha256=v1pG4qtZb8OSNWfKtFo6NjnEkReqnu5R9i_hqWh_xxg,57198
10
+ sapiopycommons/eln/experiment_handler.py,sha256=RspUDmPmBQIG7l7q_luFP8yeRljdU3E64066NH5CtdI,59817
11
11
  sapiopycommons/eln/experiment_report_util.py,sha256=FTLw-6SLAMeoWTOO-qhGROE9g54pZdyoQJIhiIzlwGw,7848
12
12
  sapiopycommons/eln/plate_designer.py,sha256=FYJfhhNq8hdfuXgDYOYHy6g0m2zNwQXZWF_MTPzElDg,7184
13
13
  sapiopycommons/files/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- sapiopycommons/files/complex_data_loader.py,sha256=XSJOl676mIklJo78v07-70u1b015a5DI4sqZPI3C-Tw,1475
15
- sapiopycommons/files/file_bridge.py,sha256=GI3-gWFzcL0q0c8jKOxTevbzJqtUpiElmkXfTnMsaOo,6224
14
+ sapiopycommons/files/complex_data_loader.py,sha256=8jgYF5iGDD6Abw8JRWLYxUWVwj4s4pH5HylyxEGFZSU,1471
15
+ sapiopycommons/files/file_bridge.py,sha256=njx_5Z3tvQUNW4mPazQerL8lopLAFStIByHWHJ7m5ug,6220
16
16
  sapiopycommons/files/file_bridge_handler.py,sha256=MU2wZR4VY606yx6Bnv8-LzG3mGCeuXeRBn914WNRFCo,13601
17
17
  sapiopycommons/files/file_data_handler.py,sha256=3-guAdhJdeJWAFq1a27ijspkO7uMMZ6CapMCD_6o4jA,36746
18
- sapiopycommons/files/file_util.py,sha256=44mzhn3M_QltoncBB-ooX7_yO6u5k-XU_bzUXHGxUiw,26299
19
- sapiopycommons/files/file_validator.py,sha256=BhXB2XnoNEzdBXuwul1s2RNoj-3ZoiMmephUCU_0o3Y,28113
18
+ sapiopycommons/files/file_util.py,sha256=ronTlJimQ6ttJN6Y9qfAzEWoeWnDoUbohkdObNK5mJQ,27042
19
+ sapiopycommons/files/file_validator.py,sha256=EqPCXfVCiilgnOb2G-yZg8XWeDqYp9iVCg8AaWznvf4,28040
20
20
  sapiopycommons/files/file_writer.py,sha256=5u_iZXTQvuUU7ceHZr8Q001_tvgJhOqBwAnB_pxcAbQ,16027
21
21
  sapiopycommons/general/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  sapiopycommons/general/accession_service.py,sha256=HYgyOsH_UaoRnoury-c2yTW8SeG4OtjLemdpCzoV4R8,13484
23
- sapiopycommons/general/aliases.py,sha256=i6af5o2oVFGNcyk7GkvTWXQs0H9xTbFKc_GIah8NKVU,3594
23
+ sapiopycommons/general/aliases.py,sha256=UddtYCGqM-wkLXT0LAUqMlFGHZSyOPjA6hzQHvjlDcQ,4324
24
+ sapiopycommons/general/audit_log.py,sha256=LNpBCpZ5mz47-HzHel8PUz1TYGCnxTY6dnerZu-cwOo,9076
24
25
  sapiopycommons/general/custom_report_util.py,sha256=cLgIR5Fn3M9uyAtgfTYRv3JRk2SKNevnsb_R5zidSYs,15557
25
26
  sapiopycommons/general/exceptions.py,sha256=DOlLKnpCatxQF-lVCToa8ryJgusWLvip6N_1ALN00QE,1679
26
27
  sapiopycommons/general/popup_util.py,sha256=-mN5IgYPrLrOEHJ4CHPi2rec4_WAN6X0yMxHwD5h3Bs,30126
28
+ sapiopycommons/general/sapio_links.py,sha256=UlqB09wmgDgbQiB8d3mEj7rxW_GMIXz3j3RlvADNt_A,2475
27
29
  sapiopycommons/general/storage_util.py,sha256=ovmK_jN7v09BoX07XxwShpBUC5WYQOM7dbKV_VeLXJU,8892
28
30
  sapiopycommons/general/time_util.py,sha256=jiJUh7jc1ZRCOem880S3HaLPZ4RboBtSl4_U9sqAQuM,7290
29
31
  sapiopycommons/multimodal/multimodal.py,sha256=A1QsC8QTPmgZyPr7KtMbPRedn2Ie4WIErodUvQ9otgU,6724
@@ -31,13 +33,13 @@ sapiopycommons/multimodal/multimodal_data.py,sha256=zqgYHO-ULaPKV0POFWZVY9N-Sfm1
31
33
  sapiopycommons/processtracking/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
34
  sapiopycommons/processtracking/endpoints.py,sha256=g5h_uCVByqacYm9zWAz8TyAdRsGfaO2o0b5RSJdOaSA,10926
33
35
  sapiopycommons/recordmodel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
- sapiopycommons/recordmodel/record_handler.py,sha256=AyK1H3x-g1eu1Mt9XD1h57yRrZp_TJjZlEaQ2kPP4Dc,54432
36
+ sapiopycommons/recordmodel/record_handler.py,sha256=qqsHeGNyqQeFKuZ4U2v2MD278AlH4n1HMvSTOY0hbyo,58636
35
37
  sapiopycommons/rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
- sapiopycommons/rules/eln_rule_handler.py,sha256=qfkBZtck0KK1i9s9Xe2UZqkzQOgPCzDxRkhxE8Si1xk,10671
37
- sapiopycommons/rules/on_save_rule_handler.py,sha256=JY9F30IcHwFVdgPAMQtTYuRastV1jeezhVktyrzNASU,10763
38
+ sapiopycommons/rules/eln_rule_handler.py,sha256=rz9E1PQLShCZM09JafMl_ylUqBbMs-et0FsOG41tQL0,9480
39
+ sapiopycommons/rules/on_save_rule_handler.py,sha256=I06HwsNvulyU0avSXOU0itBDAmiOxsyW8KGk_gH0FHc,9238
38
40
  sapiopycommons/webhook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
- sapiopycommons/webhook/webhook_handlers.py,sha256=ibpBY3Sk3Eij919bIdW0awzlogYoQSWYDDOg--NwsQE,13431
40
- sapiopycommons-2024.7.25a299.dist-info/METADATA,sha256=i4UbrKpFDQoTmRgh5esjX8qysb4lmefghuPy-UtM1hA,3176
41
- sapiopycommons-2024.7.25a299.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
42
- sapiopycommons-2024.7.25a299.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
43
- sapiopycommons-2024.7.25a299.dist-info/RECORD,,
41
+ sapiopycommons/webhook/webhook_handlers.py,sha256=1uM_epEaEB8w14padEdASXqF3BNalNiShP51a_hU-Ac,15267
42
+ sapiopycommons-2024.8.2a301.dist-info/METADATA,sha256=EVt23yIYhHMJPakRR5Q-RMUi7-1AnxZSKtMrN6hHwwM,3175
43
+ sapiopycommons-2024.8.2a301.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
44
+ sapiopycommons-2024.8.2a301.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
45
+ sapiopycommons-2024.8.2a301.dist-info/RECORD,,