ul-api-utils 7.8.0__tar.gz → 7.8.3__tar.gz

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 ul-api-utils might be problematic. Click here for more details.

Files changed (147) hide show
  1. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/PKG-INFO +1 -1
  2. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/example/conf.py +1 -0
  3. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/example/routes/api_some.py +13 -1
  4. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/setup.py +4 -1
  5. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/api_resource/api_resource.py +47 -20
  6. ul-api-utils-7.8.3/ul_api_utils/api_resource/api_resource_error_handling.py +21 -0
  7. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/api_resource/api_resource_fn_typing.py +2 -1
  8. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/modules/api_sdk_config.py +1 -1
  9. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils.egg-info/PKG-INFO +1 -1
  10. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils.egg-info/SOURCES.txt +1 -0
  11. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils.egg-info/requires.txt +2 -0
  12. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/LICENSE +0 -0
  13. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/README.md +0 -0
  14. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/example/__init__.py +0 -0
  15. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/example/main.py +0 -0
  16. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/example/models/__init__.py +0 -0
  17. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/example/permissions.py +0 -0
  18. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/example/pure_flask_example.py +0 -0
  19. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/example/rate_limit_load.py +0 -0
  20. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/example/routes/__init__.py +0 -0
  21. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/example/workers/__init__.py +0 -0
  22. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/example/workers/worker.py +0 -0
  23. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/setup.cfg +0 -0
  24. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/__init__.py +0 -0
  25. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/access/__init__.py +0 -0
  26. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/api_resource/__init__.py +0 -0
  27. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/api_resource/api_request.py +0 -0
  28. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/api_resource/api_resource_config.py +0 -0
  29. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/api_resource/api_resource_type.py +0 -0
  30. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/api_resource/api_response.py +0 -0
  31. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/api_resource/api_response_db.py +0 -0
  32. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/api_resource/api_response_payload_alias.py +0 -0
  33. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/api_resource/db_types.py +0 -0
  34. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/api_resource/signature_check.py +0 -0
  35. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/commands/__init__.py +0 -0
  36. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/commands/cmd_enc_keys.py +0 -0
  37. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/commands/cmd_gen_api_user_token.py +0 -0
  38. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/commands/cmd_gen_new_api_user.py +0 -0
  39. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/commands/cmd_generate_api_docs.py +0 -0
  40. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/commands/cmd_start.py +0 -0
  41. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/commands/cmd_worker_start.py +0 -0
  42. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/commands/start/__init__.py +0 -0
  43. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/commands/start/gunicorn.conf.py +0 -0
  44. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/commands/start/wsgi.py +0 -0
  45. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/conf/ul-debugger-main.js +0 -0
  46. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/conf/ul-debugger-ui.js +0 -0
  47. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/conf.py +0 -0
  48. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/const.py +0 -0
  49. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/debug/__init__.py +0 -0
  50. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/debug/debugger.py +0 -0
  51. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/debug/malloc.py +0 -0
  52. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/debug/stat.py +0 -0
  53. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/encrypt/__init__.py +0 -0
  54. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/encrypt/encrypt_decrypt_abstract.py +0 -0
  55. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/encrypt/encrypt_decrypt_aes_xtea.py +0 -0
  56. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/errors.py +0 -0
  57. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/internal_api/__init__.py +0 -0
  58. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/internal_api/__tests__/__init__.py +0 -0
  59. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/internal_api/__tests__/internal_api.py +0 -0
  60. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/internal_api/__tests__/internal_api_content_type.py +0 -0
  61. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/internal_api/internal_api.py +0 -0
  62. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/internal_api/internal_api_check_context.py +0 -0
  63. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/internal_api/internal_api_error.py +0 -0
  64. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/internal_api/internal_api_response.py +0 -0
  65. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/main.py +0 -0
  66. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/modules/__init__.py +0 -0
  67. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/modules/__tests__/__init__.py +0 -0
  68. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/modules/__tests__/test_api_sdk_jwt.py +0 -0
  69. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/modules/api_sdk.py +0 -0
  70. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/modules/api_sdk_jwt.py +0 -0
  71. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/modules/intermediate_state.py +0 -0
  72. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/modules/worker_context.py +0 -0
  73. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/modules/worker_sdk.py +0 -0
  74. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/modules/worker_sdk_config.py +0 -0
  75. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/py.typed +0 -0
  76. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/__init__.py +0 -0
  77. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/caching.py +0 -0
  78. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/debugger_scripts.py +0 -0
  79. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/health_check/__init__.py +0 -0
  80. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/health_check/const.py +0 -0
  81. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/health_check/health_check.py +0 -0
  82. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/health_check/health_check_template.py +0 -0
  83. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/health_check/resource.py +0 -0
  84. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/not_implemented.py +0 -0
  85. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/permissions.py +0 -0
  86. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/rate_limitter.py +0 -0
  87. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/swagger.py +0 -0
  88. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/web_forms/__init__.py +0 -0
  89. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/web_forms/custom_fields/__init__.py +0 -0
  90. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/web_forms/custom_fields/custom_checkbox_select.py +0 -0
  91. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/web_forms/custom_widgets/__init__.py +0 -0
  92. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/web_forms/custom_widgets/custom_select_widget.py +0 -0
  93. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/web_forms/custom_widgets/custom_text_input_widget.py +0 -0
  94. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/resources/web_forms/uni_form.py +0 -0
  95. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/sentry.py +0 -0
  96. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/__init__.py +0 -0
  97. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/__tests__/__init__.py +0 -0
  98. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/__tests__/api_path_version.py +0 -0
  99. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/__tests__/unwrap_typing.py +0 -0
  100. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/api_encoding.py +0 -0
  101. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/api_format.py +0 -0
  102. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/api_method.py +0 -0
  103. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/api_pagination.py +0 -0
  104. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/api_path_version.py +0 -0
  105. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/api_request_info.py +0 -0
  106. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/avro.py +0 -0
  107. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/broker_topics_message_count.py +0 -0
  108. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/cached_per_request.py +0 -0
  109. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/colors.py +0 -0
  110. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/constants.py +0 -0
  111. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/decode_base64.py +0 -0
  112. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/deprecated.py +0 -0
  113. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/flags.py +0 -0
  114. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/flask_swagger_generator/__init__.py +0 -0
  115. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/flask_swagger_generator/conf.py +0 -0
  116. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/flask_swagger_generator/exceptions.py +0 -0
  117. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/flask_swagger_generator/specifiers/__init__.py +0 -0
  118. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/flask_swagger_generator/specifiers/swagger_models.py +0 -0
  119. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/flask_swagger_generator/specifiers/swagger_specifier.py +0 -0
  120. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/flask_swagger_generator/specifiers/swagger_three_specifier.py +0 -0
  121. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/flask_swagger_generator/specifiers/swagger_version.py +0 -0
  122. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/flask_swagger_generator/utils/__init__.py +0 -0
  123. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/flask_swagger_generator/utils/input_type.py +0 -0
  124. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/flask_swagger_generator/utils/parameter_type.py +0 -0
  125. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/flask_swagger_generator/utils/replace_in_dict.py +0 -0
  126. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/flask_swagger_generator/utils/request_type.py +0 -0
  127. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/flask_swagger_generator/utils/schema_type.py +0 -0
  128. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/flask_swagger_generator/utils/security_type.py +0 -0
  129. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/imports.py +0 -0
  130. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/jinja/__init__.py +0 -0
  131. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/jinja/t_url_for.py +0 -0
  132. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/jinja/to_pretty_json.py +0 -0
  133. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/json_encoder.py +0 -0
  134. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/load_modules.py +0 -0
  135. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/token_check.py +0 -0
  136. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/token_check_through_request.py +0 -0
  137. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/unwrap_typing.py +0 -0
  138. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/utils/uuid_converter.py +0 -0
  139. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/validators/__init__.py +0 -0
  140. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/validators/__tests__/__init__.py +0 -0
  141. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/validators/__tests__/test_custom_fields.py +0 -0
  142. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/validators/custom_fields.py +0 -0
  143. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/validators/validate_empty_object.py +0 -0
  144. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils/validators/validate_uuid.py +0 -0
  145. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils.egg-info/dependency_links.txt +0 -0
  146. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils.egg-info/entry_points.txt +0 -0
  147. {ul-api-utils-7.8.0 → ul-api-utils-7.8.3}/ul_api_utils.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ul-api-utils
