loom-kernel 0.9.1__tar.gz → 0.9.2__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 (802) hide show
  1. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/CHANGELOG.md +17 -0
  2. loom_kernel-0.9.2/CHANGELOG_RELEASE.md +15 -0
  3. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/PKG-INFO +1 -1
  4. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/pyproject.toml +2 -2
  5. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/config/__init__.py +2 -0
  6. loom_kernel-0.9.2/src/loom/core/config/_resolver_utils.py +116 -0
  7. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/config/loader.py +1 -1
  8. loom_kernel-0.9.2/src/loom/core/config/secrets.py +144 -0
  9. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/config/ssm.py +6 -105
  10. loom_kernel-0.9.2/tests/unit/core/config/test_resolver_utils.py +130 -0
  11. loom_kernel-0.9.2/tests/unit/core/config/test_secrets.py +229 -0
  12. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/config/test_ssm.py +23 -7
  13. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/uv.lock +1 -1
  14. loom_kernel-0.9.1/CHANGELOG_RELEASE.md +0 -52
  15. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/.github/workflows/ci-main.yml +0 -0
  16. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/.github/workflows/ci-pr.yml +0 -0
  17. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/.github/workflows/docs.yml +0 -0
  18. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/.github/workflows/release.yml +0 -0
  19. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/.gitignore +0 -0
  20. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/.pre-commit-config.yaml +0 -0
  21. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/.readthedocs.yaml +0 -0
  22. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/LICENSE +0 -0
  23. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/Makefile +0 -0
  24. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/README.md +0 -0
  25. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/codecov.yml +0 -0
  26. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/_static/.gitkeep +0 -0
  27. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/_static/custom.css +0 -0
  28. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/_static/logo-transparent.png +0 -0
  29. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/_static/logo.svg +0 -0
  30. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/architecture/adr/README.md +0 -0
  31. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/architecture/clean-architecture.md +0 -0
  32. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/architecture/overview.md +0 -0
  33. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/conf.py +0 -0
  34. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/etl/examples.md +0 -0
  35. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/etl/pipelines.md +0 -0
  36. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/etl/testing.md +0 -0
  37. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/examples-repo/index.md +0 -0
  38. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/getting-started/etl.md +0 -0
  39. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/getting-started/rest.md +0 -0
  40. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/getting-started/streaming.md +0 -0
  41. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/guides/autocrud.md +0 -0
  42. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/guides/celery.md +0 -0
  43. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/guides/etl.md +0 -0
  44. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/guides/fake-repo-examples.md +0 -0
  45. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/guides/quickstart.md +0 -0
  46. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/guides/use-case-dsl.md +0 -0
  47. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/index.rst +0 -0
  48. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/overview.md +0 -0
  49. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/reference/api/core.rst +0 -0
  50. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/reference/api/etl.rst +0 -0
  51. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/reference/api/repository.rst +0 -0
  52. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/reference/api/rest.rst +0 -0
  53. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/reference/api/streaming.rst +0 -0
  54. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/reference/api/testing.rst +0 -0
  55. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/reference/index.rst +0 -0
  56. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/requirements.txt +0 -0
  57. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/rest/autocrud.md +0 -0
  58. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/rest/celery.md +0 -0
  59. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/rest/examples.md +0 -0
  60. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/rest/testing.md +0 -0
  61. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/rest/use-case-dsl.md +0 -0
  62. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/docs/streaming/bytewax.md +0 -0
  63. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/sonar-project.properties +0 -0
  64. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/__init__.py +0 -0
  65. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/celery/__init__.py +0 -0
  66. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/celery/auto.py +0 -0
  67. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/celery/bootstrap.py +0 -0
  68. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/celery/config.py +0 -0
  69. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/celery/constants.py +0 -0
  70. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/celery/runner.py +0 -0
  71. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/celery/service.py +0 -0
  72. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/async_bridge.py +0 -0
  73. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/backend/__init__.py +0 -0
  74. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/backend/core_model.py +0 -0
  75. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/backend/protocol.py +0 -0
  76. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/backend/sqlalchemy.py +0 -0
  77. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/bootstrap/__init__.py +0 -0
  78. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/bootstrap/bootstrap.py +0 -0
  79. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/bootstrap/kernel.py +0 -0
  80. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/cache/__init__.py +0 -0
  81. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/cache/abc/__init__.py +0 -0
  82. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/cache/abc/backend.py +0 -0
  83. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/cache/abc/config.py +0 -0
  84. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/cache/abc/dependency.py +0 -0
  85. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/cache/codec.py +0 -0
  86. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/cache/decorators.py +0 -0
  87. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/cache/dependency.py +0 -0
  88. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/cache/gateway.py +0 -0
  89. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/cache/keys.py +0 -0
  90. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/cache/repository.py +0 -0
  91. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/cache/serializer.py +0 -0
  92. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/command/__init__.py +0 -0
  93. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/command/adapter.py +0 -0
  94. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/command/base.py +0 -0
  95. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/command/field.py +0 -0
  96. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/command/introspection.py +0 -0
  97. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/compiler.py +0 -0
  98. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/config/binder.py +0 -0
  99. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/config/configurable.py +0 -0
  100. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/config/context.py +0 -0
  101. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/config/errors.py +0 -0
  102. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/config/keys.py +0 -0
  103. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/config/model.py +0 -0
  104. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/config/observability.py +0 -0
  105. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/config/resolver.py +0 -0
  106. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/contracts/__init__.py +0 -0
  107. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/contracts/manifest.py +0 -0
  108. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/di/__init__.py +0 -0
  109. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/di/container.py +0 -0
  110. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/di/scope.py +0 -0
  111. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/discovery/__init__.py +0 -0
  112. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/discovery/_utils.py +0 -0
  113. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/discovery/base.py +0 -0
  114. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/discovery/interfaces.py +0 -0
  115. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/discovery/manifest.py +0 -0
  116. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/discovery/modules.py +0 -0
  117. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/engine/__init__.py +0 -0
  118. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/engine/compilable.py +0 -0
  119. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/engine/compiler.py +0 -0
  120. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/engine/events.py +0 -0
  121. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/engine/executor.py +0 -0
  122. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/engine/metrics.py +0 -0
  123. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/engine/plan.py +0 -0
  124. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/errors/__init__.py +0 -0
  125. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/errors/codes.py +0 -0
  126. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/errors/errors.py +0 -0
  127. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/expr/__init__.py +0 -0
  128. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/expr/eval.py +0 -0
  129. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/expr/nodes.py +0 -0
  130. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/expr/refs.py +0 -0
  131. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/job/__init__.py +0 -0
  132. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/job/callback.py +0 -0
  133. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/job/context.py +0 -0
  134. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/job/handle.py +0 -0
  135. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/job/job.py +0 -0
  136. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/job/service.py +0 -0
  137. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/logger/__init__.py +0 -0
  138. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/logger/abc.py +0 -0
  139. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/logger/config.py +0 -0
  140. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/logger/registry.py +0 -0
  141. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/logger/structlogger.py +0 -0
  142. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/model/__init__.py +0 -0
  143. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/model/base.py +0 -0
  144. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/model/enums.py +0 -0
  145. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/model/field.py +0 -0
  146. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/model/introspection.py +0 -0
  147. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/model/projection.py +0 -0
  148. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/model/relation.py +0 -0
  149. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/model/struct.py +0 -0
  150. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/model/timestamped.py +0 -0
  151. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/model/types.py +0 -0
  152. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/model/types_postgres.py +0 -0
  153. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/observability/__init__.py +0 -0
  154. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/observability/config.py +0 -0
  155. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/observability/event.py +0 -0
  156. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/observability/observer/__init__.py +0 -0
  157. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/observability/observer/noop.py +0 -0
  158. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/observability/observer/otel.py +0 -0
  159. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/observability/observer/structlog.py +0 -0
  160. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/observability/protocol.py +0 -0
  161. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/observability/runtime.py +0 -0
  162. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/observability/topology.py +0 -0
  163. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/projection/__init__.py +0 -0
  164. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/projection/loaders.py +0 -0
  165. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/projection/runtime.py +0 -0
  166. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/__init__.py +0 -0
  167. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/abc/__init__.py +0 -0
  168. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/abc/query.py +0 -0
  169. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/abc/repo_for.py +0 -0
  170. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/abc/repository.py +0 -0
  171. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/mutation.py +0 -0
  172. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/registration.py +0 -0
  173. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/registry.py +0 -0
  174. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/__init__.py +0 -0
  175. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/integrity.py +0 -0
  176. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/loaders.py +0 -0
  177. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/mixins.py +0 -0
  178. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/model.py +0 -0
  179. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/profile_loader.py +0 -0
  180. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/projection.py +0 -0
  181. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/query_compiler/__init__.py +0 -0
  182. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/query_compiler/compiler.py +0 -0
  183. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/query_compiler/cursor.py +0 -0
  184. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/query_compiler/errors.py +0 -0
  185. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/query_compiler/filters.py +0 -0
  186. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/query_compiler/ordering.py +0 -0
  187. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/query_compiler/paths.py +0 -0
  188. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/query_compiler/subquery.py +0 -0
  189. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/registry.py +0 -0
  190. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/repository.py +0 -0
  191. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/session_manager.py +0 -0
  192. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/transactional.py +0 -0
  193. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/repository/sqlalchemy/uow.py +0 -0
  194. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/response/__init__.py +0 -0
  195. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/response/base.py +0 -0
  196. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/routing/__init__.py +0 -0
  197. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/routing/ref.py +0 -0
  198. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/routing/resolver.py +0 -0
  199. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/runner.py +0 -0
  200. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/schema/__init__.py +0 -0
  201. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/schema/schema_mode.py +0 -0
  202. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/tracing/__init__.py +0 -0
  203. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/tracing/context.py +0 -0
  204. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/transport/__init__.py +0 -0
  205. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/transport/adapter.py +0 -0
  206. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/uow/__init__.py +0 -0
  207. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/uow/abc.py +0 -0
  208. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/uow/context.py +0 -0
  209. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/use_case/__init__.py +0 -0
  210. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/use_case/_predicates.py +0 -0
  211. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/use_case/compute.py +0 -0
  212. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/use_case/constants.py +0 -0
  213. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/use_case/factory.py +0 -0
  214. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/use_case/field_ref.py +0 -0
  215. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/use_case/invoker.py +0 -0
  216. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/use_case/keys.py +0 -0
  217. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/use_case/markers.py +0 -0
  218. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/use_case/registry.py +0 -0
  219. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/use_case/rule.py +0 -0
  220. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/core/use_case/use_case.py +0 -0
  221. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/__init__.py +0 -0
  222. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/__init__.py +0 -0
  223. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/_format_registry.py +0 -0
  224. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/_historify/__init__.py +0 -0
  225. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/_historify/_common.py +0 -0
  226. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/_historify/_log.py +0 -0
  227. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/_historify/_ops.py +0 -0
  228. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/_historify/_snapshot.py +0 -0
  229. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/_historify/_transform.py +0 -0
  230. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/_merge.py +0 -0
  231. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/_predicate.py +0 -0
  232. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/_schema_aligner/__init__.py +0 -0
  233. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/_schema_aligner/_aligner.py +0 -0
  234. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/_schema_aligner/_policy.py +0 -0
  235. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/_write_policy.py +0 -0
  236. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/polars/__init__.py +0 -0
  237. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/polars/_dtype.py +0 -0
  238. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/polars/_file_writer.py +0 -0
  239. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/polars/_historify.py +0 -0
  240. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/polars/_predicate.py +0 -0
  241. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/polars/_reader.py +0 -0
  242. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/polars/_schema.py +0 -0
  243. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/polars/_schema_aligner.py +0 -0
  244. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/polars/_writer.py +0 -0
  245. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/polars/provider.py +0 -0
  246. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/spark/__init__.py +0 -0
  247. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/spark/_dtype.py +0 -0
  248. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/spark/_historify.py +0 -0
  249. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/spark/_reader.py +0 -0
  250. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/spark/_schema.py +0 -0
  251. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/spark/_schema_aligner.py +0 -0
  252. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/spark/_writer.py +0 -0
  253. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/backends/spark/provider.py +0 -0
  254. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/checkpoint/__init__.py +0 -0
  255. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/checkpoint/_backends/_polars.py +0 -0
  256. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/checkpoint/_backends/_spark.py +0 -0
  257. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/checkpoint/_cleaners.py +0 -0
  258. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/checkpoint/_paths.py +0 -0
  259. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/checkpoint/_scope.py +0 -0
  260. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/checkpoint/_store.py +0 -0
  261. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/compiler/__init__.py +0 -0
  262. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/compiler/_binding.py +0 -0
  263. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/compiler/_compiler.py +0 -0
  264. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/compiler/_errors.py +0 -0
  265. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/compiler/_plan.py +0 -0
  266. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/compiler/_validators.py +0 -0
  267. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/compiler/_validators_plan.py +0 -0
  268. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/compiler/_validators_step.py +0 -0
  269. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/__init__.py +0 -0
  270. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/_format.py +0 -0
  271. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/_read_options.py +0 -0
  272. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/_utils.py +0 -0
  273. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/_write_options.py +0 -0
  274. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/expr/__init__.py +0 -0
  275. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/expr/_params.py +0 -0
  276. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/expr/_predicate.py +0 -0
  277. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/expr/_predicate_dialect.py +0 -0
  278. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/expr/_refs.py +0 -0
  279. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/source/__init__.py +0 -0
  280. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/source/_from.py +0 -0
  281. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/source/_from_clickhouse.py +0 -0
  282. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/source/_from_mongo.py +0 -0
  283. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/source/_specs.py +0 -0
  284. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/target/__init__.py +0 -0
  285. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/target/_file.py +0 -0
  286. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/target/_history/__init__.py +0 -0
  287. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/target/_history/_builder.py +0 -0
  288. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/target/_history/_enums.py +0 -0
  289. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/target/_history/_errors.py +0 -0
  290. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/target/_history/_report.py +0 -0
  291. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/target/_history/_spec.py +0 -0
  292. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/target/_into.py +0 -0
  293. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/target/_schema_mode.py +0 -0
  294. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/target/_table.py +0 -0
  295. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/declarative/target/_temp.py +0 -0
  296. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/executor/__init__.py +0 -0
  297. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/executor/_dispatcher.py +0 -0
  298. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/executor/_executor.py +0 -0
  299. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/io/__init__.py +0 -0
  300. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/io/_registry.py +0 -0
  301. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/io/sources/__init__.py +0 -0
  302. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/io/sources/_clickhouse.py +0 -0
  303. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/io/sources/_mongo.py +0 -0
  304. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/io/sources/_mongo_batch.py +0 -0
  305. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/io/sources/_mongo_bson.py +0 -0
  306. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/io/sources/_mongo_predicate.py +0 -0
  307. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/io/targets/__init__.py +0 -0
  308. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/io/targets/_clickhouse.py +0 -0
  309. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/lineage/__init__.py +0 -0
  310. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/lineage/_config.py +0 -0
  311. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/lineage/_observer.py +0 -0
  312. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/lineage/_records.py +0 -0
  313. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/lineage/sinks/__init__.py +0 -0
  314. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/lineage/sinks/_protocol.py +0 -0
  315. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/lineage/sinks/_table.py +0 -0
  316. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/lineage/sinks/_writer.py +0 -0
  317. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/pipeline/__init__.py +0 -0
  318. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/pipeline/_generics.py +0 -0
  319. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/pipeline/_params.py +0 -0
  320. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/pipeline/_pipeline.py +0 -0
  321. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/pipeline/_process.py +0 -0
  322. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/pipeline/_sql.py +0 -0
  323. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/pipeline/_step.py +0 -0
  324. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/pipeline/_step_sql.py +0 -0
  325. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/runner/__init__.py +0 -0
  326. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/runner/_providers.py +0 -0
  327. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/runner/_wiring.py +0 -0
  328. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/runner/config_loader.py +0 -0
  329. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/runner/core.py +0 -0
  330. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/runner/errors.py +0 -0
  331. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/runner/filtering.py +0 -0
  332. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/runtime/__init__.py +0 -0
  333. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/runtime/contracts.py +0 -0
  334. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/schema/__init__.py +0 -0
  335. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/schema/_contract.py +0 -0
  336. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/schema/_schema.py +0 -0
  337. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/storage/__init__.py +0 -0
  338. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/storage/_config.py +0 -0
  339. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/storage/_file_locator.py +0 -0
  340. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/storage/_locator.py +0 -0
  341. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/storage/routing.py +0 -0
  342. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/testing/__init__.py +0 -0
  343. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/testing/_result.py +0 -0
  344. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/testing/_runners.py +0 -0
  345. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/testing/_scenario.py +0 -0
  346. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/testing/_stubs.py +0 -0
  347. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/etl/testing/spark.py +0 -0
  348. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/prometheus/__init__.py +0 -0
  349. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/prometheus/adapter.py +0 -0
  350. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/prometheus/kafka.py +0 -0
  351. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/prometheus/lifecycle.py +0 -0
  352. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/prometheus/middleware.py +0 -0
  353. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/py.typed +0 -0
  354. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/rest/__init__.py +0 -0
  355. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/rest/adapter.py +0 -0
  356. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/rest/autocrud.py +0 -0
  357. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/rest/compiler.py +0 -0
  358. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/rest/constants.py +0 -0
  359. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/rest/errors.py +0 -0
  360. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/rest/fastapi/__init__.py +0 -0
  361. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/rest/fastapi/app.py +0 -0
  362. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/rest/fastapi/auto.py +0 -0
  363. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/rest/fastapi/openapi.py +0 -0
  364. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/rest/fastapi/response.py +0 -0
  365. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/rest/fastapi/router_runtime.py +0 -0
  366. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/rest/middleware.py +0 -0
  367. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/rest/model.py +0 -0
  368. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/rest/rest_adapter.py +0 -0
  369. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/__init__.py +0 -0
  370. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/__init__.py +0 -0
  371. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/_adapter.py +0 -0
  372. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/_commit_tracker.py +0 -0
  373. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/_dlq.py +0 -0
  374. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/_error_boundary.py +0 -0
  375. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/_operators.py +0 -0
  376. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/_resource_manager.py +0 -0
  377. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/_runtime_io.py +0 -0
  378. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/_sink_registry.py +0 -0
  379. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/handlers/__init__.py +0 -0
  380. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/handlers/_shared.py +0 -0
  381. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/handlers/boundary.py +0 -0
  382. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/handlers/dispatcher.py +0 -0
  383. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/handlers/routing.py +0 -0
  384. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/handlers/scopes.py +0 -0
  385. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/handlers/shapes.py +0 -0
  386. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/handlers/steps.py +0 -0
  387. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/handlers/storage.py +0 -0
  388. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/bytewax/runner.py +0 -0
  389. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/compiler/__init__.py +0 -0
  390. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/compiler/_bindings.py +0 -0
  391. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/compiler/_compiler.py +0 -0
  392. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/compiler/_plan.py +0 -0
  393. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/compiler/phases/build_plan.py +0 -0
  394. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/compiler/phases/validate.py +0 -0
  395. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/core/__init__.py +0 -0
  396. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/core/_errors.py +0 -0
  397. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/core/_exceptions.py +0 -0
  398. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/core/_message.py +0 -0
  399. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/core/_typing.py +0 -0
  400. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/graph/__init__.py +0 -0
  401. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/graph/_flow.py +0 -0
  402. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/kafka/__init__.py +0 -0
  403. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/kafka/_codec.py +0 -0
  404. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/kafka/_config.py +0 -0
  405. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/kafka/_errors.py +0 -0
  406. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/kafka/_key_resolver.py +0 -0
  407. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/kafka/_message.py +0 -0
  408. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/kafka/_record.py +0 -0
  409. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/kafka/_wire.py +0 -0
  410. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/kafka/client/__init__.py +0 -0
  411. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/kafka/client/_consumer.py +0 -0
  412. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/kafka/client/_producer.py +0 -0
  413. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/kafka/client/_protocol.py +0 -0
  414. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/kafka/message/__init__.py +0 -0
  415. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/kafka/message/_consumer.py +0 -0
  416. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/kafka/message/_producer.py +0 -0
  417. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/kafka/message/_protocol.py +0 -0
  418. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/mongo/__init__.py +0 -0
  419. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/mongo/_bytewax_source.py +0 -0
  420. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/mongo/_config.py +0 -0
  421. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/mongo/_event.py +0 -0
  422. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/mongo/_normalize.py +0 -0
  423. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/__init__.py +0 -0
  424. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/_boundary.py +0 -0
  425. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/_broadcast.py +0 -0
  426. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/_capabilities.py +0 -0
  427. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/_decompose.py +0 -0
  428. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/_expand_routes.py +0 -0
  429. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/_expr_eval.py +0 -0
  430. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/_fork.py +0 -0
  431. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/_helpers.py +0 -0
  432. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/_mongo.py +0 -0
  433. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/_protocols.py +0 -0
  434. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/_router.py +0 -0
  435. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/_shape.py +0 -0
  436. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/_sink.py +0 -0
  437. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/_step.py +0 -0
  438. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/_table/__init__.py +0 -0
  439. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/_table/common.py +0 -0
  440. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/_table/config.py +0 -0
  441. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/_with.py +0 -0
  442. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/nodes/refs.py +0 -0
  443. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/streaming/testing.py +0 -0
  444. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/testing/__init__.py +0 -0
  445. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/testing/golden.py +0 -0
  446. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/testing/http_harness.py +0 -0
  447. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/testing/in_memory.py +0 -0
  448. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/testing/repository_harness.py +0 -0
  449. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/src/loom/testing/runner.py +0 -0
  450. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/__init__.py +0 -0
  451. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/conftest.py +0 -0
  452. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/golden/__init__.py +0 -0
  453. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/golden/baselines/.gitkeep +0 -0
  454. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/golden/outputs/.gitkeep +0 -0
  455. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/golden/plans/.gitkeep +0 -0
  456. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/helpers/__init__.py +0 -0
  457. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/__init__.py +0 -0
  458. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/celery_bootstrap/__init__.py +0 -0
  459. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/celery_bootstrap/config/conf.celery.integration.yaml +0 -0
  460. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/celery_bootstrap/test_auto_create_app_integration.py +0 -0
  461. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/celery_bootstrap/test_bootstrap_worker.py +0 -0
  462. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/conftest.py +0 -0
  463. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/core/__init__.py +0 -0
  464. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/core/bootstrap/__init__.py +0 -0
  465. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/core/bootstrap/test_bootstrap_integration.py +0 -0
  466. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/core/repository/__init__.py +0 -0
  467. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/core/repository/sqlalchemy/__init__.py +0 -0
  468. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/core/repository/sqlalchemy/conftest.py +0 -0
  469. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/core/repository/sqlalchemy/test_cache_integration.py +0 -0
  470. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/core/repository/sqlalchemy/test_repository_integration.py +0 -0
  471. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/core/rest/__init__.py +0 -0
  472. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/core/rest/test_auto_interface_integration.py +0 -0
  473. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/core/rest/test_fastapi_app_integration.py +0 -0
  474. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/core/rest/test_rest_error_mapping.py +0 -0
  475. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/core/rest/test_rest_observability.py +0 -0
  476. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/core/use_case/__init__.py +0 -0
  477. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/core/use_case/test_custom_repository_integration.py +0 -0
  478. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/core/use_case/test_use_case_crud_integration.py +0 -0
  479. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/etl/__init__.py +0 -0
  480. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/etl/test_runner_integration.py +0 -0
  481. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/__init__.py +0 -0
  482. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/config/__init__.py +0 -0
  483. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/config/conf.interfaces.yaml +0 -0
  484. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/config/conf.manifest.yaml +0 -0
  485. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/config/conf.modules.yaml +0 -0
  486. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/config/conf.yaml +0 -0
  487. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/main.py +0 -0
  488. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/manifest.py +0 -0
  489. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/product/__init__.py +0 -0
  490. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/product/category/__init__.py +0 -0
  491. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/product/category/model.py +0 -0
  492. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/product/category/schemas.py +0 -0
  493. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/product/interface.py +0 -0
  494. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/product/jobs.py +0 -0
  495. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/product/model.py +0 -0
  496. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/product/relations.py +0 -0
  497. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/product/repository.py +0 -0
  498. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/product/repository_contract.py +0 -0
  499. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/product/review/__init__.py +0 -0
  500. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/product/review/model.py +0 -0
  501. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/product/review/schemas.py +0 -0
  502. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/product/schemas.py +0 -0
  503. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/fake_repo/product/use_cases.py +0 -0
  504. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/streaming/__init__.py +0 -0
  505. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/streaming/test_into_table_integration.py +0 -0
  506. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/support/__init__.py +0 -0
  507. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/integration/support/logical_repo_fixtures.py +0 -0
  508. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/__init__.py +0 -0
  509. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/celery_bootstrap/__init__.py +0 -0
  510. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/celery_bootstrap/test_async_runtime.py +0 -0
  511. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/celery_bootstrap/test_bootstrap.py +0 -0
  512. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/celery_jobs/__init__.py +0 -0
  513. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/celery_jobs/test_auto.py +0 -0
  514. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/celery_jobs/test_celery_service.py +0 -0
  515. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/celery_jobs/test_config.py +0 -0
  516. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/celery_jobs/test_runner.py +0 -0
  517. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/__init__.py +0 -0
  518. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/backend/__init__.py +0 -0
  519. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/backend/test_backend_compiler.py +0 -0
  520. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/bootstrap/__init__.py +0 -0
  521. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/bootstrap/test_bootstrap.py +0 -0
  522. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/bootstrap/test_bootstrap_metrics.py +0 -0
  523. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/bootstrap/test_kernel.py +0 -0
  524. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/cache/__init__.py +0 -0
  525. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/cache/test_cached_repository.py +0 -0
  526. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/command/__init__.py +0 -0
  527. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/command/test_command_base.py +0 -0
  528. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/command/test_command_field.py +0 -0
  529. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/command/test_command_patch.py +0 -0
  530. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/command/test_introspection.py +0 -0
  531. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/config/__init__.py +0 -0
  532. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/config/test_binder.py +0 -0
  533. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/config/test_config.py +0 -0
  534. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/config/test_configurable.py +0 -0
  535. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/config/test_context.py +0 -0
  536. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/di/__init__.py +0 -0
  537. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/di/test_container.py +0 -0
  538. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/discovery/__init__.py +0 -0
  539. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/discovery/test_manifest.py +0 -0
  540. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/engine/__init__.py +0 -0
  541. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/engine/test_compiler.py +0 -0
  542. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/engine/test_executor.py +0 -0
  543. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/engine/test_executor_trace.py +0 -0
  544. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/engine/test_executor_uow.py +0 -0
  545. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/engine/test_metrics.py +0 -0
  546. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/engine/test_plan.py +0 -0
  547. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/errors/__init__.py +0 -0
  548. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/errors/test_errors.py +0 -0
  549. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/expr/__init__.py +0 -0
  550. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/expr/test_expr.py +0 -0
  551. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/job/__init__.py +0 -0
  552. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/job/conftest.py +0 -0
  553. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/job/test_callback.py +0 -0
  554. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/job/test_context.py +0 -0
  555. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/job/test_handle.py +0 -0
  556. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/job/test_inline_service.py +0 -0
  557. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/job/test_job.py +0 -0
  558. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/logger/__init__.py +0 -0
  559. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/logger/test_config.py +0 -0
  560. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/logger/test_registry.py +0 -0
  561. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/model/__init__.py +0 -0
  562. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/model/test_model.py +0 -0
  563. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/model/test_struct.py +0 -0
  564. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/model/test_timestamped.py +0 -0
  565. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/observability/__init__.py +0 -0
  566. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/observability/test_observers.py +0 -0
  567. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/observability/test_runtime.py +0 -0
  568. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/projection/__init__.py +0 -0
  569. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/projection/test_runtime.py +0 -0
  570. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/repository/__init__.py +0 -0
  571. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/repository/abc/__init__.py +0 -0
  572. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/repository/abc/conftest.py +0 -0
  573. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/repository/abc/test_query.py +0 -0
  574. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/repository/abc/test_repository_contract.py +0 -0
  575. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/repository/sqlalchemy/__init__.py +0 -0
  576. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/repository/sqlalchemy/conftest.py +0 -0
  577. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/repository/sqlalchemy/test_loaders.py +0 -0
  578. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/repository/sqlalchemy/test_repository.py +0 -0
  579. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/repository/sqlalchemy/test_transactional.py +0 -0
  580. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/routing/__init__.py +0 -0
  581. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/routing/test_routing.py +0 -0
  582. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/test_async_bridge.py +0 -0
  583. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/test_compiler_contracts.py +0 -0
  584. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/test_runner_contracts.py +0 -0
  585. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/tracing/__init__.py +0 -0
  586. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/tracing/test_context.py +0 -0
  587. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/uow/__init__.py +0 -0
  588. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/uow/test_executor_uow.py +0 -0
  589. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/uow/test_sqlalchemy_uow.py +0 -0
  590. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/uow/test_uow_protocols.py +0 -0
  591. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/use_case/__init__.py +0 -0
  592. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/use_case/test_compute.py +0 -0
  593. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/use_case/test_factory.py +0 -0
  594. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/use_case/test_field_ref.py +0 -0
  595. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/use_case/test_invoker.py +0 -0
  596. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/use_case/test_markers.py +0 -0
  597. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/use_case/test_rule.py +0 -0
  598. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/core/use_case/test_use_case.py +0 -0
  599. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/__init__.py +0 -0
  600. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/__init__.py +0 -0
  601. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/_historify_contract.py +0 -0
  602. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_historify_common.py +0 -0
  603. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_polars/__init__.py +0 -0
  604. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_polars/conftest.py +0 -0
  605. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_polars/test_apply_schema.py +0 -0
  606. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_polars/test_backend.py +0 -0
  607. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_polars/test_dtype.py +0 -0
  608. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_polars/test_file_writer.py +0 -0
  609. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_polars/test_historify_polars.py +0 -0
  610. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_polars/test_predicate_pushdown.py +0 -0
  611. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_polars/test_reader_columns.py +0 -0
  612. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_polars/test_reader_json_columns.py +0 -0
  613. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_polars/test_step_execution.py +0 -0
  614. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_polars/test_upsert_writer.py +0 -0
  615. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_polars/test_writer_null_schema.py +0 -0
  616. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_polars/test_writer_to_frame.py +0 -0
  617. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_spark/__init__.py +0 -0
  618. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_spark/conftest.py +0 -0
  619. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_spark/test_dtype.py +0 -0
  620. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_spark/test_historify_spark.py +0 -0
  621. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_spark/test_spark_apply_schema.py +0 -0
  622. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_spark/test_step_execution.py +0 -0
  623. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_spark/test_writer_to_frame.py +0 -0
  624. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/backends/test_write_policy_historify.py +0 -0
  625. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/checkpoint/__init__.py +0 -0
  626. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/checkpoint/backends/__init__.py +0 -0
  627. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/checkpoint/backends/test_checkpoint_polars.py +0 -0
  628. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/checkpoint/test_checkpoint_paths.py +0 -0
  629. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/checkpoint/test_cleaners.py +0 -0
  630. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/checkpoint/test_store.py +0 -0
  631. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/compiler/__init__.py +0 -0
  632. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/compiler/test_catalog_validator.py +0 -0
  633. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/compiler/test_compiler.py +0 -0
  634. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/compiler/test_compiler_catalog.py +0 -0
  635. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/compiler/test_compiler_upsert.py +0 -0
  636. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/compiler/test_errors.py +0 -0
  637. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/compiler/test_errors_additional_factories.py +0 -0
  638. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/compiler/test_errors_runtime_factories.py +0 -0
  639. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/compiler/test_historify_validator.py +0 -0
  640. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/compiler/test_param_exprs_validator.py +0 -0
  641. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/compiler/test_plan_traversal.py +0 -0
  642. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/compiler/test_step_validator.py +0 -0
  643. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/compiler/test_structural.py +0 -0
  644. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/compiler/test_temp_validator.py +0 -0
  645. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/compiler/test_upsert_validator.py +0 -0
  646. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/conftest.py +0 -0
  647. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/io/__init__.py +0 -0
  648. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/io/sources/__init__.py +0 -0
  649. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/io/sources/test_clickhouse_reader.py +0 -0
  650. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/io/sources/test_from_clickhouse.py +0 -0
  651. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/io/sources/test_from_mongo.py +0 -0
  652. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/io/sources/test_mongo_predicate.py +0 -0
  653. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/io/sources/test_mongo_reader.py +0 -0
  654. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/io/targets/__init__.py +0 -0
  655. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/io/targets/test_clickhouse_writer.py +0 -0
  656. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/io/targets/test_into_clickhouse.py +0 -0
  657. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/io/test_history_target.py +0 -0
  658. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/io/test_registry.py +0 -0
  659. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/io/test_source.py +0 -0
  660. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/io/test_source_json.py +0 -0
  661. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/io/test_source_options.py +0 -0
  662. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/io/test_target.py +0 -0
  663. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/io/test_utils.py +0 -0
  664. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/io/test_variants.py +0 -0
  665. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/lineage/test_observer.py +0 -0
  666. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/lineage/test_records.py +0 -0
  667. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/lineage/test_store.py +0 -0
  668. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/pipeline/__init__.py +0 -0
  669. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/pipeline/test_pipeline_process.py +0 -0
  670. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/pipeline/test_proxy.py +0 -0
  671. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/pipeline/test_step.py +0 -0
  672. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/schema/__init__.py +0 -0
  673. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/schema/test_contract.py +0 -0
  674. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/schema/test_schema.py +0 -0
  675. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/schema/test_table.py +0 -0
  676. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/sql/__init__.py +0 -0
  677. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/sql/test_merge.py +0 -0
  678. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/sql/test_predicate.py +0 -0
  679. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/sql/test_predicate_dialect.py +0 -0
  680. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/sql/test_sql_runtime.py +0 -0
  681. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/storage/__init__.py +0 -0
  682. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/storage/test_backend_factory.py +0 -0
  683. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/storage/test_io_protocols.py +0 -0
  684. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/storage/test_locator.py +0 -0
  685. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/storage/test_observability_and_protocols.py +0 -0
  686. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/storage/test_route_build.py +0 -0
  687. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/storage/test_schema_readers.py +0 -0
  688. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/storage/test_storage_config.py +0 -0
  689. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/test_config_loader.py +0 -0
  690. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/test_executor.py +0 -0
  691. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/test_format_registry.py +0 -0
  692. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/test_module_contracts.py +0 -0
  693. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/test_public_api_discovery.py +0 -0
  694. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/test_record_schema_coverage.py +0 -0
  695. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/test_runner.py +0 -0
  696. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/test_runner_errors.py +0 -0
  697. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/test_spark_testing.py +0 -0
  698. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/testing/__init__.py +0 -0
  699. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/testing/test_runners.py +0 -0
  700. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/testing/test_scenario_and_stubs.py +0 -0
  701. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/etl/testing/test_spark_helpers.py +0 -0
  702. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/prometheus/__init__.py +0 -0
  703. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/prometheus/test_adapter.py +0 -0
  704. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/prometheus/test_middleware.py +0 -0
  705. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/rest/__init__.py +0 -0
  706. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/rest/test_autocrud.py +0 -0
  707. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/rest/test_fastapi_auto_logger.py +0 -0
  708. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/rest/test_middleware.py +0 -0
  709. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/rest/test_pydantic_adapter.py +0 -0
  710. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/rest/test_response.py +0 -0
  711. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/rest/test_rest_adapter.py +0 -0
  712. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/rest/test_rest_compiler.py +0 -0
  713. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/rest/test_rest_model.py +0 -0
  714. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/rest/test_router_runtime.py +0 -0
  715. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/__init__.py +0 -0
  716. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/bytewax/__init__.py +0 -0
  717. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/bytewax/cases.py +0 -0
  718. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/bytewax/conftest.py +0 -0
  719. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/bytewax/test_adapter.py +0 -0
  720. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/bytewax/test_batch_key.py +0 -0
  721. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/bytewax/test_bytewax_dispatcher.py +0 -0
  722. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/bytewax/test_collect_batch.py +0 -0
  723. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/bytewax/test_dlq.py +0 -0
  724. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/bytewax/test_error_boundary.py +0 -0
  725. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/bytewax/test_operators.py +0 -0
  726. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/bytewax/test_resource_manager.py +0 -0
  727. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/bytewax/test_runner.py +0 -0
  728. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/bytewax/test_runtime_io.py +0 -0
  729. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/bytewax/test_runtime_sink.py +0 -0
  730. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/bytewax/test_runtime_source.py +0 -0
  731. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/bytewax/test_sink_registry.py +0 -0
  732. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/bytewax/test_steps.py +0 -0
  733. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/bytewax/test_storage.py +0 -0
  734. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/compiler/__init__.py +0 -0
  735. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/compiler/cases.py +0 -0
  736. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/compiler/test_async_walk.py +0 -0
  737. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/compiler/test_basics.py +0 -0
  738. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/compiler/test_config_bindings.py +0 -0
  739. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/compiler/test_mongo_source.py +0 -0
  740. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/compiler/test_multi_source.py +0 -0
  741. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/compiler/test_router.py +0 -0
  742. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/compiler/test_window.py +0 -0
  743. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/compiler/test_with.py +0 -0
  744. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/conftest.py +0 -0
  745. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/contracts/__init__.py +0 -0
  746. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/contracts/cases.py +0 -0
  747. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/contracts/test_boundary.py +0 -0
  748. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/contracts/test_message.py +0 -0
  749. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/contracts/test_mongo_contracts.py +0 -0
  750. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/contracts/test_multi_boundary.py +0 -0
  751. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/contracts/test_steps.py +0 -0
  752. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/flows/__init__.py +0 -0
  753. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/flows/cases/__init__.py +0 -0
  754. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/flows/cases/batch.py +0 -0
  755. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/flows/cases/explode.py +0 -0
  756. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/flows/cases/fork.py +0 -0
  757. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/flows/cases/router.py +0 -0
  758. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/flows/cases/shared.py +0 -0
  759. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/flows/cases/simple.py +0 -0
  760. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/flows/conftest.py +0 -0
  761. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/flows/test_compiler_examples.py +0 -0
  762. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/flows/test_flow_examples.py +0 -0
  763. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/kafka/__init__.py +0 -0
  764. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/kafka/cases.py +0 -0
  765. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/kafka/conftest.py +0 -0
  766. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/kafka/fakes.py +0 -0
  767. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/kafka/test_client.py +0 -0
  768. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/kafka/test_config.py +0 -0
  769. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/kafka/test_key_resolver.py +0 -0
  770. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/kafka/test_message.py +0 -0
  771. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/kafka/test_message_client.py +0 -0
  772. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/kafka/test_multi_wire.py +0 -0
  773. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/kafka/test_observability.py +0 -0
  774. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/kafka/test_settings.py +0 -0
  775. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/kafka/test_wire.py +0 -0
  776. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/mongo/test_bytewax_source.py +0 -0
  777. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/nodes/__init__.py +0 -0
  778. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/nodes/conftest.py +0 -0
  779. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/nodes/test_broadcast.py +0 -0
  780. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/nodes/test_delta_config.py +0 -0
  781. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/nodes/test_logging.py +0 -0
  782. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/nodes/test_table_package.py +0 -0
  783. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/observability/__init__.py +0 -0
  784. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/observability/cases.py +0 -0
  785. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/observability/conftest.py +0 -0
  786. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/observability/test_observability_runner.py +0 -0
  787. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/observability/test_protocols.py +0 -0
  788. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/observability/test_registry.py +0 -0
  789. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/observability/test_structlog.py +0 -0
  790. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/support/__init__.py +0 -0
  791. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/support/flow_cases.py +0 -0
  792. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/test_expand_routes.py +0 -0
  793. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/test_fork.py +0 -0
  794. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/test_otel_observability.py +0 -0
  795. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/test_routing.py +0 -0
  796. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/test_testing_mongo.py +0 -0
  797. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/streaming/test_with.py +0 -0
  798. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/testing/__init__.py +0 -0
  799. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/testing/test_golden.py +0 -0
  800. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/testing/test_http_harness.py +0 -0
  801. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/testing/test_in_memory.py +0 -0
  802. {loom_kernel-0.9.1 → loom_kernel-0.9.2}/tests/unit/testing/test_runner.py +0 -0
