loom-kernel 0.2.1__tar.gz → 0.4.0__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 (559) hide show
  1. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/.github/workflows/ci-pr.yml +1 -1
  2. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/.github/workflows/release.yml +39 -0
  3. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/.gitignore +1 -0
  4. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/.readthedocs.yaml +6 -0
  5. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/CHANGELOG.md +85 -19
  6. loom_kernel-0.4.0/CHANGELOG_RELEASE.md +15 -0
  7. loom_kernel-0.2.1/README.md → loom_kernel-0.4.0/PKG-INFO +135 -2
  8. loom_kernel-0.2.1/PKG-INFO → loom_kernel-0.4.0/README.md +77 -37
  9. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/conf.py +15 -3
  10. loom_kernel-0.4.0/docs/etl/examples.md +29 -0
  11. loom_kernel-0.4.0/docs/etl/pipelines.md +426 -0
  12. loom_kernel-0.4.0/docs/etl/testing.md +65 -0
  13. loom_kernel-0.4.0/docs/getting-started/etl.md +136 -0
  14. loom_kernel-0.4.0/docs/getting-started/rest.md +424 -0
  15. loom_kernel-0.4.0/docs/guides/etl.md +559 -0
  16. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/index.rst +17 -11
  17. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/reference/api/core.rst +8 -0
  18. loom_kernel-0.4.0/docs/reference/api/etl.rst +50 -0
  19. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/reference/index.rst +1 -0
  20. loom_kernel-0.4.0/docs/rest/autocrud.md +166 -0
  21. loom_kernel-0.4.0/docs/rest/celery.md +538 -0
  22. loom_kernel-0.4.0/docs/rest/examples.md +642 -0
  23. loom_kernel-0.4.0/docs/rest/testing.md +67 -0
  24. loom_kernel-0.4.0/docs/rest/use-case-dsl.md +477 -0
  25. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/pyproject.toml +63 -2
  26. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/config/__init__.py +2 -1
  27. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/config/loader.py +149 -26
  28. loom_kernel-0.4.0/src/loom/core/config/resolver.py +82 -0
  29. loom_kernel-0.4.0/src/loom/etl/__init__.py +221 -0
  30. loom_kernel-0.4.0/src/loom/etl/backends/__init__.py +9 -0
  31. loom_kernel-0.4.0/src/loom/etl/backends/_format_registry.py +37 -0
  32. loom_kernel-0.4.0/src/loom/etl/backends/_historify/__init__.py +19 -0
  33. loom_kernel-0.4.0/src/loom/etl/backends/_historify/_common.py +43 -0
  34. loom_kernel-0.4.0/src/loom/etl/backends/_historify/_log.py +42 -0
  35. loom_kernel-0.4.0/src/loom/etl/backends/_historify/_ops.py +90 -0
  36. loom_kernel-0.4.0/src/loom/etl/backends/_historify/_snapshot.py +72 -0
  37. loom_kernel-0.4.0/src/loom/etl/backends/_historify/_transform.py +97 -0
  38. loom_kernel-0.4.0/src/loom/etl/backends/_merge.py +276 -0
  39. loom_kernel-0.4.0/src/loom/etl/backends/_predicate.py +144 -0
  40. loom_kernel-0.4.0/src/loom/etl/backends/_schema_aligner/__init__.py +6 -0
  41. loom_kernel-0.4.0/src/loom/etl/backends/_schema_aligner/_aligner.py +23 -0
  42. loom_kernel-0.4.0/src/loom/etl/backends/_schema_aligner/_policy.py +66 -0
  43. loom_kernel-0.4.0/src/loom/etl/backends/_write_policy.py +543 -0
  44. loom_kernel-0.4.0/src/loom/etl/backends/polars/__init__.py +14 -0
  45. loom_kernel-0.4.0/src/loom/etl/backends/polars/_dtype.py +257 -0
  46. loom_kernel-0.4.0/src/loom/etl/backends/polars/_file_writer.py +92 -0
  47. loom_kernel-0.4.0/src/loom/etl/backends/polars/_historify.py +192 -0
  48. loom_kernel-0.4.0/src/loom/etl/backends/polars/_predicate.py +102 -0
  49. loom_kernel-0.4.0/src/loom/etl/backends/polars/_reader.py +193 -0
  50. loom_kernel-0.4.0/src/loom/etl/backends/polars/_schema.py +180 -0
  51. loom_kernel-0.4.0/src/loom/etl/backends/polars/_schema_aligner.py +37 -0
  52. loom_kernel-0.4.0/src/loom/etl/backends/polars/_writer.py +456 -0
  53. loom_kernel-0.4.0/src/loom/etl/backends/polars/provider.py +138 -0
  54. loom_kernel-0.4.0/src/loom/etl/backends/spark/__init__.py +16 -0
  55. loom_kernel-0.4.0/src/loom/etl/backends/spark/_dtype.py +126 -0
  56. loom_kernel-0.4.0/src/loom/etl/backends/spark/_historify.py +227 -0
  57. loom_kernel-0.4.0/src/loom/etl/backends/spark/_reader.py +196 -0
  58. loom_kernel-0.4.0/src/loom/etl/backends/spark/_schema.py +41 -0
  59. loom_kernel-0.4.0/src/loom/etl/backends/spark/_schema_aligner.py +40 -0
  60. loom_kernel-0.4.0/src/loom/etl/backends/spark/_writer.py +517 -0
  61. loom_kernel-0.4.0/src/loom/etl/backends/spark/provider.py +79 -0
  62. loom_kernel-0.4.0/src/loom/etl/checkpoint/__init__.py +15 -0
  63. loom_kernel-0.4.0/src/loom/etl/checkpoint/_backends/_polars.py +106 -0
  64. loom_kernel-0.4.0/src/loom/etl/checkpoint/_backends/_spark.py +135 -0
  65. loom_kernel-0.4.0/src/loom/etl/checkpoint/_cleaners.py +64 -0
  66. loom_kernel-0.4.0/src/loom/etl/checkpoint/_paths.py +52 -0
  67. loom_kernel-0.4.0/src/loom/etl/checkpoint/_scope.py +35 -0
  68. loom_kernel-0.4.0/src/loom/etl/checkpoint/_store.py +234 -0
  69. loom_kernel-0.4.0/src/loom/etl/compiler/__init__.py +48 -0
  70. loom_kernel-0.4.0/src/loom/etl/compiler/_binding.py +111 -0
  71. loom_kernel-0.4.0/src/loom/etl/compiler/_compiler.py +268 -0
  72. loom_kernel-0.4.0/src/loom/etl/compiler/_errors.py +316 -0
  73. loom_kernel-0.4.0/src/loom/etl/compiler/_plan.py +206 -0
  74. loom_kernel-0.4.0/src/loom/etl/compiler/_validators.py +43 -0
  75. loom_kernel-0.4.0/src/loom/etl/compiler/_validators_plan.py +267 -0
  76. loom_kernel-0.4.0/src/loom/etl/compiler/_validators_step.py +473 -0
  77. loom_kernel-0.4.0/src/loom/etl/declarative/__init__.py +80 -0
  78. loom_kernel-0.4.0/src/loom/etl/declarative/_format.py +21 -0
  79. loom_kernel-0.4.0/src/loom/etl/declarative/_read_options.py +91 -0
  80. loom_kernel-0.4.0/src/loom/etl/declarative/_utils.py +18 -0
  81. loom_kernel-0.4.0/src/loom/etl/declarative/_write_options.py +111 -0
  82. loom_kernel-0.4.0/src/loom/etl/declarative/expr/__init__.py +50 -0
  83. loom_kernel-0.4.0/src/loom/etl/declarative/expr/_params.py +61 -0
  84. loom_kernel-0.4.0/src/loom/etl/declarative/expr/_predicate.py +174 -0
  85. loom_kernel-0.4.0/src/loom/etl/declarative/expr/_predicate_dialect.py +160 -0
  86. loom_kernel-0.4.0/src/loom/etl/declarative/expr/_refs.py +122 -0
  87. loom_kernel-0.4.0/src/loom/etl/declarative/source/__init__.py +43 -0
  88. loom_kernel-0.4.0/src/loom/etl/declarative/source/_from.py +569 -0
  89. loom_kernel-0.4.0/src/loom/etl/declarative/source/_specs.py +149 -0
  90. loom_kernel-0.4.0/src/loom/etl/declarative/target/__init__.py +111 -0
  91. loom_kernel-0.4.0/src/loom/etl/declarative/target/_file.py +34 -0
  92. loom_kernel-0.4.0/src/loom/etl/declarative/target/_history/__init__.py +30 -0
  93. loom_kernel-0.4.0/src/loom/etl/declarative/target/_history/_builder.py +241 -0
  94. loom_kernel-0.4.0/src/loom/etl/declarative/target/_history/_enums.py +58 -0
  95. loom_kernel-0.4.0/src/loom/etl/declarative/target/_history/_errors.py +78 -0
  96. loom_kernel-0.4.0/src/loom/etl/declarative/target/_history/_report.py +27 -0
  97. loom_kernel-0.4.0/src/loom/etl/declarative/target/_history/_spec.py +69 -0
  98. loom_kernel-0.4.0/src/loom/etl/declarative/target/_into.py +453 -0
  99. loom_kernel-0.4.0/src/loom/etl/declarative/target/_schema_mode.py +23 -0
  100. loom_kernel-0.4.0/src/loom/etl/declarative/target/_table.py +103 -0
  101. loom_kernel-0.4.0/src/loom/etl/declarative/target/_temp.py +43 -0
  102. loom_kernel-0.4.0/src/loom/etl/executor/__init__.py +61 -0
  103. loom_kernel-0.4.0/src/loom/etl/executor/_dispatcher.py +94 -0
  104. loom_kernel-0.4.0/src/loom/etl/executor/_executor.py +357 -0
  105. loom_kernel-0.4.0/src/loom/etl/observability/__init__.py +59 -0
  106. loom_kernel-0.4.0/src/loom/etl/observability/config.py +106 -0
  107. loom_kernel-0.4.0/src/loom/etl/observability/factory.py +52 -0
  108. loom_kernel-0.4.0/src/loom/etl/observability/observers/__init__.py +13 -0
  109. loom_kernel-0.4.0/src/loom/etl/observability/observers/_labels.py +57 -0
  110. loom_kernel-0.4.0/src/loom/etl/observability/observers/composite.py +62 -0
  111. loom_kernel-0.4.0/src/loom/etl/observability/observers/noop.py +36 -0
  112. loom_kernel-0.4.0/src/loom/etl/observability/observers/otel.py +263 -0
  113. loom_kernel-0.4.0/src/loom/etl/observability/observers/protocol.py +37 -0
  114. loom_kernel-0.4.0/src/loom/etl/observability/observers/structlog.py +100 -0
  115. loom_kernel-0.4.0/src/loom/etl/observability/recording/__init__.py +5 -0
  116. loom_kernel-0.4.0/src/loom/etl/observability/recording/_recorder.py +225 -0
  117. loom_kernel-0.4.0/src/loom/etl/observability/records.py +241 -0
  118. loom_kernel-0.4.0/src/loom/etl/observability/sinks/__init__.py +17 -0
  119. loom_kernel-0.4.0/src/loom/etl/observability/sinks/_protocol.py +44 -0
  120. loom_kernel-0.4.0/src/loom/etl/observability/sinks/_table.py +42 -0
  121. loom_kernel-0.4.0/src/loom/etl/observability/sinks/_writer.py +26 -0
  122. loom_kernel-0.4.0/src/loom/etl/pipeline/__init__.py +12 -0
  123. loom_kernel-0.4.0/src/loom/etl/pipeline/_generics.py +31 -0
  124. loom_kernel-0.4.0/src/loom/etl/pipeline/_params.py +27 -0
  125. loom_kernel-0.4.0/src/loom/etl/pipeline/_pipeline.py +62 -0
  126. loom_kernel-0.4.0/src/loom/etl/pipeline/_process.py +64 -0
  127. loom_kernel-0.4.0/src/loom/etl/pipeline/_sql.py +55 -0
  128. loom_kernel-0.4.0/src/loom/etl/pipeline/_step.py +154 -0
  129. loom_kernel-0.4.0/src/loom/etl/pipeline/_step_sql.py +91 -0
  130. loom_kernel-0.4.0/src/loom/etl/runner/__init__.py +6 -0
  131. loom_kernel-0.4.0/src/loom/etl/runner/_providers.py +64 -0
  132. loom_kernel-0.4.0/src/loom/etl/runner/_wiring.py +112 -0
  133. loom_kernel-0.4.0/src/loom/etl/runner/config_loader.py +45 -0
  134. loom_kernel-0.4.0/src/loom/etl/runner/core.py +166 -0
  135. loom_kernel-0.4.0/src/loom/etl/runner/errors.py +17 -0
  136. loom_kernel-0.4.0/src/loom/etl/runner/filtering.py +107 -0
  137. loom_kernel-0.4.0/src/loom/etl/runtime/__init__.py +5 -0
  138. loom_kernel-0.4.0/src/loom/etl/runtime/contracts.py +128 -0
  139. loom_kernel-0.4.0/src/loom/etl/schema/__init__.py +46 -0
  140. loom_kernel-0.4.0/src/loom/etl/schema/_contract.py +220 -0
  141. loom_kernel-0.4.0/src/loom/etl/schema/_schema.py +334 -0
  142. loom_kernel-0.4.0/src/loom/etl/storage/__init__.py +60 -0
  143. loom_kernel-0.4.0/src/loom/etl/storage/_config.py +373 -0
  144. loom_kernel-0.4.0/src/loom/etl/storage/_file_locator.py +146 -0
  145. loom_kernel-0.4.0/src/loom/etl/storage/_locator.py +253 -0
  146. loom_kernel-0.4.0/src/loom/etl/storage/routing.py +230 -0
  147. loom_kernel-0.4.0/src/loom/etl/testing/__init__.py +58 -0
  148. loom_kernel-0.4.0/src/loom/etl/testing/_result.py +88 -0
  149. loom_kernel-0.4.0/src/loom/etl/testing/_runners.py +142 -0
  150. loom_kernel-0.4.0/src/loom/etl/testing/_scenario.py +79 -0
  151. loom_kernel-0.4.0/src/loom/etl/testing/_stubs.py +212 -0
  152. loom_kernel-0.4.0/src/loom/etl/testing/spark.py +324 -0
  153. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/conftest.py +34 -0
  154. loom_kernel-0.4.0/tests/integration/etl/__init__.py +1 -0
  155. loom_kernel-0.4.0/tests/integration/etl/test_runner_integration.py +241 -0
  156. loom_kernel-0.4.0/tests/integration/etl/test_runtime_contracts.py +455 -0
  157. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/config/test_config.py +98 -0
  158. loom_kernel-0.4.0/tests/unit/etl/backends/_historify_contract.py +885 -0
  159. loom_kernel-0.4.0/tests/unit/etl/backends/test_historify_common.py +52 -0
  160. loom_kernel-0.4.0/tests/unit/etl/backends/test_polars/conftest.py +175 -0
  161. loom_kernel-0.4.0/tests/unit/etl/backends/test_polars/test_apply_schema.py +90 -0
  162. loom_kernel-0.4.0/tests/unit/etl/backends/test_polars/test_backend.py +390 -0
  163. loom_kernel-0.4.0/tests/unit/etl/backends/test_polars/test_dtype.py +137 -0
  164. loom_kernel-0.4.0/tests/unit/etl/backends/test_polars/test_file_writer.py +71 -0
  165. loom_kernel-0.4.0/tests/unit/etl/backends/test_polars/test_historify_polars.py +212 -0
  166. loom_kernel-0.4.0/tests/unit/etl/backends/test_polars/test_predicate_pushdown.py +160 -0
  167. loom_kernel-0.4.0/tests/unit/etl/backends/test_polars/test_reader_columns.py +162 -0
  168. loom_kernel-0.4.0/tests/unit/etl/backends/test_polars/test_reader_json_columns.py +199 -0
  169. loom_kernel-0.4.0/tests/unit/etl/backends/test_polars/test_step_execution.py +223 -0
  170. loom_kernel-0.4.0/tests/unit/etl/backends/test_polars/test_upsert_writer.py +209 -0
  171. loom_kernel-0.4.0/tests/unit/etl/backends/test_polars/test_writer_to_frame.py +75 -0
  172. loom_kernel-0.4.0/tests/unit/etl/backends/test_spark/conftest.py +89 -0
  173. loom_kernel-0.4.0/tests/unit/etl/backends/test_spark/test_dtype.py +104 -0
  174. loom_kernel-0.4.0/tests/unit/etl/backends/test_spark/test_historify_spark.py +238 -0
  175. loom_kernel-0.4.0/tests/unit/etl/backends/test_spark/test_spark_apply_schema.py +215 -0
  176. loom_kernel-0.4.0/tests/unit/etl/backends/test_spark/test_step_execution.py +404 -0
  177. loom_kernel-0.4.0/tests/unit/etl/backends/test_spark/test_writer_to_frame.py +102 -0
  178. loom_kernel-0.4.0/tests/unit/etl/backends/test_write_policy_historify.py +283 -0
  179. loom_kernel-0.4.0/tests/unit/etl/checkpoint/__init__.py +0 -0
  180. loom_kernel-0.4.0/tests/unit/etl/checkpoint/backends/test_checkpoint_polars.py +33 -0
  181. loom_kernel-0.4.0/tests/unit/etl/checkpoint/test_checkpoint_paths.py +61 -0
  182. loom_kernel-0.4.0/tests/unit/etl/checkpoint/test_cleaners.py +81 -0
  183. loom_kernel-0.4.0/tests/unit/etl/checkpoint/test_store.py +248 -0
  184. loom_kernel-0.4.0/tests/unit/etl/compiler/__init__.py +0 -0
  185. loom_kernel-0.4.0/tests/unit/etl/compiler/test_catalog_validator.py +92 -0
  186. loom_kernel-0.4.0/tests/unit/etl/compiler/test_compiler.py +502 -0
  187. loom_kernel-0.4.0/tests/unit/etl/compiler/test_compiler_catalog.py +132 -0
  188. loom_kernel-0.4.0/tests/unit/etl/compiler/test_compiler_upsert.py +133 -0
  189. loom_kernel-0.4.0/tests/unit/etl/compiler/test_errors.py +223 -0
  190. loom_kernel-0.4.0/tests/unit/etl/compiler/test_errors_additional_factories.py +76 -0
  191. loom_kernel-0.4.0/tests/unit/etl/compiler/test_errors_runtime_factories.py +159 -0
  192. loom_kernel-0.4.0/tests/unit/etl/compiler/test_historify_validator.py +432 -0
  193. loom_kernel-0.4.0/tests/unit/etl/compiler/test_param_exprs_validator.py +150 -0
  194. loom_kernel-0.4.0/tests/unit/etl/compiler/test_plan_traversal.py +207 -0
  195. loom_kernel-0.4.0/tests/unit/etl/compiler/test_step_validator.py +81 -0
  196. loom_kernel-0.4.0/tests/unit/etl/compiler/test_structural.py +135 -0
  197. loom_kernel-0.4.0/tests/unit/etl/compiler/test_temp_validator.py +205 -0
  198. loom_kernel-0.4.0/tests/unit/etl/compiler/test_upsert_validator.py +125 -0
  199. loom_kernel-0.4.0/tests/unit/etl/conftest.py +40 -0
  200. loom_kernel-0.4.0/tests/unit/etl/io/__init__.py +0 -0
  201. loom_kernel-0.4.0/tests/unit/etl/io/test_history_target.py +739 -0
  202. loom_kernel-0.4.0/tests/unit/etl/io/test_source.py +263 -0
  203. loom_kernel-0.4.0/tests/unit/etl/io/test_source_json.py +236 -0
  204. loom_kernel-0.4.0/tests/unit/etl/io/test_source_options.py +178 -0
  205. loom_kernel-0.4.0/tests/unit/etl/io/test_target.py +225 -0
  206. loom_kernel-0.4.0/tests/unit/etl/io/test_utils.py +32 -0
  207. loom_kernel-0.4.0/tests/unit/etl/io/test_variants.py +125 -0
  208. loom_kernel-0.4.0/tests/unit/etl/pipeline/__init__.py +1 -0
  209. loom_kernel-0.4.0/tests/unit/etl/pipeline/test_pipeline_process.py +67 -0
  210. loom_kernel-0.4.0/tests/unit/etl/pipeline/test_proxy.py +90 -0
  211. loom_kernel-0.4.0/tests/unit/etl/pipeline/test_step.py +132 -0
  212. loom_kernel-0.4.0/tests/unit/etl/schema/__init__.py +0 -0
  213. loom_kernel-0.4.0/tests/unit/etl/schema/test_contract.py +249 -0
  214. loom_kernel-0.4.0/tests/unit/etl/schema/test_schema.py +181 -0
  215. loom_kernel-0.4.0/tests/unit/etl/schema/test_table.py +63 -0
  216. loom_kernel-0.4.0/tests/unit/etl/sql/__init__.py +0 -0
  217. loom_kernel-0.4.0/tests/unit/etl/sql/test_merge.py +214 -0
  218. loom_kernel-0.4.0/tests/unit/etl/sql/test_predicate.py +99 -0
  219. loom_kernel-0.4.0/tests/unit/etl/sql/test_predicate_dialect.py +98 -0
  220. loom_kernel-0.4.0/tests/unit/etl/sql/test_sql_runtime.py +172 -0
  221. loom_kernel-0.4.0/tests/unit/etl/storage/__init__.py +0 -0
  222. loom_kernel-0.4.0/tests/unit/etl/storage/test_backend_factory.py +426 -0
  223. loom_kernel-0.4.0/tests/unit/etl/storage/test_io_protocols.py +101 -0
  224. loom_kernel-0.4.0/tests/unit/etl/storage/test_locator.py +87 -0
  225. loom_kernel-0.4.0/tests/unit/etl/storage/test_observability_and_protocols.py +149 -0
  226. loom_kernel-0.4.0/tests/unit/etl/storage/test_route_build.py +146 -0
  227. loom_kernel-0.4.0/tests/unit/etl/storage/test_schema_readers.py +91 -0
  228. loom_kernel-0.4.0/tests/unit/etl/storage/test_storage_config.py +341 -0
  229. loom_kernel-0.4.0/tests/unit/etl/test_config_loader.py +85 -0
  230. loom_kernel-0.4.0/tests/unit/etl/test_executor.py +317 -0
  231. loom_kernel-0.4.0/tests/unit/etl/test_format_registry.py +30 -0
  232. loom_kernel-0.4.0/tests/unit/etl/test_module_contracts.py +422 -0
  233. loom_kernel-0.4.0/tests/unit/etl/test_observer.py +351 -0
  234. loom_kernel-0.4.0/tests/unit/etl/test_observer_internals.py +448 -0
  235. loom_kernel-0.4.0/tests/unit/etl/test_public_api_discovery.py +57 -0
  236. loom_kernel-0.4.0/tests/unit/etl/test_record_schema_coverage.py +65 -0
  237. loom_kernel-0.4.0/tests/unit/etl/test_runner.py +300 -0
  238. loom_kernel-0.4.0/tests/unit/etl/test_runner_errors.py +19 -0
  239. loom_kernel-0.4.0/tests/unit/etl/test_spark_testing.py +78 -0
  240. loom_kernel-0.4.0/tests/unit/etl/testing/test_runners.py +146 -0
  241. loom_kernel-0.4.0/tests/unit/etl/testing/test_scenario_and_stubs.py +106 -0
  242. loom_kernel-0.4.0/tests/unit/etl/testing/test_spark_helpers.py +167 -0
  243. loom_kernel-0.4.0/tests/unit/prometheus/__init__.py +0 -0
  244. loom_kernel-0.4.0/tests/unit/rest/__init__.py +0 -0
  245. loom_kernel-0.4.0/tests/unit/testing/__init__.py +0 -0
  246. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/uv.lock +638 -5
  247. loom_kernel-0.2.1/CHANGELOG_RELEASE.md +0 -39
  248. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/.github/workflows/ci-main.yml +0 -0
  249. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/.github/workflows/docs.yml +0 -0
  250. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/.pre-commit-config.yaml +0 -0
  251. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/LICENSE +0 -0
  252. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/Makefile +0 -0
  253. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/codecov.yml +0 -0
  254. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/_static/.gitkeep +0 -0
  255. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/_static/custom.css +0 -0
  256. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/_static/logo-transparent.png +0 -0
  257. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/_static/logo.svg +0 -0
  258. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/architecture/adr/README.md +0 -0
  259. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/architecture/clean-architecture.md +0 -0
  260. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/architecture/overview.md +0 -0
  261. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/examples-repo/index.md +0 -0
  262. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/guides/autocrud.md +0 -0
  263. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/guides/celery.md +0 -0
  264. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/guides/fake-repo-examples.md +0 -0
  265. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/guides/quickstart.md +0 -0
  266. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/guides/use-case-dsl.md +0 -0
  267. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/reference/api/repository.rst +0 -0
  268. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/reference/api/rest.rst +0 -0
  269. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/reference/api/testing.rst +0 -0
  270. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/docs/requirements.txt +0 -0
  271. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/sonar-project.properties +0 -0
  272. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/__init__.py +0 -0
  273. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/celery/__init__.py +0 -0
  274. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/celery/auto.py +0 -0
  275. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/celery/bootstrap.py +0 -0
  276. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/celery/config.py +0 -0
  277. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/celery/constants.py +0 -0
  278. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/celery/event_loop.py +0 -0
  279. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/celery/runner.py +0 -0
  280. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/celery/service.py +0 -0
  281. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/backend/__init__.py +0 -0
  282. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/backend/core_model.py +0 -0
  283. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/backend/protocol.py +0 -0
  284. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/backend/sqlalchemy.py +0 -0
  285. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/bootstrap/__init__.py +0 -0
  286. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/bootstrap/bootstrap.py +0 -0
  287. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/bootstrap/kernel.py +0 -0
  288. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/cache/__init__.py +0 -0
  289. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/cache/abc/__init__.py +0 -0
  290. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/cache/abc/backend.py +0 -0
  291. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/cache/abc/config.py +0 -0
  292. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/cache/abc/dependency.py +0 -0
  293. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/cache/codec.py +0 -0
  294. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/cache/decorators.py +0 -0
  295. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/cache/dependency.py +0 -0
  296. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/cache/gateway.py +0 -0
  297. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/cache/keys.py +0 -0
  298. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/cache/repository.py +0 -0
  299. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/cache/serializer.py +0 -0
  300. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/command/__init__.py +0 -0
  301. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/command/adapter.py +0 -0
  302. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/command/base.py +0 -0
  303. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/command/field.py +0 -0
  304. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/command/introspection.py +0 -0
  305. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/config/errors.py +0 -0
  306. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/config/keys.py +0 -0
  307. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/config/model.py +0 -0
  308. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/contracts/__init__.py +0 -0
  309. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/contracts/manifest.py +0 -0
  310. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/di/__init__.py +0 -0
  311. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/di/container.py +0 -0
  312. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/di/scope.py +0 -0
  313. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/discovery/__init__.py +0 -0
  314. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/discovery/_utils.py +0 -0
  315. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/discovery/base.py +0 -0
  316. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/discovery/interfaces.py +0 -0
  317. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/discovery/manifest.py +0 -0
  318. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/discovery/modules.py +0 -0
  319. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/engine/__init__.py +0 -0
  320. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/engine/compilable.py +0 -0
  321. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/engine/compiler.py +0 -0
  322. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/engine/events.py +0 -0
  323. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/engine/executor.py +0 -0
  324. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/engine/metrics.py +0 -0
  325. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/engine/plan.py +0 -0
  326. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/errors/__init__.py +0 -0
  327. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/errors/codes.py +0 -0
  328. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/errors/errors.py +0 -0
  329. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/job/__init__.py +0 -0
  330. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/job/callback.py +0 -0
  331. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/job/context.py +0 -0
  332. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/job/handle.py +0 -0
  333. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/job/job.py +0 -0
  334. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/job/service.py +0 -0
  335. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/logger/__init__.py +0 -0
  336. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/logger/abc.py +0 -0
  337. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/logger/config.py +0 -0
  338. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/logger/registry.py +0 -0
  339. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/logger/structlogger.py +0 -0
  340. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/model/__init__.py +0 -0
  341. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/model/base.py +0 -0
  342. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/model/enums.py +0 -0
  343. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/model/field.py +0 -0
  344. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/model/introspection.py +0 -0
  345. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/model/projection.py +0 -0
  346. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/model/relation.py +0 -0
  347. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/model/struct.py +0 -0
  348. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/model/timestamped.py +0 -0
  349. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/model/types.py +0 -0
  350. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/model/types_postgres.py +0 -0
  351. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/projection/__init__.py +0 -0
  352. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/projection/loaders.py +0 -0
  353. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/projection/runtime.py +0 -0
  354. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/__init__.py +0 -0
  355. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/abc/__init__.py +0 -0
  356. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/abc/query.py +0 -0
  357. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/abc/repo_for.py +0 -0
  358. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/abc/repository.py +0 -0
  359. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/mutation.py +0 -0
  360. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/registration.py +0 -0
  361. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/registry.py +0 -0
  362. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/__init__.py +0 -0
  363. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/integrity.py +0 -0
  364. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/loaders.py +0 -0
  365. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/mixins.py +0 -0
  366. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/model.py +0 -0
  367. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/profile_loader.py +0 -0
  368. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/projection.py +0 -0
  369. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/query_compiler/__init__.py +0 -0
  370. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/query_compiler/compiler.py +0 -0
  371. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/query_compiler/cursor.py +0 -0
  372. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/query_compiler/errors.py +0 -0
  373. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/query_compiler/filters.py +0 -0
  374. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/query_compiler/ordering.py +0 -0
  375. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/query_compiler/paths.py +0 -0
  376. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/query_compiler/subquery.py +0 -0
  377. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/registry.py +0 -0
  378. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/repository.py +0 -0
  379. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/session_manager.py +0 -0
  380. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/transactional.py +0 -0
  381. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/repository/sqlalchemy/uow.py +0 -0
  382. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/response/__init__.py +0 -0
  383. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/response/base.py +0 -0
  384. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/tracing/__init__.py +0 -0
  385. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/tracing/context.py +0 -0
  386. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/transport/__init__.py +0 -0
  387. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/transport/adapter.py +0 -0
  388. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/uow/__init__.py +0 -0
  389. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/uow/abc.py +0 -0
  390. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/uow/context.py +0 -0
  391. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/use_case/__init__.py +0 -0
  392. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/use_case/_predicates.py +0 -0
  393. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/use_case/compute.py +0 -0
  394. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/use_case/constants.py +0 -0
  395. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/use_case/factory.py +0 -0
  396. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/use_case/field_ref.py +0 -0
  397. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/use_case/invoker.py +0 -0
  398. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/use_case/keys.py +0 -0
  399. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/use_case/markers.py +0 -0
  400. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/use_case/registry.py +0 -0
  401. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/use_case/rule.py +0 -0
  402. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/core/use_case/use_case.py +0 -0
  403. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/prometheus/__init__.py +0 -0
  404. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/prometheus/adapter.py +0 -0
  405. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/prometheus/middleware.py +0 -0
  406. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/rest/__init__.py +0 -0
  407. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/rest/adapter.py +0 -0
  408. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/rest/autocrud.py +0 -0
  409. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/rest/compiler.py +0 -0
  410. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/rest/constants.py +0 -0
  411. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/rest/errors.py +0 -0
  412. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/rest/fastapi/__init__.py +0 -0
  413. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/rest/fastapi/app.py +0 -0
  414. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/rest/fastapi/auto.py +0 -0
  415. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/rest/fastapi/openapi.py +0 -0
  416. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/rest/fastapi/response.py +0 -0
  417. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/rest/fastapi/router_runtime.py +0 -0
  418. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/rest/middleware.py +0 -0
  419. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/rest/model.py +0 -0
  420. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/rest/rest_adapter.py +0 -0
  421. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/testing/__init__.py +0 -0
  422. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/testing/golden.py +0 -0
  423. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/testing/http_harness.py +0 -0
  424. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/testing/in_memory.py +0 -0
  425. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/testing/repository_harness.py +0 -0
  426. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/src/loom/testing/runner.py +0 -0
  427. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/__init__.py +0 -0
  428. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/golden/__init__.py +0 -0
  429. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/golden/baselines/.gitkeep +0 -0
  430. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/golden/outputs/.gitkeep +0 -0
  431. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/golden/plans/.gitkeep +0 -0
  432. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/helpers/__init__.py +0 -0
  433. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/__init__.py +0 -0
  434. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/celery_bootstrap/__init__.py +0 -0
  435. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/celery_bootstrap/config/conf.celery.integration.yaml +0 -0
  436. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/celery_bootstrap/test_auto_create_app_integration.py +0 -0
  437. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/celery_bootstrap/test_bootstrap_worker.py +0 -0
  438. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/conftest.py +0 -0
  439. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/core/__init__.py +0 -0
  440. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/core/repository/__init__.py +0 -0
  441. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/core/repository/sqlalchemy/__init__.py +0 -0
  442. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/core/repository/sqlalchemy/conftest.py +0 -0
  443. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/core/repository/sqlalchemy/test_cache_integration.py +0 -0
  444. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/core/repository/sqlalchemy/test_repository_integration.py +0 -0
  445. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/core/rest/__init__.py +0 -0
  446. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/core/rest/test_auto_interface_integration.py +0 -0
  447. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/core/rest/test_fastapi_app_integration.py +0 -0
  448. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/core/use_case/test_custom_repository_integration.py +0 -0
  449. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/core/use_case/test_use_case_crud_integration.py +0 -0
  450. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/__init__.py +0 -0
  451. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/config/__init__.py +0 -0
  452. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/config/conf.interfaces.yaml +0 -0
  453. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/config/conf.manifest.yaml +0 -0
  454. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/config/conf.modules.yaml +0 -0
  455. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/config/conf.yaml +0 -0
  456. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/main.py +0 -0
  457. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/manifest.py +0 -0
  458. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/product/__init__.py +0 -0
  459. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/product/category/__init__.py +0 -0
  460. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/product/category/model.py +0 -0
  461. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/product/category/schemas.py +0 -0
  462. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/product/interface.py +0 -0
  463. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/product/jobs.py +0 -0
  464. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/product/model.py +0 -0
  465. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/product/relations.py +0 -0
  466. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/product/repository.py +0 -0
  467. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/product/repository_contract.py +0 -0
  468. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/product/review/__init__.py +0 -0
  469. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/product/review/model.py +0 -0
  470. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/product/review/schemas.py +0 -0
  471. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/product/schemas.py +0 -0
  472. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/fake_repo/product/use_cases.py +0 -0
  473. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/support/__init__.py +0 -0
  474. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/integration/support/logical_repo_fixtures.py +0 -0
  475. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/celery_bootstrap/__init__.py +0 -0
  476. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/celery_bootstrap/test_bootstrap.py +0 -0
  477. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/celery_bootstrap/test_event_loop.py +0 -0
  478. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/celery_jobs/__init__.py +0 -0
  479. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/celery_jobs/test_auto.py +0 -0
  480. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/celery_jobs/test_celery_service.py +0 -0
  481. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/celery_jobs/test_config.py +0 -0
  482. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/celery_jobs/test_runner.py +0 -0
  483. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/backend/__init__.py +0 -0
  484. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/backend/test_backend_compiler.py +0 -0
  485. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/bootstrap/__init__.py +0 -0
  486. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/bootstrap/test_bootstrap.py +0 -0
  487. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/bootstrap/test_bootstrap_metrics.py +0 -0
  488. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/bootstrap/test_kernel.py +0 -0
  489. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/cache/test_cached_repository.py +0 -0
  490. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/command/__init__.py +0 -0
  491. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/command/test_command_base.py +0 -0
  492. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/command/test_command_field.py +0 -0
  493. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/command/test_command_patch.py +0 -0
  494. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/command/test_introspection.py +0 -0
  495. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/config/__init__.py +0 -0
  496. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/di/__init__.py +0 -0
  497. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/di/test_container.py +0 -0
  498. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/discovery/test_manifest.py +0 -0
  499. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/engine/__init__.py +0 -0
  500. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/engine/test_compiler.py +0 -0
  501. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/engine/test_executor.py +0 -0
  502. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/engine/test_executor_trace.py +0 -0
  503. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/engine/test_executor_uow.py +0 -0
  504. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/engine/test_metrics.py +0 -0
  505. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/engine/test_plan.py +0 -0
  506. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/errors/__init__.py +0 -0
  507. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/errors/test_errors.py +0 -0
  508. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/job/__init__.py +0 -0
  509. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/job/conftest.py +0 -0
  510. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/job/test_callback.py +0 -0
  511. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/job/test_context.py +0 -0
  512. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/job/test_handle.py +0 -0
  513. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/job/test_inline_service.py +0 -0
  514. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/job/test_job.py +0 -0
  515. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/logger/test_registry.py +0 -0
  516. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/model/__init__.py +0 -0
  517. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/model/test_model.py +0 -0
  518. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/model/test_struct.py +0 -0
  519. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/model/test_timestamped.py +0 -0
  520. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/projection/test_runtime.py +0 -0
  521. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/repository/abc/conftest.py +0 -0
  522. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/repository/abc/test_query.py +0 -0
  523. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/repository/abc/test_repository_contract.py +0 -0
  524. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/repository/sqlalchemy/conftest.py +0 -0
  525. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/repository/sqlalchemy/test_loaders.py +0 -0
  526. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/repository/sqlalchemy/test_repository.py +0 -0
  527. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/repository/sqlalchemy/test_transactional.py +0 -0
  528. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/tracing/__init__.py +0 -0
  529. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/tracing/test_context.py +0 -0
  530. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/uow/__init__.py +0 -0
  531. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/uow/test_executor_uow.py +0 -0
  532. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/uow/test_sqlalchemy_uow.py +0 -0
  533. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/uow/test_uow_protocols.py +0 -0
  534. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/use_case/__init__.py +0 -0
  535. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/use_case/test_compute.py +0 -0
  536. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/use_case/test_factory.py +0 -0
  537. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/use_case/test_field_ref.py +0 -0
  538. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/use_case/test_invoker.py +0 -0
  539. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/use_case/test_markers.py +0 -0
  540. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/use_case/test_rule.py +0 -0
  541. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/core/use_case/test_use_case.py +0 -0
  542. {loom_kernel-0.2.1/tests/unit/prometheus → loom_kernel-0.4.0/tests/unit/etl}/__init__.py +0 -0
  543. {loom_kernel-0.2.1/tests/unit/rest → loom_kernel-0.4.0/tests/unit/etl/backends/test_polars}/__init__.py +0 -0
  544. {loom_kernel-0.2.1/tests/unit/testing → loom_kernel-0.4.0/tests/unit/etl/backends/test_spark}/__init__.py +0 -0
  545. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/prometheus/test_adapter.py +0 -0
  546. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/prometheus/test_middleware.py +0 -0
  547. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/rest/test_autocrud.py +0 -0
  548. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/rest/test_fastapi_auto_logger.py +0 -0
  549. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/rest/test_middleware.py +0 -0
  550. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/rest/test_pydantic_adapter.py +0 -0
  551. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/rest/test_response.py +0 -0
  552. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/rest/test_rest_adapter.py +0 -0
  553. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/rest/test_rest_compiler.py +0 -0
  554. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/rest/test_rest_model.py +0 -0
  555. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/rest/test_router_runtime.py +0 -0
  556. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/testing/test_golden.py +0 -0
  557. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/testing/test_http_harness.py +0 -0
  558. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/testing/test_in_memory.py +0 -0
  559. {loom_kernel-0.2.1 → loom_kernel-0.4.0}/tests/unit/testing/test_runner.py +0 -0
