sapiopycommons 2024.12.12a382__py3-none-any.whl → 2024.12.13a385__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.

@@ -1163,7 +1163,7 @@ class FieldModifier:
1163
1163
  """
1164
1164
  field = copy_field(field)
1165
1165
  if self.prepend_data_type is True:
1166
- field._data_field_name = field.data_field_name + "." + field.data_field_name
1166
+ field._data_field_name = field.data_type_name + "." + field.data_field_name
1167
1167
  if self.display_name is not None:
1168
1168
  field.display_name = self.display_name
1169
1169
  if self.required is not None:
@@ -15,6 +15,7 @@ from sapiopylib.rest.utils.recordmodel.RecordModelManager import RecordModelMana
15
15
  from sapiopylib.rest.utils.recordmodel.ancestry import RecordModelAncestorManager
16
16
  from werkzeug.datastructures import Headers
17
17
  from werkzeug.datastructures.structures import MultiDict
18
+ from werkzeug.exceptions import UnsupportedMediaType, BadRequest
18
19
 
19
20
  from sapiopycommons.general.exceptions import SapioException
20
21
  from sapiopycommons.recordmodel.record_handler import RecordHandler
@@ -73,11 +74,54 @@ class SapioWebserviceResult:
73
74
  WebserviceResponse = SapioWebserviceResult | Response | tuple[dict[str, Any] | int]
74
75
 
75
76
 
76
- class BaseAuthenticatorClass(AbstractWebhookHandler, ABC):
77
+ class AbstractWebserviceHandler(AbstractWebhookHandler):
77
78
  """
78
- The base class for classes that may need to authenticate a SapioUser object for interacting with a Sapio server
79
- through the webservice API.
79
+ A base class for constructing POST webservice endpoints on your webhook server. These are endpoints that can be
80
+ communicated with by external sources without needing to format the request in the webhook context format that
81
+ normal webhook handlers expect.
82
+
83
+ Since this extends AbstractWebhookHandler, you can still register endpoints from this class in the same way you
84
+ would normal webhook endpoints.
80
85
  """
86
+ request: Request
87
+
88
+ def post(self) -> Response | tuple[dict[str, Any], int]:
89
+ """
90
+ Internal method to be executed to translate incoming POST requests.
91
+ """
92
+ # noinspection PyBroadException
93
+ try:
94
+ self.request = request
95
+ try:
96
+ raw_json = request.json
97
+ headers = request.headers
98
+ params = request.args
99
+ except UnsupportedMediaType as e:
100
+ return SapioWebserviceResult(str(e), 415, True).to_json(), 415
101
+ except BadRequest as e:
102
+ return SapioWebserviceResult(str(e), 400, True).to_json(), 400
103
+ ret_val: WebserviceResponse = self.run(raw_json, headers, params)
104
+ if isinstance(ret_val, SapioWebserviceResult):
105
+ return ret_val.to_result()
106
+ return ret_val
107
+ except Exception:
108
+ print('Error occurred while running webservice custom logic. See traceback.', file=sys.stderr)
109
+ traceback.print_exc()
110
+ return SapioWebserviceResult("Unexpected error occurred.", 500, True).to_json(), 500
111
+
112
+ # noinspection PyMethodOverriding
113
+ @abstractmethod
114
+ def run(self, payload: Any, headers: Headers, params: MultiDict[str, str]) -> WebserviceResponse:
115
+ """
116
+ The execution details for this endpoint.
117
+
118
+ :param payload: The JSON payload from the request. Usually a dictionary of strings to Any.
119
+ :param headers: The headers from the request. Can be used like a dictionary.
120
+ :param params: The URL parameters from the request.
121
+ :return: A response object to send back to the requester.
122
+ """
123
+ pass
124
+
81
125
  def authenticate_user(self, headers: dict[str, str]) -> SapioUser:
82
126
  """
83
127
  Authenticate a user for making requests to a Sapio server using the provided headers. If no user can be
@@ -144,90 +188,10 @@ class BaseAuthenticatorClass(AbstractWebhookHandler, ABC):
144
188
  return SapioUser(url, self.verify_sapio_cert, self.client_timeout_seconds, bearer_token=bearer_token)
