continuo-python-runtime 0.10.0__tar.gz → 0.12.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 (237) hide show
  1. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/image-build.yml +7 -1
  2. continuo_python_runtime-0.12.0/.python-version +1 -0
  3. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/CHANGELOG.md +213 -0
  4. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/CLAUDE.md +12 -8
  5. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/CONTRIBUTING.md +1 -1
  6. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/Dockerfile.duckdb +9 -22
  7. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/Dockerfile.postgres +11 -34
  8. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/Dockerfile.trino +11 -34
  9. continuo_python_runtime-0.10.0/README.md → continuo_python_runtime-0.12.0/PKG-INFO +151 -11
  10. continuo_python_runtime-0.10.0/PKG-INFO → continuo_python_runtime-0.12.0/README.md +130 -31
  11. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/README.md +12 -3
  12. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/application/warehouse.py +2 -0
  13. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/infrastructure/session.py +47 -2
  14. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/pyproject.toml +7 -7
  15. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_adapter_duckdb_wiring.py +4 -0
  16. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_infra_duckdb_session.py +66 -3
  17. continuo_python_runtime-0.12.0/adapters/duckdb/tests/test_integration_duckdb_conformance.py +51 -0
  18. continuo_python_runtime-0.12.0/adapters/duckdb/tests/test_integration_duckdb_entrypoint.py +185 -0
  19. continuo_python_runtime-0.12.0/adapters/duckdb/tests/test_integration_duckdb_seed_preflight.py +154 -0
  20. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_integration_duckdb_stack.py +18 -6
  21. continuo_python_runtime-0.12.0/adapters/postgres/README.md +87 -0
  22. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/continuo_postgres_adapter/adapter.py +238 -12
  23. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/pyproject.toml +6 -6
  24. continuo_python_runtime-0.12.0/adapters/postgres/tests/test_adapter_postgres_connect.py +209 -0
  25. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/tests/test_adapter_postgres_validation.py +22 -1
  26. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/tests/test_integration_postgres_conformance.py +28 -0
  27. continuo_python_runtime-0.12.0/adapters/postgres/tests/test_integration_postgres_dependents.py +701 -0
  28. continuo_python_runtime-0.12.0/adapters/postgres/tests/test_integration_postgres_entrypoint.py +209 -0
  29. continuo_python_runtime-0.12.0/adapters/postgres/tests/test_integration_postgres_seed_preflight.py +141 -0
  30. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/tests/test_integration_runtime_postgres.py +29 -0
  31. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/README.md +41 -0
  32. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/continuo_trino_adapter/adapter.py +195 -3
  33. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/pyproject.toml +11 -6
  34. continuo_python_runtime-0.12.0/adapters/trino/tests/test_adapter_trino_connect.py +217 -0
  35. continuo_python_runtime-0.12.0/adapters/trino/tests/test_adapter_trino_dependents.py +224 -0
  36. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/tests/test_adapter_trino_validation.py +4 -0
  37. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/tests/test_integration_trino_conformance.py +33 -0
  38. continuo_python_runtime-0.12.0/adapters/trino/tests/test_integration_trino_entrypoint.py +204 -0
  39. continuo_python_runtime-0.12.0/adapters/trino/tests/test_integration_trino_seed_preflight.py +105 -0
  40. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/cli.py +6 -0
  41. continuo_python_runtime-0.12.0/continuo_python_runtime/content_check.py +73 -0
  42. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/contract/kinds.py +10 -2
  43. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/contract/loader.py +52 -2
  44. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/contract/merge.py +26 -45
  45. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/contract/model.py +1 -0
  46. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/contract/paths.py +33 -0
  47. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/errors.py +13 -1
  48. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/harness.py +15 -1
  49. continuo_python_runtime-0.12.0/continuo_python_runtime/hash_inputs.py +63 -0
  50. continuo_python_runtime-0.12.0/continuo_python_runtime/hashing.py +93 -0
  51. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/lint.py +194 -6
  52. continuo_python_runtime-0.12.0/continuo_python_runtime/validation/preflight.py +410 -0
  53. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/validation/runner.py +20 -3
  54. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/README.md +16 -5
  55. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/continuo_engine_contract/port.py +79 -2
  56. continuo_python_runtime-0.12.0/contract/continuo_engine_contract/result.py +59 -0
  57. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/continuo_engine_contract/testing/conformance.py +249 -6
  58. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/pyproject.toml +3 -3
  59. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/tests/test_conformance_suite.py +48 -1
  60. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/tests/test_contract_packaging.py +1 -1
  61. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/tests/test_port.py +15 -0
  62. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/tests/test_result.py +33 -0
  63. continuo_python_runtime-0.12.0/contract/tests/test_startup_conformance.py +180 -0
  64. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/docs/boundary-contract.md +67 -49
  65. continuo_python_runtime-0.12.0/image-requirements-duckdb.txt +3 -0
  66. continuo_python_runtime-0.12.0/image-requirements-postgres.txt +3 -0
  67. continuo_python_runtime-0.12.0/image-requirements-trino.txt +3 -0
  68. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/pyproject.toml +10 -7
  69. continuo_python_runtime-0.12.0/scripts/install_image_pins.py +137 -0
  70. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/scripts/verify_installed_packages.py +3 -0
  71. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/template/.github/workflows/release.yml +28 -3
  72. continuo_python_runtime-0.12.0/template/Dockerfile +17 -0
  73. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/template/Dockerfile.pip +7 -6
  74. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/template/README.md +31 -8
  75. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/contract/test_loader.py +49 -0
  76. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/contract/test_merge.py +172 -40
  77. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/contract/test_wire_contract_write_modes.py +4 -0
  78. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/fixtures/wire_contract_write_modes.yml +16 -1
  79. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/smoke/trino-stack/docker-compose.yml +4 -1
  80. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_cli.py +10 -0
  81. continuo_python_runtime-0.12.0/tests/test_entrypoint_shims.py +23 -0
  82. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_harness.py +99 -0
  83. continuo_python_runtime-0.12.0/tests/test_harness_content_check.py +176 -0
  84. continuo_python_runtime-0.12.0/tests/test_hashing.py +196 -0
  85. continuo_python_runtime-0.12.0/tests/test_hashing_vectors.py +35 -0
  86. continuo_python_runtime-0.12.0/tests/test_install_image_pins.py +148 -0
  87. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_kind_registries.py +2 -3
  88. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_lint.py +77 -0
  89. continuo_python_runtime-0.12.0/tests/test_projection_vectors.py +34 -0
  90. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_rehearsal_version.py +1 -1
  91. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_release_pipeline_structure.py +13 -3
  92. continuo_python_runtime-0.12.0/tests/test_template.py +498 -0
  93. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_types.py +34 -0
  94. continuo_python_runtime-0.12.0/tests/test_validation_preflight.py +524 -0
  95. continuo_python_runtime-0.12.0/tests/test_verify_installed_packages.py +34 -0
  96. continuo_python_runtime-0.12.0/uv.lock +936 -0
  97. continuo_python_runtime-0.10.0/.python-version +0 -1
  98. continuo_python_runtime-0.10.0/adapters/duckdb/tests/test_integration_duckdb_conformance.py +0 -27
  99. continuo_python_runtime-0.10.0/adapters/postgres/README.md +0 -36
  100. continuo_python_runtime-0.10.0/continuo_python_runtime/hashing.py +0 -94
  101. continuo_python_runtime-0.10.0/contract/continuo_engine_contract/result.py +0 -34
  102. continuo_python_runtime-0.10.0/image-requirements-duckdb.txt +0 -3
  103. continuo_python_runtime-0.10.0/image-requirements-postgres.txt +0 -3
  104. continuo_python_runtime-0.10.0/image-requirements-trino.txt +0 -3
  105. continuo_python_runtime-0.10.0/template/Dockerfile +0 -16
  106. continuo_python_runtime-0.10.0/tests/test_hashing.py +0 -195
  107. continuo_python_runtime-0.10.0/tests/test_template.py +0 -248
  108. continuo_python_runtime-0.10.0/uv.lock +0 -895
  109. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.claude/agents/ddd-architecture-auditor.md +0 -0
  110. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.dockerignore +0 -0
  111. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/CODEOWNERS +0 -0
  112. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  113. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  114. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  115. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  116. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/dependabot.yml +0 -0
  117. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/ci.yml +0 -0
  118. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/dco.yml +0 -0
  119. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/image-smoke.yml +0 -0
  120. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/images.yml +0 -0
  121. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/publish-pypi.yml +0 -0
  122. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/release.yml +0 -0
  123. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/security.yml +0 -0
  124. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/verify-packages.yml +0 -0
  125. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.gitignore +0 -0
  126. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.gitleaks.toml +0 -0
  127. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/CODE_OF_CONDUCT.md +0 -0
  128. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/DCO +0 -0
  129. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/LICENSE +0 -0
  130. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/NOTICE +0 -0
  131. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/SECURITY.md +0 -0
  132. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/__init__.py +0 -0
  133. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/adapter.py +0 -0
  134. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/application/__init__.py +0 -0
  135. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/application/ports.py +0 -0
  136. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/domain/__init__.py +0 -0
  137. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/domain/columns.py +0 -0
  138. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/domain/identifiers.py +0 -0
  139. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/domain/layout.py +0 -0
  140. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/infrastructure/__init__.py +0 -0
  141. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/infrastructure/ddl.py +0 -0
  142. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/infrastructure/extensions.py +0 -0
  143. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/infrastructure/passfile.py +0 -0
  144. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/infrastructure/settings.py +0 -0
  145. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/__init__.py +0 -0
  146. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/conftest.py +0 -0
  147. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_adapter_duckdb_proxy.py +0 -0
  148. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_adapter_duckdb_runtime.py +0 -0
  149. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_adapter_duckdb_validation.py +0 -0
  150. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_domain_duckdb_columns.py +0 -0
  151. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_domain_duckdb_identifiers.py +0 -0
  152. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_domain_duckdb_layout.py +0 -0
  153. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_infra_duckdb_settings_ddl.py +0 -0
  154. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_integration_duckdb_layout.py +0 -0
  155. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_integration_duckdb_nullability_probe.py +0 -0
  156. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_integration_duckdb_runtime.py +0 -0
  157. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_integration_duckdb_validation.py +0 -0
  158. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/continuo_postgres_adapter/__init__.py +0 -0
  159. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/tests/__init__.py +0 -0
  160. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/tests/conftest.py +0 -0
  161. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/tests/test_adapter_runtime_postgres.py +0 -0
  162. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/tests/test_integration_postgres_validation.py +0 -0
  163. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/continuo_trino_adapter/__init__.py +0 -0
  164. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/tests/__init__.py +0 -0
  165. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/tests/test_adapter_runtime_trino.py +0 -0
  166. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/tests/test_adapter_trino_writes.py +0 -0
  167. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/tests/test_integration_runtime_trino.py +0 -0
  168. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/tests/test_integration_trino_merge_probe.py +0 -0
  169. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/tests/test_integration_trino_validation.py +0 -0
  170. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/__init__.py +0 -0
  171. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/closure.py +0 -0
  172. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/conform.py +0 -0
  173. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/context.py +0 -0
  174. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/contract/__init__.py +0 -0
  175. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/contract/secret_ref.py +0 -0
  176. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/csv_loader.py +0 -0
  177. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/csv_readers/__init__.py +0 -0
  178. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/csv_readers/https.py +0 -0
  179. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/csv_readers/s3.py +0 -0
  180. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/csv_source.py +0 -0
  181. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/shape.py +0 -0
  182. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/types.py +0 -0
  183. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/validation/__init__.py +0 -0
  184. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/validation/s3.py +0 -0
  185. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/LICENSE +0 -0
  186. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/NOTICE +0 -0
  187. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/continuo_engine_contract/__init__.py +0 -0
  188. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/continuo_engine_contract/config.py +0 -0
  189. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/continuo_engine_contract/keys.py +0 -0
  190. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/continuo_engine_contract/sql.py +0 -0
  191. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/continuo_engine_contract/testing/__init__.py +0 -0
  192. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/continuo_engine_contract/types.py +0 -0
  193. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/tests/__init__.py +0 -0
  194. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/tests/test_config.py +0 -0
  195. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/tests/test_contract_keys.py +0 -0
  196. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/tests/test_contract_types.py +0 -0
  197. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/tests/test_sql.py +0 -0
  198. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/scripts/apply_rehearsal_version.py +0 -0
  199. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/scripts/bake_duckdb_extensions.py +0 -0
  200. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/scripts/check_version_bumps.py +0 -0
  201. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/scripts/security-scan.sh +0 -0
  202. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/template/contracts/example.yml +0 -0
  203. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/template/contracts/example_csv.yml +0 -0
  204. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/template/requirements.lock +0 -0
  205. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/template/scripts/example.py +0 -0
  206. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/__init__.py +0 -0
  207. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/conftest.py +0 -0
  208. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/contract/__init__.py +0 -0
  209. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/contract/test_kinds.py +0 -0
  210. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/contract/test_model.py +0 -0
  211. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/smoke/duckdb-stack/docker-compose.yml +0 -0
  212. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/smoke/node_smoke/contracts/smoke.yml +0 -0
  213. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/smoke/node_smoke/scripts/smoke.py +0 -0
  214. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/smoke/postgres-stack/docker-compose.yml +0 -0
  215. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/smoke/trino-stack/catalog/iceberg.properties +0 -0
  216. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_adapter_naming.py +0 -0
  217. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_check_version_bumps_tags.py +0 -0
  218. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_ci_test_coverage.py +0 -0
  219. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_closure.py +0 -0
  220. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_conform.py +0 -0
  221. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_context.py +0 -0
  222. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_contract_loader.py +0 -0
  223. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_contract_pin_consistency.py +0 -0
  224. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_csv_loader.py +0 -0
  225. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_csv_readers_https.py +0 -0
  226. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_csv_readers_integration.py +0 -0
  227. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_csv_source.py +0 -0
  228. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_errors.py +0 -0
  229. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_harness_write_modes.py +0 -0
  230. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_image_requirements_sync.py +0 -0
  231. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_image_smoke_validation.py +0 -0
  232. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_no_legacy_names.py +0 -0
  233. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_package.py +0 -0
  234. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_python_version_consistency.py +0 -0
  235. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_shape.py +0 -0
  236. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_validation_runner.py +0 -0
  237. {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_validation_s3.py +0 -0
@@ -89,7 +89,13 @@ jobs:
89
89
  # once published. (The image build itself runs inside python:3.14-slim.)
90
90
  python-version: "3.14"
91
91
  # Ordering between the upload and this build is a `needs:` edge in
92
- # publish-pypi.yml, but an index can lag its own upload, so poll. The
92
+ # publish-pypi.yml, but an index can lag its own upload, so poll. A
93
+ # probe that succeeds does not guarantee the build's own request the
94
+ # same answer (two requests seconds apart can be served different
95
+ # copies of the index page), so the image build's install
96
+ # (scripts/install_image_pins.py) also retries while a pin is not
97
+ # served yet. This probe is the fast pre-check, and in a rehearsal it
98
+ # fetches the files compared byte for byte below. The
93
99
  # probe runs with --no-cache-dir: the simple index is served with
94
100
  # `Cache-Control: max-age=600`, which pip's HTTP cache honours, so one
95
101
  # early stale fetch would otherwise be replayed for 10 minutes, exactly
@@ -0,0 +1 @@
1
+ 3.14.8
@@ -5,6 +5,219 @@ follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.12.0] - 2026-11-11
9
+
10
+ **TL;DR**
11
+
12
+ - Hashes now come from continuo-contracts 0.1.0, the library continuo uses.
13
+ Every Python node's `content_hash` changes once, on its first release with
14
+ this version.
15
+ - A node can list the files its script reads in `assets`, and the lint refuses
16
+ five kinds of code the hash cannot see.
17
+ - The harness checks, when a node starts, that the image holds what the
18
+ release hashed.
19
+ - The validation runner has two new read-only ops, `seed_preflight` and
20
+ `probe_views`.
21
+ - Adapter authors: every adapter must now declare `drop_semantics`.
22
+
23
+ **Upgrade**
24
+
25
+ 1. Build your domain image `FROM` the `v0.12.0` engine image and install
26
+ `continuo-python-runtime==0.12.0` in CI. The template's "Pin the runtime to
27
+ the image" step does this from the `FROM` line. A `Dockerfile.pip`
28
+ repository replaces that step as the template README says.
29
+ 2. Move each Python service with continuo's rebaseline release, not an
30
+ ordinary one: its `content_hash` changes once.
31
+ 3. `COPY` into the image every file a node lists in `assets`.
32
+ 4. Bring-your-own adapter: declare `drop_semantics`. You may also implement
33
+ `DependentsIntrospection` and run `DependentsConformance`.
34
+
35
+ Versions: runtime 0.12.0 (pins continuo-contracts 0.1.0), engine contract 0.10.0, postgres adapter 0.4.0, trino adapter 0.5.0, duckdb adapter 0.3.0.
36
+
37
+ ### Added
38
+
39
+ - Every engine adapter declares `drop_semantics`, what dropping a table does
40
+ to the objects that read it: `"cascade"` (they are destroyed) or
41
+ `"late_binding"` (they survive and fail on their next read). The postgres
42
+ adapter declares `cascade`, the trino and duckdb adapters `late_binding`.
43
+ `StartupConformance` has a new case, `test_declares_a_drop_semantics`.
44
+ - `continuo_engine_contract.port` has an opt-in capability,
45
+ `DependentsIntrospection`, with `Dependent` and `Dependents` and the
46
+ vocabularies `DROP_SEMANTICS`, `COMPLETENESS` and `DEPENDENT_KINDS`. Its one
47
+ method, `dependents(schema, table)`, lists every object a drop of the table
48
+ would destroy or leave reading a missing table, and gives none for a missing
49
+ table or schema. The conformance class `DependentsConformance` checks it,
50
+ with an overridable `create_view` hook.
51
+ - `PostgresAdapter.dependents(schema, table)` lists, with `completeness="exact"`,
52
+ every object a `DROP TABLE ... CASCADE` of the table destroys or changes: views
53
+ and materialized views to any depth, SQL-standard functions and procedures,
54
+ foreign keys and policies on other tables, rules, inheriting tables, tables
55
+ with a column of the table's row type or of an array of it, the types built
56
+ on the table (a domain, a range, a composite type) and what reads them, and
57
+ what reads a partition of the table or a sequence of it (owned or identity).
58
+ Each object is listed once, at its shallowest depth, and the walk follows at
59
+ most 32 dependency levels. It reads `pg_depend`, so it sees what
60
+ `information_schema.view_table_usage` misses, and finds the table
61
+ case-insensitively. `TestPostgresDependents` plus a guard that snapshots the
62
+ schemas around a rolled-back cascade check it. The adapter's README lists
63
+ every kind.
64
+ - `TrinoAdapter.dependents(schema, table)` lists, with
65
+ `completeness="best_effort"`, the views whose SQL reads the table. It reads
66
+ `information_schema.views` of the adapter's catalog in one query and parses
67
+ each definition with sqlglot: an unqualified name is in the view's own
68
+ schema, a name without a catalog is in the adapter's, and a CTE of the same
69
+ statement is not the table. A definition that does not parse is matched by
70
+ the table's name as a whole identifier, with a WARNING naming the view. It
71
+ misses dynamic SQL, views in other catalogs, and views that read the table
72
+ only through another view. The adapter pins `sqlglot==30.23.0`, as the
73
+ engine contract does, and `TestTrinoDependents` runs the conformance cases
74
+ against Trino and the Iceberg REST catalog.
75
+ - The validation runner has two read-only ops, `seed_preflight` and `probe_views`
76
+ (`VALIDATION_OP`), which need no `DBT_TARGET_SCHEMA`. `seed_preflight` lists the
77
+ objects a reload of a seed's production table would destroy or leave reading
78
+ a missing table, compares them with `SEED_PREFLIGHT_ALLOWED` and
79
+ `SEED_PREFLIGHT_ACKNOWLEDGED`, and in `check` mode exits 1 with `reason`
80
+ `unowned_dependents`, `engine_mismatch` or `warehouse_unreachable` when the
81
+ reload must not run; `report` mode prints the same `reason` and exits 0.
82
+ `probe_views` reads each view of `PROBE_VIEWS` with a zero-row `SELECT` and
83
+ reports which no longer bind, without failing. Both print one result block
84
+ with their own keys after `reason`; `result_block` takes them as a keyword-only
85
+ `fields` mapping and refuses a key that shadows a standard one. The README
86
+ section "Seed preflight and view probe" has the inputs, the block and the
87
+ decision table.
88
+ - `continuo-runtime --version` prints `continuo-runtime <version>` to stdout and
89
+ exits 0. The template's `release.yml` has a "Pin the runtime to the image"
90
+ step that reads the version from the Dockerfile's
91
+ `FROM ghcr.io/carolsimone/continuo-python-runtime-<engine>:vX.Y.Z` line
92
+ (failing with an `::error::` when none matches), installs exactly that
93
+ runtime, and fails when the version `uv tool list` reports differs, so CI hashes
94
+ with the runtime the image runs.
95
+ - The harness checks, before it builds the adapter, that the image holds what
96
+ the release hashed. When `CONTENT_HASH` is set it recomputes the node's
97
+ `content_hash` from the files in the image, with the helpers `merge` uses,
98
+ and a difference, or a hashed file missing from the image, fails the node
99
+ with `ImageContractMismatch` (a `ContractError`) and exit 1. The message
100
+ names both hashes, the three parts, the unit paths and the runtime version.
101
+ An unset or empty `CONTENT_HASH` logs a warning and runs. The result block
102
+ carries an optional `reason` key after `unique_id`
103
+ (`image_contract_mismatch`); a block without one keeps its bytes, and
104
+ `continuo_engine_contract.result.result_block` takes it as a keyword-only
105
+ `reason`.
106
+ - `assets:` on a `python-node` or `python-api` node lists the repository files
107
+ its script reads. `merge` folds their bytes into `shared_code_hash`, so
108
+ editing one changes the node's `content_hash`, and writes `assets` on the
109
+ wire entry when a node declares any. A missing path, a non-file or a path
110
+ that resolves outside the repository fails `merge`; `python-csv` refuses the
111
+ key. The image must `COPY` the files.
112
+ - `lint` and `merge` refuse code the content hash cannot see: `runpy`, a change
113
+ to `sys.path`, a `sitecustomize` or `usercustomize` module, `compile()` and
114
+ `types.FunctionType`, and `pickle.load`, `pickle.loads` and
115
+ `pickle.Unpickler`. `merge` also refuses a `sitecustomize.py` or
116
+ `usercustomize.py` at the repository root. A file a script reads belongs in
117
+ `assets`.
118
+
119
+ ### Changed
120
+
121
+ - **Breaking for adapter authors.** `WarehouseAdapter.drop_semantics` is a
122
+ required declaration with no default: an adapter that does not set it cannot
123
+ pass the new conformance case.
124
+ - A node's hashes come from continuo-contracts 0.1.0, the library
125
+ continuo's topology-controller uses too, so CI and continuo compute the
126
+ same values. `config_hash` hashes the node's code projection: `owner`,
127
+ `description`, `criticality` and `schedule` no longer move a node's hash,
128
+ a column type's spelling does not (`INT` and `INTEGER` hash alike), and a
129
+ read's SQL is hashed as written, apart from LF line endings and the
130
+ whitespace around it. `shared_code_hash` folds each import closure file
131
+ with its repo-relative path, so two files that swap their contents change
132
+ it. Every Python node's `content_hash` changes once, on the first release
133
+ built with this version. The wire entry keeps its keys and the fold.
134
+ - A node whose `config` holds a value the hash cannot write (an integer
135
+ beyond 2**53 - 1, NaN or an infinity, nesting deeper than 99 levels, a
136
+ lone surrogate) fails `merge` with a `ContractError` naming the node.
137
+ - The package gate no longer counts `continuo-contracts` as a first-party
138
+ distribution.
139
+
140
+ ### Fixed
141
+
142
+ - A release's image build no longer fails when PyPI still serves an index
143
+ page from before the upload. The engine images install their pins through
144
+ `scripts/install_image_pins.py`, which retries an install while pip says a
145
+ pinned version is not served yet (up to 10 minutes) and fails any other
146
+ error at once. The v0.11.0 trino amd64 build hit this 40 s after the upload,
147
+ although the runner's own probe had seen the new version. No package
148
+ changes.
149
+
150
+ ## [0.11.0] - 2026-11-04
151
+
152
+ **TL;DR**
153
+
154
+ - A failed python node's log now says why it failed.
155
+ - Every engine adapter waits up to about 10 s for a warehouse that refuses
156
+ the first connections, as a new Kubernetes pod sees until the cluster's
157
+ network policy admits it. That used to fail the attempt at once.
158
+ - The trino adapter now connects when it is created, so a wrong Trino
159
+ password fails at start-up instead of at the first read.
160
+ - Adapter authors: `StartupConformance` is a new conformance class every
161
+ adapter's integration suite runs.
162
+
163
+ **Upgrade**
164
+
165
+ 1. Build your domain image `FROM` the `v0.11.0` engine image (or pin
166
+ `continuo-python-runtime==0.11.0` and your adapter's new version).
167
+ 2. Bring-your-own adapter: subclass `StartupConformance` in your integration
168
+ suite and provide the `warehouse_address` and `adapter_from_env` fixtures.
169
+
170
+ Versions: runtime 0.11.0, engine contract 0.9.0, postgres adapter 0.3.2,
171
+ trino adapter 0.4.0, duckdb adapter 0.2.2.
172
+
173
+ ### Fixed
174
+
175
+ - A failed python node's stored log names its failure. The harness logs every
176
+ runtime error at ERROR on stderr, with the traceback of the exception it
177
+ wraps, as well as printing it in the result block. Continuo cuts the result
178
+ block out of the pod log before storing it, so a failure only printed there,
179
+ such as `LoadError: adapter construction failed: … Connection refused`, was
180
+ missing from the stored log.
181
+ - Every adapter's `from_env` waits out a warehouse that refuses connections
182
+ for the first few seconds. A Job pod's first connection can be refused until
183
+ the cluster's NetworkPolicy engine (k3s's kube-router rejects) has admitted
184
+ the pod; that cost a task retry and a failed Job. A connection that no server
185
+ answered (every address refused, had no route or sat on an unreachable
186
+ network) is tried up to 5 times, 2 s apart, each retry logged. An
187
+ authentication failure, a timeout on any address and every other failure are
188
+ raised at once.
189
+ - postgres: around `psycopg2.connect`.
190
+ - duckdb: around the catalog attach.
191
+ - trino: `from_env` now sends `SELECT 1`, since the trino DBAPI opens no
192
+ connection until the first request. A refusal is retried only if it failed
193
+ within 5 s: urllib3 reports only the last address it tried, so a slower
194
+ one hides an address that timed out. A failed authentication now fails
195
+ `from_env` (a harness `LoadError`) rather than the first read or write.
196
+
197
+ ### Added
198
+
199
+ - `StartupConformance` in `continuo_engine_contract.testing.conformance`: every
200
+ adapter's integration suite runs it. It puts the real engine behind a
201
+ loopback port that refuses connections for 3 s (`LateOpeningPort`), then
202
+ checks that `from_env` returns an adapter that answers `SELECT 1`. The new
203
+ fixtures are `warehouse_address` and `adapter_from_env`.
204
+
205
+ ### Changed
206
+
207
+ - The python-node env contract in `docs/boundary-contract.md` lists
208
+ `TASK_ATTEMPT`, the 0-based number of the task's attempt, which the executor
209
+ sets on every production Job. The harness does not read it; a node script
210
+ may. Documentation only: no package changes.
211
+ - The engine images build on `python:3.14.8-slim` (was `3.14.2`), and
212
+ `.python-version` and the `template/` Dockerfile follow.
213
+ - `pyarrow` is pinned at `26.0.0` (was `25.0.1`) in the runtime, the engine
214
+ contract's `testing` extra and the three adapters, so they keep resolving
215
+ together.
216
+ - Dependency pins move together across the workspace: `ruff` 0.17.1, `mypy`
217
+ 2.4.0, `boto3` 1.43.114, `sqlglot` 30.23.0 (runtime and engine contract),
218
+ `trino` 0.340.0 and `psycopg2-binary` 2.9.13. `urllib3` moves to 2.8.0 in
219
+ `uv.lock` (CVE-2026-97687, CVE-2026-97689).
220
+
8
221
  ## [0.10.0] - 2026-10-22
