continuo-python-runtime 0.4.1__tar.gz → 0.5.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 (140) hide show
  1. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/.github/workflows/images.yml +1 -1
  2. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/.github/workflows/security.yml +2 -2
  3. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/.gitignore +1 -0
  4. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/CHANGELOG.md +46 -0
  5. continuo_python_runtime-0.5.0/CLAUDE.md +37 -0
  6. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/PKG-INFO +4 -4
  7. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/README.md +2 -2
  8. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/postgres/pyproject.toml +2 -2
  9. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/trino/pyproject.toml +3 -3
  10. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/validation/runner.py +21 -7
  11. continuo_python_runtime-0.5.0/image-requirements-postgres.txt +2 -0
  12. continuo_python_runtime-0.5.0/image-requirements-trino.txt +2 -0
  13. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/pyproject.toml +3 -3
  14. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/template/Dockerfile +1 -1
  15. continuo_python_runtime-0.5.0/template/requirements.lock +225 -0
  16. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_validation_runner.py +87 -7
  17. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/uv.lock +38 -38
  18. continuo_python_runtime-0.4.1/docs/superpowers/plans/2026-07-31-python-runtime.md +0 -1307
  19. continuo_python_runtime-0.4.1/docs/superpowers/plans/2026-08-07-step-3b-config-three-part-hash.md +0 -852
  20. continuo_python_runtime-0.4.1/docs/superpowers/specs/2026-07-31-python-runtime-design.md +0 -273
  21. continuo_python_runtime-0.4.1/image-requirements-postgres.txt +0 -2
  22. continuo_python_runtime-0.4.1/image-requirements-trino.txt +0 -2
  23. continuo_python_runtime-0.4.1/template/requirements.lock +0 -22
  24. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/.dockerignore +0 -0
  25. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/.github/CODEOWNERS +0 -0
  26. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  27. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  28. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  29. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  30. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/.github/dependabot.yml +0 -0
  31. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/.github/workflows/ci.yml +0 -0
  32. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/.github/workflows/dco.yml +0 -0
  33. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/.github/workflows/publish-pypi.yml +0 -0
  34. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/.github/workflows/release.yml +0 -0
  35. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/.gitleaks.toml +0 -0
  36. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/CODE_OF_CONDUCT.md +0 -0
  37. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/CONTRIBUTING.md +0 -0
  38. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/DCO +0 -0
  39. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/Dockerfile.postgres +0 -0
  40. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/Dockerfile.trino +0 -0
  41. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/LICENSE +0 -0
  42. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/NOTICE +0 -0
  43. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/SECURITY.md +0 -0
  44. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/postgres/README.md +0 -0
  45. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/postgres/continuo_postgres_adapter/__init__.py +0 -0
  46. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/postgres/continuo_postgres_adapter/adapter.py +0 -0
  47. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/postgres/tests/__init__.py +0 -0
  48. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/postgres/tests/conftest.py +0 -0
  49. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/postgres/tests/test_adapter_postgres_validation.py +0 -0
  50. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/postgres/tests/test_adapter_runtime_postgres.py +0 -0
  51. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/postgres/tests/test_integration_postgres_validation.py +0 -0
  52. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/postgres/tests/test_integration_runtime_postgres.py +0 -0
  53. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/trino/README.md +0 -0
  54. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/trino/continuo_trino_adapter/__init__.py +0 -0
  55. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/trino/continuo_trino_adapter/adapter.py +0 -0
  56. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/trino/tests/__init__.py +0 -0
  57. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/trino/tests/test_adapter_runtime_trino.py +0 -0
  58. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/trino/tests/test_adapter_trino_validation.py +0 -0
  59. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/trino/tests/test_integration_runtime_trino.py +0 -0
  60. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/adapters/trino/tests/test_integration_trino_validation.py +0 -0
  61. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/__init__.py +0 -0
  62. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/cli.py +0 -0
  63. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/closure.py +0 -0
  64. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/conform.py +0 -0
  65. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/context.py +0 -0
  66. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/contract/__init__.py +0 -0
  67. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/contract/loader.py +0 -0
  68. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/contract/merge.py +0 -0
  69. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/contract/model.py +0 -0
  70. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/contract/paths.py +0 -0
  71. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/csv_loader.py +0 -0
  72. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/csv_readers/__init__.py +0 -0
  73. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/csv_readers/https.py +0 -0
  74. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/csv_readers/s3.py +0 -0
  75. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/csv_source.py +0 -0
  76. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/errors.py +0 -0
  77. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/harness.py +0 -0
  78. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/hashing.py +0 -0
  79. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/lint.py +0 -0
  80. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/types.py +0 -0
  81. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/validation/__init__.py +0 -0
  82. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/continuo_python_runtime/validation/s3.py +0 -0
  83. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/contract/LICENSE +0 -0
  84. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/contract/NOTICE +0 -0
  85. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/contract/README.md +0 -0
  86. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/contract/continuo_engine_contract/__init__.py +0 -0
  87. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/contract/continuo_engine_contract/config.py +0 -0
  88. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/contract/continuo_engine_contract/port.py +0 -0
  89. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/contract/continuo_engine_contract/result.py +0 -0
  90. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/contract/continuo_engine_contract/sql.py +0 -0
  91. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/contract/continuo_engine_contract/types.py +0 -0
  92. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/contract/pyproject.toml +0 -0
  93. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/contract/tests/__init__.py +0 -0
  94. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/contract/tests/test_config.py +0 -0
  95. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/contract/tests/test_contract_types.py +0 -0
  96. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/contract/tests/test_port.py +0 -0
  97. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/contract/tests/test_result.py +0 -0
  98. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/contract/tests/test_sql.py +0 -0
  99. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/docs/boundary-contract.md +0 -0
  100. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/scripts/check_version_bumps.py +0 -0
  101. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/scripts/security-scan.sh +0 -0
  102. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/template/.github/workflows/release.yml +0 -0
  103. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/template/Dockerfile.pip +0 -0
  104. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/template/README.md +0 -0
  105. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/template/contracts/example.yml +0 -0
  106. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/template/contracts/example_csv.yml +0 -0
  107. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/template/scripts/example.py +0 -0
  108. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/__init__.py +0 -0
  109. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/conftest.py +0 -0
  110. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/contract/__init__.py +0 -0
  111. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/contract/test_loader.py +0 -0
  112. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/contract/test_merge.py +0 -0
  113. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/contract/test_model.py +0 -0
  114. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/smoke/node_smoke/contracts/smoke.yml +0 -0
  115. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/smoke/node_smoke/scripts/smoke.py +0 -0
  116. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/smoke/postgres-stack/docker-compose.yml +0 -0
  117. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/smoke/trino-stack/catalog/iceberg.properties +0 -0
  118. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/smoke/trino-stack/docker-compose.yml +0 -0
  119. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_adapter_naming.py +0 -0
  120. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_cli.py +0 -0
  121. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_closure.py +0 -0
  122. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_conform.py +0 -0
  123. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_context.py +0 -0
  124. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_contract_loader.py +0 -0
  125. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_contract_pin_consistency.py +0 -0
  126. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_csv_loader.py +0 -0
  127. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_csv_readers_https.py +0 -0
  128. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_csv_readers_integration.py +0 -0
  129. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_csv_source.py +0 -0
  130. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_errors.py +0 -0
  131. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_harness.py +0 -0
  132. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_hashing.py +0 -0
  133. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_image_requirements_sync.py +0 -0
  134. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_image_smoke_validation.py +0 -0
  135. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_lint.py +0 -0
  136. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_no_legacy_names.py +0 -0
  137. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_package.py +0 -0
  138. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_template.py +0 -0
  139. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_types.py +0 -0
  140. {continuo_python_runtime-0.4.1 → continuo_python_runtime-0.5.0}/tests/test_validation_s3.py +0 -0
