kiba-core 0.5.3.dev78__tar.gz → 0.5.3.dev80__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 (144) hide show
  1. kiba_core-0.5.3.dev80/.github/workflows/publish.yml +29 -0
  2. kiba_core-0.5.3.dev80/.github/workflows/release.yml +34 -0
  3. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/PKG-INFO +1 -1
  4. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/locks/sql.py +2 -1
  5. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/queues/sql.py +3 -2
  6. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/store/database.py +5 -0
  7. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/store/entity_repository.py +2 -1
  8. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/store/retriever.py +22 -22
  9. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/store/saver.py +4 -4
  10. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/kiba_core.egg-info/PKG-INFO +1 -1
  11. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/kiba_core.egg-info/SOURCES.txt +1 -0
  12. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/pyproject.toml +1 -1
  13. kiba_core-0.5.3.dev78/.github/workflows/release.yml +0 -39
  14. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/.github/pull_request_template.md +0 -0
  15. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/.github/workflows/deploy.yml +0 -0
  16. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/.github/workflows/pull-request.yml +0 -0
  17. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/.gitignore +0 -0
  18. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/CHANGELOG.md +0 -0
  19. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/Dockerfile +0 -0
  20. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/README.md +0 -0
  21. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/__init__.py +0 -0
  22. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/__init__.py +0 -0
  23. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/api_request.py +0 -0
  24. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/api_response.py +0 -0
  25. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/authorizer.py +0 -0
  26. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/default_routes.py +0 -0
  27. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/health.py +0 -0
  28. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/json_route.py +0 -0
  29. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/middleware/__init__.py +0 -0
  30. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/middleware/database_connection_middleware.py +0 -0
  31. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/middleware/exception_handling_middleware.py +0 -0
  32. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/middleware/logging_middleware.py +0 -0
  33. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/middleware/origin_ip_middleware.py +0 -0
  34. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/middleware/server_headers_middleware.py +0 -0
  35. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/openapi.py +0 -0
  36. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/rate_limit.py +0 -0
  37. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/request_context.py +0 -0
  38. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/route.py +0 -0
  39. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/route_auth.py +0 -0
  40. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/route_metadata.py +0 -0
  41. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/api/streaming_json_route.py +0 -0
  42. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/aws_requester.py +0 -0
  43. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/caching/__init__.py +0 -0
  44. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/caching/cache.py +0 -0
  45. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/caching/dict_cache.py +0 -0
  46. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/caching/file_cache.py +0 -0
  47. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/cron/__init__.py +0 -0
  48. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/cron/api_request_cron_job_processor.py +0 -0
  49. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/cron/cron_executor.py +0 -0
  50. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/cron/cron_job_processor.py +0 -0
  51. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/cron/model.py +0 -0
  52. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/exceptions.py +0 -0
  53. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/http/__init__.py +0 -0
  54. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/http/basic_authentication.py +0 -0
  55. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/http/jwt.py +0 -0
  56. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/http/rest_method.py +0 -0
  57. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/locks/__init__.py +0 -0
  58. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/locks/lock.py +0 -0
  59. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/locks/model.py +0 -0
  60. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/logging.py +0 -0
  61. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/notifications/__init__.py +0 -0
  62. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/notifications/discord_client.py +0 -0
  63. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/notifications/notification_client.py +0 -0
  64. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/notifications/slack_client.py +0 -0
  65. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/py.typed +0 -0
  66. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/queues/__init__.py +0 -0
  67. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/queues/aqs.py +0 -0
  68. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/queues/cosmos.py +0 -0
  69. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/queues/message_queue.py +0 -0
  70. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/queues/message_queue_processor.py +0 -0
  71. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/queues/model.py +0 -0
  72. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/queues/sqs.py +0 -0
  73. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/requester/__init__.py +0 -0
  74. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/requester/requester.py +0 -0
  75. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/s3_manager.py +0 -0
  76. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/service_client.py +0 -0
  77. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/store/__init__.py +0 -0
  78. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/util/__init__.py +0 -0
  79. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/util/async_util.py +0 -0
  80. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/util/chain_util.py +0 -0
  81. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/util/date_util.py +0 -0
  82. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/util/dict_util.py +0 -0
  83. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/util/file_util.py +0 -0
  84. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/util/hashing_util.py +0 -0
  85. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/util/http_util.py +0 -0
  86. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/util/json_util.py +0 -0
  87. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/util/list_util.py +0 -0
  88. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/util/process_util.py +0 -0
  89. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/util/string_util.py +0 -0
  90. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/util/typing_util.py +0 -0
  91. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/util/url_util.py +0 -0
  92. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/util/value_holder.py +0 -0
  93. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/web3/__init__.py +0 -0
  94. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/web3/eth_client.py +0 -0
  95. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/web3/eth_client_registry.py +0 -0
  96. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/core/web3/multicall3.py +0 -0
  97. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/kiba_core.egg-info/dependency_links.txt +0 -0
  98. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/kiba_core.egg-info/requires.txt +0 -0
  99. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/kiba_core.egg-info/top_level.txt +0 -0
  100. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/makefile +0 -0
  101. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/setup.cfg +0 -0
  102. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/__init__.py +0 -0
  103. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/api/test_api_response.py +0 -0
  104. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/api/test_authorizer.py +0 -0
  105. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/api/test_exception_handling_middleware.py +0 -0
  106. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/api/test_json_route.py +0 -0
  107. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/api/test_openapi.py +0 -0
  108. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/api/test_origin_ip_middleware.py +0 -0
  109. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/api/test_rate_limit.py +0 -0
  110. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/api/test_request_context.py +0 -0
  111. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/api/test_route.py +0 -0
  112. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/api/test_streaming_json_route.py +0 -0
  113. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/caching/test_dict_cache.py +0 -0
  114. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/caching/test_file_cache.py +0 -0
  115. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/cron/__init__.py +0 -0
  116. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/cron/test_cron_executor.py +0 -0
  117. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/locks/test_sql_lock.py +0 -0
  118. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/queues/conftest.py +0 -0
  119. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/queues/test_aqs_queue.py +0 -0
  120. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/queues/test_cosmos_queue.py +0 -0
  121. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/queues/test_message_queue_processor.py +0 -0
  122. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/queues/test_sql_queue.py +0 -0
  123. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/queues/test_sqs_queue.py +0 -0
  124. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/requester/__init__.py +0 -0
  125. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/requester/test_requester.py +0 -0
  126. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/test_database.py +0 -0
  127. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/test_entity_repository.py +0 -0
  128. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/test_exceptions.py +0 -0
  129. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/test_logging.py +0 -0
  130. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/util/__init__.py +0 -0
  131. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/util/test_async_util.py +0 -0
  132. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/util/test_chain_util.py +0 -0
  133. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/util/test_date_util.py +0 -0
  134. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/util/test_dict_util.py +0 -0
  135. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/util/test_file_util.py +0 -0
  136. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/util/test_json_util.py +0 -0
  137. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/util/test_list_util.py +0 -0
  138. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/util/test_process_util.py +0 -0
  139. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/util/test_string_util.py +0 -0
  140. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/util/test_url_util.py +0 -0
  141. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/web3/__init__.py +0 -0
  142. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/web3/test_eth_client_registry.py +0 -0
  143. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/tests/web3/test_rest_eth_client.py +0 -0
  144. {kiba_core-0.5.3.dev78 → kiba_core-0.5.3.dev80}/uv.lock +0 -0