145
189
 
146
190
 
147
- class AbstractWebservicePostHandler(BaseAuthenticatorClass):
148
- """
149
- A base class for constructing POST webservice endpoints on your webhook server. These are endpoints that can be
150
- communicated with by external sources without needing to format the request in the webhook context format that
151
- normal webhook handlers expect.
152
-
153
- Since this extends AbstractWebhookHandler, you can still register endpoints from this class in the same way you
154
- would normal webhook endpoints.
155
- """
156
- request: Request
157
-
158
- def post(self) -> Response | tuple[dict[str, Any], int]:
159
- """
160
- Internal method to be executed to translate incoming POST requests.
161
- """
162
- # noinspection PyBroadException
163
- try:
164
- self.request = request
165
- ret_val: WebserviceResponse = self.run(request.json, request.headers, request.args)
166
- if isinstance(ret_val, SapioWebserviceResult):
167
- return ret_val.to_result()
168
- return ret_val
169
- except Exception:
170
- print('Error occurred while running webservice custom logic. See traceback.', file=sys.stderr)
171
- traceback.print_exc()
172
- return SapioWebserviceResult("Unexpected error occurred.", 500, True).to_json(), 500
173
-
174
- # noinspection PyMethodOverriding
175
- @abstractmethod
176
- def run(self, payload: Any, headers: Headers, params: MultiDict[str, str]) -> WebserviceResponse:
177
- """
178
- The execution details for this endpoint.
179
-
180
- :param payload: The JSON payload from the request. Usually a dictionary of strings to Any.
181
- :param headers: The headers from the request. Can be used like a dictionary.
182
- :param params: The URL parameters from the request.
183
- :return: A response object to send back to the requester.
184
- """
185
- pass
186
-
187
-
188
- class AbstractWebserviceGetHandler(BaseAuthenticatorClass):
189
- """
190
- A base class for constructing GET webservice endpoints on your webhook server. These are endpoints that can be
191
- communicated with by external sources without needing to format the request in the webhook context format that
192
- normal webhook handlers expect.
193
-
194
- Since this extends AbstractWebhookHandler, you can still register endpoints from this class in the same way you
195
- would normal webhook endpoints.
196
- """
197
- request: Request
198
-
199
- def get(self) -> Response | tuple[dict[str, Any], int]:
200
- """
201
- Internal method to be executed to translate incoming GET requests.
202
- """
203
- # noinspection PyBroadException
204
- try:
205
- self.request = request
206
- ret_val: WebserviceResponse = self.run(request.headers, request.args)
207
- if isinstance(ret_val, SapioWebserviceResult):
208
- return ret_val.to_result()
209
- return ret_val
210
- except Exception:
211
- print('Error occurred while running webservice custom logic. See traceback.', file=sys.stderr)
212
- traceback.print_exc()
213
- return SapioWebserviceResult("Unexpected error occurred.", 500, True).to_json(), 500
214
-
215
- # noinspection PyMethodOverriding
216
- @abstractmethod
217
- def run(self, headers: Headers, params: MultiDict[str, str]) -> WebserviceResponse:
218
- """
219
- The execution details for this endpoint.
220
-
221
- :param headers: The headers from the request. Can be used like a dictionary.
222
- :param params: The URL parameters from the request.
223
- :return: A response object to send back to the requester.
224
- """
225
- pass
226
-
227
-
228
- class CommonsWebserviceBaseHandler(BaseAuthenticatorClass, ABC):
191
+ class CommonsWebserviceHandler(AbstractWebserviceHandler, ABC):
229
192
  """
230
- A base class for all commons webservice handlers.
193
+ A subclass of AbstractWebservicePostHandler that provides additional quality of life features, including
194
+ authentication of a SapioUser from the request headers, initialization of various commonly used managers, and more.
231
195
  """
232
196
  logger: Logger
233
197
 
@@ -242,6 +206,18 @@ class CommonsWebserviceBaseHandler(BaseAuthenticatorClass, ABC):
242
206
  dt_cache: DataTypeCacheManager