9
222
 
10
223
  ### Added
@@ -28,15 +28,19 @@ merged PRs before adding anything new.
28
28
  conformance suite for engine adapter authors. Its dependencies are installed
29
29
  with `continuo-engine-contract[testing]`.
30
30
 
31
- - Every adapter MUST satisfy the engine contract and pass the shared
32
- conformance classes for every capability it declares: `IntrospectionConformance`
33
- for `TableIntrospection`, `AppendConformance` for `AppendCapable`, and
34
- `UpsertConformance` for `UpsertCapable`. Append and upsert adapters must also
35
- run the introspection class. An adapter need not declare capabilities its
36
- engine cannot support.
31
+ - Every adapter MUST satisfy the engine contract, declare a `drop_semantics`,
32
+ and pass `StartupConformance` (`from_env` waits out a warehouse that refuses
33
+ connections at first, and `drop_semantics` is declared) and the
34
+ shared conformance classes for every capability it declares:
35
+ `IntrospectionConformance` for `TableIntrospection`, `AppendConformance` for
36
+ `AppendCapable`, `UpsertConformance` for `UpsertCapable`, and
37
+ `DependentsConformance` for `DependentsIntrospection`. Append and
38
+ upsert adapters must also run the introspection class. An adapter need not
39
+ declare capabilities its engine cannot support.
37
40
  - Each adapter's integration suite MUST subclass the applicable classes,
