vgi-python 0.34.1__tar.gz → 0.36.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.
- {vgi_python-0.34.1 → vgi_python-0.36.0}/CLAUDE.md +4 -3
- {vgi_python-0.34.1 → vgi_python-0.36.0}/PKG-INFO +2 -2
- {vgi_python-0.34.1 → vgi_python-0.36.0}/pyproject.toml +8 -3
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/catalog/test_client_catalog.py +1 -5
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/catalog/test_example_worker_catalog.py +2 -1
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/client/test_stop_force.py +9 -3
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_function_inventory.py +4 -3
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conftest.py +151 -10
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/scalar/test_client.py +24 -7
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table/generator/test_exception_function.py +4 -3
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table/generator/test_filter_echo_function.py +4 -3
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table/generator/test_logging_function.py +4 -3
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table/generator/test_partitioned_function.py +7 -6
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table/generator/test_projected_data_function.py +3 -2
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table/generator/test_sequence_function.py +2 -1
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table/generator/test_settings_function.py +5 -4
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table/generator/test_struct_settings_function.py +3 -2
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table_in_out/generator/test_substream_partial_sum_function.py +43 -11
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table_in_out/test_client.py +27 -9
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_bind_exceptions.py +6 -5
- vgi_python-0.36.0/tests/test_dynamic_filter_http_turns.py +199 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_exception_handling.py +12 -11
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_function_storage.py +119 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_launch_transport.py +45 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_projection_enforcement.py +4 -3
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_projection_repro.py +8 -7
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_serve.py +16 -12
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_setting_secret_annotations.py +3 -2
- vgi_python-0.36.0/tests/test_subprocess_transport.py +41 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/uv.lock +5 -5
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/filters.py +4 -1
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/sequence.py +4 -1
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/splits.py +10 -5
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table_in_out.py +6 -5
- vgi_python-0.36.0/vgi/auth.py +132 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/catalog/catalog_interface.py +40 -20
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/client/client.py +197 -96
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/filter_v2.py +62 -2
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/function.py +18 -4
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/function_storage.py +41 -29
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/protocol.py +140 -25
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/scalar_function.py +3 -2
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/serve.py +1 -58
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/table_filter_pushdown.py +36 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/table_in_out_function.py +12 -5
- vgi_python-0.34.1/vgi/auth.py +0 -76
- {vgi_python-0.34.1 → vgi_python-0.36.0}/.dockerignore +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/.gitattributes +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/.github/dependabot.yml +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/.github/styles/config/vocabularies/VGI/accept.txt +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/.github/workflows/ci.yml +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/.github/workflows/docs.yml +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/.github/workflows/integration.yml +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/.github/workflows/release.yml +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/.github/workflows/tailnet-integration.yml +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/.gitignore +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/.python-version +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/.vale.ini +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/DOCS_ACCEPTANCE_CRITERIA.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/DOCS_REVIEW_RUBRIC.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/DOCS_USABILITY_TEST.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/LICENSE +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/PROTOCOL.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/README.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/RELEASE-RUNBOOK.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/SECURITY.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/ci/README.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/ci/preprocess-require.awk +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/ci/run-integration.sh +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/README.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/cases/negative/and-too-few-children.json +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/cases/negative/delta-required-upsert.json +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/cases/negative/nested-runtime-filter.json +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/cases/negative/remove-with-expression.json +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/cases/negative/required-runtime-filter.json +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/cases/negative/snapshot-nonzero-revision.json +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/cases/negative/unknown-document-property.json +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/cases/negative/unknown-node.json +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/cases/positive/advisory-upsert-delta.json +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/cases/positive/empty-snapshot.json +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/cases/positive/nested-required-snapshot.json +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/cases/positive/remove-delta.json +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/cases/positive/runtime-filter-snapshot.json +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/filter-v2.schema.json +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/generate_runtime.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/manifest.json +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/run_worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/arithmetic-add/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/arithmetic-add/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/arithmetic-add/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/arithmetic-multiply/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/arithmetic-multiply/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/arithmetic-multiply/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/arithmetic-negate/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/arithmetic-negate/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/arithmetic-negate/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/arithmetic-subtract/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/arithmetic-subtract/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/arithmetic-subtract/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/cast-integer-to-double/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/cast-integer-to-double/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/cast-integer-to-double/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-distinct_from/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-distinct_from/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-distinct_from/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-distinct_from/worker-expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-eq/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-eq/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-eq/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-eq/worker-expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-ge/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-ge/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-ge/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-ge/worker-expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-gt/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-gt/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-gt/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-gt/worker-expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-le/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-le/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-le/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-le/worker-expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-lt/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-lt/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-lt/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-lt/worker-expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-ne/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-ne/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-ne/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-ne/worker-expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-not_distinct_from/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-not_distinct_from/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-not_distinct_from/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/comparison-not_distinct_from/worker-expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/delta-atomic-multi-update/delta-0.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/delta-atomic-multi-update/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/delta-atomic-multi-update/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/delta-atomic-multi-update/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/delta-empty-noop/delta-0.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/delta-empty-noop/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/delta-empty-noop/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/delta-empty-noop/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/delta-upsert-remove-stale/delta-0.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/delta-upsert-remove-stale/delta-1.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/delta-upsert-remove-stale/delta-2.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/delta-upsert-remove-stale/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/delta-upsert-remove-stale/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/delta-upsert-remove-stale/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/empty-snapshot/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/empty-snapshot/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/empty-snapshot/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/empty-snapshot/worker-expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-cast-type-not-null/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-cast-type-not-null/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-column-index/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-column-index/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-column-name/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-column-name/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-contextual-cast-without-session/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-contextual-cast-without-session/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-duplicate-predicate-id/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-duplicate-predicate-id/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-external-column-index/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-external-column-index/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-external-column-index/join-keys-0.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-external-column-name/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-external-column-name/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-external-column-name/join-keys-0.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-field-non-struct/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-field-non-struct/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-in-payload-not-list/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-in-payload-not-list/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-in-payload-null-list/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-in-payload-null-list/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-invalid-overload/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-invalid-overload/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-missing-literal/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-missing-literal/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-non-boolean-root/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-non-boolean-root/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-unknown-standard-function/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/error-unknown-standard-function/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/external-in-nonzero-column/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/external-in-nonzero-column/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/external-in-nonzero-column/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/external-in-nonzero-column/join-keys-0.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/external-in-nonzero-column/worker-expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/function-contains/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/function-contains/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/function-contains/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/function-ends-with/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/function-ends-with/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/function-ends-with/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/function-list-contains/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/function-list-contains/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/function-list-contains/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/function-starts-with/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/function-starts-with/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/function-starts-with/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/in-empty/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/in-empty/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/in-empty/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/in-empty/worker-expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/in-with-null/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/in-with-null/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/in-with-null/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/in-with-null/worker-expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/is-not-null/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/is-not-null/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/is-not-null/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/is-not-null/worker-expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/is-null/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/is-null/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/is-null/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/is-null/worker-expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/kleene-and/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/kleene-and/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/kleene-and/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/kleene-not/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/kleene-not/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/kleene-not/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/kleene-or/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/kleene-or/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/kleene-or/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/nan-comparison/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/nan-comparison/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/nan-comparison/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/negative-zero-membership/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/negative-zero-membership/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/negative-zero-membership/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/nested-null-propagation/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/nested-null-propagation/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/nested-null-propagation/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/not-in-empty/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/not-in-empty/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/not-in-empty/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/not-in-empty/worker-expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/not-in-with-null/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/not-in-with-null/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/not-in-with-null/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/not-in-with-null/worker-expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/session-integer-division/expected.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/session-integer-division/filter.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime/session-integer-division/input.arrow +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/conformance/filter-v2/runtime-manifest.json +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/dist-vgi/.gitignore +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/aggregate-functions.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/api/arguments.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/api/auth.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/api/catalogs.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/api/client.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/api/exceptions.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/api/filters.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/api/functions.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/api/http.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/api/index.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/api/metadata.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/api/observability.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/api/storage.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/api/transactor.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/api/worker.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/argument-serialization.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/assets/apple-touch-icon.png +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/assets/favicon-16x16.png +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/assets/favicon-32x32.png +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/assets/favicon.ico +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/assets/kinds/aggregate.svg +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/assets/kinds/buffering.svg +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/assets/kinds/scalar.svg +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/assets/kinds/table-in-out.svg +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/assets/kinds/table.svg +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/assets/logo.png +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/assets/social-card.png +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/authentication.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/catalog-interface.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/cli.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/column-statistics.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/concepts/index.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/contributing-docs.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/filter-pushdown.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/generator-api.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/global-functions.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/how-to/catalogs.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/how-to/function-patterns.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/how-to/http-auth.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/how-to/index.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/how-to/iroh.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/how-to/pushdown-and-statistics.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/how-to/state-storage.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/how-to/tailnet.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/index.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/lifecycle.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/metadata.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/overrides/main.html +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/protocol/index.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/protocol/vgi-catalog-query-pushdown-design.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/protocol/vgi-duckdb-filter-adapter.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/protocol/vgi-filter-encoding-v2-spec.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/protocol/vgi-protocol-proposed-changes.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/protocol/vgi-runtime-filter-artifacts.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/robots.txt +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/shared-storage.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/stylesheets/extra.css +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/tutorial/index.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/tutorial/scalar.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/tutorial/table.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/docs/vgi-logo.png +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/examples/batch_index_worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/examples/cache_worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/examples/calc_scalar_worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/examples/calc_worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/examples/copy_format_worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/examples/filter_worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/examples/greeting_scalar_worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/examples/row_count_worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/examples/series_streaming_worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/examples/sum_worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/identity.png +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/mkdocs.yml +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/packages/vgi-fixtures/LICENSE +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/packages/vgi-fixtures/README.md +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/packages/vgi-fixtures/docker/Dockerfile +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/packages/vgi-fixtures/docker/docker-entrypoint.sh +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/packages/vgi-fixtures/pyproject.toml +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/scripts/measure_startup.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/scripts/regen_generated.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/scripts/run_all_tests.sh +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/test-data/generate.sh +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/_http_fixtures.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/catalog/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/catalog/test_attach_option.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/catalog/test_catalog_interface.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/catalog/test_column_statistics.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/catalog/test_declarative.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/catalog/test_integration.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/catalog/test_required_filters.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/catalog/test_scan_branches.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/catalog/test_serialization.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/catalog/test_setting.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/catalog/test_storage.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/catalog/test_time_travel.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/catalog/test_writable_table.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/client/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/client/test_aggregate_client.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/client/test_batch_metadata_callback.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/client/test_bind_and_join_keys.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/client/test_broken_pipe.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/client/test_cli.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/client/test_cli_catalog_functions.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/client/test_copy_client.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/client/test_http_response_budget.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/client/test_iroh_client.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/client/test_scan_branches_client.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/client/test_split_client.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/client/test_table_column_statistics.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/client/test_time_travel_client.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/client/test_worker_debug.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/_stub.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/conftest.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_accumulate.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_aggregate.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_attach.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_bearer_auth.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_const_param_enforcement.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_container.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_copy_from.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_copy_to.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_directory_parity.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_github.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_http_client.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_http_external_location.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_http_upload_url.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_macro.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_overload.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_protocol_inventory.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_protocol_version.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_resumable_scan.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_scalar.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_scalar_attach_opaque_data.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_secret.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_settings.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_splits.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_table.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_table_in_out.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_view.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/conformance/test_writable.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/data/split_tokens/anchor_len_overrun.bin +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/data/split_tokens/bad_fingerprint.bin +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/data/split_tokens/bad_flags_unsealed_but_key_present.bin +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/data/split_tokens/bad_version.bin +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/data/split_tokens/generate.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/data/split_tokens/manifest.json +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/data/split_tokens/reserved_flag_bit.bin +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/data/split_tokens/stale_anchor.bin +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/data/split_tokens/truncated.bin +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/data/split_tokens/valid_sealed.bin +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/data/split_tokens/valid_unsealed.bin +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/scalar/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/scalar/test_bernoulli_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/scalar/test_binary_packet_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/scalar/test_conditional_message_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/scalar/test_hash_seed_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/scalar/test_multiply_by_setting_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/scalar/test_multiply_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/scalar/test_random_bytes_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/scalar/test_return_secret_value_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table/generator/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table/generator/test_constant_columns_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table/generator/test_double_sequence_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table/generator/test_nested_sequence_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table/generator/test_ten_thousand_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table/test_wide_columns.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table_in_out/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table_in_out/generator/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table_in_out/generator/test_buffer_input_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table_in_out/generator/test_echo_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table_in_out/generator/test_exception_functions.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table_in_out/generator/test_filter_by_setting_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table_in_out/generator/test_repeat_inputs_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table_in_out/generator/test_sum_all_columns_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table_in_out/test_blended_exchange.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/table_in_out/test_blended_metadata.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/tailnet/Dockerfile +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/tailnet/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/tailnet/compose.yaml +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/tailnet/probe.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/tailnet/run.sh +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/tailnet/test_worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/tailnet/worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_access_log_audit.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_aggregate_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_argument_spec.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_auth.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_bind_request_at_clause.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_bound_storage_conformance.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_cache_control.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_call_state_attach.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_catalog_auth_binding.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_client_oauth.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_codegen_request_inventory.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_copy_from_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_copy_to_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_docstrings.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_documentation_examples.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_example_function_arg_types.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_examples_workers.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_exceptions.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_filter_pushdown.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_filter_pushdown_extension.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_filter_v2.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_filter_v2_builder.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_filter_v2_runtime_corpus.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_filter_v2_spec_schema.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_fixture_catalog_parity.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_function_shape_mismatch.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_function_storage_azure_sql.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_function_storage_cf_do.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_function_storage_cf_do_integration.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_function_storage_conformance.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_generated_cpp_constants.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_generated_cpp_protocol_name.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_generated_cpp_protocol_version.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_generated_cpp_request_builders.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_generated_cpp_schemas.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_generated_cpp_secret.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_generated_go_schemas.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_generated_java_schemas.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_generated_protocol_version.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_generated_rust_request_builders.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_generated_rust_schemas.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_generated_schemas_cross_lang.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_generated_ts_client.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_generated_ts_schemas.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_http_demo_storage.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_http_s3_offload_input.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_http_s3_offload_output.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_import_side_effects.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_metadata.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_mypy_consolidated.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_nest_tensor.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_otel.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_protocol_classes.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_resolved_secrets.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_schema_paths_v2.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_schema_scoped_functions.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_schema_utils.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_signing_key.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_split_token.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_table_buffering_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_table_function_dynamic_to_string.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_tcp_transport.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_type_bounds.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_union_argument.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_wire_record_schema_parity.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_worker_cli.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_worker_page.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/test_write_results.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/transactor/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/tests/transactor/test_transactor.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_duckdb.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_storage_profile.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/accumulate/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/accumulate/worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/aggregate/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/aggregate/_common.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/aggregate/basic.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/aggregate/dynamic.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/aggregate/generic.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/aggregate/listagg.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/aggregate/percentile.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/aggregate/same_name.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/aggregate/secret_typed.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/aggregate/streaming.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/aggregate/varargs.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/aggregate/window.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/attach_options.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/bad_enum.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/bad_protocol.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/cancellable.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/catalog.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/companion.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/copy_from.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/copy_to.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/global_functions.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/http_server.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/narrow_bind/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/narrow_bind/worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/nest_tensor.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/orchard_catalog.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/projection_repro/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/projection_repro/worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/scalar/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/scalar/_common.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/scalar/arithmetic.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/scalar/bench_ladder.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/scalar/binary.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/scalar/formatting.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/scalar/geo.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/scalar/null_handling.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/scalar/random_demo.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/scalar/same_name.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/scalar/settings_secrets.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/scalar/type_info.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/schema_reconcile/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/schema_reconcile/worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/simple_writable.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/_common.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/batch_index.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/batch_index_broken.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/cache.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/catalog_scans.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/late_materialization.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/make_series.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/misc.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/order_modes.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/pairs.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/partition_columns.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/partition_columns_broken.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/profiling_example.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/required_filters.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/same_name_cached.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/same_name_schemas.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/settings.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/transaction_storage.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/tt_pushdown.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/typed_probe.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/versioned.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table/wide.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/table_in_out_same_name.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/twin_catalogs.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/versioned.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/versioned_tables.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/writable/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/writable/generic.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/writable/table.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/_test_fixtures/writable/worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/aggregate_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/argument_spec.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/arguments.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/attach_header.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/cache_control.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/catalog/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/catalog/_descriptor_spec.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/catalog/attach_option.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/catalog/descriptors.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/catalog/duckdb_statistics.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/catalog/secret_type.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/catalog/setting.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/catalog/storage.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/client/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/client/aggregate.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/client/catalog_mixin.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/client/cli.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/client/cli_catalog.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/client/cli_schema.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/client/cli_table.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/client/cli_transaction.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/client/cli_utils.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/client/cli_view.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/client/errors.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/codegen/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/codegen/_common.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/codegen/cpp_constants.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/codegen/cpp_protocol_name.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/codegen/cpp_protocol_version.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/codegen/cpp_request_builders.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/codegen/cpp_schemas.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/codegen/cpp_secret_protocol_version.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/codegen/cpp_secret_request_builders.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/codegen/cpp_secret_schemas.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/codegen/go_schemas.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/codegen/java_schemas.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/codegen/protocol_version.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/codegen/rust_request_builders.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/codegen/rust_schemas.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/codegen/ts_client.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/codegen/ts_schemas.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/copy_from_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/copy_to_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/exceptions.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/filter_v2_builder.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/function_storage_azure_sql.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/function_storage_cf_do.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/http/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/http/demo_storage.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/http/landing.html +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/http/landing_page.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/http/vgi-client.js +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/http/worker_page.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/invocation.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/logging_config.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/meta_worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/metadata.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/otel.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/profiling.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/protocol_version.txt +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/py.typed +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/schema_path.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/schema_utils.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/secret_protocol.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/secret_service.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/split_token.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/table_buffering_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/table_function.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/transactor/__init__.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/transactor/_duckdb_compat.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/transactor/client.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/transactor/protocol.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/transactor/server.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/worker.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/vgi/write_results.py +0 -0
- {vgi_python-0.34.1 → vgi_python-0.36.0}/wrangler.jsonc +0 -0
|
@@ -298,7 +298,6 @@ vgi-client --input data.parquet --function sum_all_columns --worker vgi-fixture-
|
|
|
298
298
|
| `VGI_OAUTH_DEVICE_CODE_CLIENT_SECRET` | Client secret for device-code flow (optional, URL-safe chars only) |
|
|
299
299
|
| `VGI_OAUTH_USE_ID_TOKEN` | When `1`/`true`/`yes`, clients use OIDC `id_token` as Bearer instead of `access_token` |
|
|
300
300
|
| `VGI_INTROSPECT_PRINCIPALS` | Comma-separated principals permitted to call `vgi_rpc.Identity.v1`'s `introspect_token`. Required — no permissive default — whenever the worker implements `resolve_token()` (see below) |
|
|
301
|
-
| `VGI_INTROSPECT_RATE_LIMIT` | Introspection requests allowed per caller per second (default 20) |
|
|
302
301
|
| `VGI_WORKER_ACCESS_LOG_SAMPLE` | Fraction of *successful* calls to keep in the access log, `0.0`–`1.0`. Errors are always kept; the decision is per call, so every record of one stream shares a fate |
|
|
303
302
|
| `VGI_WORKER_ACCESS_LOG_ASYNC` | When `1`/`true`/`yes`, emit access-log records from a listener thread. Bounded queue; full means drop, and a crash loses whatever is queued |
|
|
304
303
|
| `VGI_WORKER_ACCESS_LOG_QUEUE_SIZE` | Bound on the async access-log queue (default 10000) |
|
|
@@ -461,8 +460,10 @@ Enabling it also requires an allowlist of principals permitted to ask, via
|
|
|
461
460
|
default and a worker that overrides the hook without one **refuses to start**:
|
|
462
461
|
authenticating and introspecting are different capabilities, and "any
|
|
463
462
|
authenticated caller" lets any user resolve any other user's credential to its
|
|
464
|
-
owner.
|
|
465
|
-
|
|
463
|
+
owner. Introspection is deliberately not rate limited (vgi-rpc removed the
|
|
464
|
+
limiter): the allowlisted caller is a proxy asking on behalf of every client, so a
|
|
465
|
+
per-caller limit was one budget for every user's login, drainable by junk
|
|
466
|
+
credentials. Throttle untrusted traffic at the proxy, per client.
|
|
466
467
|
|
|
467
468
|
Return `None` for "the store answered and this credential is unknown"; raise
|
|
468
469
|
`AuthUnavailableError` for "the answer is not knowable". A caller that
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: vgi-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.36.0
|
|
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
|
|
@@ -162,7 +162,7 @@ Requires-Dist: httpx2>=2.9.1
|
|
|
162
162
|
Requires-Dist: platformdirs
|
|
163
163
|
Requires-Dist: pyarrow
|
|
164
164
|
Requires-Dist: typer>=0.9
|
|
165
|
-
Requires-Dist: vgi-rpc>=0.
|
|
165
|
+
Requires-Dist: vgi-rpc>=0.47.0
|
|
166
166
|
Provides-Extra: azure
|
|
167
167
|
Requires-Dist: azure-identity>=1.16.0; extra == 'azure'
|
|
168
168
|
Requires-Dist: pymssql>=2.3.0; extra == 'azure'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "vgi-python"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.36.0"
|
|
4
4
|
description = "Vector Gateway Interface - Connect DuckDB to external programs via Apache Arrow"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
keywords = [
|
|
@@ -40,7 +40,7 @@ dependencies = [
|
|
|
40
40
|
"pyarrow",
|
|
41
41
|
"typer>=0.9",
|
|
42
42
|
"platformdirs",
|
|
43
|
-
"vgi-rpc>=0.
|
|
43
|
+
"vgi-rpc>=0.47.0",
|
|
44
44
|
"httpx2>=2.9.1",
|
|
45
45
|
]
|
|
46
46
|
|
|
@@ -223,7 +223,12 @@ warn_unused_ignores = false
|
|
|
223
223
|
python-version = "3.13"
|
|
224
224
|
|
|
225
225
|
[tool.pytest.ini_options]
|
|
226
|
-
|
|
226
|
+
# worksteal: xdist's default "load" hands each worker a contiguous slice of the
|
|
227
|
+
# collection up front, so tests/catalog/test_integration.py (30 tests that each
|
|
228
|
+
# start a fresh catalog worker process, ~0.7 s apiece) all landed on one xdist
|
|
229
|
+
# worker, which then ran for 20 s after the rest had finished. worksteal lets
|
|
230
|
+
# idle workers take queued tests from busy ones. Ignored without -n.
|
|
231
|
+
addopts = "--ruff --dist worksteal"
|
|
227
232
|
testpaths = ["tests"]
|
|
228
233
|
|
|
229
234
|
[tool.coverage.run]
|
|
@@ -10,13 +10,9 @@ For full catalog CRUD workflows (create/get/drop tables, views, schemas),
|
|
|
10
10
|
see tests/catalog/test_integration.py which exercises all catalog operations.
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
|
-
import
|
|
14
|
-
|
|
13
|
+
from tests.conftest import CATALOG_WORKER
|
|
15
14
|
from vgi.client import Client
|
|
16
15
|
|
|
17
|
-
# Worker command for catalog tests
|
|
18
|
-
CATALOG_WORKER = f"{sys.executable} -m vgi._test_fixtures.catalog"
|
|
19
|
-
|
|
20
16
|
|
|
21
17
|
class TestClientCatalogStatelessOperations:
|
|
22
18
|
"""Test catalog operations that work independently."""
|
|
@@ -8,6 +8,7 @@ interface, allowing clients to discover available functions.
|
|
|
8
8
|
|
|
9
9
|
import pyarrow as pa
|
|
10
10
|
|
|
11
|
+
from tests.conftest import FIXTURE_WORKER
|
|
11
12
|
from vgi._test_fixtures.worker import ExampleWorker
|
|
12
13
|
from vgi.catalog import (
|
|
13
14
|
AttachOpaqueData,
|
|
@@ -23,7 +24,7 @@ from vgi.catalog import (
|
|
|
23
24
|
from vgi.client import Client
|
|
24
25
|
|
|
25
26
|
# Worker command for catalog tests
|
|
26
|
-
EXAMPLE_WORKER =
|
|
27
|
+
EXAMPLE_WORKER = FIXTURE_WORKER
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
def _get_expected_function_names() -> set[str]:
|
|
@@ -26,8 +26,11 @@ import pytest
|
|
|
26
26
|
from vgi.arguments import Arguments
|
|
27
27
|
from vgi.client.client import Client, _default_pool
|
|
28
28
|
|
|
29
|
-
#
|
|
30
|
-
|
|
29
|
+
# How long the worker sleeps before each row. The first row alone costs this
|
|
30
|
+
# much, so it is kept short; the forced stop is held to half of it (see
|
|
31
|
+
# test_force_returns_promptly_mid_stream), which a teardown that waited out the
|
|
32
|
+
# sleep would miss by a wide margin, and a kill (milliseconds) clears.
|
|
33
|
+
_SLEEP_MS = 2_000
|
|
31
34
|
|
|
32
35
|
|
|
33
36
|
def _started_client(**kwargs: Any) -> Client:
|
|
@@ -65,10 +68,13 @@ def test_force_returns_promptly_mid_stream(tmp_path: Any) -> None:
|
|
|
65
68
|
)
|
|
66
69
|
next(gen) # worker is now mid-stream, sleeping between batches
|
|
67
70
|
|
|
71
|
+
# The client's reader thread asks for the next row as soon as it has the
|
|
72
|
+
# first, so the worker is now inside that row's sleep. A stop that waited
|
|
73
|
+
# it out would take nearly the whole sleep; hold the kill to half of it.
|
|
68
74
|
started = time.monotonic()
|
|
69
75
|
client.stop(force=True)
|
|
70
76
|
elapsed = time.monotonic() - started
|
|
71
|
-
assert elapsed < _SLEEP_MS /
|
|
77
|
+
assert elapsed < _SLEEP_MS / 2000.0, f"forced stop waited {elapsed:.2f}s on a sleeping worker"
|
|
72
78
|
|
|
73
79
|
|
|
74
80
|
def test_graceful_stop_is_unchanged() -> None:
|
|
@@ -19,6 +19,7 @@ from dataclasses import dataclass
|
|
|
19
19
|
|
|
20
20
|
import pytest
|
|
21
21
|
|
|
22
|
+
from tests.conftest import FIXTURE_WORKER
|
|
22
23
|
from vgi.catalog.catalog_interface import AttachOpaqueData, SchemaObjectType
|
|
23
24
|
from vgi.client.client import Client
|
|
24
25
|
|
|
@@ -79,7 +80,7 @@ _COVERAGE_MAP: dict[SchemaObjectType, TypeCoverage] = {
|
|
|
79
80
|
@pytest.fixture(scope="module")
|
|
80
81
|
def attached_example() -> tuple[str, AttachOpaqueData]:
|
|
81
82
|
"""Attach to the ``example`` catalog once per module and yield ``(worker, attach_opaque_data)``."""
|
|
82
|
-
worker =
|
|
83
|
+
worker = FIXTURE_WORKER
|
|
83
84
|
client = Client(worker)
|
|
84
85
|
result = client.catalog_attach(
|
|
85
86
|
name=EXAMPLE_CATALOG_NAME,
|
|
@@ -92,7 +93,7 @@ def attached_example() -> tuple[str, AttachOpaqueData]:
|
|
|
92
93
|
|
|
93
94
|
def test_example_catalog_is_attachable() -> None:
|
|
94
95
|
"""Sanity: the example worker advertises a catalog named ``example``."""
|
|
95
|
-
client = Client(
|
|
96
|
+
client = Client(FIXTURE_WORKER)
|
|
96
97
|
names = [c.name for c in client.catalogs()]
|
|
97
98
|
assert EXAMPLE_CATALOG_NAME in names, (
|
|
98
99
|
f"Example worker should advertise the {EXAMPLE_CATALOG_NAME!r} catalog; got {names!r}"
|
|
@@ -149,7 +150,7 @@ def test_fixture_worker_registers_at_least_one_per_category(
|
|
|
149
150
|
broken — both are drift we want to catch.
|
|
150
151
|
"""
|
|
151
152
|
_worker, attach_opaque_data = attached_example
|
|
152
|
-
client = Client(
|
|
153
|
+
client = Client(FIXTURE_WORKER)
|
|
153
154
|
infos = client.schema_contents(
|
|
154
155
|
attach_opaque_data=attach_opaque_data,
|
|
155
156
|
path=[EXAMPLE_SCHEMA_NAME],
|
|
@@ -2,13 +2,128 @@
|
|
|
2
2
|
|
|
3
3
|
"""Shared fixtures for VGI tests."""
|
|
4
4
|
|
|
5
|
+
import contextlib
|
|
5
6
|
import logging
|
|
7
|
+
import os
|
|
8
|
+
import shlex
|
|
9
|
+
import shutil
|
|
10
|
+
import subprocess
|
|
11
|
+
import sys
|
|
12
|
+
import threading
|
|
13
|
+
import uuid
|
|
6
14
|
from typing import Any
|
|
7
15
|
|
|
8
|
-
|
|
9
|
-
import
|
|
16
|
+
# pyarrow imports numpy, and numpy's OpenBLAS starts one thread per core at
|
|
17
|
+
# import and busy-waits them: about 2.7 CPU-seconds per process on a 48-core
|
|
18
|
+
# machine. No test does linear algebra. This module is loaded before xdist
|
|
19
|
+
# starts its workers, so every process of the session inherits the setting:
|
|
20
|
+
# xdist workers, fixture and example workers, HTTP servers, CLI runs. On
|
|
21
|
+
# 48 cores it cut the suite's CPU time from 363 s to 208 s.
|
|
22
|
+
os.environ.setdefault("OPENBLAS_NUM_THREADS", "1")
|
|
23
|
+
|
|
24
|
+
import pyarrow as pa # noqa: E402
|
|
25
|
+
import pytest # noqa: E402
|
|
26
|
+
|
|
27
|
+
from vgi import schema # noqa: E402
|
|
28
|
+
|
|
29
|
+
# =============================================================================
|
|
30
|
+
# Fixture-worker transport
|
|
31
|
+
# =============================================================================
|
|
32
|
+
|
|
33
|
+
# How tests reach the fixture workers. ``launch`` (the default wherever AF_UNIX
|
|
34
|
+
# exists) routes every fixture-worker ``Client`` through ``vgi_rpc.launcher``:
|
|
35
|
+
# one warm worker per command, shared by every test process, so ``pytest -n 48``
|
|
36
|
+
# talks to one worker instead of each xdist process growing its own pool (and
|
|
37
|
+
# the matrix's ``subprocess-direct`` leg spawning a fresh worker per test) —
|
|
38
|
+
# which put hundreds of ``vgi-fixture-worker`` processes on a 48-core box.
|
|
39
|
+
# ``VGI_TEST_CLIENT_TRANSPORT=subprocess`` restores the per-process pools.
|
|
40
|
+
TEST_TRANSPORT = os.environ.get("VGI_TEST_CLIENT_TRANSPORT") or ("subprocess" if sys.platform == "win32" else "launch")
|
|
41
|
+
if TEST_TRANSPORT not in ("launch", "subprocess"):
|
|
42
|
+
raise pytest.UsageError(f"VGI_TEST_CLIENT_TRANSPORT must be 'launch' or 'subprocess', got {TEST_TRANSPORT!r}")
|
|
43
|
+
|
|
44
|
+
# Part of the launcher's hash domain (it hashes every ``VGI_RPC_*`` variable), so
|
|
45
|
+
# each session gets its own workers: never a warm one left by an earlier run of
|
|
46
|
+
# older code, and never one another checkout on the machine is using. Set here,
|
|
47
|
+
# before xdist spawns its workers, so every process of one session agrees on it.
|
|
48
|
+
_SESSION_ENV = "VGI_RPC_TEST_SESSION"
|
|
49
|
+
os.environ.setdefault(_SESSION_ENV, uuid.uuid4().hex)
|
|
50
|
+
|
|
51
|
+
_LAUNCHED: list[list[str]] = []
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _fixture_command(*argv: str) -> str:
|
|
55
|
+
"""Return the ``Client`` worker string for a fixture command under ``TEST_TRANSPORT``."""
|
|
56
|
+
if TEST_TRANSPORT == "subprocess":
|
|
57
|
+
# Unquoted, as these commands always were: Windows splits server_path
|
|
58
|
+
# non-POSIX, so shlex quoting around a backslashed python.exe path
|
|
59
|
+
# stayed on the argv and the executable was not found.
|
|
60
|
+
return " ".join(argv)
|
|
61
|
+
# Every test process shares the one worker, so its connection cap must sit
|
|
62
|
+
# above anything the suite opens: at the default 64 a scan holding its
|
|
63
|
+
# connections while its next one waits in the backlog can wait on the others
|
|
64
|
+
# doing the same, forever. Finite because ``Worker.main`` refuses 0.
|
|
65
|
+
launch_argv = [shutil.which(argv[0]) or argv[0], *argv[1:], "--max-connections", "4096"]
|
|
66
|
+
_LAUNCHED.append(launch_argv)
|
|
67
|
+
return "launch:" + shlex.join(launch_argv)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
#: The protocol fixture worker, and the catalog fixture worker.
|
|
71
|
+
FIXTURE_WORKER = _fixture_command("vgi-fixture-worker")
|
|
72
|
+
CATALOG_WORKER = _fixture_command(sys.executable, "-m", "vgi._test_fixtures.catalog")
|
|
73
|
+
|
|
74
|
+
#: The protocol fixture worker as a plain subprocess, for tests of the
|
|
75
|
+
#: subprocess transport itself (stderr capture, pooling).
|
|
76
|
+
SUBPROCESS_FIXTURE_WORKER = "vgi-fixture-worker"
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def pytest_configure(config: pytest.Config) -> None:
|
|
80
|
+
"""Start the shared fixture worker while the test processes collect.
|
|
81
|
+
|
|
82
|
+
Otherwise the first tests to reach it all wait for its start (about a
|
|
83
|
+
second of imports) and then for the first function listings, which build
|
|
84
|
+
and encode every function's metadata before it is cached; each costs
|
|
85
|
+
the one GIL-bound worker 0.2-0.3 s, and the early tests run them all at
|
|
86
|
+
once. Collection takes several seconds, so warming the worker in the
|
|
87
|
+
background here costs nothing. Only the controlling process does it.
|
|
88
|
+
"""
|
|
89
|
+
if hasattr(config, "workerinput") or TEST_TRANSPORT != "launch":
|
|
90
|
+
return
|
|
91
|
+
threading.Thread(target=_warm_fixture_worker, name="warm-fixture-worker", daemon=True).start()
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _warm_fixture_worker() -> None:
|
|
95
|
+
"""Launch the fixture worker and fill its function-listing caches."""
|
|
96
|
+
from vgi.catalog import SchemaObjectType
|
|
97
|
+
from vgi.client import Client
|
|
98
|
+
|
|
99
|
+
# Best effort: a worker that cannot start fails the tests that use it, with
|
|
100
|
+
# the real error.
|
|
101
|
+
with contextlib.suppress(Exception), Client(FIXTURE_WORKER) as client:
|
|
102
|
+
attach = client.catalog_attach(name="example", options={}, data_version_spec=None, implementation_version=None)
|
|
103
|
+
for kind in (
|
|
104
|
+
SchemaObjectType.TABLE_FUNCTION,
|
|
105
|
+
SchemaObjectType.SCALAR_FUNCTION,
|
|
106
|
+
SchemaObjectType.AGGREGATE_FUNCTION,
|
|
107
|
+
):
|
|
108
|
+
list(client.schema_contents(attach_opaque_data=attach.attach_opaque_data, path=["main"], type=kind))
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def pytest_unconfigure(config: pytest.Config) -> None:
|
|
112
|
+
"""Stop this session's launched workers rather than leaving them to idle out.
|
|
113
|
+
|
|
114
|
+
Only the controlling process does it — an xdist worker finishing early must
|
|
115
|
+
not pull the shared worker out from under the others.
|
|
116
|
+
"""
|
|
117
|
+
if hasattr(config, "workerinput") or not _LAUNCHED or sys.platform == "win32":
|
|
118
|
+
return
|
|
119
|
+
from vgi_rpc.launcher import compute_hash, default_state_dir, gc_state_dir
|
|
120
|
+
|
|
121
|
+
for argv in _LAUNCHED:
|
|
122
|
+
# The worker's argv carries ``--unix <state dir>/<hash>.sock``, and the
|
|
123
|
+
# session variable makes that hash this session's alone.
|
|
124
|
+
subprocess.run(["pkill", "-TERM", "-f", f"{compute_hash(argv)}.sock"], check=False)
|
|
125
|
+
gc_state_dir(default_state_dir())
|
|
10
126
|
|
|
11
|
-
from vgi import schema
|
|
12
127
|
|
|
13
128
|
# =============================================================================
|
|
14
129
|
# Utility Functions (not fixtures, can be imported directly)
|
|
@@ -59,6 +174,24 @@ def empty_batch_from_schema(schema: pa.Schema) -> pa.RecordBatch:
|
|
|
59
174
|
return pa.RecordBatch.from_pydict({field.name: [] for field in schema}, schema=schema)
|
|
60
175
|
|
|
61
176
|
|
|
177
|
+
def record_opened_connections(client: Any) -> list[int]:
|
|
178
|
+
"""Record the index of each worker connection a started ``client`` opens from now on.
|
|
179
|
+
|
|
180
|
+
The primary connection (index 0) is opened when the client starts, so call
|
|
181
|
+
this afterwards: the list then holds only secondary connections, which a
|
|
182
|
+
call opens for fan-out. Only records; each connection is opened for real.
|
|
183
|
+
"""
|
|
184
|
+
opened: list[int] = []
|
|
185
|
+
spawn = client._spawn_worker
|
|
186
|
+
|
|
187
|
+
def recording_spawn(worker_index: int) -> Any:
|
|
188
|
+
opened.append(worker_index)
|
|
189
|
+
return spawn(worker_index)
|
|
190
|
+
|
|
191
|
+
client._spawn_worker = recording_spawn
|
|
192
|
+
return opened
|
|
193
|
+
|
|
194
|
+
|
|
62
195
|
# =============================================================================
|
|
63
196
|
# Fixtures
|
|
64
197
|
# =============================================================================
|
|
@@ -72,8 +205,8 @@ def test_logger() -> logging.Logger:
|
|
|
72
205
|
|
|
73
206
|
@pytest.fixture
|
|
74
207
|
def fixture_worker() -> str:
|
|
75
|
-
"""Return the
|
|
76
|
-
return
|
|
208
|
+
"""Return the example worker, as a ``Client`` worker string for ``TEST_TRANSPORT``."""
|
|
209
|
+
return FIXTURE_WORKER
|
|
77
210
|
|
|
78
211
|
|
|
79
212
|
@pytest.fixture(scope="session")
|
|
@@ -118,8 +251,11 @@ def http_worker() -> Any:
|
|
|
118
251
|
# Keys used to identify transport modes in conformance tests. Keeping the
|
|
119
252
|
# literal values here (rather than inside the fixture) makes it easy for
|
|
120
253
|
# individual tests to opt out with ``@pytest.mark.parametrize("client_transport",
|
|
121
|
-
# ["subprocess-pooled"], indirect=True)``.
|
|
122
|
-
|
|
254
|
+
# ["subprocess-pooled"], indirect=True)``. The subprocess legs join the default
|
|
255
|
+
# matrix only under ``VGI_TEST_CLIENT_TRANSPORT=subprocess``.
|
|
256
|
+
_CLIENT_TRANSPORT_MODES = (
|
|
257
|
+
["launch", "http"] if TEST_TRANSPORT == "launch" else ["subprocess-pooled", "subprocess-direct", "http"]
|
|
258
|
+
)
|
|
123
259
|
|
|
124
260
|
|
|
125
261
|
@pytest.fixture(scope="session")
|
|
@@ -160,7 +296,8 @@ def client_transport(
|
|
|
160
296
|
returned client as a context manager.
|
|
161
297
|
|
|
162
298
|
Modes:
|
|
163
|
-
|
|
299
|
+
launch: The launcher-shared worker (``launch:`` worker string).
|
|
300
|
+
subprocess-pooled: Pool-backed subprocess.
|
|
164
301
|
subprocess-direct: ``pool=None`` — direct Popen management.
|
|
165
302
|
http: ``Client.from_http(base_url)`` backed by a per-test
|
|
166
303
|
``vgi-fixture-http`` subprocess. Skips if the HTTP transport
|
|
@@ -171,10 +308,14 @@ def client_transport(
|
|
|
171
308
|
mode = request.param
|
|
172
309
|
|
|
173
310
|
def _make() -> Client:
|
|
311
|
+
if mode == "launch":
|
|
312
|
+
if TEST_TRANSPORT != "launch":
|
|
313
|
+
pytest.skip("VGI_TEST_CLIENT_TRANSPORT=subprocess")
|
|
314
|
+
return Client(fixture_worker)
|
|
174
315
|
if mode == "subprocess-pooled":
|
|
175
|
-
return Client(
|
|
316
|
+
return Client(SUBPROCESS_FIXTURE_WORKER, pool=_default_pool)
|
|
176
317
|
if mode == "subprocess-direct":
|
|
177
|
-
return Client(
|
|
318
|
+
return Client(SUBPROCESS_FIXTURE_WORKER, pool=None)
|
|
178
319
|
if mode == "http":
|
|
179
320
|
if not _HTTP_TRANSPORT_READY:
|
|
180
321
|
pytest.skip("Client HTTP transport arrives in Phase 2 of whimsical-mccarthy plan")
|
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
+
import os
|
|
7
8
|
from typing import cast
|
|
8
9
|
|
|
9
10
|
import pyarrow as pa
|
|
10
11
|
import pytest
|
|
11
12
|
|
|
12
|
-
from tests.conftest import assert_total_rows
|
|
13
|
+
from tests.conftest import assert_total_rows, record_opened_connections
|
|
13
14
|
from vgi import schema
|
|
14
15
|
from vgi.arguments import Arguments
|
|
15
16
|
from vgi.client import Client
|
|
@@ -388,6 +389,7 @@ class TestScalarFunctionParallel:
|
|
|
388
389
|
batches = [pa.RecordBatch.from_pydict({"x": list(range(i * 100, (i + 1) * 100))}, schema=s) for i in range(10)]
|
|
389
390
|
|
|
390
391
|
with Client(fixture_worker, worker_limit=4) as client:
|
|
392
|
+
opened = record_opened_connections(client)
|
|
391
393
|
outputs = list(
|
|
392
394
|
client.scalar_function(
|
|
393
395
|
function_name="double",
|
|
@@ -397,6 +399,11 @@ class TestScalarFunctionParallel:
|
|
|
397
399
|
)
|
|
398
400
|
)
|
|
399
401
|
|
|
402
|
+
# Ten batches dealt round-robin reach every connection the client
|
|
403
|
+
# allows: four, or one per core on a smaller machine (GitHub's macOS
|
|
404
|
+
# runners have three).
|
|
405
|
+
assert opened == list(range(1, min(4, os.cpu_count() or 1)))
|
|
406
|
+
|
|
400
407
|
# Should get all 1000 rows back
|
|
401
408
|
assert_total_rows(outputs, 1000)
|
|
402
409
|
|
|
@@ -675,9 +682,12 @@ class TestRandomIntFunction:
|
|
|
675
682
|
class TestScalarMultiWorkerEdgeCases:
|
|
676
683
|
"""Tests for edge cases with multiple workers for scalar functions.
|
|
677
684
|
|
|
678
|
-
These tests
|
|
685
|
+
These tests exposed timeout/hang bugs when:
|
|
679
686
|
- Processing parquet with one batch of zero rows
|
|
680
|
-
- Additional workers spawned but
|
|
687
|
+
- Additional workers were spawned but received no batches
|
|
688
|
+
|
|
689
|
+
The client now opens a secondary connection only when a batch is dealt to
|
|
690
|
+
it, so no connection sits idle. The tests check that too.
|
|
681
691
|
"""
|
|
682
692
|
|
|
683
693
|
def test_zero_row_batch_single_worker(self, fixture_worker: str) -> None:
|
|
@@ -704,8 +714,9 @@ class TestScalarMultiWorkerEdgeCases:
|
|
|
704
714
|
s = schema(x=pa.int64())
|
|
705
715
|
zero_row_batch = pa.RecordBatch.from_pydict({"x": []}, schema=s)
|
|
706
716
|
|
|
707
|
-
#
|
|
717
|
+
# Allow 4 workers even though there's only one batch with zero rows
|
|
708
718
|
with Client(fixture_worker, worker_limit=4) as client:
|
|
719
|
+
opened = record_opened_connections(client)
|
|
709
720
|
outputs = list(
|
|
710
721
|
client.scalar_function(
|
|
711
722
|
function_name="double",
|
|
@@ -715,17 +726,19 @@ class TestScalarMultiWorkerEdgeCases:
|
|
|
715
726
|
)
|
|
716
727
|
)
|
|
717
728
|
|
|
718
|
-
# Should complete without hanging
|
|
729
|
+
# Should complete without hanging, on the primary alone
|
|
719
730
|
assert len(outputs) == 1
|
|
720
731
|
assert outputs[0].num_rows == 0
|
|
732
|
+
assert opened == []
|
|
721
733
|
|
|
722
734
|
def test_single_batch_multiple_workers(self, fixture_worker: str) -> None:
|
|
723
735
|
"""Single normal batch with max_workers=4 should complete without hanging."""
|
|
724
736
|
s = schema(x=pa.int64())
|
|
725
737
|
single_batch = pa.RecordBatch.from_pydict({"x": [1, 2, 3]}, schema=s)
|
|
726
738
|
|
|
727
|
-
#
|
|
739
|
+
# Allow 4 workers even though there's only 1 batch
|
|
728
740
|
with Client(fixture_worker, worker_limit=4) as client:
|
|
741
|
+
opened = record_opened_connections(client)
|
|
729
742
|
outputs = list(
|
|
730
743
|
client.scalar_function(
|
|
731
744
|
function_name="double",
|
|
@@ -737,6 +750,7 @@ class TestScalarMultiWorkerEdgeCases:
|
|
|
737
750
|
|
|
738
751
|
# Should complete without hanging and return correct data
|
|
739
752
|
assert_total_rows(outputs, 3)
|
|
753
|
+
assert opened == []
|
|
740
754
|
|
|
741
755
|
def test_fewer_batches_than_workers(self, fixture_worker: str) -> None:
|
|
742
756
|
"""2 batches with max_workers=4 should complete without hanging."""
|
|
@@ -744,8 +758,9 @@ class TestScalarMultiWorkerEdgeCases:
|
|
|
744
758
|
batch1 = pa.RecordBatch.from_pydict({"x": [1, 2]}, schema=s)
|
|
745
759
|
batch2 = pa.RecordBatch.from_pydict({"x": [3, 4, 5]}, schema=s)
|
|
746
760
|
|
|
747
|
-
#
|
|
761
|
+
# Allow 4 workers even though there are only 2 batches
|
|
748
762
|
with Client(fixture_worker, worker_limit=4) as client:
|
|
763
|
+
opened = record_opened_connections(client)
|
|
749
764
|
outputs = list(
|
|
750
765
|
client.scalar_function(
|
|
751
766
|
function_name="double",
|
|
@@ -757,3 +772,5 @@ class TestScalarMultiWorkerEdgeCases:
|
|
|
757
772
|
|
|
758
773
|
# Should complete without hanging and return correct data (5 rows total)
|
|
759
774
|
assert_total_rows(outputs, 5)
|
|
775
|
+
# The second batch opened the one secondary connection it needed.
|
|
776
|
+
assert opened == [1]
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import pyarrow as pa
|
|
6
6
|
import pytest
|
|
7
7
|
|
|
8
|
+
from tests.conftest import FIXTURE_WORKER
|
|
8
9
|
from vgi.arguments import Arguments
|
|
9
10
|
from vgi.client import Client, ClientError
|
|
10
11
|
|
|
@@ -15,7 +16,7 @@ class TestGeneratorExceptionFunctionViaClient:
|
|
|
15
16
|
def test_raises_exception_after_batches(self) -> None:
|
|
16
17
|
"""Function should raise exception after specified batches via Client."""
|
|
17
18
|
with (
|
|
18
|
-
Client(
|
|
19
|
+
Client(FIXTURE_WORKER) as client,
|
|
19
20
|
pytest.raises(ClientError) as exc_info,
|
|
20
21
|
):
|
|
21
22
|
list(
|
|
@@ -31,7 +32,7 @@ class TestGeneratorExceptionFunctionViaClient:
|
|
|
31
32
|
def test_raises_exception_immediately(self) -> None:
|
|
32
33
|
"""Function with fail_after=0 should raise immediately via Client."""
|
|
33
34
|
with (
|
|
34
|
-
Client(
|
|
35
|
+
Client(FIXTURE_WORKER) as client,
|
|
35
36
|
pytest.raises(ClientError) as exc_info,
|
|
36
37
|
):
|
|
37
38
|
list(
|
|
@@ -46,7 +47,7 @@ class TestGeneratorExceptionFunctionViaClient:
|
|
|
46
47
|
|
|
47
48
|
def test_outputs_batches_before_failure(self) -> None:
|
|
48
49
|
"""Function should output batches before failing via Client."""
|
|
49
|
-
with Client(
|
|
50
|
+
with Client(FIXTURE_WORKER) as client:
|
|
50
51
|
outputs: list[pa.RecordBatch] = []
|
|
51
52
|
try:
|
|
52
53
|
for batch in client.table_function(
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import pyarrow as pa
|
|
6
6
|
|
|
7
|
+
from tests.conftest import FIXTURE_WORKER
|
|
7
8
|
from vgi.arguments import Arguments
|
|
8
9
|
from vgi.client import Client
|
|
9
10
|
|
|
@@ -13,7 +14,7 @@ class TestFilterEchoFunction:
|
|
|
13
14
|
|
|
14
15
|
def test_no_filter_output(self) -> None:
|
|
15
16
|
"""Without filters, pushed_filters should be '(none)' for all rows."""
|
|
16
|
-
with Client(
|
|
17
|
+
with Client(FIXTURE_WORKER) as client:
|
|
17
18
|
batches = list(
|
|
18
19
|
client.table_function(
|
|
19
20
|
function_name="filter_echo",
|
|
@@ -36,7 +37,7 @@ class TestFilterEchoFunction:
|
|
|
36
37
|
|
|
37
38
|
def test_count_argument(self) -> None:
|
|
38
39
|
"""Verify row count matches the count argument."""
|
|
39
|
-
with Client(
|
|
40
|
+
with Client(FIXTURE_WORKER) as client:
|
|
40
41
|
batches = list(
|
|
41
42
|
client.table_function(
|
|
42
43
|
function_name="filter_echo",
|
|
@@ -50,7 +51,7 @@ class TestFilterEchoFunction:
|
|
|
50
51
|
|
|
51
52
|
def test_s_column_values(self) -> None:
|
|
52
53
|
"""The s column should match 'row_{n}' pattern."""
|
|
53
|
-
with Client(
|
|
54
|
+
with Client(FIXTURE_WORKER) as client:
|
|
54
55
|
batches = list(
|
|
55
56
|
client.table_function(
|
|
56
57
|
function_name="filter_echo",
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import pyarrow as pa
|
|
6
6
|
|
|
7
|
+
from tests.conftest import FIXTURE_WORKER
|
|
7
8
|
from vgi.arguments import Arguments
|
|
8
9
|
from vgi.client import Client
|
|
9
10
|
|
|
@@ -13,7 +14,7 @@ class TestLoggingGeneratorFunctionViaClient:
|
|
|
13
14
|
|
|
14
15
|
def test_generates_correct_output(self) -> None:
|
|
15
16
|
"""Function should generate correct output via Client."""
|
|
16
|
-
with Client(
|
|
17
|
+
with Client(FIXTURE_WORKER) as client:
|
|
17
18
|
outputs = list(
|
|
18
19
|
client.table_function(
|
|
19
20
|
function_name="logging_generator",
|
|
@@ -31,7 +32,7 @@ class TestLoggingGeneratorFunctionViaClient:
|
|
|
31
32
|
|
|
32
33
|
def test_zero_count_produces_no_output(self) -> None:
|
|
33
34
|
"""Function with count=0 should produce no output via Client."""
|
|
34
|
-
with Client(
|
|
35
|
+
with Client(FIXTURE_WORKER) as client:
|
|
35
36
|
outputs = list(
|
|
36
37
|
client.table_function(
|
|
37
38
|
function_name="logging_generator",
|
|
@@ -44,7 +45,7 @@ class TestLoggingGeneratorFunctionViaClient:
|
|
|
44
45
|
|
|
45
46
|
def test_large_output(self) -> None:
|
|
46
47
|
"""Function should handle larger outputs via Client."""
|
|
47
|
-
with Client(
|
|
48
|
+
with Client(FIXTURE_WORKER) as client:
|
|
48
49
|
outputs = list(
|
|
49
50
|
client.table_function(
|
|
50
51
|
function_name="logging_generator",
|
|
@@ -8,6 +8,7 @@ from typing import Any
|
|
|
8
8
|
|
|
9
9
|
import pyarrow as pa
|
|
10
10
|
|
|
11
|
+
from tests.conftest import FIXTURE_WORKER
|
|
11
12
|
from vgi.arguments import Arguments
|
|
12
13
|
from vgi.client import Client
|
|
13
14
|
|
|
@@ -22,7 +23,7 @@ class TestPartitionedSequenceFunctionMultiWorker:
|
|
|
22
23
|
|
|
23
24
|
def test_two_workers_produce_complete_sequence(self) -> None:
|
|
24
25
|
"""Two workers should together produce the complete sequence."""
|
|
25
|
-
with Client(
|
|
26
|
+
with Client(FIXTURE_WORKER, worker_limit=2) as client:
|
|
26
27
|
outputs = list(
|
|
27
28
|
client.table_function(
|
|
28
29
|
function_name="partitioned_sequence",
|
|
@@ -39,7 +40,7 @@ class TestPartitionedSequenceFunctionMultiWorker:
|
|
|
39
40
|
|
|
40
41
|
def test_three_workers_produce_complete_sequence(self) -> None:
|
|
41
42
|
"""Three workers should together produce the complete sequence."""
|
|
42
|
-
with Client(
|
|
43
|
+
with Client(FIXTURE_WORKER, worker_limit=3) as client:
|
|
43
44
|
outputs = list(
|
|
44
45
|
client.table_function(
|
|
45
46
|
function_name="partitioned_sequence",
|
|
@@ -56,7 +57,7 @@ class TestPartitionedSequenceFunctionMultiWorker:
|
|
|
56
57
|
|
|
57
58
|
def test_workers_produce_large_sequence(self) -> None:
|
|
58
59
|
"""Multiple workers should handle large sequences."""
|
|
59
|
-
with Client(
|
|
60
|
+
with Client(FIXTURE_WORKER, worker_limit=4) as client:
|
|
60
61
|
outputs = list(
|
|
61
62
|
client.table_function(
|
|
62
63
|
function_name="partitioned_sequence",
|
|
@@ -73,7 +74,7 @@ class TestPartitionedSequenceFunctionMultiWorker:
|
|
|
73
74
|
|
|
74
75
|
def test_uneven_distribution(self) -> None:
|
|
75
76
|
"""Workers should handle sequences that don't divide evenly."""
|
|
76
|
-
with Client(
|
|
77
|
+
with Client(FIXTURE_WORKER, worker_limit=3) as client:
|
|
77
78
|
outputs = list(
|
|
78
79
|
client.table_function(
|
|
79
80
|
function_name="partitioned_sequence",
|
|
@@ -90,7 +91,7 @@ class TestPartitionedSequenceFunctionMultiWorker:
|
|
|
90
91
|
|
|
91
92
|
def test_single_worker_fallback(self) -> None:
|
|
92
93
|
"""worker_limit=1 should work like single worker mode."""
|
|
93
|
-
with Client(
|
|
94
|
+
with Client(FIXTURE_WORKER, worker_limit=1) as client:
|
|
94
95
|
outputs = list(
|
|
95
96
|
client.table_function(
|
|
96
97
|
function_name="partitioned_sequence",
|
|
@@ -107,7 +108,7 @@ class TestPartitionedSequenceFunctionMultiWorker:
|
|
|
107
108
|
|
|
108
109
|
def test_increment_with_multi_workers(self) -> None:
|
|
109
110
|
"""Multiple workers should handle increment parameter."""
|
|
110
|
-
with Client(
|
|
111
|
+
with Client(FIXTURE_WORKER, worker_limit=2) as client:
|
|
111
112
|
outputs = list(
|
|
112
113
|
client.table_function(
|
|
113
114
|
function_name="partitioned_sequence",
|