codex-platform 0.5.0__tar.gz → 0.5.1__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 (165) hide show
  1. {codex_platform-0.5.0 → codex_platform-0.5.1}/.github/workflows/ci.yml +2 -2
  2. {codex_platform-0.5.0 → codex_platform-0.5.1}/CHANGELOG.md +6 -0
  3. {codex_platform-0.5.0 → codex_platform-0.5.1}/PKG-INFO +4 -2
  4. {codex_platform-0.5.0 → codex_platform-0.5.1}/pyproject.toml +3 -1
  5. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/integration/test_streams.py +2 -0
  6. {codex_platform-0.5.0 → codex_platform-0.5.1}/uv.lock +59 -55
  7. {codex_platform-0.5.0 → codex_platform-0.5.1}/.agents/rules/graphify.md +0 -0
  8. {codex_platform-0.5.0 → codex_platform-0.5.1}/.github/workflows/docs.yml +0 -0
  9. {codex_platform-0.5.0 → codex_platform-0.5.1}/.github/workflows/publish.yml +0 -0
  10. {codex_platform-0.5.0 → codex_platform-0.5.1}/.gitignore +0 -0
  11. {codex_platform-0.5.0 → codex_platform-0.5.1}/.pre-commit-config.yaml +0 -0
  12. {codex_platform-0.5.0 → codex_platform-0.5.1}/.python-version +0 -0
  13. {codex_platform-0.5.0 → codex_platform-0.5.1}/AGENTS.md +0 -0
  14. {codex_platform-0.5.0 → codex_platform-0.5.1}/CLAUDE.md +0 -0
  15. {codex_platform-0.5.0 → codex_platform-0.5.1}/README.md +0 -0
  16. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/changelog.md +0 -0
  17. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/dev/messaging/00_overview.md +0 -0
  18. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/dev/messaging/01_core_dtos_and_protocols.md +0 -0
  19. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/dev/messaging/02_channels_and_registry.md +0 -0
  20. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/dev/messaging/03_renderer_and_templates.md +0 -0
  21. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/dev/messaging/04_threading_and_headers.md +0 -0
  22. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/dev/messaging/05_workers_contract.md +0 -0
  23. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/dev/messaging/06_migration_from_notifications.md +0 -0
  24. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/index.md +0 -0
  25. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/notifications/channels.md +0 -0
  26. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/notifications/delivery/arq.md +0 -0
  27. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/notifications/delivery/base.md +0 -0
  28. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/notifications/delivery/direct.md +0 -0
  29. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/notifications/dto.md +0 -0
  30. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/notifications/index.md +0 -0
  31. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/notifications/orchestrator.md +0 -0
  32. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/notifications/registry.md +0 -0
  33. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/notifications/renderer.md +0 -0
  34. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/redis_service/base.md +0 -0
  35. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/redis_service/index.md +0 -0
  36. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/redis_service/keys.md +0 -0
  37. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/redis_service/operations/hash.md +0 -0
  38. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/redis_service/operations/json_module.md +0 -0
  39. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/redis_service/operations/json_string.md +0 -0
  40. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/redis_service/operations/list_.md +0 -0
  41. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/redis_service/operations/pipeline.md +0 -0
  42. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/redis_service/operations/set_.md +0 -0
  43. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/redis_service/operations/string.md +0 -0
  44. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/redis_service/operations/zset.md +0 -0
  45. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/redis_service/service.md +0 -0
  46. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/streams/consumer.md +0 -0
  47. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/streams/dispatcher.md +0 -0
  48. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/streams/index.md +0 -0
  49. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/streams/processor.md +0 -0
  50. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/streams/producer.md +0 -0
  51. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/streams/router.md +0 -0
  52. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/workers/arq/base.md +0 -0
  53. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/workers/arq/config.md +0 -0
  54. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/workers/arq/index.md +0 -0
  55. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/workers/arq/task_utils.md +0 -0
  56. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/api/workers/arq/types.md +0 -0
  57. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/architecture/notifications/README.md +0 -0
  58. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/architecture/notifications/data_flow.md +0 -0
  59. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/architecture/redis_service/README.md +0 -0
  60. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/architecture/redis_service/data_flow.md +0 -0
  61. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/architecture/streams/README.md +0 -0
  62. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/architecture/streams/data_flow.md +0 -0
  63. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/architecture/workers/README.md +0 -0
  64. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/en/architecture/workers/data_flow.md +0 -0
  65. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/index.md +0 -0
  66. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/ru/architecture/notifications/README.md +0 -0
  67. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/ru/architecture/notifications/data_flow.md +0 -0
  68. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/ru/architecture/redis_service/README.md +0 -0
  69. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/ru/architecture/redis_service/data_flow.md +0 -0
  70. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/ru/architecture/streams/README.md +0 -0
  71. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/ru/architecture/streams/data_flow.md +0 -0
  72. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/ru/architecture/workers/README.md +0 -0
  73. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/ru/architecture/workers/data_flow.md +0 -0
  74. {codex_platform-0.5.0 → codex_platform-0.5.1}/docs/stylesheets/extra.css +0 -0
  75. {codex_platform-0.5.0 → codex_platform-0.5.1}/mkdocs.yml +0 -0
  76. {codex_platform-0.5.0 → codex_platform-0.5.1}/project_structure.txt +0 -0
  77. {codex_platform-0.5.0 → codex_platform-0.5.1}/redis-backends-recovery.md +0 -0
  78. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/__init__.py +0 -0
  79. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/notifications/__init__.py +0 -0
  80. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/notifications/channels.py +0 -0
  81. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/notifications/clients/__init__.py +0 -0
  82. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/notifications/clients/smtp.py +0 -0
  83. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/notifications/delivery/__init__.py +0 -0
  84. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/notifications/delivery/arq.py +0 -0
  85. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/notifications/delivery/base.py +0 -0
  86. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/notifications/delivery/direct.py +0 -0
  87. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/notifications/dto.py +0 -0
  88. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/notifications/interfaces.py +0 -0
  89. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/notifications/orchestrator.py +0 -0
  90. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/notifications/registry.py +0 -0
  91. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/notifications/renderer.py +0 -0
  92. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/py.typed +0 -0
  93. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/__init__.py +0 -0
  94. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/base.py +0 -0
  95. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/exceptions.py +0 -0
  96. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/keys.py +0 -0
  97. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/managers/__init__.py +0 -0
  98. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/managers/base_manager.py +0 -0
  99. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/managers/site_settings.py +0 -0
  100. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/operations/__init__.py +0 -0
  101. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/operations/hash.py +0 -0
  102. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/operations/json_module.py +0 -0
  103. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/operations/json_string.py +0 -0
  104. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/operations/list_.py +0 -0
  105. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/operations/pipeline.py +0 -0
  106. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/operations/set_.py +0 -0
  107. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/operations/string.py +0 -0
  108. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/operations/sync_hash.py +0 -0
  109. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/operations/sync_string.py +0 -0
  110. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/operations/zset.py +0 -0
  111. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/redis_service/service.py +0 -0
  112. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/streams/__init__.py +0 -0
  113. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/streams/codec.py +0 -0
  114. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/streams/consumer.py +0 -0
  115. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/streams/dispatcher.py +0 -0
  116. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/streams/processor.py +0 -0
  117. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/streams/producer.py +0 -0
  118. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/streams/router.py +0 -0
  119. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/streams/runtime.py +0 -0
  120. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/workers/__init__.py +0 -0
  121. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/workers/arq/__init__.py +0 -0
  122. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/workers/arq/base.py +0 -0
  123. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/workers/arq/config.py +0 -0
  124. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/workers/arq/task_utils.py +0 -0
  125. {codex_platform-0.5.0 → codex_platform-0.5.1}/src/codex_platform/workers/arq/types.py +0 -0
  126. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/integration/__init__.py +0 -0
  127. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/integration/conftest.py +0 -0
  128. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/integration/test_docs_build.py +0 -0
  129. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/integration/test_redis_service.py +0 -0
  130. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/__init__.py +0 -0
  131. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/conftest.py +0 -0
  132. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_arq_base.py +0 -0
  133. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_arq_config.py +0 -0
  134. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_arq_public_api.py +0 -0
  135. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_arq_task_utils.py +0 -0
  136. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_notification_adapters.py +0 -0
  137. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_notification_channels.py +0 -0
  138. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_notification_dto.py +0 -0
  139. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_notification_orchestrator.py +0 -0
  140. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_notification_registry.py +0 -0
  141. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_notification_renderer.py +0 -0
  142. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_notification_smtp.py +0 -0
  143. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_redis_base.py +0 -0
  144. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_redis_hash.py +0 -0
  145. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_redis_keys.py +0 -0
  146. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_redis_list.py +0 -0
  147. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_redis_manager.py +0 -0
  148. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_redis_pipeline.py +0 -0
  149. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_redis_service.py +0 -0
  150. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_redis_set.py +0 -0
  151. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_redis_string.py +0 -0
  152. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_redis_zset.py +0 -0
  153. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_site_settings_manager.py +0 -0
  154. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_stream_consumer.py +0 -0
  155. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_stream_dispatcher.py +0 -0
  156. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_stream_processor.py +0 -0
  157. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_stream_producer.py +0 -0
  158. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_stream_router.py +0 -0
  159. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_stream_runtime.py +0 -0
  160. {codex_platform-0.5.0 → codex_platform-0.5.1}/tests/unit/test_sync_operations.py +0 -0
  161. {codex_platform-0.5.0 → codex_platform-0.5.1}/tools/__init__.py +0 -0
  162. {codex_platform-0.5.0 → codex_platform-0.5.1}/tools/dev/README.md +0 -0
  163. {codex_platform-0.5.0 → codex_platform-0.5.1}/tools/dev/__init__.py +0 -0
  164. {codex_platform-0.5.0 → codex_platform-0.5.1}/tools/dev/check.py +0 -0
  165. {codex_platform-0.5.0 → codex_platform-0.5.1}/tools/dev/generate_project_tree.py +0 -0