@@ -204,7 +204,7 @@ jobs:
204
204
  # they are published, spinning out every retry. (The image build itself
205
205
  # installs inside python:3.14-slim, so it is unaffected; this is only for
206
206
  # the host-side probe below.)
207
- - uses: actions/setup-python@v5
207
+ - uses: actions/setup-python@v7
208
208
  with:
209
209
  python-version: '3.14'
210
210
  - name: Wait until the pinned versions are installable from PyPI
@@ -96,7 +96,7 @@ jobs:
96
96
  - name: Upload SARIF to code scanning
97
97
  if: always()
98
98
  continue-on-error: true
99
- uses: github/codeql-action/upload-sarif@v3
99
+ uses: github/codeql-action/upload-sarif@v4
100
100
  with:
101
101
  sarif_file: sarif/
102
102
  category: gitleaks
@@ -124,7 +124,7 @@ jobs:
124
124
  - name: Upload SARIF to code scanning
125
125
  if: always()
126
126
  continue-on-error: true
127
- uses: github/codeql-action/upload-sarif@v3
127
+ uses: github/codeql-action/upload-sarif@v4
128
128
  with:
129
129
  sarif_file: sarif/
130
130
  category: trivy-fs
@@ -4,6 +4,7 @@ __pycache__/
4
4
  .venv/
5
5
  dist/
6
6
  .superpowers/
7
+ docs/superpowers/
7
8
  .pytest_cache/
8
9
  .mypy_cache/
9
10
  .ruff_cache/
@@ -5,6 +5,52 @@ follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.5.0] - 2026-09-09
9
+
10
+ ### Added
11
+
12
+ - `check_binds` validation op: EXPLAINs a dbt test's compiled SQL against the
13
+ candidate schema and creates nothing, so a test that names a dropped or
14
+ renamed column fails. Reads the SQL from `CANDIDATE_SQL_URI`, like
15
+ `build_from_sql`.
16
+
17
+ ### Changed
18
+
19
+ - `continuo-postgres-adapter` and `continuo-trino-adapter` 0.2.0 → 0.2.1.
20
+
21
+ ## [0.4.1] - 2026-08-25
22
+
23
+ ### Added
24
+
25
+ - Bring-your-own engine adapters: `continuo-postgres-adapter` and
26
+ `continuo-trino-adapter` are separate installable packages, so an install
27
+ can supply its own engine adapter independently of the runtime.
28
+ - `scripts/check_version_bumps.py`: fails a release when a package's source
29
+ changed since the last tag but its version did not.
30
+
31
+ ### Changed
32
+
33
+ - Deterministic python-node container builds: pinned per-engine
34
+ image-requirements and hashed template Dockerfiles.
35
+ - `continuo-engine-contract` 0.7.2 → 0.7.3.
36
+
37
+ ## [0.4.0] - 2026-08-21
38
+
39
+ ### Added
40
+
41
+ - `python-csv` node kind: a contract-only CSV loader (no user script) that
42
+ materializes the declared table from the contract's CSV URI, with a
43
+ validation header check.
44
+
45
+ ### Changed
46
+
47
+ - `continuo-engine-contract` 0.7.1 → 0.7.2.
48
+
49
+ ### Fixed
50
+
51
+ - `release.yml`'s github-release job now checks out the repository; without the
52
+ checkout it could not read the tag's files.
53
+
8
54
  ## [0.3.1] - 2026-08-21
9
55
 
