vgi-python 0.29.3__tar.gz → 0.29.5__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.3 → vgi_python-0.29.5}/PKG-INFO +6 -3
- {vgi_python-0.29.3 → vgi_python-0.29.5}/pyproject.toml +9 -4
- vgi_python-0.29.5/tests/table_in_out/test_blended_exchange.py +240 -0
- vgi_python-0.29.5/tests/test_launch_transport.py +114 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/uv.lock +27 -9
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/client/catalog_mixin.py +31 -4
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/client/client.py +257 -22
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/protocol.py +75 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/.gitattributes +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/.github/dependabot.yml +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/.github/styles/config/vocabularies/VGI/accept.txt +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/.github/workflows/ci.yml +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/.github/workflows/docs.yml +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/.github/workflows/integration.yml +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/.github/workflows/release.yml +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/.gitignore +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/.python-version +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/.vale.ini +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/CLAUDE.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/DOCS_ACCEPTANCE_CRITERIA.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/DOCS_REVIEW_RUBRIC.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/DOCS_USABILITY_TEST.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/LICENSE +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/README.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/RELEASE-RUNBOOK.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/SECURITY.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/ci/README.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/ci/preprocess-require.awk +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/ci/run-integration.sh +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/dist-vgi/.gitignore +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/aggregate-functions.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/api/arguments.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/api/auth.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/api/catalogs.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/api/client.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/api/exceptions.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/api/filters.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/api/functions.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/api/http.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/api/index.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/api/metadata.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/api/observability.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/api/storage.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/api/transactor.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/api/worker.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/argument-serialization.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/assets/apple-touch-icon.png +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/assets/favicon-16x16.png +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/assets/favicon-32x32.png +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/assets/favicon.ico +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/assets/kinds/aggregate.svg +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/assets/kinds/buffering.svg +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/assets/kinds/scalar.svg +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/assets/kinds/table-in-out.svg +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/assets/kinds/table.svg +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/assets/logo.png +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/assets/social-card.png +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/authentication.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/catalog-interface.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/cli.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/column-statistics.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/concepts/index.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/contributing-docs.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/filter-pushdown.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/generator-api.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/global-functions.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/how-to/catalogs.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/how-to/function-patterns.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/how-to/http-auth.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/how-to/index.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/how-to/pushdown-and-statistics.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/how-to/state-storage.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/index.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/lifecycle.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/metadata.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/overrides/main.html +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/robots.txt +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/shared-storage.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/stylesheets/extra.css +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/tutorial/index.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/tutorial/scalar.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/tutorial/table.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/docs/vgi-logo.png +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/examples/batch_index_worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/examples/cache_worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/examples/calc_scalar_worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/examples/calc_worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/examples/copy_format_worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/examples/filter_worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/examples/greeting_scalar_worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/examples/row_count_worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/examples/series_streaming_worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/examples/sum_worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/mkdocs.yml +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/packages/vgi-fixtures/LICENSE +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/packages/vgi-fixtures/README.md +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/packages/vgi-fixtures/docker/Dockerfile +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/packages/vgi-fixtures/docker/docker-entrypoint.sh +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/packages/vgi-fixtures/pyproject.toml +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/scripts/measure_startup.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/scripts/run_all_tests.sh +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/test-data/generate.sh +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/_http_fixtures.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/catalog/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/catalog/test_attach_option.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/catalog/test_catalog_interface.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/catalog/test_client_catalog.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/catalog/test_column_statistics.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/catalog/test_declarative.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/catalog/test_example_worker_catalog.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/catalog/test_integration.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/catalog/test_required_filters.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/catalog/test_scan_branches.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/catalog/test_serialization.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/catalog/test_setting.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/catalog/test_storage.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/catalog/test_time_travel.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/catalog/test_writable_table.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/client/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/client/test_aggregate_client.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/client/test_batch_metadata_callback.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/client/test_broken_pipe.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/client/test_cli.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/client/test_cli_catalog_functions.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/client/test_copy_client.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/client/test_scan_branches_client.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/client/test_split_client.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/client/test_stop_force.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/client/test_table_column_statistics.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/client/test_time_travel_client.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/client/test_worker_debug.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/_stub.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/conftest.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_accumulate.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_aggregate.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_attach.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_bearer_auth.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_const_param_enforcement.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_container.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_copy_from.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_copy_to.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_directory_parity.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_function_inventory.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_github.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_http_client.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_http_external_location.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_http_upload_url.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_macro.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_overload.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_protocol_inventory.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_protocol_version.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_resumable_scan.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_scalar.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_scalar_attach_opaque_data.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_secret.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_settings.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_splits.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_table.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_table_in_out.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_view.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conformance/test_writable.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/conftest.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/data/split_tokens/anchor_len_overrun.bin +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/data/split_tokens/bad_fingerprint.bin +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/data/split_tokens/bad_flags_unsealed_but_key_present.bin +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/data/split_tokens/bad_version.bin +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/data/split_tokens/generate.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/data/split_tokens/manifest.json +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/data/split_tokens/reserved_flag_bit.bin +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/data/split_tokens/stale_anchor.bin +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/data/split_tokens/truncated.bin +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/data/split_tokens/valid_sealed.bin +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/data/split_tokens/valid_unsealed.bin +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/scalar/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/scalar/test_bernoulli_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/scalar/test_binary_packet_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/scalar/test_client.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/scalar/test_conditional_message_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/scalar/test_hash_seed_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/scalar/test_multiply_by_setting_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/scalar/test_multiply_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/scalar/test_random_bytes_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/scalar/test_return_secret_value_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table/generator/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table/generator/test_constant_columns_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table/generator/test_double_sequence_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table/generator/test_exception_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table/generator/test_filter_echo_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table/generator/test_logging_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table/generator/test_nested_sequence_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table/generator/test_partitioned_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table/generator/test_projected_data_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table/generator/test_sequence_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table/generator/test_settings_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table/generator/test_struct_settings_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table/generator/test_ten_thousand_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table/test_wide_columns.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table_in_out/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table_in_out/generator/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table_in_out/generator/test_buffer_input_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table_in_out/generator/test_echo_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table_in_out/generator/test_exception_functions.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table_in_out/generator/test_filter_by_setting_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table_in_out/generator/test_repeat_inputs_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table_in_out/generator/test_substream_partial_sum_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table_in_out/generator/test_sum_all_columns_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table_in_out/test_blended_metadata.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/table_in_out/test_client.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_access_log_audit.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_aggregate_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_argument_spec.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_auth.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_bind_exceptions.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_bind_request_at_clause.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_bound_storage_conformance.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_cache_control.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_call_state_attach.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_catalog_auth_binding.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_copy_from_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_copy_to_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_docstrings.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_documentation_examples.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_example_function_arg_types.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_examples_workers.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_exception_handling.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_exceptions.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_filter_pushdown.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_filter_pushdown_extension.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_fixture_catalog_parity.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_function_storage.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_function_storage_azure_sql.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_function_storage_cf_do.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_function_storage_cf_do_integration.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_function_storage_conformance.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_generated_cpp_constants.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_generated_cpp_protocol_version.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_generated_cpp_request_builders.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_generated_cpp_schemas.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_generated_cpp_secret.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_generated_go_schemas.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_generated_java_schemas.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_generated_protocol_version.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_generated_rust_request_builders.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_generated_rust_schemas.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_generated_schemas_cross_lang.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_generated_ts_client.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_generated_ts_schemas.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_http_demo_storage.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_http_s3_offload_input.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_http_s3_offload_output.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_metadata.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_mypy_consolidated.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_nest_tensor.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_otel.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_projection_enforcement.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_projection_repro.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_protocol_classes.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_resolved_secrets.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_schema_scoped_functions.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_schema_utils.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_serve.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_setting_secret_annotations.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_signing_key.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_split_token.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_table_buffering_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_table_function_dynamic_to_string.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_tcp_transport.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_type_bounds.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_union_argument.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_wire_record_schema_parity.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_worker_cli.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/test_worker_page.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/transactor/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/tests/transactor/test_transactor.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_duckdb.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_storage_profile.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/accumulate/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/accumulate/worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/aggregate/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/aggregate/_common.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/aggregate/basic.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/aggregate/dynamic.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/aggregate/generic.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/aggregate/listagg.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/aggregate/percentile.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/aggregate/same_name.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/aggregate/secret_typed.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/aggregate/streaming.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/aggregate/varargs.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/aggregate/window.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/attach_options.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/bad_enum.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/bad_protocol.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/cancellable.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/catalog.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/companion.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/copy_from.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/copy_to.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/global_functions.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/http_server.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/narrow_bind/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/narrow_bind/worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/nest_tensor.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/orchard_catalog.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/projection_repro/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/projection_repro/worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/scalar/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/scalar/_common.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/scalar/arithmetic.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/scalar/bench_ladder.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/scalar/binary.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/scalar/formatting.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/scalar/geo.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/scalar/null_handling.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/scalar/random_demo.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/scalar/same_name.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/scalar/settings_secrets.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/scalar/type_info.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/schema_reconcile/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/schema_reconcile/worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/simple_writable.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/_common.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/batch_index.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/batch_index_broken.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/cache.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/catalog_scans.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/filters.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/late_materialization.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/make_series.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/misc.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/order_modes.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/pairs.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/partition_columns.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/partition_columns_broken.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/profiling_example.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/required_filters.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/same_name_cached.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/sequence.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/settings.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/splits.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/transaction_storage.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/tt_pushdown.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/typed_probe.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/versioned.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table/wide.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table_in_out.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/table_in_out_same_name.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/twin_catalogs.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/versioned.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/versioned_tables.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/writable/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/writable/generic.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/writable/table.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/_test_fixtures/writable/worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/aggregate_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/argument_spec.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/arguments.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/attach_header.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/auth.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/cache_control.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/catalog/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/catalog/_descriptor_spec.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/catalog/attach_option.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/catalog/catalog_interface.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/catalog/descriptors.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/catalog/duckdb_statistics.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/catalog/secret_type.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/catalog/setting.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/catalog/storage.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/client/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/client/aggregate.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/client/cli.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/client/cli_catalog.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/client/cli_schema.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/client/cli_table.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/client/cli_transaction.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/client/cli_utils.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/client/cli_view.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/client/errors.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/codegen/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/codegen/_common.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/codegen/cpp_constants.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/codegen/cpp_protocol_version.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/codegen/cpp_request_builders.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/codegen/cpp_schemas.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/codegen/cpp_secret_protocol_version.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/codegen/cpp_secret_request_builders.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/codegen/cpp_secret_schemas.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/codegen/go_schemas.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/codegen/java_schemas.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/codegen/protocol_version.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/codegen/rust_request_builders.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/codegen/rust_schemas.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/codegen/ts_client.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/codegen/ts_schemas.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/copy_from_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/copy_to_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/exceptions.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/function_storage.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/function_storage_azure_sql.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/function_storage_cf_do.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/http/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/http/demo_storage.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/http/landing.html +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/http/landing_page.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/http/vgi-client.js +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/http/worker_page.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/invocation.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/logging_config.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/meta_worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/metadata.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/otel.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/profiling.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/protocol_version.txt +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/py.typed +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/scalar_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/schema_utils.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/secret_protocol.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/secret_service.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/serve.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/split_token.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/table_buffering_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/table_filter_pushdown.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/table_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/table_in_out_function.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/transactor/__init__.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/transactor/_duckdb_compat.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/transactor/client.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/transactor/protocol.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/transactor/server.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/vgi/worker.py +0 -0
- {vgi_python-0.29.3 → vgi_python-0.29.5}/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.5
|
|
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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "vgi-python"
|
|
3
|
-
version = "0.29.
|
|
3
|
+
version = "0.29.5"
|
|
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,240 @@
|
|
|
1
|
+
# Copyright 2025, 2026 Query Farm LLC - https://query.farm
|
|
2
|
+
|
|
3
|
+
"""RPC-level exchange coverage for blended (`RowTransformFunction`) table functions.
|
|
4
|
+
|
|
5
|
+
`test_blended_metadata.py` covers `resolve_metadata()` in isolation — no worker
|
|
6
|
+
subprocess. This file is the first exchange-level coverage for the blended
|
|
7
|
+
fixtures registered in `vgi/_test_fixtures/table_in_out.py`: it drives them
|
|
8
|
+
through `Client.table_in_out_function(...)`'s new `parent_row_callback`, which
|
|
9
|
+
decodes `vgi_rpc.parent_row#b64` provenance for a 1->N / 1->0 emit (see
|
|
10
|
+
`vgi.protocol._decode_parent_rows`).
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
import pyarrow as pa
|
|
18
|
+
import pytest
|
|
19
|
+
|
|
20
|
+
from tests.conftest import make_schema
|
|
21
|
+
from vgi.arguments import Arguments
|
|
22
|
+
from vgi.client import Client
|
|
23
|
+
from vgi.client.client import ClientError
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class TestBlendedExplodeProvenance:
|
|
27
|
+
"""`blended_explode`: 1->N fan-out with per-output-row parent_row provenance."""
|
|
28
|
+
|
|
29
|
+
def test_parent_row_pairing_is_correct(self, fixture_worker: str) -> None:
|
|
30
|
+
"""Each output row's parent index must point at the input row that produced it.
|
|
31
|
+
|
|
32
|
+
Asserting only the final row *set* would pass even for a naive
|
|
33
|
+
"assume identity" implementation whenever fan-out counts differ
|
|
34
|
+
across rows -- so this reconstructs the exact expected
|
|
35
|
+
(parent_row, emitted_value) pairs in emission order and compares.
|
|
36
|
+
"""
|
|
37
|
+
input_schema = make_schema([pa.field("n", pa.int64())])
|
|
38
|
+
counts = [0, 1, 3, 2]
|
|
39
|
+
batch = pa.RecordBatch.from_pydict({"n": counts}, schema=input_schema)
|
|
40
|
+
|
|
41
|
+
parent_rows_seen: list[int] = []
|
|
42
|
+
|
|
43
|
+
with Client(fixture_worker) as client:
|
|
44
|
+
results = list(
|
|
45
|
+
client.table_in_out_function(
|
|
46
|
+
function_name="blended_explode",
|
|
47
|
+
schema_name="main",
|
|
48
|
+
input=iter([batch]),
|
|
49
|
+
parent_row_callback=parent_rows_seen.extend,
|
|
50
|
+
)
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
assert len(results) == 1
|
|
54
|
+
out = results[0]
|
|
55
|
+
i_values = out.column("i").to_pylist()
|
|
56
|
+
|
|
57
|
+
assert len(i_values) == sum(counts)
|
|
58
|
+
assert len(parent_rows_seen) == len(i_values)
|
|
59
|
+
|
|
60
|
+
expected_pairs = [(row_idx, k) for row_idx, n in enumerate(counts) for k in range(n)]
|
|
61
|
+
actual_pairs = list(zip(parent_rows_seen, i_values, strict=True))
|
|
62
|
+
assert actual_pairs == expected_pairs
|
|
63
|
+
|
|
64
|
+
def test_all_rows_filtered_to_empty_result(self, fixture_worker: str) -> None:
|
|
65
|
+
"""n=0 for every input row -> a correctly-schemed, zero-row output."""
|
|
66
|
+
input_schema = make_schema([pa.field("n", pa.int64())])
|
|
67
|
+
batch = pa.RecordBatch.from_pydict({"n": [0, 0, 0]}, schema=input_schema)
|
|
68
|
+
|
|
69
|
+
parent_rows_seen: list[list[int]] = []
|
|
70
|
+
|
|
71
|
+
with Client(fixture_worker) as client:
|
|
72
|
+
results = list(
|
|
73
|
+
client.table_in_out_function(
|
|
74
|
+
function_name="blended_explode",
|
|
75
|
+
schema_name="main",
|
|
76
|
+
input=iter([batch]),
|
|
77
|
+
parent_row_callback=parent_rows_seen.append,
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
assert len(results) == 1
|
|
82
|
+
out = results[0]
|
|
83
|
+
assert out.num_rows == 0
|
|
84
|
+
assert out.schema.names == ["i"]
|
|
85
|
+
assert parent_rows_seen == [[]]
|
|
86
|
+
|
|
87
|
+
def test_identity_map_when_row_counts_match(self, fixture_worker: str) -> None:
|
|
88
|
+
"""n=1 for every row -> a 1:1 emit; the identity map is a valid decode.
|
|
89
|
+
|
|
90
|
+
`blended_explode` never encodes `vgi_rpc.parent_row` for a 1:1 emit
|
|
91
|
+
(the C++ reference assumes identity for that case too), so this
|
|
92
|
+
exercises `_decode_parent_rows`'s absent-metadata branch, not just
|
|
93
|
+
the explicit-array branch the other tests exercise.
|
|
94
|
+
"""
|
|
95
|
+
input_schema = make_schema([pa.field("n", pa.int64())])
|
|
96
|
+
batch = pa.RecordBatch.from_pydict({"n": [1, 1, 1]}, schema=input_schema)
|
|
97
|
+
|
|
98
|
+
parent_rows_seen: list[int] = []
|
|
99
|
+
|
|
100
|
+
with Client(fixture_worker) as client:
|
|
101
|
+
results = list(
|
|
102
|
+
client.table_in_out_function(
|
|
103
|
+
function_name="blended_explode",
|
|
104
|
+
schema_name="main",
|
|
105
|
+
input=iter([batch]),
|
|
106
|
+
parent_row_callback=parent_rows_seen.extend,
|
|
107
|
+
)
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
assert len(results) == 1
|
|
111
|
+
assert results[0].column("i").to_pylist() == [0, 0, 0]
|
|
112
|
+
assert parent_rows_seen == [0, 1, 2]
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class TestHostileProvenance:
|
|
116
|
+
"""`hostile_provenance`: adversarial worker payloads must raise, never corrupt."""
|
|
117
|
+
|
|
118
|
+
@pytest.mark.parametrize("mode", ["range", "length", "base64"])
|
|
119
|
+
def test_malformed_provenance_raises_client_error(
|
|
120
|
+
self,
|
|
121
|
+
client_transport: Any,
|
|
122
|
+
mode: str,
|
|
123
|
+
) -> None:
|
|
124
|
+
"""Each hostile mode must raise ClientError on both subprocess and HTTP.
|
|
125
|
+
|
|
126
|
+
Symmetry matters here: an asymmetry between transports would mean one
|
|
127
|
+
parse path validates and the other doesn't -- a security bug, not
|
|
128
|
+
just an inconsistency.
|
|
129
|
+
"""
|
|
130
|
+
input_schema = make_schema([pa.field("x", pa.int64())])
|
|
131
|
+
batch = pa.RecordBatch.from_pydict({"x": [1, 2, 3]}, schema=input_schema)
|
|
132
|
+
|
|
133
|
+
with client_transport() as client, pytest.raises(ClientError):
|
|
134
|
+
list(
|
|
135
|
+
client.table_in_out_function(
|
|
136
|
+
function_name="hostile_provenance",
|
|
137
|
+
schema_name="main",
|
|
138
|
+
input=iter([batch]),
|
|
139
|
+
arguments=Arguments(named={"mode": pa.scalar(mode)}),
|
|
140
|
+
parent_row_callback=lambda _rows: None,
|
|
141
|
+
)
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
def test_no_callback_no_decode_no_raise(self, fixture_worker: str) -> None:
|
|
145
|
+
"""Without `parent_row_callback`, malformed provenance is never even decoded.
|
|
146
|
+
|
|
147
|
+
`decode_parent_rows` is derived from `parent_row_callback is not None`
|
|
148
|
+
-- this is the backward-compat guarantee that an ordinary (non-blended)
|
|
149
|
+
table-in-out caller, which never passes the callback, is completely
|
|
150
|
+
unaffected by this feature existing.
|
|
151
|
+
"""
|
|
152
|
+
input_schema = make_schema([pa.field("x", pa.int64())])
|
|
153
|
+
batch = pa.RecordBatch.from_pydict({"x": [1, 2, 3]}, schema=input_schema)
|
|
154
|
+
|
|
155
|
+
with Client(fixture_worker) as client:
|
|
156
|
+
results = list(
|
|
157
|
+
client.table_in_out_function(
|
|
158
|
+
function_name="hostile_provenance",
|
|
159
|
+
schema_name="main",
|
|
160
|
+
input=iter([batch]),
|
|
161
|
+
arguments=Arguments(named={"mode": pa.scalar("range")}),
|
|
162
|
+
)
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
assert len(results) == 1
|
|
166
|
+
assert results[0].column("hv").to_pylist() == [1, 2, 3]
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class TestBlendedArityAndVarargs:
|
|
170
|
+
"""Broader coverage once the core provenance mechanism is proven."""
|
|
171
|
+
|
|
172
|
+
def test_geo_encode_two_arg_overload(self, fixture_worker: str) -> None:
|
|
173
|
+
"""`geo_encode(lat, lon)` -- the 2-arg overload, identity 1:1 map."""
|
|
174
|
+
input_schema = make_schema([pa.field("latitude", pa.float64()), pa.field("longitude", pa.float64())])
|
|
175
|
+
batch = pa.RecordBatch.from_pydict(
|
|
176
|
+
{"latitude": [52.0, 48.5], "longitude": [13.0, 2.3]},
|
|
177
|
+
schema=input_schema,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
parent_rows_seen: list[int] = []
|
|
181
|
+
|
|
182
|
+
with Client(fixture_worker) as client:
|
|
183
|
+
results = list(
|
|
184
|
+
client.table_in_out_function(
|
|
185
|
+
function_name="geo_encode",
|
|
186
|
+
schema_name="main",
|
|
187
|
+
input=iter([batch]),
|
|
188
|
+
arguments=Arguments(named={"precision": pa.scalar(1)}),
|
|
189
|
+
parent_row_callback=parent_rows_seen.extend,
|
|
190
|
+
)
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
assert len(results) == 1
|
|
194
|
+
assert results[0].column("geohash").to_pylist() == ["52.0:13.0", "48.5:2.3"]
|
|
195
|
+
assert parent_rows_seen == [0, 1]
|
|
196
|
+
|
|
197
|
+
def test_geo_encode_three_arg_overload(self, fixture_worker: str) -> None:
|
|
198
|
+
"""`geo_encode(lat, lon, alt)` -- same Meta.name, resolved by input arity."""
|
|
199
|
+
input_schema = make_schema(
|
|
200
|
+
[
|
|
201
|
+
pa.field("latitude", pa.float64()),
|
|
202
|
+
pa.field("longitude", pa.float64()),
|
|
203
|
+
pa.field("altitude", pa.float64()),
|
|
204
|
+
]
|
|
205
|
+
)
|
|
206
|
+
batch = pa.RecordBatch.from_pydict(
|
|
207
|
+
{"latitude": [52.0], "longitude": [13.0], "altitude": [100.0]},
|
|
208
|
+
schema=input_schema,
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
with Client(fixture_worker) as client:
|
|
212
|
+
results = list(
|
|
213
|
+
client.table_in_out_function(
|
|
214
|
+
function_name="geo_encode",
|
|
215
|
+
schema_name="main",
|
|
216
|
+
input=iter([batch]),
|
|
217
|
+
arguments=Arguments(named={"precision": pa.scalar(0)}),
|
|
218
|
+
)
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
assert len(results) == 1
|
|
222
|
+
assert results[0].column("geohash").to_pylist() == ["52.0:13.0:100.0"]
|
|
223
|
+
|
|
224
|
+
def test_row_sum_varargs(self, fixture_worker: str) -> None:
|
|
225
|
+
"""`row_sum(a, b, c)` -- varargs positional input, positionally-named columns."""
|
|
226
|
+
input_schema = make_schema([pa.field("col0", pa.float64()), pa.field("col1", pa.float64())])
|
|
227
|
+
batch = pa.RecordBatch.from_pydict({"col0": [1.0, -2.0], "col1": [2.0, -3.0]}, schema=input_schema)
|
|
228
|
+
|
|
229
|
+
with Client(fixture_worker) as client:
|
|
230
|
+
results = list(
|
|
231
|
+
client.table_in_out_function(
|
|
232
|
+
function_name="row_sum",
|
|
233
|
+
schema_name="main",
|
|
234
|
+
input=iter([batch]),
|
|
235
|
+
arguments=Arguments(named={"absolute": pa.scalar(True)}),
|
|
236
|
+
)
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
assert len(results) == 1
|
|
240
|
+
assert results[0].column("row_sum").to_pylist() == [3.0, 5.0]
|
|
@@ -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)
|
|
@@ -714,6 +714,15 @@ wheels = [
|
|
|
714
714
|
{ url = "https://files.pythonhosted.org/packages/da/ef/5790e74a7b39d2c085554f347be22a1882649a29a7a65e9c81bfaf9e8fc6/falcon-4.3.1-py3-none-any.whl", hash = "sha256:5402602d14bc426afc01c388538f2ad402ac4c8c2477415dfe972a2deee17248", size = 332719, upload-time = "2026-06-16T05:31:23.373Z" },
|
|
715
715
|
]
|
|
716
716
|
|
|
717
|
+
[[package]]
|
|
718
|
+
name = "filelock"
|
|
719
|
+
version = "3.32.4"
|
|
720
|
+
source = { registry = "https://pypi.org/simple" }
|
|
721
|
+
sdist = { url = "https://files.pythonhosted.org/packages/6d/30/03b03951873a1a0ffc7e8ca0e10c15597b59e8d0e39260704cd2ea087bc4/filelock-3.32.4.tar.gz", hash = "sha256:2bde2e4cf732e0153406d8a7bc80620ecf5e621fe0d25e41143c4e3b4733ff30", size = 222126, upload-time = "2026-08-23T17:37:55.363Z" }
|
|
722
|
+
wheels = [
|
|
723
|
+
{ url = "https://files.pythonhosted.org/packages/01/a4/9b63d595d748e3aff8812b65eacc1a2c4bd90b7c2012e08e72373b4835eb/filelock-3.32.4-py3-none-any.whl", hash = "sha256:22e58ca3b1ae3b98993b762d7338367ae64fe50252bf78d59da3bfebcdf1cedd", size = 99864, upload-time = "2026-08-23T17:37:53.913Z" },
|
|
724
|
+
]
|
|
725
|
+
|
|
717
726
|
[[package]]
|
|
718
727
|
name = "frozenlist"
|
|
719
728
|
version = "1.8.0"
|
|
@@ -2560,7 +2569,7 @@ requires-dist = [
|
|
|
2560
2569
|
|
|
2561
2570
|
[[package]]
|
|
2562
2571
|
name = "vgi-python"
|
|
2563
|
-
version = "0.29.
|
|
2572
|
+
version = "0.29.5"
|
|
2564
2573
|
source = { editable = "." }
|
|
2565
2574
|
dependencies = [
|
|
2566
2575
|
{ name = "click" },
|
|
@@ -2591,7 +2600,7 @@ dev = [
|
|
|
2591
2600
|
{ name = "pytest-xdist" },
|
|
2592
2601
|
{ name = "ruff" },
|
|
2593
2602
|
{ name = "sqlglot" },
|
|
2594
|
-
{ name = "vgi-rpc", extra = ["conformance", "external", "http", "oauth", "otel", "sentry"] },
|
|
2603
|
+
{ name = "vgi-rpc", extra = ["cli", "conformance", "external", "http", "oauth", "otel", "sentry"] },
|
|
2595
2604
|
]
|
|
2596
2605
|
duckdb = [
|
|
2597
2606
|
{ name = "duckdb" },
|
|
@@ -2609,6 +2618,9 @@ haybarn = [
|
|
|
2609
2618
|
http = [
|
|
2610
2619
|
{ name = "vgi-rpc", extra = ["http"] },
|
|
2611
2620
|
]
|
|
2621
|
+
launch = [
|
|
2622
|
+
{ name = "vgi-rpc", extra = ["cli"] },
|
|
2623
|
+
]
|
|
2612
2624
|
oauth = [
|
|
2613
2625
|
{ name = "vgi-rpc", extra = ["oauth"] },
|
|
2614
2626
|
]
|
|
@@ -2672,17 +2684,18 @@ requires-dist = [
|
|
|
2672
2684
|
{ name = "typer", specifier = ">=0.9" },
|
|
2673
2685
|
{ name = "vgi-fixtures", marker = "extra == 'fixtures'", editable = "packages/vgi-fixtures" },
|
|
2674
2686
|
{ name = "vgi-python", extras = ["test-fixtures"], marker = "extra == 'test-fixtures-writable'" },
|
|
2675
|
-
{ name = "vgi-python", extras = ["test-fixtures", "test-fixtures-writable", "http", "oauth", "otel", "sentry", "azure"], marker = "extra == 'dev'" },
|
|
2687
|
+
{ name = "vgi-python", extras = ["test-fixtures", "test-fixtures-writable", "http", "launch", "oauth", "otel", "sentry", "azure"], marker = "extra == 'dev'" },
|
|
2676
2688
|
{ name = "vgi-python", extras = ["transactor"], marker = "extra == 'test-fixtures-writable'" },
|
|
2677
|
-
{ name = "vgi-rpc", specifier = ">=0.43.
|
|
2678
|
-
{ name = "vgi-rpc", extras = ["
|
|
2689
|
+
{ name = "vgi-rpc", specifier = ">=0.43.2" },
|
|
2690
|
+
{ name = "vgi-rpc", extras = ["cli"], marker = "extra == 'launch'" },
|
|
2691
|
+
{ name = "vgi-rpc", extras = ["cli", "conformance", "external", "http", "oauth", "otel", "sentry"], marker = "extra == 'dev'" },
|
|
2679
2692
|
{ name = "vgi-rpc", extras = ["http"], marker = "extra == 'granian'" },
|
|
2680
2693
|
{ name = "vgi-rpc", extras = ["http"], marker = "extra == 'http'" },
|
|
2681
2694
|
{ name = "vgi-rpc", extras = ["oauth"], marker = "extra == 'oauth'" },
|
|
2682
2695
|
{ name = "vgi-rpc", extras = ["otel"], marker = "extra == 'otel'" },
|
|
2683
2696
|
{ name = "vgi-rpc", extras = ["sentry"], marker = "extra == 'sentry'" },
|
|
2684
2697
|
]
|
|
2685
|
-
provides-extras = ["haybarn", "duckdb", "http", "granian", "oauth", "otel", "sentry", "azure", "test-fixtures", "transactor", "fixtures", "test-fixtures-writable", "dev"]
|
|
2698
|
+
provides-extras = ["haybarn", "duckdb", "http", "launch", "granian", "oauth", "otel", "sentry", "azure", "test-fixtures", "transactor", "fixtures", "test-fixtures-writable", "dev"]
|
|
2686
2699
|
|
|
2687
2700
|
[package.metadata.requires-dev]
|
|
2688
2701
|
dev = [
|
|
@@ -2703,7 +2716,7 @@ docs = [
|
|
|
2703
2716
|
|
|
2704
2717
|
[[package]]
|
|
2705
2718
|
name = "vgi-rpc"
|
|
2706
|
-
version = "0.43.
|
|
2719
|
+
version = "0.43.2"
|
|
2707
2720
|
source = { registry = "https://pypi.org/simple" }
|
|
2708
2721
|
dependencies = [
|
|
2709
2722
|
{ name = "docstring-parser" },
|
|
@@ -2711,12 +2724,17 @@ dependencies = [
|
|
|
2711
2724
|
{ name = "pywin32", marker = "sys_platform == 'win32'" },
|
|
2712
2725
|
{ name = "tzdata", marker = "sys_platform == 'win32'" },
|
|
2713
2726
|
]
|
|
2714
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
2727
|
+
sdist = { url = "https://files.pythonhosted.org/packages/ce/04/efb99f0fb56535bcba110e6c12448c31b429e0861aae4bc2f7136299cfc2/vgi_rpc-0.43.2.tar.gz", hash = "sha256:6a06437af17442451bfe07186bc472a2efb57e030b0e5b38a28922034a814123", size = 1147340, upload-time = "2026-08-27T18:33:54.608Z" }
|
|
2715
2728
|
wheels = [
|
|
2716
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2729
|
+
{ url = "https://files.pythonhosted.org/packages/ac/b9/33cdb4fe27ef3893e1cded63f396af8bc517e390615f34db6f4bd227ef4c/vgi_rpc-0.43.2-py3-none-any.whl", hash = "sha256:b112ab76828367176a41f1b9a4ceeaba8979629e4e5972f64bf769c94b3e36a4", size = 528134, upload-time = "2026-08-27T18:33:52.829Z" },
|
|
2717
2730
|
]
|
|
2718
2731
|
|
|
2719
2732
|
[package.optional-dependencies]
|
|
2733
|
+
cli = [
|
|
2734
|
+
{ name = "filelock" },
|
|
2735
|
+
{ name = "httpx2" },
|
|
2736
|
+
{ name = "typer" },
|
|
2737
|
+
]
|
|
2720
2738
|
conformance = [
|
|
2721
2739
|
{ name = "jsonschema" },
|
|
2722
2740
|
{ name = "psutil" },
|
|
@@ -100,9 +100,11 @@ class CatalogClientMixin:
|
|
|
100
100
|
non-DuckDB use case this mixin supports.
|
|
101
101
|
|
|
102
102
|
Other attributes expected from ``Client``: ``_transport`` (subprocess,
|
|
103
|
-
http, or
|
|
104
|
-
(TCP endpoint),
|
|
105
|
-
|
|
103
|
+
http, tcp, or launch), ``_base_url`` (HTTP base URL), ``_tcp_host`` /
|
|
104
|
+
``_tcp_port`` (TCP endpoint), ``_launch_argv`` / ``_launch_idle_timeout`` /
|
|
105
|
+
``_launch_state_dir`` / ``_launch_socket_path`` (launcher worker
|
|
106
|
+
identity + lifecycle), and ``_get_or_create_httpx_client()`` (shared
|
|
107
|
+
HTTP client factory).
|
|
106
108
|
|
|
107
109
|
Attributes:
|
|
108
110
|
server_path: Worker command used for subprocess transport — a string to
|
|
@@ -111,10 +113,14 @@ class CatalogClientMixin:
|
|
|
111
113
|
|
|
112
114
|
# Type hints for attributes expected from Client
|
|
113
115
|
server_path: str | Sequence[str]
|
|
114
|
-
_transport: Literal["subprocess", "http", "tcp"]
|
|
116
|
+
_transport: Literal["subprocess", "http", "tcp", "launch"]
|
|
115
117
|
_base_url: str | None
|
|
116
118
|
_tcp_host: str | None
|
|
117
119
|
_tcp_port: int | None
|
|
120
|
+
_launch_argv: tuple[str, ...] | None
|
|
121
|
+
_launch_idle_timeout: float
|
|
122
|
+
_launch_state_dir: str | None
|
|
123
|
+
_launch_socket_path: str | None
|
|
118
124
|
_external_location: Any | None
|
|
119
125
|
|
|
120
126
|
def _worker_argv(self) -> list[str]:
|
|
@@ -144,6 +150,11 @@ class CatalogClientMixin:
|
|
|
144
150
|
``Client._get_or_create_httpx_client`` so auth headers and
|
|
145
151
|
connection pooling are consistent.
|
|
146
152
|
|
|
153
|
+
Launch: opens a short-lived ``resolve_and_connect`` session per call
|
|
154
|
+
against the launcher-managed shared worker — same warm-worker sharing
|
|
155
|
+
as exchange-mode calls (``Client._spawn_launch_connection``), just a
|
|
156
|
+
fresh connection to it per catalog RPC rather than one held open.
|
|
157
|
+
|
|
147
158
|
Worker errors are caught and re-raised as ``CatalogClientError``.
|
|
148
159
|
|
|
149
160
|
Yields:
|
|
@@ -173,6 +184,22 @@ class CatalogClientMixin:
|
|
|
173
184
|
external_location=getattr(self, "_external_location", None),
|
|
174
185
|
) as proxy:
|
|
175
186
|
yield proxy
|
|
187
|
+
elif transport == "launch":
|
|
188
|
+
from vgi_rpc.launcher import LaunchConfig, resolve_and_connect
|
|
189
|
+
|
|
190
|
+
assert self._launch_argv is not None
|
|
191
|
+
config = LaunchConfig(
|
|
192
|
+
worker_argv=self._launch_argv,
|
|
193
|
+
socket_path=self._launch_socket_path,
|
|
194
|
+
idle_timeout=self._launch_idle_timeout,
|
|
195
|
+
state_dir=self._launch_state_dir,
|
|
196
|
+
)
|
|
197
|
+
with resolve_and_connect(
|
|
198
|
+
VgiProtocol, # type: ignore[type-abstract]
|
|
199
|
+
config,
|
|
200
|
+
external_location=getattr(self, "_external_location", None),
|
|
201
|
+
) as proxy:
|
|
202
|
+
yield proxy
|
|
176
203
|
else:
|
|
177
204
|
cmd = self._worker_argv()
|
|
178
205
|
with _catalog_pool.connect(VgiProtocol, cmd) as proxy: # type: ignore[type-abstract]
|