@@ -188,7 +188,7 @@ jobs:
188
188
  --skip-existing dist/*
189
189
 
190
190
  - name: Enforce changelog generation
191
- if: ${{ always() }}
191
+ if: ${{ always() && !startsWith(github.head_ref, 'docs/release-') }}
192
192
  shell: bash
193
193
  run: |
194
194
  set -euo pipefail
@@ -14,6 +14,7 @@ on:
14
14
  permissions:
15
15
  contents: write
16
16
  id-token: write
17
+ pull-requests: write
17
18
 
18
19
  concurrency:
19
20
  group: release-${{ github.ref }}
@@ -30,6 +31,7 @@ jobs:
30
31
  - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
31
32
  with:
32
33
  fetch-depth: 0
34
+ token: ${{ secrets.GITHUB_TOKEN }}
33
35
 
34
36
  - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
35
37
  with:
@@ -85,6 +87,43 @@ jobs:
85
87
  sed -i "0,/^version = \".*\"/s//version = \"${VERSION}\"/" pyproject.toml
86
88
  sed -i "/^\[tool.commitizen\]/,/^\[/ s/^version = \".*\"/version = \"${VERSION}\"/" pyproject.toml
87
89
 
90
+ - name: Open version bump PR
91
+ if: ${{ steps.version.outputs.deploy == 'true' }}
92
+ env:
93
+ VERSION: ${{ steps.version.outputs.version }}
94
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
95
+ shell: bash
96
+ run: |
97
+ set -euo pipefail
98
+ git config user.name "github-actions[bot]"
99
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
100
+
101
+ BRANCH="docs/release-v${VERSION}"
102
+ git checkout -B "${BRANCH}"
103
+
104
+ if [ -f CHANGELOG_RELEASE.md ]; then
105
+ HEADER=$(head -1 CHANGELOG_RELEASE.md)
106
+ if ! grep -qF "${HEADER}" CHANGELOG.md; then
107
+ cat CHANGELOG_RELEASE.md CHANGELOG.md > CHANGELOG_MERGED.md
108
+ mv CHANGELOG_MERGED.md CHANGELOG.md
109
+ fi
110
+ fi
111
+
112
+ git add pyproject.toml CHANGELOG.md
113
+ git diff --staged --quiet && exit 0
114
+ git commit -m "chore(release): bump version to ${VERSION}"
115
+ git push origin "${BRANCH}" --force
116
+
117
+ if ! gh pr list --head "${BRANCH}" --state open --json number --jq '.[0].number' | grep -qE '^[0-9]+$'; then
118
+ gh pr create \
119
+ --title "chore(release): bump version to ${VERSION}" \
120
+ --body "Automated version bump and changelog update after release v${VERSION}." \
121
+ --base master \
122
+ --head "${BRANCH}"
123
+ fi
124
+
125
+ gh pr merge "${BRANCH}" --squash --auto --delete-branch
126
+
88
127
  - name: Build package
89
128
  if: ${{ steps.version.outputs.deploy == 'true' }}
90
129
  shell: bash
@@ -19,6 +19,7 @@ htmlcov/
19
19
  docs/__pycache__/
20
20
  .claude/
21
21
  .claude.md
22
+ CLAUDE.md
22
23
  AGENTS.md
23
24
 
24
25
  # Internal discussion docs (not part of distributable source)
@@ -13,3 +13,9 @@ python:
13
13
  - requirements: docs/requirements.txt
14
14
  - method: pip
15
15
  path: .
16
+ extra_requirements:
17
+ - rest
18
+ - sqlalchemy
19
+ - cache
20
+ - config
21
+ - prometheus
@@ -1,43 +1,109 @@
1
- # 🚀 Release 0.2.1 ([#12](https://github.com/the-reacher-data/loom-py/pull/12)) ([`87f7d1f`](https://github.com/the-reacher-data/loom-py/commit/87f7d1f1eb1ccde71d0aca1c5584b83317e30707))
1
+ # 🚀 Release 0.4.0 ([#18](https://github.com/the-reacher-data/loom-py/pull/18)) ([`09e5aa3`](https://github.com/the-reacher-data/loom-py/commit/09e5aa340f88e0488daca2bf10320aad7aebbe1d))
2
2
 
3
3
 
4
4
  ## ✨ Features
5
- ### logger
6
- - **logger:** support per-logger levels from config
5
+ ### etl
6
+ - **etl:** add IntoHistory builder and SCD Type 2 domain contracts
7
7
 
8
- ### repository
9
- - **repository:** generalize main repo registration for loom structs
10
8
 
11
9
 
12
- ## 🐛 Fixes
13
- ### rest
14
- - **rest:** serialize pagination envelopes in camel case
15
- - **rest:** support loom structs in autocrud tests
16
10
 
17
- ### prometheus
18
- - **prometheus:** expose metrics at exact path
19
11
 
20
- ### review
21
- - **review:** apply quick-fix pass from code review
12
+
13
+
14
+
15
+
16
+
17
+
18
+ # 🚀 Release 0.3.0 ([#14](https://github.com/the-reacher-data/loom-py/pull/14)) ([`ef414c5`](https://github.com/the-reacher-data/loom-py/commit/ef414c5bfd303296af450840318dfbe9d301e5d1))
19
+
20
+
21
+ ## ✨ Features
22
+ ### config
23
+ - **config:** add cloud URI support and pluggable resolver extension point<br>
24
+ > Add fsspec as a hard dependency of loom[config]
25
+ > load_config() now accepts s3://, gs://, abfss://, r2:// URIs via fsspec
26
+ > Add ConfigResolver protocol for pluggable ${prefix:key} resolution at
27
+ > parse time (enables SSM, Key Vault, etc. without baking secrets into images)
28
+ > Resolver registration is idempotent; resolvers are evaluated at job startup
29
+ > so secret rotation takes effect on the next run
30
+ > Migrate loom.etl.runner.config_loader to use core load_config, removing
31
+ > the parallel OmegaConf implementation
32
+ > ETL _load_yaml inherits cloud URI and resolver support transparently
33
+
34
+
35
+ ### etl
36
+ - **etl:** add FileLocator with explicit alias API for file routes<br>
37
+ > Introduces `FileLocator` protocol and `MappingFileLocator` so that
38
+ > `FromFile.alias("name")` / `IntoFile.alias("name")` specs resolve at
39
+ > runtime through `storage.files` config rather than hard-coded URIs.
40
+ > `FileLocation` / `FileLocator` / `MappingFileLocator` in `storage/_file_locator.py`
41
+ > `StorageConfig.to_file_locator()` returns `MappingFileLocator | None`
42
+ > (None when `files` is empty — no conditional needed at call sites)
43
+ > `FromFile.alias()` / `IntoFile.alias()` classmethods set `is_alias=True`
44
+ > on the emitted spec
45
+ > `is_alias: bool` added to `FileSourceSpec` and `FileSpec`
46
+ > Polars and Spark backends resolve aliases via injected `file_locator`
47
+ > Both providers wired: `file_locator = config.to_file_locator()`
48
+ > Full test coverage across io, storage, and backend layers
49
+
50
+
51
+
52
+ ## 🐛 Fixes
53
+ ### observability
54
+ - **observability:** honor missing table policy for record store writers
22
55
 
23
56
 
24
57
  ## 📖 Documentation
25
- ### repository
26
- - **repository:** align custom repo examples
58
+ ### etl
59
+ - **etl:** keep only user guide and drop refactor docs
60
+ - **etl:** expand ETL documentation and update directory table<br>
61
+ > Add dummy-loom-etl companion repo link in README and etl guide
62
+ > Expand README subpaths table with loom.etl and loom.core.config entries
63
+ > Add FileLocator/alias API, cloud config URI, and ConfigResolver sections to etl guide
64
+ > Add loom.etl.backends (polars + spark) to etl.rst API reference
65
+ > Add loom.core.config to core.rst API reference
66
+
27
67
 
28
68
 
29
69
 
30
70
  ## ♻️ Refactor
31
- ### repository
32
- - **repository:** clarify sqlalchemy registration builder
33
- - **repository:** inject default repository builder
34
- - **repository:** simplify registration module
71
+ ### stepsql
72
+ - **stepsql:** delegate SQL execution to backend readers
73
+
74
+
75
+
76
+
35
77
 
78
+ # 🚀 Release 0.2.1 ([#12](https://github.com/the-reacher-data/loom-py/pull/12)) ([`87f7d1f`](https://github.com/the-reacher-data/loom-py/commit/87f7d1f1eb1ccde71d0aca1c5584b83317e30707))
36
79
 
80
+ ## ✨ Features
37
81
 
82
+ ### logger
83
+ - **logger:** support per-logger levels from config<br>
84
+ > `LoomConfig` now accepts a `loggers` mapping to override the log level per named logger. Resolves `structlog` / stdlib incompatibility when mixing loom-managed and third-party loggers.
85
+
86
+ ### repository
87
+ - **repository:** generalize main repo registration for loom structs<br>
88
+ > `repository_for` is now importable from `loom.core.repository` (top-level). The SQLAlchemy-specific import path still works but is no longer the canonical one.
38
89
 
90
+ ## 🐛 Bug Fixes
91
+
92
+ ### rest
93
+ - **rest:** serialize pagination envelopes in camel case<br>
94
+ > `PageResult` and list-envelope responses were serialized in snake_case. All envelope fields now follow the camelCase contract of the HTTP layer.
95
+ - **rest:** support loom structs in autocrud tests<br>
96
+ > Auto-CRUD route generation was not exercising the `msgspec.Struct` code path in integration tests.
97
+
98
+ ### prometheus
99
+ - **prometheus:** expose metrics at exact path<br>
100
+ > Metrics endpoint was registered with a trailing-slash variant that did not match the documented `/metrics` path.
39
101
 
102
+ ### docs
103
+ - **docs:** fix RTD build failure, logo and docs examples (#10, #11)<br>
104
+ > Mock `starlette`, `celery`, `kombu`, `redis` in `autodoc_mock_imports`. Logo resized to natural proportions with dark-mode safe background. Status badges added to index. Rule/Compute examples updated to named predicates.
40
105
 
106
+ ---
41
107
 
42
108
  # 🚀 Release 0.2.0 ([#9](https://github.com/the-reacher-data/loom-py/pull/9)) ([`2f669ab`](https://github.com/the-reacher-data/loom-py/commit/2f669ab205c7255eb6494e4cdb8ab8092817af62))
43
109
 
@@ -0,0 +1,15 @@
1
+ # 🚀 Release 0.4.0 ([#18](https://github.com/the-reacher-data/loom-py/pull/18)) ([`09e5aa3`](https://github.com/the-reacher-data/loom-py/commit/09e5aa340f88e0488daca2bf10320aad7aebbe1d))
2
+
3
+
4
+ ## ✨ Features
5
+ ### etl
6
+ - **etl:** add IntoHistory builder and SCD Type 2 domain contracts
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
@@ -1,3 +1,61 @@
1
+ Metadata-Version: 2.4
2
+ Name: loom-kernel
3
+ Version: 0.4.0
4
+ Summary: Loom Python project
5
+ License-File: LICENSE
6
+ Requires-Python: >=3.11
7
+ Requires-Dist: aiocache<1.0,>=0.12
8
+ Requires-Dist: msgspec<1.0,>=0.18
9
+ Requires-Dist: omegaconf<3.0,>=2.3
10
+ Requires-Dist: prometheus-client>=0.20
11
+ Requires-Dist: structlog<26.0,>=24.4
12
+ Provides-Extra: cache
13
+ Requires-Dist: aiocache<1.0,>=0.12; extra == 'cache'
14
+ Requires-Dist: omegaconf<3.0,>=2.3; extra == 'cache'
15
+ Provides-Extra: celery
16
+ Requires-Dist: celery<6.0,>=5.3; extra == 'celery'
17
+ Requires-Dist: kombu<6.0,>=5.3; extra == 'celery'
18
+ Requires-Dist: redis<6.0,>=5.0; extra == 'celery'
19
+ Provides-Extra: config
20
+ Requires-Dist: fsspec>=2024.2.0; extra == 'config'
21
+ Requires-Dist: omegaconf<3.0,>=2.3; extra == 'config'
22
+ Provides-Extra: etl-otel
23
+ Requires-Dist: opentelemetry-api<2.0,>=1.20; extra == 'etl-otel'
24
+ Requires-Dist: opentelemetry-exporter-otlp-proto-grpc<2.0,>=1.20; extra == 'etl-otel'
25
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http<2.0,>=1.20; extra == 'etl-otel'
26
+ Requires-Dist: opentelemetry-sdk<2.0,>=1.20; extra == 'etl-otel'
27
+ Provides-Extra: etl-polars
28
+ Requires-Dist: deltalake<2.0,>=1.5; extra == 'etl-polars'
29
+ Requires-Dist: fsspec>=2024.2.0; extra == 'etl-polars'
30
+ Requires-Dist: opentelemetry-api<2.0,>=1.20; extra == 'etl-polars'
31
+ Requires-Dist: opentelemetry-exporter-otlp-proto-grpc<2.0,>=1.20; extra == 'etl-polars'
32
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http<2.0,>=1.20; extra == 'etl-polars'
33
+ Requires-Dist: opentelemetry-sdk<2.0,>=1.20; extra == 'etl-polars'
34
+ Requires-Dist: polars<2.0,>=1.0; extra == 'etl-polars'
35
+ Provides-Extra: etl-spark
36
+ Requires-Dist: delta-spark<4.0,>=3.2; extra == 'etl-spark'
37
+ Requires-Dist: findspark<3.0,>=2.0; extra == 'etl-spark'
38
+ Requires-Dist: fsspec>=2024.2.0; extra == 'etl-spark'
39
+ Requires-Dist: opentelemetry-api<2.0,>=1.20; extra == 'etl-spark'
40
+ Requires-Dist: opentelemetry-exporter-otlp-proto-grpc<2.0,>=1.20; extra == 'etl-spark'
41
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http<2.0,>=1.20; extra == 'etl-spark'
42
+ Requires-Dist: opentelemetry-sdk<2.0,>=1.20; extra == 'etl-spark'
43
+ Requires-Dist: pyspark<4.0,>=3.5; extra == 'etl-spark'
44
+ Provides-Extra: prometheus
45
+ Requires-Dist: prometheus-client>=0.20; extra == 'prometheus'
46
+ Provides-Extra: pyspark
47
+ Requires-Dist: pyspark<4.0,>=3.5; extra == 'pyspark'
48
+ Provides-Extra: rest
49
+ Requires-Dist: fastapi<1.0,>=0.115; extra == 'rest'
50
+ Requires-Dist: httptools<1.0,>=0.6; extra == 'rest'
51
+ Requires-Dist: prometheus-client>=0.20; extra == 'rest'
52
+ Requires-Dist: pydantic<3.0,>=2.0; extra == 'rest'
53
+ Requires-Dist: uvicorn<1.0,>=0.30; extra == 'rest'
54
+ Requires-Dist: uvloop<1.0,>=0.21; (sys_platform != 'win32') and extra == 'rest'
55
+ Provides-Extra: sqlalchemy
56
+ Requires-Dist: sqlalchemy<3.0,>=2.0; extra == 'sqlalchemy'
57
+ Description-Content-Type: text/markdown
58
+
1
59
  <p align="center">
2
60
  <img src="docs/_static/logo-transparent.png" alt="loom-kernel" width="160" style="background:#ffffff;border-radius:6px;padding:8px 20px;" />
3
61
  </p>
@@ -20,7 +78,8 @@ Framework-agnostic Python toolkit to build backend applications with:
20
78
  - repositories decoupled from infrastructure
21
79
  - REST/FastAPI adapters with OpenAPI generation
22
80
  - background jobs and Celery workers, first-class
23
- - testing utilities for business workflows
81
+ - **declarative ETL** — compile-time-validated pipelines for Polars and Spark
82
+ - testing utilities for business workflows and ETL steps
24
83
 
25
84
  ## Purpose
26
85
 
@@ -35,7 +94,8 @@ infrastructure (DB, cache, transport) without breaking business logic.
35
94
 
36
95
  - Usage guides and architecture docs are available in the `docs/` site.
37
96
  - API reference is autogenerated from public docstrings.
38
- - End-to-end demo application: [`dummy-loom`](https://github.com/the-reacher-data/dummy-loom).
97
+ - End-to-end REST demo: [`dummy-loom`](https://github.com/the-reacher-data/dummy-loom).
98
+ - End-to-end ETL demo: [`dummy-loom-etl`](https://github.com/the-reacher-data/dummy-loom-etl) — full Polars and Spark pipeline examples.
39
99
 
40
100
  ## Main subpaths
41
101
 
@@ -47,10 +107,23 @@ infrastructure (DB, cache, transport) without breaking business logic.
47
107
  | `src/loom/core/repository/sqlalchemy` | Concrete async SQLAlchemy repository implementation. |
48
108
  | `src/loom/core/model` | Base model, fields, relations, and entity introspection. |
49
109
  | `src/loom/core/cache` | Decorators and cached repository with dependency invalidation. |
110
+ | `src/loom/core/config` | YAML config loader with cloud URI support and pluggable resolvers. |
50
111
  | `src/loom/rest` | Framework-agnostic REST model and route compiler. |
51
112
  | `src/loom/rest/fastapi` | Direct FastAPI integration (auto wiring and runtime router). |
52
113
  | `src/loom/prometheus` | Middleware and adapter for runtime metrics. |
53
114
  | `src/loom/testing` | Harnesses for unit/integration tests and golden tests. |
115
+ | `src/loom/etl` | Declarative ETL subsystem — pipelines, Polars/Spark backends, observability. |
116
+ | `src/loom/etl/pipeline` | `ETLStep`, `ETLProcess`, `ETLPipeline`, `StepSQL`, and `ETLParams`. |
117
+ | `src/loom/etl/declarative` | `FromTable`, `FromFile`, `IntoTable`, `IntoFile`, predicate DSL, and `params` proxy. |
118
+ | `src/loom/etl/schema` | Backend-agnostic schema model (`LoomDtype`, `ColumnSchema`, `TableRef`). |
119
+ | `src/loom/etl/storage` | Storage config, table/file locators, and route resolution. |
120
+ | `src/loom/etl/compiler` | Compile-time validation and execution plan builder. |
121
+ | `src/loom/etl/runner` | `ETLRunner` entry point and YAML config loader. |
122
+ | `src/loom/etl/checkpoint` | Step-level checkpoint store for incremental re-runs. |
123
+ | `src/loom/etl/observability` | Run/step observers, OTEL sink, structlog sink, and execution records. |
124
+ | `src/loom/etl/backends/polars` | Polars + Delta Lake reader, writer, and schema aligner. |
125
+ | `src/loom/etl/backends/spark` | Spark + Delta reader, writer, and schema aligner. |
126
+ | `src/loom/etl/testing` | `PolarsStepRunner`, `SparkStepRunner`, `ETLScenario`, and test stubs. |
54
127
 
55
128
  ## Quick start
56
129
 
@@ -380,6 +453,66 @@ For deeper references, review the integration examples under
380
453
  For a runnable full-stack sample with all patterns combined, check the companion repository
381
454
  [`dummy-loom`](https://github.com/the-reacher-data/dummy-loom).
382
455
 
456
+ ## ETL quick start
457
+
458
+ Install a backend:
459
+
460
+ ```bash
461
+ pip install "loom-kernel[etl-polars]"
462
+ # or
463
+ pip install "loom-kernel[etl-spark]"
464
+ ```
465
+
466
+ Declare a pipeline — sources, targets, and transformation logic are explicit and compile-time validated:
467
+
468
+ ```python
469
+ from datetime import date
470
+ import polars as pl
471
+ from loom.etl import ETLParams, ETLStep, ETLProcess, ETLPipeline, ETLRunner, FromTable, IntoTable
472
+
473
+ class DailyParams(ETLParams):
474
+ run_date: date
475
+
476
+ class CleanOrders(ETLStep[DailyParams]):
477
+ orders = FromTable("raw.orders").columns("id", "amount", "run_date")
478
+ target = IntoTable("staging.orders").replace()
479
+
480
+ def execute(self, params: DailyParams, *, orders: pl.LazyFrame) -> pl.LazyFrame:
481
+ return orders.filter(pl.col("amount") > 0)
482
+
483
+ class DailyProcess(ETLProcess[DailyParams]):
484
+ steps = [CleanOrders]
485
+
486
+ class DailyPipeline(ETLPipeline[DailyParams]):
487
+ processes = [DailyProcess]
488
+
489
+ runner = ETLRunner.from_yaml("config/etl.yaml")
490
+ runner.run(DailyPipeline, DailyParams(run_date=date.today()))
491
+ ```
492
+
493
+ Write modes — `replace`, `append`, `replace_partition`, `replace_partitions`, `replace_where`, `upsert` — are declared on the target, validated at compile time. Partition predicates use the `params` proxy so no values are hard-coded:
494
+
495
+ ```python
496
+ from loom.etl import params
497
+
498
+ target = IntoTable("staging.orders").replace_partition(
499
+ year=params.run_date.year,
500
+ month=params.run_date.month,
501
+ )
502
+ ```
503
+
504
+ File aliases decouple paths from pipelines — declare once in YAML, reference by name:
505
+
506
+ ```python
507
+ events = FromFile.alias("events_raw", format=Format.CSV)
508
+ target = IntoFile.alias("exports_daily", format=Format.PARQUET)
509
+ ```
510
+
511
+ For a full Polars + Spark + Delta Lake example see [`dummy-loom-etl`](https://github.com/the-reacher-data/dummy-loom-etl).
512
+ For the complete API reference and write-mode guide see the [ETL docs](https://loom-py.readthedocs.io/en/latest/guides/etl.html).
513
+
514
+ ---
515
+
383
516
  ## Performance
384
517
 
385
518
  `loom-kernel` adds zero measurable overhead at the concurrency levels typical of
@@ -1,38 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: loom-kernel
3
- Version: 0.2.1
4
- Summary: Loom Python project
5
- License-File: LICENSE
6
- Requires-Python: >=3.11
7
- Requires-Dist: aiocache<1.0,>=0.12
8
- Requires-Dist: msgspec<1.0,>=0.18
9
- Requires-Dist: omegaconf<3.0,>=2.3
10
- Requires-Dist: prometheus-client>=0.20
11
- Requires-Dist: structlog<26.0,>=24.4
12
- Provides-Extra: cache
13
- Requires-Dist: aiocache<1.0,>=0.12; extra == 'cache'
14
- Requires-Dist: omegaconf<3.0,>=2.3; extra == 'cache'
15
- Provides-Extra: celery
16
- Requires-Dist: celery<6.0,>=5.3; extra == 'celery'
17
- Requires-Dist: kombu<6.0,>=5.3; extra == 'celery'
18
- Requires-Dist: redis<6.0,>=5.0; extra == 'celery'
19
- Provides-Extra: config
20
- Requires-Dist: omegaconf<3.0,>=2.3; extra == 'config'
21
- Provides-Extra: prometheus
22
- Requires-Dist: prometheus-client>=0.20; extra == 'prometheus'
23
- Provides-Extra: pyspark
24
- Requires-Dist: pyspark<4.0,>=3.5; extra == 'pyspark'
25
- Provides-Extra: rest
26
- Requires-Dist: fastapi<1.0,>=0.115; extra == 'rest'
27
- Requires-Dist: httptools<1.0,>=0.6; extra == 'rest'
28
- Requires-Dist: prometheus-client>=0.20; extra == 'rest'
29
- Requires-Dist: pydantic<3.0,>=2.0; extra == 'rest'
30
- Requires-Dist: uvicorn<1.0,>=0.30; extra == 'rest'
31
- Requires-Dist: uvloop<1.0,>=0.21; (sys_platform != 'win32') and extra == 'rest'
32
- Provides-Extra: sqlalchemy
33
- Requires-Dist: sqlalchemy<3.0,>=2.0; extra == 'sqlalchemy'
34
- Description-Content-Type: text/markdown
35
-
36
1
  <p align="center">
37
2
  <img src="docs/_static/logo-transparent.png" alt="loom-kernel" width="160" style="background:#ffffff;border-radius:6px;padding:8px 20px;" />
38
3
  </p>
@@ -55,7 +20,8 @@ Framework-agnostic Python toolkit to build backend applications with:
55
20
  - repositories decoupled from infrastructure
56
21
  - REST/FastAPI adapters with OpenAPI generation
57
22
  - background jobs and Celery workers, first-class
58
- - testing utilities for business workflows
23
+ - **declarative ETL** — compile-time-validated pipelines for Polars and Spark
24
+ - testing utilities for business workflows and ETL steps
59
25
 
60
26
  ## Purpose
61
27
 
@@ -70,7 +36,8 @@ infrastructure (DB, cache, transport) without breaking business logic.
70
36
 
71
37
  - Usage guides and architecture docs are available in the `docs/` site.
72
38
  - API reference is autogenerated from public docstrings.
73
- - End-to-end demo application: [`dummy-loom`](https://github.com/the-reacher-data/dummy-loom).
39
+ - End-to-end REST demo: [`dummy-loom`](https://github.com/the-reacher-data/dummy-loom).
40
+ - End-to-end ETL demo: [`dummy-loom-etl`](https://github.com/the-reacher-data/dummy-loom-etl) — full Polars and Spark pipeline examples.
74
41
 
75
42
  ## Main subpaths
76
43
 
@@ -82,10 +49,23 @@ infrastructure (DB, cache, transport) without breaking business logic.
82
49
  | `src/loom/core/repository/sqlalchemy` | Concrete async SQLAlchemy repository implementation. |
83
50
  | `src/loom/core/model` | Base model, fields, relations, and entity introspection. |
84
51
  | `src/loom/core/cache` | Decorators and cached repository with dependency invalidation. |
52
+ | `src/loom/core/config` | YAML config loader with cloud URI support and pluggable resolvers. |
85
53
  | `src/loom/rest` | Framework-agnostic REST model and route compiler. |
86
54
  | `src/loom/rest/fastapi` | Direct FastAPI integration (auto wiring and runtime router). |
87
55
  | `src/loom/prometheus` | Middleware and adapter for runtime metrics. |
88
56
  | `src/loom/testing` | Harnesses for unit/integration tests and golden tests. |
57
+ | `src/loom/etl` | Declarative ETL subsystem — pipelines, Polars/Spark backends, observability. |
58
+ | `src/loom/etl/pipeline` | `ETLStep`, `ETLProcess`, `ETLPipeline`, `StepSQL`, and `ETLParams`. |
59
+ | `src/loom/etl/declarative` | `FromTable`, `FromFile`, `IntoTable`, `IntoFile`, predicate DSL, and `params` proxy. |
60
+ | `src/loom/etl/schema` | Backend-agnostic schema model (`LoomDtype`, `ColumnSchema`, `TableRef`). |
61
+ | `src/loom/etl/storage` | Storage config, table/file locators, and route resolution. |
62
+ | `src/loom/etl/compiler` | Compile-time validation and execution plan builder. |
63
+ | `src/loom/etl/runner` | `ETLRunner` entry point and YAML config loader. |
64
+ | `src/loom/etl/checkpoint` | Step-level checkpoint store for incremental re-runs. |
65
+ | `src/loom/etl/observability` | Run/step observers, OTEL sink, structlog sink, and execution records. |
66
+ | `src/loom/etl/backends/polars` | Polars + Delta Lake reader, writer, and schema aligner. |
67
+ | `src/loom/etl/backends/spark` | Spark + Delta reader, writer, and schema aligner. |
68
+ | `src/loom/etl/testing` | `PolarsStepRunner`, `SparkStepRunner`, `ETLScenario`, and test stubs. |
89
69
 
90
70
  ## Quick start
91
71
 
@@ -415,6 +395,66 @@ For deeper references, review the integration examples under
415
395
  For a runnable full-stack sample with all patterns combined, check the companion repository
416
396
  [`dummy-loom`](https://github.com/the-reacher-data/dummy-loom).
417
397
 
398
+ ## ETL quick start
399
+
400
+ Install a backend:
401
+
402
+ ```bash
403
+ pip install "loom-kernel[etl-polars]"
404
+ # or
405
+ pip install "loom-kernel[etl-spark]"
406
+ ```
407
+
408
+ Declare a pipeline — sources, targets, and transformation logic are explicit and compile-time validated:
409
+
410
+ ```python
411
+ from datetime import date
412
+ import polars as pl
413
+ from loom.etl import ETLParams, ETLStep, ETLProcess, ETLPipeline, ETLRunner, FromTable, IntoTable
414
+
415
+ class DailyParams(ETLParams):
416
+ run_date: date
417
+
418
+ class CleanOrders(ETLStep[DailyParams]):
419
+ orders = FromTable("raw.orders").columns("id", "amount", "run_date")
420
+ target = IntoTable("staging.orders").replace()
421
+
422
+ def execute(self, params: DailyParams, *, orders: pl.LazyFrame) -> pl.LazyFrame:
423
+ return orders.filter(pl.col("amount") > 0)
424
+
425
+ class DailyProcess(ETLProcess[DailyParams]):
426
+ steps = [CleanOrders]
427
+
428
+ class DailyPipeline(ETLPipeline[DailyParams]):
429
+ processes = [DailyProcess]
430
+
431
+ runner = ETLRunner.from_yaml("config/etl.yaml")
432
+ runner.run(DailyPipeline, DailyParams(run_date=date.today()))
433
+ ```
434
+
435
+ Write modes — `replace`, `append`, `replace_partition`, `replace_partitions`, `replace_where`, `upsert` — are declared on the target, validated at compile time. Partition predicates use the `params` proxy so no values are hard-coded:
436
+
437
+ ```python
438
+ from loom.etl import params
439
+
440
+ target = IntoTable("staging.orders").replace_partition(
441
+ year=params.run_date.year,
442
+ month=params.run_date.month,
443
+ )
444
+ ```
445
+
446
+ File aliases decouple paths from pipelines — declare once in YAML, reference by name:
447
+
448
+ ```python
449
+ events = FromFile.alias("events_raw", format=Format.CSV)
450
+ target = IntoFile.alias("exports_daily", format=Format.PARQUET)
451
+ ```
452
+
453
+ For a full Polars + Spark + Delta Lake example see [`dummy-loom-etl`](https://github.com/the-reacher-data/dummy-loom-etl).
454
+ For the complete API reference and write-mode guide see the [ETL docs](https://loom-py.readthedocs.io/en/latest/guides/etl.html).
455
+
456
+ ---
457
+
418
458
  ## Performance
419
459
 
420
460
  `loom-kernel` adds zero measurable overhead at the concurrency levels typical of
@@ -6,6 +6,7 @@ import os
6
6
  import sys
7
7
  from datetime import datetime
8
8
  from pathlib import Path
9
+ from typing import Any
9
10
 
10
11
  ROOT = Path(__file__).resolve().parents[1]
11
12
  SRC = ROOT / "src"
@@ -28,7 +29,7 @@ extensions = [
28
29
  ]
29
30
 
30
31
  templates_path = ["_templates"]
31
- exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
32
+ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "guides", "architecture", "examples-repo"]
32
33
 
33
34
  html_theme = "furo"
34
35
  html_static_path = ["_static"]
@@ -52,7 +53,14 @@ napoleon_google_docstring = True
52
53
  napoleon_numpy_docstring = False
53
54
 
54
55
 
55
- def _skip_duplicate_reexports(app, what, name, obj, skip, options):
56
+ def _skip_duplicate_reexports(
57
+ app: Any,
58
+ what: str,
59
+ name: str,
60
+ obj: Any,
61
+ skip: bool,
62
+ options: Any,
63
+ ) -> bool:
56
64
  """Skip known re-exported symbols that duplicate canonical API objects."""
57
65
  del what, obj, options
58
66
  current_module = app.env.temp_data.get("autodoc:module")
@@ -81,9 +89,13 @@ intersphinx_mapping = {
81
89
  autodoc_mock_imports = [
82
90
  "aiocache",
83
91
  "celery",
92
+ "deltalake",
84
93
  "fastapi",
94
+ "fsspec",
85
95
  "kombu",
86
96
  "omegaconf",
97
+ "polars",
98
+ "pyarrow",
87
99
  "prometheus_client",
88
100
  "pydantic",
89
101
  "pyspark",
@@ -94,6 +106,6 @@ autodoc_mock_imports = [
94
106
  ]
95
107
 
96
108
 
97
- def setup(app):
109
+ def setup(app: Any) -> None:
98
110
  """Register Sphinx hooks."""
99
111
  app.connect("autodoc-skip-member", _skip_duplicate_reexports)
@@ -0,0 +1,29 @@
1
+ # ETL Examples
2
+
3
+ The companion repository [`dummy-loom-etl`](https://github.com/the-reacher-data/dummy-loom-etl)
4
+ contains runnable end-to-end examples of `loom.etl` with both Polars and Spark
5
+ backends.
6
+
7
+ ## What it covers
8
+
9
+ - Polars and Spark pipeline declarations
10
+ - Delta Lake read/write modes (`replace`, `upsert`, `replace_partitions`)
11
+ - Cloud storage configuration (S3, GCS, Azure) via `fsspec`
12
+ - File aliases with `FromFile.alias` / `IntoFile.alias`
13
+ - Observability and run sinks
14
+ - Integration tests with `PolarsStepRunner` and `SparkTestSession`
15
+
16
+ ## Quick start
17
+
18
+ ```bash
19
+ git clone https://github.com/the-reacher-data/dummy-loom-etl
20
+ cd dummy-loom-etl
21
+ make test # run Polars and Spark test suites
22
+ make run # run the sample pipeline locally
23
+ ```
24
+
25
+ ## Next steps
26
+
27
+ - [ETL pipelines guide](pipelines.md)
28
+ - [ETL testing guide](testing.md)
29
+ - [API reference](../reference/api/etl)