38
- supply connected `adapter` and temporary `schema` fixtures, and run them
39
- against its real warehouse in CI. In-memory reference tests alone do not
41
+ supply connected `adapter` and temporary `schema` fixtures (and, for
42
+ `StartupConformance`, `warehouse_address` and `adapter_from_env`), and run
43
+ them against its real warehouse in CI. In-memory reference tests alone do not
40
44
  establish an adapter's conformance. Do not skip or weaken shared checks to
41
45
  accommodate an adapter that violates the contract.
42
46
  - Every new or changed engine-independent contract requirement, including
@@ -151,7 +151,7 @@ gh workflow run publish-pypi.yml --ref <branch> -f dry_run=true
151
151
  |---|---|---|---|---|
152
152
  | `prepare`, `verify-packages`, `preflight-*` | nothing | nothing | none | Fix, delete the tag (`git push --delete origin vX.Y.Z`), re-tag. |
153
153
  | `publish-packages` | maybe some of the five files | nothing | none | Re-run failed jobs (`skip-existing` makes it resumable), or fix forward. |
154
- | `candidate-build` | published | maybe untagged digests | none | Transient (index lag, runner): re-run failed jobs. Real defect: yank the files on pypi.org and **fix forward** with a new version. |
154
+ | `candidate-build` | published | maybe untagged digests | none | The build waits up to 10 minutes on its own for the index to serve the new pins. Transient (a runner, a longer index lag): re-run failed jobs. Real defect: yank the files on pypi.org and **fix forward** with a new version. |
155
155
  | `candidate-verify` | published | untagged candidates | none | Same: an image defect means yank and fix forward. |
