kiba-core 0.5.3.dev51__tar.gz → 0.5.3.dev52__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.dev51 → kiba_core-0.5.3.dev52}/CHANGELOG.md +1 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/PKG-INFO +10 -10
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/authorizer.py +13 -19
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/json_route.py +4 -9
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/streaming_json_route.py +3 -7
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/logging.py +9 -10
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/queues/aqs.py +2 -2
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/queues/sql.py +1 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/queues/sqs.py +3 -3
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/s3_manager.py +2 -2
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/store/database.py +7 -2
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/store/retriever.py +1 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/json_util.py +5 -5
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/web3/eth_client.py +7 -5
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/kiba_core.egg-info/PKG-INFO +10 -10
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/kiba_core.egg-info/requires.txt +9 -9
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/makefile +3 -4
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/pyproject.toml +11 -11
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/web3/test_rest_eth_client.py +75 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/uv.lock +1008 -924
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/.github/pull_request_template.md +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/.github/workflows/deploy.yml +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/.github/workflows/pull-request.yml +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/.github/workflows/release.yml +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/.gitignore +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/Dockerfile +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/README.md +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/__init__.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/__init__.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/api_request.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/api_response.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/default_routes.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/health.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/middleware/__init__.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/middleware/database_connection_middleware.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/middleware/exception_handling_middleware.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/middleware/logging_middleware.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/middleware/server_headers_middleware.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/aws_requester.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/caching/__init__.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/caching/cache.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/caching/dict_cache.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/caching/file_cache.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/exceptions.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/http/__init__.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/http/basic_authentication.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/http/jwt.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/http/rest_method.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/notifications/__init__.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/notifications/discord_client.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/notifications/notification_client.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/notifications/slack_client.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/py.typed +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/queues/__init__.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/queues/cosmos.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/queues/message_queue.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/queues/message_queue_processor.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/queues/model.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/requester/__init__.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/requester/requester.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/service_client.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/store/__init__.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/store/saver.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/__init__.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/async_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/chain_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/date_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/dict_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/file_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/hashing_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/http_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/list_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/string_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/typing_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/url_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/value_holder.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/web3/__init__.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/web3/multicall3.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/kiba_core.egg-info/SOURCES.txt +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/kiba_core.egg-info/dependency_links.txt +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/kiba_core.egg-info/top_level.txt +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/setup.cfg +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/__init__.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/api/test_authorizer.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/api/test_json_route.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/api/test_streaming_json_route.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/caching/test_dict_cache.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/caching/test_file_cache.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/__init__.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/test_async_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/test_chain_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/test_date_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/test_dict_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/test_file_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/test_json_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/test_list_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/test_string_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/test_url_util.py +0 -0
- {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/web3/__init__.py +0 -0
|
@@ -33,6 +33,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
|
|
33
33
|
- [MINOR] Truncate discord notification messages to fit api
|
|
34
34
|
- [MINOR] Added `blockNumber` to `EthClient.multicall` function
|
|
35
35
|
- [MINOR] Added `SqlMessageQueue` and `CosmosMessageQueue` to support database backed queues
|
|
36
|
+
- [MINOR] Added `shouldAllowFailures` to `EthClient.multicall` to allow individual calls to fail without reverting the whole batch
|
|
36
37
|
|
|
37
38
|
### Changed
|
|
38
39
|
|
|
@@ -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.dev52
|
|
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
|
|
@@ -9,33 +9,33 @@ Requires-Dist: aiofiles>=25.1.0
|
|
|
9
9
|
Requires-Dist: pydantic>=2.13.4
|
|
10
10
|
Requires-Dist: orjson>=3.11.9
|
|
11
11
|
Provides-Extra: api
|
|
12
|
-
Requires-Dist: fastapi>=0.
|
|
12
|
+
Requires-Dist: fastapi>=0.141.1; extra == "api"
|
|
13
13
|
Requires-Dist: uvicorn[standard]>=0.51.0; extra == "api"
|
|
14
14
|
Provides-Extra: core-api
|
|
15
|
-
Requires-Dist: starlette>=1.
|
|
15
|
+
Requires-Dist: starlette>=1.6.0; extra == "core-api"
|
|
16
16
|
Requires-Dist: uvicorn[standard]>=0.51.0; extra == "core-api"
|
|
17
17
|
Provides-Extra: storage
|
|
18
|
-
Requires-Dist: aiobotocore>=3.
|
|
18
|
+
Requires-Dist: aiobotocore>=3.9.0; extra == "storage"
|
|
19
19
|
Provides-Extra: queues
|
|
20
|
-
Requires-Dist: aiobotocore>=3.
|
|
20
|
+
Requires-Dist: aiobotocore>=3.9.0; extra == "queues"
|
|
21
21
|
Provides-Extra: queue-sqs
|
|
22
|
-
Requires-Dist: aiobotocore>=3.
|
|
22
|
+
Requires-Dist: aiobotocore>=3.9.0; extra == "queue-sqs"
|
|
23
23
|
Provides-Extra: queue-aqs
|
|
24
24
|
Requires-Dist: azure-storage-queue[aio]>=12.17.0; extra == "queue-aqs"
|
|
25
25
|
Provides-Extra: queue-cosmos
|
|
26
|
-
Requires-Dist: azure-cosmos>=4.16.
|
|
26
|
+
Requires-Dist: azure-cosmos>=4.16.3; extra == "queue-cosmos"
|
|
27
27
|
Provides-Extra: database-psql
|
|
28
|
-
Requires-Dist: sqlalchemy[asyncio]>=2.0.
|
|
28
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.0.52; 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.0.
|
|
31
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.0.52; extra == "database-sqlite"
|
|
32
32
|
Requires-Dist: aiosqlite>=0.22.1; extra == "database-sqlite"
|
|
33
33
|
Provides-Extra: requester
|
|
34
34
|
Requires-Dist: httpx>=0.28.1; extra == "requester"
|
|
35
35
|
Provides-Extra: web3
|
|
36
36
|
Requires-Dist: web3>=7.16.0; extra == "web3"
|
|
37
37
|
Provides-Extra: types
|
|
38
|
-
Requires-Dist: types-aiobotocore[essential]>=3.
|
|
38
|
+
Requires-Dist: types-aiobotocore[essential]>=3.9.0; extra == "types"
|
|
39
39
|
Requires-Dist: types-aiofiles>=25.1.0.20260518; extra == "types"
|
|
40
40
|
|
|
41
41
|
# Core-Py
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
import typing
|
|
3
3
|
from collections.abc import AsyncIterator
|
|
4
|
-
from typing import ParamSpec
|
|
5
4
|
|
|
6
|
-
from mypy_extensions import Arg
|
|
7
5
|
from pydantic import BaseModel
|
|
8
6
|
|
|
9
7
|
from core import logging
|
|
@@ -13,7 +11,6 @@ from core.exceptions import UnauthorizedException
|
|
|
13
11
|
from core.http.basic_authentication import BasicAuthentication
|
|
14
12
|
from core.http.jwt import Jwt
|
|
15
13
|
|
|
16
|
-
_P = ParamSpec('_P')
|
|
17
14
|
_AnyReturn = typing.Awaitable[typing.Any] | AsyncIterator[typing.Any] # type: ignore[explicit-any]
|
|
18
15
|
|
|
19
16
|
|
|
@@ -43,19 +40,18 @@ async def _authorize_bearer_jwt[ApiRequest: BaseModel](request: KibaApiRequest[A
|
|
|
43
40
|
|
|
44
41
|
def authorize_bearer_jwt[ApiRequest: BaseModel]( # type: ignore[explicit-any]
|
|
45
42
|
authorizer: Authorizer,
|
|
46
|
-
) -> typing.Callable[[typing.Callable[[
|
|
47
|
-
def decorator(func: typing.Callable[[
|
|
43
|
+
) -> typing.Callable[[typing.Callable[[KibaApiRequest[ApiRequest]], _AnyReturn]], typing.Callable[[KibaApiRequest[ApiRequest]], typing.Any]]:
|
|
44
|
+
def decorator(func: typing.Callable[[KibaApiRequest[ApiRequest]], _AnyReturn]) -> typing.Callable[[KibaApiRequest[ApiRequest]], typing.Any]: # type: ignore[explicit-any]
|
|
48
45
|
@functools.wraps(func)
|
|
49
46
|
async def async_wrapper(request: KibaApiRequest[ApiRequest]) -> typing.Any: # type: ignore[explicit-any, misc]
|
|
50
47
|
request.authJwt = await _authorize_bearer_jwt(request=request, authorizer=authorizer)
|
|
51
|
-
result = func(request
|
|
48
|
+
result = func(request)
|
|
52
49
|
# NOTE(krishan711): this is here to support streaming responses which return an async generator
|
|
53
50
|
if hasattr(result, '__aiter__'):
|
|
54
51
|
return result
|
|
55
52
|
return await result
|
|
56
53
|
|
|
57
|
-
|
|
58
|
-
return async_wrapper # type: ignore[return-value]
|
|
54
|
+
return async_wrapper
|
|
59
55
|
|
|
60
56
|
return decorator
|
|
61
57
|
|
|
@@ -72,26 +68,25 @@ async def get_basic_authentication_from_authorization_signature[ApiRequest: Base
|
|
|
72
68
|
except UnauthorizedException:
|
|
73
69
|
raise
|
|
74
70
|
except BaseException as exception: # noqa: BLE001
|
|
75
|
-
logging.exception(exception) # type: ignore[arg-type]
|
|
71
|
+
logging.exception(exception) # type: ignore[arg-type, ty:invalid-argument-type]
|
|
76
72
|
raise ForbiddenException(message='AUTH_INVALID')
|
|
77
73
|
return BasicAuthentication(username=signerId, password=signatureString)
|
|
78
74
|
|
|
79
75
|
|
|
80
76
|
def authorize_signature[ApiRequest: BaseModel]( # type: ignore[explicit-any]
|
|
81
77
|
authorizer: SignatureAuthorizer,
|
|
82
|
-
) -> typing.Callable[[typing.Callable[[
|
|
83
|
-
def decorator(func: typing.Callable[[
|
|
78
|
+
) -> typing.Callable[[typing.Callable[[KibaApiRequest[ApiRequest]], _AnyReturn]], typing.Callable[[KibaApiRequest[ApiRequest]], typing.Any]]:
|
|
79
|
+
def decorator(func: typing.Callable[[KibaApiRequest[ApiRequest]], _AnyReturn]) -> typing.Callable[[KibaApiRequest[ApiRequest]], typing.Any]: # type: ignore[explicit-any]
|
|
84
80
|
@functools.wraps(func)
|
|
85
81
|
async def async_wrapper(request: KibaApiRequest[ApiRequest]) -> typing.Any: # type: ignore[explicit-any, misc]
|
|
86
82
|
request.authBasic = await get_basic_authentication_from_authorization_signature(request=request, authorizer=authorizer)
|
|
87
|
-
result = func(request
|
|
83
|
+
result = func(request)
|
|
88
84
|
# NOTE(krishan711): this is here to support streaming responses which return an async generator
|
|
89
85
|
if hasattr(result, '__aiter__'):
|
|
90
86
|
return result
|
|
91
87
|
return await result
|
|
92
88
|
|
|
93
|
-
|
|
94
|
-
return async_wrapper # type: ignore[return-value]
|
|
89
|
+
return async_wrapper
|
|
95
90
|
|
|
96
91
|
return decorator
|
|
97
92
|
|
|
@@ -112,8 +107,8 @@ class StaticTokenAuthorizer(TokenAuthorizer):
|
|
|
112
107
|
|
|
113
108
|
def authorize_token[ApiRequest: BaseModel]( # type: ignore[explicit-any]
|
|
114
109
|
authorizer: TokenAuthorizer,
|
|
115
|
-
) -> typing.Callable[[typing.Callable[[
|
|
116
|
-
def decorator(func: typing.Callable[[
|
|
110
|
+
) -> typing.Callable[[typing.Callable[[KibaApiRequest[ApiRequest]], _AnyReturn]], typing.Callable[[KibaApiRequest[ApiRequest]], typing.Any]]:
|
|
111
|
+
def decorator(func: typing.Callable[[KibaApiRequest[ApiRequest]], _AnyReturn]) -> typing.Callable[[KibaApiRequest[ApiRequest]], typing.Any]: # type: ignore[explicit-any]
|
|
117
112
|
@functools.wraps(func)
|
|
118
113
|
async def async_wrapper(request: KibaApiRequest[ApiRequest]) -> typing.Any: # type: ignore[explicit-any, misc]
|
|
119
114
|
authorization = request.headers.get('Authorization')
|
|
@@ -122,13 +117,12 @@ def authorize_token[ApiRequest: BaseModel]( # type: ignore[explicit-any]
|
|
|
122
117
|
if not authorization.startswith('Token '):
|
|
123
118
|
raise ForbiddenException(message='AUTH_INVALID')
|
|
124
119
|
await authorizer.validate_token(authorization[6:])
|
|
125
|
-
result = func(request
|
|
120
|
+
result = func(request)
|
|
126
121
|
# NOTE(krishan711): this is here to support streaming responses which return an async generator
|
|
127
122
|
if hasattr(result, '__aiter__'):
|
|
128
123
|
return result
|
|
129
124
|
return await result
|
|
130
125
|
|
|
131
|
-
|
|
132
|
-
return async_wrapper # type: ignore[return-value]
|
|
126
|
+
return async_wrapper
|
|
133
127
|
|
|
134
128
|
return decorator
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
import typing
|
|
3
|
-
from typing import ParamSpec
|
|
4
3
|
|
|
5
|
-
from mypy_extensions import Arg
|
|
6
4
|
from pydantic import BaseModel
|
|
7
5
|
from pydantic import ValidationError
|
|
8
6
|
|
|
@@ -13,14 +11,12 @@ from core.exceptions import InternalServerErrorException
|
|
|
13
11
|
from core.util import json_util
|
|
14
12
|
from core.util.typing_util import JsonObject
|
|
15
13
|
|
|
16
|
-
_P = ParamSpec('_P')
|
|
17
|
-
|
|
18
14
|
|
|
19
15
|
def json_route[ApiRequest: BaseModel, ApiResponse: BaseModel](
|
|
20
16
|
requestType: typing.Type[ApiRequest],
|
|
21
17
|
responseType: typing.Type[ApiResponse],
|
|
22
|
-
) -> typing.Callable[[typing.Callable[[
|
|
23
|
-
def decorator(func: typing.Callable[[
|
|
18
|
+
) -> typing.Callable[[typing.Callable[[KibaApiRequest[ApiRequest]], typing.Awaitable[ApiResponse]]], typing.Callable[..., typing.Awaitable[KibaJSONResponse]]]:
|
|
19
|
+
def decorator(func: typing.Callable[[KibaApiRequest[ApiRequest]], typing.Awaitable[ApiResponse]]) -> typing.Callable[..., typing.Awaitable[KibaJSONResponse]]:
|
|
24
20
|
@functools.wraps(func)
|
|
25
21
|
async def async_wrapper(*args: typing.Any) -> KibaJSONResponse: # type: ignore[explicit-any, misc]
|
|
26
22
|
receivedRequest = args[0]
|
|
@@ -42,12 +38,11 @@ def json_route[ApiRequest: BaseModel, ApiResponse: BaseModel](
|
|
|
42
38
|
raise BadRequestException(f'Invalid request: {validationErrorMessage}')
|
|
43
39
|
kibaRequest: KibaApiRequest[ApiRequest] = KibaApiRequest(scope=receivedRequest.scope, receive=receivedRequest._receive, send=receivedRequest._send) # noqa: SLF001
|
|
44
40
|
kibaRequest.data = requestParams
|
|
45
|
-
receivedResponse = await func(
|
|
41
|
+
receivedResponse = await func(kibaRequest)
|
|
46
42
|
if not isinstance(receivedResponse, responseType):
|
|
47
43
|
raise InternalServerErrorException(f'Expected response to be of type {responseType}, got {type(receivedResponse)}')
|
|
48
44
|
return KibaJSONResponse(content=receivedResponse.model_dump())
|
|
49
45
|
|
|
50
|
-
|
|
51
|
-
return async_wrapper # type: ignore[return-value]
|
|
46
|
+
return async_wrapper
|
|
52
47
|
|
|
53
48
|
return decorator
|
|
@@ -2,7 +2,6 @@ import functools
|
|
|
2
2
|
import inspect
|
|
3
3
|
import typing
|
|
4
4
|
from collections.abc import AsyncIterator
|
|
5
|
-
from typing import ParamSpec
|
|
6
5
|
|
|
7
6
|
from pydantic import BaseModel
|
|
8
7
|
from pydantic import ValidationError
|
|
@@ -14,8 +13,6 @@ from core.exceptions import InternalServerErrorException
|
|
|
14
13
|
from core.util import json_util
|
|
15
14
|
from core.util.typing_util import JsonObject
|
|
16
15
|
|
|
17
|
-
_P = ParamSpec('_P')
|
|
18
|
-
|
|
19
16
|
|
|
20
17
|
async def _convert_to_json_generator[T: BaseModel](response_iterator: AsyncIterator[T], expectedType: typing.Type[T]) -> AsyncIterator[bytes]:
|
|
21
18
|
async for content in response_iterator:
|
|
@@ -27,8 +24,8 @@ async def _convert_to_json_generator[T: BaseModel](response_iterator: AsyncItera
|
|
|
27
24
|
def streaming_json_route[ApiRequest: BaseModel, ApiResponse: BaseModel](
|
|
28
25
|
requestType: typing.Type[ApiRequest],
|
|
29
26
|
responseType: typing.Type[ApiResponse],
|
|
30
|
-
) -> typing.Callable[[typing.Callable[[KibaApiRequest[ApiRequest]], AsyncIterator[ApiResponse]]], typing.Callable[
|
|
31
|
-
def decorator(func: typing.Callable[[KibaApiRequest[ApiRequest]], AsyncIterator[ApiResponse]]) -> typing.Callable[
|
|
27
|
+
) -> typing.Callable[[typing.Callable[[KibaApiRequest[ApiRequest]], AsyncIterator[ApiResponse]]], typing.Callable[..., typing.Awaitable[StreamingResponse]]]:
|
|
28
|
+
def decorator(func: typing.Callable[[KibaApiRequest[ApiRequest]], AsyncIterator[ApiResponse]]) -> typing.Callable[..., typing.Awaitable[StreamingResponse]]:
|
|
32
29
|
@functools.wraps(func)
|
|
33
30
|
async def async_wrapper(*args: typing.Any, **kwargs: typing.Any) -> StreamingResponse: # type: ignore[explicit-any, misc]
|
|
34
31
|
receivedRequest = kwargs.get('request', args[0] if args else None)
|
|
@@ -58,7 +55,6 @@ def streaming_json_route[ApiRequest: BaseModel, ApiResponse: BaseModel](
|
|
|
58
55
|
# NOTE(krishan711): we set content-encoding to identity to prevent gzip from trying to process it (cos it buffers all the content)
|
|
59
56
|
return StreamingResponse(content=wrappedGenerator, media_type='application/x-ndjson', headers={'Content-Encoding': 'identity'})
|
|
60
57
|
|
|
61
|
-
|
|
62
|
-
return async_wrapper # type: ignore[return-value]
|
|
58
|
+
return async_wrapper
|
|
63
59
|
|
|
64
60
|
return decorator
|
|
@@ -4,7 +4,6 @@ import logging
|
|
|
4
4
|
import os
|
|
5
5
|
import re
|
|
6
6
|
import sys
|
|
7
|
-
import typing
|
|
8
7
|
from collections.abc import Callable
|
|
9
8
|
from collections.abc import Collection
|
|
10
9
|
from logging import Formatter
|
|
@@ -153,7 +152,7 @@ def init_basic_logging(showDebug: bool = False) -> None:
|
|
|
153
152
|
init_logger(logger=logger, loggingLevel=loggingLevel, handler=handler)
|
|
154
153
|
|
|
155
154
|
|
|
156
|
-
def _serialize_numeric_value(value: Union[
|
|
155
|
+
def _serialize_numeric_value(value: Union[float, None]) -> str:
|
|
157
156
|
if value is None:
|
|
158
157
|
return ''
|
|
159
158
|
roundedNumber = round(value, 6)
|
|
@@ -169,7 +168,7 @@ def stat(name: str, key: str, value: float = 1) -> None:
|
|
|
169
168
|
nameValue = _serialize_string_value(value=str(name))
|
|
170
169
|
keyValue = _serialize_string_value(value=str(key))
|
|
171
170
|
statValue = _serialize_numeric_value(value=value)
|
|
172
|
-
STAT_LOGGER.log(level=logging.INFO, msg='', extra=
|
|
171
|
+
STAT_LOGGER.log(level=logging.INFO, msg='', extra={'statName': nameValue, 'statKey': keyValue, 'statValue': statValue})
|
|
173
172
|
|
|
174
173
|
|
|
175
174
|
# TODO(krishan711): make pathPattern mandatory in next major release
|
|
@@ -184,7 +183,7 @@ def api(action: str, path: str, query: str, pathPattern: str | None = None, resp
|
|
|
184
183
|
API_LOGGER.log(
|
|
185
184
|
level=logging.INFO,
|
|
186
185
|
msg='',
|
|
187
|
-
extra=
|
|
186
|
+
extra={'apiAction': actionString, 'apiPath': pathString, 'apiPathPattern': pathPatternString, 'apiQuery': queryString, 'apiResponse': responseString or '', 'apiDuration': durationString or ''},
|
|
188
187
|
)
|
|
189
188
|
|
|
190
189
|
|
|
@@ -204,11 +203,11 @@ def _log(level: int, msg: str, *args: Any, **kwargs: Any) -> None: # type: igno
|
|
|
204
203
|
|
|
205
204
|
|
|
206
205
|
def critical(msg: str, *args: Any, **kwargs: Any) -> None: # type: ignore[explicit-any]
|
|
207
|
-
_log(
|
|
206
|
+
_log(CRITICAL, msg, *args, **kwargs)
|
|
208
207
|
|
|
209
208
|
|
|
210
209
|
def error(msg: str, *args: Any, **kwargs: Any) -> None: # type: ignore[explicit-any]
|
|
211
|
-
_log(
|
|
210
|
+
_log(ERROR, msg, *args, **kwargs)
|
|
212
211
|
|
|
213
212
|
|
|
214
213
|
def exception(msg: Union[str, Exception], *args: Any, exc_info: bool = True, **kwargs: Any) -> None: # type: ignore[explicit-any]
|
|
@@ -218,19 +217,19 @@ def exception(msg: Union[str, Exception], *args: Any, exc_info: bool = True, **k
|
|
|
218
217
|
resolvedMessage = str(msg)
|
|
219
218
|
else:
|
|
220
219
|
resolvedMessage = msg
|
|
221
|
-
_log(
|
|
220
|
+
_log(ERROR, resolvedMessage, *args, exc_info=exc_info, **kwargs)
|
|
222
221
|
|
|
223
222
|
|
|
224
223
|
def warning(msg: str, *args: Any, **kwargs: Any) -> None: # type: ignore[explicit-any]
|
|
225
|
-
_log(
|
|
224
|
+
_log(WARNING, msg, *args, **kwargs)
|
|
226
225
|
|
|
227
226
|
|
|
228
227
|
def info(msg: str, *args: Any, **kwargs: Any) -> None: # type: ignore[explicit-any]
|
|
229
|
-
_log(
|
|
228
|
+
_log(INFO, msg, *args, **kwargs)
|
|
230
229
|
|
|
231
230
|
|
|
232
231
|
def debug(msg: str, *args: Any, **kwargs: Any) -> None: # type: ignore[explicit-any]
|
|
233
|
-
_log(
|
|
232
|
+
_log(DEBUG, msg, *args, **kwargs)
|
|
234
233
|
|
|
235
234
|
|
|
236
235
|
def basicConfig(**kwargs: Any) -> None: # type: ignore[explicit-any] # noqa: N802 # noqa: B026
|
|
@@ -18,7 +18,7 @@ class AqsMessage(Message):
|
|
|
18
18
|
|
|
19
19
|
@classmethod
|
|
20
20
|
def from_aqs_message(cls, aqsMessage: RawAqsMessage) -> AqsMessage:
|
|
21
|
-
message = Message.
|
|
21
|
+
message = Message.model_validate_json(aqsMessage.content)
|
|
22
22
|
return cls(
|
|
23
23
|
command=message.command,
|
|
24
24
|
content=message.content,
|
|
@@ -54,7 +54,7 @@ class AqsMessageQueue(MessageQueue[AqsMessage]):
|
|
|
54
54
|
if not self._aqsClient:
|
|
55
55
|
raise InternalServerErrorException('You need to call .connect() before trying to send messages')
|
|
56
56
|
message.prepare_for_send()
|
|
57
|
-
await self._aqsClient.send_message(visibility_timeout=delaySeconds, content=message.
|
|
57
|
+
await self._aqsClient.send_message(visibility_timeout=delaySeconds, content=message.model_dump_json())
|
|
58
58
|
|
|
59
59
|
async def send_messages(self, messages: Sequence[Message], delaySeconds: int = 0) -> None:
|
|
60
60
|
if not self._aqsClient:
|
|
@@ -27,7 +27,7 @@ class SqsMessage(Message):
|
|
|
27
27
|
|
|
28
28
|
@classmethod
|
|
29
29
|
def from_sqs_message(cls, sqsMessage: RawSqsMessageTypeDef) -> SqsMessage:
|
|
30
|
-
message = Message.
|
|
30
|
+
message = Message.model_validate_json(sqsMessage['Body'])
|
|
31
31
|
return cls(
|
|
32
32
|
command=message.command,
|
|
33
33
|
content=message.content,
|
|
@@ -61,7 +61,7 @@ class SqsMessageQueue(MessageQueue[SqsMessage]):
|
|
|
61
61
|
if not self._sqsClient:
|
|
62
62
|
raise InternalServerErrorException('You need to call .connect() before trying to send messages')
|
|
63
63
|
message.prepare_for_send()
|
|
64
|
-
await self._sqsClient.send_message(QueueUrl=self.queueUrl, DelaySeconds=delaySeconds, MessageAttributes={}, MessageBody=message.
|
|
64
|
+
await self._sqsClient.send_message(QueueUrl=self.queueUrl, DelaySeconds=delaySeconds, MessageAttributes={}, MessageBody=message.model_dump_json())
|
|
65
65
|
|
|
66
66
|
async def send_messages(self, messages: Sequence[Message], delaySeconds: int = 0) -> None:
|
|
67
67
|
if not self._sqsClient:
|
|
@@ -71,7 +71,7 @@ class SqsMessageQueue(MessageQueue[SqsMessage]):
|
|
|
71
71
|
requests: list[SendMessageBatchRequestEntryTypeDef] = []
|
|
72
72
|
for index, message in enumerate(messageChunk):
|
|
73
73
|
message.prepare_for_send()
|
|
74
|
-
requests.append({'Id': str(index), 'DelaySeconds': int(delaySeconds), 'MessageAttributes': {}, 'MessageBody': message.
|
|
74
|
+
requests.append({'Id': str(index), 'DelaySeconds': int(delaySeconds), 'MessageAttributes': {}, 'MessageBody': message.model_dump_json()})
|
|
75
75
|
response = await self._sqsClient.send_message_batch(QueueUrl=self.queueUrl, Entries=requests)
|
|
76
76
|
failures += response.get('Failed', [])
|
|
77
77
|
if len(failures) > 0:
|
|
@@ -94,7 +94,7 @@ class S3Manager:
|
|
|
94
94
|
raise InternalServerErrorException('You need to call .connect() before trying to write to s3')
|
|
95
95
|
targetBucket, targetKey = self._split_path_to_bucket_key(path=targetPath)
|
|
96
96
|
extraArgs = self._get_extra_args(accessControl=accessControl, cacheControl=cacheControl, contentType=contentType or self._get_file_mimetype(fileName=targetKey))
|
|
97
|
-
await self._s3Client.put_object(Body=content, Bucket=targetBucket, Key=targetKey, **extraArgs) # type: ignore[arg-type]
|
|
97
|
+
await self._s3Client.put_object(Body=content, Bucket=targetBucket, Key=targetKey, **extraArgs) # type: ignore[arg-type, ty:invalid-argument-type]
|
|
98
98
|
|
|
99
99
|
async def upload_file(self, filePath: str, targetPath: str, accessControl: str | None = None, cacheControl: str | None = None, contentType: str | None = None) -> None:
|
|
100
100
|
if not self._s3Client:
|
|
@@ -124,7 +124,7 @@ class S3Manager:
|
|
|
124
124
|
sourceBucket, sourceKey = self._split_path_to_bucket_key(path=source)
|
|
125
125
|
targetBucket, targetKey = self._split_path_to_bucket_key(path=target)
|
|
126
126
|
extraArgs = self._get_extra_args(accessControl=accessControl, cacheControl=cacheControl, contentType=contentType or self._get_file_mimetype(fileName=targetKey))
|
|
127
|
-
await self._s3Client.copy_object(CopySource={'Bucket': sourceBucket, 'Key': sourceKey}, Bucket=targetBucket, Key=targetKey, MetadataDirective='REPLACE', **extraArgs) # type: ignore[arg-type]
|
|
127
|
+
await self._s3Client.copy_object(CopySource={'Bucket': sourceBucket, 'Key': sourceKey}, Bucket=targetBucket, Key=targetKey, MetadataDirective='REPLACE', **extraArgs) # type: ignore[arg-type, ty:invalid-argument-type]
|
|
128
128
|
|
|
129
129
|
async def delete_file(self, filePath: str) -> None:
|
|
130
130
|
if not self._s3Client:
|
|
@@ -5,6 +5,7 @@ from collections.abc import AsyncIterator
|
|
|
5
5
|
from typing import TypeVar
|
|
6
6
|
|
|
7
7
|
import sqlalchemy
|
|
8
|
+
import sqlalchemy.exc
|
|
8
9
|
from sqlalchemy.engine import Result
|
|
9
10
|
from sqlalchemy.ext.asyncio import AsyncConnection
|
|
10
11
|
from sqlalchemy.ext.asyncio import AsyncEngine
|
|
@@ -95,11 +96,15 @@ class Database:
|
|
|
95
96
|
await self.disconnect()
|
|
96
97
|
await self.connect()
|
|
97
98
|
|
|
98
|
-
|
|
99
|
+
@typing.overload
|
|
100
|
+
async def execute(self, query: TypedReturnsRows[ResultType], connection: DatabaseConnection | None = None) -> Result[ResultType]: ...
|
|
101
|
+
@typing.overload
|
|
102
|
+
async def execute(self, query: sqlalchemy.sql.Executable, connection: DatabaseConnection | None = None) -> Result[typing.Any]: ... # type: ignore[explicit-any]
|
|
103
|
+
async def execute(self, query: sqlalchemy.sql.Executable, connection: DatabaseConnection | None = None) -> Result[typing.Any]: # type: ignore[explicit-any]
|
|
99
104
|
if not self._engine:
|
|
100
105
|
raise InternalServerErrorException(message='Connection has not been established. Please called collect() first.')
|
|
101
106
|
if not connection:
|
|
102
107
|
connection = self._get_context_connection()
|
|
103
108
|
if not connection:
|
|
104
109
|
raise InternalServerErrorException(message='No connection found. Please provide a connection or call create_context_connection() for the context.')
|
|
105
|
-
return typing.cast(Result[
|
|
110
|
+
return typing.cast(Result[typing.Any], await connection.execute(statement=query)) # type: ignore[explicit-any]
|
|
@@ -23,13 +23,13 @@ _HAS_LOGGED_FOR_SERIALIZATION_ERROR = False
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class DatetimeEncoder(json.JSONEncoder):
|
|
26
|
-
def default(self,
|
|
27
|
-
if isinstance(
|
|
28
|
-
return date_util.datetime_to_string(
|
|
26
|
+
def default(self, o: typing.Any) -> str: # type: ignore[explicit-any]
|
|
27
|
+
if isinstance(o, datetime.datetime):
|
|
28
|
+
return date_util.datetime_to_string(o)
|
|
29
29
|
try:
|
|
30
|
-
return typing.cast(str, super().default(
|
|
30
|
+
return typing.cast(str, super().default(o))
|
|
31
31
|
except TypeError:
|
|
32
|
-
return str(
|
|
32
|
+
return str(o)
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
def dumpb(obj: Any) -> bytes: # type: ignore[explicit-any]
|
|
@@ -222,7 +222,9 @@ class EthClientInterface:
|
|
|
222
222
|
raise TransactionFailedException(transactionReceipt=transactionReceipt)
|
|
223
223
|
return transactionReceipt
|
|
224
224
|
|
|
225
|
-
async def multicall(self, contractCalls: list[ContractCall], shouldUseMulticall3: bool = True, blockNumber: int | None = None) -> list[ListAny]:
|
|
225
|
+
async def multicall(self, contractCalls: list[ContractCall], shouldUseMulticall3: bool = True, blockNumber: int | None = None, shouldAllowFailures: bool = False) -> list[ListAny]:
|
|
226
|
+
# NOTE: when shouldAllowFailures=True, a call that reverts on-chain does not fail the whole batch -
|
|
227
|
+
# its slot in the returned list is [None] instead of a decoded value. Callers must check for that per-slot.
|
|
226
228
|
multicall3Address = CHAIN_ID_MULTICALL3_ADDRESS_MAP.get(self.chainId) if shouldUseMulticall3 else None
|
|
227
229
|
if not multicall3Address or not shouldUseMulticall3:
|
|
228
230
|
results = await asyncio.gather(*[self.call(contractCall=contractCall, blockNumber=blockNumber) for contractCall in contractCalls])
|
|
@@ -233,7 +235,7 @@ class EthClientInterface:
|
|
|
233
235
|
functionName='aggregate3',
|
|
234
236
|
arguments={
|
|
235
237
|
'calls': [
|
|
236
|
-
{'target': contractCall.toAddress, 'allowFailure':
|
|
238
|
+
{'target': contractCall.toAddress, 'allowFailure': shouldAllowFailures, 'callData': chain_util.encode_transaction_data_by_name(contractAbi=contractCall.contractAbi, functionName=contractCall.functionName, arguments=contractCall.arguments)}
|
|
237
239
|
for contractCall in contractCalls
|
|
238
240
|
]
|
|
239
241
|
},
|
|
@@ -453,16 +455,16 @@ class RestEthClient(EthClientInterface):
|
|
|
453
455
|
if 'chainId' not in params:
|
|
454
456
|
if chainId is None:
|
|
455
457
|
chainId = self.chainId
|
|
456
|
-
params['chainId'] = hex(chainId) # type: ignore[typeddict-item]
|
|
458
|
+
params['chainId'] = hex(chainId) # type: ignore[typeddict-item, ty:invalid-assignment]
|
|
457
459
|
if 'nonce' not in params:
|
|
458
460
|
if nonce is None:
|
|
459
461
|
nonce = await self.get_transaction_count(address=fromAddress)
|
|
460
|
-
params['nonce'] = hex(nonce) # type: ignore[typeddict-item]
|
|
462
|
+
params['nonce'] = hex(nonce) # type: ignore[typeddict-item, ty:invalid-assignment]
|
|
461
463
|
if 'gas' not in params:
|
|
462
464
|
if gas is None:
|
|
463
465
|
response = await self._make_request(method='eth_estimateGas', params=[params])
|
|
464
466
|
gas = int(response['result'], 16)
|
|
465
|
-
params['gas'] = hex(gas) # type: ignore[typeddict-item]
|
|
467
|
+
params['gas'] = hex(gas) # type: ignore[typeddict-item, ty:invalid-assignment]
|
|
466
468
|
if 'gasPrice' not in params:
|
|
467
469
|
if 'maxPriorityFeePerGas' not in params:
|
|
468
470
|
if maxPriorityFeePerGas is None:
|
|
@@ -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.dev52
|
|
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
|
|
@@ -9,33 +9,33 @@ Requires-Dist: aiofiles>=25.1.0
|
|
|
9
9
|
Requires-Dist: pydantic>=2.13.4
|
|
10
10
|
Requires-Dist: orjson>=3.11.9
|
|
11
11
|
Provides-Extra: api
|
|
12
|
-
Requires-Dist: fastapi>=0.
|
|
12
|
+
Requires-Dist: fastapi>=0.141.1; extra == "api"
|
|
13
13
|
Requires-Dist: uvicorn[standard]>=0.51.0; extra == "api"
|
|
14
14
|
Provides-Extra: core-api
|
|
15
|
-
Requires-Dist: starlette>=1.
|
|
15
|
+
Requires-Dist: starlette>=1.6.0; extra == "core-api"
|
|
16
16
|
Requires-Dist: uvicorn[standard]>=0.51.0; extra == "core-api"
|
|
17
17
|
Provides-Extra: storage
|
|
18
|
-
Requires-Dist: aiobotocore>=3.
|
|
18
|
+
Requires-Dist: aiobotocore>=3.9.0; extra == "storage"
|
|
19
19
|
Provides-Extra: queues
|
|
20
|
-
Requires-Dist: aiobotocore>=3.
|
|
20
|
+
Requires-Dist: aiobotocore>=3.9.0; extra == "queues"
|
|
21
21
|
Provides-Extra: queue-sqs
|
|
22
|
-
Requires-Dist: aiobotocore>=3.
|
|
22
|
+
Requires-Dist: aiobotocore>=3.9.0; extra == "queue-sqs"
|
|
23
23
|
Provides-Extra: queue-aqs
|
|
24
24
|
Requires-Dist: azure-storage-queue[aio]>=12.17.0; extra == "queue-aqs"
|
|
25
25
|
Provides-Extra: queue-cosmos
|
|
26
|
-
Requires-Dist: azure-cosmos>=4.16.
|
|
26
|
+
Requires-Dist: azure-cosmos>=4.16.3; extra == "queue-cosmos"
|
|
27
27
|
Provides-Extra: database-psql
|
|
28
|
-
Requires-Dist: sqlalchemy[asyncio]>=2.0.
|
|
28
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.0.52; 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.0.
|
|
31
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.0.52; extra == "database-sqlite"
|
|
32
32
|
Requires-Dist: aiosqlite>=0.22.1; extra == "database-sqlite"
|
|
33
33
|
Provides-Extra: requester
|
|
34
34
|
Requires-Dist: httpx>=0.28.1; extra == "requester"
|
|
35
35
|
Provides-Extra: web3
|
|
36
36
|
Requires-Dist: web3>=7.16.0; extra == "web3"
|
|
37
37
|
Provides-Extra: types
|
|
38
|
-
Requires-Dist: types-aiobotocore[essential]>=3.
|
|
38
|
+
Requires-Dist: types-aiobotocore[essential]>=3.9.0; extra == "types"
|
|
39
39
|
Requires-Dist: types-aiofiles>=25.1.0.20260518; extra == "types"
|
|
40
40
|
|
|
41
41
|
# Core-Py
|
|
@@ -3,41 +3,41 @@ pydantic>=2.13.4
|
|
|
3
3
|
orjson>=3.11.9
|
|
4
4
|
|
|
5
5
|
[api]
|
|
6
|
-
fastapi>=0.
|
|
6
|
+
fastapi>=0.141.1
|
|
7
7
|
uvicorn[standard]>=0.51.0
|
|
8
8
|
|
|
9
9
|
[core-api]
|
|
10
|
-
starlette>=1.
|
|
10
|
+
starlette>=1.6.0
|
|
11
11
|
uvicorn[standard]>=0.51.0
|
|
12
12
|
|
|
13
13
|
[database-psql]
|
|
14
|
-
sqlalchemy[asyncio]>=2.0.
|
|
14
|
+
sqlalchemy[asyncio]>=2.0.52
|
|
15
15
|
asyncpg>=0.31.0
|
|
16
16
|
|
|
17
17
|
[database-sqlite]
|
|
18
|
-
sqlalchemy[asyncio]>=2.0.
|
|
18
|
+
sqlalchemy[asyncio]>=2.0.52
|
|
19
19
|
aiosqlite>=0.22.1
|
|
20
20
|
|
|
21
21
|
[queue-aqs]
|
|
22
22
|
azure-storage-queue[aio]>=12.17.0
|
|
23
23
|
|
|
24
24
|
[queue-cosmos]
|
|
25
|
-
azure-cosmos>=4.16.
|
|
25
|
+
azure-cosmos>=4.16.3
|
|
26
26
|
|
|
27
27
|
[queue-sqs]
|
|
28
|
-
aiobotocore>=3.
|
|
28
|
+
aiobotocore>=3.9.0
|
|
29
29
|
|
|
30
30
|
[queues]
|
|
31
|
-
aiobotocore>=3.
|
|
31
|
+
aiobotocore>=3.9.0
|
|
32
32
|
|
|
33
33
|
[requester]
|
|
34
34
|
httpx>=0.28.1
|
|
35
35
|
|
|
36
36
|
[storage]
|
|
37
|
-
aiobotocore>=3.
|
|
37
|
+
aiobotocore>=3.9.0
|
|
38
38
|
|
|
39
39
|
[types]
|
|
40
|
-
types-aiobotocore[essential]>=3.
|
|
40
|
+
types-aiobotocore[essential]>=3.9.0
|
|
41
41
|
types-aiofiles>=25.1.0.20260518
|
|
42
42
|
|
|
43
43
|
[web3]
|
|
@@ -10,14 +10,13 @@ list-outdated: install
|
|
|
10
10
|
@ pip list -o
|
|
11
11
|
|
|
12
12
|
lint-check:
|
|
13
|
-
@ uv run lint-check
|
|
13
|
+
@ uv run lint-check ./core
|
|
14
14
|
|
|
15
15
|
lint-check-ci:
|
|
16
|
-
@ uv run lint-check
|
|
16
|
+
@ uv run lint-check ./core --output-file lint-check-results.json --output-format annotations
|
|
17
17
|
|
|
18
18
|
lint-fix:
|
|
19
|
-
@ uv run
|
|
20
|
-
@ uv run lint-check --new --fix ./core
|
|
19
|
+
@ uv run lint-check --fix ./core
|
|
21
20
|
|
|
22
21
|
type-check:
|
|
23
22
|
@ uv run type-check ./core
|