continuo-python-runtime 0.9.0__tar.gz → 0.10.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.9.0 → continuo_python_runtime-0.10.0}/CHANGELOG.md +22 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/PKG-INFO +14 -5
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/README.md +12 -3
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/pyproject.toml +2 -2
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/postgres/continuo_postgres_adapter/adapter.py +1 -1
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/postgres/pyproject.toml +2 -2
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/trino/pyproject.toml +2 -2
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/contract/loader.py +17 -1
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/contract/merge.py +4 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/contract/model.py +1 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/hashing.py +8 -3
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/continuo_engine_contract/keys.py +3 -3
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/pyproject.toml +1 -1
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/docs/boundary-contract.md +12 -1
- continuo_python_runtime-0.10.0/image-requirements-duckdb.txt +3 -0
- continuo_python_runtime-0.10.0/image-requirements-postgres.txt +3 -0
- continuo_python_runtime-0.10.0/image-requirements-trino.txt +3 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/pyproject.toml +2 -2
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/template/Dockerfile +1 -1
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/contract/test_loader.py +20 -1
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/contract/test_merge.py +22 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_hashing.py +7 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/uv.lock +5 -5
- continuo_python_runtime-0.9.0/image-requirements-duckdb.txt +0 -3
- continuo_python_runtime-0.9.0/image-requirements-postgres.txt +0 -3
- continuo_python_runtime-0.9.0/image-requirements-trino.txt +0 -3
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.claude/agents/ddd-architecture-auditor.md +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.dockerignore +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/CODEOWNERS +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/dependabot.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/workflows/ci.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/workflows/dco.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/workflows/image-build.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/workflows/image-smoke.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/workflows/images.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/workflows/publish-pypi.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/workflows/release.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/workflows/security.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/workflows/verify-packages.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.gitignore +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.gitleaks.toml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.python-version +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/CLAUDE.md +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/CODE_OF_CONDUCT.md +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/CONTRIBUTING.md +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/DCO +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/Dockerfile.duckdb +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/Dockerfile.postgres +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/Dockerfile.trino +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/LICENSE +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/NOTICE +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/SECURITY.md +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/README.md +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/continuo_duckdb_adapter/__init__.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/continuo_duckdb_adapter/adapter.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/continuo_duckdb_adapter/application/__init__.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/continuo_duckdb_adapter/application/ports.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/continuo_duckdb_adapter/application/warehouse.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/continuo_duckdb_adapter/domain/__init__.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/continuo_duckdb_adapter/domain/columns.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/continuo_duckdb_adapter/domain/identifiers.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/continuo_duckdb_adapter/domain/layout.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/continuo_duckdb_adapter/infrastructure/__init__.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/continuo_duckdb_adapter/infrastructure/ddl.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/continuo_duckdb_adapter/infrastructure/extensions.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/continuo_duckdb_adapter/infrastructure/passfile.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/continuo_duckdb_adapter/infrastructure/session.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/continuo_duckdb_adapter/infrastructure/settings.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/__init__.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/conftest.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/test_adapter_duckdb_proxy.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/test_adapter_duckdb_runtime.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/test_adapter_duckdb_validation.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/test_adapter_duckdb_wiring.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/test_domain_duckdb_columns.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/test_domain_duckdb_identifiers.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/test_domain_duckdb_layout.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/test_infra_duckdb_session.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/test_infra_duckdb_settings_ddl.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/test_integration_duckdb_conformance.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/test_integration_duckdb_layout.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/test_integration_duckdb_nullability_probe.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/test_integration_duckdb_runtime.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/test_integration_duckdb_stack.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/test_integration_duckdb_validation.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/postgres/README.md +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/postgres/continuo_postgres_adapter/__init__.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/postgres/tests/__init__.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/postgres/tests/conftest.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/postgres/tests/test_adapter_postgres_validation.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/postgres/tests/test_adapter_runtime_postgres.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/postgres/tests/test_integration_postgres_conformance.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/postgres/tests/test_integration_postgres_validation.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/postgres/tests/test_integration_runtime_postgres.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/trino/README.md +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/trino/continuo_trino_adapter/__init__.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/trino/continuo_trino_adapter/adapter.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/trino/tests/__init__.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/trino/tests/test_adapter_runtime_trino.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/trino/tests/test_adapter_trino_validation.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/trino/tests/test_adapter_trino_writes.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/trino/tests/test_integration_runtime_trino.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/trino/tests/test_integration_trino_conformance.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/trino/tests/test_integration_trino_merge_probe.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/trino/tests/test_integration_trino_validation.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/__init__.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/cli.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/closure.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/conform.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/context.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/contract/__init__.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/contract/kinds.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/contract/paths.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/contract/secret_ref.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/csv_loader.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/csv_readers/__init__.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/csv_readers/https.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/csv_readers/s3.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/csv_source.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/errors.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/harness.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/lint.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/shape.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/types.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/validation/__init__.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/validation/runner.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/validation/s3.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/LICENSE +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/NOTICE +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/README.md +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/continuo_engine_contract/__init__.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/continuo_engine_contract/config.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/continuo_engine_contract/port.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/continuo_engine_contract/result.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/continuo_engine_contract/sql.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/continuo_engine_contract/testing/__init__.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/continuo_engine_contract/testing/conformance.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/continuo_engine_contract/types.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/tests/__init__.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/tests/test_config.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/tests/test_conformance_suite.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/tests/test_contract_keys.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/tests/test_contract_packaging.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/tests/test_contract_types.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/tests/test_port.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/tests/test_result.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/contract/tests/test_sql.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/scripts/apply_rehearsal_version.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/scripts/bake_duckdb_extensions.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/scripts/check_version_bumps.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/scripts/security-scan.sh +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/scripts/verify_installed_packages.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/template/.github/workflows/release.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/template/Dockerfile.pip +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/template/README.md +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/template/contracts/example.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/template/contracts/example_csv.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/template/requirements.lock +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/template/scripts/example.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/__init__.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/conftest.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/contract/__init__.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/contract/test_kinds.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/contract/test_model.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/contract/test_wire_contract_write_modes.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/fixtures/wire_contract_write_modes.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/smoke/duckdb-stack/docker-compose.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/smoke/node_smoke/contracts/smoke.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/smoke/node_smoke/scripts/smoke.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/smoke/postgres-stack/docker-compose.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/smoke/trino-stack/catalog/iceberg.properties +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/smoke/trino-stack/docker-compose.yml +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_adapter_naming.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_check_version_bumps_tags.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_ci_test_coverage.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_cli.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_closure.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_conform.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_context.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_contract_loader.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_contract_pin_consistency.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_csv_loader.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_csv_readers_https.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_csv_readers_integration.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_csv_source.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_errors.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_harness.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_harness_write_modes.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_image_requirements_sync.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_image_smoke_validation.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_kind_registries.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_lint.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_no_legacy_names.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_package.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_python_version_consistency.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_rehearsal_version.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_release_pipeline_structure.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_shape.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_template.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_types.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_validation_runner.py +0 -0
- {continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/test_validation_s3.py +0 -0
|
@@ -5,6 +5,28 @@ follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [0.10.0] - 2026-10-22
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Contracts may set `timeout_minutes` on any node: an integer from 1 to 10,080
|
|
13
|
+
that is the node's task timeout. Other values are refused as a contract
|
|
14
|
+
error naming the node. The merged wire entry carries the key only when set,
|
|
15
|
+
and it is the one wire key outside `config_hash`: changing it alone leaves
|
|
16
|
+
`config_hash` and `content_hash` unchanged. A node that does not set it has
|
|
17
|
+
the wire entry it always had.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- The "mode_type not allowed for kind" contract error now quotes the offending
|
|
22
|
+
`mode_type` and `kind` (`repr`), matching the sibling "must be one of" error,
|
|
23
|
+
so an empty or whitespace value is legible. Docstring fixes only alongside:
|
|
24
|
+
the postgres `ensure_table` port-signature reference (0.6.0 → 0.8.0) and the
|
|
25
|
+
`ensure_unique_key` message-order claim (pyarrow grouping order is not
|
|
26
|
+
contractual).
|
|
27
|
+
- The trino adapter (0.3.1) and duckdb adapter (0.2.1) release with their
|
|
28
|
+
`continuo-engine-contract` pin moved to 0.8.1; no behavior change.
|
|
29
|
+
|
|
8
30
|
## [0.9.0] - 2026-10-11
|
|
9
31
|
|
|
10
32
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: continuo-python-runtime
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.0
|
|
4
4
|
Summary: Runtime harness, contract tooling, and CI lint for Continuo python nodes.
|
|
5
5
|
Author: Simone Carolini
|
|
6
6
|
Maintainer: Simone Carolini
|
|
@@ -12,7 +12,7 @@ Classifier: Intended Audience :: Developers
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.14
|
|
13
13
|
Requires-Python: >=3.14
|
|
14
14
|
Requires-Dist: boto3==1.43.85
|
|
15
|
-
Requires-Dist: continuo-engine-contract==0.8.
|
|
15
|
+
Requires-Dist: continuo-engine-contract==0.8.1
|
|
16
16
|
Requires-Dist: pyarrow==25.0.1
|
|
17
17
|
Requires-Dist: pyyaml==6.0.3
|
|
18
18
|
Requires-Dist: sqlglot==30.17.0
|
|
@@ -196,6 +196,15 @@ produced, never how it is checked or written.
|
|
|
196
196
|
script reads with `os.environ[...]`. The contract never holds a secret value
|
|
197
197
|
or env var name; the Secret itself is created in the cluster by the operator.
|
|
198
198
|
|
|
199
|
+
### Task timeout
|
|
200
|
+
|
|
201
|
+
Any node may set `timeout_minutes:` — an integer from 1 to 10,080 (one week) —
|
|
202
|
+
to declare how long its task may run before continuo gives up on it. A value
|
|
203
|
+
outside that range, or one that is not an integer, fails
|
|
204
|
+
`continuo-runtime validate`/`merge`/`lint`. It is the one key that is not part
|
|
205
|
+
of `config_hash`, so changing only the timeout never changes the node's
|
|
206
|
+
`content_hash`.
|
|
207
|
+
|
|
199
208
|
## Write modes
|
|
200
209
|
|
|
201
210
|
`mode_type:` chooses how the harness writes a node's table on each run:
|
|
@@ -347,11 +356,11 @@ A domain repo picks its warehouse engine by which base image it builds
|
|
|
347
356
|
`FROM`:
|
|
348
357
|
|
|
349
358
|
```dockerfile
|
|
350
|
-
FROM ghcr.io/carolsimone/continuo-python-runtime-postgres:v0.
|
|
359
|
+
FROM ghcr.io/carolsimone/continuo-python-runtime-postgres:v0.10.0
|
|
351
360
|
# or
|
|
352
|
-
FROM ghcr.io/carolsimone/continuo-python-runtime-trino:v0.
|
|
361
|
+
FROM ghcr.io/carolsimone/continuo-python-runtime-trino:v0.10.0
|
|
353
362
|
# or
|
|
354
|
-
FROM ghcr.io/carolsimone/continuo-python-runtime-duckdb:v0.
|
|
363
|
+
FROM ghcr.io/carolsimone/continuo-python-runtime-duckdb:v0.10.0
|
|
355
364
|
```
|
|
356
365
|
|
|
357
366
|
The engine is part of the image **name**; the tag is the bare version, so
|
|
@@ -176,6 +176,15 @@ produced, never how it is checked or written.
|
|
|
176
176
|
script reads with `os.environ[...]`. The contract never holds a secret value
|
|
177
177
|
or env var name; the Secret itself is created in the cluster by the operator.
|
|
178
178
|
|
|
179
|
+
### Task timeout
|
|
180
|
+
|
|
181
|
+
Any node may set `timeout_minutes:` — an integer from 1 to 10,080 (one week) —
|
|
182
|
+
to declare how long its task may run before continuo gives up on it. A value
|
|
183
|
+
outside that range, or one that is not an integer, fails
|
|
184
|
+
`continuo-runtime validate`/`merge`/`lint`. It is the one key that is not part
|
|
185
|
+
of `config_hash`, so changing only the timeout never changes the node's
|
|
186
|
+
`content_hash`.
|
|
187
|
+
|
|
179
188
|
## Write modes
|
|
180
189
|
|
|
181
190
|
`mode_type:` chooses how the harness writes a node's table on each run:
|
|
@@ -327,11 +336,11 @@ A domain repo picks its warehouse engine by which base image it builds
|
|
|
327
336
|
`FROM`:
|
|
328
337
|
|
|
329
338
|
```dockerfile
|
|
330
|
-
FROM ghcr.io/carolsimone/continuo-python-runtime-postgres:v0.
|
|
339
|
+
FROM ghcr.io/carolsimone/continuo-python-runtime-postgres:v0.10.0
|
|
331
340
|
# or
|
|
332
|
-
FROM ghcr.io/carolsimone/continuo-python-runtime-trino:v0.
|
|
341
|
+
FROM ghcr.io/carolsimone/continuo-python-runtime-trino:v0.10.0
|
|
333
342
|
# or
|
|
334
|
-
FROM ghcr.io/carolsimone/continuo-python-runtime-duckdb:v0.
|
|
343
|
+
FROM ghcr.io/carolsimone/continuo-python-runtime-duckdb:v0.10.0
|
|
335
344
|
```
|
|
336
345
|
|
|
337
346
|
The engine is part of the image **name**; the tag is the bare version, so
|
{continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/pyproject.toml
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[project]
|
|
2
|
-
version = "0.2.
|
|
2
|
+
version = "0.2.1"
|
|
3
3
|
name = "continuo-duckdb-adapter"
|
|
4
4
|
description = "DuckDB (DuckLake) warehouse adapter for Continuo: validation and python-node runtime."
|
|
5
5
|
authors = [{ name = "Simone Carolini" }]
|
|
@@ -10,7 +10,7 @@ dependencies = [
|
|
|
10
10
|
# Pinned exactly for the same reason as the postgres adapter: the
|
|
11
11
|
# [tool.uv.sources] redirect below is uv-only and never reaches built
|
|
12
12
|
# metadata, and this adapter subclasses the contract's port directly.
|
|
13
|
-
"continuo-engine-contract==0.8.
|
|
13
|
+
"continuo-engine-contract==0.8.1",
|
|
14
14
|
"duckdb==1.5.6",
|
|
15
15
|
"pyarrow==25.0.1",
|
|
16
16
|
]
|
|
@@ -706,7 +706,7 @@ class PostgresAdapter(WarehouseAdapter, AppendCapable, UpsertCapable):
|
|
|
706
706
|
this engine's physical-layout vocabulary — ``indexes`` — validated by
|
|
707
707
|
:func:`_validated_indexes` before any DDL runs, so a malformed config
|
|
708
708
|
never leaves a half-built table behind (fail closed). Required and
|
|
709
|
-
keyword-only, matching the contract 0.
|
|
709
|
+
keyword-only, matching the contract 0.8.0 port signature. The create
|
|
710
710
|
and every index either all land or none do, in the same explicit
|
|
711
711
|
BEGIN/COMMIT/ROLLBACK shape build_empty_from_columns uses.
|
|
712
712
|
|
{continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/postgres/pyproject.toml
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[project]
|
|
2
|
-
version = "0.3.
|
|
2
|
+
version = "0.3.1"
|
|
3
3
|
name = "continuo-postgres-adapter"
|
|
4
4
|
description = "Postgres warehouse adapter for Continuo: validation and python-node runtime."
|
|
5
5
|
authors = [{ name = "Simone Carolini" }]
|
|
@@ -12,7 +12,7 @@ dependencies = [
|
|
|
12
12
|
# of this adapter would otherwise accept whatever contract release is
|
|
13
13
|
# newest. This adapter subclasses the contract's WarehouseAdapter port
|
|
14
14
|
# directly, so the pair must stay the tested one.
|
|
15
|
-
"continuo-engine-contract==0.8.
|
|
15
|
+
"continuo-engine-contract==0.8.1",
|
|
16
16
|
"psycopg2-binary==2.9.12",
|
|
17
17
|
"pyarrow==25.0.1",
|
|
18
18
|
]
|
{continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/trino/pyproject.toml
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[project]
|
|
2
|
-
version = "0.3.
|
|
2
|
+
version = "0.3.1"
|
|
3
3
|
name = "continuo-trino-adapter"
|
|
4
4
|
description = "Trino warehouse adapter for Continuo: validation and python-node runtime."
|
|
5
5
|
authors = [{ name = "Simone Carolini" }]
|
|
@@ -12,7 +12,7 @@ dependencies = [
|
|
|
12
12
|
# of this adapter would otherwise accept whatever contract release is
|
|
13
13
|
# newest. This adapter subclasses the contract's WarehouseAdapter port
|
|
14
14
|
# directly, so the pair must stay the tested one.
|
|
15
|
-
"continuo-engine-contract==0.8.
|
|
15
|
+
"continuo-engine-contract==0.8.1",
|
|
16
16
|
"trino==0.339.0",
|
|
17
17
|
"pyarrow==25.0.1",
|
|
18
18
|
]
|
|
@@ -44,8 +44,13 @@ _ALLOWED_KEYS = {
|
|
|
44
44
|
"secret_ref",
|
|
45
45
|
"mode_type",
|
|
46
46
|
"primary_key",
|
|
47
|
+
"timeout_minutes",
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
# Bounds of a node's declared task timeout, in minutes (one minute to one week).
|
|
51
|
+
MIN_TIMEOUT_MINUTES = 1
|
|
52
|
+
MAX_TIMEOUT_MINUTES = 10_080
|
|
53
|
+
|
|
49
54
|
_REQUIRED_STRING_FIELDS = ("schema", "table", "owner", "schedule")
|
|
50
55
|
|
|
51
56
|
_ALLOWED_OUTPUT_COLUMN_KEYS = {"name", "type", "nullable"}
|
|
@@ -295,6 +300,16 @@ def parse_node(
|
|
|
295
300
|
raise ContractError(f"{label}: 'secret_ref' is not allowed for kind {kind}")
|
|
296
301
|
secret_ref = validate_secret_ref(raw["secret_ref"], label)
|
|
297
302
|
|
|
303
|
+
timeout_minutes = raw.get("timeout_minutes")
|
|
304
|
+
if "timeout_minutes" in raw and (
|
|
305
|
+
type(timeout_minutes) is not int
|
|
306
|
+
or not MIN_TIMEOUT_MINUTES <= timeout_minutes <= MAX_TIMEOUT_MINUTES
|
|
307
|
+
):
|
|
308
|
+
raise ContractError(
|
|
309
|
+
f"{label}: 'timeout_minutes' must be an integer between "
|
|
310
|
+
f"{MIN_TIMEOUT_MINUTES} and {MAX_TIMEOUT_MINUTES}, got {timeout_minutes!r}"
|
|
311
|
+
)
|
|
312
|
+
|
|
298
313
|
mode_type = raw.get("mode_type", DEFAULT_MODE_TYPE)
|
|
299
314
|
if not isinstance(mode_type, str) or mode_type not in MODE_TYPES:
|
|
300
315
|
raise ContractError(
|
|
@@ -302,7 +317,7 @@ def parse_node(
|
|
|
302
317
|
)
|
|
303
318
|
if mode_type not in rules.mode_types:
|
|
304
319
|
raise ContractError(
|
|
305
|
-
f"{label}: 'mode_type' {mode_type} is not allowed for kind {kind} "
|
|
320
|
+
f"{label}: 'mode_type' {mode_type!r} is not allowed for kind {kind!r} "
|
|
306
321
|
f"(allowed: {sorted(rules.mode_types)})"
|
|
307
322
|
)
|
|
308
323
|
|
|
@@ -375,6 +390,7 @@ def parse_node(
|
|
|
375
390
|
secret_ref=secret_ref,
|
|
376
391
|
mode_type=mode_type,
|
|
377
392
|
primary_key=primary_key,
|
|
393
|
+
timeout_minutes=timeout_minutes,
|
|
378
394
|
)
|
|
379
395
|
|
|
380
396
|
|
|
@@ -170,6 +170,10 @@ def build_wire_contract(
|
|
|
170
170
|
|
|
171
171
|
primary_bytes, member_bytes = _HASH_INPUTS[node.kind](node, repo_root)
|
|
172
172
|
entry.update(hash_parts(entry, primary_bytes, member_bytes))
|
|
173
|
+
# The one wire key outside config_hash: it is written after the hashes
|
|
174
|
+
# are computed, so changing it alone never changes content_hash.
|
|
175
|
+
if node.timeout_minutes is not None:
|
|
176
|
+
entry["timeout_minutes"] = node.timeout_minutes
|
|
173
177
|
|
|
174
178
|
wire_nodes.append(entry)
|
|
175
179
|
|
{continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/continuo_python_runtime/hashing.py
RENAMED
|
@@ -21,6 +21,10 @@ from json import dumps
|
|
|
21
21
|
|
|
22
22
|
HASH_PART_FIELDS = ("source_hash", "shared_code_hash", "config_hash")
|
|
23
23
|
CONTENT_HASH_FIELD = "content_hash"
|
|
24
|
+
# A wire key that is not part of the config_hash basis: it tunes how the node
|
|
25
|
+
# runs (the task timeout) and says nothing about what the node computes, so
|
|
26
|
+
# changing it alone is not a code change.
|
|
27
|
+
NON_HASHED_FIELDS = ("timeout_minutes",)
|
|
24
28
|
|
|
25
29
|
|
|
26
30
|
def canonical_entry(entry: dict) -> dict:
|
|
@@ -28,13 +32,14 @@ def canonical_entry(entry: dict) -> dict:
|
|
|
28
32
|
|
|
29
33
|
Drops ``content_hash`` and all three of ``HASH_PART_FIELDS`` from the
|
|
30
34
|
basis, and whitespace-normalizes every ``str`` value in ``reads`` via
|
|
31
|
-
``" ".join(sql.split())``.
|
|
32
|
-
|
|
35
|
+
``" ".join(sql.split())``. ``timeout_minutes`` is the one other wire key
|
|
36
|
+
left out of the basis (``NON_HASHED_FIELDS``). Everything else is
|
|
37
|
+
preserved verbatim, including ``config``.
|
|
33
38
|
"""
|
|
34
39
|
canonical = deepcopy(entry)
|
|
35
40
|
|
|
36
41
|
canonical.pop(CONTENT_HASH_FIELD, None)
|
|
37
|
-
for field in HASH_PART_FIELDS:
|
|
42
|
+
for field in (*HASH_PART_FIELDS, *NON_HASHED_FIELDS):
|
|
38
43
|
canonical.pop(field, None)
|
|
39
44
|
|
|
40
45
|
reads = canonical.get("reads")
|
|
@@ -29,9 +29,9 @@ def ensure_unique_key(data: "pyarrow.Table", primary_key: Sequence[str]) -> None
|
|
|
29
29
|
Groups the rows by the key columns. NULL counts as a value here; the
|
|
30
30
|
contract requires every key column to be ``nullable: false`` and the
|
|
31
31
|
harness's ``conform()`` rejects NULLs in such columns before this runs.
|
|
32
|
-
The message names the
|
|
33
|
-
|
|
34
|
-
needs no pyarrow import.
|
|
32
|
+
The message names up to a fixed number of the repeated keys with their row
|
|
33
|
+
counts; their order follows pyarrow's grouping and is not contractual. Only
|
|
34
|
+
methods of *data* are called, so this module needs no pyarrow import.
|
|
35
35
|
|
|
36
36
|
Raises:
|
|
37
37
|
ValueError: If *primary_key* is empty, names a column *data* lacks, or
|
|
@@ -61,6 +61,16 @@ s3://<bucket>/<service>/<release_id>/contract.yaml
|
|
|
61
61
|
node's wire entry or `config_hash` changes), and it is part of
|
|
62
62
|
`config_hash`, so `content_hash` changes when the referenced Secret name
|
|
63
63
|
changes. `source_hash` does not.
|
|
64
|
+
- **`timeout_minutes`** is additive and optional, valid on every `kind`: an
|
|
65
|
+
integer from 1 to 10,080 (one week) that is the node's task timeout. Any
|
|
66
|
+
other value (zero, above the bound, a string, a float, a boolean) fails
|
|
67
|
+
`ContractError` naming the node and the key. On the merged wire entry it
|
|
68
|
+
appears only when the node declares it, and it is the one wire key **outside
|
|
69
|
+
`config_hash`**: it is written after the hash parts are computed and is
|
|
70
|
+
excluded from the `config_hash` basis, so changing it alone changes none of
|
|
71
|
+
the four hashes and is not a code change. A node that does not declare it
|
|
72
|
+
has the wire entry, `config_hash` and `content_hash` it always had, and
|
|
73
|
+
`contract_version` stays 1.
|
|
64
74
|
- **`mode_type`** and **`primary_key`** are additive and optional. `mode_type`
|
|
65
75
|
(`replace`, the default; `append`; `upsert`) says how the harness writes
|
|
66
76
|
the node's table on each run; `python-csv` allows only `replace`.
|
|
@@ -222,7 +232,8 @@ content_hash = "sha256:" + sha256(source_hash + "|" + shared_code_hash
|
|
|
222
232
|
collapse to a single space, then stripped); `content_hash` **and all
|
|
223
233
|
three part fields** (`source_hash`, `shared_code_hash`, `config_hash`)
|
|
224
234
|
are excluded from the basis — `config_hash` cannot include itself, and
|
|
225
|
-
none of the four hash fields participates in another's basis.
|
|
235
|
+
none of the four hash fields participates in another's basis. So is
|
|
236
|
+
`timeout_minutes`, the one non-hash wire key left out of the basis. Every
|
|
226
237
|
other field, including `config`, participates verbatim.
|
|
227
238
|
|
|
228
239
|
Invariant: formatting-only edits (spaces in SQL, yaml indentation/key
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "continuo-python-runtime"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.10.0"
|
|
4
4
|
description = "Runtime harness, contract tooling, and CI lint for Continuo python nodes."
|
|
5
5
|
authors = [{ name = "Simone Carolini" }]
|
|
6
6
|
maintainers = [{ name = "Simone Carolini" }]
|
|
@@ -19,7 +19,7 @@ dependencies = [
|
|
|
19
19
|
# directly. Both packages ship from this repo on one v* tag, so a new
|
|
20
20
|
# contract version never exists without a new runtime version to match it;
|
|
21
21
|
# an exact pin therefore costs nothing and keeps the tested pair together.
|
|
22
|
-
"continuo-engine-contract==0.8.
|
|
22
|
+
"continuo-engine-contract==0.8.1",
|
|
23
23
|
"boto3==1.43.85",
|
|
24
24
|
"pyarrow==25.0.1",
|
|
25
25
|
"PyYAML==6.0.3",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# Tags are v<version>; one image per engine (continuo-python-runtime-postgres / -trino).
|
|
2
|
-
FROM ghcr.io/carolsimone/continuo-python-runtime-postgres:v0.
|
|
2
|
+
FROM ghcr.io/carolsimone/continuo-python-runtime-postgres:v0.10.0
|
|
3
3
|
COPY contracts/ /app/contracts/
|
|
4
4
|
COPY scripts/ /app/scripts/
|
|
5
5
|
# COPY every OTHER directory your scripts import from, too. CI folds a script's
|
{continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/contract/test_loader.py
RENAMED
|
@@ -786,7 +786,7 @@ def test_python_csv_only_allows_replace(mode):
|
|
|
786
786
|
entry = _csv_entry(mode_type=mode)
|
|
787
787
|
if mode == "upsert":
|
|
788
788
|
entry["primary_key"] = ["order_id"]
|
|
789
|
-
with pytest.raises(ContractError, match=f"'mode_type' {mode} is not allowed for kind python-csv"):
|
|
789
|
+
with pytest.raises(ContractError, match=f"'mode_type' '{mode}' is not allowed for kind 'python-csv'"):
|
|
790
790
|
parse_node(entry, "f.yml", check_reads=False)
|
|
791
791
|
|
|
792
792
|
|
|
@@ -878,3 +878,22 @@ def test_primary_key_names_a_column_that_differs_only_in_case_from_another():
|
|
|
878
878
|
entry["output_columns"].append({"name": "Base", "type": "VARCHAR(3)", "nullable": False})
|
|
879
879
|
node = parse_node(entry, "c.yml")
|
|
880
880
|
assert node.primary_key == ("rate_date", "Base")
|
|
881
|
+
|
|
882
|
+
|
|
883
|
+
# --- timeout_minutes ------------------------------------------------------------
|
|
884
|
+
|
|
885
|
+
|
|
886
|
+
def test_timeout_minutes_is_read():
|
|
887
|
+
assert parse_node({**VALID, "timeout_minutes": 120}, "f.yml").timeout_minutes == 120
|
|
888
|
+
assert parse_node({**VALID, "timeout_minutes": 1}, "f.yml").timeout_minutes == 1
|
|
889
|
+
assert parse_node({**VALID, "timeout_minutes": 10080}, "f.yml").timeout_minutes == 10080
|
|
890
|
+
|
|
891
|
+
|
|
892
|
+
def test_timeout_minutes_defaults_to_none():
|
|
893
|
+
assert parse_node(VALID, "f.yml").timeout_minutes is None
|
|
894
|
+
|
|
895
|
+
|
|
896
|
+
@pytest.mark.parametrize("bad", [0, 10081, "2h", 1.5, True])
|
|
897
|
+
def test_a_bad_timeout_minutes_is_refused(bad):
|
|
898
|
+
with pytest.raises(ContractError, match=r"f\.yml \(analytics\.t\): 'timeout_minutes'"):
|
|
899
|
+
parse_node({**VALID, "timeout_minutes": bad}, "f.yml")
|
{continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/tests/contract/test_merge.py
RENAMED
|
@@ -617,3 +617,25 @@ def test_a_replace_entry_hashes_exactly_as_it_did_before_write_modes(extra):
|
|
|
617
617
|
entry = node_entry(parse_node({**_REPLACE_NODE, **extra}, "f.yml"))
|
|
618
618
|
assert "mode_type" not in entry and "primary_key" not in entry
|
|
619
619
|
assert config_hash(entry) == _PRE_WRITE_MODES_CONFIG_HASH
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
# --- timeout_minutes ----------------------------------------------------------
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
def test_timeout_minutes_is_outside_the_config_hash(tmp_path):
|
|
626
|
+
without = _only_entry(_modes_repo(tmp_path / "a"))
|
|
627
|
+
short = _only_entry(_modes_repo(tmp_path / "b", timeout_minutes=120))
|
|
628
|
+
long = _only_entry(_modes_repo(tmp_path / "c", timeout_minutes=480))
|
|
629
|
+
assert short["config_hash"] == long["config_hash"] == without["config_hash"]
|
|
630
|
+
assert short["content_hash"] == long["content_hash"] == without["content_hash"]
|
|
631
|
+
# The wire entry hashes exactly as the same entry would without the key.
|
|
632
|
+
assert config_hash(short) == short["config_hash"]
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
def test_the_wire_entry_carries_timeout_minutes_only_when_set(tmp_path):
|
|
636
|
+
without = _only_entry(_modes_repo(tmp_path / "a"))
|
|
637
|
+
declared = _only_entry(_modes_repo(tmp_path / "b", timeout_minutes=120))
|
|
638
|
+
assert "timeout_minutes" not in without
|
|
639
|
+
assert set(without) == WIRE_ENTRY_KEYS
|
|
640
|
+
assert declared["timeout_minutes"] == 120
|
|
641
|
+
assert set(declared) == WIRE_ENTRY_KEYS | {"timeout_minutes"}
|
|
@@ -186,3 +186,10 @@ def test_hash_parts_returns_four_keys_and_consistent_fold():
|
|
|
186
186
|
assert parts["content_hash"] == content_hash_fold(
|
|
187
187
|
parts["source_hash"], parts["shared_code_hash"], parts["config_hash"]
|
|
188
188
|
)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def test_timeout_minutes_is_outside_the_config_hash_basis():
|
|
192
|
+
with_timeout = {**ENTRY, "timeout_minutes": 120}
|
|
193
|
+
assert "timeout_minutes" not in canonical_entry(with_timeout)
|
|
194
|
+
assert config_hash(with_timeout) == config_hash(ENTRY)
|
|
195
|
+
assert config_hash({**ENTRY, "timeout_minutes": 480}) == config_hash(ENTRY)
|
|
@@ -162,7 +162,7 @@ wheels = [
|
|
|
162
162
|
|
|
163
163
|
[[package]]
|
|
164
164
|
name = "continuo-duckdb-adapter"
|
|
165
|
-
version = "0.2.
|
|
165
|
+
version = "0.2.1"
|
|
166
166
|
source = { editable = "adapters/duckdb" }
|
|
167
167
|
dependencies = [
|
|
168
168
|
{ name = "continuo-engine-contract" },
|
|
@@ -203,7 +203,7 @@ test = [
|
|
|
203
203
|
|
|
204
204
|
[[package]]
|
|
205
205
|
name = "continuo-engine-contract"
|
|
206
|
-
version = "0.8.
|
|
206
|
+
version = "0.8.1"
|
|
207
207
|
source = { editable = "contract" }
|
|
208
208
|
dependencies = [
|
|
209
209
|
{ name = "sqlglot" },
|
|
@@ -225,7 +225,7 @@ provides-extras = ["testing"]
|
|
|
225
225
|
|
|
226
226
|
[[package]]
|
|
227
227
|
name = "continuo-postgres-adapter"
|
|
228
|
-
version = "0.3.
|
|
228
|
+
version = "0.3.1"
|
|
229
229
|
source = { editable = "adapters/postgres" }
|
|
230
230
|
dependencies = [
|
|
231
231
|
{ name = "continuo-engine-contract" },
|
|
@@ -262,7 +262,7 @@ test = [
|
|
|
262
262
|
|
|
263
263
|
[[package]]
|
|
264
264
|
name = "continuo-python-runtime"
|
|
265
|
-
version = "0.
|
|
265
|
+
version = "0.10.0"
|
|
266
266
|
source = { editable = "." }
|
|
267
267
|
dependencies = [
|
|
268
268
|
{ name = "boto3" },
|
|
@@ -305,7 +305,7 @@ test = [
|
|
|
305
305
|
|
|
306
306
|
[[package]]
|
|
307
307
|
name = "continuo-trino-adapter"
|
|
308
|
-
version = "0.3.
|
|
308
|
+
version = "0.3.1"
|
|
309
309
|
source = { editable = "adapters/trino" }
|
|
310
310
|
dependencies = [
|
|
311
311
|
{ name = "continuo-engine-contract" },
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/ISSUE_TEMPLATE/config.yml
RENAMED
|
File without changes
|
|
File without changes
|
{continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/PULL_REQUEST_TEMPLATE.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/workflows/image-build.yml
RENAMED
|
File without changes
|
{continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/workflows/image-smoke.yml
RENAMED
|
File without changes
|
{continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/workflows/images.yml
RENAMED
|
File without changes
|
{continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/workflows/publish-pypi.yml
RENAMED
|
File without changes
|
{continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/workflows/release.yml
RENAMED
|
File without changes
|
{continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/.github/workflows/security.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/__init__.py
RENAMED
|
File without changes
|
{continuo_python_runtime-0.9.0 → continuo_python_runtime-0.10.0}/adapters/duckdb/tests/conftest.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|