156
156
  | `promote` | published | verified digests, maybe some engines tagged | none | Re-run failed jobs; tagging is idempotent and refuses to move an existing tag to different content. |
157
157
 
@@ -1,4 +1,4 @@
1
- FROM python:3.14.2-slim
1
+ FROM python:3.14.8-slim
2
2
  # One dual-role image per engine: the python-node runtime harness (default
3
3
  # command `run`) and the blue/green validation runner (`validation-op`). It
4
4
  # installs the PUBLISHED, versioned libraries, never the repo source:
@@ -12,30 +12,17 @@ FROM python:3.14.2-slim
12
12
  # package names, so it is never an extra index.
13
13
  # Any other value fails the build.
14
14
  # The pinned versions live in image-requirements-duckdb.txt, kept equal to the
15
- # repo's pyproject versions by tests/test_image_requirements_sync.py. See
16
- # Dockerfile.postgres for the full reasoning behind the two-step wheelhouse
17
- # install (exact local files first, --no-index --no-deps, then PyPI for the
18
- # third-party dependencies).
15
+ # repo's pyproject versions by tests/test_image_requirements_sync.py.
16
+ # scripts/install_image_pins.py runs the installs for each WHEEL_SOURCE (and
17
+ # says why the wheelhouse wheels are installed by exact file first). It
18
+ # retries an index install while the index does not serve a just-uploaded
19
+ # pin yet: a release builds its images right after the upload.
19
20
  ARG WHEEL_SOURCE=pypi
