vgi-python 0.36.2__tar.gz → 0.37.1__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.
- {vgi_python-0.36.2 → vgi_python-0.37.1}/PKG-INFO +1 -1
- {vgi_python-0.36.2 → vgi_python-0.37.1}/pyproject.toml +1 -1
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_serve.py +157 -1
- {vgi_python-0.36.2 → vgi_python-0.37.1}/uv.lock +1 -1
- vgi_python-0.37.1/vgi/_test_fixtures/secret_cache.py +237 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/__init__.py +2 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/partition_columns.py +126 -1
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/worker.py +35 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/auth.py +12 -3
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/serve.py +15 -7
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/worker.py +75 -1
- {vgi_python-0.36.2 → vgi_python-0.37.1}/.dockerignore +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/.gitattributes +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/.github/dependabot.yml +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/.github/styles/config/vocabularies/VGI/accept.txt +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/.github/workflows/ci.yml +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/.github/workflows/docs.yml +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/.github/workflows/integration.yml +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/.github/workflows/release.yml +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/.github/workflows/tailnet-integration.yml +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/.gitignore +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/.python-version +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/.vale.ini +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/CLAUDE.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/DOCS_ACCEPTANCE_CRITERIA.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/DOCS_REVIEW_RUBRIC.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/DOCS_USABILITY_TEST.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/LICENSE +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/PROTOCOL.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/README.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/RELEASE-RUNBOOK.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/SECURITY.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/ci/README.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/ci/preprocess-require.awk +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/ci/run-integration.sh +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/README.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/cases/negative/and-too-few-children.json +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/cases/negative/delta-required-upsert.json +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/cases/negative/nested-runtime-filter.json +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/cases/negative/remove-with-expression.json +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/cases/negative/required-runtime-filter.json +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/cases/negative/snapshot-nonzero-revision.json +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/cases/negative/unknown-document-property.json +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/cases/negative/unknown-node.json +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/cases/positive/advisory-upsert-delta.json +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/cases/positive/boolean-column-predicate.json +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/cases/positive/empty-snapshot.json +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/cases/positive/nested-required-snapshot.json +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/cases/positive/remove-delta.json +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/cases/positive/runtime-filter-snapshot.json +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/filter-v2.schema.json +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/generate_runtime.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/manifest.json +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/run_worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/arithmetic-add/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/arithmetic-add/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/arithmetic-add/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/arithmetic-multiply/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/arithmetic-multiply/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/arithmetic-multiply/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/arithmetic-negate/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/arithmetic-negate/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/arithmetic-negate/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/arithmetic-subtract/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/arithmetic-subtract/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/arithmetic-subtract/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/cast-integer-to-double/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/cast-integer-to-double/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/cast-integer-to-double/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-distinct_from/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-distinct_from/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-distinct_from/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-distinct_from/worker-expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-eq/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-eq/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-eq/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-eq/worker-expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-ge/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-ge/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-ge/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-ge/worker-expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-gt/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-gt/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-gt/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-gt/worker-expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-le/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-le/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-le/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-le/worker-expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-lt/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-lt/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-lt/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-lt/worker-expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-ne/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-ne/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-ne/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-ne/worker-expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-not_distinct_from/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-not_distinct_from/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-not_distinct_from/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/comparison-not_distinct_from/worker-expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/delta-atomic-multi-update/delta-0.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/delta-atomic-multi-update/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/delta-atomic-multi-update/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/delta-atomic-multi-update/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/delta-empty-noop/delta-0.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/delta-empty-noop/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/delta-empty-noop/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/delta-empty-noop/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/delta-upsert-remove-stale/delta-0.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/delta-upsert-remove-stale/delta-1.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/delta-upsert-remove-stale/delta-2.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/delta-upsert-remove-stale/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/delta-upsert-remove-stale/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/delta-upsert-remove-stale/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/empty-snapshot/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/empty-snapshot/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/empty-snapshot/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/empty-snapshot/worker-expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-cast-type-not-null/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-cast-type-not-null/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-column-index/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-column-index/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-column-name/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-column-name/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-contextual-cast-without-session/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-contextual-cast-without-session/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-duplicate-predicate-id/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-duplicate-predicate-id/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-external-column-index/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-external-column-index/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-external-column-index/join-keys-0.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-external-column-name/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-external-column-name/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-external-column-name/join-keys-0.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-field-non-struct/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-field-non-struct/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-in-payload-not-list/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-in-payload-not-list/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-in-payload-null-list/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-in-payload-null-list/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-invalid-overload/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-invalid-overload/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-missing-literal/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-missing-literal/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-non-boolean-root/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-non-boolean-root/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-unknown-standard-function/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/error-unknown-standard-function/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/external-in-nonzero-column/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/external-in-nonzero-column/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/external-in-nonzero-column/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/external-in-nonzero-column/join-keys-0.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/external-in-nonzero-column/worker-expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/function-contains/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/function-contains/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/function-contains/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/function-ends-with/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/function-ends-with/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/function-ends-with/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/function-list-contains/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/function-list-contains/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/function-list-contains/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/function-starts-with/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/function-starts-with/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/function-starts-with/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/in-empty/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/in-empty/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/in-empty/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/in-empty/worker-expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/in-with-null/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/in-with-null/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/in-with-null/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/in-with-null/worker-expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/is-not-null/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/is-not-null/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/is-not-null/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/is-not-null/worker-expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/is-null/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/is-null/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/is-null/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/is-null/worker-expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/kleene-and/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/kleene-and/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/kleene-and/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/kleene-not/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/kleene-not/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/kleene-not/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/kleene-or/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/kleene-or/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/kleene-or/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/nan-comparison/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/nan-comparison/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/nan-comparison/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/negative-zero-membership/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/negative-zero-membership/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/negative-zero-membership/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/nested-null-propagation/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/nested-null-propagation/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/nested-null-propagation/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/not-in-empty/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/not-in-empty/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/not-in-empty/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/not-in-empty/worker-expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/not-in-with-null/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/not-in-with-null/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/not-in-with-null/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/not-in-with-null/worker-expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/session-integer-division/expected.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/session-integer-division/filter.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime/session-integer-division/input.arrow +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/conformance/filter-v2/runtime-manifest.json +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/dist-vgi/.gitignore +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/aggregate-functions.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/api/arguments.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/api/auth.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/api/catalogs.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/api/client.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/api/exceptions.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/api/filters.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/api/functions.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/api/http.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/api/index.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/api/metadata.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/api/observability.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/api/storage.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/api/transactor.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/api/worker.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/argument-serialization.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/assets/apple-touch-icon.png +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/assets/favicon-16x16.png +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/assets/favicon-32x32.png +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/assets/favicon.ico +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/assets/kinds/aggregate.svg +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/assets/kinds/buffering.svg +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/assets/kinds/scalar.svg +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/assets/kinds/table-in-out.svg +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/assets/kinds/table.svg +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/assets/logo.png +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/assets/social-card.png +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/authentication.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/catalog-interface.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/cli.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/column-statistics.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/concepts/index.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/contributing-docs.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/filter-pushdown.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/generator-api.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/global-functions.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/how-to/catalogs.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/how-to/function-patterns.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/how-to/http-auth.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/how-to/index.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/how-to/iroh.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/how-to/pushdown-and-statistics.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/how-to/state-storage.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/how-to/tailnet.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/index.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/lifecycle.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/metadata.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/overrides/main.html +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/protocol/index.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/protocol/vgi-catalog-query-pushdown-design.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/protocol/vgi-duckdb-filter-adapter.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/protocol/vgi-filter-encoding-v2-spec.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/protocol/vgi-protocol-proposed-changes.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/protocol/vgi-runtime-filter-artifacts.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/robots.txt +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/shared-storage.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/stylesheets/extra.css +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/tutorial/index.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/tutorial/scalar.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/tutorial/table.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/docs/vgi-logo.png +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/examples/batch_index_worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/examples/cache_worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/examples/calc_scalar_worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/examples/calc_worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/examples/copy_format_worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/examples/filter_worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/examples/greeting_scalar_worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/examples/row_count_worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/examples/series_streaming_worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/examples/sum_worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/identity.png +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/mkdocs.yml +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/packages/vgi-fixtures/LICENSE +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/packages/vgi-fixtures/README.md +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/packages/vgi-fixtures/docker/Dockerfile +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/packages/vgi-fixtures/docker/docker-entrypoint.sh +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/packages/vgi-fixtures/pyproject.toml +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/scripts/measure_startup.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/scripts/regen_generated.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/scripts/run_all_tests.sh +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/test-data/generate.sh +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/_http_fixtures.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/catalog/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/catalog/test_attach_option.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/catalog/test_catalog_interface.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/catalog/test_client_catalog.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/catalog/test_column_statistics.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/catalog/test_declarative.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/catalog/test_example_worker_catalog.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/catalog/test_integration.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/catalog/test_required_filters.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/catalog/test_scan_branches.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/catalog/test_serialization.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/catalog/test_setting.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/catalog/test_storage.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/catalog/test_time_travel.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/catalog/test_writable_table.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/client/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/client/test_aggregate_client.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/client/test_batch_metadata_callback.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/client/test_bind_and_join_keys.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/client/test_broken_pipe.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/client/test_cli.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/client/test_cli_catalog_functions.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/client/test_copy_client.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/client/test_http_response_budget.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/client/test_iroh_client.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/client/test_scan_branches_client.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/client/test_split_client.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/client/test_stop_force.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/client/test_table_column_statistics.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/client/test_time_travel_client.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/client/test_worker_debug.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/_stub.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/conftest.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_accumulate.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_aggregate.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_attach.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_bearer_auth.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_const_param_enforcement.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_container.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_copy_from.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_copy_to.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_directory_parity.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_function_inventory.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_github.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_http_client.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_http_external_location.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_http_upload_url.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_macro.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_overload.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_protocol_inventory.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_protocol_version.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_resumable_scan.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_scalar.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_scalar_attach_opaque_data.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_secret.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_settings.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_splits.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_table.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_table_in_out.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_view.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conformance/test_writable.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/conftest.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/data/split_tokens/anchor_len_overrun.bin +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/data/split_tokens/bad_fingerprint.bin +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/data/split_tokens/bad_flags_unsealed_but_key_present.bin +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/data/split_tokens/bad_version.bin +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/data/split_tokens/generate.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/data/split_tokens/manifest.json +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/data/split_tokens/reserved_flag_bit.bin +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/data/split_tokens/stale_anchor.bin +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/data/split_tokens/truncated.bin +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/data/split_tokens/valid_sealed.bin +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/data/split_tokens/valid_unsealed.bin +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/scalar/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/scalar/test_bernoulli_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/scalar/test_binary_packet_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/scalar/test_client.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/scalar/test_conditional_message_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/scalar/test_hash_seed_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/scalar/test_multiply_by_setting_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/scalar/test_multiply_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/scalar/test_random_bytes_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/scalar/test_return_secret_value_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table/generator/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table/generator/test_constant_columns_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table/generator/test_double_sequence_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table/generator/test_exception_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table/generator/test_filter_echo_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table/generator/test_logging_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table/generator/test_nested_sequence_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table/generator/test_partitioned_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table/generator/test_projected_data_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table/generator/test_sequence_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table/generator/test_settings_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table/generator/test_struct_settings_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table/generator/test_ten_thousand_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table/test_wide_columns.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table_in_out/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table_in_out/generator/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table_in_out/generator/test_buffer_input_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table_in_out/generator/test_echo_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table_in_out/generator/test_exception_functions.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table_in_out/generator/test_filter_by_setting_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table_in_out/generator/test_repeat_inputs_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table_in_out/generator/test_substream_partial_sum_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table_in_out/generator/test_sum_all_columns_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table_in_out/test_blended_exchange.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table_in_out/test_blended_metadata.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/table_in_out/test_client.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/tailnet/Dockerfile +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/tailnet/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/tailnet/compose.yaml +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/tailnet/probe.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/tailnet/run.sh +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/tailnet/test_worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/tailnet/worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_access_log_audit.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_aggregate_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_argument_spec.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_auth.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_bind_exceptions.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_bind_request_at_clause.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_bound_storage_conformance.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_cache_control.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_call_state_attach.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_catalog_auth_binding.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_client_oauth.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_codegen_request_inventory.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_copy_from_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_copy_to_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_docstrings.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_documentation_examples.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_dynamic_filter_http_turns.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_example_function_arg_types.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_examples_workers.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_exception_handling.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_exceptions.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_filter_pushdown.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_filter_pushdown_extension.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_filter_v2.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_filter_v2_builder.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_filter_v2_runtime_corpus.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_filter_v2_spec_schema.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_fixture_catalog_parity.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_function_shape_mismatch.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_function_storage.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_function_storage_azure_sql.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_function_storage_cf_do.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_function_storage_cf_do_integration.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_function_storage_conformance.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_generated_cpp_constants.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_generated_cpp_protocol_name.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_generated_cpp_protocol_version.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_generated_cpp_request_builders.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_generated_cpp_schemas.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_generated_cpp_secret.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_generated_go_schemas.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_generated_java_schemas.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_generated_protocol_version.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_generated_rust_request_builders.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_generated_rust_schemas.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_generated_schemas_cross_lang.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_generated_ts_client.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_generated_ts_schemas.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_http_demo_storage.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_http_s3_offload_input.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_http_s3_offload_output.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_import_side_effects.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_launch_transport.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_metadata.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_mypy_consolidated.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_nest_tensor.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_otel.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_projection_enforcement.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_projection_repro.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_protocol_classes.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_resolved_secrets.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_schema_paths_v2.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_schema_scoped_functions.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_schema_utils.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_setting_secret_annotations.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_signing_key.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_split_token.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_subprocess_transport.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_table_buffering_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_table_function_dynamic_to_string.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_tcp_transport.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_type_bounds.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_union_argument.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_wire_record_schema_parity.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_worker_cli.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_worker_page.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/test_write_results.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/transactor/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/tests/transactor/test_transactor.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_duckdb.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_storage_profile.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/accumulate/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/accumulate/worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/aggregate/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/aggregate/_common.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/aggregate/basic.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/aggregate/dynamic.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/aggregate/generic.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/aggregate/listagg.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/aggregate/percentile.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/aggregate/same_name.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/aggregate/secret_typed.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/aggregate/streaming.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/aggregate/varargs.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/aggregate/window.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/attach_options.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/bad_enum.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/bad_protocol.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/cancellable.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/catalog.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/companion.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/copy_from.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/copy_to.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/global_functions.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/http_server.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/narrow_bind/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/narrow_bind/worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/nest_tensor.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/orchard_catalog.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/projection_repro/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/projection_repro/worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/scalar/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/scalar/_common.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/scalar/arithmetic.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/scalar/bench_ladder.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/scalar/binary.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/scalar/formatting.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/scalar/geo.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/scalar/null_handling.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/scalar/random_demo.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/scalar/same_name.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/scalar/settings_secrets.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/scalar/type_info.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/schema_reconcile/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/schema_reconcile/worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/simple_writable.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/_common.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/batch_index.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/batch_index_broken.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/cache.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/catalog_scans.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/filters.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/late_materialization.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/make_series.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/misc.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/order_modes.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/pairs.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/partition_columns_broken.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/profiling_example.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/required_filters.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/same_name_cached.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/same_name_schemas.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/sequence.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/settings.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/splits.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/transaction_storage.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/tt_pushdown.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/typed_probe.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/versioned.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table/wide.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table_in_out.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/table_in_out_same_name.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/twin_catalogs.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/versioned.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/versioned_tables.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/writable/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/writable/generic.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/writable/table.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/_test_fixtures/writable/worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/aggregate_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/argument_spec.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/arguments.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/attach_header.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/cache_control.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/catalog/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/catalog/_descriptor_spec.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/catalog/attach_option.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/catalog/catalog_interface.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/catalog/descriptors.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/catalog/duckdb_statistics.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/catalog/secret_type.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/catalog/setting.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/catalog/storage.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/client/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/client/aggregate.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/client/catalog_mixin.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/client/cli.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/client/cli_catalog.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/client/cli_schema.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/client/cli_table.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/client/cli_transaction.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/client/cli_utils.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/client/cli_view.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/client/client.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/client/errors.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/codegen/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/codegen/_common.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/codegen/cpp_constants.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/codegen/cpp_protocol_name.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/codegen/cpp_protocol_version.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/codegen/cpp_request_builders.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/codegen/cpp_schemas.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/codegen/cpp_secret_protocol_version.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/codegen/cpp_secret_request_builders.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/codegen/cpp_secret_schemas.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/codegen/go_schemas.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/codegen/java_schemas.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/codegen/protocol_version.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/codegen/rust_request_builders.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/codegen/rust_schemas.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/codegen/ts_client.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/codegen/ts_schemas.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/copy_from_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/copy_to_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/exceptions.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/filter_v2.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/filter_v2_builder.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/function_storage.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/function_storage_azure_sql.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/function_storage_cf_do.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/http/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/http/demo_storage.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/http/landing.html +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/http/landing_page.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/http/vgi-client.js +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/http/worker_page.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/invocation.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/logging_config.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/meta_worker.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/metadata.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/otel.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/profiling.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/protocol.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/protocol_version.txt +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/py.typed +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/scalar_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/schema_path.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/schema_utils.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/secret_protocol.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/secret_service.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/split_token.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/table_buffering_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/table_filter_pushdown.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/table_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/table_in_out_function.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/transactor/__init__.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/transactor/_duckdb_compat.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/transactor/client.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/transactor/protocol.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/transactor/server.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/vgi/write_results.py +0 -0
- {vgi_python-0.36.2 → vgi_python-0.37.1}/wrangler.jsonc +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: vgi-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.37.1
|
|
4
4
|
Summary: Vector Gateway Interface - Connect DuckDB to external programs via Apache Arrow
|
|
5
5
|
Project-URL: Homepage, https://query.farm
|
|
6
6
|
Project-URL: Repository, https://github.com/Query-farm/vgi-python
|
|
@@ -24,7 +24,7 @@ from vgi_rpc import (
|
|
|
24
24
|
from vgi_rpc.rpc import AuthContext, PeerResolutionContext, peer_identity_primary
|
|
25
25
|
|
|
26
26
|
from vgi.arguments import Arguments, Auth, Param, Returns
|
|
27
|
-
from vgi.auth import TokenIdentity
|
|
27
|
+
from vgi.auth import IssuedGrant, TokenIdentity
|
|
28
28
|
from vgi.client import Client
|
|
29
29
|
from vgi.scalar_function import ScalarFunction
|
|
30
30
|
from vgi.serve import (
|
|
@@ -486,6 +486,32 @@ class _IntrospectingWorker(Worker):
|
|
|
486
486
|
return None
|
|
487
487
|
|
|
488
488
|
|
|
489
|
+
class _MintingWorker(Worker):
|
|
490
|
+
"""Worker that implements only the optional grant-minting hook."""
|
|
491
|
+
|
|
492
|
+
functions = [_DoubleFunc]
|
|
493
|
+
|
|
494
|
+
@classmethod
|
|
495
|
+
def mint_grant(cls, principal: str, purpose: str, scopes: list[str], ttl_seconds: int) -> IssuedGrant:
|
|
496
|
+
# A sealed self-contained credential: the worker owns the format and
|
|
497
|
+
# the framework never parses it. Capped TTL, to pin that a worker may
|
|
498
|
+
# issue SHORTER than asked.
|
|
499
|
+
ttl = min(ttl_seconds, 3600)
|
|
500
|
+
return IssuedGrant(
|
|
501
|
+
token=f"sealed:{principal}:{':'.join(scopes)}:{purpose}",
|
|
502
|
+
expires_at=1_000_000.0 + ttl,
|
|
503
|
+
grant_id="grant-1",
|
|
504
|
+
)
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
class _BothWorker(_IntrospectingWorker):
|
|
508
|
+
"""Worker that both resolves credentials and mints grants."""
|
|
509
|
+
|
|
510
|
+
@classmethod
|
|
511
|
+
def mint_grant(cls, principal: str, purpose: str, scopes: list[str], ttl_seconds: int) -> IssuedGrant:
|
|
512
|
+
return IssuedGrant(token=f"sealed:{principal}", expires_at=1_000_000.0, grant_id="g")
|
|
513
|
+
|
|
514
|
+
|
|
489
515
|
class TestIntrospectResolverDetection:
|
|
490
516
|
"""``resolve_token`` presence is detected by override, not by a flag."""
|
|
491
517
|
|
|
@@ -516,6 +542,31 @@ def _introspector_ctx(principal: str) -> object:
|
|
|
516
542
|
)
|
|
517
543
|
|
|
518
544
|
|
|
545
|
+
def _minting_ctx(principal: str, *, auth_age_s: float = 0.0) -> object:
|
|
546
|
+
"""Build a ``CallContext`` for a caller who authenticated *auth_age_s* ago.
|
|
547
|
+
|
|
548
|
+
Minting reads ``auth_time`` off the credential's claims, and a credential
|
|
549
|
+
without one cannot mint at all. That single rule is what stops a grant
|
|
550
|
+
minting another grant — a grant is not IdP-issued, so it carries no
|
|
551
|
+
``auth_time`` — and what makes a static bearer token, which proves a
|
|
552
|
+
machine holds a secret rather than that a human just authenticated,
|
|
553
|
+
fail closed here.
|
|
554
|
+
"""
|
|
555
|
+
import time
|
|
556
|
+
|
|
557
|
+
from vgi_rpc.rpc import AuthContext, CallContext
|
|
558
|
+
|
|
559
|
+
return CallContext(
|
|
560
|
+
auth=AuthContext(
|
|
561
|
+
domain="test",
|
|
562
|
+
authenticated=True,
|
|
563
|
+
principal=principal,
|
|
564
|
+
claims={"auth_time": time.time() - auth_age_s},
|
|
565
|
+
),
|
|
566
|
+
emit_client_log=lambda *a, **k: None,
|
|
567
|
+
)
|
|
568
|
+
|
|
569
|
+
|
|
519
570
|
def _hosted_protocols(worker_cls: type[Worker]) -> frozenset[str]:
|
|
520
571
|
"""Return the protocol names the server built for *worker_cls* hosts.
|
|
521
572
|
|
|
@@ -655,6 +706,111 @@ class TestTokenIntrospection:
|
|
|
655
706
|
create_app(_IntrospectingWorker, prefix="/vgi", describe=False)
|
|
656
707
|
|
|
657
708
|
|
|
709
|
+
class TestGrantMinting:
|
|
710
|
+
"""``issue_grant`` — the other half of ``vgi_rpc.Identity.v1``.
|
|
711
|
+
|
|
712
|
+
Guarded very differently from ``introspect_token``, and deliberately so.
|
|
713
|
+
Introspection answers a question about *somebody else's* credential, so it
|
|
714
|
+
needs an allowlist. Minting produces a credential for the *caller* — there
|
|
715
|
+
is no subject on the wire, so cross-subject minting is closed by
|
|
716
|
+
construction and no allowlist applies. What this repo owns is the wiring:
|
|
717
|
+
a ``mint_grant`` override becomes an ``IdentityImpl`` that offers the
|
|
718
|
+
method, and a worker that never wrote one does not host it.
|
|
719
|
+
"""
|
|
720
|
+
|
|
721
|
+
@staticmethod
|
|
722
|
+
def _identity(worker_cls: type[Worker], **env: str) -> object:
|
|
723
|
+
from vgi.serve import _build_identity
|
|
724
|
+
|
|
725
|
+
with pytest.MonkeyPatch.context() as mp:
|
|
726
|
+
mp.delenv("VGI_INTROSPECT_PRINCIPALS", raising=False)
|
|
727
|
+
for key, value in env.items():
|
|
728
|
+
mp.setenv(key, value)
|
|
729
|
+
return _build_identity(worker_cls, None)
|
|
730
|
+
|
|
731
|
+
def test_base_worker_has_no_minter(self) -> None:
|
|
732
|
+
"""A worker that never wrote the minting gets no issuer."""
|
|
733
|
+
assert _SingleWorker._grant_minter() is None
|
|
734
|
+
|
|
735
|
+
def test_override_is_detected(self) -> None:
|
|
736
|
+
"""Implementing the hook is what enables it."""
|
|
737
|
+
minter = _MintingWorker._grant_minter()
|
|
738
|
+
assert minter is not None
|
|
739
|
+
|
|
740
|
+
def test_minting_alone_hosts_the_protocol(self) -> None:
|
|
741
|
+
"""A worker may mint without resolving — the two are independent."""
|
|
742
|
+
assert "vgi_rpc.Identity.v1" in _hosted_protocols(_MintingWorker)
|
|
743
|
+
|
|
744
|
+
def test_minting_alone_offers_only_issue_grant(self) -> None:
|
|
745
|
+
"""The protocol describes what the worker does, not what it could do."""
|
|
746
|
+
identity = self._identity(_MintingWorker)
|
|
747
|
+
assert identity is not None
|
|
748
|
+
assert identity.offered_methods() == frozenset({"issue_grant"}) # type: ignore[attr-defined]
|
|
749
|
+
|
|
750
|
+
def test_minting_alone_needs_no_introspect_allowlist(self) -> None:
|
|
751
|
+
"""No allowlist is required to mint: a grant is not an oracle.
|
|
752
|
+
|
|
753
|
+
Requiring one would be a startup error for a worker that never exposes
|
|
754
|
+
anybody else's identity — the exact opposite of the guard's purpose.
|
|
755
|
+
"""
|
|
756
|
+
with pytest.MonkeyPatch.context() as mp:
|
|
757
|
+
mp.delenv("VGI_INTROSPECT_PRINCIPALS", raising=False)
|
|
758
|
+
create_app(_MintingWorker, prefix="/vgi", describe=False)
|
|
759
|
+
|
|
760
|
+
def test_both_hooks_offer_both_methods(self) -> None:
|
|
761
|
+
"""Resolving and minting compose."""
|
|
762
|
+
identity = self._identity(_BothWorker, VGI_INTROSPECT_PRINCIPALS="proxy-a")
|
|
763
|
+
assert identity is not None
|
|
764
|
+
assert identity.offered_methods() == frozenset({"introspect_token", "issue_grant"}) # type: ignore[attr-defined]
|
|
765
|
+
|
|
766
|
+
def test_the_caller_is_the_subject(self) -> None:
|
|
767
|
+
"""The framework supplies the principal; the wire method has no subject field.
|
|
768
|
+
|
|
769
|
+
This is the property that makes an allowlist unnecessary, so pin it
|
|
770
|
+
here rather than trusting the signature to stay that way.
|
|
771
|
+
"""
|
|
772
|
+
identity = self._identity(_MintingWorker)
|
|
773
|
+
assert identity is not None
|
|
774
|
+
grant = identity.issue_grant( # type: ignore[attr-defined]
|
|
775
|
+
"nightly-etl", ["read"], 600, _minting_ctx("alice")
|
|
776
|
+
)
|
|
777
|
+
assert grant.token.startswith("sealed:alice:")
|
|
778
|
+
assert grant.grant_id == "grant-1"
|
|
779
|
+
|
|
780
|
+
def test_a_worker_may_issue_a_shorter_ttl_than_asked(self) -> None:
|
|
781
|
+
"""A worker may narrow the request; it must never widen it."""
|
|
782
|
+
identity = self._identity(_MintingWorker)
|
|
783
|
+
assert identity is not None
|
|
784
|
+
grant = identity.issue_grant( # type: ignore[attr-defined]
|
|
785
|
+
"long", [], 86_400, _minting_ctx("alice")
|
|
786
|
+
)
|
|
787
|
+
assert grant.expires_at == 1_000_000.0 + 3600
|
|
788
|
+
|
|
789
|
+
def test_stale_authentication_cannot_mint(self) -> None:
|
|
790
|
+
"""Minting while the user is present is enforced, not just documented."""
|
|
791
|
+
from vgi_rpc.rpc._token_identity import StaleAuthError
|
|
792
|
+
|
|
793
|
+
identity = self._identity(_MintingWorker)
|
|
794
|
+
assert identity is not None
|
|
795
|
+
with pytest.raises(StaleAuthError):
|
|
796
|
+
identity.issue_grant("x", [], 60, _minting_ctx("alice", auth_age_s=86_400)) # type: ignore[attr-defined]
|
|
797
|
+
|
|
798
|
+
def test_a_credential_with_no_auth_time_cannot_mint(self) -> None:
|
|
799
|
+
"""A grant cannot mint another grant, and a static bearer cannot mint at all.
|
|
800
|
+
|
|
801
|
+
Neither carries ``auth_time`` — only an IdP-issued credential does — so
|
|
802
|
+
the lineage cannot escape the identity provider. This is the rule that
|
|
803
|
+
makes delegation accountable to a human login rather than to whoever
|
|
804
|
+
currently holds a machine secret.
|
|
805
|
+
"""
|
|
806
|
+
from vgi_rpc.rpc._token_identity import StaleAuthError
|
|
807
|
+
|
|
808
|
+
identity = self._identity(_MintingWorker)
|
|
809
|
+
assert identity is not None
|
|
810
|
+
with pytest.raises(StaleAuthError):
|
|
811
|
+
identity.issue_grant("x", [], 60, _introspector_ctx("etl-service")) # type: ignore[attr-defined]
|
|
812
|
+
|
|
813
|
+
|
|
658
814
|
class TestAuthUnavailableReExport:
|
|
659
815
|
"""``AuthUnavailableError`` is reachable without naming a vgi_rpc module."""
|
|
660
816
|
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Copyright 2026 Query Farm LLC - https://query.farm
|
|
2
|
+
|
|
3
|
+
"""Cacheable fixtures whose results depend on a secret.
|
|
4
|
+
|
|
5
|
+
The C++ result cache keys a secret-dependent result on a fingerprint of the
|
|
6
|
+
secrets its bind resolved (never their values), so a result is reused while the
|
|
7
|
+
secret is unchanged and recomputed the moment it is rotated, re-scoped or
|
|
8
|
+
dropped. Each fixture here reads the ``vgi_example`` secret's ``secret_string``
|
|
9
|
+
and advertises cacheability, one per cache path the fingerprint has to reach:
|
|
10
|
+
|
|
11
|
+
* ``secret_cache_nonce()`` — producer table function; the secret is declared in
|
|
12
|
+
``Meta.required_secrets``. Also exposed as the ``data.secret_cache_nonce``
|
|
13
|
+
table with ``inline_bind=True``, which covers the client's inline-bind path
|
|
14
|
+
(no bind RPC; the secrets are resolved client-side for init).
|
|
15
|
+
* ``secret_cached_scalar(x)`` — scalar, per-value memoized; secret declared via
|
|
16
|
+
a ``Secret()`` annotation.
|
|
17
|
+
* ``secret_cached_lateral(x)`` — blended map, per-value memoized, called under
|
|
18
|
+
``LATERAL``; the secret is requested in ``on_bind`` (the two-phase bind).
|
|
19
|
+
|
|
20
|
+
Every output carries a ``nonce`` minted only when the worker really runs. It is
|
|
21
|
+
random rather than a counter because a pooled worker may run several processes,
|
|
22
|
+
and a per-process counter can repeat across them: equal nonces prove a cache
|
|
23
|
+
HIT, different ones a MISS, on any pool size.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
import os
|
|
29
|
+
from dataclasses import dataclass
|
|
30
|
+
from typing import TYPE_CHECKING, Annotated, Any, ClassVar, cast
|
|
31
|
+
|
|
32
|
+
import pyarrow as pa
|
|
33
|
+
from vgi_rpc import ArrowSerializableDataclass
|
|
34
|
+
from vgi_rpc.rpc import OutputCollector
|
|
35
|
+
|
|
36
|
+
from vgi.arguments import Arg, OutputLength, Param, Returns, Secret, SecretLookupEntry
|
|
37
|
+
from vgi.cache_control import CacheControl
|
|
38
|
+
from vgi.invocation import BindResponse
|
|
39
|
+
from vgi.metadata import FunctionExample
|
|
40
|
+
from vgi.scalar_function import ScalarFunction
|
|
41
|
+
from vgi.schema_utils import schema
|
|
42
|
+
from vgi.table_function import (
|
|
43
|
+
BindParams,
|
|
44
|
+
ProcessParams,
|
|
45
|
+
TableFunctionGenerator,
|
|
46
|
+
bind_fixed_schema,
|
|
47
|
+
init_single_worker,
|
|
48
|
+
)
|
|
49
|
+
from vgi.table_in_out_function import RowTransformFunction
|
|
50
|
+
|
|
51
|
+
if TYPE_CHECKING:
|
|
52
|
+
from vgi.protocol import VgiOutputCollector
|
|
53
|
+
|
|
54
|
+
#: The secret type every fixture here reads. Registered by the C++ extension's
|
|
55
|
+
#: test build (``CREATE SECRET ... (TYPE vgi_example, secret_string '...')``).
|
|
56
|
+
SECRET_TYPE = "vgi_example"
|
|
57
|
+
|
|
58
|
+
#: Long enough that TTL never lapses mid-test.
|
|
59
|
+
_TTL_SECONDS = 300
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _nonce() -> int:
|
|
63
|
+
"""A value unique to this invocation, across every process in a worker pool."""
|
|
64
|
+
return int.from_bytes(os.urandom(7), "big")
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _secret_string(secret: dict[str, Any]) -> str | None:
|
|
68
|
+
"""The ``secret_string`` field of a resolved secret, or None when there is none."""
|
|
69
|
+
value = secret.get("secret_string")
|
|
70
|
+
if value is None:
|
|
71
|
+
return None
|
|
72
|
+
return str(value.as_py()) if isinstance(value, pa.Scalar) else str(value)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# ---------------------------------------------------------------------------
|
|
76
|
+
# secret_cache_nonce — producer
|
|
77
|
+
# ---------------------------------------------------------------------------
|
|
78
|
+
@dataclass(slots=True, frozen=True)
|
|
79
|
+
class SecretCacheNonceArgs:
|
|
80
|
+
"""Arguments for SecretCacheNonceFunction (none)."""
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@dataclass(kw_only=True)
|
|
84
|
+
class _SecretCacheNonceState(ArrowSerializableDataclass):
|
|
85
|
+
"""The one row to emit, minted on a real invocation."""
|
|
86
|
+
|
|
87
|
+
secret_string: str | None
|
|
88
|
+
nonce: int
|
|
89
|
+
done: bool = False
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@init_single_worker
|
|
93
|
+
@bind_fixed_schema
|
|
94
|
+
class SecretCacheNonceFunction(TableFunctionGenerator[SecretCacheNonceArgs, _SecretCacheNonceState]):
|
|
95
|
+
"""One row: the secret's ``secret_string`` and a per-invocation nonce; cacheable.
|
|
96
|
+
|
|
97
|
+
``initial_state`` runs only on a cache MISS, so the nonce is stable across
|
|
98
|
+
HITs. A rotated secret must MISS and report the new value; restoring the
|
|
99
|
+
original secret must HIT the entry it produced.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
class Meta:
|
|
103
|
+
"""Metadata for SecretCacheNonceFunction."""
|
|
104
|
+
|
|
105
|
+
name = "secret_cache_nonce"
|
|
106
|
+
description = "One row with a secret's value and a per-invocation nonce; cacheable per secret"
|
|
107
|
+
categories = ["generator", "cache", "secret", "testing"]
|
|
108
|
+
required_secrets = [SecretLookupEntry(secret_type=SECRET_TYPE)]
|
|
109
|
+
examples = [
|
|
110
|
+
FunctionExample(
|
|
111
|
+
sql="SELECT * FROM secret_cache_nonce()",
|
|
112
|
+
description="The nonce is stable while the vgi_example secret is unchanged",
|
|
113
|
+
),
|
|
114
|
+
]
|
|
115
|
+
|
|
116
|
+
FunctionArguments = SecretCacheNonceArgs
|
|
117
|
+
FIXED_SCHEMA: ClassVar[pa.Schema] = schema(secret_string=pa.string(), nonce=pa.int64())
|
|
118
|
+
|
|
119
|
+
@classmethod
|
|
120
|
+
def initial_state(cls, params: ProcessParams[SecretCacheNonceArgs]) -> _SecretCacheNonceState:
|
|
121
|
+
"""Read the secret and mint a nonce for this (real) invocation."""
|
|
122
|
+
secret = next(iter(params.secrets.of_type(SECRET_TYPE)), {})
|
|
123
|
+
return _SecretCacheNonceState(secret_string=_secret_string(secret), nonce=_nonce())
|
|
124
|
+
|
|
125
|
+
@classmethod
|
|
126
|
+
def process(
|
|
127
|
+
cls,
|
|
128
|
+
params: ProcessParams[SecretCacheNonceArgs],
|
|
129
|
+
state: _SecretCacheNonceState,
|
|
130
|
+
out: OutputCollector,
|
|
131
|
+
) -> None:
|
|
132
|
+
"""Emit the single row once, advertising a cache TTL."""
|
|
133
|
+
if state.done:
|
|
134
|
+
out.finish()
|
|
135
|
+
return
|
|
136
|
+
batch = pa.RecordBatch.from_pydict(
|
|
137
|
+
{"secret_string": [state.secret_string], "nonce": [state.nonce]},
|
|
138
|
+
schema=params.output_schema,
|
|
139
|
+
)
|
|
140
|
+
cast("VgiOutputCollector", out).emit(batch, cache_control=CacheControl(ttl=_TTL_SECONDS))
|
|
141
|
+
state.done = True
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# ---------------------------------------------------------------------------
|
|
145
|
+
# secret_cached_scalar — scalar, per-value
|
|
146
|
+
# ---------------------------------------------------------------------------
|
|
147
|
+
class SecretCachedScalarFunction(ScalarFunction):
|
|
148
|
+
"""``x`` -> ``'<secret_string>|<nonce>'``, memoized per value per secret.
|
|
149
|
+
|
|
150
|
+
With no secret resolved the label is ``'|<nonce>'``.
|
|
151
|
+
|
|
152
|
+
One nonce per ``compute`` call, shared by the batch, so a served value keeps
|
|
153
|
+
the nonce of the call that produced it. ``per_value`` is a test choice, as on
|
|
154
|
+
``cached_double_scalar``: the point is coverage of the tier, not economics.
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
CACHE_CONTROL = CacheControl(ttl=_TTL_SECONDS, per_value=True)
|
|
158
|
+
|
|
159
|
+
class Meta:
|
|
160
|
+
"""Function metadata."""
|
|
161
|
+
|
|
162
|
+
name = "secret_cached_scalar"
|
|
163
|
+
description = "Returns '<secret_string>|<nonce>' per value; memoized per value per secret"
|
|
164
|
+
examples = [
|
|
165
|
+
FunctionExample(
|
|
166
|
+
sql="SELECT secret_cached_scalar(1)",
|
|
167
|
+
description="Stable while the vgi_example secret is unchanged",
|
|
168
|
+
),
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
@classmethod
|
|
172
|
+
def compute(
|
|
173
|
+
cls,
|
|
174
|
+
value: Annotated[pa.Int64Array, Param(doc="Any value; the output ignores it")],
|
|
175
|
+
_length: Annotated[int, OutputLength()],
|
|
176
|
+
vgi_example: Annotated[dict[str, pa.Scalar[Any]] | None, Secret(SECRET_TYPE)] = None,
|
|
177
|
+
) -> Annotated[pa.StringArray, Returns(pa.string())]:
|
|
178
|
+
"""Label every row with the secret's value ('' when none) and this call's nonce.
|
|
179
|
+
|
|
180
|
+
The framework omits a ``Secret()`` argument when no such secret exists,
|
|
181
|
+
hence the default: a dropped secret is a state this fixture must serve.
|
|
182
|
+
"""
|
|
183
|
+
label = f"{_secret_string(vgi_example or {}) or ''}|{_nonce()}"
|
|
184
|
+
return pa.array([label] * _length, type=pa.string())
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
# ---------------------------------------------------------------------------
|
|
188
|
+
# secret_cached_lateral — blended map, per-value, two-phase secret
|
|
189
|
+
# ---------------------------------------------------------------------------
|
|
190
|
+
@dataclass(slots=True, frozen=True, kw_only=True)
|
|
191
|
+
class _SecretCachedLateralArgs:
|
|
192
|
+
"""One positional input column; the output ignores its value."""
|
|
193
|
+
|
|
194
|
+
x: Annotated[int, Arg(0, doc="Input column")]
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class SecretCachedLateralFunction(RowTransformFunction[_SecretCachedLateralArgs]):
|
|
198
|
+
"""1->1 map emitting the secret's ``secret_string`` and a per-call nonce.
|
|
199
|
+
|
|
200
|
+
Requests the secret from ``on_bind`` — the two-phase bind, so the secret is
|
|
201
|
+
discovered at bind time rather than declared — and advertises ``per_value``
|
|
202
|
+
so a correlated ``LATERAL`` call is memoized per input value per secret.
|
|
203
|
+
"""
|
|
204
|
+
|
|
205
|
+
class Meta:
|
|
206
|
+
"""Function metadata."""
|
|
207
|
+
|
|
208
|
+
name = "secret_cached_lateral"
|
|
209
|
+
description = "Blended map emitting a secret's value and a per-call nonce; memoized per secret"
|
|
210
|
+
categories = ["blended", "cache", "secret", "test"]
|
|
211
|
+
|
|
212
|
+
@classmethod
|
|
213
|
+
def on_bind(cls, params: BindParams[_SecretCachedLateralArgs]) -> BindResponse:
|
|
214
|
+
"""Request the secret (two-phase) and declare the output columns."""
|
|
215
|
+
params.secrets.get(SECRET_TYPE)
|
|
216
|
+
return BindResponse(output_schema=schema(secret_string=pa.string(), nonce=pa.int64()))
|
|
217
|
+
|
|
218
|
+
@classmethod
|
|
219
|
+
def process(
|
|
220
|
+
cls,
|
|
221
|
+
params: ProcessParams[_SecretCachedLateralArgs],
|
|
222
|
+
state: None,
|
|
223
|
+
batch: pa.RecordBatch,
|
|
224
|
+
out: OutputCollector,
|
|
225
|
+
) -> None:
|
|
226
|
+
"""Emit one row per input row, all carrying this call's nonce."""
|
|
227
|
+
secret = next(iter(params.secrets.of_type(SECRET_TYPE)), {})
|
|
228
|
+
rows = batch.num_rows
|
|
229
|
+
cast("VgiOutputCollector", out).emit(
|
|
230
|
+
pa.record_batch(
|
|
231
|
+
{
|
|
232
|
+
"secret_string": pa.array([_secret_string(secret)] * rows, type=pa.string()),
|
|
233
|
+
"nonce": pa.array([_nonce()] * rows, type=pa.int64()),
|
|
234
|
+
}
|
|
235
|
+
),
|
|
236
|
+
cache_control=CacheControl(ttl=_TTL_SECONDS, per_value=True),
|
|
237
|
+
)
|
|
@@ -113,6 +113,7 @@ from vgi._test_fixtures.table.partition_columns import (
|
|
|
113
113
|
OverlappingRangePartitionedFunction,
|
|
114
114
|
PartitionedWithExplicitOverrideFunction,
|
|
115
115
|
RegionYearPartitionedFunction,
|
|
116
|
+
TrailingPartitionSalesFunction,
|
|
116
117
|
)
|
|
117
118
|
from vgi._test_fixtures.table.partition_columns_broken import (
|
|
118
119
|
BrokenMissingPartitionValuesFunction,
|
|
@@ -264,6 +265,7 @@ __all__ = [
|
|
|
264
265
|
"RFF_SIMPLE_COLUMNS",
|
|
265
266
|
"RFF_STRUCT_COLUMNS",
|
|
266
267
|
"RegionYearPartitionedFunction",
|
|
268
|
+
"TrailingPartitionSalesFunction",
|
|
267
269
|
"RepeatValueIntFunction",
|
|
268
270
|
"RepeatValueStrFunction",
|
|
269
271
|
"RffMultiScanFunction",
|
|
@@ -23,6 +23,11 @@ Fixtures:
|
|
|
23
23
|
* :class:`RegionYearPartitionedFunction` — multi-column SINGLE_VALUE.
|
|
24
24
|
Each chunk has a single ``(region, year)`` tuple.
|
|
25
25
|
|
|
26
|
+
* :class:`TrailingPartitionSalesFunction` — same contract as the
|
|
27
|
+
country fixture, but the partition column is declared LAST rather
|
|
28
|
+
than first, so the worker-schema and scan-local index spaces do not
|
|
29
|
+
coincide. Also exposed as a catalog table.
|
|
30
|
+
|
|
26
31
|
* :class:`PartitionedWithProjectedOutColumnFunction` — declares
|
|
27
32
|
partition on ``category`` but DOES NOT include ``category`` in the
|
|
28
33
|
emitted batch. Uses the explicit ``partition_values=`` override on
|
|
@@ -49,7 +54,7 @@ from __future__ import annotations
|
|
|
49
54
|
|
|
50
55
|
import struct
|
|
51
56
|
from dataclasses import dataclass
|
|
52
|
-
from typing import Annotated, ClassVar, cast
|
|
57
|
+
from typing import Annotated, Any, ClassVar, cast
|
|
53
58
|
|
|
54
59
|
import pyarrow as pa
|
|
55
60
|
from vgi_rpc import ArrowSerializableDataclass
|
|
@@ -285,6 +290,126 @@ class RegionYearPartitionedFunction(TableFunctionGenerator[_RegionYearArgs, _Reg
|
|
|
285
290
|
state.current_idx = rpp
|
|
286
291
|
|
|
287
292
|
|
|
293
|
+
# =============================================================================
|
|
294
|
+
# SINGLE_VALUE_PARTITIONS with the partition column NOT first
|
|
295
|
+
# =============================================================================
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
@dataclass(slots=True, frozen=True)
|
|
299
|
+
class _TrailingPartitionArgs:
|
|
300
|
+
"""Arguments for ``trailing_partition_sales``."""
|
|
301
|
+
|
|
302
|
+
rows_per_country: Annotated[int, Arg(0, doc="Rows to emit per country partition", ge=1)]
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
@dataclass(kw_only=True)
|
|
306
|
+
class _TrailingPartitionState(ArrowSerializableDataclass):
|
|
307
|
+
"""Per-worker cursor over countries (same shape as the country fixture)."""
|
|
308
|
+
|
|
309
|
+
current_country: str | None = None
|
|
310
|
+
current_country_idx: int = -1
|
|
311
|
+
current_idx: int = 0
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
@bind_fixed_schema
|
|
315
|
+
@_cardinality_from_count
|
|
316
|
+
class TrailingPartitionSalesFunction(TableFunctionGenerator[_TrailingPartitionArgs, _TrailingPartitionState]):
|
|
317
|
+
"""``country`` is single-valued per chunk, but sits LAST in the schema.
|
|
318
|
+
|
|
319
|
+
Identical contract to :class:`CountryPartitionedSalesFunction`; the only
|
|
320
|
+
difference is where the partition column lives. That difference is the
|
|
321
|
+
point: every other partitioned fixture declares its partition column at
|
|
322
|
+
index 0, which makes two distinct index spaces accidentally agree.
|
|
323
|
+
|
|
324
|
+
``CanUsePartitionedAggregate`` asks ``get_partition_info`` about
|
|
325
|
+
WORKER-SCHEMA indices, but the sink later asks ``get_partition_data``
|
|
326
|
+
about SCAN-LOCAL ones (positions in the scan's own ``column_ids``, after
|
|
327
|
+
projection pushdown). ``GROUP BY country`` projects just ``country`` and
|
|
328
|
+
``sales``, so here the sink asks about scan-local 0 while the declared
|
|
329
|
+
index is 3 — and a client that compares them without mapping raises
|
|
330
|
+
"sink requested partition column 0 that is not in the declared partition
|
|
331
|
+
set", which is fatal. With the partition column at index 0 both spaces
|
|
332
|
+
say 0 and the bug is invisible.
|
|
333
|
+
|
|
334
|
+
Also registered as a catalog TABLE (``example.data.trailing_partition_sales``)
|
|
335
|
+
because the two paths install their scan functions separately: a client can
|
|
336
|
+
wire ``get_partition_info`` for direct function calls and miss it for
|
|
337
|
+
catalog tables, in which case the planner silently never picks
|
|
338
|
+
``PARTITIONED_AGGREGATE`` for a table however it is declared.
|
|
339
|
+
"""
|
|
340
|
+
|
|
341
|
+
FIXED_SCHEMA: ClassVar[pa.Schema] = pa.schema(
|
|
342
|
+
cast(
|
|
343
|
+
"list[pa.Field[Any]]",
|
|
344
|
+
[
|
|
345
|
+
pa.field("seq", pa.int64()),
|
|
346
|
+
pa.field("label", pa.string()),
|
|
347
|
+
pa.field("sales", pa.int64()),
|
|
348
|
+
partition_field("country", pa.string()),
|
|
349
|
+
],
|
|
350
|
+
)
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
class Meta:
|
|
354
|
+
name = "trailing_partition_sales"
|
|
355
|
+
projection_pushdown = True
|
|
356
|
+
description = (
|
|
357
|
+
"Per-country sales rows, one Arrow batch per country, with the "
|
|
358
|
+
"SINGLE_VALUE partition column declared LAST in the schema "
|
|
359
|
+
"instead of first."
|
|
360
|
+
)
|
|
361
|
+
categories = ["generator", "partitioning"]
|
|
362
|
+
partition_kind = PartitionKind.SINGLE_VALUE_PARTITIONS
|
|
363
|
+
examples = [
|
|
364
|
+
FunctionExample(
|
|
365
|
+
sql="SELECT country, SUM(sales) FROM trailing_partition_sales(100) GROUP BY country",
|
|
366
|
+
description="Partitioned aggregate over a non-leading partition column",
|
|
367
|
+
),
|
|
368
|
+
]
|
|
369
|
+
|
|
370
|
+
@classmethod
|
|
371
|
+
def on_init(cls, params: InitParams[_TrailingPartitionArgs]) -> GlobalInitResponse:
|
|
372
|
+
items = [struct.pack(_QUEUE_ITEM_FMT, i) for i in range(len(_COUNTRIES))]
|
|
373
|
+
params.storage.queue_push(items)
|
|
374
|
+
return GlobalInitResponse()
|
|
375
|
+
|
|
376
|
+
@classmethod
|
|
377
|
+
def initial_state(cls, params: ProcessParams[_TrailingPartitionArgs]) -> _TrailingPartitionState:
|
|
378
|
+
return _TrailingPartitionState()
|
|
379
|
+
|
|
380
|
+
@classmethod
|
|
381
|
+
def process(
|
|
382
|
+
cls,
|
|
383
|
+
params: ProcessParams[_TrailingPartitionArgs],
|
|
384
|
+
state: _TrailingPartitionState,
|
|
385
|
+
out: OutputCollector,
|
|
386
|
+
) -> None:
|
|
387
|
+
if state.current_country is None or state.current_idx >= params.args.rows_per_country:
|
|
388
|
+
item = params.storage.queue_pop()
|
|
389
|
+
if item is None:
|
|
390
|
+
out.finish()
|
|
391
|
+
return
|
|
392
|
+
(state.current_country_idx,) = struct.unpack(_QUEUE_ITEM_FMT, item)
|
|
393
|
+
state.current_country = _COUNTRIES[state.current_country_idx]
|
|
394
|
+
state.current_idx = 0
|
|
395
|
+
|
|
396
|
+
rpc = params.args.rows_per_country
|
|
397
|
+
# Same deterministic sales values as country_partitioned_sales, so a
|
|
398
|
+
# test can assert the two agree column-for-column despite the layout.
|
|
399
|
+
base = state.current_country_idx * 1_000_000
|
|
400
|
+
batch = pa.RecordBatch.from_pydict(
|
|
401
|
+
{
|
|
402
|
+
"seq": list(range(rpc)),
|
|
403
|
+
"label": [f"{state.current_country}-{i}" for i in range(rpc)],
|
|
404
|
+
"sales": [base + i for i in range(rpc)],
|
|
405
|
+
"country": [state.current_country] * rpc,
|
|
406
|
+
},
|
|
407
|
+
schema=cls.FIXED_SCHEMA,
|
|
408
|
+
)
|
|
409
|
+
out.emit(batch)
|
|
410
|
+
state.current_idx = rpc
|
|
411
|
+
|
|
412
|
+
|
|
288
413
|
# =============================================================================
|
|
289
414
|
# Projected-out partition column — exercises explicit override path
|
|
290
415
|
# =============================================================================
|