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.
- sapiopycommons/callbacks/callback_util.py +1 -1
- sapiopycommons/webhook/webservice_handlers.py +82 -151
- {sapiopycommons-2024.12.12a382.dist-info → sapiopycommons-2024.12.13a385.dist-info}/METADATA +1 -1
- {sapiopycommons-2024.12.12a382.dist-info → sapiopycommons-2024.12.13a385.dist-info}/RECORD +6 -6
- {sapiopycommons-2024.12.12a382.dist-info → sapiopycommons-2024.12.13a385.dist-info}/WHEEL +0 -0
- {sapiopycommons-2024.12.12a382.dist-info → sapiopycommons-2024.12.13a385.dist-info}/licenses/LICENSE +0 -0
|
@@ -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.
|
|
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
|
|
77
|
+
class AbstractWebserviceHandler(AbstractWebhookHandler):
|
|
77
78
|
"""
|
|
78
|
-
|
|
79
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
{sapiopycommons-2024.12.12a382.dist-info → sapiopycommons-2024.12.13a385.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: sapiopycommons
|
|
3
|
-
Version: 2024.12.
|
|
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=
|
|
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=
|
|
56
|
-
sapiopycommons-2024.12.
|
|
57
|
-
sapiopycommons-2024.12.
|
|
58
|
-
sapiopycommons-2024.12.
|
|
59
|
-
sapiopycommons-2024.12.
|
|
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,,
|
|
File without changes
|
{sapiopycommons-2024.12.12a382.dist-info → sapiopycommons-2024.12.13a385.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|