20
21
  COPY image-requirements-duckdb.txt /tmp/req.txt
21
22
  COPY wheelhous[e] /tmp/wheelhouse
22
- RUN set -eu; \
23
- if [ "$WHEEL_SOURCE" = "wheelhouse" ]; then \
24
- pip install --no-cache-dir --no-index --no-deps \
25
- /tmp/wheelhouse/continuo_engine_contract-*.whl \
26
- /tmp/wheelhouse/continuo_python_runtime-*.whl \
27
- /tmp/wheelhouse/continuo_duckdb_adapter-*.whl; \
28
- pip install --no-cache-dir -r /tmp/req.txt; \
29
- elif [ "$WHEEL_SOURCE" = "testpypi" ]; then \
30
- pip install --no-cache-dir --no-deps --only-binary=:all: --index-url https://test.pypi.org/simple/ \
31
- -r /tmp/req.txt; \
32
- pip install --no-cache-dir -r /tmp/req.txt; \
33
- elif [ "$WHEEL_SOURCE" = "pypi" ]; then \
34
- pip install --no-cache-dir -r /tmp/req.txt; \
35
- else \
36
- echo "unknown WHEEL_SOURCE=$WHEEL_SOURCE (pypi|testpypi|wheelhouse)" >&2; exit 1; \
37
- fi; \
38
- rm -rf /tmp/req.txt /tmp/wheelhouse
23
+ COPY scripts/install_image_pins.py /tmp/install_image_pins.py
24
+ RUN python /tmp/install_image_pins.py --source "$WHEEL_SOURCE" --adapter duckdb --requirements /tmp/req.txt --wheelhouse /tmp/wheelhouse \
25
+ && rm -rf /tmp/req.txt /tmp/wheelhouse /tmp/install_image_pins.py
39
26
  # The adapter LOADs ducklake/postgres/httpfs/aws from this directory. They are