@@ -82,8 +82,8 @@ jobs:
82
82
  with:
83
83
  version: "0.10.7"
84
84
 
85
- - name: Sync dev environment
86
- run: uv sync --locked --extra dev
85
+ - name: Sync dev + docs environment
86
+ run: uv sync --locked --extra dev --extra docs
87
87
 
88
88
  - name: Run integration tests
89
89
  env:
@@ -5,6 +5,12 @@ Grouped by `Added` · `Changed` · `Deprecated` · `Removed` · `Fixed`.
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.5.1] - 2026-04-30
9
+
10
+ ### Fixed
11
+ - Fixed GitHub Actions integration environment to install docs dependencies required by the MkDocs build test.
12
+ - Stabilized the multi-consumer-group streams integration test by creating Redis consumer groups before publishing the shared event.
13
+
8
14
  ## [0.5.0] - 2026-04-30
9
15
 
10
16
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codex-platform
3
- Version: 0.5.0
3
+ Version: 0.5.1
4
4
  Summary: Modular async infrastructure (Redis, Streams, ARQ, Notifications) built for Codex, designed for independent use.
5
5
  Project-URL: Homepage, https://github.com/codexdlc/codex-platform
6
6
  Project-URL: Documentation, https://codexdlc.github.io/codex-platform/
@@ -31,12 +31,14 @@ Requires-Dist: bandit>=1.7; extra == 'dev'
31
31
  Requires-Dist: detect-secrets>=1.5; extra == 'dev'
32
32
  Requires-Dist: fakeredis[lua]>=2.20; extra == 'dev'
33
33
  Requires-Dist: jinja2>=3.1; extra == 'dev'
34
+ Requires-Dist: lupa>2.6; extra == 'dev'
34
35
  Requires-Dist: mypy>=1.10; extra == 'dev'
35
36
  Requires-Dist: pip-audit>=2.7; extra == 'dev'
37
+ Requires-Dist: pip>=26.1; extra == 'dev'
36
38
  Requires-Dist: pre-commit>=3.0; extra == 'dev'
37
39
  Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
38
40
  Requires-Dist: pytest-cov; extra == 'dev'
39
- Requires-Dist: pytest>=8.0; extra == 'dev'
41
+ Requires-Dist: pytest>=9.0.3; extra == 'dev'
40
42
  Requires-Dist: redis>=5.0; extra == 'dev'
41
43
  Requires-Dist: ruff>=0.4; extra == 'dev'
42
44
  Provides-Extra: docs
@@ -39,15 +39,17 @@ all = [
39
39
  ]
40
40
  dev = [
41
41
  "codex-platform[all]",
42
- "pytest>=8.0",
42
+ "pytest>=9.0.3",
43
43
  "pytest-asyncio>=0.23",
44
44
  "pytest-cov",
45
45
  "fakeredis[lua]>=2.20",
46
+ "lupa>2.6",
46
47
  "ruff>=0.4",
47
48
  "mypy>=1.10",
48
49
  "pre-commit>=3.0",
49
50
  "bandit>=1.7",
50
51
  "pip-audit>=2.7",
52
+ "pip>=26.1",
51
53
  "detect-secrets>=1.5",
52
54
  ]