243
207
  rec_handler: RecordHandler
244
208
 
209
+ def run(self, payload: Any, headers: Headers, params: MultiDict[str, str]) -> WebserviceResponse:
210
+ try:
211
+ self.initialize(headers)
212
+ result = self.execute(self.user, payload, headers, params)
213
+ if result is None:
214
+ raise SapioException("Your execute function returned a None result! Don't forget your return statement!")
215
+ return result
216
+ except SapioWebserviceException as e:
217
+ return self.handle_webservice_exception(e)
218
+ except Exception as e:
219
+ return self.handle_unexpected_exception(e)
220
+
245
221
  def initialize(self, headers: Headers) -> None:
246
222
  """
247
223
  A function that can be optionally overridden by your classes to initialize additional instance variables,
@@ -262,6 +238,20 @@ class CommonsWebserviceBaseHandler(BaseAuthenticatorClass, ABC):
262
238
  self.dt_cache = DataTypeCacheManager(self.user)
263
239
  self.rec_handler = RecordHandler(self.user)
264
240
 
241
+ @abstractmethod
242
+ def execute(self, user: SapioUser, payload: Any, headers: Headers, params: MultiDict[str, str]) \
243
+ -> SapioWebserviceResult:
244
+ """
245
+ The execution details for this endpoint.
246
+
247
+ :param user: The SapioUser object authenticated from the request headers.
248
+ :param payload: The JSON payload from the request. Usually a dictionary of strings to Any.
249
+ :param headers: The headers from the request. Can be used like a dictionary.
250
+ :param params: The URL parameters from the request.
251
+ :return: A response object to send back to the requester.
252
+ """
253
+ pass
254
+
265
255
  def handle_webservice_exception(self, e: SapioWebserviceException) -> WebserviceResponse:
266
256
  """
267
257
  Handle a generic exception which isn't one of the handled Sapio exceptions.
@@ -314,73 +304,14 @@ class CommonsWebserviceBaseHandler(BaseAuthenticatorClass, ABC):
314
304
  """
315
305
  Write an info message to the webhook server log. Log destination is stdout.
316
306
  """
317
- self.logger.info(msg)
307
+ # If there's no user, then there's no logger.
308
+ if self.user:
309
+ self.logger.info(msg)
318
310
 
319
311
  def log_error(self, msg: str) -> None:
320
312
  """
321
313
  Write an error message to the webhook server log. Log destination is stderr.
322
314
  """
