vgi-python 0.19.0__tar.gz → 0.21.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {vgi_python-0.19.0 → vgi_python-0.21.0}/PKG-INFO +1 -1
- {vgi_python-0.19.0 → vgi_python-0.21.0}/pyproject.toml +1 -1
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/catalog/test_serialization.py +12 -6
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_protocol_version.py +3 -3
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/landing/describe.expected.json +63 -1
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_protocol_classes.py +58 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/uv.lock +1 -1
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/aggregate/__init__.py +3 -0
- vgi_python-0.21.0/vgi/_test_fixtures/aggregate/same_name.py +139 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/http_server.py +14 -4
- vgi_python-0.21.0/vgi/_test_fixtures/table/same_name_cached.py +131 -0
- vgi_python-0.21.0/vgi/_test_fixtures/table_in_out_same_name.py +243 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/worker.py +29 -4
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/catalog/catalog_interface.py +4 -3
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/protocol.py +65 -5
- vgi_python-0.21.0/vgi/protocol_version.txt +1 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/worker.py +16 -4
- vgi_python-0.19.0/vgi/protocol_version.txt +0 -1
- {vgi_python-0.19.0 → vgi_python-0.21.0}/.gitattributes +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/.github/dependabot.yml +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/.github/styles/config/vocabularies/VGI/accept.txt +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/.github/workflows/ci.yml +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/.github/workflows/docs.yml +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/.github/workflows/integration.yml +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/.github/workflows/release.yml +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/.gitignore +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/.python-version +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/.vale.ini +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/CLAUDE.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/DOCS_ACCEPTANCE_CRITERIA.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/DOCS_REVIEW_RUBRIC.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/DOCS_USABILITY_TEST.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/LICENSE +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/README.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/SECURITY.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/ci/README.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/ci/preprocess-require.awk +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/ci/run-integration.sh +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/dist-vgi/.gitignore +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/aggregate-functions.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/api/arguments.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/api/auth.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/api/catalogs.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/api/client.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/api/exceptions.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/api/filters.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/api/functions.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/api/http.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/api/index.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/api/metadata.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/api/observability.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/api/storage.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/api/transactor.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/api/worker.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/argument-serialization.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/assets/apple-touch-icon.png +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/assets/favicon-16x16.png +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/assets/favicon-32x32.png +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/assets/favicon.ico +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/assets/kinds/aggregate.svg +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/assets/kinds/buffering.svg +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/assets/kinds/scalar.svg +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/assets/kinds/table-in-out.svg +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/assets/kinds/table.svg +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/assets/logo.png +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/assets/social-card.png +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/authentication.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/catalog-interface.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/cli.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/column-statistics.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/concepts/index.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/contributing-docs.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/filter-pushdown.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/generator-api.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/how-to/catalogs.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/how-to/function-patterns.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/how-to/http-auth.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/how-to/index.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/how-to/pushdown-and-statistics.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/how-to/state-storage.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/index.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/lifecycle.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/metadata.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/overrides/main.html +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/robots.txt +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/shared-storage.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/stylesheets/extra.css +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/tutorial/index.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/tutorial/scalar.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/tutorial/table.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/docs/vgi-logo.png +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/examples/calc_scalar_worker.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/examples/calc_worker.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/examples/filter_worker.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/examples/greeting_scalar_worker.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/examples/row_count_worker.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/examples/series_streaming_worker.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/examples/sum_worker.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/mkdocs.yml +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/packages/vgi-fixtures/LICENSE +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/packages/vgi-fixtures/README.md +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/packages/vgi-fixtures/docker/Dockerfile +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/packages/vgi-fixtures/docker/docker-entrypoint.sh +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/packages/vgi-fixtures/pyproject.toml +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/scripts/measure_startup.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/scripts/run_all_tests.sh +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/test-data/generate.sh +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/_http_fixtures.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/catalog/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/catalog/test_catalog_interface.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/catalog/test_client_catalog.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/catalog/test_column_statistics.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/catalog/test_declarative.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/catalog/test_example_worker_catalog.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/catalog/test_integration.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/catalog/test_required_filters.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/catalog/test_scan_branches.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/catalog/test_setting.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/catalog/test_storage.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/catalog/test_time_travel.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/catalog/test_writable_table.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/client/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/client/test_broken_pipe.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/client/test_cli.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/client/test_cli_catalog_functions.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/client/test_worker_debug.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/_stub.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/conftest.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_accumulate.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_aggregate.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_attach.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_bearer_auth.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_const_param_enforcement.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_container.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_copy_from.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_copy_to.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_directory_parity.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_function_inventory.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_github.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_http_client.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_http_external_location.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_http_upload_url.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_macro.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_overload.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_protocol_inventory.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_resumable_scan.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_scalar.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_scalar_attach_opaque_data.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_secret.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_settings.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_table.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_table_in_out.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_view.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conformance/test_writable.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/conftest.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/landing/_checker.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/landing/describe.schema.json +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/scalar/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/scalar/test_bernoulli_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/scalar/test_binary_packet_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/scalar/test_client.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/scalar/test_conditional_message_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/scalar/test_hash_seed_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/scalar/test_multiply_by_setting_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/scalar/test_multiply_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/scalar/test_random_bytes_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/scalar/test_return_secret_value_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table/generator/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table/generator/test_constant_columns_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table/generator/test_double_sequence_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table/generator/test_exception_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table/generator/test_filter_echo_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table/generator/test_logging_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table/generator/test_nested_sequence_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table/generator/test_partitioned_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table/generator/test_projected_data_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table/generator/test_sequence_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table/generator/test_settings_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table/generator/test_struct_settings_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table/generator/test_ten_thousand_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table_in_out/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table_in_out/generator/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table_in_out/generator/test_buffer_input_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table_in_out/generator/test_echo_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table_in_out/generator/test_exception_functions.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table_in_out/generator/test_filter_by_setting_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table_in_out/generator/test_repeat_inputs_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table_in_out/generator/test_substream_partial_sum_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table_in_out/generator/test_sum_all_columns_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table_in_out/test_blended_metadata.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/table_in_out/test_client.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_access_log_audit.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_aggregate_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_argument_spec.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_auth.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_bind_exceptions.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_bind_request_at_clause.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_bound_storage_conformance.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_cache_control.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_catalog_auth_binding.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_copy_from_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_copy_to_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_docstrings.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_documentation_examples.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_example_function_arg_types.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_examples_workers.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_exception_handling.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_exceptions.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_filter_pushdown.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_filter_pushdown_extension.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_function_storage.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_function_storage_azure_sql.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_function_storage_cf_do.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_function_storage_cf_do_integration.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_function_storage_conformance.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_generated_cpp_constants.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_generated_cpp_protocol_version.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_generated_cpp_request_builders.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_generated_cpp_schemas.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_generated_cpp_secret.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_generated_go_schemas.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_generated_protocol_version.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_generated_schemas_cross_lang.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_generated_ts_client.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_generated_ts_schemas.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_http_demo_storage.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_http_s3_offload_input.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_http_s3_offload_output.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_landing_conformance.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_metadata.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_mypy_consolidated.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_nest_tensor.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_otel.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_projection_enforcement.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_projection_repro.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_resolved_secrets.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_schema_scoped_functions.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_schema_utils.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_serve.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_setting_secret_annotations.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_table_buffering_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_table_function_dynamic_to_string.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_tcp_transport.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_type_bounds.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_union_argument.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_worker.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_worker_cli.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/test_worker_page.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/transactor/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/tests/transactor/test_transactor.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_duckdb.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_storage_profile.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/accumulate/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/accumulate/worker.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/aggregate/_common.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/aggregate/basic.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/aggregate/dynamic.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/aggregate/generic.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/aggregate/listagg.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/aggregate/percentile.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/aggregate/secret_typed.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/aggregate/streaming.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/aggregate/varargs.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/aggregate/window.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/attach_options.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/bad_enum.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/bad_protocol.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/cancellable.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/catalog.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/companion.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/copy_from.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/copy_to.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/narrow_bind/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/narrow_bind/worker.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/nest_tensor.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/orchard_catalog.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/projection_repro/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/projection_repro/worker.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/scalar/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/scalar/_common.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/scalar/arithmetic.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/scalar/bench_ladder.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/scalar/binary.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/scalar/formatting.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/scalar/geo.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/scalar/null_handling.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/scalar/random_demo.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/scalar/same_name.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/scalar/settings_secrets.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/scalar/type_info.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/schema_reconcile/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/schema_reconcile/worker.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/simple_writable.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/_common.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/batch_index.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/batch_index_broken.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/cache.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/catalog_scans.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/filters.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/late_materialization.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/make_series.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/misc.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/order_modes.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/pairs.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/partition_columns.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/partition_columns_broken.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/profiling_example.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/required_filters.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/sequence.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/settings.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/transaction_storage.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/tt_pushdown.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/typed_probe.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table/versioned.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/table_in_out.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/twin_catalogs.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/versioned.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/versioned_tables.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/writable/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/writable/generic.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/writable/table.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/_test_fixtures/writable/worker.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/aggregate_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/argument_spec.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/arguments.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/attach_header.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/auth.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/cache_control.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/catalog/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/catalog/_descriptor_spec.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/catalog/attach_option.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/catalog/descriptors.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/catalog/duckdb_statistics.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/catalog/secret_type.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/catalog/setting.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/catalog/storage.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/client/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/client/catalog_mixin.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/client/cli.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/client/cli_catalog.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/client/cli_schema.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/client/cli_table.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/client/cli_transaction.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/client/cli_utils.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/client/cli_view.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/client/client.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/codegen/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/codegen/_common.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/codegen/cpp_constants.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/codegen/cpp_protocol_version.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/codegen/cpp_request_builders.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/codegen/cpp_schemas.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/codegen/cpp_secret_protocol_version.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/codegen/cpp_secret_request_builders.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/codegen/cpp_secret_schemas.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/codegen/go_schemas.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/codegen/protocol_version.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/codegen/ts_client.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/codegen/ts_schemas.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/copy_from_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/copy_to_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/exceptions.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/function_storage.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/function_storage_azure_sql.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/function_storage_cf_do.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/http/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/http/demo_storage.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/http/describe_json.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/http/landing.html +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/http/landing_page.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/http/worker_page.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/invocation.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/logging_config.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/meta_worker.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/metadata.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/otel.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/py.typed +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/scalar_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/schema_utils.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/secret_protocol.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/secret_service.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/serve.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/table_buffering_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/table_filter_pushdown.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/table_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/table_in_out_function.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/transactor/__init__.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/transactor/_duckdb_compat.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/transactor/client.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/transactor/protocol.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/vgi/transactor/server.py +0 -0
- {vgi_python-0.19.0 → vgi_python-0.21.0}/wrangler.jsonc +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vgi-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.21.0
|
|
4
4
|
Summary: Vector Gateway Interface - Connect DuckDB to external programs via Apache Arrow
|
|
5
5
|
Project-URL: Homepage, https://query.farm
|
|
6
6
|
Project-URL: Repository, https://github.com/Query-farm/vgi-python
|
|
@@ -1275,16 +1275,22 @@ class TestScanBranchSerialization:
|
|
|
1275
1275
|
assert restored.branches[1].function_name == "iceberg_scan"
|
|
1276
1276
|
assert restored.required_extensions == ["iceberg", "httpfs"]
|
|
1277
1277
|
|
|
1278
|
-
def
|
|
1279
|
-
"""Empty branches list
|
|
1280
|
-
|
|
1281
|
-
|
|
1278
|
+
def test_scan_branches_result_empty_branches_tolerated(self) -> None:
|
|
1279
|
+
"""Empty branches list round-trips cleanly.
|
|
1280
|
+
|
|
1281
|
+
Lenient producers (the Rust/Go/Java SDKs, tolerated by the DuckDB C++
|
|
1282
|
+
client) omit the IPC stream for an empty nested list, so a strict
|
|
1283
|
+
consumer must accept a zero-branch result rather than raising — otherwise
|
|
1284
|
+
the Cedar proxy (the only strict Python consumer in the path) fails
|
|
1285
|
+
closed on a legitimate response.
|
|
1286
|
+
"""
|
|
1282
1287
|
from vgi.catalog import ScanBranchesResult
|
|
1283
1288
|
|
|
1284
1289
|
empty = ScanBranchesResult(branches=[], required_extensions=[])
|
|
1285
1290
|
batch, _ = deserialize_record_batch(empty.serialize())
|
|
1286
|
-
|
|
1287
|
-
|
|
1291
|
+
restored = ScanBranchesResult.deserialize(batch)
|
|
1292
|
+
assert restored.branches == []
|
|
1293
|
+
assert restored.required_extensions == []
|
|
1288
1294
|
|
|
1289
1295
|
|
|
1290
1296
|
class TestSecretTypeSpecSerialization:
|
|
@@ -32,14 +32,14 @@ CLIENT_PROTOCOL_VERSION = VgiProtocol.protocol_version
|
|
|
32
32
|
|
|
33
33
|
def test_client_protocol_version_is_canonical() -> None:
|
|
34
34
|
"""Sanity-check the constants this test reasons about haven't drifted apart."""
|
|
35
|
-
assert CLIENT_PROTOCOL_VERSION == "1.
|
|
35
|
+
assert CLIENT_PROTOCOL_VERSION == "1.2.0"
|
|
36
36
|
# The fixture must be a genuine mismatch in the major/minor that the
|
|
37
37
|
# framework compares; a patch-only difference would (correctly) pass.
|
|
38
38
|
assert BAD_PROTOCOL_VERSION.split(".")[:2] != CLIENT_PROTOCOL_VERSION.split(".")[:2]
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
def test_mismatched_worker_protocol_version_raises() -> None:
|
|
42
|
-
"""A worker enforcing 99.0.0 must reject the 1.
|
|
42
|
+
"""A worker enforcing 99.0.0 must reject the 1.2.0 client at dispatch."""
|
|
43
43
|
with Client("vgi-fixture-bad-protocol-worker") as client, pytest.raises(ClientError) as exc_info:
|
|
44
44
|
list(
|
|
45
45
|
client.table_function(
|
|
@@ -54,5 +54,5 @@ def test_mismatched_worker_protocol_version_raises() -> None:
|
|
|
54
54
|
assert "protocol_version mismatch" in message
|
|
55
55
|
assert CLIENT_PROTOCOL_VERSION in message
|
|
56
56
|
assert BAD_PROTOCOL_VERSION in message
|
|
57
|
-
# Directional hint: the client (1.
|
|
57
|
+
# Directional hint: the client (1.2.0) is older than the worker (99.0.0).
|
|
58
58
|
assert "upgrade the VGI extension/client" in message
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
{
|
|
4
4
|
"attach_options": [],
|
|
5
5
|
"counts": {
|
|
6
|
-
"functions":
|
|
6
|
+
"functions": 217,
|
|
7
7
|
"schemas": 2,
|
|
8
8
|
"tables": 59,
|
|
9
9
|
"views": 3
|
|
@@ -16,6 +16,19 @@
|
|
|
16
16
|
{
|
|
17
17
|
"doc": "Example tables backed by functions",
|
|
18
18
|
"functions": [
|
|
19
|
+
{
|
|
20
|
+
"args": [
|
|
21
|
+
{
|
|
22
|
+
"desc": "Integer value to accumulate",
|
|
23
|
+
"name": "value",
|
|
24
|
+
"type": "int64"
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"doc": "Schema-disambiguation probe; the data-schema aggregate",
|
|
28
|
+
"name": "test_same_name_agg",
|
|
29
|
+
"returns": "string",
|
|
30
|
+
"type": "aggregate"
|
|
31
|
+
},
|
|
19
32
|
{
|
|
20
33
|
"args": [
|
|
21
34
|
{
|
|
@@ -28,6 +41,24 @@
|
|
|
28
41
|
"name": "test_same_name_bind",
|
|
29
42
|
"returns": "string",
|
|
30
43
|
"type": "scalar"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"args": [],
|
|
47
|
+
"doc": "Schema-disambiguation probe; the data-schema cacheable producer",
|
|
48
|
+
"name": "test_same_name_cached",
|
|
49
|
+
"type": "table"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"args": [],
|
|
53
|
+
"doc": "Schema-disambiguation probe; the data-schema table-in-out",
|
|
54
|
+
"name": "test_same_name_transform",
|
|
55
|
+
"type": "table"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"args": [],
|
|
59
|
+
"doc": "Schema-disambiguation probe; the data-schema buffered function",
|
|
60
|
+
"name": "test_same_name_buffered",
|
|
61
|
+
"type": "table_in_out"
|
|
31
62
|
}
|
|
32
63
|
],
|
|
33
64
|
"name": "data",
|
|
@@ -371,6 +402,19 @@
|
|
|
371
402
|
"returns": "null",
|
|
372
403
|
"type": "aggregate"
|
|
373
404
|
},
|
|
405
|
+
{
|
|
406
|
+
"args": [
|
|
407
|
+
{
|
|
408
|
+
"desc": "Integer value to accumulate",
|
|
409
|
+
"name": "value",
|
|
410
|
+
"type": "int64"
|
|
411
|
+
}
|
|
412
|
+
],
|
|
413
|
+
"doc": "Schema-disambiguation probe; the main-schema aggregate",
|
|
414
|
+
"name": "test_same_name_agg",
|
|
415
|
+
"returns": "string",
|
|
416
|
+
"type": "aggregate"
|
|
417
|
+
},
|
|
374
418
|
{
|
|
375
419
|
"args": [
|
|
376
420
|
{
|
|
@@ -2884,6 +2928,18 @@
|
|
|
2884
2928
|
"name": "ten_thousand",
|
|
2885
2929
|
"type": "table"
|
|
2886
2930
|
},
|
|
2931
|
+
{
|
|
2932
|
+
"args": [],
|
|
2933
|
+
"doc": "Schema-disambiguation probe; the main-schema cacheable producer",
|
|
2934
|
+
"name": "test_same_name_cached",
|
|
2935
|
+
"type": "table"
|
|
2936
|
+
},
|
|
2937
|
+
{
|
|
2938
|
+
"args": [],
|
|
2939
|
+
"doc": "Schema-disambiguation probe; the main-schema table-in-out",
|
|
2940
|
+
"name": "test_same_name_transform",
|
|
2941
|
+
"type": "table"
|
|
2942
|
+
},
|
|
2887
2943
|
{
|
|
2888
2944
|
"args": [
|
|
2889
2945
|
{
|
|
@@ -3314,6 +3370,12 @@
|
|
|
3314
3370
|
"doc": "Distributed sum using the buffered (Sink+Combine+Source) model",
|
|
3315
3371
|
"name": "sum_all_columns_simple_distributed",
|
|
3316
3372
|
"type": "table_in_out"
|
|
3373
|
+
},
|
|
3374
|
+
{
|
|
3375
|
+
"args": [],
|
|
3376
|
+
"doc": "Schema-disambiguation probe; the main-schema buffered function",
|
|
3377
|
+
"name": "test_same_name_buffered",
|
|
3378
|
+
"type": "table_in_out"
|
|
3317
3379
|
}
|
|
3318
3380
|
],
|
|
3319
3381
|
"name": "main",
|
|
@@ -1149,3 +1149,61 @@ class TestAnyArrow:
|
|
|
1149
1149
|
assert obj.data.value == {"key": "value"}
|
|
1150
1150
|
assert obj.data.position == "data"
|
|
1151
1151
|
assert obj.data.name == "data"
|
|
1152
|
+
|
|
1153
|
+
|
|
1154
|
+
class TestBindCallWireFormat:
|
|
1155
|
+
"""The embedded ``bind_call`` must serialize as an opaque binary IPC blob.
|
|
1156
|
+
|
|
1157
|
+
Every non-Python VGI implementation (the DuckDB C++ client, the Rust/Go/Java
|
|
1158
|
+
SDKs) encodes ``bind_call`` as ``Bytes`` — an IPC-serialized ``BindRequest``
|
|
1159
|
+
(Rust: ``ipc::read_batch(&dto.bind_call.0)``). If Python serializes it as an
|
|
1160
|
+
inline Arrow *struct* instead, those workers reject the request with
|
|
1161
|
+
"expected Binary array". This regression-anchors the ``bind_call`` field
|
|
1162
|
+
being ``Annotated[BindRequest, ArrowType(pa.binary())]`` on every request
|
|
1163
|
+
that carries one, so the Cedar proxy's re-serialized bind stays wire-
|
|
1164
|
+
compatible with a non-Python backend.
|
|
1165
|
+
"""
|
|
1166
|
+
|
|
1167
|
+
@staticmethod
|
|
1168
|
+
def _bind_call_arrow_type(obj: object) -> str:
|
|
1169
|
+
batch = pa.ipc.open_stream(obj.serialize_to_bytes()).read_next_batch() # type: ignore[attr-defined]
|
|
1170
|
+
return str(dict((f.name, f.type) for f in batch.schema)["bind_call"])
|
|
1171
|
+
|
|
1172
|
+
def _make_bind(self) -> object:
|
|
1173
|
+
"""Build a minimal ``BindRequest`` to embed as ``bind_call``."""
|
|
1174
|
+
from vgi.protocol import BindRequest, FunctionType
|
|
1175
|
+
|
|
1176
|
+
return BindRequest(
|
|
1177
|
+
function_name="f",
|
|
1178
|
+
arguments=Arguments(positional=[], named=None),
|
|
1179
|
+
function_type=FunctionType.TABLE,
|
|
1180
|
+
)
|
|
1181
|
+
|
|
1182
|
+
def test_init_request_bind_call_is_binary(self) -> None:
|
|
1183
|
+
"""``InitRequest.bind_call`` serializes as binary and round-trips."""
|
|
1184
|
+
from vgi.protocol import InitRequest
|
|
1185
|
+
|
|
1186
|
+
ir = InitRequest(bind_call=self._make_bind(), output_schema=pa.schema([pa.field("x", pa.int64())]))
|
|
1187
|
+
assert self._bind_call_arrow_type(ir) == "binary"
|
|
1188
|
+
# round-trips back into a BindRequest
|
|
1189
|
+
restored = InitRequest.deserialize_from_bytes(ir.serialize_to_bytes())
|
|
1190
|
+
assert restored.bind_call.function_name == "f"
|
|
1191
|
+
|
|
1192
|
+
def test_table_function_requests_bind_call_is_binary(self) -> None:
|
|
1193
|
+
"""The ``table_function_*`` requests also serialize ``bind_call`` as binary."""
|
|
1194
|
+
from vgi.protocol import (
|
|
1195
|
+
TableFunctionCardinalityRequest,
|
|
1196
|
+
TableFunctionDynamicToStringRequest,
|
|
1197
|
+
TableFunctionStatisticsRequest,
|
|
1198
|
+
)
|
|
1199
|
+
|
|
1200
|
+
cases = [
|
|
1201
|
+
(TableFunctionCardinalityRequest, {}),
|
|
1202
|
+
(TableFunctionStatisticsRequest, {}),
|
|
1203
|
+
(TableFunctionDynamicToStringRequest, {"global_execution_id": b"exec"}),
|
|
1204
|
+
]
|
|
1205
|
+
for cls, extra in cases:
|
|
1206
|
+
obj = cls(bind_call=self._make_bind(), **extra)
|
|
1207
|
+
assert self._bind_call_arrow_type(obj) == "binary", cls.__name__
|
|
1208
|
+
restored = cls.deserialize_from_bytes(obj.serialize_to_bytes())
|
|
1209
|
+
assert restored.bind_call.function_name == "f", cls.__name__
|
|
@@ -32,6 +32,7 @@ from vgi._test_fixtures.aggregate.dynamic import (
|
|
|
32
32
|
from vgi._test_fixtures.aggregate.generic import GenericSumFunction
|
|
33
33
|
from vgi._test_fixtures.aggregate.listagg import ListAggFunction
|
|
34
34
|
from vgi._test_fixtures.aggregate.percentile import PercentileFunction
|
|
35
|
+
from vgi._test_fixtures.aggregate.same_name import SameNameDataAgg, SameNameMainAgg
|
|
35
36
|
from vgi._test_fixtures.aggregate.secret_typed import SecretTypedSumFunction
|
|
36
37
|
from vgi._test_fixtures.aggregate.streaming import StreamingSumFunction
|
|
37
38
|
from vgi._test_fixtures.aggregate.varargs import SumAllFunction
|
|
@@ -45,6 +46,8 @@ from vgi._test_fixtures.aggregate.window import (
|
|
|
45
46
|
__all__ = [
|
|
46
47
|
"AvgFunction",
|
|
47
48
|
"CountFunction",
|
|
49
|
+
"SameNameDataAgg",
|
|
50
|
+
"SameNameMainAgg",
|
|
48
51
|
"DynamicAggregateFunction",
|
|
49
52
|
"DynamicMLAggregateFunction",
|
|
50
53
|
"GenericSumFunction",
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Copyright 2025, 2026 Query Farm LLC - https://query.farm
|
|
2
|
+
|
|
3
|
+
"""Same-name-in-two-schemas *aggregate* fixtures.
|
|
4
|
+
|
|
5
|
+
The third member of the schema-disambiguation family, after
|
|
6
|
+
:mod:`vgi._test_fixtures.scalar.same_name` (scalar) and
|
|
7
|
+
:mod:`vgi._test_fixtures.table_in_out_same_name` (table-in-out + buffering).
|
|
8
|
+
|
|
9
|
+
Aggregates are the widest surface of the three. Every aggregate RPC —
|
|
10
|
+
``aggregate_update`` / ``_combine`` / ``_finalize`` / ``_destructor``, the four
|
|
11
|
+
window calls, and the three streaming calls — resolves the function through the
|
|
12
|
+
worker's single ``_resolve_aggregate`` entry point, which had no schema to work
|
|
13
|
+
with: none of those request types carried one, not even ``AggregateBindRequest``.
|
|
14
|
+
So an aggregate name declared in two schemas resolved to whichever the by-name
|
|
15
|
+
lookup found first.
|
|
16
|
+
|
|
17
|
+
Both classes register under ``test_same_name_agg``, in the ``main`` and ``data``
|
|
18
|
+
schemas of the ``example`` catalog. Each returns a VARCHAR tagged with its own
|
|
19
|
+
schema *and* the aggregated value, so a mis-routed call reads as the wrong tag
|
|
20
|
+
rather than a plausible answer, and a call that mis-routes only partway (bind to
|
|
21
|
+
one implementation, update/finalize to another) still shows up — the tag is
|
|
22
|
+
stamped at ``finalize`` while the accumulation happens in ``update``.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
from dataclasses import dataclass
|
|
28
|
+
from typing import Annotated
|
|
29
|
+
|
|
30
|
+
import pyarrow as pa
|
|
31
|
+
from vgi_rpc import ArrowSerializableDataclass, ArrowType
|
|
32
|
+
|
|
33
|
+
from vgi.aggregate_function import AggregateFunction
|
|
34
|
+
from vgi.arguments import Param, Returns
|
|
35
|
+
from vgi.metadata import (
|
|
36
|
+
DistinctDependence,
|
|
37
|
+
FunctionExample,
|
|
38
|
+
NullHandling,
|
|
39
|
+
OrderDependence,
|
|
40
|
+
)
|
|
41
|
+
from vgi.table_function import ProcessParams
|
|
42
|
+
|
|
43
|
+
# Deliberately identical in both schemas — the collision is the point.
|
|
44
|
+
FUNCTION_NAME = "test_same_name_agg"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass(kw_only=True)
|
|
48
|
+
class SameNameAggState(ArrowSerializableDataclass):
|
|
49
|
+
"""Running total for one group."""
|
|
50
|
+
|
|
51
|
+
total: Annotated[int, ArrowType(pa.int64())] = 0
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class _SameNameAgg(AggregateFunction[SameNameAggState]):
|
|
55
|
+
"""Shared body; each subclass supplies the schema it is declared in."""
|
|
56
|
+
|
|
57
|
+
#: Schema this implementation is registered into — the tag it stamps.
|
|
58
|
+
OWNING_SCHEMA: str = ""
|
|
59
|
+
|
|
60
|
+
@classmethod
|
|
61
|
+
def initial_state(cls, params: ProcessParams[None]) -> SameNameAggState:
|
|
62
|
+
"""Start each group at zero."""
|
|
63
|
+
return SameNameAggState()
|
|
64
|
+
|
|
65
|
+
@classmethod
|
|
66
|
+
def update(
|
|
67
|
+
cls,
|
|
68
|
+
states: dict[int, SameNameAggState],
|
|
69
|
+
group_ids: pa.Int64Array,
|
|
70
|
+
value: Annotated[pa.Int64Array, Param(doc="Integer value to accumulate")],
|
|
71
|
+
) -> None:
|
|
72
|
+
"""Accumulate each row's value into its group."""
|
|
73
|
+
for gid, v in zip(group_ids.to_pylist(), value.to_pylist(), strict=True):
|
|
74
|
+
if v is None or gid is None:
|
|
75
|
+
continue
|
|
76
|
+
states[gid] = SameNameAggState(total=states[gid].total + v)
|
|
77
|
+
|
|
78
|
+
@classmethod
|
|
79
|
+
def combine(
|
|
80
|
+
cls,
|
|
81
|
+
source: SameNameAggState,
|
|
82
|
+
target: SameNameAggState,
|
|
83
|
+
params: ProcessParams[None],
|
|
84
|
+
) -> SameNameAggState:
|
|
85
|
+
"""Merge two partial states."""
|
|
86
|
+
return SameNameAggState(total=source.total + target.total)
|
|
87
|
+
|
|
88
|
+
@classmethod
|
|
89
|
+
def finalize(
|
|
90
|
+
cls,
|
|
91
|
+
group_ids: pa.Int64Array,
|
|
92
|
+
states: dict[int, SameNameAggState],
|
|
93
|
+
params: ProcessParams[None],
|
|
94
|
+
) -> Annotated[pa.RecordBatch, Returns(pa.string())]:
|
|
95
|
+
"""Tag each group's total with the owning schema."""
|
|
96
|
+
results = [f"{cls.OWNING_SCHEMA}:{states[gid.as_py()].total}" for gid in group_ids]
|
|
97
|
+
return pa.record_batch({"result": pa.array(results, type=pa.string())})
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class SameNameMainAgg(_SameNameAgg):
|
|
101
|
+
"""``test_same_name_agg`` as declared in the ``main`` schema."""
|
|
102
|
+
|
|
103
|
+
OWNING_SCHEMA = "main"
|
|
104
|
+
|
|
105
|
+
class Meta:
|
|
106
|
+
"""Function metadata."""
|
|
107
|
+
|
|
108
|
+
name = FUNCTION_NAME
|
|
109
|
+
description = "Schema-disambiguation probe; the main-schema aggregate"
|
|
110
|
+
null_handling = NullHandling.SPECIAL
|
|
111
|
+
order_dependent = OrderDependence.NOT_ORDER_DEPENDENT
|
|
112
|
+
distinct_dependent = DistinctDependence.NOT_DISTINCT_DEPENDENT
|
|
113
|
+
examples = [
|
|
114
|
+
FunctionExample(
|
|
115
|
+
sql="SELECT example.main.test_same_name_agg(n) FROM range(3) t(n)",
|
|
116
|
+
description="Returns 'main:3'",
|
|
117
|
+
),
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class SameNameDataAgg(_SameNameAgg):
|
|
122
|
+
"""``test_same_name_agg`` as declared in the ``data`` schema."""
|
|
123
|
+
|
|
124
|
+
OWNING_SCHEMA = "data"
|
|
125
|
+
|
|
126
|
+
class Meta:
|
|
127
|
+
"""Function metadata."""
|
|
128
|
+
|
|
129
|
+
name = FUNCTION_NAME
|
|
130
|
+
description = "Schema-disambiguation probe; the data-schema aggregate"
|
|
131
|
+
null_handling = NullHandling.SPECIAL
|
|
132
|
+
order_dependent = OrderDependence.NOT_ORDER_DEPENDENT
|
|
133
|
+
distinct_dependent = DistinctDependence.NOT_DISTINCT_DEPENDENT
|
|
134
|
+
examples = [
|
|
135
|
+
FunctionExample(
|
|
136
|
+
sql="SELECT example.data.test_same_name_agg(n) FROM range(3) t(n)",
|
|
137
|
+
description="Returns 'data:3'",
|
|
138
|
+
),
|
|
139
|
+
]
|
|
@@ -330,13 +330,23 @@ def main() -> None:
|
|
|
330
330
|
|
|
331
331
|
authenticate = _optional_bearer
|
|
332
332
|
|
|
333
|
-
from vgi.worker import _get_vgi_version
|
|
334
|
-
|
|
335
333
|
# Match vgi-fixture-worker (subprocess transport): always serve the
|
|
336
334
|
# base ExampleWorker plus the projection_repro, schema_reconcile,
|
|
337
335
|
# and accumulate fixture catalogs. Add the writable catalog when its
|
|
338
|
-
# extra is installed.
|
|
339
|
-
|
|
336
|
+
# extra is installed. The twin_a/twin_b catalogs (same worker, one
|
|
337
|
+
# function name colliding across two catalogs) back
|
|
338
|
+
# scalar/same_name_catalogs.test — catalog-qualified dispatch.
|
|
339
|
+
from vgi._test_fixtures.twin_catalogs import TwinAWorker, TwinBWorker
|
|
340
|
+
from vgi.worker import _get_vgi_version
|
|
341
|
+
|
|
342
|
+
worker_classes: list[type] = [
|
|
343
|
+
ExampleWorker,
|
|
344
|
+
ProjReproWorker,
|
|
345
|
+
SchemaReconcileWorker,
|
|
346
|
+
AccumulateWorker,
|
|
347
|
+
TwinAWorker,
|
|
348
|
+
TwinBWorker,
|
|
349
|
+
]
|
|
340
350
|
try:
|
|
341
351
|
from vgi._test_fixtures.writable.worker import WritableWorker
|
|
342
352
|
except ImportError:
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Copyright 2025, 2026 Query Farm LLC - https://query.farm
|
|
2
|
+
|
|
3
|
+
"""Cacheable same-name-in-two-schemas producer fixtures.
|
|
4
|
+
|
|
5
|
+
The result-cache member of the schema-disambiguation family (see
|
|
6
|
+
``scalar/same_name.py``, ``table_in_out_same_name.py``, ``aggregate/same_name.py``).
|
|
7
|
+
Those probe *dispatch*; this one probes the *result cache*, a distinct layer.
|
|
8
|
+
|
|
9
|
+
``test_same_name_cached`` is a one-row producer table function that advertises
|
|
10
|
+
``vgi.cache.ttl`` and is registered in BOTH the ``main`` and ``data`` schemas of
|
|
11
|
+
the ``example`` catalog. Each schema's implementation emits a single row tagged
|
|
12
|
+
with its own schema name.
|
|
13
|
+
|
|
14
|
+
The result cache keyed on catalog + auth + function name with no schema
|
|
15
|
+
dimension, so the two implementations produced byte-identical cache keys and one
|
|
16
|
+
schema's memoized rows cross-served the other — the caching-layer twin of the
|
|
17
|
+
``(schema, name)`` dispatch bug. The tag makes a cross-serve visible:
|
|
18
|
+
``example.data.test_same_name_cached()`` would return a ``main`` row. With the
|
|
19
|
+
schema in the key, each schema gets its own entry (so ``vgi_result_cache()``
|
|
20
|
+
holds two rows for the one function name) and returns its own tag. Driven by
|
|
21
|
+
``cache/same_name_schemas.test``.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
from dataclasses import dataclass
|
|
27
|
+
from typing import ClassVar, cast
|
|
28
|
+
|
|
29
|
+
import pyarrow as pa
|
|
30
|
+
from vgi_rpc import ArrowSerializableDataclass
|
|
31
|
+
from vgi_rpc.rpc import OutputCollector
|
|
32
|
+
|
|
33
|
+
from vgi.cache_control import CacheControl
|
|
34
|
+
from vgi.metadata import FunctionExample
|
|
35
|
+
from vgi.protocol import VgiOutputCollector
|
|
36
|
+
from vgi.schema_utils import schema
|
|
37
|
+
from vgi.table_function import (
|
|
38
|
+
ProcessParams,
|
|
39
|
+
TableFunctionGenerator,
|
|
40
|
+
bind_fixed_schema,
|
|
41
|
+
init_single_worker,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
FUNCTION_NAME = "test_same_name_cached"
|
|
45
|
+
|
|
46
|
+
# Long enough that the TTL never lapses mid-test.
|
|
47
|
+
_TTL_SECONDS = 300
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass(slots=True, frozen=True)
|
|
51
|
+
class _CachedArgs:
|
|
52
|
+
"""Arguments for the cacheable same-name producer (none)."""
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass(kw_only=True)
|
|
56
|
+
class _CachedState(ArrowSerializableDataclass):
|
|
57
|
+
"""One-shot emit latch for the single output row."""
|
|
58
|
+
|
|
59
|
+
done: bool = False
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class _SameNameCached(TableFunctionGenerator[_CachedArgs, _CachedState]):
|
|
63
|
+
"""Shared body; each subclass supplies the schema it is declared in."""
|
|
64
|
+
|
|
65
|
+
#: Schema this implementation is declared in — the tag it stamps.
|
|
66
|
+
OWNING_SCHEMA: ClassVar[str] = ""
|
|
67
|
+
|
|
68
|
+
FunctionArguments = _CachedArgs
|
|
69
|
+
FIXED_SCHEMA: ClassVar[pa.Schema] = schema(tag=pa.string())
|
|
70
|
+
|
|
71
|
+
@classmethod
|
|
72
|
+
def initial_state(cls, params: ProcessParams[_CachedArgs]) -> _CachedState:
|
|
73
|
+
"""Fresh latch per (real, cache-missing) invocation."""
|
|
74
|
+
return _CachedState()
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def process(
|
|
78
|
+
cls,
|
|
79
|
+
params: ProcessParams[_CachedArgs],
|
|
80
|
+
state: _CachedState,
|
|
81
|
+
out: OutputCollector,
|
|
82
|
+
) -> None:
|
|
83
|
+
"""Emit the single schema-tagged row once, advertising a cache TTL."""
|
|
84
|
+
if state.done:
|
|
85
|
+
out.finish()
|
|
86
|
+
return
|
|
87
|
+
batch = pa.RecordBatch.from_pydict({"tag": [cls.OWNING_SCHEMA]}, schema=params.output_schema)
|
|
88
|
+
cast(VgiOutputCollector, out).emit(batch, cache_control=CacheControl(ttl=_TTL_SECONDS))
|
|
89
|
+
state.done = True
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@init_single_worker
|
|
93
|
+
@bind_fixed_schema
|
|
94
|
+
class SameNameMainCached(_SameNameCached):
|
|
95
|
+
"""``test_same_name_cached`` as declared in the ``main`` schema."""
|
|
96
|
+
|
|
97
|
+
OWNING_SCHEMA = "main"
|
|
98
|
+
|
|
99
|
+
class Meta:
|
|
100
|
+
"""Function metadata."""
|
|
101
|
+
|
|
102
|
+
name = FUNCTION_NAME
|
|
103
|
+
description = "Schema-disambiguation probe; the main-schema cacheable producer"
|
|
104
|
+
categories = ["generator", "cache", "testing"]
|
|
105
|
+
examples = [
|
|
106
|
+
FunctionExample(
|
|
107
|
+
sql="SELECT * FROM example.main.test_same_name_cached()",
|
|
108
|
+
description="One cacheable row tagged 'main'",
|
|
109
|
+
),
|
|
110
|
+
]
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@init_single_worker
|
|
114
|
+
@bind_fixed_schema
|
|
115
|
+
class SameNameDataCached(_SameNameCached):
|
|
116
|
+
"""``test_same_name_cached`` as declared in the ``data`` schema."""
|
|
117
|
+
|
|
118
|
+
OWNING_SCHEMA = "data"
|
|
119
|
+
|
|
120
|
+
class Meta:
|
|
121
|
+
"""Function metadata."""
|
|
122
|
+
|
|
123
|
+
name = FUNCTION_NAME
|
|
124
|
+
description = "Schema-disambiguation probe; the data-schema cacheable producer"
|
|
125
|
+
categories = ["generator", "cache", "testing"]
|
|
126
|
+
examples = [
|
|
127
|
+
FunctionExample(
|
|
128
|
+
sql="SELECT * FROM example.data.test_same_name_cached()",
|
|
129
|
+
description="One cacheable row tagged 'data'",
|
|
130
|
+
),
|
|
131
|
+
]
|