40
27
  # installed now, as root, because the runtime user below has no home directory
41
28
  # and the container may have no network. HOME=/tmp gives DuckDB a writable
@@ -1,4 +1,4 @@
1
- FROM python:3.14.2-slim
1
+ FROM python:3.14.8-slim
2
2
  # One dual-role image per engine — the python-node runtime harness (default
3
3
  # command `run`) and the blue/green validation runner (`validation-op`). It
4
4
  # installs the PUBLISHED, versioned libraries, never the repo source:
@@ -15,48 +15,25 @@ FROM python:3.14.2-slim
15
15
  # Any other value fails the build.
16
16
  # The wheelhouse holds only this repo's own first-party wheels (built via
17
17
  # `uv build --all-packages`); third-party dependencies always resolve from
18
- # PyPI in both branches, so the wheelhouse branch never passes --no-index to
19
- # the requirements install below.
18
+ # PyPI in both branches, so the wheelhouse install never passes --no-index to
19
+ # the requirements install.
20
20
  # The pinned versions live in image-requirements-postgres.txt, kept equal to the
21
21
  # repo's pyproject versions by tests/test_image_requirements_sync.py.
22
22
  #
23
- # The wheelhouse branch installs its three first-party wheels (contract,
24
- # runtime, adapter) by exact local file first, with --no-index --no-deps: a
25
- # plain `--find-links=/tmp/wheelhouse -r req.txt` is not enough, because pip
26
- # does not prefer a find-links wheel over an index match at the same
27
- # name+version, and continuo-python-runtime / continuo-engine-contract are
28
- # already published on PyPI under the version this repo's HEAD currently
29
- # carries (a routine dependency bump lands between releases without a version
30
- # bump). Left unpinned-by-file, pip silently installs the last PyPI release's
31
- # transitive pins instead of the wheel this build just produced, defeating
32
- # the point of testing an unreleased change. Installing the exact local files
33
- # first (no index contacted at all for this step) is unambiguous; the second
34
- # install then only has PyPI-only third-party deps left to resolve, and finds
35
- # the three first-party packages already satisfied.
23
+ # scripts/install_image_pins.py runs the installs for each WHEEL_SOURCE (and
24
+ # says why the wheelhouse wheels are installed by exact file first). It
25
+ # retries an index install while the index does not serve a just-uploaded
26
+ # pin yet: a release builds its images right after the upload.
36
27
  ARG WHEEL_SOURCE=pypi