10
56
  ### Added
@@ -0,0 +1,37 @@
1
+ # continuo-python-runtime
2
+
3
+ The validation/execution runtime that continuo's executor runs as a Kubernetes
4
+ Job. Python 3.12, uv workspace: the runtime (`continuo_python_runtime`), the
5
+ engine contract (`contract/`), and the engine adapters (`adapters/postgres`,
6
+ `adapters/trino`).
7
+
8
+ ## CHANGELOG is not optional
9
+
10
+ Every user-facing change keeps `CHANGELOG.md` current. Two steps, both required:
11
+
12
+ - **On every PR** that changes behavior, the CLI/op surface, a package version,
13
+ or a container: add a bullet under `## [Unreleased]` (Keep a Changelog style —
14
+ Added / Changed / Fixed / Removed). No entry, no merge.
15
+ - **On every release**: rename `## [Unreleased]` to `## [X.Y.Z] - YYYY-MM-DD`,
16
+ add a fresh empty `## [Unreleased]` above it, and tag. `release.yml` reads the
17
+ section matching the pushed tag for the GitHub Release notes, so a release with
18
+ no matching section ships with generic auto-notes and the changelog silently
19
+ loses that version.
20
+
21
+ If the changelog is missing a shipped version, backfill it from that tag's
22
+ merged PRs before adding anything new.
23
+
24
+ ## Releasing
25
+
26
+ A release is one `chore(release):` commit that bumps versions and updates the
27
+ changelog, then a `vX.Y.Z` tag on it. Bump the version of every package whose
28
+ source changed since the last tag — `scripts/check_version_bumps.py` fails the
29
+ PyPI publish otherwise. The tag builds and publishes the `-postgres` / `-trino`
30
+ images and the PyPI packages. See `CONTRIBUTING.md` for the full steps.
31
+
32
+ ## Conventions
33
+
34
+ - Standard `logging` for diagnostics, never `print` — except the CLI's
35
+ sentinel-framed result blocks, which own stdout.
36
+ - In-repo packages are pinned exactly, not with ranges (see `pyproject.toml`).
37
+ - Commits are signed off (`git commit -s`); CI enforces the DCO.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: continuo-python-runtime
3
- Version: 0.4.1
3
+ Version: 0.5.0
4
4
  Summary: Runtime harness, contract tooling, and CI lint for Continuo python nodes.
5
5
  Author: Simone Carolini
6
6
  Maintainer: Simone Carolini
@@ -11,7 +11,7 @@ Classifier: Development Status :: 4 - Beta
11
11
  Classifier: Intended Audience :: Developers
12
12
  Classifier: Programming Language :: Python :: 3.14
13
13
  Requires-Python: >=3.14
14
- Requires-Dist: boto3==1.43.74
14
+ Requires-Dist: boto3==1.43.85
15
15
  Requires-Dist: continuo-engine-contract==0.7.3
16
16
  Requires-Dist: pyarrow==25.0.1
17
17
  Requires-Dist: pyyaml==6.0.3
@@ -275,9 +275,9 @@ A domain repo picks its warehouse engine by which base image it builds
275
275
  `FROM`:
276
276
 
277
277
  ```dockerfile
278
- FROM ghcr.io/carolsimone/continuo-python-runtime-postgres:v0.4.1
278
+ FROM ghcr.io/carolsimone/continuo-python-runtime-postgres:v0.5.0
279
279
  # or
280
- FROM ghcr.io/carolsimone/continuo-python-runtime-trino:v0.4.1
280
+ FROM ghcr.io/carolsimone/continuo-python-runtime-trino:v0.5.0
281
281
  ```
282
282
 
283
283
  The engine is part of the image **name**; the tag is the bare version, so
@@ -255,9 +255,9 @@ A domain repo picks its warehouse engine by which base image it builds
255
255
  `FROM`:
256
256
 
257
257
  ```dockerfile
258
- FROM ghcr.io/carolsimone/continuo-python-runtime-postgres:v0.4.1
258
+ FROM ghcr.io/carolsimone/continuo-python-runtime-postgres:v0.5.0
259
259
  # or
260
- FROM ghcr.io/carolsimone/continuo-python-runtime-trino:v0.4.1
260
+ FROM ghcr.io/carolsimone/continuo-python-runtime-trino:v0.5.0
261
261
  ```
262
262
 
263
263
  The engine is part of the image **name**; the tag is the bare version, so
@@ -1,5 +1,5 @@
1
1
  [project]
2
- version = "0.2.0"
2
+ version = "0.2.1"
3
3
  name = "continuo-postgres-adapter"
4
4
  description = "Postgres warehouse adapter for Continuo: validation and python-node runtime."
5
5
  authors = [{ name = "Simone Carolini" }]
@@ -27,7 +27,7 @@ postgres = "continuo_postgres_adapter.adapter:PostgresAdapter"
27
27
 
28
28
  [dependency-groups]
29
29
  dev = [
30
- "ruff==0.16.3",
30
+ "ruff==0.16.5",
31
31
  "mypy==2.3.1",
32
32
  ]