3
- Version: 7.8.0
3
+ Version: 7.8.3
4
4
  Summary: Python api utils
5
5
  Author: Unic-lab
6
6
  Author-email:
@@ -16,6 +16,7 @@ sdk = ApiSdk(ApiSdkConfig(
16
16
  flask_debugging_plugins=ApiSdkFlaskDebuggingPluginsEnabled(
17
17
  flask_monitoring_dashboard=True,
18
18
  ),
19
+ web_error_template='error.html.jinja2',
19
20
  ))
20
21
 
21
22
 
@@ -12,7 +12,8 @@ from example.permissions import SOME_PERMISSION, SOME_PERMISSION2
12
12
  from ul_api_utils.api_resource.api_request import ApiRequestQuery
13
13
  from ul_api_utils.api_resource.api_resource import ApiResource
14
14
  from ul_api_utils.api_resource.api_resource_config import ApiResourceConfig
15
- from ul_api_utils.api_resource.api_response import FileApiResponse, JsonApiResponsePayload, JsonApiResponse, AnyJsonApiResponse, ProxyJsonApiResponse, HtmlApiResponse
15
+ from ul_api_utils.api_resource.api_response import FileApiResponse, JsonApiResponsePayload, JsonApiResponse, \
16
+ AnyJsonApiResponse, ProxyJsonApiResponse, HtmlApiResponse, EmptyJsonApiResponse
16
17
  from ul_api_utils.errors import Server5XXInternalApiError, NoResultFoundApiError, Client4XXInternalApiError
