vgi-python 0.29.0__tar.gz → 0.29.4__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.29.0 → vgi_python-0.29.4}/PKG-INFO +15 -8
- {vgi_python-0.29.0 → vgi_python-0.29.4}/README.md +9 -5
- vgi_python-0.29.4/docs/vgi-logo.png +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/pyproject.toml +9 -4
- vgi_python-0.29.4/tests/client/test_batch_metadata_callback.py +77 -0
- vgi_python-0.29.4/tests/client/test_scan_branches_client.py +67 -0
- vgi_python-0.29.4/tests/client/test_split_client.py +93 -0
- vgi_python-0.29.4/tests/client/test_time_travel_client.py +85 -0
- vgi_python-0.29.4/tests/test_launch_transport.py +114 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/uv.lock +33 -10
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table_in_out.py +96 -1
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/worker.py +2 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/client/catalog_mixin.py +117 -4
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/client/client.py +380 -17
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/codegen/cpp_request_builders.py +98 -12
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/worker.py +11 -0
- vgi_python-0.29.0/docs/vgi-logo.png +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/.gitattributes +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/.github/dependabot.yml +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/.github/styles/config/vocabularies/VGI/accept.txt +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/.github/workflows/ci.yml +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/.github/workflows/docs.yml +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/.github/workflows/integration.yml +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/.github/workflows/release.yml +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/.gitignore +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/.python-version +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/.vale.ini +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/CLAUDE.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/DOCS_ACCEPTANCE_CRITERIA.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/DOCS_REVIEW_RUBRIC.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/DOCS_USABILITY_TEST.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/LICENSE +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/RELEASE-RUNBOOK.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/SECURITY.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/ci/README.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/ci/preprocess-require.awk +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/ci/run-integration.sh +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/dist-vgi/.gitignore +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/aggregate-functions.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/api/arguments.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/api/auth.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/api/catalogs.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/api/client.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/api/exceptions.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/api/filters.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/api/functions.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/api/http.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/api/index.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/api/metadata.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/api/observability.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/api/storage.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/api/transactor.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/api/worker.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/argument-serialization.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/assets/apple-touch-icon.png +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/assets/favicon-16x16.png +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/assets/favicon-32x32.png +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/assets/favicon.ico +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/assets/kinds/aggregate.svg +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/assets/kinds/buffering.svg +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/assets/kinds/scalar.svg +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/assets/kinds/table-in-out.svg +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/assets/kinds/table.svg +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/assets/logo.png +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/assets/social-card.png +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/authentication.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/catalog-interface.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/cli.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/column-statistics.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/concepts/index.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/contributing-docs.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/filter-pushdown.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/generator-api.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/global-functions.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/how-to/catalogs.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/how-to/function-patterns.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/how-to/http-auth.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/how-to/index.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/how-to/pushdown-and-statistics.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/how-to/state-storage.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/index.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/lifecycle.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/metadata.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/overrides/main.html +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/robots.txt +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/shared-storage.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/stylesheets/extra.css +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/tutorial/index.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/tutorial/scalar.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/docs/tutorial/table.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/examples/batch_index_worker.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/examples/cache_worker.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/examples/calc_scalar_worker.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/examples/calc_worker.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/examples/copy_format_worker.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/examples/filter_worker.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/examples/greeting_scalar_worker.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/examples/row_count_worker.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/examples/series_streaming_worker.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/examples/sum_worker.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/mkdocs.yml +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/packages/vgi-fixtures/LICENSE +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/packages/vgi-fixtures/README.md +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/packages/vgi-fixtures/docker/Dockerfile +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/packages/vgi-fixtures/docker/docker-entrypoint.sh +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/packages/vgi-fixtures/pyproject.toml +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/scripts/measure_startup.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/scripts/run_all_tests.sh +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/test-data/generate.sh +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/_http_fixtures.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/catalog/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/catalog/test_attach_option.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/catalog/test_catalog_interface.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/catalog/test_client_catalog.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/catalog/test_column_statistics.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/catalog/test_declarative.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/catalog/test_example_worker_catalog.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/catalog/test_integration.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/catalog/test_required_filters.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/catalog/test_scan_branches.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/catalog/test_serialization.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/catalog/test_setting.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/catalog/test_storage.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/catalog/test_time_travel.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/catalog/test_writable_table.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/client/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/client/test_aggregate_client.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/client/test_broken_pipe.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/client/test_cli.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/client/test_cli_catalog_functions.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/client/test_copy_client.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/client/test_stop_force.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/client/test_table_column_statistics.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/client/test_worker_debug.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/_stub.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/conftest.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_accumulate.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_aggregate.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_attach.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_bearer_auth.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_const_param_enforcement.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_container.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_copy_from.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_copy_to.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_directory_parity.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_function_inventory.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_github.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_http_client.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_http_external_location.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_http_upload_url.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_macro.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_overload.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_protocol_inventory.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_protocol_version.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_resumable_scan.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_scalar.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_scalar_attach_opaque_data.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_secret.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_settings.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_splits.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_table.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_table_in_out.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_view.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conformance/test_writable.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/conftest.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/data/split_tokens/anchor_len_overrun.bin +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/data/split_tokens/bad_fingerprint.bin +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/data/split_tokens/bad_flags_unsealed_but_key_present.bin +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/data/split_tokens/bad_version.bin +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/data/split_tokens/generate.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/data/split_tokens/manifest.json +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/data/split_tokens/reserved_flag_bit.bin +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/data/split_tokens/stale_anchor.bin +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/data/split_tokens/truncated.bin +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/data/split_tokens/valid_sealed.bin +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/data/split_tokens/valid_unsealed.bin +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/scalar/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/scalar/test_bernoulli_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/scalar/test_binary_packet_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/scalar/test_client.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/scalar/test_conditional_message_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/scalar/test_hash_seed_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/scalar/test_multiply_by_setting_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/scalar/test_multiply_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/scalar/test_random_bytes_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/scalar/test_return_secret_value_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table/generator/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table/generator/test_constant_columns_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table/generator/test_double_sequence_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table/generator/test_exception_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table/generator/test_filter_echo_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table/generator/test_logging_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table/generator/test_nested_sequence_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table/generator/test_partitioned_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table/generator/test_projected_data_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table/generator/test_sequence_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table/generator/test_settings_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table/generator/test_struct_settings_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table/generator/test_ten_thousand_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table/test_wide_columns.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table_in_out/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table_in_out/generator/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table_in_out/generator/test_buffer_input_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table_in_out/generator/test_echo_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table_in_out/generator/test_exception_functions.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table_in_out/generator/test_filter_by_setting_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table_in_out/generator/test_repeat_inputs_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table_in_out/generator/test_substream_partial_sum_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table_in_out/generator/test_sum_all_columns_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table_in_out/test_blended_metadata.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/table_in_out/test_client.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_access_log_audit.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_aggregate_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_argument_spec.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_auth.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_bind_exceptions.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_bind_request_at_clause.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_bound_storage_conformance.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_cache_control.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_call_state_attach.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_catalog_auth_binding.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_copy_from_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_copy_to_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_docstrings.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_documentation_examples.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_example_function_arg_types.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_examples_workers.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_exception_handling.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_exceptions.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_filter_pushdown.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_filter_pushdown_extension.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_fixture_catalog_parity.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_function_storage.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_function_storage_azure_sql.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_function_storage_cf_do.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_function_storage_cf_do_integration.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_function_storage_conformance.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_generated_cpp_constants.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_generated_cpp_protocol_version.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_generated_cpp_request_builders.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_generated_cpp_schemas.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_generated_cpp_secret.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_generated_go_schemas.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_generated_java_schemas.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_generated_protocol_version.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_generated_rust_request_builders.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_generated_rust_schemas.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_generated_schemas_cross_lang.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_generated_ts_client.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_generated_ts_schemas.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_http_demo_storage.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_http_s3_offload_input.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_http_s3_offload_output.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_metadata.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_mypy_consolidated.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_nest_tensor.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_otel.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_projection_enforcement.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_projection_repro.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_protocol_classes.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_resolved_secrets.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_schema_scoped_functions.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_schema_utils.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_serve.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_setting_secret_annotations.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_signing_key.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_split_token.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_table_buffering_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_table_function_dynamic_to_string.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_tcp_transport.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_type_bounds.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_union_argument.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_wire_record_schema_parity.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_worker.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_worker_cli.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/test_worker_page.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/transactor/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/tests/transactor/test_transactor.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_duckdb.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_storage_profile.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/accumulate/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/accumulate/worker.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/_common.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/basic.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/dynamic.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/generic.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/listagg.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/percentile.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/same_name.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/secret_typed.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/streaming.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/varargs.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/window.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/attach_options.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/bad_enum.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/bad_protocol.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/cancellable.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/catalog.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/companion.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/copy_from.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/copy_to.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/global_functions.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/http_server.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/narrow_bind/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/narrow_bind/worker.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/nest_tensor.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/orchard_catalog.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/projection_repro/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/projection_repro/worker.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/_common.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/arithmetic.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/bench_ladder.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/binary.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/formatting.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/geo.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/null_handling.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/random_demo.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/same_name.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/settings_secrets.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/type_info.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/schema_reconcile/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/schema_reconcile/worker.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/simple_writable.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/_common.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/batch_index.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/batch_index_broken.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/cache.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/catalog_scans.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/filters.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/late_materialization.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/make_series.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/misc.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/order_modes.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/pairs.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/partition_columns.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/partition_columns_broken.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/profiling_example.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/required_filters.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/same_name_cached.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/sequence.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/settings.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/splits.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/transaction_storage.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/tt_pushdown.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/typed_probe.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/versioned.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table/wide.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/table_in_out_same_name.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/twin_catalogs.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/versioned.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/versioned_tables.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/writable/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/writable/generic.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/writable/table.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/_test_fixtures/writable/worker.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/aggregate_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/argument_spec.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/arguments.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/attach_header.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/auth.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/cache_control.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/catalog/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/catalog/_descriptor_spec.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/catalog/attach_option.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/catalog/catalog_interface.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/catalog/descriptors.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/catalog/duckdb_statistics.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/catalog/secret_type.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/catalog/setting.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/catalog/storage.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/client/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/client/aggregate.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/client/cli.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/client/cli_catalog.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/client/cli_schema.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/client/cli_table.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/client/cli_transaction.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/client/cli_utils.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/client/cli_view.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/client/errors.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/codegen/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/codegen/_common.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/codegen/cpp_constants.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/codegen/cpp_protocol_version.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/codegen/cpp_schemas.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/codegen/cpp_secret_protocol_version.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/codegen/cpp_secret_request_builders.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/codegen/cpp_secret_schemas.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/codegen/go_schemas.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/codegen/java_schemas.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/codegen/protocol_version.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/codegen/rust_request_builders.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/codegen/rust_schemas.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/codegen/ts_client.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/codegen/ts_schemas.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/copy_from_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/copy_to_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/exceptions.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/function_storage.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/function_storage_azure_sql.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/function_storage_cf_do.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/http/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/http/demo_storage.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/http/landing.html +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/http/landing_page.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/http/vgi-client.js +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/http/worker_page.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/invocation.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/logging_config.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/meta_worker.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/metadata.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/otel.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/profiling.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/protocol.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/protocol_version.txt +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/py.typed +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/scalar_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/schema_utils.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/secret_protocol.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/secret_service.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/serve.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/split_token.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/table_buffering_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/table_filter_pushdown.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/table_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/table_in_out_function.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/transactor/__init__.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/transactor/_duckdb_compat.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/transactor/client.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/transactor/protocol.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/vgi/transactor/server.py +0 -0
- {vgi_python-0.29.0 → vgi_python-0.29.4}/wrangler.jsonc +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: vgi-python
|
|
3
|
-
Version: 0.29.
|
|
3
|
+
Version: 0.29.4
|
|
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.43.
|
|
165
|
+
Requires-Dist: vgi-rpc>=0.43.2
|
|
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'
|
|
@@ -181,7 +181,8 @@ Requires-Dist: pytest-ruff; extra == 'dev'
|
|
|
181
181
|
Requires-Dist: pytest-xdist; extra == 'dev'
|
|
182
182
|
Requires-Dist: ruff; extra == 'dev'
|
|
183
183
|
Requires-Dist: sqlglot; extra == 'dev'
|
|
184
|
-
Requires-Dist: vgi-rpc[conformance,external,http,oauth,otel,sentry]; extra == 'dev'
|
|
184
|
+
Requires-Dist: vgi-rpc[cli,conformance,external,http,oauth,otel,sentry]; extra == 'dev'
|
|
185
|
+
Requires-Dist: vgi-rpc[cli]; extra == 'dev'
|
|
185
186
|
Requires-Dist: vgi-rpc[http]; extra == 'dev'
|
|
186
187
|
Requires-Dist: vgi-rpc[oauth]; extra == 'dev'
|
|
187
188
|
Requires-Dist: vgi-rpc[otel]; extra == 'dev'
|
|
@@ -197,6 +198,8 @@ Provides-Extra: haybarn
|
|
|
197
198
|
Requires-Dist: haybarn>=1.5.5rc1; extra == 'haybarn'
|
|
198
199
|
Provides-Extra: http
|
|
199
200
|
Requires-Dist: vgi-rpc[http]; extra == 'http'
|
|
201
|
+
Provides-Extra: launch
|
|
202
|
+
Requires-Dist: vgi-rpc[cli]; extra == 'launch'
|
|
200
203
|
Provides-Extra: oauth
|
|
201
204
|
Requires-Dist: vgi-rpc[oauth]; extra == 'oauth'
|
|
202
205
|
Provides-Extra: otel
|
|
@@ -212,18 +215,22 @@ Provides-Extra: transactor
|
|
|
212
215
|
Requires-Dist: sqlglot; extra == 'transactor'
|
|
213
216
|
Description-Content-Type: text/markdown
|
|
214
217
|
|
|
215
|
-
# VGI (Vector Gateway Interface)
|
|
216
|
-
|
|
217
218
|
<p align="center">
|
|
218
|
-
<img src="https://raw.githubusercontent.com/Query-farm/vgi-python/main/docs/vgi-logo.png" alt="
|
|
219
|
+
<img src="https://raw.githubusercontent.com/Query-farm/vgi-python/main/docs/vgi-logo.png?v=2" alt="Vector Gateway Interface logo" width="320">
|
|
219
220
|
</p>
|
|
220
221
|
|
|
222
|
+
<h1 align="center">VGI</h1>
|
|
223
|
+
|
|
221
224
|
<p align="center">
|
|
222
|
-
|
|
225
|
+
Apache Arrow-based protocol for extending DuckDB using any language — the Python reference implementation.<br>
|
|
226
|
+
Built by <a href="https://query.farm">🚜 Query.Farm</a>
|
|
223
227
|
</p>
|
|
224
228
|
|
|
225
229
|
<p align="center">
|
|
226
|
-
|
|
230
|
+
<a href="https://github.com/Query-farm/vgi-python/actions/workflows/ci.yml"><img src="https://github.com/Query-farm/vgi-python/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
231
|
+
<a href="https://pypi.org/project/vgi-python/"><img src="https://img.shields.io/pypi/v/vgi-python" alt="PyPI"></a>
|
|
232
|
+
<a href="https://pypi.org/project/vgi-python/"><img src="https://img.shields.io/pypi/pyversions/vgi-python" alt="Python versions"></a>
|
|
233
|
+
<a href="LICENSE"><img src="https://img.shields.io/pypi/l/vgi-python" alt="License"></a>
|
|
227
234
|
</p>
|
|
228
235
|
|
|
229
236
|
---
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
# VGI (Vector Gateway Interface)
|
|
2
|
-
|
|
3
1
|
<p align="center">
|
|
4
|
-
<img src="https://raw.githubusercontent.com/Query-farm/vgi-python/main/docs/vgi-logo.png" alt="
|
|
2
|
+
<img src="https://raw.githubusercontent.com/Query-farm/vgi-python/main/docs/vgi-logo.png?v=2" alt="Vector Gateway Interface logo" width="320">
|
|
5
3
|
</p>
|
|
6
4
|
|
|
5
|
+
<h1 align="center">VGI</h1>
|
|
6
|
+
|
|
7
7
|
<p align="center">
|
|
8
|
-
|
|
8
|
+
Apache Arrow-based protocol for extending DuckDB using any language — the Python reference implementation.<br>
|
|
9
|
+
Built by <a href="https://query.farm">🚜 Query.Farm</a>
|
|
9
10
|
</p>
|
|
10
11
|
|
|
11
12
|
<p align="center">
|
|
12
|
-
|
|
13
|
+
<a href="https://github.com/Query-farm/vgi-python/actions/workflows/ci.yml"><img src="https://github.com/Query-farm/vgi-python/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
14
|
+
<a href="https://pypi.org/project/vgi-python/"><img src="https://img.shields.io/pypi/v/vgi-python" alt="PyPI"></a>
|
|
15
|
+
<a href="https://pypi.org/project/vgi-python/"><img src="https://img.shields.io/pypi/pyversions/vgi-python" alt="Python versions"></a>
|
|
16
|
+
<a href="LICENSE"><img src="https://img.shields.io/pypi/l/vgi-python" alt="License"></a>
|
|
13
17
|
</p>
|
|
14
18
|
|
|
15
19
|
---
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "vgi-python"
|
|
3
|
-
version = "0.29.
|
|
3
|
+
version = "0.29.4"
|
|
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.
|
|
43
|
+
"vgi-rpc>=0.43.2",
|
|
44
44
|
"httpx2>=2.9.1",
|
|
45
45
|
]
|
|
46
46
|
|
|
@@ -52,6 +52,11 @@ dependencies = [
|
|
|
52
52
|
haybarn = ["haybarn>=1.5.5rc1"]
|
|
53
53
|
duckdb = ["duckdb>=1.5.3"]
|
|
54
54
|
http = ["vgi-rpc[http]"]
|
|
55
|
+
# transport="launch": vgi_rpc.launcher imports filelock unconditionally at
|
|
56
|
+
# module level, which lives behind vgi-rpc's own `cli` extra (alongside
|
|
57
|
+
# typer, already a core dependency here, and httpx2, ditto) rather than in
|
|
58
|
+
# vgi-rpc's core dependency set.
|
|
59
|
+
launch = ["vgi-rpc[cli]"]
|
|
55
60
|
# Alternative HTTP server: granian moves socket I/O and HTTP parsing into Rust,
|
|
56
61
|
# off the GIL. Optional because it is a compiled extension where waitress is
|
|
57
62
|
# pure Python; select it with `vgi-serve --http --server granian`.
|
|
@@ -93,8 +98,8 @@ dev = [
|
|
|
93
98
|
"pytest-ruff",
|
|
94
99
|
"pytest-xdist",
|
|
95
100
|
"ruff",
|
|
96
|
-
"vgi-python[test-fixtures,test-fixtures-writable,http,oauth,otel,sentry,azure]",
|
|
97
|
-
"vgi-rpc[conformance,external,http,oauth,otel,sentry]",
|
|
101
|
+
"vgi-python[test-fixtures,test-fixtures-writable,http,launch,oauth,otel,sentry,azure]",
|
|
102
|
+
"vgi-rpc[cli,conformance,external,http,oauth,otel,sentry]",
|
|
98
103
|
]
|
|
99
104
|
[project.scripts]
|
|
100
105
|
vgi-serve = "vgi.serve:main"
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Copyright 2026 Query Farm LLC - https://query.farm
|
|
2
|
+
|
|
3
|
+
# ruff: noqa: S101, D101, D102, D103
|
|
4
|
+
"""`Client.table_function(batch_metadata_callback=...)`.
|
|
5
|
+
|
|
6
|
+
`_table_function_parallel` previously discarded `AnnotatedBatch.custom_metadata`
|
|
7
|
+
unconditionally (`if output.batch.num_rows > 0: output_queue.put(output.batch)`)
|
|
8
|
+
and only forwarded the bare `pa.RecordBatch` — so a worker's `vgi.cache.*`
|
|
9
|
+
cacheability advertisement (`vgi/cache_control.py`), which rides
|
|
10
|
+
`custom_metadata`, was structurally unreachable through the public
|
|
11
|
+
`table_function()` generator. `batch_metadata_callback` mirrors the existing
|
|
12
|
+
`bind_result_callback` pattern to fix that additively, with no change to the
|
|
13
|
+
generator's yield type. Exercised against `cacheable_numbers`
|
|
14
|
+
(`vgi/_test_fixtures/table/cache.py`), which advertises `vgi.cache.ttl` on its
|
|
15
|
+
first batch.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
from typing import Any
|
|
21
|
+
|
|
22
|
+
import pyarrow as pa
|
|
23
|
+
import pytest
|
|
24
|
+
|
|
25
|
+
from vgi.arguments import Arguments
|
|
26
|
+
|
|
27
|
+
DATA = "data"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@pytest.fixture
|
|
31
|
+
def client(client_transport: Any) -> Any:
|
|
32
|
+
with client_transport() as c:
|
|
33
|
+
c.catalog_attach(name="example", data_version_spec=None, implementation_version=None)
|
|
34
|
+
yield c
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_callback_receives_cache_control_metadata(client: Any) -> None:
|
|
38
|
+
metas: list[pa.KeyValueMetadata | None] = []
|
|
39
|
+
batches = list(
|
|
40
|
+
client.table_function(
|
|
41
|
+
function_name="cacheable_numbers",
|
|
42
|
+
schema_name=DATA,
|
|
43
|
+
arguments=Arguments(named={"n": pa.scalar(5)}),
|
|
44
|
+
batch_metadata_callback=metas.append,
|
|
45
|
+
)
|
|
46
|
+
)
|
|
47
|
+
assert sum(b.num_rows for b in batches) == 5
|
|
48
|
+
assert len(metas) == len(batches)
|
|
49
|
+
assert metas[0] is not None
|
|
50
|
+
assert dict(metas[0])[b"vgi.cache.ttl"] == b"300"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_callback_is_optional_and_defaults_to_none(client: Any) -> None:
|
|
54
|
+
"""No `batch_metadata_callback` -> unchanged behavior, no crash."""
|
|
55
|
+
batches = list(
|
|
56
|
+
client.table_function(
|
|
57
|
+
function_name="cacheable_numbers",
|
|
58
|
+
schema_name=DATA,
|
|
59
|
+
arguments=Arguments(named={"n": pa.scalar(3)}),
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
assert sum(b.num_rows for b in batches) == 3
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def test_callback_sees_none_for_a_batch_without_custom_metadata(client: Any) -> None:
|
|
66
|
+
"""A function that never advertises cache control still drives the callback once per batch, with `None`."""
|
|
67
|
+
metas: list[pa.KeyValueMetadata | None] = []
|
|
68
|
+
list(
|
|
69
|
+
client.table_function(
|
|
70
|
+
function_name="sequence",
|
|
71
|
+
schema_name="main",
|
|
72
|
+
arguments=Arguments(positional=[pa.scalar(4)]),
|
|
73
|
+
batch_metadata_callback=metas.append,
|
|
74
|
+
)
|
|
75
|
+
)
|
|
76
|
+
assert metas
|
|
77
|
+
assert all(m is None for m in metas)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Copyright 2026 Query Farm LLC - https://query.farm
|
|
2
|
+
|
|
3
|
+
# ruff: noqa: S101, D101, D102, D103
|
|
4
|
+
"""`Client.table_scan_branches_get`.
|
|
5
|
+
|
|
6
|
+
`Client` had no wrapper for `catalog_table_scan_branches_get` at all —
|
|
7
|
+
grepped the whole `vgi/client/` package for "branch" and the only hit was an
|
|
8
|
+
unrelated code comment ("skip the subprocess branch"). A multi-branch table
|
|
9
|
+
was therefore invisible to any non-DuckDB caller, not just unsupported by a
|
|
10
|
+
higher-level connector. Exercised against `data.multi_branch_numbers` (two
|
|
11
|
+
`sequence(50)` arms — `vgi/_test_fixtures/worker.py`) and, for the legacy
|
|
12
|
+
fallback, `data.numbers` (an ordinary single-branch table whose worker only
|
|
13
|
+
implements the older `table_scan_function_get`).
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
import pytest
|
|
21
|
+
|
|
22
|
+
from vgi.catalog import ScanBranch, ScanBranchesResult
|
|
23
|
+
|
|
24
|
+
DATA = "data"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@pytest.fixture
|
|
28
|
+
def client(client_transport: Any) -> Any:
|
|
29
|
+
with client_transport() as c:
|
|
30
|
+
c.catalog_attach(name="example", data_version_spec=None, implementation_version=None)
|
|
31
|
+
yield c
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _attach_opaque(client: Any) -> Any:
|
|
35
|
+
# catalog_attach() was already called by the fixture above (its return
|
|
36
|
+
# value discarded) — re-attach here to get the opaque data this method
|
|
37
|
+
# needs, mirroring how CatalogClientMixin methods are used standalone.
|
|
38
|
+
return client.catalog_attach(name="example", data_version_spec=None, implementation_version=None).attach_opaque_data
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def test_multi_branch_table_returns_all_branches(client: Any) -> None:
|
|
42
|
+
result = client.table_scan_branches_get(
|
|
43
|
+
attach_opaque_data=_attach_opaque(client),
|
|
44
|
+
schema_name=DATA,
|
|
45
|
+
name="multi_branch_numbers",
|
|
46
|
+
)
|
|
47
|
+
assert isinstance(result, ScanBranchesResult)
|
|
48
|
+
assert len(result.branches) == 2
|
|
49
|
+
for branch in result.branches:
|
|
50
|
+
assert isinstance(branch, ScanBranch)
|
|
51
|
+
assert branch.function_name == "sequence"
|
|
52
|
+
assert branch.source_table is None # function branch, not catalog-table
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_single_branch_table_falls_back_to_legacy_rpc(client: Any) -> None:
|
|
56
|
+
"""`data.numbers` only implements `table_scan_function_get` — the fallback wraps it as one branch."""
|
|
57
|
+
result = client.table_scan_branches_get(
|
|
58
|
+
attach_opaque_data=_attach_opaque(client),
|
|
59
|
+
schema_name=DATA,
|
|
60
|
+
name="numbers",
|
|
61
|
+
)
|
|
62
|
+
assert len(result.branches) == 1
|
|
63
|
+
assert result.branches[0].function_name == client.table_scan_function_get(
|
|
64
|
+
attach_opaque_data=_attach_opaque(client),
|
|
65
|
+
schema_name=DATA,
|
|
66
|
+
name="numbers",
|
|
67
|
+
).function_name
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Copyright 2026 Query Farm LLC - https://query.farm
|
|
2
|
+
|
|
3
|
+
# ruff: noqa: S101, D101, D102, D103
|
|
4
|
+
"""`Client.table_function_plan` + `Client.table_function(split_tokens=...)`.
|
|
5
|
+
|
|
6
|
+
Splits were previously entirely unreachable from `Client` — no wrapper for
|
|
7
|
+
`on_plan()` existed at all, and `table_function()`/`_do_init` had no
|
|
8
|
+
`split_tokens` parameter to redeem one, even though the wire protocol
|
|
9
|
+
(`TableFunctionPlanRequest`/`PlanResponse`/`InitRequest.split_tokens`) and the
|
|
10
|
+
`VgiProtocol.table_function_plan` RPC already supported it — the DuckDB C++
|
|
11
|
+
extension drives this today, but the reference Python client never grew the
|
|
12
|
+
equivalent. Exercised against `split_sequence` (the split-capable twin of
|
|
13
|
+
`sequence`, `vgi/_test_fixtures/table/splits.py`) over every client transport.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
import pyarrow as pa
|
|
21
|
+
import pytest
|
|
22
|
+
|
|
23
|
+
from vgi.arguments import Arguments
|
|
24
|
+
from vgi.protocol import ScanSplit
|
|
25
|
+
|
|
26
|
+
MAIN = "main"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@pytest.fixture
|
|
30
|
+
def client(client_transport: Any) -> Any:
|
|
31
|
+
with client_transport() as c:
|
|
32
|
+
c.catalog_attach(name="example", data_version_spec=None, implementation_version=None)
|
|
33
|
+
yield c
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_plan_returns_typed_scan_splits(client: Any) -> None:
|
|
37
|
+
args = Arguments(named={"n": pa.scalar(20), "splits": pa.scalar(4)})
|
|
38
|
+
plan = client.table_function_plan(function_name="split_sequence", schema_name=MAIN, arguments=args)
|
|
39
|
+
assert len(plan.splits) == 4
|
|
40
|
+
for split in plan.splits:
|
|
41
|
+
assert isinstance(split, ScanSplit)
|
|
42
|
+
assert split.token # framework-stamped, non-empty
|
|
43
|
+
assert split.estimated_rows == 5
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_redeeming_each_split_in_order_reproduces_the_whole_scan(client: Any) -> None:
|
|
47
|
+
"""split_sequence redeemed split-by-split must equal sequence(n)'s output.
|
|
48
|
+
|
|
49
|
+
Also threads ``split_execution_id``/``split_init_opaque_data`` from the
|
|
50
|
+
plan on every redemption — this fixture doesn't need cross-split shared
|
|
51
|
+
state to be correct, but this proves the wire path accepts and round-trips
|
|
52
|
+
them without erroring, for workers that do.
|
|
53
|
+
"""
|
|
54
|
+
args = Arguments(named={"n": pa.scalar(37), "splits": pa.scalar(5)})
|
|
55
|
+
plan = client.table_function_plan(function_name="split_sequence", schema_name=MAIN, arguments=args)
|
|
56
|
+
|
|
57
|
+
all_rows: list[int] = []
|
|
58
|
+
for split in plan.splits:
|
|
59
|
+
batches = list(
|
|
60
|
+
client.table_function(
|
|
61
|
+
function_name="split_sequence",
|
|
62
|
+
schema_name=MAIN,
|
|
63
|
+
arguments=args,
|
|
64
|
+
split_tokens=[split.token],
|
|
65
|
+
split_execution_id=plan.execution_id,
|
|
66
|
+
split_init_opaque_data=plan.init_opaque_data,
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
for batch in batches:
|
|
70
|
+
all_rows.extend(batch.column("n").to_pylist())
|
|
71
|
+
|
|
72
|
+
assert sorted(all_rows) == list(range(37))
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_split_zero_yields_no_splits_and_no_rows(client: Any) -> None:
|
|
76
|
+
args = Arguments(named={"n": pa.scalar(10), "splits": pa.scalar(4)})
|
|
77
|
+
plan = client.table_function_plan(function_name="split_zero", schema_name=MAIN, arguments=args)
|
|
78
|
+
assert plan.splits == []
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def test_redeeming_a_split_forces_single_worker(client: Any) -> None:
|
|
82
|
+
"""`split_tokens` bypasses `_spawn_additional_workers` — no additional worker connections open."""
|
|
83
|
+
args = Arguments(named={"n": pa.scalar(8), "splits": pa.scalar(2)})
|
|
84
|
+
plan = client.table_function_plan(function_name="split_sequence", schema_name=MAIN, arguments=args)
|
|
85
|
+
list(
|
|
86
|
+
client.table_function(
|
|
87
|
+
function_name="split_sequence",
|
|
88
|
+
schema_name=MAIN,
|
|
89
|
+
arguments=args,
|
|
90
|
+
split_tokens=[plan.splits[0].token],
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
assert client._additional_workers == []
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Copyright 2026 Query Farm LLC - https://query.farm
|
|
2
|
+
|
|
3
|
+
# ruff: noqa: S101, D101, D102, D103
|
|
4
|
+
"""`Client.table_get`/`table_function(at_unit=..., at_value=...)`.
|
|
5
|
+
|
|
6
|
+
Both methods previously dropped `at_unit`/`at_value` on the floor even though
|
|
7
|
+
the underlying wire RPCs (`catalog_table_get`, `BindRequest.at_unit`/
|
|
8
|
+
`.at_value`) already carried them — `table_scan_function_get` was the only
|
|
9
|
+
`Client` method that exposed time travel at all. Two distinct worker
|
|
10
|
+
patterns are exercised, both real fixtures, proving this isn't just plumbing
|
|
11
|
+
that happens to compile:
|
|
12
|
+
|
|
13
|
+
* `data.versioned_data` reads its version through a pre-resolved bind
|
|
14
|
+
argument (`table_scan_function_get(at_unit=...)` bakes it into the
|
|
15
|
+
returned `ScanFunctionResult.arguments`) — `table_get(at_unit=...)` is
|
|
16
|
+
what needed fixing here, to see the schema at that version at all.
|
|
17
|
+
* `data.tt_pushdown_fn` (`tt_pushdown_scan`) reads `at_unit`/`at_value`
|
|
18
|
+
**directly off the init request** (`ProcessParams.at_unit`/`.at_value`,
|
|
19
|
+
see `vgi/_test_fixtures/table/tt_pushdown.py`) — this is the pattern that
|
|
20
|
+
needed `table_function(at_unit=...)` specifically; no amount of
|
|
21
|
+
pre-resolved arguments would reach it.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
from typing import Any
|
|
27
|
+
|
|
28
|
+
import pyarrow as pa
|
|
29
|
+
import pytest
|
|
30
|
+
|
|
31
|
+
from vgi.arguments import Arguments
|
|
32
|
+
|
|
33
|
+
DATA = "data"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@pytest.fixture
|
|
37
|
+
def client(client_transport: Any) -> Any:
|
|
38
|
+
with client_transport() as c:
|
|
39
|
+
c.catalog_attach(name="example", data_version_spec=None, implementation_version=None)
|
|
40
|
+
yield c
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _attach_opaque(client: Any) -> Any:
|
|
44
|
+
result = client.catalog_attach(name="example", data_version_spec=None, implementation_version=None)
|
|
45
|
+
return result.attach_opaque_data
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_table_get_at_unit_returns_the_versioned_schema(client: Any) -> None:
|
|
49
|
+
opaque = _attach_opaque(client)
|
|
50
|
+
v1 = client.table_get(
|
|
51
|
+
attach_opaque_data=opaque, schema_name=DATA, name="versioned_data", at_unit="VERSION", at_value="1"
|
|
52
|
+
)
|
|
53
|
+
live = client.table_get(attach_opaque_data=opaque, schema_name=DATA, name="versioned_data")
|
|
54
|
+
|
|
55
|
+
v1_schema = pa.ipc.read_schema(pa.py_buffer(v1.columns))
|
|
56
|
+
live_schema = pa.ipc.read_schema(pa.py_buffer(live.columns))
|
|
57
|
+
assert v1_schema.names == ["id"] # version 1: (id int64) only
|
|
58
|
+
assert live_schema.names == ["id", "score"] # current: version 3
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_table_get_with_no_at_clause_is_unaffected(client: Any) -> None:
|
|
62
|
+
"""The new `at_unit`/`at_value` params default to `None` — unchanged behavior without them."""
|
|
63
|
+
info = client.table_get(attach_opaque_data=_attach_opaque(client), schema_name=DATA, name="numbers")
|
|
64
|
+
assert info is not None
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def test_table_function_at_unit_reaches_a_worker_that_reads_it_from_init(client: Any) -> None:
|
|
68
|
+
"""`tt_pushdown_scan` reads `at_unit`/`at_value` off the init request, not a resolved bind arg."""
|
|
69
|
+
v1_batches = list(
|
|
70
|
+
client.table_function(function_name="tt_pushdown_scan", schema_name=DATA, at_unit="VERSION", at_value="1")
|
|
71
|
+
)
|
|
72
|
+
live_batches = list(client.table_function(function_name="tt_pushdown_scan", schema_name=DATA))
|
|
73
|
+
|
|
74
|
+
assert sum(b.num_rows for b in v1_batches) == 5
|
|
75
|
+
assert sum(b.num_rows for b in live_batches) == 10
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def test_table_function_with_no_at_clause_is_unaffected(client: Any) -> None:
|
|
79
|
+
"""The new `at_unit`/`at_value` params default to `None` — unchanged behavior without them."""
|
|
80
|
+
batches = list(
|
|
81
|
+
client.table_function(
|
|
82
|
+
function_name="sequence", schema_name="main", arguments=Arguments(positional=[pa.scalar(5)])
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
assert sum(b.num_rows for b in batches) == 5
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Copyright 2025, 2026 Query Farm LLC - https://query.farm
|
|
2
|
+
|
|
3
|
+
"""Round-trip tests for the launcher-managed (``transport="launch"``) transport.
|
|
4
|
+
|
|
5
|
+
Drives ``vgi._test_fixtures.worker`` (the same fixture module ``test_tcp_transport.py``
|
|
6
|
+
uses) through ``Client.from_launch(...)`` — no separate fixture worker needed, since
|
|
7
|
+
``MetaWorker.serve`` already passes argv through to ``vgi_rpc.rpc.run_server()``, which
|
|
8
|
+
participates in the AF_UNIX launcher path (``--unix PATH --idle-timeout SEC``) the same
|
|
9
|
+
way it participates in the TCP path (``--tcp HOST:PORT``).
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import shutil
|
|
15
|
+
import sys
|
|
16
|
+
import tempfile
|
|
17
|
+
import uuid
|
|
18
|
+
from collections.abc import Iterator
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
import pyarrow as pa
|
|
22
|
+
import pytest
|
|
23
|
+
from vgi_rpc.launcher import status_rows
|
|
24
|
+
|
|
25
|
+
from vgi.arguments import Arguments
|
|
26
|
+
from vgi.client import Client
|
|
27
|
+
|
|
28
|
+
_WORKER_ARGV = (sys.executable, "-m", "vgi._test_fixtures.worker")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@pytest.fixture
|
|
32
|
+
def state_dir() -> Iterator[str]:
|
|
33
|
+
"""Per-test state dir under ``/tmp`` to stay under macOS's 104-byte AF_UNIX limit.
|
|
34
|
+
|
|
35
|
+
Mirrors ``vgi-rpc``'s own ``test_launcher.py`` fixture — ``tmp_path`` resolves to a
|
|
36
|
+
deeply nested path that, concatenated with ``<hash>.sock``, blows past the cap.
|
|
37
|
+
"""
|
|
38
|
+
d = Path(tempfile.gettempdir()) / f"vgi-launch-test-{uuid.uuid4().hex[:8]}"
|
|
39
|
+
d.mkdir(mode=0o700)
|
|
40
|
+
try:
|
|
41
|
+
yield str(d)
|
|
42
|
+
finally:
|
|
43
|
+
shutil.rmtree(d, ignore_errors=True)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_launch_round_trip_table_function(state_dir: str) -> None:
|
|
47
|
+
"""A table function streams rows correctly over the launch transport."""
|
|
48
|
+
with Client.from_launch(_WORKER_ARGV, idle_timeout=10.0, state_dir=state_dir) as client:
|
|
49
|
+
batches = list(
|
|
50
|
+
client.table_function(
|
|
51
|
+
function_name="sequence",
|
|
52
|
+
schema_name="main",
|
|
53
|
+
arguments=Arguments(positional=(pa.scalar(5),)),
|
|
54
|
+
)
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
table = pa.Table.from_batches(batches)
|
|
58
|
+
assert table.column("n").to_pylist() == [0, 1, 2, 3, 4]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_launch_round_trip_catalog_listing(state_dir: str) -> None:
|
|
62
|
+
"""Catalog discovery works over the launch transport (catalog_mixin path)."""
|
|
63
|
+
with Client.from_launch(_WORKER_ARGV, idle_timeout=10.0, state_dir=state_dir) as client:
|
|
64
|
+
catalogs = client.catalogs()
|
|
65
|
+
|
|
66
|
+
assert any(c.name == "example" for c in catalogs)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def test_launch_shares_one_worker_across_clients(state_dir: str) -> None:
|
|
70
|
+
"""Two `Client`s with the same worker_argv + state_dir share one warm worker.
|
|
71
|
+
|
|
72
|
+
The whole point of the launcher over plain subprocess/TCP: a second client
|
|
73
|
+
pointing at the same command must reuse the first client's worker rather than
|
|
74
|
+
spawning its own. Proven by checking exactly one tracked worker exists in the
|
|
75
|
+
shared state dir after both clients have connected, not by any client-visible
|
|
76
|
+
process identity (the client has no API for that, by design — it shouldn't need
|
|
77
|
+
to know or care).
|
|
78
|
+
"""
|
|
79
|
+
with Client.from_launch(_WORKER_ARGV, idle_timeout=10.0, state_dir=state_dir) as client_a:
|
|
80
|
+
assert client_a.catalogs()
|
|
81
|
+
with Client.from_launch(_WORKER_ARGV, idle_timeout=10.0, state_dir=state_dir) as client_b:
|
|
82
|
+
assert client_b.catalogs()
|
|
83
|
+
rows = status_rows(Path(state_dir))
|
|
84
|
+
assert len(rows) == 1, f"expected exactly one shared worker, found {len(rows)}: {rows}"
|
|
85
|
+
assert rows[0].alive
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class TestLaunchConstructorValidation:
|
|
89
|
+
"""``transport='launch'`` argument validation."""
|
|
90
|
+
|
|
91
|
+
def test_requires_launch_argv(self) -> None:
|
|
92
|
+
"""Launch transport without launch_argv is rejected."""
|
|
93
|
+
with pytest.raises(ValueError, match="requires a non-empty launch_argv"):
|
|
94
|
+
Client(transport="launch", pool=None)
|
|
95
|
+
|
|
96
|
+
def test_rejects_empty_launch_argv(self) -> None:
|
|
97
|
+
"""An explicitly empty launch_argv is rejected the same as omitting it."""
|
|
98
|
+
with pytest.raises(ValueError, match="requires a non-empty launch_argv"):
|
|
99
|
+
Client(transport="launch", launch_argv=(), pool=None)
|
|
100
|
+
|
|
101
|
+
def test_rejects_server_path(self) -> None:
|
|
102
|
+
"""server_path is subprocess-only."""
|
|
103
|
+
with pytest.raises(ValueError, match="server_path is only meaningful"):
|
|
104
|
+
Client("some-worker", transport="launch", launch_argv=("x",), pool=None)
|
|
105
|
+
|
|
106
|
+
def test_rejects_base_url(self) -> None:
|
|
107
|
+
"""base_url is http-only."""
|
|
108
|
+
with pytest.raises(ValueError, match="base_url is only meaningful"):
|
|
109
|
+
Client(transport="launch", launch_argv=("x",), base_url="http://x", pool=None)
|
|
110
|
+
|
|
111
|
+
def test_rejects_tcp_host_and_port(self) -> None:
|
|
112
|
+
"""tcp_host/tcp_port are tcp-only."""
|
|
113
|
+
with pytest.raises(ValueError, match="tcp_host/tcp_port are only meaningful"):
|
|
114
|
+
Client(transport="launch", launch_argv=("x",), tcp_host="127.0.0.1", tcp_port=1, pool=None)
|