@@ -1,3 +1,20 @@
1
+ # 🚀 Release 0.9.2 ([#39](https://github.com/the-reacher-data/loom-py/pull/39)) ([`f1a482d`](https://github.com/the-reacher-data/loom-py/commit/f1a482d03f8b83f8e0c7725e7af6160466ac6126))
2
+
3
+
4
+ ## ✨ Features
5
+ ### config
6
+ - **config:** add SecretsManagerResolver + shared resolver utilities
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
1
18
  # 🚀 Release 0.9.1 ([#36](https://github.com/the-reacher-data/loom-py/pull/36)) ([`5c420c9`](https://github.com/the-reacher-data/loom-py/commit/5c420c9dd4efe0f697affb8a921054bc6504358f))
2
19
 
3
20
 
@@ -0,0 +1,15 @@
1
+ # 🚀 Release 0.9.2 ([#39](https://github.com/the-reacher-data/loom-py/pull/39)) ([`f1a482d`](https://github.com/the-reacher-data/loom-py/commit/f1a482d03f8b83f8e0c7725e7af6160466ac6126))
2
+
3
+
4
+ ## ✨ Features
5
+ ### config
6
+ - **config:** add SecretsManagerResolver + shared resolver utilities
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: loom-kernel
3
- Version: 0.9.1
3
+ Version: 0.9.2
4
4
  Summary: Loom Python project