37
28
  COPY image-requirements-postgres.txt /tmp/req.txt
38
29
  # Optional COPY: the bracket glob matches ./wheelhouse when it exists (the CI/PR
39
30
  # WHEEL_SOURCE=wheelhouse path builds it) and no-ops when it is absent, so a
40
31
  # release build or a plain `docker build -f Dockerfile.postgres .` needs no
41
- # pre-created directory. Only the wheelhouse branch below reads its contents.
32
+ # pre-created directory. Only the wheelhouse install reads its contents.
42
33
  COPY wheelhous[e] /tmp/wheelhouse
43
- RUN set -eu; \
44
- if [ "$WHEEL_SOURCE" = "wheelhouse" ]; then \
45
- pip install --no-cache-dir --no-index --no-deps \
46
- /tmp/wheelhouse/continuo_engine_contract-*.whl \
47
- /tmp/wheelhouse/continuo_python_runtime-*.whl \
48
- /tmp/wheelhouse/continuo_postgres_adapter-*.whl; \
49
- pip install --no-cache-dir -r /tmp/req.txt; \
50
- elif [ "$WHEEL_SOURCE" = "testpypi" ]; then \
51
- pip install --no-cache-dir --no-deps --only-binary=:all: --index-url https://test.pypi.org/simple/ \
52
- -r /tmp/req.txt; \
53
- pip install --no-cache-dir -r /tmp/req.txt; \
54
- elif [ "$WHEEL_SOURCE" = "pypi" ]; then \
55
- pip install --no-cache-dir -r /tmp/req.txt; \
56
- else \
57
- echo "unknown WHEEL_SOURCE=$WHEEL_SOURCE (pypi|testpypi|wheelhouse)" >&2; exit 1; \
58
- fi; \
59
- rm -rf /tmp/req.txt /tmp/wheelhouse
34
+ COPY scripts/install_image_pins.py /tmp/install_image_pins.py
35
+ RUN python /tmp/install_image_pins.py --source "$WHEEL_SOURCE" --adapter postgres --requirements /tmp/req.txt --wheelhouse /tmp/wheelhouse \
36
+ && rm -rf /tmp/req.txt /tmp/wheelhouse /tmp/install_image_pins.py
60
37
  # PYTHONPATH is belt-and-braces: the harness also inserts APP_ROOT and the
