kiba-core 0.5.3.dev74__tar.gz → 0.5.3.dev76__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.
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/CHANGELOG.md +1 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/Dockerfile +1 -1
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/PKG-INFO +12 -12
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/json_route.py +2 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/streaming_json_route.py +2 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/kiba_core.egg-info/PKG-INFO +12 -12
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/kiba_core.egg-info/requires.txt +11 -11
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/pyproject.toml +12 -12
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/api/test_json_route.py +11 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/api/test_streaming_json_route.py +11 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/uv.lock +99 -68
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/.github/pull_request_template.md +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/.github/workflows/deploy.yml +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/.github/workflows/pull-request.yml +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/.github/workflows/release.yml +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/.gitignore +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/README.md +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/__init__.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/__init__.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/api_request.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/api_response.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/authorizer.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/default_routes.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/health.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/middleware/__init__.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/middleware/database_connection_middleware.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/middleware/exception_handling_middleware.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/middleware/logging_middleware.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/middleware/origin_ip_middleware.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/middleware/server_headers_middleware.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/openapi.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/rate_limit.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/request_context.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/route.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/route_auth.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/api/route_metadata.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/aws_requester.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/caching/__init__.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/caching/cache.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/caching/dict_cache.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/caching/file_cache.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/cron/__init__.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/cron/api_request_cron_job_processor.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/cron/cron_executor.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/cron/cron_job_processor.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/cron/model.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/exceptions.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/http/__init__.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/http/basic_authentication.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/http/jwt.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/http/rest_method.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/locks/__init__.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/locks/lock.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/locks/model.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/locks/sql.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/logging.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/notifications/__init__.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/notifications/discord_client.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/notifications/notification_client.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/notifications/slack_client.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/py.typed +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/queues/__init__.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/queues/aqs.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/queues/cosmos.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/queues/message_queue.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/queues/message_queue_processor.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/queues/model.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/queues/sql.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/queues/sqs.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/requester/__init__.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/requester/requester.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/s3_manager.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/service_client.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/store/__init__.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/store/database.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/store/retriever.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/store/saver.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/util/__init__.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/util/async_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/util/chain_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/util/date_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/util/dict_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/util/file_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/util/hashing_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/util/http_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/util/json_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/util/list_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/util/process_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/util/string_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/util/typing_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/util/url_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/util/value_holder.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/web3/__init__.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/web3/eth_client.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/web3/eth_client_registry.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/core/web3/multicall3.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/kiba_core.egg-info/SOURCES.txt +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/kiba_core.egg-info/dependency_links.txt +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/kiba_core.egg-info/top_level.txt +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/makefile +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/setup.cfg +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/__init__.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/api/test_api_response.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/api/test_authorizer.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/api/test_exception_handling_middleware.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/api/test_openapi.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/api/test_origin_ip_middleware.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/api/test_rate_limit.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/api/test_request_context.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/api/test_route.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/caching/test_dict_cache.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/caching/test_file_cache.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/cron/__init__.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/cron/test_cron_executor.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/locks/test_sql_lock.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/queues/conftest.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/queues/test_aqs_queue.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/queues/test_cosmos_queue.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/queues/test_message_queue_processor.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/queues/test_sql_queue.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/queues/test_sqs_queue.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/requester/__init__.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/requester/test_requester.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/test_database.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/test_exceptions.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/test_logging.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/util/__init__.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/util/test_async_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/util/test_chain_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/util/test_date_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/util/test_dict_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/util/test_file_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/util/test_json_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/util/test_list_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/util/test_process_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/util/test_string_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/util/test_url_util.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/web3/__init__.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/web3/test_eth_client_registry.py +0 -0
- {kiba_core-0.5.3.dev74 → kiba_core-0.5.3.dev76}/tests/web3/test_rest_eth_client.py +0 -0
|
@@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
10
|
### Added
|
|
11
|
+
- [PATCH] Fixed `json_route` and `streaming_json_route` returning a 500 when the JSON body isn't an object (e.g. `true` or `[1]`); they now raise `BadRequestException` (400)
|
|
11
12
|
- [MINOR] Added `shouldNotifyRetriedFailures` (default `True`) to `MessageQueueProcessor`: when `False`, failure notifications are only sent once the queue gives up on a message, not for failures it will retry. `MessageQueue.fail_message` now returns whether the queue scheduled another attempt: `SqlMessageQueue` and `CosmosMessageQueue` return `True` until `maxAttempts` is reached, while `SqsMessageQueue` and `AqsMessageQueue` always return `False` as the platform decides on redelivery, so they keep notifying every failure
|
|
12
13
|
- [MAJOR] Updated `CosmosMessageQueue` to retry failed messages like `SqlMessageQueue`: added `maxAttempts` (default 3) and `failureRetryDelaySeconds` (default 60). `fail_message` reschedules the message with linear backoff and stores `lastError`, and a visible message whose lease expired counts as an attempt when it is claimed again. Once `postCount` reaches `maxAttempts` the message is removed, along with its deduplication item. Previously failed or abandoned messages reappeared once their lease expired and were retried forever
|
|
13
14
|
- [MINOR] Added `pollLogIntervalSeconds` (default 600) to `MessageQueueProcessor`: `Retrieving messages...` is now logged on the first poll and then at most once per interval instead of on every poll, so it still shows the worker is alive without flooding the logs; pass `0` to log every poll as before
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kiba-core
|
|
3
|
-
Version: 0.5.3.
|
|
3
|
+
Version: 0.5.3.dev76
|
|
4
4
|
Summary: Kiba Labs' python utilities
|
|
5
5
|
Project-URL: repository, https://github.com/kibalabs/core-py
|
|
6
6
|
Requires-Python: <4,>=3.12
|
|
@@ -12,32 +12,32 @@ Provides-Extra: api
|
|
|
12
12
|
Requires-Dist: fastapi>=0.141.1; extra == "api"
|
|
13
13
|
Requires-Dist: uvicorn[standard]>=0.53.0; extra == "api"
|
|
14
14
|
Provides-Extra: core-api
|
|
15
|
-
Requires-Dist: starlette>=1.
|
|
15
|
+
Requires-Dist: starlette>=1.7.0; extra == "core-api"
|
|
16
16
|
Requires-Dist: uvicorn[standard]>=0.53.0; extra == "core-api"
|
|
17
17
|
Provides-Extra: storage
|
|
18
|
-
Requires-Dist: aiobotocore>=3.9.
|
|
18
|
+
Requires-Dist: aiobotocore>=3.9.2; extra == "storage"
|
|
19
19
|
Provides-Extra: queues
|
|
20
|
-
Requires-Dist: aiobotocore>=3.9.
|
|
20
|
+
Requires-Dist: aiobotocore>=3.9.2; extra == "queues"
|
|
21
21
|
Provides-Extra: queue-sqs
|
|
22
|
-
Requires-Dist: aiobotocore>=3.9.
|
|
22
|
+
Requires-Dist: aiobotocore>=3.9.2; extra == "queue-sqs"
|
|
23
23
|
Provides-Extra: queue-aqs
|
|
24
|
-
Requires-Dist: azure-storage-queue[aio]>=12.
|
|
24
|
+
Requires-Dist: azure-storage-queue[aio]>=12.18.0; extra == "queue-aqs"
|
|
25
25
|
Provides-Extra: queue-cosmos
|
|
26
|
-
Requires-Dist: azure-cosmos>=4.17.
|
|
26
|
+
Requires-Dist: azure-cosmos>=4.17.1; extra == "queue-cosmos"
|
|
27
27
|
Provides-Extra: database-psql
|
|
28
|
-
Requires-Dist: sqlalchemy[asyncio]>=2.
|
|
28
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.1.3; extra == "database-psql"
|
|
29
29
|
Requires-Dist: asyncpg>=0.31.0; extra == "database-psql"
|
|
30
30
|
Provides-Extra: database-sqlite
|
|
31
|
-
Requires-Dist: sqlalchemy[asyncio]>=2.
|
|
31
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.1.3; extra == "database-sqlite"
|
|
32
32
|
Requires-Dist: aiosqlite>=0.22.1; extra == "database-sqlite"
|
|
33
33
|
Provides-Extra: requester
|
|
34
|
-
Requires-Dist: httpx2>=2.13.
|
|
34
|
+
Requires-Dist: httpx2>=2.13.1; extra == "requester"
|
|
35
35
|
Provides-Extra: web3
|
|
36
36
|
Requires-Dist: web3<8.0.0,>=7.16.0; extra == "web3"
|
|
37
37
|
Provides-Extra: cron
|
|
38
|
-
Requires-Dist: apscheduler<4,>=3.11.
|
|
38
|
+
Requires-Dist: apscheduler<4,>=3.11.3; extra == "cron"
|
|
39
39
|
Provides-Extra: types
|
|
40
|
-
Requires-Dist: types-aiobotocore[essential]>=3.9.
|
|
40
|
+
Requires-Dist: types-aiobotocore[essential]>=3.9.2; extra == "types"
|
|
41
41
|
Requires-Dist: types-aiofiles>=25.1.0.20260518; extra == "types"
|
|
42
42
|
|
|
43
43
|
# Core-Py
|
|
@@ -30,6 +30,8 @@ def json_route[ApiRequest: BaseModel, ApiResponse: BaseModel](
|
|
|
30
30
|
body = typing.cast(JsonObject, json_util.loads(bodyBytes.decode()))
|
|
31
31
|
except json_util.JsonDecodeException as exception:
|
|
32
32
|
raise BadRequestException(f'Invalid JSON body: {exception}')
|
|
33
|
+
if not isinstance(body, dict):
|
|
34
|
+
raise BadRequestException('Invalid JSON body: expected an object')
|
|
33
35
|
allParams = {**pathParams, **body, **queryParams}
|
|
34
36
|
try:
|
|
35
37
|
requestParams = requestType(**allParams)
|
|
@@ -39,6 +39,8 @@ def streaming_json_route[ApiRequest: BaseModel, ApiResponse: BaseModel](
|
|
|
39
39
|
body = typing.cast(JsonObject, json_util.loads(bodyBytes.decode()))
|
|
40
40
|
except json_util.JsonDecodeException as exception:
|
|
41
41
|
raise BadRequestException(f'Invalid JSON body: {exception}')
|
|
42
|
+
if not isinstance(body, dict):
|
|
43
|
+
raise BadRequestException('Invalid JSON body: expected an object')
|
|
42
44
|
allParams = {**pathParams, **body, **queryParams}
|
|
43
45
|
try:
|
|
44
46
|
requestParams = requestType(**allParams)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kiba-core
|
|
3
|
-
Version: 0.5.3.
|
|
3
|
+
Version: 0.5.3.dev76
|
|
4
4
|
Summary: Kiba Labs' python utilities
|
|
5
5
|
Project-URL: repository, https://github.com/kibalabs/core-py
|
|
6
6
|
Requires-Python: <4,>=3.12
|
|
@@ -12,32 +12,32 @@ Provides-Extra: api
|
|
|
12
12
|
Requires-Dist: fastapi>=0.141.1; extra == "api"
|
|
13
13
|
Requires-Dist: uvicorn[standard]>=0.53.0; extra == "api"
|
|
14
14
|
Provides-Extra: core-api
|
|
15
|
-
Requires-Dist: starlette>=1.
|
|
15
|
+
Requires-Dist: starlette>=1.7.0; extra == "core-api"
|
|
16
16
|
Requires-Dist: uvicorn[standard]>=0.53.0; extra == "core-api"
|
|
17
17
|
Provides-Extra: storage
|
|
18
|
-
Requires-Dist: aiobotocore>=3.9.
|
|
18
|
+
Requires-Dist: aiobotocore>=3.9.2; extra == "storage"
|
|
19
19
|
Provides-Extra: queues
|
|
20
|
-
Requires-Dist: aiobotocore>=3.9.
|
|
20
|
+
Requires-Dist: aiobotocore>=3.9.2; extra == "queues"
|
|
21
21
|
Provides-Extra: queue-sqs
|
|
22
|
-
Requires-Dist: aiobotocore>=3.9.
|
|
22
|
+
Requires-Dist: aiobotocore>=3.9.2; extra == "queue-sqs"
|
|
23
23
|
Provides-Extra: queue-aqs
|
|
24
|
-
Requires-Dist: azure-storage-queue[aio]>=12.
|
|
24
|
+
Requires-Dist: azure-storage-queue[aio]>=12.18.0; extra == "queue-aqs"
|
|
25
25
|
Provides-Extra: queue-cosmos
|
|
26
|
-
Requires-Dist: azure-cosmos>=4.17.
|
|
26
|
+
Requires-Dist: azure-cosmos>=4.17.1; extra == "queue-cosmos"
|
|
27
27
|
Provides-Extra: database-psql
|
|
28
|
-
Requires-Dist: sqlalchemy[asyncio]>=2.
|
|
28
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.1.3; extra == "database-psql"
|
|
29
29
|
Requires-Dist: asyncpg>=0.31.0; extra == "database-psql"
|
|
30
30
|
Provides-Extra: database-sqlite
|
|
31
|
-
Requires-Dist: sqlalchemy[asyncio]>=2.
|
|
31
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.1.3; extra == "database-sqlite"
|
|
32
32
|
Requires-Dist: aiosqlite>=0.22.1; extra == "database-sqlite"
|
|
33
33
|
Provides-Extra: requester
|
|
34
|
-
Requires-Dist: httpx2>=2.13.
|
|
34
|
+
Requires-Dist: httpx2>=2.13.1; extra == "requester"
|
|
35
35
|
Provides-Extra: web3
|
|
36
36
|
Requires-Dist: web3<8.0.0,>=7.16.0; extra == "web3"
|
|
37
37
|
Provides-Extra: cron
|
|
38
|
-
Requires-Dist: apscheduler<4,>=3.11.
|
|
38
|
+
Requires-Dist: apscheduler<4,>=3.11.3; extra == "cron"
|
|
39
39
|
Provides-Extra: types
|
|
40
|
-
Requires-Dist: types-aiobotocore[essential]>=3.9.
|
|
40
|
+
Requires-Dist: types-aiobotocore[essential]>=3.9.2; extra == "types"
|
|
41
41
|
Requires-Dist: types-aiofiles>=25.1.0.20260518; extra == "types"
|
|
42
42
|
|
|
43
43
|
# Core-Py
|
|
@@ -7,40 +7,40 @@ fastapi>=0.141.1
|
|
|
7
7
|
uvicorn[standard]>=0.53.0
|
|
8
8
|
|
|
9
9
|
[core-api]
|
|
10
|
-
starlette>=1.
|
|
10
|
+
starlette>=1.7.0
|
|
11
11
|
uvicorn[standard]>=0.53.0
|
|
12
12
|
|
|
13
13
|
[cron]
|
|
14
|
-
apscheduler<4,>=3.11.
|
|
14
|
+
apscheduler<4,>=3.11.3
|
|
15
15
|
|
|
16
16
|
[database-psql]
|
|
17
|
-
sqlalchemy[asyncio]>=2.
|
|
17
|
+
sqlalchemy[asyncio]>=2.1.3
|
|
18
18
|
asyncpg>=0.31.0
|
|
19
19
|
|
|
20
20
|
[database-sqlite]
|
|
21
|
-
sqlalchemy[asyncio]>=2.
|
|
21
|
+
sqlalchemy[asyncio]>=2.1.3
|
|
22
22
|
aiosqlite>=0.22.1
|
|
23
23
|
|
|
24
24
|
[queue-aqs]
|
|
25
|
-
azure-storage-queue[aio]>=12.
|
|
25
|
+
azure-storage-queue[aio]>=12.18.0
|
|
26
26
|
|
|
27
27
|
[queue-cosmos]
|
|
28
|
-
azure-cosmos>=4.17.
|
|
28
|
+
azure-cosmos>=4.17.1
|
|
29
29
|
|
|
30
30
|
[queue-sqs]
|
|
31
|
-
aiobotocore>=3.9.
|
|
31
|
+
aiobotocore>=3.9.2
|
|
32
32
|
|
|
33
33
|
[queues]
|
|
34
|
-
aiobotocore>=3.9.
|
|
34
|
+
aiobotocore>=3.9.2
|
|
35
35
|
|
|
36
36
|
[requester]
|
|
37
|
-
httpx2>=2.13.
|
|
37
|
+
httpx2>=2.13.1
|
|
38
38
|
|
|
39
39
|
[storage]
|
|
40
|
-
aiobotocore>=3.9.
|
|
40
|
+
aiobotocore>=3.9.2
|
|
41
41
|
|
|
42
42
|
[types]
|
|
43
|
-
types-aiobotocore[essential]>=3.9.
|
|
43
|
+
types-aiobotocore[essential]>=3.9.2
|
|
44
44
|
types-aiofiles>=25.1.0.20260518
|
|
45
45
|
|
|
46
46
|
[web3]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "kiba-core"
|
|
3
|
-
version = "0.5.3.
|
|
3
|
+
version = "0.5.3.dev76"
|
|
4
4
|
description = "Kiba Labs' python utilities"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12, <4"
|
|
@@ -16,44 +16,44 @@ api = [
|
|
|
16
16
|
"uvicorn[standard]>=0.53.0",
|
|
17
17
|
]
|
|
18
18
|
core-api = [
|
|
19
|
-
"starlette>=1.
|
|
19
|
+
"starlette>=1.7.0",
|
|
20
20
|
"uvicorn[standard]>=0.53.0",
|
|
21
21
|
]
|
|
22
22
|
storage = [
|
|
23
|
-
"aiobotocore>=3.9.
|
|
23
|
+
"aiobotocore>=3.9.2",
|
|
24
24
|
]
|
|
25
25
|
# TODO(krishan711): remove this in next major update
|
|
26
26
|
queues = [
|
|
27
|
-
"aiobotocore>=3.9.
|
|
27
|
+
"aiobotocore>=3.9.2",
|
|
28
28
|
]
|
|
29
29
|
queue-sqs = [
|
|
30
|
-
"aiobotocore>=3.9.
|
|
30
|
+
"aiobotocore>=3.9.2",
|
|
31
31
|
]
|
|
32
32
|
queue-aqs = [
|
|
33
|
-
"azure-storage-queue[aio]>=12.
|
|
33
|
+
"azure-storage-queue[aio]>=12.18.0",
|
|
34
34
|
]
|
|
35
35
|
queue-cosmos = [
|
|
36
|
-
"azure-cosmos>=4.17.
|
|
36
|
+
"azure-cosmos>=4.17.1",
|
|
37
37
|
]
|
|
38
38
|
database-psql = [
|
|
39
|
-
"sqlalchemy[asyncio]>=2.
|
|
39
|
+
"sqlalchemy[asyncio]>=2.1.3",
|
|
40
40
|
"asyncpg>=0.31.0",
|
|
41
41
|
]
|
|
42
42
|
database-sqlite = [
|
|
43
|
-
"sqlalchemy[asyncio]>=2.
|
|
43
|
+
"sqlalchemy[asyncio]>=2.1.3",
|
|
44
44
|
"aiosqlite>=0.22.1",
|
|
45
45
|
]
|
|
46
46
|
requester = [
|
|
47
|
-
"httpx2>=2.13.
|
|
47
|
+
"httpx2>=2.13.1",
|
|
48
48
|
]
|
|
49
49
|
web3 = [
|
|
50
50
|
"web3>=7.16.0,<8.0.0",
|
|
51
51
|
]
|
|
52
52
|
cron = [
|
|
53
|
-
"apscheduler>=3.11.
|
|
53
|
+
"apscheduler>=3.11.3,<4",
|
|
54
54
|
]
|
|
55
55
|
types = [
|
|
56
|
-
"types-aiobotocore[essential]>=3.9.
|
|
56
|
+
"types-aiobotocore[essential]>=3.9.2",
|
|
57
57
|
"types-aiofiles>=25.1.0.20260518",
|
|
58
58
|
]
|
|
59
59
|
|
|
@@ -134,3 +134,14 @@ def test_json_route_empty_body(client):
|
|
|
134
134
|
data = response.json()
|
|
135
135
|
assert data["request_name"] == "EmptyBody"
|
|
136
136
|
assert data["request_age"] == 50
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@pytest.mark.parametrize("content", ["true", "[1, 2]", "\"text\"", "null", "1"])
|
|
140
|
+
def test_json_route_with_non_object_json(client, content):
|
|
141
|
+
response = client.post(
|
|
142
|
+
"/test?name=NonObject&age=1",
|
|
143
|
+
content=content,
|
|
144
|
+
headers={"Content-Type": "application/json"}
|
|
145
|
+
)
|
|
146
|
+
assert response.status_code == 400
|
|
147
|
+
assert "expected an object" in response.json().get("message", "")
|
|
@@ -184,3 +184,14 @@ def test_error_thrown_by_endpoint(client):
|
|
|
184
184
|
data = dataList[0]
|
|
185
185
|
assert data["request_name"] == "Name"
|
|
186
186
|
assert data["request_age"] == 30
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
@pytest.mark.parametrize("content", ["true", "[1, 2]", "\"text\"", "null", "1"])
|
|
190
|
+
def test_streaming_json_route_with_non_object_json(client, content):
|
|
191
|
+
response = client.post(
|
|
192
|
+
"/test?name=NonObject&age=1",
|
|
193
|
+
content=content,
|
|
194
|
+
headers={"Content-Type": "application/json"}
|
|
195
|
+
)
|
|
196
|
+
assert response.status_code == 400
|
|
197
|
+
assert "expected an object" in response.json().get("message", "")
|