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.
Files changed (99) hide show
  1. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/CHANGELOG.md +1 -0
  2. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/PKG-INFO +10 -10
  3. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/authorizer.py +13 -19
  4. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/json_route.py +4 -9
  5. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/streaming_json_route.py +3 -7
  6. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/logging.py +9 -10
  7. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/queues/aqs.py +2 -2
  8. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/queues/sql.py +1 -0
  9. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/queues/sqs.py +3 -3
  10. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/s3_manager.py +2 -2
  11. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/store/database.py +7 -2
  12. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/store/retriever.py +1 -0
  13. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/json_util.py +5 -5
  14. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/web3/eth_client.py +7 -5
  15. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/kiba_core.egg-info/PKG-INFO +10 -10
  16. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/kiba_core.egg-info/requires.txt +9 -9
  17. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/makefile +3 -4
  18. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/pyproject.toml +11 -11
  19. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/web3/test_rest_eth_client.py +75 -0
  20. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/uv.lock +1008 -924
  21. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/.github/pull_request_template.md +0 -0
  22. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/.github/workflows/deploy.yml +0 -0
  23. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/.github/workflows/pull-request.yml +0 -0
  24. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/.github/workflows/release.yml +0 -0
  25. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/.gitignore +0 -0
  26. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/Dockerfile +0 -0
  27. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/README.md +0 -0
  28. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/__init__.py +0 -0
  29. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/__init__.py +0 -0
  30. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/api_request.py +0 -0
  31. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/api_response.py +0 -0
  32. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/default_routes.py +0 -0
  33. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/health.py +0 -0
  34. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/middleware/__init__.py +0 -0
  35. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/middleware/database_connection_middleware.py +0 -0
  36. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/middleware/exception_handling_middleware.py +0 -0
  37. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/middleware/logging_middleware.py +0 -0
  38. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/api/middleware/server_headers_middleware.py +0 -0
  39. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/aws_requester.py +0 -0
  40. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/caching/__init__.py +0 -0
  41. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/caching/cache.py +0 -0
  42. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/caching/dict_cache.py +0 -0
  43. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/caching/file_cache.py +0 -0
  44. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/exceptions.py +0 -0
  45. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/http/__init__.py +0 -0
  46. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/http/basic_authentication.py +0 -0
  47. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/http/jwt.py +0 -0
  48. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/http/rest_method.py +0 -0
  49. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/notifications/__init__.py +0 -0
  50. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/notifications/discord_client.py +0 -0
  51. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/notifications/notification_client.py +0 -0
  52. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/notifications/slack_client.py +0 -0
  53. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/py.typed +0 -0
  54. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/queues/__init__.py +0 -0
  55. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/queues/cosmos.py +0 -0
  56. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/queues/message_queue.py +0 -0
  57. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/queues/message_queue_processor.py +0 -0
  58. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/queues/model.py +0 -0
  59. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/requester/__init__.py +0 -0
  60. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/requester/requester.py +0 -0
  61. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/service_client.py +0 -0
  62. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/store/__init__.py +0 -0
  63. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/store/saver.py +0 -0
  64. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/__init__.py +0 -0
  65. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/async_util.py +0 -0
  66. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/chain_util.py +0 -0
  67. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/date_util.py +0 -0
  68. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/dict_util.py +0 -0
  69. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/file_util.py +0 -0
  70. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/hashing_util.py +0 -0
  71. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/http_util.py +0 -0
  72. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/list_util.py +0 -0
  73. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/string_util.py +0 -0
  74. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/typing_util.py +0 -0
  75. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/url_util.py +0 -0
  76. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/util/value_holder.py +0 -0
  77. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/web3/__init__.py +0 -0
  78. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/core/web3/multicall3.py +0 -0
  79. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/kiba_core.egg-info/SOURCES.txt +0 -0
  80. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/kiba_core.egg-info/dependency_links.txt +0 -0
  81. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/kiba_core.egg-info/top_level.txt +0 -0
  82. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/setup.cfg +0 -0
  83. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/__init__.py +0 -0
  84. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/api/test_authorizer.py +0 -0
  85. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/api/test_json_route.py +0 -0
  86. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/api/test_streaming_json_route.py +0 -0
  87. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/caching/test_dict_cache.py +0 -0
  88. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/caching/test_file_cache.py +0 -0
  89. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/__init__.py +0 -0
  90. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/test_async_util.py +0 -0
  91. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/test_chain_util.py +0 -0
  92. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/test_date_util.py +0 -0
  93. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/test_dict_util.py +0 -0
  94. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/test_file_util.py +0 -0
  95. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/test_json_util.py +0 -0
  96. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/test_list_util.py +0 -0
  97. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/test_string_util.py +0 -0
  98. {kiba_core-0.5.3.dev51 → kiba_core-0.5.3.dev52}/tests/util/test_url_util.py +0 -0
  99. {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.dev51
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.139.1; extra == "api"
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.3.1; extra == "core-api"
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.7.0; extra == "storage"
18
+ Requires-Dist: aiobotocore>=3.9.0; extra == "storage"
19
19
  Provides-Extra: queues
20
- Requires-Dist: aiobotocore>=3.7.0; extra == "queues"
20
+ Requires-Dist: aiobotocore>=3.9.0; extra == "queues"
21
21
  Provides-Extra: queue-sqs
22
- Requires-Dist: aiobotocore>=3.7.0; extra == "queue-sqs"
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.2; extra == "queue-cosmos"
26
+ Requires-Dist: azure-cosmos>=4.16.3; extra == "queue-cosmos"
27
27
  Provides-Extra: database-psql
28
- Requires-Dist: sqlalchemy[asyncio]>=2.0.51; extra == "database-psql"
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.51; extra == "database-sqlite"
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.7.0; extra == "types"
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[[Arg(KibaApiRequest[ApiRequest], 'request')], _AnyReturn]], typing.Callable[_P, typing.Any]]:
47
- def decorator(func: typing.Callable[[Arg(KibaApiRequest[ApiRequest], 'request')], _AnyReturn]) -> typing.Callable[_P, typing.Any]: # type: ignore[explicit-any]
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=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
- # TODO(krishan711): figure out correct typing here
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[[Arg(KibaApiRequest[ApiRequest], 'request')], _AnyReturn]], typing.Callable[_P, typing.Any]]:
83
- def decorator(func: typing.Callable[[Arg(KibaApiRequest[ApiRequest], 'request')], _AnyReturn]) -> typing.Callable[_P, typing.Any]: # type: ignore[explicit-any]
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=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
- # TODO(krishan711): figure out correct typing here
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[[Arg(KibaApiRequest[ApiRequest], 'request')], _AnyReturn]], typing.Callable[_P, typing.Any]]:
116
- def decorator(func: typing.Callable[[Arg(KibaApiRequest[ApiRequest], 'request')], _AnyReturn]) -> typing.Callable[_P, typing.Any]: # type: ignore[explicit-any]
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=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
- # TODO(krishan711): figure out correct typing here
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[[Arg(KibaApiRequest[ApiRequest], 'request')], typing.Awaitable[ApiResponse]]], typing.Callable[_P, KibaJSONResponse]]:
23
- def decorator(func: typing.Callable[[Arg(KibaApiRequest[ApiRequest], 'request')], typing.Awaitable[ApiResponse]]) -> typing.Callable[_P, KibaJSONResponse]:
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(request=kibaRequest)
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
- # TODO(krishan711): figure out correct typing here
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[_P, StreamingResponse]]:
31
- def decorator(func: typing.Callable[[KibaApiRequest[ApiRequest]], AsyncIterator[ApiResponse]]) -> typing.Callable[_P, StreamingResponse]:
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
- # TODO(krishan711): figure out correct typing here
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[None, float]) -> str:
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=typing.cast(dict[str, str], {'statName': nameValue, 'statKey': keyValue, 'statValue': statValue}))
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=typing.cast(dict[str, str], {'apiAction': actionString, 'apiPath': pathString, 'apiPathPattern': pathPatternString, 'apiQuery': queryString, 'apiResponse': responseString or '', 'apiDuration': durationString or ''}),
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(level=CRITICAL, msg=msg, *args, **kwargs) # type: ignore[misc] # noqa: B026
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(level=ERROR, msg=msg, *args, **kwargs) # type: ignore[misc] # noqa: B026
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(level=ERROR, msg=resolvedMessage, exc_info=exc_info, *args, **kwargs) # type: ignore[misc] # noqa: B026
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(level=WARNING, msg=msg, *args, **kwargs) # type: ignore[misc] # noqa: B026
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(level=INFO, msg=msg, *args, **kwargs) # type: ignore[misc] # noqa: B026
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(level=DEBUG, msg=msg, *args, **kwargs) # type: ignore[misc] # noqa: B026
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.parse_raw(aqsMessage.content)
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.json())
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:
@@ -8,6 +8,7 @@ from collections.abc import Sequence
8
8
  from typing import Any
