kiba-core 0.5.3.dev59__tar.gz → 0.5.3.dev60__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 (105) hide show
  1. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/PKG-INFO +1 -1
  2. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/util/json_util.py +11 -20
  3. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/kiba_core.egg-info/PKG-INFO +1 -1
  4. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/pyproject.toml +1 -1
  5. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/util/test_json_util.py +49 -6
  6. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/.github/pull_request_template.md +0 -0
  7. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/.github/workflows/deploy.yml +0 -0
  8. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/.github/workflows/pull-request.yml +0 -0
  9. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/.github/workflows/release.yml +0 -0
  10. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/.gitignore +0 -0
  11. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/CHANGELOG.md +0 -0
  12. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/Dockerfile +0 -0
  13. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/README.md +0 -0
  14. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/__init__.py +0 -0
  15. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/api/__init__.py +0 -0
  16. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/api/api_request.py +0 -0
  17. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/api/api_response.py +0 -0
  18. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/api/authorizer.py +0 -0
  19. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/api/default_routes.py +0 -0
  20. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/api/health.py +0 -0
  21. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/api/json_route.py +0 -0
  22. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/api/middleware/__init__.py +0 -0
  23. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/api/middleware/database_connection_middleware.py +0 -0
  24. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/api/middleware/exception_handling_middleware.py +0 -0
  25. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/api/middleware/logging_middleware.py +0 -0
  26. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/api/middleware/server_headers_middleware.py +0 -0
  27. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/api/streaming_json_route.py +0 -0
  28. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/aws_requester.py +0 -0
  29. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/caching/__init__.py +0 -0
  30. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/caching/cache.py +0 -0
  31. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/caching/dict_cache.py +0 -0
  32. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/caching/file_cache.py +0 -0
  33. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/exceptions.py +0 -0
  34. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/http/__init__.py +0 -0
  35. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/http/basic_authentication.py +0 -0
  36. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/http/jwt.py +0 -0
  37. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/http/rest_method.py +0 -0
  38. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/logging.py +0 -0
  39. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/notifications/__init__.py +0 -0
  40. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/notifications/discord_client.py +0 -0
  41. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/notifications/notification_client.py +0 -0
  42. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/notifications/slack_client.py +0 -0
  43. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/py.typed +0 -0
  44. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/queues/__init__.py +0 -0
  45. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/queues/aqs.py +0 -0
  46. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/queues/cosmos.py +0 -0
  47. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/queues/message_queue.py +0 -0
  48. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/queues/message_queue_processor.py +0 -0
  49. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/queues/model.py +0 -0
  50. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/queues/sql.py +0 -0
  51. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/queues/sqs.py +0 -0
  52. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/requester/__init__.py +0 -0
  53. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/requester/requester.py +0 -0
  54. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/s3_manager.py +0 -0
  55. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/service_client.py +0 -0
  56. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/store/__init__.py +0 -0
  57. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/store/database.py +0 -0
  58. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/store/retriever.py +0 -0
  59. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/store/saver.py +0 -0
  60. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/util/__init__.py +0 -0
  61. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/util/async_util.py +0 -0
  62. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/util/chain_util.py +0 -0
  63. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/util/date_util.py +0 -0
  64. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/util/dict_util.py +0 -0
  65. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/util/file_util.py +0 -0
  66. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/util/hashing_util.py +0 -0
  67. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/util/http_util.py +0 -0
  68. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/util/list_util.py +0 -0
  69. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/util/string_util.py +0 -0
  70. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/util/typing_util.py +0 -0
  71. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/util/url_util.py +0 -0
  72. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/util/value_holder.py +0 -0
  73. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/web3/__init__.py +0 -0
  74. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/web3/eth_client.py +0 -0
  75. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/core/web3/multicall3.py +0 -0
  76. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/kiba_core.egg-info/SOURCES.txt +0 -0
  77. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/kiba_core.egg-info/dependency_links.txt +0 -0
  78. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/kiba_core.egg-info/requires.txt +0 -0
  79. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/kiba_core.egg-info/top_level.txt +0 -0
  80. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/makefile +0 -0
  81. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/setup.cfg +0 -0
  82. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/__init__.py +0 -0
  83. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/api/test_api_response.py +0 -0
  84. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/api/test_authorizer.py +0 -0
  85. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/api/test_exception_handling_middleware.py +0 -0
  86. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/api/test_json_route.py +0 -0
  87. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/api/test_streaming_json_route.py +0 -0
  88. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/caching/test_dict_cache.py +0 -0
  89. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/caching/test_file_cache.py +0 -0
  90. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/requester/__init__.py +0 -0
  91. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/requester/test_requester.py +0 -0
  92. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/test_database.py +0 -0
  93. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/test_exceptions.py +0 -0
  94. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/util/__init__.py +0 -0
  95. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/util/test_async_util.py +0 -0
  96. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/util/test_chain_util.py +0 -0
  97. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/util/test_date_util.py +0 -0
  98. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/util/test_dict_util.py +0 -0
  99. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/util/test_file_util.py +0 -0
  100. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/util/test_list_util.py +0 -0
  101. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/util/test_string_util.py +0 -0
  102. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/util/test_url_util.py +0 -0
  103. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/web3/__init__.py +0 -0
  104. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/tests/web3/test_rest_eth_client.py +0 -0
  105. {kiba_core-0.5.3.dev59 → kiba_core-0.5.3.dev60}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kiba-core