53
55
  docs = [
@@ -205,6 +205,8 @@ async def test_two_consumer_groups_receive_same_event_history(clean_redis: Redis
205
205
  runtime_a.include_router(router_a)
206
206
  runtime_b.include_router(router_b)
207
207
 
208
+ await runtime_a.consumer.ensure_group()
209
+ await runtime_b.consumer.ensure_group()
208
210
  await runtime_a.start()
209
211
  await runtime_b.start()
210
212
  await runtime_a.producer.publish("shared.event", {"value": 7})
@@ -248,7 +248,9 @@ dev = [
248
248
  { name = "detect-secrets" },
249
249
  { name = "fakeredis", extra = ["lua"] },
250
250
  { name = "jinja2" },
251
+ { name = "lupa" },
251
252
  { name = "mypy" },
253
+ { name = "pip" },
252
254
  { name = "pip-audit" },
253
255
  { name = "pre-commit" },
254
256
  { name = "pytest" },
@@ -290,16 +292,18 @@ requires-dist = [
290
292
  { name = "jinja2", marker = "extra == 'all'", specifier = ">=3.1" },
291
293
  { name = "jinja2", marker = "extra == 'dev'", specifier = ">=3.1" },
292
294
  { name = "jinja2", marker = "extra == 'notifications'", specifier = ">=3.1" },
295
+ { name = "lupa", marker = "extra == 'dev'", specifier = ">2.6" },
293
296
  { name = "mike", marker = "extra == 'docs'", specifier = ">=2.0" },
294
297
  { name = "mkdocs", marker = "extra == 'docs'", specifier = ">=1.5,<2.0" },
295
298
  { name = "mkdocs-include-markdown-plugin", marker = "extra == 'docs'" },
296
299
  { name = "mkdocs-material", marker = "extra == 'docs'", specifier = ">=9.0" },
297
300
  { name = "mkdocstrings", extras = ["python"], marker = "extra == 'docs'", specifier = ">=0.24" },
298
301
  { name = "mypy", marker = "extra == 'dev'", specifier = ">=1.10" },
302
+ { name = "pip", marker = "extra == 'dev'", specifier = ">=26.1" },
299
303
  { name = "pip-audit", marker = "extra == 'dev'", specifier = ">=2.7" },
300
304
  { name = "pre-commit", marker = "extra == 'dev'", specifier = ">=3.0" },
301
305
  { name = "pydantic", specifier = ">=2.0,<3.0" },
302
- { name = "pytest", marker = "extra == 'dev'", specifier = ">=8.0" },
306
+ { name = "pytest", marker = "extra == 'dev'", specifier = ">=9.0.3" },
303
307
  { name = "pytest-asyncio", marker = "extra == 'dev'", specifier = ">=0.23" },
304
308
  { name = "pytest-cov", marker = "extra == 'dev'" },
305
309
  { name = "redis", marker = "extra == 'all'", specifier = ">=5.0" },
@@ -671,54 +675,54 @@ wheels = [
671
675
 
672
676
  [[package]]
673
677
  name = "lupa"
674
- version = "2.6"
675
- source = { registry = "https://pypi.org/simple" }
676
- sdist = { url = "https://files.pythonhosted.org/packages/b8/1c/191c3e6ec6502e3dbe25a53e27f69a5daeac3e56de1f73c0138224171ead/lupa-2.6.tar.gz", hash = "sha256:9a770a6e89576be3447668d7ced312cd6fd41d3c13c2462c9dc2c2ab570e45d9", size = 7240282, upload-time = "2025-10-24T07:20:29.738Z" }
677
- wheels = [
678
- { url = "https://files.pythonhosted.org/packages/94/86/ce243390535c39d53ea17ccf0240815e6e457e413e40428a658ea4ee4b8d/lupa-2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:47ce718817ef1cc0c40d87c3d5ae56a800d61af00fbc0fad1ca9be12df2f3b56", size = 951707, upload-time = "2025-10-24T07:18:03.884Z" },
679
- { url = "https://files.pythonhosted.org/packages/86/85/cedea5e6cbeb54396fdcc55f6b741696f3f036d23cfaf986d50d680446da/lupa-2.6-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:7aba985b15b101495aa4b07112cdc08baa0c545390d560ad5cfde2e9e34f4d58", size = 1916703, upload-time = "2025-10-24T07:18:05.6Z" },
680
- { url = "https://files.pythonhosted.org/packages/24/be/3d6b5f9a8588c01a4d88129284c726017b2089f3a3fd3ba8bd977292fea0/lupa-2.6-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:b766f62f95b2739f2248977d29b0722e589dcf4f0ccfa827ccbd29f0148bd2e5", size = 985152, upload-time = "2025-10-24T07:18:08.561Z" },
681
- { url = "https://files.pythonhosted.org/packages/eb/23/9f9a05beee5d5dce9deca4cb07c91c40a90541fc0a8e09db4ee670da550f/lupa-2.6-cp312-cp312-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:00a934c23331f94cb51760097ebfab14b005d55a6b30a2b480e3c53dd2fa290d", size = 1159599, upload-time = "2025-10-24T07:18:10.346Z" },
682
- { url = "https://files.pythonhosted.org/packages/40/4e/e7c0583083db9d7f1fd023800a9767d8e4391e8330d56c2373d890ac971b/lupa-2.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21de9f38bd475303e34a042b7081aabdf50bd9bafd36ce4faea2f90fd9f15c31", size = 1038686, upload-time = "2025-10-24T07:18:12.112Z" },
683
- { url = "https://files.pythonhosted.org/packages/1c/9f/5a4f7d959d4feba5e203ff0c31889e74d1ca3153122be4a46dca7d92bf7c/lupa-2.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf3bda96d3fc41237e964a69c23647d50d4e28421111360274d4799832c560e9", size = 2071956, upload-time = "2025-10-24T07:18:14.572Z" },
684
- { url = "https://files.pythonhosted.org/packages/92/34/2f4f13ca65d01169b1720176aedc4af17bc19ee834598c7292db232cb6dc/lupa-2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a76ead245da54801a81053794aa3975f213221f6542d14ec4b859ee2e7e0323", size = 1057199, upload-time = "2025-10-24T07:18:16.379Z" },
685
- { url = "https://files.pythonhosted.org/packages/35/2a/5f7d2eebec6993b0dcd428e0184ad71afb06a45ba13e717f6501bfed1da3/lupa-2.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8dd0861741caa20886ddbda0a121d8e52fb9b5bb153d82fa9bba796962bf30e8", size = 1173693, upload-time = "2025-10-24T07:18:18.153Z" },
686
- { url = "https://files.pythonhosted.org/packages/e4/29/089b4d2f8e34417349af3904bb40bec40b65c8731f45e3fd8d497ca573e5/lupa-2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:239e63948b0b23023f81d9a19a395e768ed3da6a299f84e7963b8f813f6e3f9c", size = 2164394, upload-time = "2025-10-24T07:18:20.403Z" },
687
- { url = "https://files.pythonhosted.org/packages/f3/1b/79c17b23c921f81468a111cad843b076a17ef4b684c4a8dff32a7969c3f0/lupa-2.6-cp312-cp312-win32.whl", hash = "sha256:325894e1099499e7a6f9c351147661a2011887603c71086d36fe0f964d52d1ce", size = 1420647, upload-time = "2025-10-24T07:18:23.368Z" },
688
- { url = "https://files.pythonhosted.org/packages/b8/15/5121e68aad3584e26e1425a5c9a79cd898f8a152292059e128c206ee817c/lupa-2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c735a1ce8ee60edb0fe71d665f1e6b7c55c6021f1d340eb8c865952c602cd36f", size = 1688529, upload-time = "2025-10-24T07:18:25.523Z" },
689
- { url = "https://files.pythonhosted.org/packages/28/1d/21176b682ca5469001199d8b95fa1737e29957a3d185186e7a8b55345f2e/lupa-2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:663a6e58a0f60e7d212017d6678639ac8df0119bc13c2145029dcba084391310", size = 947232, upload-time = "2025-10-24T07:18:27.878Z" },
690
- { url = "https://files.pythonhosted.org/packages/ce/4c/d327befb684660ca13cf79cd1f1d604331808f9f1b6fb6bf57832f8edf80/lupa-2.6-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:d1f5afda5c20b1f3217a80e9bc1b77037f8a6eb11612fd3ada19065303c8f380", size = 1908625, upload-time = "2025-10-24T07:18:29.944Z" },
691
- { url = "https://files.pythonhosted.org/packages/66/8e/ad22b0a19454dfd08662237a84c792d6d420d36b061f239e084f29d1a4f3/lupa-2.6-cp313-cp313-macosx_11_0_x86_64.whl", hash = "sha256:26f2b3c085fe76e9119e48c1013c1cccdc1f51585d456858290475aa38e7089e", size = 981057, upload-time = "2025-10-24T07:18:31.553Z" },
692
- { url = "https://files.pythonhosted.org/packages/5c/48/74859073ab276bd0566c719f9ca0108b0cfc1956ca0d68678d117d47d155/lupa-2.6-cp313-cp313-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:60d2f902c7b96fb8ab98493dcff315e7bb4d0b44dc9dd76eb37de575025d5685", size = 1156227, upload-time = "2025-10-24T07:18:33.981Z" },
693
- { url = "https://files.pythonhosted.org/packages/09/6c/0e9ded061916877253c2266074060eb71ed99fb21d73c8c114a76725bce2/lupa-2.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a02d25dee3a3250967c36590128d9220ae02f2eda166a24279da0b481519cbff", size = 1035752, upload-time = "2025-10-24T07:18:36.32Z" },
694
- { url = "https://files.pythonhosted.org/packages/dd/ef/f8c32e454ef9f3fe909f6c7d57a39f950996c37a3deb7b391fec7903dab7/lupa-2.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6eae1ee16b886b8914ff292dbefbf2f48abfbdee94b33a88d1d5475e02423203", size = 2069009, upload-time = "2025-10-24T07:18:38.072Z" },
695
- { url = "https://files.pythonhosted.org/packages/53/dc/15b80c226a5225815a890ee1c11f07968e0aba7a852df41e8ae6fe285063/lupa-2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0edd5073a4ee74ab36f74fe61450148e6044f3952b8d21248581f3c5d1a58be", size = 1056301, upload-time = "2025-10-24T07:18:40.165Z" },
696
- { url = "https://files.pythonhosted.org/packages/31/14/2086c1425c985acfb30997a67e90c39457122df41324d3c179d6ee2292c6/lupa-2.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0c53ee9f22a8a17e7d4266ad48e86f43771951797042dd51d1494aaa4f5f3f0a", size = 1170673, upload-time = "2025-10-24T07:18:42.426Z" },
697
- { url = "https://files.pythonhosted.org/packages/10/e5/b216c054cf86576c0191bf9a9f05de6f7e8e07164897d95eea0078dca9b2/lupa-2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:de7c0f157a9064a400d828789191a96da7f4ce889969a588b87ec80de9b14772", size = 2162227, upload-time = "2025-10-24T07:18:46.112Z" },
698
- { url = "https://files.pythonhosted.org/packages/59/2f/33ecb5bedf4f3bc297ceacb7f016ff951331d352f58e7e791589609ea306/lupa-2.6-cp313-cp313-win32.whl", hash = "sha256:ee9523941ae0a87b5b703417720c5d78f72d2f5bc23883a2ea80a949a3ed9e75", size = 1419558, upload-time = "2025-10-24T07:18:48.371Z" },
699
- { url = "https://files.pythonhosted.org/packages/f9/b4/55e885834c847ea610e111d87b9ed4768f0afdaeebc00cd46810f25029f6/lupa-2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b1335a5835b0a25ebdbc75cf0bda195e54d133e4d994877ef025e218c2e59db9", size = 1683424, upload-time = "2025-10-24T07:18:50.976Z" },
700
- { url = "https://files.pythonhosted.org/packages/66/9d/d9427394e54d22a35d1139ef12e845fd700d4872a67a34db32516170b746/lupa-2.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:dcb6d0a3264873e1653bc188499f48c1fb4b41a779e315eba45256cfe7bc33c1", size = 953818, upload-time = "2025-10-24T07:18:53.378Z" },
701
- { url = "https://files.pythonhosted.org/packages/10/41/27bbe81953fb2f9ecfced5d9c99f85b37964cfaf6aa8453bb11283983721/lupa-2.6-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:a37e01f2128f8c36106726cb9d360bac087d58c54b4522b033cc5691c584db18", size = 1915850, upload-time = "2025-10-24T07:18:55.259Z" },
702
- { url = "https://files.pythonhosted.org/packages/a3/98/f9ff60db84a75ba8725506bbf448fb085bc77868a021998ed2a66d920568/lupa-2.6-cp314-cp314-macosx_11_0_x86_64.whl", hash = "sha256:458bd7e9ff3c150b245b0fcfbb9bd2593d1152ea7f0a7b91c1d185846da033fe", size = 982344, upload-time = "2025-10-24T07:18:57.05Z" },
703
- { url = "https://files.pythonhosted.org/packages/41/f7/f39e0f1c055c3b887d86b404aaf0ca197b5edfd235a8b81b45b25bac7fc3/lupa-2.6-cp314-cp314-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:052ee82cac5206a02df77119c325339acbc09f5ce66967f66a2e12a0f3211cad", size = 1156543, upload-time = "2025-10-24T07:18:59.251Z" },
704
- { url = "https://files.pythonhosted.org/packages/9e/9c/59e6cffa0d672d662ae17bd7ac8ecd2c89c9449dee499e3eb13ca9cd10d9/lupa-2.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96594eca3c87dd07938009e95e591e43d554c1dbd0385be03c100367141db5a8", size = 1047974, upload-time = "2025-10-24T07:19:01.449Z" },
705
- { url = "https://files.pythonhosted.org/packages/23/c6/a04e9cef7c052717fcb28fb63b3824802488f688391895b618e39be0f684/lupa-2.6-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8faddd9d198688c8884091173a088a8e920ecc96cda2ffed576a23574c4b3f6", size = 2073458, upload-time = "2025-10-24T07:19:03.369Z" },
706
- { url = "https://files.pythonhosted.org/packages/e6/10/824173d10f38b51fc77785228f01411b6ca28826ce27404c7c912e0e442c/lupa-2.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:daebb3a6b58095c917e76ba727ab37b27477fb926957c825205fbda431552134", size = 1067683, upload-time = "2025-10-24T07:19:06.2Z" },
707
- { url = "https://files.pythonhosted.org/packages/b6/dc/9692fbcf3c924d9c4ece2d8d2f724451ac2e09af0bd2a782db1cef34e799/lupa-2.6-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f3154e68972befe0f81564e37d8142b5d5d79931a18309226a04ec92487d4ea3", size = 1171892, upload-time = "2025-10-24T07:19:08.544Z" },
708
- { url = "https://files.pythonhosted.org/packages/84/ff/e318b628d4643c278c96ab3ddea07fc36b075a57383c837f5b11e537ba9d/lupa-2.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e4dadf77b9fedc0bfa53417cc28dc2278a26d4cbd95c29f8927ad4d8fe0a7ef9", size = 2166641, upload-time = "2025-10-24T07:19:10.485Z" },
709
- { url = "https://files.pythonhosted.org/packages/12/f7/a6f9ec2806cf2d50826980cdb4b3cffc7691dc6f95e13cc728846d5cb793/lupa-2.6-cp314-cp314-win32.whl", hash = "sha256:cb34169c6fa3bab3e8ac58ca21b8a7102f6a94b6a5d08d3636312f3f02fafd8f", size = 1456857, upload-time = "2025-10-24T07:19:37.989Z" },
710
- { url = "https://files.pythonhosted.org/packages/c5/de/df71896f25bdc18360fdfa3b802cd7d57d7fede41a0e9724a4625b412c85/lupa-2.6-cp314-cp314-win_amd64.whl", hash = "sha256:b74f944fe46c421e25d0f8692aef1e842192f6f7f68034201382ac440ef9ea67", size = 1731191, upload-time = "2025-10-24T07:19:40.281Z" },
711
- { url = "https://files.pythonhosted.org/packages/47/3c/a1f23b01c54669465f5f4c4083107d496fbe6fb45998771420e9aadcf145/lupa-2.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0e21b716408a21ab65723f8841cf7f2f37a844b7a965eeabb785e27fca4099cf", size = 999343, upload-time = "2025-10-24T07:19:12.519Z" },
712
- { url = "https://files.pythonhosted.org/packages/c5/6d/501994291cb640bfa2ccf7f554be4e6914afa21c4026bd01bff9ca8aac57/lupa-2.6-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:589db872a141bfff828340079bbdf3e9a31f2689f4ca0d88f97d9e8c2eae6142", size = 2000730, upload-time = "2025-10-24T07:19:14.869Z" },
713
- { url = "https://files.pythonhosted.org/packages/53/a5/457ffb4f3f20469956c2d4c4842a7675e884efc895b2f23d126d23e126cc/lupa-2.6-cp314-cp314t-macosx_11_0_x86_64.whl", hash = "sha256:cd852a91a4a9d4dcbb9a58100f820a75a425703ec3e3f049055f60b8533b7953", size = 1021553, upload-time = "2025-10-24T07:19:17.123Z" },
714
- { url = "https://files.pythonhosted.org/packages/51/6b/36bb5a5d0960f2a5c7c700e0819abb76fd9bf9c1d8a66e5106416d6e9b14/lupa-2.6-cp314-cp314t-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:0334753be028358922415ca97a64a3048e4ed155413fc4eaf87dd0a7e2752983", size = 1133275, upload-time = "2025-10-24T07:19:20.51Z" },
715
- { url = "https://files.pythonhosted.org/packages/19/86/202ff4429f663013f37d2229f6176ca9f83678a50257d70f61a0a97281bf/lupa-2.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:661d895cd38c87658a34780fac54a690ec036ead743e41b74c3fb81a9e65a6aa", size = 1038441, upload-time = "2025-10-24T07:19:22.509Z" },
716
- { url = "https://files.pythonhosted.org/packages/a7/42/d8125f8e420714e5b52e9c08d88b5329dfb02dcca731b4f21faaee6cc5b5/lupa-2.6-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6aa58454ccc13878cc177c62529a2056be734da16369e451987ff92784994ca7", size = 2058324, upload-time = "2025-10-24T07:19:24.979Z" },
717
- { url = "https://files.pythonhosted.org/packages/2b/2c/47bf8b84059876e877a339717ddb595a4a7b0e8740bacae78ba527562e1c/lupa-2.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1425017264e470c98022bba8cff5bd46d054a827f5df6b80274f9cc71dafd24f", size = 1060250, upload-time = "2025-10-24T07:19:27.262Z" },
718
- { url = "https://files.pythonhosted.org/packages/c2/06/d88add2b6406ca1bdec99d11a429222837ca6d03bea42ca75afa169a78cb/lupa-2.6-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:224af0532d216e3105f0a127410f12320f7c5f1aa0300bdf9646b8d9afb0048c", size = 1151126, upload-time = "2025-10-24T07:19:29.522Z" },
719
- { url = "https://files.pythonhosted.org/packages/b4/a0/89e6a024c3b4485b89ef86881c9d55e097e7cb0bdb74efb746f2fa6a9a76/lupa-2.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9abb98d5a8fd27c8285302e82199f0e56e463066f88f619d6594a450bf269d80", size = 2153693, upload-time = "2025-10-24T07:19:31.379Z" },
720
- { url = "https://files.pythonhosted.org/packages/b6/36/a0f007dc58fc1bbf51fb85dcc82fcb1f21b8c4261361de7dab0e3d8521ef/lupa-2.6-cp314-cp314t-win32.whl", hash = "sha256:1849efeba7a8f6fb8aa2c13790bee988fd242ae404bd459509640eeea3d1e291", size = 1590104, upload-time = "2025-10-24T07:19:33.514Z" },
721
- { url = "https://files.pythonhosted.org/packages/7d/5e/db903ce9cf82c48d6b91bf6d63ae4c8d0d17958939a4e04ba6b9f38b8643/lupa-2.6-cp314-cp314t-win_amd64.whl", hash = "sha256:fc1498d1a4fc028bc521c26d0fad4ca00ed63b952e32fb95949bda76a04bad52", size = 1913818, upload-time = "2025-10-24T07:19:36.039Z" },
678
+ version = "2.8"
679
+ source = { registry = "https://pypi.org/simple" }
680
+ sdist = { url = "https://files.pythonhosted.org/packages/c3/a6/0f869fbb07c393f15473b1eefefb7b5bec162fb7481803d040ed4dc46002/lupa-2.8.tar.gz", hash = "sha256:d8022641b9ec8ecf2c5ecbe9f47e5a70e0b87c4b5ae921b92cb02a638e0acd08", size = 6156370, upload-time = "2026-04-15T20:08:30.534Z" }
681
+ wheels = [
682
+ { url = "https://files.pythonhosted.org/packages/09/21/9be4516ddd22f8eadba336d9ba065d17d79108465ae1b7f71424ab99b9d0/lupa-2.8-cp310-abi3-win32.whl", hash = "sha256:c2a5fd15dc62374e1661a55f01744c9ec1c56f291ba4a0749d3af2174556e78f", size = 1594887, upload-time = "2026-04-15T20:05:23.377Z" },
683
+ { url = "https://files.pythonhosted.org/packages/2d/99/1557c9685d7034d9ce8dd2b54c40a26d6deb7c67c1fdb5c801abd1a02c3f/lupa-2.8-cp310-abi3-win_arm64.whl", hash = "sha256:9e304fb1c50cf23fd8882afbe1aa87525ef8a72667bcab3b37b2bbb2bc542269", size = 1371742, upload-time = "2026-04-15T20:05:27.417Z" },
684
+ { url = "https://files.pythonhosted.org/packages/ad/0b/368f2f0bc750b25c69d4563e44f677925ab5dd3d2887f9b0c15465d21a2a/lupa-2.8-cp312-abi3-macosx_10_13_x86_64.whl", hash = "sha256:f4342f4de76ae7ce2ab0672d36003bdb7e1a33252f293b569298ddd792e70e33", size = 1194056, upload-time = "2026-04-15T20:05:55.794Z" },
685
+ { url = "https://files.pythonhosted.org/packages/5b/0f/c89eb8dd36fdea4e50ae3f7f5275bea3b0cc5d4057b8ee7b3bbc78010422/lupa-2.8-cp312-abi3-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:4203fa1659315e939a5304e75001b8cc14234fb3cbb3ed86c049b0cc5d90fcee", size = 1434278, upload-time = "2026-04-15T20:05:57.94Z" },
686
+ { url = "https://files.pythonhosted.org/packages/47/30/c3b4d2cd8733621b404b8a4214e5f852955c4ba632546dc84123bea9ee89/lupa-2.8-cp312-abi3-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:81f2d843ce668b653146c007467570210ae44be51dac6926666c51d49536f307", size = 1150068, upload-time = "2026-04-15T20:06:01.04Z" },
687
+ { url = "https://files.pythonhosted.org/packages/8d/d2/bac12c398519efafc6af84be1974edd0d7a4895fb4735b5c8d615d298595/lupa-2.8-cp312-abi3-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d3d0cde2c77588d1c60875a4f34f059513476c6e1775351897195b51e0f3df08", size = 1409532, upload-time = "2026-04-15T20:06:03.592Z" },
688
+ { url = "https://files.pythonhosted.org/packages/9c/6a/18b52e11962014026e07813530b0b108ee8bc0a2a13ef0eaea5d41dce023/lupa-2.8-cp312-abi3-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9e0d11b8f3a8dac6413f704fef7161d048bb10c58bdac6cbffa5e60efa56e9a3", size = 1242687, upload-time = "2026-04-15T20:06:06.863Z" },
689
+ { url = "https://files.pythonhosted.org/packages/b3/8e/7fd4eb049875f61429b96780d2eae4700f0e78fe0a52db8edb231b1cd09f/lupa-2.8-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:54cff414f21f8cd8c6be4aae52541f3b9cd39602b59e3a3db9b5c9f9f674ff18", size = 1856038, upload-time = "2026-04-15T20:06:09.358Z" },
690
+ { url = "https://files.pythonhosted.org/packages/e9/f9/37ad9d2773d30f2931890d310a4bdce28d45484206e6f48bc18b0325eabd/lupa-2.8-cp312-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:24b4d8af5558e549b70daf1547f5c1c1d664ecea9fc790f83efe5d75e9a93797", size = 1128982, upload-time = "2026-04-15T20:06:12.312Z" },
691
+ { url = "https://files.pythonhosted.org/packages/57/31/c0fd7984c24844ea79caa45c0235f61a06b38fd69a839f6c62770f8d684a/lupa-2.8-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:ce86dff1ee7f7cf45f5622065ae991949dd7bb1703581cbc58a630137bb7ccf9", size = 1457594, upload-time = "2026-04-15T20:06:15.881Z" },
692
+ { url = "https://files.pythonhosted.org/packages/11/f5/a28e411be30ec1bf0db1eb0c087eebc73be9e7a1adcfe6ac209861ccc446/lupa-2.8-cp312-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:f4d01b2a08c70bbb883a9e082b6b36b89121ed5910b710f1ba11c73295ff4fba", size = 1425721, upload-time = "2026-04-15T20:06:18.009Z" },
693
+ { url = "https://files.pythonhosted.org/packages/ed/c1/359f767c4ae024be30d909fe8a9f0e9af266bad47ce2bd2ed248fb986fcf/lupa-2.8-cp312-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:7f210d5a8353e510ea1199c42cf3cbdd630553bf2bc8fb4c00fea06fdec7c798", size = 1253258, upload-time = "2026-04-15T20:06:21.17Z" },
694
+ { url = "https://files.pythonhosted.org/packages/17/52/473f11790c261fd02bbf318a546fe040e9ec9f677181272fa78d3b4112a4/lupa-2.8-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4f81a02806e7c7ad26d8c6fa222c8bef1b0c1b124347c879be880b41339d41e4", size = 2395272, upload-time = "2026-04-15T20:06:24.137Z" },
695
+ { url = "https://files.pythonhosted.org/packages/94/bf/75c8795655a8836eab6a11a630352c4b7c5dc5c54d075077bc9bffdeee45/lupa-2.8-cp312-abi3-win32.whl", hash = "sha256:360056453a7a4eaa4ac5a204c31a5a014b1eb2ee5490603234d2ba831684f1f2", size = 1606136, upload-time = "2026-04-15T20:06:27.815Z" },
696
+ { url = "https://files.pythonhosted.org/packages/d8/29/11a2cdd612b6f55e506292dfb6ba343216e80a693e7fe3f876ef204ce9c6/lupa-2.8-cp312-abi3-win_arm64.whl", hash = "sha256:1628371c6592a6d5650497a9e31fb2bb3a7e9883c1f301d1111265e484045af9", size = 1364495, upload-time = "2026-04-15T20:06:30.254Z" },
697
+ { url = "https://files.pythonhosted.org/packages/4d/17/fa834b6b09ad17e7df5d0f7715d64877a125a3776ada689751a1f9dc2959/lupa-2.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:450650f91c48c2415b0d59ab3abfcfda3b6efb5b858205f4d4bda8ad141fa529", size = 1190111, upload-time = "2026-04-15T20:06:32.84Z" },
698
+ { url = "https://files.pythonhosted.org/packages/ab/43/45589901b7d1a0e3a9d91d19a311fb6a56924e8571536c3f2212160fd953/lupa-2.8-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27044f3363047f946b3d3aab9157cbd172b3538ada9ec1baef43432bf7d03a78", size = 1812999, upload-time = "2026-04-15T20:06:35.664Z" },
699
+ { url = "https://files.pythonhosted.org/packages/a1/ac/4ade7d15ff5c61758d7943ac6f0a496bf1cc65b6c09f842b52a0702e664c/lupa-2.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8cf4f064a0e5531afce2d7d750120c10c10f9529139af6ca6150d13151034398", size = 2368731, upload-time = "2026-04-15T20:06:37.959Z" },
700
+ { url = "https://files.pythonhosted.org/packages/0c/27/05f950d15b8ab120b39c43588b438ff3ace70c1b1b0225a960393a497483/lupa-2.8-cp312-cp312-win_amd64.whl", hash = "sha256:281bedc5deb92d31e649a3552edd662449365a635904fa4d5cb4509c7245e34e", size = 1941809, upload-time = "2026-04-15T20:06:40.302Z" },
701
+ { url = "https://files.pythonhosted.org/packages/a6/3f/19f83c3a0c84dc8bea8a58e7416dca6a3ede662c33c8d1ec758e5afc754a/lupa-2.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45fc9da0145ecb0083ef5ff9975116cc784bd0258bdc2bd131ba15483ce18398", size = 1201203, upload-time = "2026-04-15T20:06:42.169Z" },
702
+ { url = "https://files.pythonhosted.org/packages/89/0f/a14f0073f09610158038582e230618a48c14da6bd88185289461aa4cb854/lupa-2.8-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:58e18afed57955b41130e269c78f53d4123ab86e236b53816f4cbffa25cb5d30", size = 1806210, upload-time = "2026-04-15T20:06:45.486Z" },
703
+ { url = "https://files.pythonhosted.org/packages/2f/14/48fff156c63a136001a7620878af7d31aa07e66b495ed621e3eddd73c294/lupa-2.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fc47f536ac13a79cef47d29a2b205576a22841f042a2bcec1676b95806e7706a", size = 2359005, upload-time = "2026-04-15T20:06:47.819Z" },
704
+ { url = "https://files.pythonhosted.org/packages/fe/18/3ac638ec90edf178242b8a2b2f00f8adae694248c03a26341ef941bb746e/lupa-2.8-cp313-cp313-win_amd64.whl", hash = "sha256:ce9404c661dbac65cc9bed351ad45e797af93d30d70be309a3fa8209ac86d93b", size = 1936754, upload-time = "2026-04-15T20:06:50.448Z" },
705
+ { url = "https://files.pythonhosted.org/packages/b0/ef/5ee5fed6ea7459a671196359ce04bfeeaf26be1dac8ff24bf28e5c7a6e81/lupa-2.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:348c3f8ecabb6324dcbc05c2740d762ef8fcec7b06c79e45262ab97a217684e3", size = 1209388, upload-time = "2026-04-15T20:06:53.022Z" },
706
+ { url = "https://files.pythonhosted.org/packages/6e/b1/67a940d5542cb0384b443fe951b5a83ea9340d1333a733a258fdd1c619ba/lupa-2.8-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:951496471056061598a7d1729a6cdf48d662fec777a9f2d8aa5a1e62fd30e5a5", size = 1826821, upload-time = "2026-04-15T20:06:55.699Z" },
707
+ { url = "https://files.pythonhosted.org/packages/a1/a2/b354e5ba3b911ec50686003dc8897e892b9e8c5c036b33219b03d54c4daf/lupa-2.8-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a591b9947ca347b41a63370e121d6e2b1458fe6dde9ae065029ec10a37f25ff4", size = 2366893, upload-time = "2026-04-15T20:06:58.9Z" },
708
+ { url = "https://files.pythonhosted.org/packages/8e/52/d76066401f29539df5352f70ecded66576f32933b6045cd0bfc56cb770b9/lupa-2.8-cp314-cp314-win_amd64.whl", hash = "sha256:3903c9cf628dae2f56405503247b77a61a3a61bd2dda470e336950c74776d55d", size = 1994716, upload-time = "2026-04-15T20:07:19.194Z" },
709
+ { url = "https://files.pythonhosted.org/packages/c3/bd/3efc437a4361c16d25e66478c50357c9a8e8ecfb718fe749eb9ca3176ef6/lupa-2.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f711a8ab0486b9ac6fdda94a22ddcfbc9f0d4a27e3a8cf1bf79c6e48b33017c1", size = 1251217, upload-time = "2026-04-15T20:07:01.64Z" },
710
+ { url = "https://files.pythonhosted.org/packages/ea/f4/2e9f8ecbaca854bfdf14af8a9b505ec0cbc640377b3b218921594b7563cd/lupa-2.8-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc51250e76367a3e27fcd01dc769b9bfcbbc34f48df48dde53d6af6e75b7eaa5", size = 1814701, upload-time = "2026-04-15T20:07:04.149Z" },
711
+ { url = "https://files.pythonhosted.org/packages/ba/53/4000b1acaa8b1f3827fcff0cfcdff44d3befddda42cab7e685a49689b5a1/lupa-2.8-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f8a22088a552828958603323f0a5c4b3e11e03b75d0bf4c965ef879de9b60a8d", size = 2348414, upload-time = "2026-04-15T20:07:07.285Z" },
712
+ { url = "https://files.pythonhosted.org/packages/d5/78/26ee48d3890cddf03cefb65f433e3492759c0b3c0582180755bddbaab7bd/lupa-2.8-cp314-cp314t-win32.whl", hash = "sha256:4f7c553c1d8cfffbe85d81daef730d12cae4b6002d457542914da0ac8a1145b3", size = 1831611, upload-time = "2026-04-15T20:07:09.752Z" },
713
+ { url = "https://files.pythonhosted.org/packages/3c/d1/4a5cc64a3cad22821ae4c3f7a90456a08ca19457d8354f4abf46ad03c7e8/lupa-2.8-cp314-cp314t-win_amd64.whl", hash = "sha256:d8766aff03a78c80ad2d188a8bdb216de5ec838359cd87e05bbdfa56394a6105", size = 2209250, upload-time = "2026-04-15T20:07:11.906Z" },
714
+ { url = "https://files.pythonhosted.org/packages/37/7c/cdcb654daf668192aaf36b0aeb94f2281dad092aaa5003688691131736ea/lupa-2.8-cp314-cp314t-win_arm64.whl", hash = "sha256:91d622777febda3ab1bed1d45295f2f32a4680c7b3d7caf8c669998ed5c44118", size = 1126735, upload-time = "2026-04-15T20:07:15.434Z" },
715
+ { url = "https://files.pythonhosted.org/packages/1d/44/de1961ad38e17cd326a53c246c7e3b91178ed578f4cf22ffcd5e7e11b041/lupa-2.8-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b036738282a5acd2e71fdddb317c9df8b87c1673aa57f403d05fcc2be8abc4ba", size = 1186020, upload-time = "2026-04-15T20:07:35.017Z" },
716
+ { url = "https://files.pythonhosted.org/packages/13/c2/276f0b9dc8bcc5a8a58af5316dfa0e6f56be3613dd6dbcc8d3d2cb6559ba/lupa-2.8-cp39-abi3-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:ac6b6e8d0e617e26a98cbb44880bcd75de5d32b3ad7b3b3793583909292b47ed", size = 1468944, upload-time = "2026-04-15T20:07:37.782Z" },
717
+ { url = "https://files.pythonhosted.org/packages/63/38/52934e52a5180dc6425d20284d004fe4b27a4f9171a82dc99fb67af250bf/lupa-2.8-cp39-abi3-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ba3a7dd839f90c3d2e53bebe3c192b1f3f9fd720a6781256405123211fd0dce6", size = 1172998, upload-time = "2026-04-15T20:07:40.812Z" },
718
+ { url = "https://files.pythonhosted.org/packages/c7/82/76b3809bd0839d9b3b4ec58d06591e08f17337b6d9576877cb9d48b34e94/lupa-2.8-cp39-abi3-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d7edb13a7a5250b5c6c22d1495d9e842b5c9fc5081c8fe6b5efe2112fe3e41f9", size = 1449975, upload-time = "2026-04-15T20:07:44.262Z" },
719
+ { url = "https://files.pythonhosted.org/packages/16/07/2f89d54f747c67c23b4b9ae4aa8c8dd06bb409155dedcf406157f2736b66/lupa-2.8-cp39-abi3-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:891f72e0bffbed1e4175f975aeb2a083956586a100066525e1be485f617f7b25", size = 1281944, upload-time = "2026-04-15T20:07:46.458Z" },
720
+ { url = "https://files.pythonhosted.org/packages/e7/bd/7375d2b0fcae79d806baf52a76f26c96964593f58e1372d13ae5ac09c676/lupa-2.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:a295f87b5b7ebbfd5191932e8cb0e51df3c7769101ac6b6c7d7c9fb27bfd1307", size = 1910455, upload-time = "2026-04-15T20:07:49.75Z" },
721
+ { url = "https://files.pythonhosted.org/packages/8b/0c/8abb3bc0e08b311fc01db05b6e9f9ff31a8f65e4fc3f0aeb05cfef75c8ac/lupa-2.8-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:4fe5d7a810b64ea8511eb885fc8cdde042ee5ff7b7d08ae78f32449756acb177", size = 1155548, upload-time = "2026-04-15T20:07:52.657Z" },
722
+ { url = "https://files.pythonhosted.org/packages/80/2e/9eeecd3f493099721c1d3f31beeca23a4237db1a54223684df4dc96aa1bd/lupa-2.8-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:bfc470012ef66ad064c7bd77416af03a3452ef630b04b9012595ea13f2e54518", size = 1489232, upload-time = "2026-04-15T20:07:54.92Z" },
723
+ { url = "https://files.pythonhosted.org/packages/c3/13/731c99dc2e7652ae818a6de45bdf0142049f7cb566049061c898355f1891/lupa-2.8-cp39-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:250e035fdaffe8c87093e3ebc206ac29a26131b1568ea711d780c26001ce96e7", size = 1466321, upload-time = "2026-04-15T20:07:57.627Z" },
724
+ { url = "https://files.pythonhosted.org/packages/de/71/3ad8cc4fc05a77dc0d3f7079348bd1cad4675a0d14c24f8e6a3ce5f008f7/lupa-2.8-cp39-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:b9bddb09acfffb4f828f790f444b11dc0cca591afea1a244d9329eea2d20c003", size = 1288577, upload-time = "2026-04-15T20:07:59.913Z" },
725
+ { url = "https://files.pythonhosted.org/packages/d8/b2/1175f6d0aa7b68627fbe2f58bd1e8bea36a89d10dfd67671d2b024c96162/lupa-2.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2e64acbbd47e9b82a64405a39e0d2b36a5a7dad8ab41c0f3437f572f7d282ba3", size = 2444866, upload-time = "2026-04-15T20:08:02.753Z" },
722
726
  ]
723
727
 
724
728
  [[package]]
@@ -1105,11 +1109,11 @@ wheels = [
1105
1109
 
1106
1110
  [[package]]
1107
1111
  name = "pip"
1108
- version = "26.0.1"
1112
+ version = "26.1"
1109
1113
  source = { registry = "https://pypi.org/simple" }
1110
- sdist = { url = "https://files.pythonhosted.org/packages/48/83/0d7d4e9efe3344b8e2fe25d93be44f64b65364d3c8d7bc6dc90198d5422e/pip-26.0.1.tar.gz", hash = "sha256:c4037d8a277c89b320abe636d59f91e6d0922d08a05b60e85e53b296613346d8", size = 1812747, upload-time = "2026-02-05T02:20:18.702Z" }
1114
+ sdist = { url = "https://files.pythonhosted.org/packages/73/7e/d2b04004e1068ad4fdfa2f227b839b5d03e602e47cdbbf49de71137c9546/pip-26.1.tar.gz", hash = "sha256:81e13ebcca3ffa8cc85e4deff5c27e1ee26dea0aa7fc2f294a073ac208806ff3", size = 1840316, upload-time = "2026-04-26T21:00:05.406Z" }
1111
1115
  wheels = [
1112
- { url = "https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl", hash = "sha256:bdb1b08f4274833d62c1aa29e20907365a2ceb950410df15fc9521bad440122b", size = 1787723, upload-time = "2026-02-05T02:20:16.416Z" },
1116
+ { url = "https://files.pythonhosted.org/packages/70/7a/be4bd8bcbb24ea475856dd68159d78b03b2bb53dae369f69c9606b8888f5/pip-26.1-py3-none-any.whl", hash = "sha256:4e8486d821d814b77319acb7b9e8bf5a4ee7590a643e7cb21029f209be8573c1", size = 1812804, upload-time = "2026-04-26T21:00:03.194Z" },
1113
1117
  ]
1114
1118
 
1115
1119
  [[package]]
@@ -1346,7 +1350,7 @@ wheels = [
1346
1350
 
1347
1351
  [[package]]
1348
1352
  name = "pytest"
1349
- version = "9.0.2"
1353
+ version = "9.0.3"
1350
1354
  source = { registry = "https://pypi.org/simple" }
1351
1355
  dependencies = [
1352
1356
  { name = "colorama", marker = "sys_platform == 'win32'" },
@@ -1355,9 +1359,9 @@ dependencies = [
1355
1359
  { name = "pluggy" },
1356
1360
  { name = "pygments" },
1357
1361
  ]
1358
- sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" }
1362
+ sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" }
1359
1363
  wheels = [
1360
- { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" },
1364
+ { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" },
1361
1365
  ]
1362
1366
 
1363
1367
  [[package]]
File without changes
File without changes
File without changes