9
9
 
10
10
  import sqlalchemy
11
+ import sqlalchemy.exc
11
12
  from sqlalchemy.dialects import postgresql as sqlalchemy_psql
12
13
 
13
14
  from core.queues.message_queue import MessageQueue
@@ -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.parse_raw(sqsMessage['Body'])
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.json())
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.json()})
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
- async def execute(self, query: TypedReturnsRows[ResultType], connection: DatabaseConnection | None = None) -> Result[ResultType]:
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[ResultType], await connection.execute(statement=query))
110
+ return typing.cast(Result[typing.Any], await connection.execute(statement=query)) # type: ignore[explicit-any]
@@ -4,6 +4,7 @@ from collections.abc import Sequence
4
4
  from enum import Enum
5
5
 
6
6
  import sqlalchemy
7
+ import sqlalchemy.sql.functions
7
8
  from sqlalchemy import Table
8
9
  from sqlalchemy.sql import Select
9
10
 
@@ -23,13 +23,13 @@ _HAS_LOGGED_FOR_SERIALIZATION_ERROR = False
23
23
 
24
24
 
25
25
  class DatetimeEncoder(json.JSONEncoder):
26
- def default(self, obj: typing.Any) -> str: # type: ignore[explicit-any]
27
- if isinstance(obj, datetime.datetime):
28
- return date_util.datetime_to_string(obj)
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(obj))
30
+ return typing.cast(str, super().default(o))
31
31
  except TypeError:
32
- return str(obj)
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': False, 'callData': chain_util.encode_transaction_data_by_name(contractAbi=contractCall.contractAbi, functionName=contractCall.functionName, arguments=contractCall.arguments)}
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.dev51
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.139.1; extra == "api"
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.3.1; extra == "core-api"
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.7.0; extra == "storage"
18
+ Requires-Dist: aiobotocore>=3.9.0; extra == "storage"
19
19
  Provides-Extra: queues
20
- Requires-Dist: aiobotocore>=3.7.0; extra == "queues"
20
+ Requires-Dist: aiobotocore>=3.9.0; extra == "queues"
21
21
  Provides-Extra: queue-sqs
22
- Requires-Dist: aiobotocore>=3.7.0; extra == "queue-sqs"
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.2; extra == "queue-cosmos"
26
+ Requires-Dist: azure-cosmos>=4.16.3; extra == "queue-cosmos"
27
27
  Provides-Extra: database-psql
28
- Requires-Dist: sqlalchemy[asyncio]>=2.0.51; extra == "database-psql"
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.51; extra == "database-sqlite"
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.7.0; extra == "types"
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.139.1
6
+ fastapi>=0.141.1
7
7
  uvicorn[standard]>=0.51.0
8
8
 
9
9
  [core-api]
10
- starlette>=1.3.1
10
+ starlette>=1.6.0
11
11
  uvicorn[standard]>=0.51.0
12
12
 
13
13
  [database-psql]
14
- sqlalchemy[asyncio]>=2.0.51
14
+ sqlalchemy[asyncio]>=2.0.52
15
15
  asyncpg>=0.31.0
16
16
 
17
17
  [database-sqlite]
18
- sqlalchemy[asyncio]>=2.0.51
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.2
25
+ azure-cosmos>=4.16.3
26
26
 
27
27
  [queue-sqs]
28
- aiobotocore>=3.7.0
28
+ aiobotocore>=3.9.0
29
29
 
30
30
  [queues]
31
- aiobotocore>=3.7.0
31
+ aiobotocore>=3.9.0
32
32
 
33
33
  [requester]
34
34
  httpx>=0.28.1
35
35
 
36
36
  [storage]
37
- aiobotocore>=3.7.0
37
+ aiobotocore>=3.9.0
38
38
 
39
39
  [types]
40
- types-aiobotocore[essential]>=3.7.0
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 --new ./core
13
+ @ uv run lint-check ./core
14
14
 
15
15
  lint-check-ci:
16
- @ uv run lint-check --new ./core --output-file lint-check-results.json --output-format annotations
16
+ @ uv run lint-check ./core --output-file lint-check-results.json --output-format annotations
17
17
 
18
18
  lint-fix:
19
- @ uv run isort --sl -l 1000 ./core
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