17
18
  from ul_api_utils.internal_api.internal_api import InternalApi
18
19
  from ul_api_utils.utils.api_encoding import ApiEncoding
@@ -224,6 +225,17 @@ def override(api_resource: ApiResource) -> JsonApiResponse[RespObject]:
224
225
  return api_resource.response_ok(RespObject(now=datetime.now()))
225
226
 
226
227
 
228
+ @sdk.rest_api('GET', '/example-resource-empty', access=sdk.ACCESS_PUBLIC)
229
+ def empty_resp_test(api_resource: ApiResource) -> EmptyJsonApiResponse:
230
+ return api_resource.response_empty_ok()
231
+
232
+
233
+ @sdk.rest_api('POST', '/example-resource-empty-check', access=sdk.ACCESS_PUBLIC)
234
+ def empty_resp_req_test(api_resource: ApiResource) -> EmptyJsonApiResponse:
235
+ internal_api.request_get('/example-resource-empty').check()
236
+ return api_resource.response_empty_ok()
237
+
238
+
227
239
  @sdk.rest_api('POST', '/example-resource-empty-gzip', access=sdk.ACCESS_PUBLIC)
228
240
  def some12(api_resource: ApiResource, body: List[SomeBody]) -> JsonApiResponse[RespObject]:
229
241
  sess = db.session()
@@ -9,7 +9,7 @@ with open(path.join(HERE, 'README.md'), encoding='utf-8') as f:
9
9
 