323
- self.logger.error(msg)
324
-
325
-
326
- class CommonsWebservicePostHandler(AbstractWebservicePostHandler, CommonsWebserviceBaseHandler):
327
- """
328
- A subclass of AbstractWebservicePostHandler that provides additional quality of life features, including
329
- authentication of a SapioUser from the request headers, initialization of various commonly used managers, and more.
330
- """
331
- def run(self, payload: Any, headers: Headers, params: MultiDict[str, str]) -> WebserviceResponse:
332
- try:
333
- self.initialize(headers)
334
- result = self.execute(self.user, payload, headers, params)
335
- if result is None:
336
- raise SapioException("Your execute function returned a None result! Don't forget your return statement!")
337
- return result
338
- except SapioWebserviceException as e:
339
- return self.handle_webservice_exception(e)
340
- except Exception as e:
341
- return self.handle_unexpected_exception(e)
342
-
343
- @abstractmethod
344
- def execute(self, user: SapioUser, payload: Any, headers: Headers, params: MultiDict[str, str]) \
345
- -> SapioWebserviceResult:
346
- """
347
- The execution details for this endpoint.
348
-
349
- :param user: The SapioUser object authenticated from the request headers.
350
- :param payload: The JSON payload from the request. Usually a dictionary of strings to Any.
351
- :param headers: The headers from the request. Can be used like a dictionary.
352
- :param params: The URL parameters from the request.
353
- :return: A response object to send back to the requester.
354
- """
355
- pass
356
-
357
-
358
- class CommonsWebserviceGetHandler(AbstractWebserviceGetHandler, CommonsWebserviceBaseHandler):
359
- """
360
- A subclass of AbstractWebserviceGetHandler that provides additional quality of life features, including
361
- authentication of a SapioUser from the request headers, initialization of various commonly used managers, and more.
362
- """
363
- def run(self, headers: Headers, params: MultiDict[str, str]) -> WebserviceResponse:
364
- try:
365
- self.initialize(headers)
366
- result = self.execute(self.user, headers, params)
367
- if result is None:
368
- raise SapioException("Your execute function returned a None result! Don't forget your return statement!")
369
- return result
370
- except SapioWebserviceException as e:
371
- return self.handle_webservice_exception(e)
372
- except Exception as e:
373
- return self.handle_unexpected_exception(e)
374
-
375
- @abstractmethod
376
- def execute(self, user: SapioUser, headers: Headers, params: MultiDict[str, str]) \
377
- -> SapioWebserviceResult:
378
- """
379
- The execution details for this endpoint.
380
-
381
- :param user: The SapioUser object authenticated from the request headers.
382
- :param headers: The headers from the request. Can be used like a dictionary.
383
- :param params: The URL parameters from the request.
384
- :return: A response object to send back to the requester.
385
- """
386
- pass
315
+ # If there's no user, then there's no logger.
316
+ if self.user:
317
+ self.logger.error(msg)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sapiopycommons
3
- Version: 2024.12.12a382
3
+ Version: 2024.12.13a385
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,6 +1,6 @@
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=nb6cXK8yFq96gtG0Z2NiK-qdNaRh88bavUH-ZoBjh18,67953
3
+ sapiopycommons/callbacks/callback_util.py,sha256=2pGr14f_FVCqeF6dsbYP1e4cOsaUTQyQ7XVwZuUkM_k,67952
4
4
  sapiopycommons/callbacks/field_builder.py,sha256=p2XacN99MuKk3ite8GAqstUMpixqugul2CsC4gB83-o,38620
5
5
  sapiopycommons/chem/IndigoMolecules.py,sha256=slM2y39zZFHc468c366EqR8T-GYJ24UnM9HWAqWFEwQ,3900
6
6
  sapiopycommons/chem/Molecules.py,sha256=9B4sbwbvYs50XHRn0TZiu-D1Oa3pKrI9qE5vNW8zv-U,12464
@@ -52,8 +52,8 @@ sapiopycommons/sftpconnect/sftp_builder.py,sha256=lFK3FeXk-sFLefW0hqY8WGUQDeYiGa
52
52
  sapiopycommons/webhook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
53
  sapiopycommons/webhook/webhook_context.py,sha256=D793uLsb1691SalaPnBUk3rOSxn_hYLhdvkaIxjNXss,1909
54
54
  sapiopycommons/webhook/webhook_handlers.py,sha256=MdsVK4bHffkMNmNWl0_qvu-5Lz8-qGu4Ryi7lZO1BZs,18586
55
- sapiopycommons/webhook/webservice_handlers.py,sha256=AFM2Va9Fpb2BvlFycIUUOdghtGiEv1Ab5jf44yjHSgU,17218
56
- sapiopycommons-2024.12.12a382.dist-info/METADATA,sha256=mlgkT6CXxsqlKU179ENC20t7D2vtc-PBMXHylDjFlLU,3144
57
- sapiopycommons-2024.12.12a382.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
58
- sapiopycommons-2024.12.12a382.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
59
- sapiopycommons-2024.12.12a382.dist-info/RECORD,,
55
+ sapiopycommons/webhook/webservice_handlers.py,sha256=Y5dHx_UFWFuSqaoPL6Re-fsKYRuxvCWZ8bj6KSZ3jfM,14285
56
+ sapiopycommons-2024.12.13a385.dist-info/METADATA,sha256=s27na5Zc8V-FkzNFV7UeyJYmlWL3k-6VVtSiebeEb4Q,3144
57
+ sapiopycommons-2024.12.13a385.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
58
+ sapiopycommons-2024.12.13a385.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
59
+ sapiopycommons-2024.12.13a385.dist-info/RECORD,,