@@ -0,0 +1,29 @@
1
+ name: Publish
2
+ on:
3
+ push:
4
+ tags: ["v*"]
5
+ jobs:
6
+ deploy-package:
7
+ runs-on: ubuntu-latest
8
+ env:
9
+ DOCKER_IMAGE: build
10
+ PYPI_PUBLISH_TOKEN: ${{ secrets.PYPI_PUBLISH_TOKEN }}
11
+ steps:
12
+ - name: Check out the repo
13
+ uses: actions/checkout@v7
14
+ - name: Build docker image
15
+ run: docker build --tag $DOCKER_IMAGE .
16
+ - name: Publish package to pypi
17
+ run: docker run -e UV_PUBLISH_TOKEN=$PYPI_PUBLISH_TOKEN $DOCKER_IMAGE /bin/bash -c " make publish"
18
+ create-release:
19
+ needs: deploy-package
20
+ runs-on: ubuntu-latest
21
+ permissions:
22
+ contents: write
23
+ steps:
24
+ - name: Check out the repo
25
+ uses: actions/checkout@v7
26
+ - name: Create Release
27
+ env:
28
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29
+ run: gh release create ${{ github.ref_name }} --title "Release ${{ github.ref_name }}" --generate-notes
@@ -0,0 +1,34 @@
1
+ name: Release
2
+ on:
3
+ workflow_dispatch:
4
+ concurrency:
5
+ group: release
6
+ jobs:
7
+ push-version-tag:
8
+ runs-on: ubuntu-latest
9
+ # NOTE(krishan711): the release environment only allows main and holds the deploy key, the only thing allowed to push version tags. Unlike the GITHUB_TOKEN, a push with it starts the workflows that publish the tag.
10
+ environment: release
11
+ permissions:
12
+ contents: read
13
+ steps:
14
+ - name: Check out the repo
15
+ uses: actions/checkout@v7
16
+ with:
17
+ ssh-key: ${{ secrets.RELEASE_DEPLOY_KEY }}
18
+ - name: Push the version tag
19
+ run: |
20
+ version="v$(python3 -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")"
21
+ if [[ ! "$version" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
22
+ echo "::error::pyproject.toml version $version is not X.Y.Z"
23
+ exit 1
24
+ fi
25
+ existingSha="$(git ls-remote origin "refs/tags/$version" | cut -f1)"
26
+ if [[ "$existingSha" == "$GITHUB_SHA" ]]; then
27
+ echo "$version is already tagged on this commit; if publishing failed, re-run the workflow run for the tag"
28
+ elif [[ -n "$existingSha" ]]; then
29
+ echo "::error::$version already exists on $existingSha, bump the version in pyproject.toml"
30
+ exit 1
31
+ else
32
+ git tag "$version"
33
+ git push origin "refs/tags/$version"
34
+ fi
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kiba-core
3
- Version: 0.5.3.dev78
3
+ Version: 0.5.3.dev80
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
@@ -11,6 +11,7 @@ from core.exceptions import LockedException
11
11
  from core.locks.lock import Lock
12
12
  from core.locks.model import LockLease
13
13
  from core.store.database import Database
14
+ from core.store.database import DatabaseTable
14
15
  from core.util import date_util
15
16
  from core.util import process_util
16
17
 
@@ -31,7 +32,7 @@ LocksTable = sqlalchemy.Table(
31
32
 
32
33
 
33
34
  class SqlLock(Lock):
34
- def __init__(self, database: Database, table: sqlalchemy.Table = LocksTable, pollIntervalSeconds: float = 1.0, owner: str | None = None) -> None:
35
+ def __init__(self, database: Database, table: DatabaseTable = LocksTable, pollIntervalSeconds: float = 1.0, owner: str | None = None) -> None:
35
36
  self.database = database
36
37
  self.table = table
37
38
  self.pollIntervalSeconds = pollIntervalSeconds
@@ -16,6 +16,7 @@ from core.exceptions import InternalServerErrorException
16
16
  from core.queues.message_queue import MessageQueue
17
17
  from core.queues.model import Message
18
18
  from core.store.database import Database
19
+ from core.store.database import DatabaseTable
19
20
  from core.util import process_util
20
21
 
21
22
  MESSAGE_STATUS_PENDING = 'pending'
@@ -61,7 +62,7 @@ class SqlMessage(Message):
61
62
  lockToken: str
62
63
 
63
64
  @classmethod
64
- def from_row(cls, row: RowMapping, table: sqlalchemy.Table) -> SqlMessage:
65
+ def from_row(cls, row: RowMapping, table: DatabaseTable) -> SqlMessage:
65
66
  return cls(
66
67
  id=row[table.c.id],
67
68
  command=row[table.c.command],
@@ -79,7 +80,7 @@ class SqlMessageQueue(MessageQueue[SqlMessage]):
79
80
  self,
80
81
  database: Database,
81
82
  queueName: str,
82
- table: sqlalchemy.Table = QueueMessagesTable,
83
+ table: DatabaseTable = QueueMessagesTable,
83
84
  pollIntervalSeconds: float = 1.0,
84
85
  maxAttempts: int = 3,
85
86
  failureRetryDelaySeconds: int = 60,
@@ -12,7 +12,9 @@ from sqlalchemy.engine import Result
12
12
  from sqlalchemy.ext.asyncio import AsyncConnection
13
13
  from sqlalchemy.ext.asyncio import AsyncEngine
14
14
  from sqlalchemy.ext.asyncio import create_async_engine
15
+ from sqlalchemy.sql.base import ReadOnlyColumnCollection
15
16
  from sqlalchemy.sql.dml import UpdateBase
17
+ from sqlalchemy.sql.elements import KeyedColumnElement
16
18
  from sqlalchemy.sql.selectable import TypedReturnsRows
17
19
 
18
20
  from core import logging
@@ -21,6 +23,9 @@ from core.util import json_util
21
23
 
22
24
  DatabaseConnection = AsyncConnection
23
25
  ResultType = TypeVarTuple('ResultType')
26
+ # NOTE(krishan711): these spell out sqlalchemy 2.1's default column collections. mypy's disallow_any_explicit rejects bare Table / FromClause annotations because the defaults contain Any, but not uses of these aliases
27
+ DatabaseTable = sqlalchemy.Table[ReadOnlyColumnCollection[str, sqlalchemy.Column[typing.Any]]] # type: ignore[explicit-any]
28
+ DatabaseFromClause = sqlalchemy.FromClause[ReadOnlyColumnCollection[str, KeyedColumnElement[typing.Any]]] # type: ignore[explicit-any]
24
29
 
25
30
 
26
31
  class Database:
@@ -14,6 +14,7 @@ from core.exceptions import KibaException
14
14
  from core.exceptions import NotFoundException
15
15
  from core.store.database import Database
16
16
  from core.store.database import DatabaseConnection
17
+ from core.store.database import DatabaseTable
17
18
  from core.store.retriever import FieldFilter
18
19
  from core.store.retriever import Order
19
20
  from core.store.retriever import apply_field_filters
@@ -37,7 +38,7 @@ class EntityRepository(typing.Generic[EntityType]): # noqa: UP046
37
38
 
38
39
  def __init__(
39
40
  self,
40
- table: sqlalchemy.Table,
41
+ table: DatabaseTable,
41
42
  modelClass: type[EntityType],
42
43
  ) -> None:
43
44
  self.table = table
@@ -7,11 +7,11 @@ from enum import Enum
7
7
 
8
8
  import sqlalchemy
9
9
  import sqlalchemy.sql.functions
10
- from sqlalchemy import Table
11
10
  from sqlalchemy.sql import ColumnElement
12
11
  from sqlalchemy.sql import Select
13
12
 
14
13
  from core.store.database import Database
14
+ from core.store.database import DatabaseTable
15
15
  from core.store.database import ResultType
16
16
  from core.util import date_util
17
17
 
@@ -110,7 +110,7 @@ def datetime_to_column_value(column: sqlalchemy.ColumnElement[typing.Any], dt: d
110
110
  return date_util.datetime_to_utc_naive_datetime(dt=dt)
111
111
 
112
112
 
113
- def apply_order(query: Select[*ResultType], table: Table, order: Order) -> Select[*ResultType]:
113
+ def apply_order(query: Select[*ResultType], table: DatabaseTable, order: Order) -> Select[*ResultType]:
114
114
  if isinstance(order, RandomOrder):
115
115
  query = query.order_by(sqlalchemy.sql.functions.random())
116
116
  else:
@@ -119,13 +119,13 @@ def apply_order(query: Select[*ResultType], table: Table, order: Order) -> Selec
119
119
  return query
120
120
 
121
121
 
122
- def apply_orders(query: Select[*ResultType], table: Table, orders: Sequence[Order]) -> Select[*ResultType]:
122
+ def apply_orders(query: Select[*ResultType], table: DatabaseTable, orders: Sequence[Order]) -> Select[*ResultType]:
123
123
  for order in orders:
124
124
  query = apply_order(query=query, table=table, order=order)
125
125
  return query
126
126
 
127
127
 
128
- def get_string_field_filter_conditions(table: Table, fieldFilter: StringFieldFilter) -> list[ColumnElement[bool]]:
128
+ def get_string_field_filter_conditions(table: DatabaseTable, fieldFilter: StringFieldFilter) -> list[ColumnElement[bool]]:
129
129
  field = table.c[fieldFilter.fieldName]
130
130
  conditions: list[ColumnElement[bool]] = []
131
131
  if fieldFilter.eq is not None:
@@ -139,7 +139,7 @@ def get_string_field_filter_conditions(table: Table, fieldFilter: StringFieldFil
139
139
  return conditions
140
140
 
141
141
 
142
- def get_uuid_field_filter_conditions(table: Table, fieldFilter: UUIDFieldFilter) -> list[ColumnElement[bool]]:
142
+ def get_uuid_field_filter_conditions(table: DatabaseTable, fieldFilter: UUIDFieldFilter) -> list[ColumnElement[bool]]:
143
143
  field = table.c[fieldFilter.fieldName]
144
144
  conditions: list[ColumnElement[bool]] = []
145
145
  if fieldFilter.eq is not None:
@@ -153,7 +153,7 @@ def get_uuid_field_filter_conditions(table: Table, fieldFilter: UUIDFieldFilter)
153
153
  return conditions
154
154
 
155
155
 
156
- def get_date_field_filter_conditions(table: Table, fieldFilter: DateFieldFilter) -> list[ColumnElement[bool]]:
156
+ def get_date_field_filter_conditions(table: DatabaseTable, fieldFilter: DateFieldFilter) -> list[ColumnElement[bool]]:
157
157
  field = table.c[fieldFilter.fieldName]
158
158
  conditions: list[ColumnElement[bool]] = []
159
159
  if fieldFilter.eq is not None:
@@ -175,7 +175,7 @@ def get_date_field_filter_conditions(table: Table, fieldFilter: DateFieldFilter)
175
175
  return conditions
176
176
 
177
177
 
178
- def get_integer_field_filter_conditions(table: Table, fieldFilter: IntegerFieldFilter) -> list[ColumnElement[bool]]:
178
+ def get_integer_field_filter_conditions(table: DatabaseTable, fieldFilter: IntegerFieldFilter) -> list[ColumnElement[bool]]:
179
179
  # NOTE(krishan711): `field == value` / `field.in_(values)` let SQLAlchemy's `Numeric.coerce_compared_value`
180
180
  # re-infer a bind param type from the compared Python `int` (typically `BigInteger`, i.e. int64) instead of
181
181
  # keeping `field.type` (e.g. `Numeric(78, 0)` for uint256 columns). Binding explicitly with `type_=field.type`
@@ -201,7 +201,7 @@ def get_integer_field_filter_conditions(table: Table, fieldFilter: IntegerFieldF
201
201
  return conditions
202
202
 
203
203
 
204
- def get_float_field_filter_conditions(table: Table, fieldFilter: FloatFieldFilter) -> list[ColumnElement[bool]]:
204
+ def get_float_field_filter_conditions(table: DatabaseTable, fieldFilter: FloatFieldFilter) -> list[ColumnElement[bool]]:
205
205
  field = table.c[fieldFilter.fieldName]
206
206
  conditions: list[ColumnElement[bool]] = []
207
207
  if fieldFilter.eq is not None:
@@ -223,7 +223,7 @@ def get_float_field_filter_conditions(table: Table, fieldFilter: FloatFieldFilte
223
223
  return conditions
224
224
 
225
225
 
226
- def get_boolean_field_filter_conditions(table: Table, fieldFilter: BooleanFieldFilter) -> list[ColumnElement[bool]]:
226
+ def get_boolean_field_filter_conditions(table: DatabaseTable, fieldFilter: BooleanFieldFilter) -> list[ColumnElement[bool]]:
227
227
  field = table.c[fieldFilter.fieldName]
228
228
  conditions: list[ColumnElement[bool]] = []
229
229
  if fieldFilter.eq is not None:
@@ -233,7 +233,7 @@ def get_boolean_field_filter_conditions(table: Table, fieldFilter: BooleanFieldF
233
233
  return conditions
234
234
 
235
235
 
236
- def get_field_filter_conditions(table: Table, fieldFilter: FieldFilter) -> list[ColumnElement[bool]]:
236
+ def get_field_filter_conditions(table: DatabaseTable, fieldFilter: FieldFilter) -> list[ColumnElement[bool]]:
237
237
  field = table.c[fieldFilter.fieldName]
238
238
  conditions: list[ColumnElement[bool]] = []
239
239
  if fieldFilter.isNull:
@@ -255,11 +255,11 @@ def get_field_filter_conditions(table: Table, fieldFilter: FieldFilter) -> list[
255
255
  return conditions
256
256
 
257
257
 
258
- def get_field_filters_conditions(table: Table, fieldFilters: Sequence[FieldFilter]) -> list[ColumnElement[bool]]:
258
+ def get_field_filters_conditions(table: DatabaseTable, fieldFilters: Sequence[FieldFilter]) -> list[ColumnElement[bool]]:
259
259
  return [condition for fieldFilter in fieldFilters for condition in get_field_filter_conditions(table=table, fieldFilter=fieldFilter)]
260
260
 
261
261
 
262
- def apply_field_filters(query: Select[*ResultType], table: Table, fieldFilters: Sequence[FieldFilter]) -> Select[*ResultType]:
262
+ def apply_field_filters(query: Select[*ResultType], table: DatabaseTable, fieldFilters: Sequence[FieldFilter]) -> Select[*ResultType]:
263
263
  return query.where(*get_field_filters_conditions(table=table, fieldFilters=fieldFilters))
264
264
 
265
265
 
@@ -267,32 +267,32 @@ class Retriever:
267
267
  def __init__(self, database: Database) -> None:
268
268
  self.database = database
269
269
 
270
- def _apply_order(self, query: Select[*ResultType], table: Table, order: Order) -> Select[*ResultType]:
270
+ def _apply_order(self, query: Select[*ResultType], table: DatabaseTable, order: Order) -> Select[*ResultType]:
271
271
  return apply_order(query=query, table=table, order=order)
272
272
 
273
- def _apply_orders(self, query: Select[*ResultType], table: Table, orders: Sequence[Order]) -> Select[*ResultType]:
273
+ def _apply_orders(self, query: Select[*ResultType], table: DatabaseTable, orders: Sequence[Order]) -> Select[*ResultType]:
274
274
  return apply_orders(query=query, table=table, orders=orders)
275
275
 
276
- def _apply_string_field_filter(self, query: Select[*ResultType], table: Table, fieldFilter: StringFieldFilter) -> Select[*ResultType]:
276
+ def _apply_string_field_filter(self, query: Select[*ResultType], table: DatabaseTable, fieldFilter: StringFieldFilter) -> Select[*ResultType]:
277
277
  return query.where(*get_string_field_filter_conditions(table=table, fieldFilter=fieldFilter))
278
278
 
279
- def _apply_uuid_field_filter(self, query: Select[*ResultType], table: Table, fieldFilter: UUIDFieldFilter) -> Select[*ResultType]:
279
+ def _apply_uuid_field_filter(self, query: Select[*ResultType], table: DatabaseTable, fieldFilter: UUIDFieldFilter) -> Select[*ResultType]:
280
280
  return query.where(*get_uuid_field_filter_conditions(table=table, fieldFilter=fieldFilter))
281
281
 
282
- def _apply_date_field_filter(self, query: Select[*ResultType], table: Table, fieldFilter: DateFieldFilter) -> Select[*ResultType]:
282
+ def _apply_date_field_filter(self, query: Select[*ResultType], table: DatabaseTable, fieldFilter: DateFieldFilter) -> Select[*ResultType]:
283
283
  return query.where(*get_date_field_filter_conditions(table=table, fieldFilter=fieldFilter))
284
284
 
285
- def _apply_integer_field_filter(self, query: Select[*ResultType], table: Table, fieldFilter: IntegerFieldFilter) -> Select[*ResultType]:
285
+ def _apply_integer_field_filter(self, query: Select[*ResultType], table: DatabaseTable, fieldFilter: IntegerFieldFilter) -> Select[*ResultType]:
286
286
  return query.where(*get_integer_field_filter_conditions(table=table, fieldFilter=fieldFilter))
287
287
 
288
- def _apply_float_field_filter(self, query: Select[*ResultType], table: Table, fieldFilter: FloatFieldFilter) -> Select[*ResultType]:
288
+ def _apply_float_field_filter(self, query: Select[*ResultType], table: DatabaseTable, fieldFilter: FloatFieldFilter) -> Select[*ResultType]:
289
289
  return query.where(*get_float_field_filter_conditions(table=table, fieldFilter=fieldFilter))
290
290
 
291
- def _apply_boolean_field_filter(self, query: Select[*ResultType], table: Table, fieldFilter: BooleanFieldFilter) -> Select[*ResultType]:
291
+ def _apply_boolean_field_filter(self, query: Select[*ResultType], table: DatabaseTable, fieldFilter: BooleanFieldFilter) -> Select[*ResultType]:
292
292
  return query.where(*get_boolean_field_filter_conditions(table=table, fieldFilter=fieldFilter))
293
293
 
294
- def _apply_field_filter(self, query: Select[*ResultType], table: Table, fieldFilter: FieldFilter) -> Select[*ResultType]:
294
+ def _apply_field_filter(self, query: Select[*ResultType], table: DatabaseTable, fieldFilter: FieldFilter) -> Select[*ResultType]:
295
295
  return query.where(*get_field_filter_conditions(table=table, fieldFilter=fieldFilter))
296
296
 
297
- def _apply_field_filters(self, query: Select[*ResultType], table: Table, fieldFilters: Sequence[FieldFilter]) -> Select[*ResultType]:
297
+ def _apply_field_filters(self, query: Select[*ResultType], table: DatabaseTable, fieldFilters: Sequence[FieldFilter]) -> Select[*ResultType]:
298
298
  return apply_field_filters(query=query, table=table, fieldFilters=fieldFilters)
@@ -3,13 +3,13 @@ from collections.abc import AsyncIterator
3
3
  from typing import TYPE_CHECKING
4
4
  from typing import Any
5
5
 
6
- from sqlalchemy import Table
7
6
  from sqlalchemy.engine import Result
8
7
  from sqlalchemy.sql.selectable import TypedReturnsRows
9
8
 
10
9
  from core.exceptions import InternalServerErrorException
11
10
  from core.store.database import Database
12
11
  from core.store.database import DatabaseConnection
12
+ from core.store.database import DatabaseTable
13
13
  from core.store.database import ResultType
14
14
 
15
15
  if TYPE_CHECKING:
@@ -49,19 +49,19 @@ class Saver:
49
49
  except Exception as exception:
50
50
  raise SavingException(message=f'Error running save operation: {exception!s}') from exception
51
51
 
52
- async def _insert_record(self, table: Table, values: CreateRecordValuesDict, connection: DatabaseConnection | None = None) -> int:
52
+ async def _insert_record(self, table: DatabaseTable, values: CreateRecordValuesDict, connection: DatabaseConnection | None = None) -> int:
53
53
  query = table.insert().values(values).returning(table.c.id)
54
54
  result = await self._execute(query=query, connection=connection)
55
55
  rowId = int(result.scalar_one())
56
56
  return rowId
57
57
 
58
- async def _update_records(self, table: Table, where: WhereClause, values: UpdateRecordValuesDict, connection: DatabaseConnection | None = None) -> list[int]:
58
+ async def _update_records(self, table: DatabaseTable, where: WhereClause, values: UpdateRecordValuesDict, connection: DatabaseConnection | None = None) -> list[int]:
59
59
  query = table.update().where(where).values(values).returning(table.c.id)
60
60
  result = await self._execute(query=query, connection=connection)
61
61
  rowIds = [int(rowId) for rowId in result.scalars()]
62
62
  return rowIds
63
63
 
64
- async def _delete_records(self, table: Table, where: WhereClause, connection: DatabaseConnection | None = None) -> list[int]:
64
+ async def _delete_records(self, table: DatabaseTable, where: WhereClause, connection: DatabaseConnection | None = None) -> list[int]:
65
65
  query = table.delete().where(where).returning(table.c.id)
66
66
  result = await self._execute(query=query, connection=connection)
67
67
  rowIds = [int(rowId) for rowId in result.scalars()]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kiba-core
3
- Version: 0.5.3.dev78
3
+ Version: 0.5.3.dev80
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
@@ -7,6 +7,7 @@ pyproject.toml
7
7
  uv.lock
8
8
  .github/pull_request_template.md
9
9
  .github/workflows/deploy.yml
10
+ .github/workflows/publish.yml
10
11
  .github/workflows/pull-request.yml
11
12
  .github/workflows/release.yml
12
13
  core/__init__.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kiba-core"
3
- version = "0.5.3.dev78"
3
+ version = "0.5.3.dev80"
4
4
  description = "Kiba Labs' python utilities"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12, <4"
@@ -1,39 +0,0 @@
1
- name: Release
2
- on:
3
- push:
4
- tags: ["v*"]
5
- jobs:
6
- deploy-package:
7
- runs-on: ubuntu-latest
8
- env:
9
- DOCKER_IMAGE: build
10
- PYPI_PUBLISH_TOKEN: ${{ secrets.PYPI_PUBLISH_TOKEN }}
11
- steps:
12
- - name: Check out the repo
13
- uses: actions/checkout@v2
14
- - name: Check the package version is the same as the tag
15
- run: |
16
- version=$(python3 setup.py --version)
17
- if [ "${{ github.ref }}" != "refs/tags/v${version}" ]; then
18
- echo "version in setup.py (v${version}) is different to the given tag (${{ github.ref }})"
19
- exit 1;
20
- fi
21
- - name: Build docker image
22
- run: docker build --tag $DOCKER_IMAGE .
23
- - name: Publish package to pypi
24
- run: docker run -e UV_PUBLISH_TOKEN=$PYPI_PUBLISH_TOKEN $DOCKER_IMAGE /bin/bash -c " make publish"
25
- create-release:
26
- needs: deploy-package
27
- runs-on: ubuntu-latest
28
- env:
29
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30
- steps:
31
- - name: Check out the repo
32
- uses: actions/checkout@v2
33
- - name: Create Release
34
- uses: actions/create-release@v1
35
- with:
36
- tag_name: ${{ github.ref }}
37
- release_name: Release ${{ github.ref }}
38
- draft: false
39
- prerelease: false
File without changes