10
10
  setup(
11
11
  name='ul-api-utils',
12
- version='7.8.0',
12
+ version='7.8.3',
13
13
  description='Python api utils',
14
14
  author='Unic-lab',
15
15
  long_description=long_description,
@@ -78,6 +78,9 @@ setup(
78
78
 
79
79
  "werkzeug==2.3.7",
80
80
 
81
+ "wtforms==3.0.1",
82
+ "wtforms-alchemy==0.18.0",
83
+
81
84
  # "opentelemetry-sdk==1.8.0",
82
85
  # "opentelemetry-api==1.8.0",
83
86
  # "opentelemetry-instrumentation-flask==0.27b0",
@@ -12,6 +12,8 @@ from werkzeug.datastructures import FileStorage
12
12
 
13
13
  from ul_api_utils.access import GLOBAL_PERMISSION__PUBLIC, PermissionDefinition, GLOBAL_PERMISSION__PRIVATE_RT, GLOBAL_PERMISSION__PRIVATE
14
14
  from ul_api_utils.api_resource.api_resource_config import ApiResourceConfig
15
+ from ul_api_utils.api_resource.api_resource_error_handling import WEB_EXCEPTION_HANDLING_PARAMS__MAP, \
16
+ ProcessingExceptionsParams, WEB_UNKNOWN_ERROR_PARAMS
15
17
  from ul_api_utils.api_resource.api_resource_fn_typing import ApiResourceFnTyping
16
18
  from ul_api_utils.api_resource.api_resource_type import ApiResourceType
17
19
  from ul_api_utils.api_resource.api_response import JsonApiResponse, HtmlApiResponse, FileApiResponse, JsonApiResponsePayload, EmptyJsonApiResponse, \
@@ -20,7 +22,8 @@ from ul_api_utils.conf import APPLICATION_ENV, APPLICATION_JWT_PUBLIC_KEY, APPLI
20
22
  from ul_api_utils.const import REQUEST_HEADER__X_FORWARDED_FOR, \
21
23
  RESPONSE_HEADER__WWW_AUTH, OOPS, REQUEST_HEADER__USER_AGENT
22
24
  from ul_api_utils.errors import ValidationListApiError, AccessApiError, NoResultFoundApiError, PermissionDeniedApiError, \
23
- SimpleValidateApiError, ValidateApiError, HasAlreadyExistsApiError, AbstractInternalApiError, InvalidContentTypeError
25
+ SimpleValidateApiError, ValidateApiError, HasAlreadyExistsApiError, AbstractInternalApiError, \
26
+ InvalidContentTypeError
24
27
  from ul_api_utils.internal_api.internal_api_response import InternalApiResponse
25
28
  from ul_api_utils.modules.api_sdk_config import ApiSdkConfig
26
29
  from ul_api_utils.modules.api_sdk_jwt import ApiSdkJwt, JWT_VERSION
@@ -88,6 +91,9 @@ class ApiResource:
88
91
  self._limiter_enabled = limiter_enabled
89
92
  self._db_initialized = db_initialized
90
93
 
94
+ def __repr__(self) -> str:
95
+ return f"ApiResource object. Type: {self._type}, Function: {self._fn_typing.fn.__name__}"
96
+
91
97
  @property
92
98
  def debugger_enabled(self) -> bool:
93
99
  return self._debugger_enabled
@@ -208,30 +214,51 @@ class ApiResource:
208
214
 
209
215
  return JsonApiResponse._internal_use_response_error(self._fn_typing.response_payload_many, 500, [self._mk_error("system-error", str(err))])
210
216
 
211
- def response_web_error(self, err: Exception) -> HtmlApiResponse:
212
- if isinstance(err, PermissionDeniedApiError):
213
- resp = HtmlApiResponse(error=err, content=f"403 Access Not Permitted. {str(err)}", ok=False, status_code=403)
214
- if self.method != ApiMethod.OPTIONS and self._config.http_auth is not None:
215
- resp.headers[RESPONSE_HEADER__WWW_AUTH] = f'{self._config.http_auth.scheme} realm="{self._config.http_auth.realm}"'
216
- return resp
217
- if isinstance(err, AccessApiError):
218
- resp = HtmlApiResponse(error=err, content=f"401 Invalid Token. {str(err)}", ok=False, status_code=401)
217
+ def _generate_web_error_response(
218
+ self,
219
+ happened_exception: Exception,
220
+ default_status_code: int,
221
+ error_message: str,
222
+ apply_auth_headers: bool = False,
223
+ ) -> HtmlApiResponse:
224
+ if hasattr(happened_exception, "status_code"):
225
+ default_status_code = happened_exception.status_code # type: ignore
226
+ assert self._config.web_error_template is not None # only for mypy
227
+ response = HtmlApiResponse(
228
+ content=self.render_template(
229
+ self._config.web_error_template,
230
+ {
231
+ "error_traceback": happened_exception,
232
+ "error_message": error_message,
233
+ "status_code": default_status_code,
234
+ },
235
+ ),
236
+ ok=False,
237
+ status_code=default_status_code,
238
+ )
239
+ if apply_auth_headers:
219
240
  if self.method != ApiMethod.OPTIONS and self._config.http_auth is not None:
220
- resp.headers[RESPONSE_HEADER__WWW_AUTH] = f'{self._config.http_auth.scheme} realm="{self._config.http_auth.realm}"'
221
- return resp
222
- if isinstance(err, ValidateApiError):
223
- return HtmlApiResponse(error=err, content="400 Invalid Request\n Request validation error", ok=False, status_code=400)
241
+ response.headers[RESPONSE_HEADER__WWW_AUTH] = f'{self._config.http_auth.scheme} realm="{self._config.http_auth.realm}"'
242
+ return response
243
+ return response
244
+
245
+ def response_web_error(self, err: Exception) -> HtmlApiResponse:
246
+ if self._config.web_error_template is None:
247
+ return HtmlApiResponse(error=err, content=OOPS, ok=False, status_code=500)
224
248
 
225
249
  if self._db_initialized:
226
250
  from sqlalchemy.exc import NoResultFound as NoResultFoundError
227
251
 
228
- if isinstance(err, NoResultFoundError):
229
- if self._config.not_found_template is None:
230
- return HtmlApiResponse(error=err, content="404 Not Found", ok=False, status_code=404)
231
- return HtmlApiResponse(error=err, content=self.render_template(self._config.not_found_template, {}), ok=False, status_code=404)
232
- if self._config.not_found_template is None:
233
- return HtmlApiResponse(error=err, content=OOPS, ok=False, status_code=500)
234
- return HtmlApiResponse(error=err, content=OOPS, ok=False, status_code=500)
252
+ WEB_EXCEPTION_HANDLING_PARAMS__MAP[NoResultFoundError] = ProcessingExceptionsParams(default_status_code=404, error_message="Not found")
253
+
254
+ error_response_params = WEB_EXCEPTION_HANDLING_PARAMS__MAP.get(type(err), WEB_UNKNOWN_ERROR_PARAMS)
255
+
256
+ return self._generate_web_error_response(
257
+ happened_exception=err,
258
+ default_status_code=error_response_params.default_status_code,
259
+ error_message=error_response_params.error_message,
260
+ apply_auth_headers=error_response_params.apply_auth_headers,
261
+ )
235
262
 
236
263
  def render_template(self, template_name: str, data: Dict[str, Any]) -> str:
237
264
  return render_template(
@@ -0,0 +1,21 @@
1
+ from typing import NamedTuple, Dict, Type
2
+
3
+ from ul_api_utils.errors import PermissionDeniedApiError, AccessApiError, ValidateApiError, \
4
+ Server5XXInternalApiError, Client4XXInternalApiError
5
+
6
+
7
+ class ProcessingExceptionsParams(NamedTuple):
8
+ default_status_code: int
9
+ error_message: str
10
+ apply_auth_headers: bool = False
11
+
12
+
13
+ WEB_EXCEPTION_HANDLING_PARAMS__MAP: Dict[Type[Exception], ProcessingExceptionsParams] = {
14
+ PermissionDeniedApiError: ProcessingExceptionsParams(default_status_code=403, error_message="Access not permitted", apply_auth_headers=True),
15
+ AccessApiError: ProcessingExceptionsParams(default_status_code=401, error_message="Invalid token", apply_auth_headers=True),
16
+ ValidateApiError: ProcessingExceptionsParams(default_status_code=400, error_message="Request validation error"),
17
+ Server5XXInternalApiError: ProcessingExceptionsParams(default_status_code=500, error_message="Server error"),
18
+ Client4XXInternalApiError: ProcessingExceptionsParams(default_status_code=400, error_message="Request validation error"),
19
+ }
20
+
21
+ WEB_UNKNOWN_ERROR_PARAMS = ProcessingExceptionsParams(default_status_code=500, error_message="Unknown error")
@@ -154,7 +154,8 @@ class ApiResourceFnTyping(NamedTuple):
154
154
  return kwargs, errors
155
155
  body = self._get_body()
156
156
  try:
157
- kwargs['body'] = [set_model(self.body_typing, fields) for fields in _body_list(body)] if self.request_body_many else set_model(self.body_typing, body) # type: ignore
157
+ expected_typing: Type[BaseModel | List[BaseModel]] = List[self.body_typing] if self.request_body_many else self.body_typing # type: ignore
158
+ kwargs['body'] = parse_obj_as(expected_typing, body)
158
159
  except ValidationError as ve:
159
160
  if self.has_body_validation_error:
160
161
  kwargs['body_validation_error'] = ve
@@ -42,7 +42,7 @@ class ApiSdkConfig(BaseModel):
42
42
 
43
43
  static_url_path: Optional[str] = None
44
44
 
45
- not_found_template: Optional[str] = None
45
+ web_error_template: Optional[str] = None
46
46
 
47
47
  rate_limit: Union[str, List[str]] = '100/minute' # [count (int)] [per|/] [second|minute|hour|day|month|year][s]
48
48
  rate_limit_storage_uri: str = '' # supports url of redis, memcached, mongodb
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ul-api-utils
3
- Version: 7.8.0
3
+ Version: 7.8.3
4
4
  Summary: Python api utils
5
5
  Author: Unic-lab
6
6
  Author-email:
@@ -30,6 +30,7 @@ ul_api_utils/api_resource/__init__.py
30
30
  ul_api_utils/api_resource/api_request.py
31
31
  ul_api_utils/api_resource/api_resource.py
32
32
  ul_api_utils/api_resource/api_resource_config.py
33
+ ul_api_utils/api_resource/api_resource_error_handling.py
33
34
  ul_api_utils/api_resource/api_resource_fn_typing.py
34
35
  ul_api_utils/api_resource/api_resource_type.py
35
36
  ul_api_utils/api_resource/api_response.py
@@ -23,3 +23,5 @@ sentry-sdk[flask]==1.9.2
23
23
  types-requests==2.28.8
24
24
  types-jinja2==2.11.9
25
25
  werkzeug==2.3.7
26
+ wtforms==3.0.1
27
+ wtforms-alchemy==0.18.0
File without changes
File without changes
File without changes