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.
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/image-build.yml +7 -1
- continuo_python_runtime-0.12.0/.python-version +1 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/CHANGELOG.md +213 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/CLAUDE.md +12 -8
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/CONTRIBUTING.md +1 -1
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/Dockerfile.duckdb +9 -22
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/Dockerfile.postgres +11 -34
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/Dockerfile.trino +11 -34
- continuo_python_runtime-0.10.0/README.md → continuo_python_runtime-0.12.0/PKG-INFO +151 -11
- continuo_python_runtime-0.10.0/PKG-INFO → continuo_python_runtime-0.12.0/README.md +130 -31
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/README.md +12 -3
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/application/warehouse.py +2 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/infrastructure/session.py +47 -2
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/pyproject.toml +7 -7
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_adapter_duckdb_wiring.py +4 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_infra_duckdb_session.py +66 -3
- continuo_python_runtime-0.12.0/adapters/duckdb/tests/test_integration_duckdb_conformance.py +51 -0
- continuo_python_runtime-0.12.0/adapters/duckdb/tests/test_integration_duckdb_entrypoint.py +185 -0
- continuo_python_runtime-0.12.0/adapters/duckdb/tests/test_integration_duckdb_seed_preflight.py +154 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_integration_duckdb_stack.py +18 -6
- continuo_python_runtime-0.12.0/adapters/postgres/README.md +87 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/continuo_postgres_adapter/adapter.py +238 -12
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/pyproject.toml +6 -6
- continuo_python_runtime-0.12.0/adapters/postgres/tests/test_adapter_postgres_connect.py +209 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/tests/test_adapter_postgres_validation.py +22 -1
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/tests/test_integration_postgres_conformance.py +28 -0
- continuo_python_runtime-0.12.0/adapters/postgres/tests/test_integration_postgres_dependents.py +701 -0
- continuo_python_runtime-0.12.0/adapters/postgres/tests/test_integration_postgres_entrypoint.py +209 -0
- continuo_python_runtime-0.12.0/adapters/postgres/tests/test_integration_postgres_seed_preflight.py +141 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/tests/test_integration_runtime_postgres.py +29 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/README.md +41 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/continuo_trino_adapter/adapter.py +195 -3
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/pyproject.toml +11 -6
- continuo_python_runtime-0.12.0/adapters/trino/tests/test_adapter_trino_connect.py +217 -0
- continuo_python_runtime-0.12.0/adapters/trino/tests/test_adapter_trino_dependents.py +224 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/tests/test_adapter_trino_validation.py +4 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/tests/test_integration_trino_conformance.py +33 -0
- continuo_python_runtime-0.12.0/adapters/trino/tests/test_integration_trino_entrypoint.py +204 -0
- continuo_python_runtime-0.12.0/adapters/trino/tests/test_integration_trino_seed_preflight.py +105 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/cli.py +6 -0
- continuo_python_runtime-0.12.0/continuo_python_runtime/content_check.py +73 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/contract/kinds.py +10 -2
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/contract/loader.py +52 -2
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/contract/merge.py +26 -45
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/contract/model.py +1 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/contract/paths.py +33 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/errors.py +13 -1
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/harness.py +15 -1
- continuo_python_runtime-0.12.0/continuo_python_runtime/hash_inputs.py +63 -0
- continuo_python_runtime-0.12.0/continuo_python_runtime/hashing.py +93 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/lint.py +194 -6
- continuo_python_runtime-0.12.0/continuo_python_runtime/validation/preflight.py +410 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/validation/runner.py +20 -3
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/README.md +16 -5
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/continuo_engine_contract/port.py +79 -2
- continuo_python_runtime-0.12.0/contract/continuo_engine_contract/result.py +59 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/continuo_engine_contract/testing/conformance.py +249 -6
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/pyproject.toml +3 -3
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/tests/test_conformance_suite.py +48 -1
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/tests/test_contract_packaging.py +1 -1
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/tests/test_port.py +15 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/tests/test_result.py +33 -0
- continuo_python_runtime-0.12.0/contract/tests/test_startup_conformance.py +180 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/docs/boundary-contract.md +67 -49
- continuo_python_runtime-0.12.0/image-requirements-duckdb.txt +3 -0
- continuo_python_runtime-0.12.0/image-requirements-postgres.txt +3 -0
- continuo_python_runtime-0.12.0/image-requirements-trino.txt +3 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/pyproject.toml +10 -7
- continuo_python_runtime-0.12.0/scripts/install_image_pins.py +137 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/scripts/verify_installed_packages.py +3 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/template/.github/workflows/release.yml +28 -3
- continuo_python_runtime-0.12.0/template/Dockerfile +17 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/template/Dockerfile.pip +7 -6
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/template/README.md +31 -8
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/contract/test_loader.py +49 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/contract/test_merge.py +172 -40
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/contract/test_wire_contract_write_modes.py +4 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/fixtures/wire_contract_write_modes.yml +16 -1
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/smoke/trino-stack/docker-compose.yml +4 -1
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_cli.py +10 -0
- continuo_python_runtime-0.12.0/tests/test_entrypoint_shims.py +23 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_harness.py +99 -0
- continuo_python_runtime-0.12.0/tests/test_harness_content_check.py +176 -0
- continuo_python_runtime-0.12.0/tests/test_hashing.py +196 -0
- continuo_python_runtime-0.12.0/tests/test_hashing_vectors.py +35 -0
- continuo_python_runtime-0.12.0/tests/test_install_image_pins.py +148 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_kind_registries.py +2 -3
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_lint.py +77 -0
- continuo_python_runtime-0.12.0/tests/test_projection_vectors.py +34 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_rehearsal_version.py +1 -1
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_release_pipeline_structure.py +13 -3
- continuo_python_runtime-0.12.0/tests/test_template.py +498 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_types.py +34 -0
- continuo_python_runtime-0.12.0/tests/test_validation_preflight.py +524 -0
- continuo_python_runtime-0.12.0/tests/test_verify_installed_packages.py +34 -0
- continuo_python_runtime-0.12.0/uv.lock +936 -0
- continuo_python_runtime-0.10.0/.python-version +0 -1
- continuo_python_runtime-0.10.0/adapters/duckdb/tests/test_integration_duckdb_conformance.py +0 -27
- continuo_python_runtime-0.10.0/adapters/postgres/README.md +0 -36
- continuo_python_runtime-0.10.0/continuo_python_runtime/hashing.py +0 -94
- continuo_python_runtime-0.10.0/contract/continuo_engine_contract/result.py +0 -34
- continuo_python_runtime-0.10.0/image-requirements-duckdb.txt +0 -3
- continuo_python_runtime-0.10.0/image-requirements-postgres.txt +0 -3
- continuo_python_runtime-0.10.0/image-requirements-trino.txt +0 -3
- continuo_python_runtime-0.10.0/template/Dockerfile +0 -16
- continuo_python_runtime-0.10.0/tests/test_hashing.py +0 -195
- continuo_python_runtime-0.10.0/tests/test_template.py +0 -248
- continuo_python_runtime-0.10.0/uv.lock +0 -895
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.claude/agents/ddd-architecture-auditor.md +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.dockerignore +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/CODEOWNERS +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/dependabot.yml +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/ci.yml +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/dco.yml +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/image-smoke.yml +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/images.yml +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/publish-pypi.yml +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/release.yml +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/security.yml +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/verify-packages.yml +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.gitignore +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.gitleaks.toml +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/CODE_OF_CONDUCT.md +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/DCO +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/LICENSE +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/NOTICE +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/SECURITY.md +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/__init__.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/adapter.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/application/__init__.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/application/ports.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/domain/__init__.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/domain/columns.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/domain/identifiers.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/domain/layout.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/infrastructure/__init__.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/infrastructure/ddl.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/infrastructure/extensions.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/infrastructure/passfile.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/continuo_duckdb_adapter/infrastructure/settings.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/__init__.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/conftest.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_adapter_duckdb_proxy.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_adapter_duckdb_runtime.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_adapter_duckdb_validation.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_domain_duckdb_columns.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_domain_duckdb_identifiers.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_domain_duckdb_layout.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_infra_duckdb_settings_ddl.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_integration_duckdb_layout.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_integration_duckdb_nullability_probe.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_integration_duckdb_runtime.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/duckdb/tests/test_integration_duckdb_validation.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/continuo_postgres_adapter/__init__.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/tests/__init__.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/tests/conftest.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/tests/test_adapter_runtime_postgres.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/postgres/tests/test_integration_postgres_validation.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/continuo_trino_adapter/__init__.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/tests/__init__.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/tests/test_adapter_runtime_trino.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/tests/test_adapter_trino_writes.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/tests/test_integration_runtime_trino.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/tests/test_integration_trino_merge_probe.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/adapters/trino/tests/test_integration_trino_validation.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/__init__.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/closure.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/conform.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/context.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/contract/__init__.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/contract/secret_ref.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/csv_loader.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/csv_readers/__init__.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/csv_readers/https.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/csv_readers/s3.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/csv_source.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/shape.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/types.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/validation/__init__.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/continuo_python_runtime/validation/s3.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/LICENSE +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/NOTICE +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/continuo_engine_contract/__init__.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/continuo_engine_contract/config.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/continuo_engine_contract/keys.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/continuo_engine_contract/sql.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/continuo_engine_contract/testing/__init__.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/continuo_engine_contract/types.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/tests/__init__.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/tests/test_config.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/tests/test_contract_keys.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/tests/test_contract_types.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/contract/tests/test_sql.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/scripts/apply_rehearsal_version.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/scripts/bake_duckdb_extensions.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/scripts/check_version_bumps.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/scripts/security-scan.sh +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/template/contracts/example.yml +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/template/contracts/example_csv.yml +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/template/requirements.lock +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/template/scripts/example.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/__init__.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/conftest.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/contract/__init__.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/contract/test_kinds.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/contract/test_model.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/smoke/duckdb-stack/docker-compose.yml +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/smoke/node_smoke/contracts/smoke.yml +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/smoke/node_smoke/scripts/smoke.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/smoke/postgres-stack/docker-compose.yml +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/smoke/trino-stack/catalog/iceberg.properties +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_adapter_naming.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_check_version_bumps_tags.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_ci_test_coverage.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_closure.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_conform.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_context.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_contract_loader.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_contract_pin_consistency.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_csv_loader.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_csv_readers_https.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_csv_readers_integration.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_csv_source.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_errors.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_harness_write_modes.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_image_requirements_sync.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_image_smoke_validation.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_no_legacy_names.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_package.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_python_version_consistency.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_shape.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_validation_runner.py +0 -0
- {continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/tests/test_validation_s3.py +0 -0
{continuo_python_runtime-0.10.0 → continuo_python_runtime-0.12.0}/.github/workflows/image-build.yml
RENAMED
|
@@ -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.
|
|
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
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
|
39
|
-
|
|
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
|
|
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.
|
|
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.
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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.
|
|
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
|
|
19
|
-
# the requirements install
|
|
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
|
-
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
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
|
|
32
|
+
# pre-created directory. Only the wheelhouse install reads its contents.
|
|
42
33
|
COPY wheelhous[e] /tmp/wheelhouse
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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.
|
|
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
|
|
19
|
-
# the requirements install
|
|
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
|
-
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
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
|
|
32
|
+
# pre-created directory. Only the wheelhouse install reads its contents.
|
|
42
33
|
COPY wheelhous[e] /tmp/wheelhouse
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|