ul-api-utils 8.0.1a0__tar.gz → 8.0.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.
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/PKG-INFO +1 -1
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/example/routes/api_some.py +1 -1
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/setup.py +9 -11
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/access/__init__.py +2 -3
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/api_resource/api_request.py +3 -2
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/api_resource/api_resource.py +6 -5
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/api_resource/api_resource_config.py +5 -4
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/api_resource/api_resource_fn_typing.py +13 -11
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/api_resource/api_response.py +11 -11
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/api_resource/signature_check.py +6 -6
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/commands/cmd_enc_keys.py +5 -5
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/commands/cmd_gen_new_api_user.py +1 -1
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/commands/cmd_generate_api_docs.py +1 -1
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/commands/cmd_start.py +2 -2
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/debug/debugger.py +1 -1
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/errors.py +14 -8
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/internal_api/internal_api_error.py +6 -4
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/modules/api_sdk.py +2 -2
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/modules/api_sdk_config.py +6 -6
- ul-api-utils-8.0.3/ul_api_utils/modules/worker_sdk_config.py +13 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/caching.py +6 -6
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/debugger_scripts.py +1 -1
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/health_check/health_check.py +9 -11
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/flask_swagger_generator/specifiers/swagger_models.py +2 -2
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/flask_swagger_generator/specifiers/swagger_three_specifier.py +5 -6
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/json_encoder.py +5 -5
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/memory_db/repository.py +4 -4
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/unwrap_typing.py +2 -2
- ul-api-utils-8.0.3/ul_api_utils/validators/custom_fields.py +63 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils.egg-info/PKG-INFO +1 -1
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils.egg-info/requires.txt +6 -8
- ul-api-utils-8.0.1a0/ul_api_utils/modules/worker_sdk_config.py +0 -13
- ul-api-utils-8.0.1a0/ul_api_utils/validators/custom_fields.py +0 -114
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/LICENSE +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/README.md +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/example/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/example/conf.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/example/main.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/example/models/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/example/permissions.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/example/pure_flask_example.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/example/rate_limit_load.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/example/redis_repository.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/example/routes/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/example/sockets/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/example/sockets/on_connect.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/example/sockets/on_disconnect.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/example/sockets/on_json.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/example/sockets/on_message.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/example/sockets/on_open.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/example/workers/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/example/workers/worker.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/setup.cfg +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/api_resource/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/api_resource/api_resource_error_handling.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/api_resource/api_resource_type.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/api_resource/api_response_db.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/api_resource/api_response_payload_alias.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/api_resource/db_types.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/commands/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/commands/cmd_gen_api_user_token.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/commands/cmd_worker_start.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/commands/start/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/commands/start/gunicorn.conf.local.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/commands/start/gunicorn.conf.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/commands/start/wsgi.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/conf/ul-debugger-main.js +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/conf/ul-debugger-ui.js +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/conf.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/const.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/debug/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/debug/malloc.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/debug/stat.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/encrypt/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/encrypt/encrypt_decrypt_abstract.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/encrypt/encrypt_decrypt_aes_xtea.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/internal_api/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/internal_api/__tests__/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/internal_api/__tests__/internal_api.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/internal_api/__tests__/internal_api_content_type.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/internal_api/internal_api.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/internal_api/internal_api_check_context.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/internal_api/internal_api_response.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/main.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/modules/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/modules/__tests__/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/modules/__tests__/test_api_sdk_jwt.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/modules/api_sdk_jwt.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/modules/intermediate_state.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/modules/worker_context.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/modules/worker_sdk.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/py.typed +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/health_check/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/health_check/const.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/health_check/health_check_template.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/health_check/resource.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/not_implemented.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/permissions.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/rate_limitter.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/socketio.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/swagger.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/web_forms/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/web_forms/custom_fields/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/web_forms/custom_fields/custom_checkbox_select.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/web_forms/custom_widgets/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/web_forms/custom_widgets/custom_select_widget.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/web_forms/custom_widgets/custom_text_input_widget.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/web_forms/uni_form.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/sentry.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/__tests__/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/__tests__/api_path_version.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/__tests__/unwrap_typing.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/api_encoding.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/api_format.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/api_method.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/api_pagination.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/api_path_version.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/api_request_info.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/avro.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/broker_topics_message_count.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/cached_per_request.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/colors.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/constants.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/decode_base64.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/deprecated.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/flags.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/flask_swagger_generator/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/flask_swagger_generator/conf.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/flask_swagger_generator/exceptions.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/flask_swagger_generator/specifiers/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/flask_swagger_generator/specifiers/swagger_specifier.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/flask_swagger_generator/specifiers/swagger_version.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/flask_swagger_generator/utils/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/flask_swagger_generator/utils/input_type.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/flask_swagger_generator/utils/parameter_type.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/flask_swagger_generator/utils/replace_in_dict.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/flask_swagger_generator/utils/request_type.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/flask_swagger_generator/utils/schema_type.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/flask_swagger_generator/utils/security_type.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/imports.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/instance_checks.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/jinja/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/jinja/t_url_for.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/jinja/to_pretty_json.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/load_modules.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/memory_db/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/memory_db/__tests__/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/memory_db/errors.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/token_check.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/token_check_through_request.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/utils/uuid_converter.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/validators/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/validators/__tests__/__init__.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/validators/__tests__/test_custom_fields.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/validators/validate_empty_object.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/validators/validate_uuid.py +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils.egg-info/SOURCES.txt +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils.egg-info/dependency_links.txt +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils.egg-info/entry_points.txt +0 -0
- {ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils.egg-info/top_level.txt +0 -0
|
@@ -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='8.0.
|
|
12
|
+
version='8.0.3',
|
|
13
13
|
description='Python api utils',
|
|
14
14
|
author='Unic-lab',
|
|
15
15
|
long_description=long_description,
|
|
@@ -49,13 +49,11 @@ setup(
|
|
|
49
49
|
platforms='any',
|
|
50
50
|
install_requires=[
|
|
51
51
|
"unipipeline==1.9.4",
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"flask==
|
|
56
|
-
"flask-
|
|
57
|
-
"flask-limiter==3.10.1",
|
|
58
|
-
"flask-caching==2.3.0",
|
|
52
|
+
"jinja2==3.1.2",
|
|
53
|
+
"flask==2.1.3",
|
|
54
|
+
"flask-wtf==1.0.1",
|
|
55
|
+
"flask-limiter==2.5.1",
|
|
56
|
+
"flask-caching==2.1.0",
|
|
59
57
|
"flask-swagger-ui==4.11.1",
|
|
60
58
|
"flask-monitoringdashboard==3.1.2",
|
|
61
59
|
"pycryptodome==3.15.0",
|
|
@@ -78,7 +76,7 @@ setup(
|
|
|
78
76
|
"types-requests==2.28.8",
|
|
79
77
|
"types-jinja2==2.11.9",
|
|
80
78
|
"xlsxwriter==3.2.0",
|
|
81
|
-
"werkzeug==3.
|
|
79
|
+
"werkzeug==2.3.7",
|
|
82
80
|
"frozendict==2.4.4",
|
|
83
81
|
"wtforms==3.0.1",
|
|
84
82
|
"wtforms-alchemy==0.18.0",
|
|
@@ -90,7 +88,7 @@ setup(
|
|
|
90
88
|
# "opentelemetry-instrumentation-requests==0.27b0",
|
|
91
89
|
# "opentelemetry-exporter-jaeger==1.8.0",
|
|
92
90
|
# "opentelemetry-instrumentation-sqlalchemy==0.27b0",
|
|
93
|
-
# "ul-db-utils==3.3.
|
|
94
|
-
# "ul-py-tool==1.
|
|
91
|
+
# "ul-db-utils==3.3.7", # ACTUALIZE, BUT DO NOT UNCOMMENT PLEASE
|
|
92
|
+
# "ul-py-tool==2.1.2", # ACTUALIZE, BUT DO NOT UNCOMMENT PLEASE
|
|
95
93
|
],
|
|
96
94
|
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import re
|
|
2
2
|
from typing import Dict, List, Union, Any, Iterable
|
|
3
3
|
|
|
4
|
-
from pydantic import BaseModel
|
|
4
|
+
from pydantic import ConfigDict, BaseModel
|
|
5
5
|
|
|
6
6
|
from ul_api_utils.conf import APPLICATION_F
|
|
7
7
|
|
|
@@ -13,8 +13,7 @@ class PermissionDefinition(BaseModel):
|
|
|
13
13
|
category: str
|
|
14
14
|
flags: str = ''
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
allow_mutation: bool = False
|
|
16
|
+
model_config = ConfigDict(frozen=True)
|
|
18
17
|
|
|
19
18
|
|
|
20
19
|
class PermissionRegistry:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from typing import NamedTuple, Iterable, Any, List, Tuple, Dict, Optional
|
|
3
3
|
|
|
4
|
-
from pydantic import
|
|
4
|
+
from pydantic import model_validator, BaseModel
|
|
5
5
|
|
|
6
6
|
from ul_api_utils.errors import SimpleValidateApiError
|
|
7
7
|
from ul_api_utils.utils.api_pagination import ApiPagination
|
|
@@ -42,7 +42,8 @@ class ApiRequestQuery(BaseModel):
|
|
|
42
42
|
offset: Optional[int] = None
|
|
43
43
|
page: Optional[int] = None
|
|
44
44
|
|
|
45
|
-
@
|
|
45
|
+
@model_validator(mode="before")
|
|
46
|
+
@classmethod
|
|
46
47
|
def validate_empty_values(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
|
47
48
|
vals = dict()
|
|
48
49
|
for k, v in values.items():
|
|
@@ -7,7 +7,7 @@ from tempfile import NamedTemporaryFile
|
|
|
7
7
|
from typing import List, Dict, Any, Optional, Tuple, Union, BinaryIO, Mapping, TypeVar, Callable, Set, TYPE_CHECKING
|
|
8
8
|
|
|
9
9
|
from flask import render_template, request
|
|
10
|
-
from
|
|
10
|
+
from pydantic_core import PydanticCustomError
|
|
11
11
|
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
|
|
@@ -170,12 +170,13 @@ class ApiResource:
|
|
|
170
170
|
return JsonApiResponse._internal_use_response_error(self._fn_typing.response_payload_many, 401, [self._mk_error("access-error", str(err), False)])
|
|
171
171
|
if isinstance(err, SimpleValidateApiError):
|
|
172
172
|
return JsonApiResponse._internal_use_response_error(self._fn_typing.response_payload_many, 400, [self._mk_error("validation-error", str(err), False)])
|
|
173
|
-
if isinstance(err, (
|
|
173
|
+
if isinstance(err, (PydanticCustomError, ValidateApiError)):
|
|
174
174
|
return JsonApiResponse._internal_use_response_error(self._fn_typing.response_payload_many, 400, [{
|
|
175
|
-
"error_kind": f"value_error.{err.code}",
|
|
175
|
+
"error_kind": f"value_error.{err.code}", # type: ignore
|
|
176
176
|
"error_location": err.location, # type: ignore
|
|
177
177
|
"error_type": "body-validation-error",
|
|
178
|
-
"error_message": f"{err.msg_template}",
|
|
178
|
+
"error_message": f"{err.msg_template}", # type: ignore
|
|
179
|
+
"error_input": err.input, # type: ignore
|
|
179
180
|
}])
|
|
180
181
|
if isinstance(err, NoResultFoundApiError):
|
|
181
182
|
return JsonApiResponse._internal_use_response_error(self._fn_typing.response_payload_many, 404, [
|
|
@@ -222,7 +223,7 @@ class ApiResource:
|
|
|
222
223
|
apply_auth_headers: bool = False,
|
|
223
224
|
) -> HtmlApiResponse:
|
|
224
225
|
if hasattr(happened_exception, "status_code"):
|
|
225
|
-
default_status_code = happened_exception.status_code
|
|
226
|
+
default_status_code = happened_exception.status_code
|
|
226
227
|
assert self._config.web_error_template is not None # only for mypy
|
|
227
228
|
response = HtmlApiResponse(
|
|
228
229
|
content=self.render_template(
|
{ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/api_resource/api_resource_config.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import Optional, Callable, Tuple
|
|
2
2
|
|
|
3
|
-
from pydantic import
|
|
3
|
+
from pydantic import ConfigDict, BaseModel
|
|
4
4
|
|
|
5
5
|
from ul_api_utils.api_resource.api_response import ApiResponse
|
|
6
6
|
from werkzeug import Response as BaseResponse
|
|
@@ -14,6 +14,7 @@ class ApiResourceConfig(BaseModel):
|
|
|
14
14
|
exc_handler_endpoint: Optional[Callable[[Exception], Optional[ApiResponse]]] = None
|
|
15
15
|
override_flask_response: Optional[Callable[[Tuple[BaseResponse, int]], Tuple[BaseResponse, int]]] = None
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
extra
|
|
19
|
-
|
|
17
|
+
model_config = ConfigDict(
|
|
18
|
+
extra="forbid",
|
|
19
|
+
frozen=True,
|
|
20
|
+
)
|
{ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/api_resource/api_resource_fn_typing.py
RENAMED
|
@@ -2,8 +2,9 @@ import inspect
|
|
|
2
2
|
from typing import NamedTuple, Any, Callable, Optional, List, Dict, Type, Tuple, TYPE_CHECKING
|
|
3
3
|
|
|
4
4
|
from flask import request
|
|
5
|
-
from pydantic import BaseModel, ValidationError,
|
|
5
|
+
from pydantic import BaseModel, ValidationError, validate_call, TypeAdapter
|
|
6
6
|
from pydantic.utils import deep_update
|
|
7
|
+
from pydantic_core import ErrorDetails
|
|
7
8
|
|
|
8
9
|
from ul_api_utils.api_resource.api_request import ApiRequestQuery
|
|
9
10
|
from ul_api_utils.api_resource.api_resource_type import ApiResourceType
|
|
@@ -19,23 +20,23 @@ from ul_api_utils.utils.unwrap_typing import UnwrappedOptionalObjOrListOfObj
|
|
|
19
20
|
|
|
20
21
|
if TYPE_CHECKING:
|
|
21
22
|
from ul_api_utils.api_resource.api_resource import ApiResource
|
|
22
|
-
from pydantic.error_wrappers import ErrorDict
|
|
23
23
|
|
|
24
24
|
FN_SYSTEM_PROPS = {"api_resource", "query", "body", "return", "body_validation_error", "query_validation_error"}
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
def _patch_errors(dest_errors: List[Dict[str, str]], errors: List[
|
|
27
|
+
def _patch_errors(dest_errors: List[Dict[str, str]], errors: List[ErrorDetails], kind: str) -> List[Dict[str, str]]:
|
|
28
28
|
for error in errors:
|
|
29
29
|
dest_errors.append({
|
|
30
30
|
"error_type": kind,
|
|
31
31
|
"error_message": error['msg'],
|
|
32
32
|
"error_location": error["loc"], # type: ignore
|
|
33
33
|
"error_kind": error["type"],
|
|
34
|
+
"error_input": error["input"],
|
|
34
35
|
})
|
|
35
36
|
return dest_errors
|
|
36
37
|
|
|
37
38
|
|
|
38
|
-
@
|
|
39
|
+
@validate_call()
|
|
39
40
|
def _body_list(root: List[Dict[str, Any]]) -> List[Any]: # only for pydantic validation
|
|
40
41
|
return root
|
|
41
42
|
|
|
@@ -72,12 +73,12 @@ class ApiResourceFnTyping(NamedTuple):
|
|
|
72
73
|
if self.request_body_optional:
|
|
73
74
|
if self.request_body_many:
|
|
74
75
|
class BodyTypingOptList(BaseModel):
|
|
75
|
-
__root__: Optional[List[body_typing]] # type: ignore
|
|
76
|
+
__root__: Optional[List[body_typing]] = None # type: ignore
|
|
76
77
|
|
|
77
78
|
return BodyTypingOptList
|
|
78
79
|
|
|
79
80
|
class BodyTypingOpt(BaseModel):
|
|
80
|
-
__root__: Optional[body_typing] # type: ignore
|
|
81
|
+
__root__: Optional[body_typing] = None # type: ignore
|
|
81
82
|
return BodyTypingOpt
|
|
82
83
|
|
|
83
84
|
if self.request_body_many:
|
|
@@ -154,8 +155,7 @@ class ApiResourceFnTyping(NamedTuple):
|
|
|
154
155
|
return kwargs, errors
|
|
155
156
|
body = self._get_body()
|
|
156
157
|
try:
|
|
157
|
-
|
|
158
|
-
kwargs['body'] = parse_obj_as(expected_typing, body)
|
|
158
|
+
kwargs['body'] = TypeAdapter(Type[BaseModel | List[BaseModel]]).validate_python(body)
|
|
159
159
|
except ValidationError as ve:
|
|
160
160
|
if self.has_body_validation_error:
|
|
161
161
|
kwargs['body_validation_error'] = ve
|
|
@@ -167,9 +167,11 @@ class ApiResourceFnTyping(NamedTuple):
|
|
|
167
167
|
if self.query_typing is None:
|
|
168
168
|
return kwargs, errors
|
|
169
169
|
try:
|
|
170
|
+
is_complex_field = lambda field: field.annotation and not isinstance(field.annotation, (str, int, float, bool, type(None))) # noqa: E731
|
|
170
171
|
kwargs["query"] = set_model(self.query_typing, {
|
|
171
172
|
**request.args.to_dict(),
|
|
172
|
-
**{key: value for key, value in request.args.to_dict(flat=False).items()
|
|
173
|
+
**{key: value for key, value in request.args.to_dict(flat=False).items()
|
|
174
|
+
if key in self.query_typing.model_fields and is_complex_field(self.query_typing.model_fields[key])},
|
|
173
175
|
})
|
|
174
176
|
except ValidationError as ve:
|
|
175
177
|
if self.has_query_validation_error:
|
|
@@ -182,7 +184,7 @@ class ApiResourceFnTyping(NamedTuple):
|
|
|
182
184
|
loc_err = []
|
|
183
185
|
for name, type_ in self.signatures_typing:
|
|
184
186
|
try:
|
|
185
|
-
kwargs[name] =
|
|
187
|
+
kwargs[name] = TypeAdapter(type_).validate_python(kwargs.get(name))
|
|
186
188
|
except ValidationError as e:
|
|
187
189
|
err = e.errors()[0]
|
|
188
190
|
err["loc"] = [name] # type: ignore
|
|
@@ -246,7 +248,7 @@ class ApiResourceFnTyping(NamedTuple):
|
|
|
246
248
|
ret_payload_res = get_typing(return_payload_typing)
|
|
247
249
|
if len(ret_payload_res) > 1:
|
|
248
250
|
return_payload_typing = ret_payload_res[1]
|
|
249
|
-
if ret_payload_res[0] != list:
|
|
251
|
+
if ret_payload_res[0] != list: # noqa: E721
|
|
250
252
|
raise TypeError(f'{fn.__name__} :: invalid response payload type wrapper. only List is supported')
|
|
251
253
|
response_many = True
|
|
252
254
|
|
|
@@ -4,8 +4,8 @@ from types import NoneType
|
|
|
4
4
|
from typing import TypeVar, Generic, List, Optional, Dict, Any, Callable, Union, BinaryIO, Tuple, Type
|
|
5
5
|
import msgpack
|
|
6
6
|
from flask import jsonify, send_file, redirect, Response, request
|
|
7
|
-
from pydantic import
|
|
8
|
-
from pydantic
|
|
7
|
+
from pydantic import ConfigDict, RootModel
|
|
8
|
+
from pydantic import BaseModel
|
|
9
9
|
from werkzeug import Response as BaseResponse
|
|
10
10
|
|
|
11
11
|
from ul_api_utils.api_resource.db_types import TPayloadInputUnion
|
|
@@ -28,9 +28,10 @@ class ApiResponse(BaseModel):
|
|
|
28
28
|
status_code: int
|
|
29
29
|
headers: Dict[str, str] = {}
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
extra
|
|
33
|
-
arbitrary_types_allowed
|
|
31
|
+
model_config = ConfigDict(
|
|
32
|
+
extra="forbid",
|
|
33
|
+
arbitrary_types_allowed=True
|
|
34
|
+
)
|
|
34
35
|
|
|
35
36
|
@classmethod
|
|
36
37
|
def _internal_use__mk_schema(cls, inner_type: Optional[Type[BaseModel]]) -> Type[BaseModel]:
|
|
@@ -87,7 +88,7 @@ class HtmlApiResponse(ApiResponse):
|
|
|
87
88
|
|
|
88
89
|
class FileApiResponse(ApiResponse):
|
|
89
90
|
file_path: Union[str, BinaryIO, io.BytesIO]
|
|
90
|
-
mimetype: Optional[str] # it will be auto-detected by extension if mimetype==None
|
|
91
|
+
mimetype: Optional[str] = None # it will be auto-detected by extension if mimetype==None
|
|
91
92
|
as_attachment: bool = False
|
|
92
93
|
download_name: Optional[str] = None
|
|
93
94
|
attachment_filename: Optional[str] = None
|
|
@@ -139,8 +140,7 @@ class EmptyJsonApiResponse(ApiResponse):
|
|
|
139
140
|
|
|
140
141
|
|
|
141
142
|
class JsonApiResponsePayload(BaseModel):
|
|
142
|
-
|
|
143
|
-
extra = Extra.ignore
|
|
143
|
+
model_config = ConfigDict(extra="ignore")
|
|
144
144
|
|
|
145
145
|
|
|
146
146
|
TResultPayloadUnion = Union[None, Dict[str, Any], JsonApiResponsePayload, List[JsonApiResponsePayload], List[Dict[str, Any]]]
|
|
@@ -153,8 +153,8 @@ TPayloadTotalUnion = Union[
|
|
|
153
153
|
]
|
|
154
154
|
|
|
155
155
|
|
|
156
|
-
class DictJsonApiResponsePayload(
|
|
157
|
-
|
|
156
|
+
class DictJsonApiResponsePayload(RootModel[Dict[str, Any]]):
|
|
157
|
+
pass
|
|
158
158
|
|
|
159
159
|
|
|
160
160
|
TProxyPayload = TypeVar('TProxyPayload', bound=Union[JsonApiResponsePayload, List[JsonApiResponsePayload], None])
|
|
@@ -208,7 +208,7 @@ class AnyJsonApiResponse(ApiResponse):
|
|
|
208
208
|
def _internal_use__mk_schema(cls, inner_type: Optional[Type[BaseModel]]) -> Type[BaseModel]:
|
|
209
209
|
class _ResponseStd(BaseModel):
|
|
210
210
|
ok: bool
|
|
211
|
-
payload: Any
|
|
211
|
+
payload: Any = None
|
|
212
212
|
errors: List[Dict[str, Any]]
|
|
213
213
|
total_count: Optional[int] = None
|
|
214
214
|
count: Optional[int] = None
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import Any, Dict, Optional, Union, Type, TypeVar, Tuple, TYPE_CHECKING
|
|
2
2
|
from typing import _GenericAlias # type: ignore
|
|
3
3
|
|
|
4
|
-
from pydantic import BaseModel
|
|
4
|
+
from pydantic import BaseModel, RootModel
|
|
5
5
|
|
|
6
6
|
from ul_api_utils.utils.json_encoder import to_dict
|
|
7
7
|
|
|
@@ -14,8 +14,8 @@ TPydanticModel = TypeVar('TPydanticModel', bound=BaseModel)
|
|
|
14
14
|
def set_model(model: Type[TPydanticModel], data: Union[Dict[str, Any], TPydanticModel]) -> TPydanticModel:
|
|
15
15
|
if isinstance(data, model):
|
|
16
16
|
return data
|
|
17
|
-
if
|
|
18
|
-
return model(
|
|
17
|
+
if issubclass(model, RootModel):
|
|
18
|
+
return model(data).root
|
|
19
19
|
assert isinstance(data, dict), f'data must be dict. "{type(data).__name__}" was given'
|
|
20
20
|
return model(**data)
|
|
21
21
|
|
|
@@ -26,13 +26,13 @@ def set_model_dictable(model: Type[TPydanticModel], data: 'TDictable') -> Option
|
|
|
26
26
|
res: Optional[Dict[str, Any]] = to_dict(data)
|
|
27
27
|
if res is None:
|
|
28
28
|
return None
|
|
29
|
-
if
|
|
30
|
-
return model(
|
|
29
|
+
if issubclass(model, RootModel):
|
|
30
|
+
return model(data).root
|
|
31
31
|
return model(**res)
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
def get_typing(t: Type[Any]) -> Tuple[Type[Any], ...]:
|
|
35
|
-
if type(t) == _GenericAlias:
|
|
35
|
+
if type(t) == _GenericAlias: # noqa: E721
|
|
36
36
|
src_t = t
|
|
37
37
|
return src_t.__origin__, *(it for it in src_t.__args__)
|
|
38
38
|
return t, # noqa: C818
|
|
@@ -27,11 +27,11 @@ class CmdEncKeys(Cmd):
|
|
|
27
27
|
name: str
|
|
28
28
|
services: List[str]
|
|
29
29
|
dir: str
|
|
30
|
-
permissions_module: Optional[str]
|
|
31
|
-
permissions_uri: Optional[str]
|
|
32
|
-
env: Optional[str]
|
|
33
|
-
org_id: Optional[UUID]
|
|
34
|
-
user_id: Optional[UUID]
|
|
30
|
+
permissions_module: Optional[str] = None
|
|
31
|
+
permissions_uri: Optional[str] = None
|
|
32
|
+
env: Optional[str] = None
|
|
33
|
+
org_id: Optional[UUID] = None
|
|
34
|
+
user_id: Optional[UUID] = None
|
|
35
35
|
|
|
36
36
|
@staticmethod
|
|
37
37
|
def add_parser_args(parser: argparse.ArgumentParser) -> None:
|
|
@@ -29,7 +29,7 @@ class CmdGenerateNewApiUser(Cmd):
|
|
|
29
29
|
uri_auth_api: str
|
|
30
30
|
internal_access_key: str
|
|
31
31
|
permissions_list: List[int]
|
|
32
|
-
permissions_uri: Optional[str]
|
|
32
|
+
permissions_uri: Optional[str] = None
|
|
33
33
|
api_user_name: str
|
|
34
34
|
api_user_note: str
|
|
35
35
|
api_user_date_exp: datetime
|
|
@@ -85,7 +85,7 @@ class CmdGenApiFunctionDocumentation(Cmd):
|
|
|
85
85
|
|
|
86
86
|
@staticmethod
|
|
87
87
|
def load_functions(directory: str) -> Dict[str, Callable[..., Any]]:
|
|
88
|
-
function_name_object__map = {}
|
|
88
|
+
function_name_object__map: dict[str, Callable[..., Any]] = {}
|
|
89
89
|
for root, _dirs, files in os.walk(directory):
|
|
90
90
|
for file in files:
|
|
91
91
|
py_postfix = '.py'
|
|
@@ -29,8 +29,8 @@ class CmdStart(Cmd):
|
|
|
29
29
|
max_requests_jitter: int
|
|
30
30
|
worker_class: str
|
|
31
31
|
freeze_gc: bool
|
|
32
|
-
statsd_endpoint: Optional[str]
|
|
33
|
-
statsd_prefix: Optional[str]
|
|
32
|
+
statsd_endpoint: Optional[str] = None
|
|
33
|
+
statsd_prefix: Optional[str] = None
|
|
34
34
|
|
|
35
35
|
@property
|
|
36
36
|
def app_rel_dir(self) -> str:
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
from typing import Dict, List
|
|
2
|
-
|
|
3
|
-
from pydantic import PydanticValueError
|
|
1
|
+
from typing import Dict, List, Any
|
|
4
2
|
|
|
5
3
|
from ul_api_utils.internal_api.internal_api_error import InternalApiResponseErrorObj
|
|
6
4
|
|
|
@@ -94,7 +92,7 @@ class ResponseStatusAbstractInternalApiError(ResponseAbstractInternalApiError):
|
|
|
94
92
|
def __init__(self, status_code: int, errors: List[InternalApiResponseErrorObj]) -> None:
|
|
95
93
|
assert isinstance(status_code, int), f'status_code must be int. "{type(status_code).__name__}" was given'
|
|
96
94
|
assert status_code >= 400
|
|
97
|
-
super(ResponseStatusAbstractInternalApiError, self).__init__(f'status code error :: {status_code} :: {[e.
|
|
95
|
+
super(ResponseStatusAbstractInternalApiError, self).__init__(f'status code error :: {status_code} :: {[e.model_dump() for e in errors]}')
|
|
98
96
|
self.status_code = status_code
|
|
99
97
|
self.errors = errors
|
|
100
98
|
|
|
@@ -137,10 +135,18 @@ class ValidationListApiError(UserAbstractApiError):
|
|
|
137
135
|
self.errors = errors
|
|
138
136
|
|
|
139
137
|
|
|
140
|
-
class ValidateApiError(
|
|
141
|
-
code =
|
|
142
|
-
|
|
143
|
-
|
|
138
|
+
class ValidateApiError(UserAbstractApiError):
|
|
139
|
+
def __init__(self, code: str, location: list[Any], msg_template: str, input: Any = None):
|
|
140
|
+
self.code = code
|
|
141
|
+
self.location = location
|
|
142
|
+
self.msg_template = msg_template
|
|
143
|
+
self.input = input
|
|
144
|
+
|
|
145
|
+
def __str__(self): # type: ignore
|
|
146
|
+
return (
|
|
147
|
+
f"{self.msg_template} (code={self.code}, location={self.location}, "
|
|
148
|
+
f"input={self.input})"
|
|
149
|
+
)
|
|
144
150
|
|
|
145
151
|
|
|
146
152
|
class SimpleValidateApiError(UserAbstractApiError):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import Optional, Any, Dict, List, Tuple, Union
|
|
2
2
|
|
|
3
|
-
from pydantic import
|
|
3
|
+
from pydantic import ConfigDict, BaseModel
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class InternalApiResponseErrorObj(BaseModel):
|
|
@@ -8,8 +8,10 @@ class InternalApiResponseErrorObj(BaseModel):
|
|
|
8
8
|
error_message: str
|
|
9
9
|
error_location: Optional[Union[List[str], str, Tuple[str, ...]]] = None
|
|
10
10
|
error_kind: Optional[str] = None
|
|
11
|
+
error_input: Optional[Any] = None
|
|
11
12
|
other: Optional[Dict[str, Any]] = None
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
extra
|
|
15
|
-
|
|
14
|
+
model_config = ConfigDict(
|
|
15
|
+
extra="ignore",
|
|
16
|
+
frozen=True,
|
|
17
|
+
)
|
|
@@ -150,7 +150,7 @@ class ApiSdk:
|
|
|
150
150
|
|
|
151
151
|
if db_config is not None and type(db_config).__name__ == 'DbConfig':
|
|
152
152
|
from ul_db_utils.utils.waiting_for_postgres import waiting_for_postgres
|
|
153
|
-
from ul_db_utils.modules.postgres_modules.db import db #
|
|
153
|
+
from ul_db_utils.modules.postgres_modules.db import db # yes, db already defined, but can not use two conigs
|
|
154
154
|
db_config._init_from_sdk_with_flask(self)
|
|
155
155
|
waiting_for_postgres(db_config.uri)
|
|
156
156
|
self._db = db
|
|
@@ -490,7 +490,7 @@ class ApiSdk:
|
|
|
490
490
|
elif api_resource._type == ApiResourceType.FILE:
|
|
491
491
|
result = api_resource.response_api_error(e)
|
|
492
492
|
else:
|
|
493
|
-
result = api_resource.response_web_error(
|
|
493
|
+
result = api_resource.response_web_error( # type: ignore
|
|
494
494
|
ResourceRuntimeApiError(f'unsupported type "{api_resource._type.value}" of error response'),
|
|
495
495
|
)
|
|
496
496
|
res = result.to_flask_response(d), result.status_code
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
2
|
from typing import List, Optional, Callable, Union
|
|
3
3
|
|
|
4
|
-
from pydantic import
|
|
4
|
+
from pydantic import ConfigDict, BaseModel
|
|
5
5
|
|
|
6
6
|
from ul_api_utils.access import PermissionRegistry, PermissionDefinition
|
|
7
7
|
from ul_api_utils.modules.api_sdk_jwt import ApiSdkJwt
|
|
@@ -56,8 +56,8 @@ class ApiSdkConfig(BaseModel):
|
|
|
56
56
|
|
|
57
57
|
api_route_path_prefix: str = '/api'
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
extra
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
model_config = ConfigDict(
|
|
60
|
+
extra="forbid",
|
|
61
|
+
frozen=True,
|
|
62
|
+
arbitrary_types_allowed=True,
|
|
63
|
+
)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from pydantic import ConfigDict, BaseModel
|
|
2
|
+
|
|
3
|
+
from ul_api_utils.resources.socketio import SocketIOConfig
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class WorkerSdkConfig(BaseModel):
|
|
7
|
+
socket_config: SocketIOConfig | None = None
|
|
8
|
+
|
|
9
|
+
model_config = ConfigDict(
|
|
10
|
+
extra="forbid",
|
|
11
|
+
frozen=True,
|
|
12
|
+
arbitrary_types_allowed=True,
|
|
13
|
+
)
|
|
@@ -3,7 +3,7 @@ import hashlib
|
|
|
3
3
|
import inspect
|
|
4
4
|
import itertools
|
|
5
5
|
import logging
|
|
6
|
-
from _hashlib import HASH
|
|
6
|
+
from _hashlib import HASH
|
|
7
7
|
from collections import defaultdict
|
|
8
8
|
from enum import Enum
|
|
9
9
|
from typing import Optional, Callable, Dict, Tuple, List, Union, Literal, cast, TypeVar, Any, Set, TypedDict
|
|
@@ -65,7 +65,7 @@ class ULCache(Cache):
|
|
|
65
65
|
|
|
66
66
|
@staticmethod
|
|
67
67
|
def _has_common_elements(seq: Set[Tuple[str, ...]]) -> bool:
|
|
68
|
-
return bool(functools.reduce(set.intersection, map(set, seq)))
|
|
68
|
+
return bool(functools.reduce(set.intersection, map(set, seq)))
|
|
69
69
|
|
|
70
70
|
@staticmethod
|
|
71
71
|
def _format_cache_key(parts: List[Any]) -> str:
|
|
@@ -77,8 +77,8 @@ class ULCache(Cache):
|
|
|
77
77
|
source_check: bool,
|
|
78
78
|
hash_method: Callable[[bytes], HASH],
|
|
79
79
|
) -> str:
|
|
80
|
-
cache_key_parts = [request.path]
|
|
81
|
-
cache_hash = None
|
|
80
|
+
cache_key_parts: List[str] = [request.path]
|
|
81
|
+
cache_hash: HASH | None = None
|
|
82
82
|
if request.args:
|
|
83
83
|
args_as_sorted_tuple = tuple(sorted(pair for pair in request.args.items(multi=True)))
|
|
84
84
|
|
|
@@ -93,8 +93,8 @@ class ULCache(Cache):
|
|
|
93
93
|
cache_hash.update(func_source_code.encode("utf-8"))
|
|
94
94
|
else:
|
|
95
95
|
cache_hash = hash_method(func_source_code.encode("utf-8"))
|
|
96
|
-
|
|
97
|
-
cache_key_parts.append(
|
|
96
|
+
cache_hash_str = str(cache_hash.hexdigest()) if cache_hash is not None else ''
|
|
97
|
+
cache_key_parts.append(cache_hash_str)
|
|
98
98
|
|
|
99
99
|
return self._format_cache_key(cache_key_parts)
|
|
100
100
|
|
|
@@ -78,7 +78,7 @@ def load_debugger_static_scripts(sdk: 'ApiSdk') -> None:
|
|
|
78
78
|
for req_url in reversed(body.requests_hierarchy):
|
|
79
79
|
for k, api in internal_api_registry.items():
|
|
80
80
|
if req_url.startswith(k):
|
|
81
|
-
api_body = body.
|
|
81
|
+
api_body = body.model_dump()
|
|
82
82
|
api_body['requests_hierarchy'] = []
|
|
83
83
|
api_result = api.request_post('/debugger-explain', v=ApiPathVersion.NO_VERSION, json=api_body).check().typed(DebuggerExplainResponse)
|
|
84
84
|
return api_resource.response_ok(api_result.payload)
|
{ul-api-utils-8.0.1a0 → ul-api-utils-8.0.3}/ul_api_utils/resources/health_check/health_check.py
RENAMED
|
@@ -2,7 +2,7 @@ import time
|
|
|
2
2
|
from enum import Enum, IntEnum
|
|
3
3
|
from typing import List, Callable, Any, Optional, Dict, TYPE_CHECKING, Tuple, NamedTuple, Set, Union
|
|
4
4
|
|
|
5
|
-
from pydantic import Field, BaseModel,
|
|
5
|
+
from pydantic import model_validator, ConfigDict, Field, BaseModel, PositiveInt, TypeAdapter
|
|
6
6
|
from sqlalchemy.sql import text
|
|
7
7
|
from unipipeline.errors import UniError
|
|
8
8
|
from unipipeline.modules.uni import Uni
|
|
@@ -64,7 +64,7 @@ class HealthCheckStepType(Enum):
|
|
|
64
64
|
executed_result.check()
|
|
65
65
|
except (Client4XXInternalApiError, Server5XXInternalApiError) as e:
|
|
66
66
|
error = e
|
|
67
|
-
payload =
|
|
67
|
+
payload = TypeAdapter(HealthCheckApiResponse).validate_python(executed_result.payload_raw).checks
|
|
68
68
|
if error:
|
|
69
69
|
if isinstance(error, Client4XXInternalApiError):
|
|
70
70
|
return HealthCheckResultStatus.WARN, '', payload
|
|
@@ -144,7 +144,7 @@ class HealthCheckStep(NamedTuple):
|
|
|
144
144
|
type: HealthCheckStepType
|
|
145
145
|
executable: Callable[..., Any]
|
|
146
146
|
executable_args: Tuple[Any, ...] = tuple()
|
|
147
|
-
executable_kwargs: Any = Field(default_factory=dict)
|
|
147
|
+
executable_kwargs: Any = Field(default_factory=lambda: dict())
|
|
148
148
|
|
|
149
149
|
def run(self) -> Tuple[HealthCheckResultStatus, float, str, List[HealthCheckResult]]:
|
|
150
150
|
start_time = time.perf_counter()
|
|
@@ -380,8 +380,7 @@ class HealthCheckApiResponse(JsonApiResponsePayload):
|
|
|
380
380
|
service_name: str
|
|
381
381
|
checks: List[HealthCheckResult] = Field(default_factory=list)
|
|
382
382
|
|
|
383
|
-
|
|
384
|
-
use_enum_values = True
|
|
383
|
+
model_config = ConfigDict(use_enum_values=True)
|
|
385
384
|
|
|
386
385
|
|
|
387
386
|
class HealthCheckMessageQueueRange(BaseModel):
|
|
@@ -407,13 +406,13 @@ class HealthCheckMessageQueueRange(BaseModel):
|
|
|
407
406
|
description="Maximum number of messages for queue to have in order to be classified with status WARN (400).",
|
|
408
407
|
)
|
|
409
408
|
|
|
410
|
-
@
|
|
411
|
-
def root_validate(
|
|
412
|
-
ok, warn =
|
|
409
|
+
@model_validator(mode='after')
|
|
410
|
+
def root_validate(self) -> 'HealthCheckMessageQueueRange':
|
|
411
|
+
ok, warn = self.ok, self.warn
|
|
413
412
|
if ok is not None and warn is not None:
|
|
414
413
|
if ok >= warn:
|
|
415
414
|
raise ValueError(f"OK attribute should be less than WARN attribute, but you provided {ok=}, {warn=}")
|
|
416
|
-
return
|
|
415
|
+
return self
|
|
417
416
|
|
|
418
417
|
def get_status(self, message_count: int) -> HealthCheckResultStatus:
|
|
419
418
|
if message_count <= self.ok:
|
|
@@ -437,5 +436,4 @@ class HealthCheckQueueMessageCountStatus(BaseModel):
|
|
|
437
436
|
queue_name: str
|
|
438
437
|
message_count_status_map: Dict[range, HealthCheckResultStatus]
|
|
439
438
|
|
|
440
|
-
|
|
441
|
-
arbitrary_types_allowed = True
|
|
439
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|