5
5
  License-File: LICENSE
6
6
  Classifier: Typing :: Typed
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "loom-kernel"
3
- version = "0.9.1"
3
+ version = "0.9.2"
4
4
  description = "Loom Python project"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -247,7 +247,7 @@ markers = [
247
247
 
248
248
  [tool.commitizen]
249
249
  name = "cz_conventional_commits"
250
- version = "0.9.1"
250
+ version = "0.9.2"
251
251
  tag_format = "v$version"
252
252
  version_files = [
253
253
  "pyproject.toml:project.version",
@@ -20,6 +20,7 @@ from loom.core.config.keys import ConfigKey
20
20
  from loom.core.config.loader import load_config, section
21
21
  from loom.core.config.observability import OtelConfig
22
22
  from loom.core.config.resolver import ConfigResolver
23
+ from loom.core.config.secrets import SecretsManagerResolver
23
24
  from loom.core.config.ssm import SsmResolver
24
25
 
25
26
  __all__ = [
@@ -30,6 +31,7 @@ __all__ = [
30
31
  "ConfigResolver",
31
32
  "Configurable",
32
33
  "OtelConfig",
34
+ "SecretsManagerResolver",
33
35
  "SsmResolver",
34
36
  "StructBinder",
35
37
  "load_config",
@@ -0,0 +1,116 @@
1
+ """Shared utilities for config resolvers (SSM, Secrets Manager, etc.)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import os
7
+ import re
8
+
9
+ from loom.core.config.errors import ConfigError
10
+
11
+ _ENV_VAR_PATTERN = re.compile(r"%([A-Z][A-Z0-9_]*)%")
12
+
13
+
14
+ def _expand_env_vars(key: str) -> str:
15
+ """Expand ``%VAR_NAME%`` placeholders in *key* using environment variables.
16
+
17
+ Only uppercase identifiers matching ``[A-Z][A-Z0-9_]*`` are expanded.
18
+ The ``%VAR%`` syntax avoids conflicts with OmegaConf's ANTLR grammar,
19
+ which rejects bare ``{`` inside ``${resolver:...}`` interpolations.
20
+
21
+ Args:
22
+ key: Resolver path, possibly containing ``%VAR_NAME%`` tokens.
23
+
24
+ Returns:
25
+ Path with all tokens replaced by their environment variable values.
26
+
27
+ Raises:
28
+ ConfigError: When a referenced variable is absent from the environment.
29
+ """
30
+ if not _ENV_VAR_PATTERN.search(key):
31
+ return key
32
+
33
+ def _replace(match: re.Match[str]) -> str:
34
+ var_name = match.group(1)
35
+ value = os.environ.get(var_name)
36
+ if value is None:
37
+ raise ConfigError(
38
+ f"Env var {var_name!r} not found in environment "
39
+ f"(referenced in resolver path {key!r})"
40
+ )
41
+ return value
42
+
43
+ return _ENV_VAR_PATTERN.sub(_replace, key)
44
+
45
+
46
+ def _split_resolver_key(key: str) -> tuple[str, list[str]]:
47
+ """Split a resolver key into the base path and JSON navigation keys.
48
+
49
+ The first dot after the last '/' separator marks the start of a JSON key
50
+ path. Both SSM and Secrets Manager use '/' as path separator, so a dot
51
+ is unambiguously a JSON navigation token.
52
+
53
+ Note: ARN-style SecretIds (``arn:aws:secretsmanager:...``) are not
54
+ supported for dot-notation — use short names instead.
55
+
56
+ **Limitation — env-var values with dots in the final path segment:**
57
+ If a ``%VAR%`` token expands to a value that contains a dot *and* that
58
+ token appears in the last path segment (after the final ``/``), the dot
59
+ will be interpreted as a JSON navigation separator, producing a confusing
60
+ ``ConfigError``. Example: ``/app/svc/%ENV%`` where ``ENV=db.prod`` becomes
61
+ ``/app/svc/db`` with JSON key ``["prod"]``. Use env-var tokens only in
62
+ path segments that are guaranteed to be dot-free (environment names,
63
+ region codes, etc.).
64
+
65
+ Args:
66
+ key: Expanded resolver key, e.g. ``"/app/prod/db_config.host"``.
67
+
68
+ Returns:
69
+ A 2-tuple ``(base_path, json_keys)`` where *base_path* is the path
70
+ to fetch and *json_keys* is a list of dict keys to navigate
71
+ (empty list when no dot-notation is present).
72
+ """
73
+ if not key:
74
+ return key, []
75
+ last_slash = key.rfind("/")
76
+ after_last_slash = key[last_slash + 1 :] if last_slash != -1 else key
77
+ dot_pos = after_last_slash.find(".")
78
+ if dot_pos == -1:
79
+ return key, []
80
+ base_end = (last_slash + 1 + dot_pos) if last_slash != -1 else dot_pos
81
+ json_tail = key[base_end + 1 :]
82
+ return key[:base_end], [k for k in json_tail.split(".") if k]
83
+
84
+
85
+ def _navigate_json(raw: str, keys: list[str], path: str) -> object:
86
+ """Parse *raw* as JSON and navigate to the value at *keys*.
87
+
88
+ Args:
89
+ raw: Raw string value from the resolver backend.
90
+ keys: Ordered list of dict keys to traverse.
91
+ path: Original path, used only in error messages.
92
+
93
+ Returns:
94
+ The value at the navigated position. May be any JSON-compatible type.
95
+
96
+ Raises:
97
+ ConfigError: When *raw* is not valid JSON, or a key is absent.
98
+ """
99
+ try:
100
+ data: object = json.loads(raw)
101
+ except json.JSONDecodeError as exc:
102
+ # Suppress chain (from None) — JSONDecodeError.doc holds the raw secret
103
+ # and would be exposed via __cause__ in tracebacks / APM serialisation.
104
+ raise ConfigError(
105
+ f"Resolver path {path!r} value is not valid JSON "
106
+ f"(required for key navigation): {exc.msg} at position {exc.pos}"
107
+ ) from None
108
+ current: object = data
109
+ for k in keys:
110
+ if not isinstance(current, dict) or k not in current:
111
+ raise ConfigError(f"Key {k!r} not found at resolver path {path!r}")
112
+ current = current[k]
113
+ return current
114
+
115
+
116
+ __all__ = ["_expand_env_vars", "_split_resolver_key", "_navigate_json"]
@@ -212,7 +212,7 @@ def _register_resolvers(resolvers: Sequence[Any], omega_conf: Any) -> None:
212
212
  """
213
213
  for resolver in resolvers:
214
214
  with contextlib.suppress(Exception):
215
- omega_conf.register_new_resolver(resolver.name, resolver.resolve)
215
+ omega_conf.register_new_resolver(resolver.name, resolver.resolve, use_cache=True)
216
216
 
217
217
 
218
218
  def load_config(
@@ -0,0 +1,144 @@
1
+ """AWS Secrets Manager resolver for loom configuration.
2
+
3
+ Resolves ``${secrets:/path/to/secret}`` placeholders in OmegaConf configs
4
+ by fetching values from AWS Secrets Manager at parse time.
5
+
6
+ Example::
7
+
8
+ from loom.core.config import load_config
9
+ from loom.core.config.secrets import SecretsManagerResolver
10
+
11
+ cfg = load_config("config/prod.yaml", resolvers=[SecretsManagerResolver("eu-west-1")])
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import logging
17
+ from typing import Any
18
+
19
+ try:
20
+ import boto3 as _boto3_module # type: ignore[import-untyped]
21
+ except ImportError:
22
+ _boto3_module = None
23
+
24
+ from loom.core.config._resolver_utils import (
25
+ _expand_env_vars,
26
+ _navigate_json,
27
+ _split_resolver_key,
28
+ )
29
+ from loom.core.config.errors import ConfigError
30
+
31
+ logger = logging.getLogger(__name__)
32
+
33
+
34
+ def _fetch_secret(client: Any, name: str) -> str:
35
+ """Fetch a string secret value from AWS Secrets Manager.
36
+
37
+ Args:
38
+ client: Boto3 secretsmanager client.
39
+ name: Secret name or short ARN. ARN-style names are supported for
40
+ plain fetches but not for dot-notation JSON navigation.
41
+
42
+ Returns:
43
+ The secret value as a string.
44
+
45
+ Raises:
46
+ ConfigError: When the secret is binary, or on any API error.
47
+ """
48
+ try:
49
+ result = client.get_secret_value(SecretId=name)
50
+ except Exception as exc:
51
+ raise ConfigError(f"Failed to fetch Secrets Manager secret {name!r}: {exc}") from exc
52
+ if "SecretString" not in result:
53
+ raise ConfigError(
54
+ f"Secrets Manager secret {name!r} is binary — only string secrets are supported"
55
+ )
56
+ return str(result["SecretString"])
57
+
58
+
59
+ class SecretsManagerResolver:
60
+ """Resolves AWS Secrets Manager paths for use with :func:`~loom.core.config.load_config`.
61
+
62
+ Fetches secret values from AWS Secrets Manager. The boto3 client is
63
+ created lazily on first use and reused across calls.
64
+
65
+ Env-var tokens in the form ``%VAR_NAME%`` (uppercase letters, digits,
66
+ and underscores only) are expanded from ``os.environ`` before the
67
+ request is made.
68
+
69
+ Args:
70
+ region: AWS region name. Passed directly to ``boto3.client``.
71
+ Defaults to ``None``, which lets boto3 use its own resolution
72
+ chain (env vars, instance metadata, etc.).
73
+
74
+ Example::
75
+
76
+ resolver = SecretsManagerResolver("eu-west-1")
77
+ value = resolver.resolve("/myapp/%ENV%/db_password")
78
+ """
79
+
80
+ def __init__(self, region: str | None = None) -> None:
81
+ self._region = region
82
+ self._client: Any = None
83
+
84
+ @property
85
+ def name(self) -> str:
86
+ """OmegaConf resolver prefix.
87
+
88
+ Returns:
89
+ The string ``"secrets"``.
90
+ """
91
+ return "secrets"
92
+
93
+ def _get_client(self) -> Any:
94
+ """Return the boto3 secretsmanager client, creating it on first call.
95
+
96
+ Returns:
97
+ A boto3 secretsmanager client instance.
98
+
99
+ Raises:
100
+ ConfigError: When boto3 is not installed.
101
+ """
102
+ if self._client is None:
103
+ if _boto3_module is None:
104
+ raise ConfigError(
105
+ "boto3 is required for SecretsManagerResolver. "
106
+ "Install it with: pip install loom[config-ssm]"
107
+ )
108
+ self._client = _boto3_module.client("secretsmanager", region_name=self._region)
109
+ return self._client
110
+
111
+ def resolve(self, key: str) -> object:
112
+ """Resolve an AWS Secrets Manager path to its stored value.
113
+
114
+ Expands ``%VAR_NAME%`` tokens in *key* from the environment, then
115
+ fetches the secret from AWS Secrets Manager.
116
+
117
+ Args:
118
+ key: Secret path, optionally containing ``%VAR_NAME%``
119
+ placeholders that are replaced with environment variable values.
120
+ Supports dot-notation for JSON key navigation: ``/path/secret.key``
121
+ fetches ``/path/secret`` and returns ``secret["key"]``.
122
+
123
+ Returns:
124
+ Resolved value. A plain string for secrets without dot-notation;
125
+ a structured value (string, int, dict, etc.) when dot-notation
126
+ navigates into a JSON secret.
127
+
128
+ Raises:
129
+ ConfigError: When *key* is empty, an env-var placeholder is
130
+ missing, boto3 is not installed, the secret is binary,
131
+ or the API call fails.
132
+ """
133
+ if not key:
134
+ raise ConfigError("Secrets Manager key must not be empty")
135
+ expanded = _expand_env_vars(key)
136
+ path, json_keys = _split_resolver_key(expanded)
137
+ logger.info("secrets_resolver: fetching %s", path)
138
+ raw = _fetch_secret(self._get_client(), path)
139
+ if not json_keys:
140
+ return raw
141
+ return _navigate_json(raw, json_keys, path)
142
+
143
+
144
+ __all__ = ["SecretsManagerResolver"]
@@ -13,10 +13,7 @@ Example::
13
13
 
14
14
  from __future__ import annotations
15
15
 
16
- import json
17
16
  import logging
18
- import os
19
- import re
20
17
  from typing import Any
21
18
 
22
19
  try:
@@ -24,42 +21,11 @@ try:
24
21
  except ImportError:
25
22
  _boto3_module = None
26
23
 
24
+ from loom.core.config._resolver_utils import _expand_env_vars, _navigate_json, _split_resolver_key
27
25
  from loom.core.config.errors import ConfigError
28
26
 
29
27
  logger = logging.getLogger(__name__)
30
28
 
31
- _ENV_VAR_PATTERN = re.compile(r"\{([A-Z][A-Z0-9_]*)\}")
32
-
33
-
34
- def _expand_env_vars(key: str) -> str:
35
- """Expand ``{VAR_NAME}`` placeholders in *key* using environment variables.
36
-
37
- Only uppercase identifiers matching ``[A-Z][A-Z0-9_]*`` are expanded.
38
-
39
- Args:
40
- key: SSM parameter path, possibly containing ``{VAR_NAME}`` tokens.
41
-
42
- Returns:
43
- Path with all tokens replaced by their environment variable values.
44
-
45
- Raises:
46
- ConfigError: When a referenced variable is absent from the environment.
47
- """
48
- matches = _ENV_VAR_PATTERN.findall(key)
49
- if not matches:
50
- return key
51
-
52
- def _replace(match: re.Match[str]) -> str:
53
- var_name = match.group(1)
54
- value = os.environ.get(var_name)
55
- if value is None:
56
- raise ConfigError(
57
- f"Env var {var_name!r} not found in environment (referenced in SSM path {key!r})"
58
- )
59
- return value
60
-
61
- return _ENV_VAR_PATTERN.sub(_replace, key)
62
-
63
29
 
64
30
  def _fetch_parameter(client: Any, name: str, with_decryption: bool) -> str:
65
31
  """Fetch a single parameter value from AWS SSM.
@@ -82,78 +48,13 @@ def _fetch_parameter(client: Any, name: str, with_decryption: bool) -> str:
82
48
  return str(result["Parameter"]["Value"])
83
49
 
84
50
 
85
- def _split_ssm_key(key: str) -> tuple[str, list[str]]:
86
- """Split an SSM key into the parameter path and JSON navigation keys.
87
-
88
- The first dot after the last '/' separator marks the start of a JSON key
89
- path. SSM paths use '/' as their separator, so a dot is unambiguously a
90
- JSON navigation token.
91
-
92
- Args:
93
- key: Expanded SSM key, e.g. ``"/app/prod/db_config.host"``.
94
-
95
- Returns:
96
- A 2-tuple ``(ssm_path, json_keys)`` where *ssm_path* is the SSM
97
- parameter path to fetch and *json_keys* is a list of dict keys to
98
- navigate (empty list when no dot-notation is present).
99
-
100
- Examples:
101
- >>> _split_ssm_key("/app/prod/token")
102
- ('/app/prod/token', [])
103
- >>> _split_ssm_key("/app/prod/db_config.host")
104
- ('/app/prod/db_config', ['host'])
105
- >>> _split_ssm_key("/app/prod/db.connection.host")
106
- ('/app/prod/db', ['connection', 'host'])
107
- """
108
- if not key:
109
- return key, []
110
- last_slash = key.rfind("/")
111
- after_last_slash = key[last_slash + 1 :] if last_slash != -1 else key
112
- dot_pos = after_last_slash.find(".")
113
- if dot_pos == -1:
114
- return key, []
115
- base_end = (last_slash + 1 + dot_pos) if last_slash != -1 else dot_pos
116
- json_tail = key[base_end + 1 :]
117
- return key[:base_end], [k for k in json_tail.split(".") if k]
118
-
119
-
120
- def _navigate_json(raw: str, keys: list[str], ssm_path: str) -> object:
121
- """Parse *raw* as JSON and navigate to the value at *keys*.
122
-
123
- Args:
124
- raw: Raw string value from SSM.
125
- keys: Ordered list of dict keys to traverse.
126
- ssm_path: Original SSM path, used only in error messages.
127
-
128
- Returns:
129
- The value at the navigated position. May be any JSON-compatible type.
130
-
131
- Raises:
132
- ConfigError: When *raw* is not valid JSON, or a key is absent.
133
- """
134
- try:
135
- data: object = json.loads(
136
- raw
137
- ) # json.loads returns Any; annotated as object to avoid implicit Any propagation
138
- except json.JSONDecodeError as exc:
139
- raise ConfigError(
140
- f"SSM parameter {ssm_path!r} is not valid JSON (required for key navigation): {exc}"
141
- ) from exc
142
- current: object = data
143
- for k in keys:
144
- if not isinstance(current, dict) or k not in current:
145
- raise ConfigError(f"Key {k!r} not found in SSM parameter {ssm_path!r}")
146
- current = current[k]
147
- return current
148
-
149
-
150
51
  class SsmResolver:
151
52
  """Resolves SSM Parameter Store paths for use with :func:`~loom.core.config.load_config`.
152
53
 
153
54
  Fetches parameter values from AWS Systems Manager Parameter Store.
154
55
  The boto3 client is created lazily on first use and reused across calls.
155
56
 
156
- Env-var tokens in the form ``{VAR_NAME}`` (uppercase letters, digits,
57
+ Env-var tokens in the form ``%VAR_NAME%`` (uppercase letters, digits,
157
58
  and underscores only) are expanded from ``os.environ`` before the
158
59
  SSM request is made.
159
60
 
@@ -167,7 +68,7 @@ class SsmResolver:
167
68
  Example::
168
69
 
169
70
  resolver = SsmResolver("eu-west-1")
170
- value = resolver.resolve("/myapp/{ENV}/db_password")
71
+ value = resolver.resolve("/myapp/%ENV%/db_password")
171
72
  """
172
73
 
173
74
  def __init__(
@@ -210,11 +111,11 @@ class SsmResolver:
210
111
  def resolve(self, key: str) -> object:
211
112
  """Resolve an SSM parameter path to its stored value.
212
113
 
213
- Expands ``{VAR_NAME}`` tokens in *key* from the environment, then
114
+ Expands ``%VAR_NAME%`` tokens in *key* from the environment, then
214
115
  fetches the parameter from AWS SSM Parameter Store.
215
116
 
216
117
  Args:
217
- key: SSM parameter path, optionally containing ``{VAR_NAME}``
118
+ key: SSM parameter path, optionally containing ``%VAR_NAME%``
218
119
  placeholders that are replaced with environment variable values.
219
120
  Supports dot-notation for JSON key navigation: ``/path/param.key``
220
121
  fetches ``/path/param`` and returns ``param["key"]``.
@@ -231,7 +132,7 @@ class SsmResolver:
231
132
  if not key:
232
133
  raise ConfigError("SSM key must not be empty")
233
134
  expanded = _expand_env_vars(key)
234
- ssm_path, json_keys = _split_ssm_key(expanded)
135
+ ssm_path, json_keys = _split_resolver_key(expanded)
235
136
  logger.info("ssm_resolver: fetching %s", ssm_path)
236
137
  client = self._get_client()
237
138
  raw = _fetch_parameter(client, ssm_path, self._with_decryption)
@@ -0,0 +1,130 @@
1
+ """Unit tests for shared resolver utilities (_resolver_utils).
2
+
3
+ Tests _split_resolver_key, _expand_env_vars, and _navigate_json directly
4
+ to catch edge-case regressions that are only indirectly covered by the
5
+ SSM and Secrets Manager resolver test suites.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import pytest
11
+
12
+ from loom.core.config._resolver_utils import (
13
+ _expand_env_vars,
14
+ _navigate_json,
15
+ _split_resolver_key,
16
+ )
17
+ from loom.core.config.errors import ConfigError
18
+
19
+ # ---------------------------------------------------------------------------
20
+ # _split_resolver_key
21
+ # ---------------------------------------------------------------------------
22
+
23
+
24
+ class TestSplitResolverKey:
25
+ def test_empty_string_returns_empty_and_no_keys(self) -> None:
26
+ assert _split_resolver_key("") == ("", [])
27
+
28
+ def test_plain_path_no_dot_returns_path_and_empty_keys(self) -> None:
29
+ assert _split_resolver_key("/prod/token") == ("/prod/token", [])
30
+
31
+ def test_single_dot_notation(self) -> None:
32
+ path, keys = _split_resolver_key("/prod/db_config.host")
33
+ assert path == "/prod/db_config"
34
+ assert keys == ["host"]
35
+
36
+ def test_nested_dot_notation(self) -> None:
37
+ path, keys = _split_resolver_key("/prod/db.connection.host")
38
+ assert path == "/prod/db"
39
+ assert keys == ["connection", "host"]
40
+
41
+ def test_no_slash_with_dot(self) -> None:
42
+ path, keys = _split_resolver_key("param.key")
43
+ assert path == "param"
44
+ assert keys == ["key"]
45
+
46
+ def test_no_slash_no_dot(self) -> None:
47
+ assert _split_resolver_key("simple") == ("simple", [])
48
+
49
+ def test_dot_only_in_first_segment_not_last(self) -> None:
50
+ # dot is in segment "db.prod" which is NOT the last segment
51
+ path, keys = _split_resolver_key("/app/db.prod/token")
52
+ assert path == "/app/db.prod/token"
53
+ assert keys == []
54
+
55
+ def test_trailing_dot_ignored(self) -> None:
56
+ # trailing dot produces an empty segment that is filtered out
57
+ path, keys = _split_resolver_key("/prod/db.")
58
+ assert path == "/prod/db"
59
+ assert keys == []
60
+
61
+ def test_consecutive_dots_filtered(self) -> None:
62
+ path, keys = _split_resolver_key("/prod/db..host")
63
+ assert path == "/prod/db"
64
+ assert keys == ["host"]
65
+
66
+ def test_path_with_only_slash(self) -> None:
67
+ assert _split_resolver_key("/") == ("/", [])
68
+
69
+
70
+ # ---------------------------------------------------------------------------
71
+ # _expand_env_vars
72
+ # ---------------------------------------------------------------------------
73
+
74
+
75
+ class TestExpandEnvVars:
76
+ def test_no_placeholders_returns_unchanged(self) -> None:
77
+ assert _expand_env_vars("/prod/token") == "/prod/token"
78
+
79
+ def test_single_placeholder_expanded(self, monkeypatch: pytest.MonkeyPatch) -> None:
80
+ monkeypatch.setenv("ENV", "staging")
81
+ assert _expand_env_vars("/app/%ENV%/token") == "/app/staging/token"
82
+
83
+ def test_multiple_placeholders_expanded(self, monkeypatch: pytest.MonkeyPatch) -> None:
84
+ monkeypatch.setenv("REGION", "eu-west-1")
85
+ monkeypatch.setenv("ENV", "prod")
86
+ assert _expand_env_vars("/%REGION%/%ENV%/key") == "/eu-west-1/prod/key"
87
+
88
+ def test_missing_env_var_raises_config_error(self, monkeypatch: pytest.MonkeyPatch) -> None:
89
+ monkeypatch.delenv("MISSING", raising=False)
90
+ with pytest.raises(ConfigError, match="MISSING"):
91
+ _expand_env_vars("/path/%MISSING%/token")
92
+
93
+ def test_lowercase_not_expanded(self) -> None:
94
+ assert _expand_env_vars("/path/%env%/token") == "/path/%env%/token"
95
+
96
+
97
+ # ---------------------------------------------------------------------------
98
+ # _navigate_json
99
+ # ---------------------------------------------------------------------------
100
+
101
+
102
+ class TestNavigateJson:
103
+ def test_single_key(self) -> None:
104
+ result = _navigate_json('{"host": "db.internal"}', ["host"], "/path")
105
+ assert result == "db.internal"
106
+
107
+ def test_nested_keys(self) -> None:
108
+ result = _navigate_json('{"conn": {"host": "db"}}', ["conn", "host"], "/path")
109
+ assert result == "db"
110
+
111
+ def test_missing_key_raises_config_error(self) -> None:
112
+ with pytest.raises(ConfigError, match="absent"):
113
+ _navigate_json('{"host": "db"}', ["absent"], "/path")
114
+
115
+ def test_invalid_json_raises_config_error(self) -> None:
116
+ with pytest.raises(ConfigError, match="not valid JSON"):
117
+ _navigate_json("not-json", ["key"], "/path")
118
+
119
+ def test_invalid_json_error_does_not_expose_raw_value(self) -> None:
120
+ """Security: JSONDecodeError.__cause__ must not hold the raw secret."""
121
+ secret_value = "my_raw_secret_value"
122
+ with pytest.raises(ConfigError) as exc_info:
123
+ _navigate_json(secret_value, ["key"], "/path")
124
+ assert exc_info.value.__cause__ is None, (
125
+ "ConfigError must not chain JSONDecodeError — its .doc attribute holds the raw secret"
126
+ )
127
+
128
+ def test_non_dict_intermediate_raises_config_error(self) -> None:
129
+ with pytest.raises(ConfigError):
130
+ _navigate_json('{"host": "db"}', ["host", "nested"], "/path")