61
38
  # node script's own directory at the front of sys.path before executing it.
62
39
  ENV CONTRACT_DIR=/app/contracts APP_ROOT=/app PYTHONPATH=/app
@@ -1,4 +1,4 @@
1
- FROM python:3.14.2-slim
1
+ FROM python:3.14.8-slim
2
2
  # One dual-role image per engine — the python-node runtime harness (default
3
3
  # command `run`) and the blue/green validation runner (`validation-op`). It
4
4
  # installs the PUBLISHED, versioned libraries, never the repo source:
@@ -15,48 +15,25 @@ FROM python:3.14.2-slim
15
15
  # Any other value fails the build.
16
16
  # The wheelhouse holds only this repo's own first-party wheels (built via
17
17
  # `uv build --all-packages`); third-party dependencies always resolve from
18
- # PyPI in both branches, so the wheelhouse branch never passes --no-index to
19
- # the requirements install below.
18
+ # PyPI in both branches, so the wheelhouse install never passes --no-index to
19
+ # the requirements install.
20
20
  # The pinned versions live in image-requirements-trino.txt, kept equal to the
21
21
  # repo's pyproject versions by tests/test_image_requirements_sync.py.
22
22
  #
23
- # The wheelhouse branch installs its three first-party wheels (contract,
24
- # runtime, adapter) by exact local file first, with --no-index --no-deps: a
25
- # plain `--find-links=/tmp/wheelhouse -r req.txt` is not enough, because pip
26
- # does not prefer a find-links wheel over an index match at the same
27
- # name+version, and continuo-python-runtime / continuo-engine-contract are
28
- # already published on PyPI under the version this repo's HEAD currently
29
- # carries (a routine dependency bump lands between releases without a version
30
- # bump). Left unpinned-by-file, pip silently installs the last PyPI release's
31
- # transitive pins instead of the wheel this build just produced, defeating
32
- # the point of testing an unreleased change. Installing the exact local files
33
- # first (no index contacted at all for this step) is unambiguous; the second
34
- # install then only has PyPI-only third-party deps left to resolve, and finds
35
- # the three first-party packages already satisfied.
23
+ # scripts/install_image_pins.py runs the installs for each WHEEL_SOURCE (and
24
+ # says why the wheelhouse wheels are installed by exact file first). It
25
+ # retries an index install while the index does not serve a just-uploaded
26
+ # pin yet: a release builds its images right after the upload.
36
27
  ARG WHEEL_SOURCE=pypi
37
28
  COPY image-requirements-trino.txt /tmp/req.txt
38
29
  # Optional COPY: the bracket glob matches ./wheelhouse when it exists (the CI/PR
39
30
  # WHEEL_SOURCE=wheelhouse path builds it) and no-ops when it is absent, so a
40
31
  # release build or a plain `docker build -f Dockerfile.trino .` needs no
41
- # pre-created directory. Only the wheelhouse branch below reads its contents.
32
+ # pre-created directory. Only the wheelhouse install reads its contents.
42
33
  COPY wheelhous[e] /tmp/wheelhouse
43
- RUN set -eu; \
44
- if [ "$WHEEL_SOURCE" = "wheelhouse" ]; then \
45
- pip install --no-cache-dir --no-index --no-deps \
46
- /tmp/wheelhouse/continuo_engine_contract-*.whl \
47
- /tmp/wheelhouse/continuo_python_runtime-*.whl \
48
- /tmp/wheelhouse/continuo_trino_adapter-*.whl; \
49
- pip install --no-cache-dir -r /tmp/req.txt; \
50
- elif [ "$WHEEL_SOURCE" = "testpypi" ]; then \
51
- pip install --no-cache-dir --no-deps --only-binary=:all: --index-url https://test.pypi.org/simple/ \
52
- -r /tmp/req.txt; \
53
- pip install --no-cache-dir -r /tmp/req.txt; \
54
- elif [ "$WHEEL_SOURCE" = "pypi" ]; then \
55
- pip install --no-cache-dir -r /tmp/req.txt; \
56
- else \
57
- echo "unknown WHEEL_SOURCE=$WHEEL_SOURCE (pypi|testpypi|wheelhouse)" >&2; exit 1; \
58
- fi; \
59
- rm -rf /tmp/req.txt /tmp/wheelhouse
34
+ COPY scripts/install_image_pins.py /tmp/install_image_pins.py
35
+ RUN python /tmp/install_image_pins.py --source "$WHEEL_SOURCE" --adapter trino --requirements /tmp/req.txt --wheelhouse /tmp/wheelhouse \
36
+ && rm -rf /tmp/req.txt /tmp/wheelhouse /tmp/install_image_pins.py
60
37
  # PYTHONPATH is belt-and-braces: the harness also inserts APP_ROOT and the
61
38
  # node script's own directory at the front of sys.path before executing it.
62
39
  ENV CONTRACT_DIR=/app/contracts APP_ROOT=/app PYTHONPATH=/app