33
33
  test = [
@@ -1,5 +1,5 @@
1
1
  [project]
2
- version = "0.2.0"
2
+ version = "0.2.1"
3
3
  name = "continuo-trino-adapter"
4
4
  description = "Trino warehouse adapter for Continuo: validation and python-node runtime."
5
5
  authors = [{ name = "Simone Carolini" }]
@@ -13,7 +13,7 @@ dependencies = [
13
13
  # newest. This adapter subclasses the contract's WarehouseAdapter port
14
14
  # directly, so the pair must stay the tested one.
15
15
  "continuo-engine-contract==0.7.3",
16
- "trino==0.338.0",
16
+ "trino==0.339.0",
17
17
  "pyarrow==25.0.1",
18
18
  ]
19
19
  classifiers = [
@@ -27,7 +27,7 @@ trino = "continuo_trino_adapter.adapter:TrinoAdapter"
27
27
 
28
28
  [dependency-groups]
29
29
  dev = [
30
- "ruff==0.16.3",
30
+ "ruff==0.16.5",
31
31
  "mypy==2.3.1",
32
32
  ]
33
33
  test = [
@@ -18,6 +18,11 @@ Dispatches on ``VALIDATION_OP`` env var (default ``build_from_sql``):
18
18
  that dropped a column the script reads fails the release gate, then the output
19
19
  table is materialized empty from the declared typed columns and the declared
20
20
  physical layout.
21
+ - ``check_binds``: for a dbt test's compiled SQL (``CANDIDATE_SQL_URI``, fetched
22
+ the same way as ``build_from_sql``). EXPLAINs it against the candidate schema
23
+ via the engine adapter and creates nothing — a test whose compiled SQL names
24
+ a column a candidate change dropped or renamed fails the release at its
25
+ source, before any table is built.
21
26
 
22
27
  The engine adapter is discovered from the single installed
23
28
  ``continuo_engine.adapters`` entry point — each runner image installs exactly one.
@@ -108,7 +113,7 @@ def load_candidate_spec() -> dict:
108
113
  return spec
109
114
 
110
115
 
111
- _NODE_OPS = ("build_from_sql", "clone_from_prod", "build_from_columns")
116
+ _NODE_OPS = ("build_from_sql", "clone_from_prod", "build_from_columns", "check_binds")
112
117
  _SCHEMA_OPS = ("ensure_schema", "drop_schema")
113
118
 
114
119
 
@@ -116,10 +121,13 @@ def main() -> None:
116
121
  """Run one validation op end to end; exits non-zero on failure.
117
122
 
118
123
  Node ops (``build_from_sql``/``clone_from_prod``/``build_from_columns``)
119
- materialize one empty node table and require ``TABLE_NAME``. Schema ops
120
- (``ensure_schema``/``drop_schema``) act on the whole candidate schema —
121
- the executor schedules them as one-shot engine-image Jobs to own the
122
- candidate-schema lifecycle without connecting to the warehouse itself —
124
+ materialize one empty node table and require ``TABLE_NAME``. ``check_binds``
125
+ is also a node op and requires ``TABLE_NAME`` (for identity only, in the
126
+ result block's ``unique_id``) but creates nothing: it bind-checks a dbt
127
+ test's compiled SQL against the candidate schema with the engine's EXPLAIN.
128
+ Schema ops (``ensure_schema``/``drop_schema``) act on the whole candidate
129
+ schema — the executor schedules them as one-shot engine-image Jobs to own
130
+ the candidate-schema lifecycle without connecting to the warehouse itself —
123
131
  and take no table.
124
132
  """
125
133
  logging.basicConfig(
@@ -139,7 +147,7 @@ def main() -> None:
139
147
  if op in _NODE_OPS:
140
148
  table = _require("TABLE_NAME")
141
149
  unique_id = _node_id() or f"model.{table}"
142
- if op == "build_from_sql":
150
+ if op in ("build_from_sql", "check_binds"):
143
151
  try:
144
152
  raw_sql = load_candidate_sql()
145
153
  except Exception as exc:
@@ -150,7 +158,7 @@ def main() -> None:
150
158
  if not raw_sql:
151
159
  logger.error(
152
160
  "CANDIDATE_SQL_URI is unset or the object is empty for a "
153
- "build_from_sql node; cannot validate"
161
+ "%s node; cannot validate", op
154
162
  )
155
163
  print(result.result_block("error", "CANDIDATE_SQL_URI is unset or empty",
156
164
  unique_id=unique_id), flush=True)
@@ -238,6 +246,12 @@ def main() -> None:
238
246
  if op == "build_from_sql":
239
247
  assert candidate_sql is not None, "candidate_sql must be set for build_from_sql"
240
248
  adapter.build_empty_from_sql(schema, table, candidate_sql)
249
+ elif op == "check_binds":
250
+ # A dbt test: EXPLAIN its compiled SQL against the candidate
251
+ # schema. A dropped or renamed column fails here; no table is
252
+ # created and no row is read.
253
+ assert candidate_sql is not None, "candidate_sql must be set for check_binds"
254
+ adapter.check_binds(candidate_sql)
241
255
  elif op == "build_from_columns":
242
256
  assert spec is not None, "spec must be set for build_from_columns"
243
257
  if csv_source:
@@ -0,0 +1,2 @@
1
+ continuo-python-runtime==0.5.0
2
+ continuo-postgres-adapter==0.2.1
@@ -0,0 +1,2 @@
1
+ continuo-python-runtime==0.5.0
2
+ continuo-trino-adapter==0.2.1
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "continuo-python-runtime"
3
- version = "0.4.1"
3
+ version = "0.5.0"
4
4
  description = "Runtime harness, contract tooling, and CI lint for Continuo python nodes."
5
5
  authors = [{ name = "Simone Carolini" }]
6
6
  maintainers = [{ name = "Simone Carolini" }]
@@ -20,7 +20,7 @@ dependencies = [
20
20
  # contract version never exists without a new runtime version to match it;
21
21
  # an exact pin therefore costs nothing and keeps the tested pair together.
22
22
  "continuo-engine-contract==0.7.3",
23
- "boto3==1.43.74",
23
+ "boto3==1.43.85",
24
24
  "pyarrow==25.0.1",
25
25
  "PyYAML==6.0.3",
26
26
  # Pinned in lockstep with continuo-engine-contract's OWN sqlglot pin
@@ -45,7 +45,7 @@ classifiers = [
45
45
  continuo-runtime = "continuo_python_runtime.cli:main"
46
46
 
47
47
  [dependency-groups]
48
- dev = ["ruff==0.16.3", "mypy==2.3.1", "types-PyYAML==6.0.12.20250915"]
48
+ dev = ["ruff==0.16.5", "mypy==2.3.1", "types-PyYAML==6.0.12.20250915"]
49
49
  test = ["pytest==9.1.1", "pytest-cov==7.1.0"]
50
50
 
51
51
  [build-system]
@@ -1,5 +1,5 @@
1
1
  # Tags are v<version>; one image per engine (continuo-python-runtime-postgres / -trino).
2
- FROM ghcr.io/carolsimone/continuo-python-runtime-postgres:v0.4.1
2
+ FROM ghcr.io/carolsimone/continuo-python-runtime-postgres:v0.5.0
3
3
  COPY contracts/ /app/contracts/
4
4
  COPY scripts/ /app/scripts/
5
5
  # COPY every OTHER directory your scripts import from, too. CI folds a script's
@@ -0,0 +1,225 @@
1
+ # This file was autogenerated by uv via the following command:
2
+ # uv pip compile --generate-hashes --python-version 3.14 --no-annotate - -o template/requirements.lock
3
+ #
4
+ # Shape-2 example lock for the POSTGRES engine (continuo-postgres-adapter),
5
+ # matching Shape 1's Dockerfile. For a different engine or versions, rerun the
6
+ # command above with your pins — see template/README.md.
7
+ boto3==1.43.74 \
8
+ --hash=sha256:9d4d0dcf81c941cfe7d927486435521e0f3bf657cb68b10dfe445cfe311f8839 \
9
+ --hash=sha256:d7f6a921efbda61ed787b403df8b64a95bc66e66299e9772fc40c235c28a5bde
10
+ botocore==1.43.79 \
11
+ --hash=sha256:19b2c772ea2590d0baad6ae004a0e478cf2c982e0e6a39c8e2f882d9b2981445 \
12
+ --hash=sha256:dcc0a97b65affcef80e0499745d2e6a5d120253c11b8727b8227df44ab3e958f
13
+ continuo-engine-contract==0.7.3 \
14
+ --hash=sha256:06c56389e47af4712d2307b2ec5babd50e0d1ee58a1163360979dc3b41e3bfdd \
15
+ --hash=sha256:110edd77634ab169bf870f7815bda90f541f74c45110a43be471b5ba3937069c
16
+ continuo-postgres-adapter==0.2.0 \
17
+ --hash=sha256:2f6a25e1f0ef986d3f88f24e36800df230931f5bfc317ba018ef45bc74e8ae51 \
18
+ --hash=sha256:f89b9c755895ec511583d8bc7f3ef3be2827ca63b863ac9210df89bb60b8b0f3
19
+ continuo-python-runtime==0.4.1 \
20
+ --hash=sha256:a7dae6116f7ae162361a00dee0b2a7837cc94bb1a7df7b47ef6d6db33db15f2b \
21
+ --hash=sha256:faf06c38465537d65f3a71db6ab46e2461403f342366e0f843f996159b4aebd4
22
+ jmespath==1.1.0 \
23
+ --hash=sha256:472c87d80f36026ae83c6ddd0f1d05d4e510134ed462851fd5f754c8c3cbb88d \
24
+ --hash=sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64
25
+ psycopg2-binary==2.9.12 \
26
+ --hash=sha256:00814e40fa23c2b37ef0a1e3c749d89982c73a9cb5046137f0752a22d432e82f \
27
+ --hash=sha256:049366c6d884bdcd65d66e6ca1fdbebe670b56c6c9ba46f164e6667e90881964 \
28
+ --hash=sha256:0dc9228d47c46bda253d2ecd6bb93b56a9f2d7ad33b684a1fa3622bf74ffe30c \
29
+ --hash=sha256:1006fb62f0f0bc5ce256a832356c6262e91be43f5e4eb15b5eaf38079464caf2 \
30
+ --hash=sha256:127467c6e476dd876634f17c3d870530e73ff454ff99bff73d36e80af28e1115 \
31
+ --hash=sha256:1c8ad4c08e00f7679559eaed7aff1edfffc60c086b976f93972f686384a95e2c \
32
+ --hash=sha256:29d4d134bd0ab46ffb04e94aa3c5fa3ef582e9026609165e2f758ff76fc3a3be \
33
+ --hash=sha256:3471336e1acfd9c7fe507b8bad5af9317b6a89294f9eb37bd9a030bb7bebcdc6 \
34
+ --hash=sha256:36512911ebb2b60a0c3e44d0bb5048c1980aced91235d133b7874f3d1d93487c \
35
+ --hash=sha256:398fcd4db988c7d7d3713e2b8e18939776fd3fb447052daae4f24fa39daede4c \
36
+ --hash=sha256:3d999bd982a723113c1a45b55a7a6a90d64d0ed2278020ed625c490ff7bef96c \
37
+ --hash=sha256:40e7b28b63aaf737cb3a1edc3a9bbc9a9f4ad3dcb7152e8c1130e4050eddcb7d \
38
+ --hash=sha256:411e85815652d13560fbe731878daa5d92378c4995a22302071890ec3397d019 \
39
+ --hash=sha256:4413d0caef93c5cf50b96863df4c2efe8c269bf2267df353225595e7e15e8df7 \
40
+ --hash=sha256:4766ab678563054d3f1d064a4db19cc4b5f9e3a8d9018592a8285cf200c248f3 \
41
+ --hash=sha256:4dfcf8e45ebb0c663be34a3442f65e17311f3367089cd4e5e3a3e8e62c978777 \
42
+ --hash=sha256:527e6342b3e44c2f0544f6b8e927d60de7f163f5723b8f1dfa7d2a84298738cd \
43
+ --hash=sha256:54a0dfecab1b48731f934e06139dfe11e24219fb6d0ceb32177cf0375f14c7b5 \
44
+ --hash=sha256:5a0253224780c978746cb9be55a946bcdaf40fe3519c0f622924cdabdafe2c39 \
45
+ --hash=sha256:5ac9444edc768c02a6b6a591f070b8aae28ff3a99be57560ac996001580f294c \
46
+ --hash=sha256:5c7cb4cbf894a1d36c720d713de507952c7c58f66d30834708f03dbe5c822ccf \
47
+ --hash=sha256:5c8ce6c61bd1b1f6b9c24ee32211599f6166af2c55abb19456090a21fd16554b \
48
+ --hash=sha256:5cdc05117180c5fa9c40eea8ea559ce64d73824c39d928b7da9fb5f6a9392433 \
49
+ --hash=sha256:612b965daee295ae2da8f8218ce1d274645dc76ef3f1abf6a0a94fd57eff876d \
50
+ --hash=sha256:63a3ebbd543d3d1eda088ac99164e8c5bac15293ee91f20281fd17d050aee1c4 \
51
+ --hash=sha256:66a7685d7e548f10fb4ce32fb01a7b7f4aa702134de92a292c7bd9e0d3dbd290 \
52
+ --hash=sha256:6f3b3de8a74ef8db215f22edffb19e32dc6fa41340456de7ec99efdc8a7b3ec2 \
53
+ --hash=sha256:6f9cae1f848779b5b01f417e762c40d026ea93eb0648249a604728cda991dde3 \
54
+ --hash=sha256:718e1fc18edf573b02cb8aea868de8d8d33f99ce9620206aa9144b67b0985e94 \
55
+ --hash=sha256:77b348775efd4cdab410ec6609d81ccecd1139c90265fa583a7255c8064bc03d \
56
+ --hash=sha256:7af18183109e23502c8b2ae7f6926c0882766f35b5175a4cd737ad825e4d7a1b \
57
+ --hash=sha256:7c729a73c7b1b84de3582f73cdd27d905121dc2c531f3d9a3c32a3011033b965 \
58
+ --hash=sha256:83946ba43979ebfdc99a3cd0ee775c89f221df026984ba19d46133d8d75d3cd9 \
59
+ --hash=sha256:840066105706cd2eb29b9a1c2329620056582a4bf3e8169dec5c447042d0869f \
60
+ --hash=sha256:863f5d12241ebe1c76a72a04c2113b6dc905f90b9cef0e9be0efd994affd9354 \
61
+ --hash=sha256:864c261b3690e1207d14bbfe0a61e27567981b80c47a778561e49f676f7ce433 \
62
+ --hash=sha256:89d19a9f7899e8eb0656a2b3a08e0da04c720a06db6e0033eab5928aabe60fa9 \
63
+ --hash=sha256:8ffdb59fe88f99589e34354a130217aa1fd2d615612402d6edc8b3dbc7a44463 \
64
+ --hash=sha256:96937c9c5d891f772430f418a7a8b4691a90c3e6b93cf72b5bd7cad8cbca32a5 \
65
+ --hash=sha256:98062447aebc20ed20add1f547a364fd0ef8933640d5372ff1873f8deb9b61be \
66
+ --hash=sha256:995ce929eede89db6254b50827e2b7fd61e50d11f0b116b29fffe4a2e53c4580 \
67
+ --hash=sha256:9b818ceff717f98851a64bffd4c5eb5b3059ae280276dcecc52ac658dcf006a4 \
68
+ --hash=sha256:9fe06d93e72f1c048e731a2e3e7854a5bfaa58fc736068df90b352cefe66f03f \
69
+ --hash=sha256:a46fe069b65255df410f856d842bc235f90e22ffdf532dda625fd4213d3fd9b1 \
70
+ --hash=sha256:a7e39a65b7d2a20e4ba2e0aaad1960b61cc2888d6ab047769f8347bd3c9ad915 \
71
+ --hash=sha256:a99eaab34a9010f1a086b126de467466620a750634d114d20455f3a824aae033 \
72
+ --hash=sha256:ab29414b25dcb698bf26bf213e3348abdcd07bbd5de032a5bec15bd75b298b03 \
73
+ --hash=sha256:ace94261f43850e9e79f6c56636c5e0147978ab79eda5e5e5ebf13ae146fc8fe \
74
+ --hash=sha256:b4a9eaa6e7f4ff91bec10aa3fb296878e75187bced5cc4bafe17dc40915e1326 \
75
+ --hash=sha256:b6937f5fe4e180aeee87de907a2fa982ded6f7f15d7218f78a083e4e1d68f2a0 \
76
+ --hash=sha256:b9a339b79d37c1b45f3235265f07cdeb0cb5ad7acd2ac7720a5920989c17c24e \
77
+ --hash=sha256:ba3df2fc42a1cfa45b72cf096d4acb2b885937eedc61461081d53538d4a82a86 \
78
+ --hash=sha256:c41321a14dd74aceb6a9a643b9253a334521babfa763fa873e33d89cfa122fb5 \
79
+ --hash=sha256:c5ee5213445dd45312459029b8c4c0a695461eb517b753d2582315bd07995f5e \
80
+ --hash=sha256:c6528cefc8e50fcc6f4a107e27a672058b36cc5736d665476aeb413ba88dbb06 \
81
+ --hash=sha256:cb4a1dacdd48077150dc762a9e5ddbf32c256d66cb46f80839391aa458774936 \
82
+ --hash=sha256:cfa2517c94ea3af6deb46f81e1bbd884faa63e28481eb2f889989dd8d95e5f03 \
83
+ --hash=sha256:d2fa0d7caca8635c56e373055094eeda3208d901d55dd0ff5abc1d4e47f82b56 \
84
+ --hash=sha256:d3227a3bc228c10d21011a99245edca923e4e8bf461857e869a507d9a41fe9f6 \
85
+ --hash=sha256:d6fcbba8c9fed08a73b8ac61ea79e4821e45b1e92bb466230c5e746bbf3d5256 \
86
+ --hash=sha256:e4e184b1fb6072bf05388aa41c697e1b2d01b3473f107e7ec44f186a32cfd0b8 \
87
+ --hash=sha256:ee2d84ef5eb6c04702d2e9c372ad557fb027f26a5d82804f749dfb14c7fdd2ab \
88
+ --hash=sha256:f12ae41fcafadb39b2785e64a40f9db05d6de2ac114077457e0e7c597f3af980 \
89
+ --hash=sha256:f625abb7020e4af3432d95342daa1aa0db3fa369eed19807aa596367ba791b10 \
90
+ --hash=sha256:f921f3cd87035ef7df233383011d7a53ea1d346224752c1385f1edfd790ceb6a \
91
+ --hash=sha256:fb1828cf3da68f99e45ebce1355d65d2d12b6a78fb5dfb16247aad6bdef5f5d2 \
92
+ --hash=sha256:ffdd7dc5463ccd61845ac37b7012d0f35a1548df9febe14f8dd549be4a0bc81e
93
+ pyarrow==25.0.1 \
94
+ --hash=sha256:0b1edbb2f385a6a65e9711b62ba86ac54a7816a3f8d17bb3e8a5929d65fb2485 \
95
+ --hash=sha256:0b726ad7e7b669be982b0c71c07fe4b037d654354130da79a7902a669e93a66b \
96
+ --hash=sha256:0befcf816e45a1af33ac775a9970b749e4868a230c7372f0ae5e932bee27039f \
97
+ --hash=sha256:0fe7c8b6c03969b49c8c66182e4a18e3819ab92d07cfab5d8370c531b9369ef0 \
98
+ --hash=sha256:119297a6dc197e45d9c6d4415f7814a67ffa36c180d26f68c154c58067ae782d \
99
+ --hash=sha256:169d3429d5be7c752125890620f75a60776d38b0035eddae939651640822332e \
100
+ --hash=sha256:25f8720bf6387d5dc2ebd2622112de630760419e4b66134405dd24110d15f37e \
101
+ --hash=sha256:31e49a7888fcdf3a835da33ae777f6bb9a866334e5a789282fc26dcf426f7f15 \
102
+ --hash=sha256:35935cd5de130aa5cf4dea052a63e6bf2e17006c35c3a468194242b9b2bf5956 \
103
+ --hash=sha256:38a9a4b4b9613380e200641891495a56c3d5a98a092db4a870af9975e220471d \
104
+ --hash=sha256:3f89685964f46e4216103c75483aac0c0692a5f72212d7ca835adba5ede56ce3 \
105
+ --hash=sha256:4288f27577352d608ca08553b0865e4a9b3aa14820c5d95b53337218d609835b \
106
+ --hash=sha256:4340f0ba6c1d2e13f21658de1d7c662ca2545018568d0030a1e9afca159d87e3 \
107
+ --hash=sha256:44a9120ce5bd81936b8ab9a88076e3fd47c2c6838e0e43630fed83626aca81d9 \
108
+ --hash=sha256:4facd65742a024a4a366328a1d2292062d72d6e023c1b7dda8d4c37544933a25 \
109
+ --hash=sha256:51093dd9e10325fbdb3c10a2ae7c4806e5c822d94e74ae4938b26524a3323fee \
110
+ --hash=sha256:514ddb60285631af068875550c90eddc181db3e8e63a032b1559be189e82f056 \
111
+ --hash=sha256:5389cdf79447ed1515c9e31620e6e1e2302249564d603f2ad727d4f6d313e4c3 \
112
+ --hash=sha256:59a2de54c0cbd954da861eee4d1d330f8e909c45b53455baef696380f2c55033 \
113
+ --hash=sha256:60e89d8f13861a1f7f8d950fa54aebb8023b30734d0ac51ffa80beabe2df4bba \
114
+ --hash=sha256:6109c94d8b9f3b17a041daca16cacb2f651ad8f1ef70a4232c2c0f37a23da2a8 \
115
+ --hash=sha256:62cd0d785b8aa6675ee355f9fc02252a340f4441257c42674937826fd7594325 \
116
+ --hash=sha256:6943e2fe7954d29d84de45d29d34c8dc36ce96570e67d89aa9976e650a4a9138 \
117
+ --hash=sha256:6a1fdfc6659b6b19022f2e50627fb5cf7156a66c46bf4299379955cbe742382a \
118
+ --hash=sha256:880523be3d29efcf83d3998835d206118ccf35e3871dbd2fb60408cf6b007a80 \
119
+ --hash=sha256:8858d7bfc22e3f51529aeaa4077225029724623e4595dc9eff8c793935c34140 \
120
+ --hash=sha256:9150a83248bfed9813ea3c3af74c3856c1984d444aa28e58bf7733b9750ddf6a \
121
+ --hash=sha256:9171748cdf796972d85a4b60157c279913e242992e350c90c7450182a9838b2a \
122
+ --hash=sha256:a4d6d5e9a3d1879a97c08ded0c797579b7965eafd0f0c26c30b45ccc06db939b \
123
+ --hash=sha256:a4dd8bf99a8fac133efc0ed6a92f5fddbe2adba0d0f6dd720e39ba9855cea85c \
124
+ --hash=sha256:aa0559502e1cd6254d6814614085dd9c5a3dd0419362978a936a3f68a9e5c3df \
125
+ --hash=sha256:b7a296aac7a71fa0886c08e155ddb6c636a50013f801f6178daafa0f9e726188 \
126
+ --hash=sha256:bddd0c4f7630c2a3ddf6347c1bdaa79d97bcf6bd445f9e60c816b7d77c85a5ae \
127
+ --hash=sha256:bf0b672390cdcb640d7288f96b826d71ff4e9abb254a86c89890baf51a29cee6 \
128
+ --hash=sha256:c7c534ec03c358a76ea3e505e74c1b6aef290af90c444dfd092dbfe23e755b85 \
129
+ --hash=sha256:cab40b1edfef0262e0e5251aa2c58d75630f24d06dd7794480243acc001a1d7d \
130
+ --hash=sha256:cc4aa407fde9fc660be3939e49ea31f50f3e9fec17c0ec63159f7711edd3efc9 \
131
+ --hash=sha256:d51592cb7561e87877c506113e7adbf1342ab579e6c21f0ef44b8ba41cb74c80 \
132
+ --hash=sha256:dda9470024204d7bbf2042b47c6e8a0e47a3eeb8e34405882dfaea6577e0c153 \
133
+ --hash=sha256:df961f2e7ae9cf496459259d798652c70625f6c080650d6952f8c04053c58ee9 \
134
+ --hash=sha256:eb6203482ff3746a5632303a7279ae0b5a304c46985b49ed1378cb350ea6728d \
135
+ --hash=sha256:f3831aaa25c67a99f99dc8b05873cb9d64560390372e2aa197ce9dd4a3f06a44 \
136
+ --hash=sha256:f729cfdbd36fd99d543b67a914d2de044c84ebe45be8b34902b299b608c15c8f
137
+ python-dateutil==2.9.0.post0 \
138
+ --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \
139
+ --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427
140
+ pyyaml==6.0.3 \
141
+ --hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \
142
+ --hash=sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a \
143
+ --hash=sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3 \
144
+ --hash=sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956 \
145
+ --hash=sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6 \
146
+ --hash=sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c \
147
+ --hash=sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65 \
148
+ --hash=sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a \
149
+ --hash=sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0 \
150
+ --hash=sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b \
151
+ --hash=sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1 \
152
+ --hash=sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6 \
153
+ --hash=sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7 \
154
+ --hash=sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e \
155
+ --hash=sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007 \
156
+ --hash=sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310 \
157
+ --hash=sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4 \
158
+ --hash=sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9 \
159
+ --hash=sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295 \
160
+ --hash=sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea \
161
+ --hash=sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0 \
162
+ --hash=sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e \
163
+ --hash=sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac \
164
+ --hash=sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9 \
165
+ --hash=sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7 \
166
+ --hash=sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35 \
167
+ --hash=sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb \
168
+ --hash=sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b \
169
+ --hash=sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69 \
170
+ --hash=sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5 \
171
+ --hash=sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b \
172
+ --hash=sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c \
173
+ --hash=sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369 \
174
+ --hash=sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd \
175
+ --hash=sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824 \
176
+ --hash=sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198 \
177
+ --hash=sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065 \
178
+ --hash=sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c \
179
+ --hash=sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c \
180
+ --hash=sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764 \
181
+ --hash=sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196 \
182
+ --hash=sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b \
183
+ --hash=sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00 \
184
+ --hash=sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac \
185
+ --hash=sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8 \
186
+ --hash=sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e \
187
+ --hash=sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28 \
188
+ --hash=sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3 \
189
+ --hash=sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5 \
190
+ --hash=sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4 \
191
+ --hash=sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b \
192
+ --hash=sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf \
193
+ --hash=sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5 \
194
+ --hash=sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702 \
195
+ --hash=sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8 \
196
+ --hash=sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788 \
197
+ --hash=sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da \
198
+ --hash=sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d \
199
+ --hash=sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc \
200
+ --hash=sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c \
201
+ --hash=sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba \
202
+ --hash=sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f \
203
+ --hash=sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917 \
204
+ --hash=sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5 \
205
+ --hash=sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26 \
206
+ --hash=sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f \
207
+ --hash=sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b \
208
+ --hash=sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be \
209
+ --hash=sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c \
210
+ --hash=sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3 \
211
+ --hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \
212
+ --hash=sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926 \
213
+ --hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0
214
+ s3transfer==0.19.2 \
215
+ --hash=sha256:ba0309fd86be3c27dbf78cdd813c13c5e1df16e5874b99d2535ebbdfb9892993 \
216
+ --hash=sha256:d8168eccca828cbb2cd573675333f3bddd254313a9c42494b84c76b539e8ba25
217
+ six==1.17.0 \
218
+ --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
219
+ --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81
220
+ sqlglot==30.17.0 \
221
+ --hash=sha256:2d6b8def93304fa300f4d20f48e3909e7f436fda56ca1fafd8975f6c561ef62c \
222
+ --hash=sha256:84435ac283a60173da31b5fd7d11a725037a1c3fd6ed1e21fb065de74ddb579f
223
+ urllib3==2.7.0 \
224
+ --hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \
225
+ --hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897