ul-api-utils 8.1.4__tar.gz → 8.1.6__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.1.4 → ul-api-utils-8.1.6}/PKG-INFO +1 -1
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/setup.py +1 -1
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/api_resource/api_resource_fn_typing.py +15 -14
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/api_resource/api_response.py +15 -4
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/api_resource/api_response_payload_alias.py +3 -4
- ul-api-utils-8.1.6/ul_api_utils/validators/__tests__/test_custom_fields.py +32 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/validators/custom_fields.py +21 -13
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils.egg-info/PKG-INFO +1 -1
- ul-api-utils-8.1.4/ul_api_utils/validators/__tests__/test_custom_fields.py +0 -33
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/LICENSE +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/README.md +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/example/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/example/conf.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/example/main.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/example/models/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/example/permissions.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/example/pure_flask_example.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/example/rate_limit_load.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/example/redis_repository.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/example/routes/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/example/routes/api_some.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/example/sockets/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/example/sockets/on_connect.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/example/sockets/on_disconnect.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/example/sockets/on_json.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/example/sockets/on_message.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/example/sockets/on_open.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/example/workers/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/example/workers/worker.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/setup.cfg +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/access/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/api_resource/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/api_resource/api_request.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/api_resource/api_resource.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/api_resource/api_resource_config.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/api_resource/api_resource_error_handling.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/api_resource/api_resource_type.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/api_resource/api_response_db.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/api_resource/db_types.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/api_resource/signature_check.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/commands/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/commands/cmd_enc_keys.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/commands/cmd_gen_api_user_token.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/commands/cmd_gen_new_api_user.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/commands/cmd_generate_api_docs.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/commands/cmd_start.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/commands/cmd_worker_start.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/commands/start/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/commands/start/gunicorn.conf.local.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/commands/start/gunicorn.conf.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/commands/start/wsgi.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/conf/ul-debugger-main.js +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/conf/ul-debugger-ui.js +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/conf.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/const.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/debug/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/debug/debugger.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/debug/malloc.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/debug/stat.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/encrypt/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/encrypt/encrypt_decrypt_abstract.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/encrypt/encrypt_decrypt_aes_xtea.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/errors.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/internal_api/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/internal_api/__tests__/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/internal_api/__tests__/internal_api.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/internal_api/__tests__/internal_api_content_type.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/internal_api/internal_api.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/internal_api/internal_api_check_context.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/internal_api/internal_api_error.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/internal_api/internal_api_response.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/main.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/modules/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/modules/__tests__/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/modules/__tests__/test_api_sdk_jwt.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/modules/api_sdk.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/modules/api_sdk_config.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/modules/api_sdk_jwt.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/modules/intermediate_state.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/modules/worker_context.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/modules/worker_sdk.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/modules/worker_sdk_config.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/py.typed +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/caching.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/debugger_scripts.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/health_check/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/health_check/const.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/health_check/health_check.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/health_check/health_check_template.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/health_check/resource.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/not_implemented.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/permissions.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/rate_limitter.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/socketio.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/swagger.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/web_forms/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/web_forms/custom_fields/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/web_forms/custom_fields/custom_checkbox_select.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/web_forms/custom_widgets/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/web_forms/custom_widgets/custom_select_widget.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/web_forms/custom_widgets/custom_text_input_widget.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/web_forms/uni_form.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/sentry.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/__tests__/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/__tests__/api_path_version.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/__tests__/unwrap_typing.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/api_encoding.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/api_format.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/api_method.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/api_pagination.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/api_path_version.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/api_request_info.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/avro.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/broker_topics_message_count.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/cached_per_request.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/colors.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/constants.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/decode_base64.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/deprecated.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flags.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flask_swagger_generator/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flask_swagger_generator/conf.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flask_swagger_generator/exceptions.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flask_swagger_generator/specifiers/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flask_swagger_generator/specifiers/swagger_models.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flask_swagger_generator/specifiers/swagger_specifier.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flask_swagger_generator/specifiers/swagger_three_specifier.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flask_swagger_generator/specifiers/swagger_version.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flask_swagger_generator/utils/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flask_swagger_generator/utils/input_type.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flask_swagger_generator/utils/parameter_type.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flask_swagger_generator/utils/replace_in_dict.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flask_swagger_generator/utils/request_type.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flask_swagger_generator/utils/schema_type.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flask_swagger_generator/utils/security_type.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/imports.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/instance_checks.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/jinja/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/jinja/t_url_for.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/jinja/to_pretty_json.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/json_encoder.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/load_modules.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/memory_db/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/memory_db/__tests__/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/memory_db/errors.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/memory_db/repository.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/token_check.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/token_check_through_request.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/unwrap_typing.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/uuid_converter.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/validators/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/validators/__tests__/__init__.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/validators/validate_empty_object.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/validators/validate_uuid.py +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils.egg-info/SOURCES.txt +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils.egg-info/dependency_links.txt +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils.egg-info/entry_points.txt +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils.egg-info/requires.txt +0 -0
- {ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils.egg-info/top_level.txt +0 -0
{ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/api_resource/api_resource_fn_typing.py
RENAMED
|
@@ -3,13 +3,14 @@ from typing import NamedTuple, Any, Callable, Optional, List, Dict, Type, Tuple,
|
|
|
3
3
|
|
|
4
4
|
from flask import request
|
|
5
5
|
from pydantic import BaseModel, ValidationError, validate_call, TypeAdapter
|
|
6
|
-
from pydantic.utils import deep_update
|
|
6
|
+
from pydantic.v1.utils import deep_update
|
|
7
7
|
from pydantic_core import ErrorDetails
|
|
8
8
|
|
|
9
9
|
from ul_api_utils.api_resource.api_request import ApiRequestQuery
|
|
10
10
|
from ul_api_utils.api_resource.api_resource_type import ApiResourceType
|
|
11
|
-
from ul_api_utils.api_resource.api_response import HtmlApiResponse, JsonApiResponse, FileApiResponse,
|
|
12
|
-
|
|
11
|
+
from ul_api_utils.api_resource.api_response import HtmlApiResponse, JsonApiResponse, FileApiResponse, \
|
|
12
|
+
RedirectApiResponse, ApiResponse, \
|
|
13
|
+
JsonApiResponsePayload, RootJsonApiResponsePayload, ProxyJsonApiResponse, AnyJsonApiResponse, \
|
|
13
14
|
EmptyJsonApiResponse, TPayloadTotalUnion, RootJsonApiResponse
|
|
14
15
|
from ul_api_utils.api_resource.signature_check import get_typing, set_model_dictable, set_model
|
|
15
16
|
from ul_api_utils.errors import ValidationListApiError, ResourceRuntimeApiError, InvalidContentTypeError
|
|
@@ -56,7 +57,7 @@ class ApiResourceFnTyping(NamedTuple):
|
|
|
56
57
|
query_typing: Optional[Type[ApiRequestQuery]] # none if it is not specified
|
|
57
58
|
has_query_validation_error: bool
|
|
58
59
|
return_typing: Optional[Type[ApiResponse]] # NOT NONE for api
|
|
59
|
-
return_payload_typing: Optional[Type[JsonApiResponsePayload]] # NOT NONE for api
|
|
60
|
+
return_payload_typing: Optional[Type[JsonApiResponsePayload] | Type[RootJsonApiResponsePayload[Any]]] # NOT NONE for api
|
|
60
61
|
|
|
61
62
|
def get_return_schema(self) -> Type[BaseModel]:
|
|
62
63
|
inner_type = self.return_payload_typing
|
|
@@ -91,7 +92,7 @@ class ApiResourceFnTyping(NamedTuple):
|
|
|
91
92
|
def runtime_validate_api_proxy_payload(self, response: Dict[str, Any], *, quick: bool) -> None:
|
|
92
93
|
assert isinstance(response, dict)
|
|
93
94
|
|
|
94
|
-
def runtime_validate_api_response_payload(self, payload: Any, total_count: Optional[int], *, quick: bool) -> TPayloadTotalUnion:
|
|
95
|
+
def runtime_validate_api_response_payload(self, payload: Any, total_count: Optional[int], *, quick: bool) -> TPayloadTotalUnion: # type: ignore
|
|
95
96
|
quick = quick or self.return_payload_typing is None
|
|
96
97
|
|
|
97
98
|
if self.return_typing == AnyJsonApiResponse:
|
|
@@ -106,7 +107,7 @@ class ApiResourceFnTyping(NamedTuple):
|
|
|
106
107
|
if r is None:
|
|
107
108
|
raise ResourceRuntimeApiError(f'invalid type of object. {type(o).__name__} was given')
|
|
108
109
|
new_payload.append(r)
|
|
109
|
-
return new_payload, total_count
|
|
110
|
+
return new_payload, total_count
|
|
110
111
|
|
|
111
112
|
if payload is None: # only for case when payload must be single object
|
|
112
113
|
return None, None
|
|
@@ -114,7 +115,7 @@ class ApiResourceFnTyping(NamedTuple):
|
|
|
114
115
|
new_payload = to_dict(payload) if quick else set_model_dictable(self.return_payload_typing, payload) # type: ignore
|
|
115
116
|
if new_payload is None:
|
|
116
117
|
raise ResourceRuntimeApiError(f'invalid type of object. {type(payload).__name__} was given')
|
|
117
|
-
return new_payload, None
|
|
118
|
+
return new_payload, None
|
|
118
119
|
|
|
119
120
|
def _get_body(self) -> Optional[Any]:
|
|
120
121
|
if self.api_resource_type == ApiResourceType.WEB:
|
|
@@ -230,7 +231,7 @@ class ApiResourceFnTyping(NamedTuple):
|
|
|
230
231
|
cls,
|
|
231
232
|
api_resource_type: 'ApiResourceType',
|
|
232
233
|
fn: Callable[['ApiResource'], ApiResponse],
|
|
233
|
-
) -> Tuple[bool, Optional[Type[JsonApiResponsePayload]], Optional[Type[ApiResponse]]]:
|
|
234
|
+
) -> Tuple[bool, Optional[Type[JsonApiResponsePayload] | Type[RootJsonApiResponsePayload[Any]]], Optional[Type[ApiResponse]]]:
|
|
234
235
|
response_many = False
|
|
235
236
|
return_typing = fn.__annotations__.get('return', None)
|
|
236
237
|
ret = get_typing(return_typing)
|
|
@@ -259,21 +260,21 @@ class ApiResourceFnTyping(NamedTuple):
|
|
|
259
260
|
assert return_payload_typing is None, f'{fn.__name__} :: invalid response payload typing. payload must be None. {return_payload_typing.__name__} was given'
|
|
260
261
|
|
|
261
262
|
elif return_typing is RootJsonApiResponse:
|
|
262
|
-
assert return_payload_typing is not None and issubclass(return_payload_typing, JsonApiResponsePayload), \
|
|
263
|
-
f'{fn.__name__} :: invalid response payload typing. payload must be subclass of JsonApiResponsePayload. ' \
|
|
263
|
+
assert return_payload_typing is not None and issubclass(return_payload_typing, (JsonApiResponsePayload, RootJsonApiResponsePayload)), \
|
|
264
|
+
f'{fn.__name__} :: invalid response payload typing. payload must be subclass of (JsonApiResponsePayload, RootJsonApiResponsePayload). ' \
|
|
264
265
|
f'{return_payload_typing.__name__ if return_payload_typing is not None else "None"} was given'
|
|
265
266
|
|
|
266
267
|
elif return_typing is AnyJsonApiResponse:
|
|
267
268
|
assert return_payload_typing is None, f'{fn.__name__} :: invalid response payload typing. payload must be None. {return_payload_typing.__name__} was given'
|
|
268
269
|
|
|
269
270
|
elif issubclass(return_typing, JsonApiResponse):
|
|
270
|
-
assert return_payload_typing is not None and issubclass(return_payload_typing, JsonApiResponsePayload), \
|
|
271
|
-
f'{fn.__name__} :: invalid response payload typing. payload must be subclass of JsonApiResponsePayload. ' \
|
|
271
|
+
assert return_payload_typing is not None and issubclass(return_payload_typing, (JsonApiResponsePayload, RootJsonApiResponsePayload)), \
|
|
272
|
+
f'{fn.__name__} :: invalid response payload typing. payload must be subclass of (JsonApiResponsePayload, RootJsonApiResponsePayload). ' \
|
|
272
273
|
f'{return_payload_typing.__name__ if return_payload_typing is not None else "None"} was given'
|
|
273
274
|
|
|
274
275
|
elif issubclass(return_typing, ProxyJsonApiResponse):
|
|
275
|
-
assert return_payload_typing is not None and issubclass(return_payload_typing, JsonApiResponsePayload), \
|
|
276
|
-
f'{fn.__name__} :: invalid response payload typing. payload must be subclass of JsonApiResponsePayload. ' \
|
|
276
|
+
assert return_payload_typing is not None and issubclass(return_payload_typing, (JsonApiResponsePayload, RootJsonApiResponsePayload)), \
|
|
277
|
+
f'{fn.__name__} :: invalid response payload typing. payload must be subclass of (JsonApiResponsePayload, RootJsonApiResponsePayload). ' \
|
|
277
278
|
f'{return_payload_typing.__name__ if return_payload_typing is not None else "None"} was given'
|
|
278
279
|
|
|
279
280
|
else:
|
|
@@ -2,14 +2,16 @@ import io
|
|
|
2
2
|
from datetime import datetime
|
|
3
3
|
from types import NoneType
|
|
4
4
|
from typing import TypeVar, Generic, List, Optional, Dict, Any, Callable, Union, BinaryIO, Tuple, Type
|
|
5
|
+
|
|
5
6
|
import msgpack
|
|
6
7
|
from flask import jsonify, send_file, redirect, Response, request
|
|
7
|
-
from pydantic import ConfigDict, RootModel
|
|
8
8
|
from pydantic import BaseModel
|
|
9
|
+
from pydantic import ConfigDict, RootModel
|
|
9
10
|
from werkzeug import Response as BaseResponse
|
|
10
11
|
|
|
11
12
|
from ul_api_utils.api_resource.db_types import TPayloadInputUnion
|
|
12
|
-
from ul_api_utils.const import RESPONSE_PROP_OK, RESPONSE_PROP_PAYLOAD, RESPONSE_PROP_COUNT, RESPONSE_PROP_TOTAL,
|
|
13
|
+
from ul_api_utils.const import RESPONSE_PROP_OK, RESPONSE_PROP_PAYLOAD, RESPONSE_PROP_COUNT, RESPONSE_PROP_TOTAL, \
|
|
14
|
+
RESPONSE_PROP_ERRORS, MIME__JSON, MIME__MSGPCK, \
|
|
13
15
|
REQUEST_HEADER__ACCEPT
|
|
14
16
|
from ul_api_utils.debug.debugger import Debugger
|
|
15
17
|
from ul_api_utils.utils.json_encoder import CustomJSONEncoder
|
|
@@ -139,21 +141,30 @@ class EmptyJsonApiResponse(ApiResponse):
|
|
|
139
141
|
return resp
|
|
140
142
|
|
|
141
143
|
|
|
144
|
+
T = TypeVar("T")
|
|
145
|
+
|
|
142
146
|
class JsonApiResponsePayload(BaseModel):
|
|
143
147
|
model_config = ConfigDict(extra="ignore")
|
|
144
148
|
|
|
145
149
|
|
|
146
|
-
|
|
150
|
+
class RootJsonApiResponsePayload(RootModel[T]):
|
|
151
|
+
pass
|
|
152
|
+
|
|
153
|
+
TRootJsonApiResponsePayload = TypeVar('TRootJsonApiResponsePayload')
|
|
154
|
+
|
|
155
|
+
TResultPayloadUnion = Union[None, Dict[str, Any], JsonApiResponsePayload, TRootJsonApiResponsePayload, List[JsonApiResponsePayload], List[TRootJsonApiResponsePayload], List[Dict[str, Any]]]
|
|
147
156
|
TPayloadTotalUnion = Union[
|
|
148
157
|
Tuple[None, None],
|
|
149
158
|
Tuple[Dict[str, Any], None],
|
|
150
159
|
Tuple[JsonApiResponsePayload, None],
|
|
160
|
+
Tuple[TRootJsonApiResponsePayload, None],
|
|
151
161
|
Tuple[List[JsonApiResponsePayload], int],
|
|
162
|
+
Tuple[List[TRootJsonApiResponsePayload], int],
|
|
152
163
|
Tuple[List[Dict[str, Any]], int],
|
|
153
164
|
]
|
|
154
165
|
|
|
155
166
|
|
|
156
|
-
class DictJsonApiResponsePayload(
|
|
167
|
+
class DictJsonApiResponsePayload(RootJsonApiResponsePayload[Dict[str, Any]]):
|
|
157
168
|
pass
|
|
158
169
|
|
|
159
170
|
|
{ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/api_resource/api_response_payload_alias.py
RENAMED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
|
-
from types import NoneType
|
|
3
2
|
|
|
4
|
-
from pydantic import UUID4
|
|
3
|
+
from pydantic import UUID4
|
|
5
4
|
|
|
6
|
-
from ul_api_utils.api_resource.api_response import JsonApiResponsePayload
|
|
5
|
+
from ul_api_utils.api_resource.api_response import JsonApiResponsePayload, RootJsonApiResponsePayload
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
class ApiBaseModelPayloadResponse(JsonApiResponsePayload):
|
|
@@ -22,5 +21,5 @@ class ApiBaseUserModelPayloadResponse(JsonApiResponsePayload):
|
|
|
22
21
|
is_alive: bool
|
|
23
22
|
|
|
24
23
|
|
|
25
|
-
class ApiEmptyResponse(
|
|
24
|
+
class ApiEmptyResponse(RootJsonApiResponsePayload[None]):
|
|
26
25
|
pass
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# import pytest
|
|
2
|
+
#
|
|
3
|
+
# from pydantic import BaseModel
|
|
4
|
+
# from typing import Union, List
|
|
5
|
+
# from ul_api_utils.validators.custom_fields import QueryParamsSeparatedList
|
|
6
|
+
#
|
|
7
|
+
#
|
|
8
|
+
# class ModelStr(BaseModel):
|
|
9
|
+
# param: QueryParamsSeparatedList[str]
|
|
10
|
+
#
|
|
11
|
+
#
|
|
12
|
+
# class ModelInt(BaseModel):
|
|
13
|
+
# param: QueryParamsSeparatedList[int]
|
|
14
|
+
#
|
|
15
|
+
#
|
|
16
|
+
# @pytest.mark.parametrize(
|
|
17
|
+
# "model, input_data, expected_output",
|
|
18
|
+
# [
|
|
19
|
+
# pytest.param(ModelStr, "first_array_element,second,third,this", ["first_array_element", "second", "third", "this"]),
|
|
20
|
+
# pytest.param(ModelStr, ["first_array_element,second,third,this"], ["first_array_element", "second", "third", "this"]),
|
|
21
|
+
# pytest.param(ModelInt, ["1,2,3,4,5"], [1, 2, 3, 4, 5]),
|
|
22
|
+
# pytest.param(ModelStr, 'first_array_element,"second,third",this', ["first_array_element", "second,third", "this"]),
|
|
23
|
+
# pytest.param(ModelStr, ['first_array_element,"second,third",this'], ["first_array_element", "second,third", "this"]),
|
|
24
|
+
# pytest.param(ModelStr, '"first_array_element,second,third",this, "1,2"', ["first_array_element,second,third", "this", "1,2"]),
|
|
25
|
+
# ],
|
|
26
|
+
# )
|
|
27
|
+
# def test__query_params_separated_list(
|
|
28
|
+
# model: Union[ModelStr, ModelInt], input_data: Union[List[str], str], expected_output: List[Union[str, int]],
|
|
29
|
+
# ) -> None:
|
|
30
|
+
# instance = model(param=input_data) # type: ignore
|
|
31
|
+
# assert isinstance(instance.param, list)
|
|
32
|
+
# assert instance.param == expected_output
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import csv
|
|
2
|
-
from typing import TypeVar, Generic, List, Union, Generator, Callable, Annotated, Any
|
|
2
|
+
from typing import TypeVar, Generic, List, Union, Generator, Callable, Annotated, Any
|
|
3
3
|
from uuid import UUID
|
|
4
4
|
|
|
5
|
-
from pydantic import
|
|
5
|
+
from pydantic import Field, StringConstraints, TypeAdapter
|
|
6
|
+
from pydantic_core import ValidationError, InitErrorDetails
|
|
6
7
|
from pydantic_core.core_schema import ValidationInfo
|
|
7
8
|
|
|
8
9
|
from ul_api_utils.const import CRON_EXPRESSION_VALIDATION_REGEX, MIN_UTC_OFFSET_SECONDS, MAX_UTC_OFFSET_SECONDS
|
|
@@ -38,12 +39,13 @@ class QueryParamsSeparatedList(Generic[QueryParamsSeparatedListValueType]):
|
|
|
38
39
|
Note:
|
|
39
40
|
Sent as a string, but interpreted as List.
|
|
40
41
|
"""
|
|
42
|
+
_contains_type: Any = None
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return
|
|
44
|
+
@classmethod
|
|
45
|
+
def __class_getitem__(cls, item: Any) -> QueryParamsSeparatedListValueType:
|
|
46
|
+
new_cls = super().__class_getitem__(item) # type: ignore
|
|
47
|
+
new_cls._contains_type = item
|
|
48
|
+
return new_cls
|
|
47
49
|
|
|
48
50
|
@classmethod
|
|
49
51
|
def __get_validators__(cls) -> Generator[Callable[[Union[List[str], str], ValidationInfo], List[QueryParamsSeparatedListValueType]], None, None]:
|
|
@@ -54,23 +56,29 @@ class QueryParamsSeparatedList(Generic[QueryParamsSeparatedListValueType]):
|
|
|
54
56
|
"""
|
|
55
57
|
Validate and convert the query parameter string into a list of the specified type.
|
|
56
58
|
"""
|
|
59
|
+
if cls._contains_type is None:
|
|
60
|
+
raise TypeError("QueryParamsSeparatedList must be parameterized with a type, e.g., QueryParamsSeparatedList[int]")
|
|
61
|
+
|
|
62
|
+
adapter = TypeAdapter(cls._contains_type)
|
|
63
|
+
|
|
57
64
|
if not isinstance(query_param, list):
|
|
58
65
|
query_param = [query_param]
|
|
59
66
|
|
|
60
67
|
reader = csv.reader(query_param, skipinitialspace=True)
|
|
61
68
|
splitted = next(reader)
|
|
62
69
|
|
|
63
|
-
adapter = TypeAdapter(get_args(cls)[0])
|
|
64
|
-
|
|
65
70
|
validated_items = []
|
|
66
|
-
errors = []
|
|
71
|
+
errors: List[InitErrorDetails] = []
|
|
67
72
|
|
|
68
|
-
for value in splitted:
|
|
73
|
+
for idx, value in enumerate(splitted):
|
|
69
74
|
try:
|
|
70
75
|
validated_items.append(adapter.validate_python(value))
|
|
71
76
|
except ValidationError as e:
|
|
72
|
-
errors
|
|
77
|
+
for error in e.errors(include_url=False):
|
|
78
|
+
error['loc'] = ('param', idx)
|
|
79
|
+
errors.append(error) # type: ignore
|
|
80
|
+
|
|
73
81
|
if errors:
|
|
74
|
-
raise ValidationError(errors)
|
|
82
|
+
raise ValidationError.from_exception_data("List validation error", errors)
|
|
75
83
|
|
|
76
84
|
return validated_items
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
|
|
3
|
-
from pydantic import BaseModel
|
|
4
|
-
from typing import Union, List
|
|
5
|
-
from ul_api_utils.validators.custom_fields import QueryParamsSeparatedList
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class ModelStr(BaseModel):
|
|
9
|
-
param: QueryParamsSeparatedList[str]
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class ModelInt(BaseModel):
|
|
13
|
-
param: QueryParamsSeparatedList[int]
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@pytest.mark.parametrize(
|
|
17
|
-
"model, input_data, expected_output",
|
|
18
|
-
[
|
|
19
|
-
pytest.param(ModelStr, "first_array_element,second,third,this", ["first_array_element", "second", "third", "this"]),
|
|
20
|
-
pytest.param(ModelStr, ["first_array_element,second,third,this"], ["first_array_element", "second", "third", "this"]),
|
|
21
|
-
pytest.param(ModelInt, "1,2,3,4,5", [1, 2, 3, 4, 5]),
|
|
22
|
-
pytest.param(ModelInt, ["1,2,3,4,5"], [1, 2, 3, 4, 5]),
|
|
23
|
-
pytest.param(ModelStr, 'first_array_element,"second,third",this', ["first_array_element", "second,third", "this"]),
|
|
24
|
-
pytest.param(ModelStr, ['first_array_element,"second,third",this'], ["first_array_element", "second,third", "this"]),
|
|
25
|
-
pytest.param(ModelStr, '"first_array_element,second,third",this, "1,2"', ["first_array_element,second,third", "this", "1,2"]),
|
|
26
|
-
],
|
|
27
|
-
)
|
|
28
|
-
def test__query_params_separated_list(
|
|
29
|
-
model: Union[ModelStr, ModelInt], input_data: Union[List[str], str], expected_output: List[Union[str, int]],
|
|
30
|
-
) -> None:
|
|
31
|
-
instance = model(param=input_data) # type: ignore
|
|
32
|
-
assert isinstance(instance.param, list)
|
|
33
|
-
assert instance.param == expected_output
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/api_resource/api_resource_error_handling.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/commands/start/gunicorn.conf.local.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/internal_api/__tests__/internal_api.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/internal_api/internal_api_check_context.py
RENAMED
|
File without changes
|
|
File without changes
|
{ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/internal_api/internal_api_response.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/modules/__tests__/test_api_sdk_jwt.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/health_check/health_check.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/resources/web_forms/custom_fields/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flask_swagger_generator/__init__.py
RENAMED
|
File without changes
|
{ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flask_swagger_generator/conf.py
RENAMED
|
File without changes
|
{ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/flask_swagger_generator/exceptions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ul-api-utils-8.1.4 → ul-api-utils-8.1.6}/ul_api_utils/utils/memory_db/__tests__/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|