3
- Version: 0.5.3.dev59
3
+ Version: 0.5.3.dev60
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
@@ -1,13 +1,11 @@
1
- import datetime
2
- import json
3
1
  import typing
4
2
  from typing import Any
5
3
 
6
4
  import orjson
5
+ import pydantic_core
7
6
 
8
7
  from core import logging
9
8
  from core.exceptions import KibaException
10
- from core.util import date_util
11
9
  from core.util.typing_util import Json
12
10
 
13
11
 
@@ -22,28 +20,19 @@ class JsonEncodeException(KibaException):
22
20
  _HAS_LOGGED_FOR_SERIALIZATION_ERROR = False
23
21
 
24
22
 
25
- class DatetimeEncoder(json.JSONEncoder):
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
- try:
30
- return typing.cast(str, super().default(o))
31
- except TypeError:
32
- return str(o)
33
-
34
-
35
23
  def dumpb(obj: Any) -> bytes: # type: ignore[explicit-any]
36
24
  global _HAS_LOGGED_FOR_SERIALIZATION_ERROR # noqa: PLW0603
37
25
  try:
38
- return orjson.dumps(obj)
26
+ # NOTE(krishan711): Keep UTC datetime output aligned with pydantic's ISO 8601 format.
27
+ return orjson.dumps(obj, option=orjson.OPT_UTC_Z)
39
28
  except TypeError as exception:
40
29
  if str(exception) == 'Integer exceeds 64-bit range':
41
30
  if not _HAS_LOGGED_FOR_SERIALIZATION_ERROR:
42
- logging.warning(f'There was an error during the serialization an object: `{exception}`, falling back to json.')
31
+ logging.warning(f'There was an error during the serialization an object: `{exception}`, falling back to pydantic.')
43
32
  _HAS_LOGGED_FOR_SERIALIZATION_ERROR = True
44
- return json.dumps(obj, cls=DatetimeEncoder).encode('utf-8')
45
- raise JsonEncodeException(message=str(exception)) from exception
46
- except orjson.JSONEncodeError as exception:
33
+ # NOTE(krishan711): orjson is faster, but doesnt support ints bigger than 64bit
34
+ # so we use pydantic instead (still faster than python json)
35
+ return pydantic_core.to_json(obj, fallback=str, inf_nan_mode='null')
47
36
  raise JsonEncodeException(message=str(exception)) from exception
48
37
 
49
38
 
@@ -53,6 +42,8 @@ def dumps(obj: Any) -> str: # type: ignore[explicit-any]
53
42
 
54
43
  def loads(json: str | bytes | bytearray) -> Json:
55
44
  try:
56
- return orjson.loads(json) # type: ignore[no-any-return]
57
- except orjson.JSONDecodeError as exception:
45
+ # NOTE(krishan711): orjson is faster, but doesnt support ints bigger than 64bit
46
+ # so we use pydantic instead (still faster than python json)
47
+ return typing.cast(Json, pydantic_core.from_json(json, allow_inf_nan=False))
48
+ except ValueError as exception:
58
49
  raise JsonDecodeException(message=str(exception)) from exception
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kiba-core
3
- Version: 0.5.3.dev59
3
+ Version: 0.5.3.dev60
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kiba-core"
3
- version = "0.5.3.dev59"
3
+ version = "0.5.3.dev60"
4
4
  description = "Kiba Labs' python utilities"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12, <4"
@@ -1,3 +1,6 @@
1
+ import datetime
2
+ import math
3
+
1
4
  import pytest
2
5
 
3
6
  from core.util import json_util
@@ -154,9 +157,49 @@ class TestJsonUtil:
154
157
  assert isinstance(result, bytes)
155
158
  assert result == b'11111111111111111111111'
156
159
 
157
- # NOTE(krishan711): not sure why this is failing
158
- # def test_dumpb_and_loads_with_very_long_integer(self):
159
- # veryLongInteger = 11111111111111111111111
160
- # result = json_util.dumpb(obj=veryLongInteger)
161
- # assert isinstance(result, bytes)
162
- # assert int(json_util.loads(result)) == veryLongInteger
160
+ def test_dumpb_and_loads_with_very_long_integer(self):
161
+ veryLongInteger = 11111111111111111111111
162
+ result = json_util.dumpb(obj=veryLongInteger)
163
+ assert isinstance(result, bytes)
164
+ assert int(json_util.loads(result)) == veryLongInteger
165
+
166
+ def test_dumpb_with_very_long_integer_and_datetime(self):
167
+ veryLongInteger = 25000000000000000001
168
+ naiveDatetime = datetime.datetime.fromisoformat('2024-01-02T03:04:05.678901')
169
+ utcDatetime = datetime.datetime(2024, 1, 2, 3, 4, 5, 678901, tzinfo=datetime.UTC)
170
+ result = json_util.dumpb({
171
+ 'balance': veryLongInteger,
172
+ 'naive': naiveDatetime,
173
+ 'utc': utcDatetime,
174
+ })
175
+ assert result == b'{"balance":25000000000000000001,"naive":"2024-01-02T03:04:05.678901","utc":"2024-01-02T03:04:05.678901Z"}'
176
+
177
+ def test_dumpb_with_utc_datetime_matches_pydantic_fallback(self):
178
+ utcDatetime = datetime.datetime(2024, 1, 2, 3, 4, 5, 678901, tzinfo=datetime.UTC)
179
+ assert json_util.dumpb(utcDatetime) == b'"2024-01-02T03:04:05.678901Z"'
180
+
181
+ def test_dumpb_with_very_long_integer_uses_pydantic_fallbacks(self):
182
+ veryLongInteger = 25000000000000000001
183
+
184
+ class TestObject:
185
+ def __str__(self):
186
+ return 'test-object'
187
+
188
+ result = json_util.dumpb({
189
+ 'balance': veryLongInteger,
190
+ 'unknown': TestObject(),
191
+ 'not_a_number': math.nan,
192
+ })
193
+ assert result == b'{"balance":25000000000000000001,"unknown":"test-object","not_a_number":null}'
194
+
195
+ def test_loads_preserves_large_integer_type_and_precision(self):
196
+ value = 25000000000000000001
197
+ decoded = json_util.loads(str(value))
198
+ assert type(decoded) is int
199
+ assert decoded == value
200
+
201
+ def test_loads_preserves_nested_large_integer_type_and_precision(self):
202
+ value = 25000000000000000001
203
+ decoded = json_util.loads(f'{{"balance": {value}}}')
204
+ assert type(decoded['balance']) is int
205
+ assert decoded['balance'] == value
File without changes