vgi-python 0.13.0__tar.gz → 0.15.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.13.0 → vgi_python-0.15.0}/PKG-INFO +2 -2
- {vgi_python-0.13.0 → vgi_python-0.15.0}/ci/run-integration.sh +39 -3
- {vgi_python-0.13.0 → vgi_python-0.15.0}/pyproject.toml +2 -2
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/catalog/test_declarative.py +187 -6
- vgi_python-0.15.0/tests/catalog/test_required_filters.py +92 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/catalog/test_serialization.py +4 -4
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_directory_parity.py +9 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/landing/describe.expected.json +302 -7
- vgi_python-0.15.0/tests/test_cache_control.py +222 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/uv.lock +5 -5
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/http_server.py +26 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/__init__.py +40 -0
- vgi_python-0.15.0/vgi/_test_fixtures/table/cache.py +1525 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/required_filters.py +7 -7
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/worker.py +191 -40
- vgi_python-0.15.0/vgi/cache_control.py +150 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/catalog/catalog_interface.py +68 -15
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/catalog/descriptors.py +49 -32
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/protocol.py +54 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/table_function.py +16 -0
- vgi_python-0.13.0/tests/catalog/test_required_field_filter_paths.py +0 -98
- {vgi_python-0.13.0 → vgi_python-0.15.0}/.gitattributes +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/.github/dependabot.yml +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/.github/styles/config/vocabularies/VGI/accept.txt +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/.github/workflows/ci.yml +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/.github/workflows/docs.yml +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/.github/workflows/integration.yml +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/.github/workflows/release.yml +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/.gitignore +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/.python-version +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/.vale.ini +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/CLAUDE.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/DOCS_ACCEPTANCE_CRITERIA.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/DOCS_REVIEW_RUBRIC.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/DOCS_USABILITY_TEST.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/LICENSE +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/README.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/SECURITY.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/ci/README.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/ci/preprocess-require.awk +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/dist-vgi/.gitignore +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/aggregate-functions.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/api/arguments.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/api/auth.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/api/catalogs.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/api/client.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/api/exceptions.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/api/filters.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/api/functions.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/api/http.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/api/index.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/api/metadata.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/api/observability.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/api/storage.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/api/transactor.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/api/worker.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/argument-serialization.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/assets/apple-touch-icon.png +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/assets/favicon-16x16.png +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/assets/favicon-32x32.png +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/assets/favicon.ico +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/assets/kinds/aggregate.svg +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/assets/kinds/buffering.svg +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/assets/kinds/scalar.svg +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/assets/kinds/table-in-out.svg +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/assets/kinds/table.svg +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/assets/logo.png +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/assets/social-card.png +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/authentication.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/catalog-interface.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/cli.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/column-statistics.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/concepts/index.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/contributing-docs.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/filter-pushdown.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/generator-api.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/how-to/catalogs.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/how-to/function-patterns.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/how-to/http-auth.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/how-to/index.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/how-to/pushdown-and-statistics.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/how-to/state-storage.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/index.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/lifecycle.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/metadata.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/overrides/main.html +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/robots.txt +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/shared-storage.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/stylesheets/extra.css +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/tutorial/index.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/tutorial/scalar.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/tutorial/table.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/docs/vgi-logo.png +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/examples/calc_scalar_worker.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/examples/calc_worker.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/examples/filter_worker.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/examples/greeting_scalar_worker.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/examples/row_count_worker.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/examples/series_streaming_worker.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/examples/sum_worker.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/mkdocs.yml +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/packages/vgi-fixtures/LICENSE +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/packages/vgi-fixtures/README.md +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/packages/vgi-fixtures/docker/Dockerfile +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/packages/vgi-fixtures/docker/docker-entrypoint.sh +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/packages/vgi-fixtures/pyproject.toml +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/scripts/measure_startup.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/scripts/run_all_tests.sh +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/test-data/generate.sh +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/_http_fixtures.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/catalog/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/catalog/test_catalog_interface.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/catalog/test_client_catalog.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/catalog/test_column_statistics.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/catalog/test_example_worker_catalog.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/catalog/test_integration.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/catalog/test_scan_branches.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/catalog/test_setting.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/catalog/test_storage.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/catalog/test_time_travel.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/catalog/test_writable_table.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/client/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/client/test_broken_pipe.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/client/test_cli.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/client/test_cli_catalog_functions.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/client/test_worker_debug.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/_stub.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/conftest.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_accumulate.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_aggregate.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_attach.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_bearer_auth.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_const_param_enforcement.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_container.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_copy_from.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_copy_to.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_function_inventory.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_github.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_http_client.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_http_external_location.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_http_upload_url.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_macro.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_overload.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_protocol_inventory.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_protocol_version.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_resumable_scan.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_scalar.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_scalar_attach_opaque_data.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_secret.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_settings.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_table.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_table_in_out.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_view.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conformance/test_writable.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/conftest.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/landing/_checker.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/landing/describe.schema.json +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/scalar/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/scalar/test_bernoulli_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/scalar/test_binary_packet_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/scalar/test_client.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/scalar/test_conditional_message_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/scalar/test_hash_seed_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/scalar/test_multiply_by_setting_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/scalar/test_multiply_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/scalar/test_random_bytes_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/scalar/test_return_secret_value_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table/generator/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table/generator/test_constant_columns_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table/generator/test_double_sequence_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table/generator/test_exception_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table/generator/test_filter_echo_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table/generator/test_logging_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table/generator/test_nested_sequence_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table/generator/test_partitioned_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table/generator/test_projected_data_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table/generator/test_sequence_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table/generator/test_settings_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table/generator/test_struct_settings_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table/generator/test_ten_thousand_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table_in_out/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table_in_out/generator/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table_in_out/generator/test_buffer_input_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table_in_out/generator/test_echo_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table_in_out/generator/test_exception_functions.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table_in_out/generator/test_filter_by_setting_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table_in_out/generator/test_repeat_inputs_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table_in_out/generator/test_sum_all_columns_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/table_in_out/test_client.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_access_log_audit.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_aggregate_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_argument_spec.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_auth.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_bind_exceptions.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_bind_request_at_clause.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_bound_storage_conformance.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_catalog_auth_binding.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_copy_from_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_copy_to_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_docstrings.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_documentation_examples.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_example_function_arg_types.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_examples_workers.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_exception_handling.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_exceptions.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_filter_pushdown.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_filter_pushdown_extension.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_function_storage.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_function_storage_azure_sql.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_function_storage_cf_do.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_function_storage_cf_do_integration.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_function_storage_conformance.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_generated_cpp_constants.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_generated_cpp_protocol_version.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_generated_cpp_request_builders.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_generated_cpp_schemas.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_generated_cpp_secret.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_generated_go_schemas.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_generated_protocol_version.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_generated_schemas_cross_lang.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_generated_ts_client.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_generated_ts_schemas.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_http_demo_storage.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_http_s3_offload_input.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_http_s3_offload_output.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_landing_conformance.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_metadata.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_mypy_consolidated.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_nest_tensor.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_otel.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_projection_enforcement.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_projection_repro.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_protocol_classes.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_resolved_secrets.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_schema_utils.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_serve.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_setting_secret_annotations.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_table_buffering_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_table_function_dynamic_to_string.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_tcp_transport.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_type_bounds.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_union_argument.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_worker.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_worker_cli.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/test_worker_page.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/transactor/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/tests/transactor/test_transactor.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_duckdb.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_storage_profile.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/accumulate/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/accumulate/worker.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/_common.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/basic.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/dynamic.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/generic.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/listagg.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/percentile.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/secret_typed.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/streaming.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/varargs.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/window.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/attach_options.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/bad_enum.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/bad_protocol.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/cancellable.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/catalog.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/companion.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/copy_from.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/copy_to.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/narrow_bind/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/narrow_bind/worker.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/nest_tensor.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/orchard_catalog.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/projection_repro/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/projection_repro/worker.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/_common.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/arithmetic.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/binary.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/formatting.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/geo.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/null_handling.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/random_demo.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/settings_secrets.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/type_info.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/schema_reconcile/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/schema_reconcile/worker.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/simple_writable.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/_common.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/batch_index.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/batch_index_broken.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/catalog_scans.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/filters.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/late_materialization.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/make_series.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/misc.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/order_modes.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/pairs.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/partition_columns.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/partition_columns_broken.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/profiling_example.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/sequence.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/settings.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/transaction_storage.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/tt_pushdown.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/typed_probe.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/versioned.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table_in_out.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/versioned.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/versioned_tables.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/writable/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/writable/generic.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/writable/table.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/_test_fixtures/writable/worker.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/aggregate_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/argument_spec.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/arguments.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/auth.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/catalog/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/catalog/_descriptor_spec.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/catalog/attach_option.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/catalog/duckdb_statistics.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/catalog/secret_type.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/catalog/setting.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/catalog/storage.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/client/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/client/catalog_mixin.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/client/cli.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/client/cli_catalog.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/client/cli_schema.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/client/cli_table.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/client/cli_transaction.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/client/cli_utils.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/client/cli_view.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/client/client.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/codegen/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/codegen/_common.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/codegen/cpp_constants.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/codegen/cpp_protocol_version.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/codegen/cpp_request_builders.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/codegen/cpp_schemas.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/codegen/cpp_secret_protocol_version.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/codegen/cpp_secret_request_builders.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/codegen/cpp_secret_schemas.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/codegen/go_schemas.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/codegen/protocol_version.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/codegen/ts_client.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/codegen/ts_schemas.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/copy_from_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/copy_to_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/exceptions.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/function_storage.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/function_storage_azure_sql.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/function_storage_cf_do.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/http/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/http/demo_storage.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/http/describe_json.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/http/landing.html +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/http/landing_page.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/http/worker_page.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/invocation.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/logging_config.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/meta_worker.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/metadata.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/otel.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/protocol_version.txt +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/py.typed +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/scalar_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/schema_utils.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/secret_protocol.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/secret_service.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/serve.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/table_buffering_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/table_filter_pushdown.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/table_in_out_function.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/transactor/__init__.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/transactor/_duckdb_compat.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/transactor/client.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/transactor/protocol.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/transactor/server.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.0}/vgi/worker.py +0 -0
- {vgi_python-0.13.0 → vgi_python-0.15.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.15.0
|
|
4
4
|
Summary: Vector Gateway Interface - Connect DuckDB to external programs via Apache Arrow
|
|
5
5
|
Project-URL: Homepage, https://query.farm
|
|
6
6
|
Project-URL: Repository, https://github.com/Query-farm/vgi-python
|
|
@@ -162,7 +162,7 @@ Requires-Dist: httpx>=0.24
|
|
|
162
162
|
Requires-Dist: platformdirs
|
|
163
163
|
Requires-Dist: pyarrow
|
|
164
164
|
Requires-Dist: typer>=0.9
|
|
165
|
-
Requires-Dist: vgi-rpc>=0.
|
|
165
|
+
Requires-Dist: vgi-rpc>=0.24.0
|
|
166
166
|
Provides-Extra: azure
|
|
167
167
|
Requires-Dist: azure-identity>=1.16.0; extra == 'azure'
|
|
168
168
|
Requires-Dist: pymssql>=2.3.0; extra == 'azure'
|
|
@@ -73,6 +73,11 @@ if [ "$TRANSPORT" = "http" ]; then
|
|
|
73
73
|
# * buffer_input/sizes.test — input buffering semantics differ over HTTP
|
|
74
74
|
# (same known limitation). (scale.test_slow is a .test_slow file and is
|
|
75
75
|
# never staged below, which only finds *.test.)
|
|
76
|
+
# cache/revalidate.test now runs on http too: HTTP conditional revalidation is
|
|
77
|
+
# implemented (C++ /init-request validators + vgi-rpc >=0.24.0 surfacing them to
|
|
78
|
+
# the producer's first process()). It needs a community vgi extension carrying
|
|
79
|
+
# that C++ change; if the http lane fails on it, the community extension predates
|
|
80
|
+
# the change and needs republishing.
|
|
76
81
|
EXTRA_SKIP=(
|
|
77
82
|
-not -name 'projection_pushdown_repro.test'
|
|
78
83
|
-not -name 'dynamic_filter.test'
|
|
@@ -252,12 +257,43 @@ rm -f "$STAGE/test/_warm.test"
|
|
|
252
257
|
# simple_writable); the http lane's writes self-skip.
|
|
253
258
|
echo "Running suite ($SUITE_GLOB, transport=$TRANSPORT) ..."
|
|
254
259
|
suite_rc=0
|
|
260
|
+
|
|
261
|
+
# run_unittest — invoke haybarn-unittest, streaming its output, and additionally
|
|
262
|
+
# fail on a fatal-signal report that the process's own exit code cannot express.
|
|
263
|
+
#
|
|
264
|
+
# Catch2 arms handlers for SIGTERM/SIGINT/SIGSEGV/... for the duration of a test
|
|
265
|
+
# case. Those handlers are inherited by any process the extension fork()s, and
|
|
266
|
+
# run in the child if a signal lands before it execs. The child then prints a
|
|
267
|
+
# full "FAILED: ... due to a fatal error condition: SIGTERM" block plus a run
|
|
268
|
+
# summary — the *parent's* accumulated counters, since it's an address-space
|
|
269
|
+
# copy — and dies. The parent never sees it, records no failure, and exits 0.
|
|
270
|
+
# The only trace is on stdout, so that is what we scan. Seen on the shm lane in
|
|
271
|
+
# https://github.com/Query-farm/vgi-python/actions/runs/29051359074.
|
|
272
|
+
run_unittest() {
|
|
273
|
+
local log rc=0
|
|
274
|
+
log="$(mktemp)"
|
|
275
|
+
# `set +e` rather than `|| true`: the latter runs before PIPESTATUS is read and
|
|
276
|
+
# overwrites it with true's 0, silently swallowing every real test failure.
|
|
277
|
+
set +e
|
|
278
|
+
"$HAYBARN_UNITTEST" "$@" 2>&1 | tee "$log"
|
|
279
|
+
rc="${PIPESTATUS[0]}"
|
|
280
|
+
set -e
|
|
281
|
+
if grep -q 'due to a fatal error condition' "$log"; then
|
|
282
|
+
echo "::error::a forked child ran the test harness's signal handler (see the" \
|
|
283
|
+
"'fatal error condition' block above). The parent exited $rc and would" \
|
|
284
|
+
"otherwise have passed. This is invisible to the exit code by construction."
|
|
285
|
+
rc=1
|
|
286
|
+
fi
|
|
287
|
+
rm -f "$log"
|
|
288
|
+
return "$rc"
|
|
289
|
+
}
|
|
290
|
+
|
|
255
291
|
if [ "$TRANSPORT" = "launch" ]; then
|
|
256
|
-
|
|
292
|
+
run_unittest "$SUITE_GLOB" || suite_rc=$?
|
|
257
293
|
else
|
|
258
|
-
|
|
294
|
+
run_unittest "$SUITE_GLOB" "~test/sql/integration/simple_writable/*" || suite_rc=$?
|
|
259
295
|
echo "Running simple_writable (isolated process) ..."
|
|
260
|
-
|
|
296
|
+
run_unittest "test/sql/integration/simple_writable/*" || suite_rc=$?
|
|
261
297
|
fi
|
|
262
298
|
|
|
263
299
|
exit "$suite_rc"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "vgi-python"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.15.0"
|
|
4
4
|
description = "Vector Gateway Interface - Connect DuckDB to external programs via Apache Arrow"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
keywords = [
|
|
@@ -40,7 +40,7 @@ dependencies = [
|
|
|
40
40
|
"pyarrow",
|
|
41
41
|
"typer>=0.9",
|
|
42
42
|
"platformdirs",
|
|
43
|
-
"vgi-rpc>=0.
|
|
43
|
+
"vgi-rpc>=0.24.0",
|
|
44
44
|
"httpx>=0.24",
|
|
45
45
|
]
|
|
46
46
|
|
|
@@ -14,13 +14,13 @@ Tests cover:
|
|
|
14
14
|
from __future__ import annotations
|
|
15
15
|
|
|
16
16
|
from dataclasses import dataclass
|
|
17
|
-
from typing import ClassVar
|
|
17
|
+
from typing import Annotated, ClassVar
|
|
18
18
|
|
|
19
19
|
import pyarrow as pa
|
|
20
20
|
import pytest
|
|
21
21
|
from vgi_rpc.rpc import OutputCollector
|
|
22
22
|
|
|
23
|
-
from vgi import Worker
|
|
23
|
+
from vgi import Arg, Arguments, Worker
|
|
24
24
|
from vgi.catalog import (
|
|
25
25
|
AttachOpaqueData,
|
|
26
26
|
Catalog,
|
|
@@ -50,6 +50,7 @@ from vgi.table_function import (
|
|
|
50
50
|
bind_fixed_schema,
|
|
51
51
|
init_single_worker,
|
|
52
52
|
)
|
|
53
|
+
from vgi.table_in_out_function import TableInOutGenerator
|
|
53
54
|
|
|
54
55
|
# =============================================================================
|
|
55
56
|
# Test Fixtures: Example Functions for Function-Backed Tables
|
|
@@ -61,6 +62,45 @@ class EmptyArgs:
|
|
|
61
62
|
"""No arguments."""
|
|
62
63
|
|
|
63
64
|
|
|
65
|
+
@dataclass(frozen=True)
|
|
66
|
+
class CountedRowsArgs:
|
|
67
|
+
"""A required positional argument plus an optional named one."""
|
|
68
|
+
|
|
69
|
+
count: Annotated[int, Arg(0, doc="Number of rows to generate", ge=0)]
|
|
70
|
+
label: Annotated[str, Arg("label", default="rows", doc="Label for the rows")]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@init_single_worker
|
|
74
|
+
@bind_fixed_schema
|
|
75
|
+
class CountedRowsFunction(TableFunctionGenerator[CountedRowsArgs]):
|
|
76
|
+
"""Table function with a required positional arg, for arg-propagation tests."""
|
|
77
|
+
|
|
78
|
+
class Meta: # noqa: D106
|
|
79
|
+
name = "counted_rows"
|
|
80
|
+
description = "Generate N rows"
|
|
81
|
+
|
|
82
|
+
FIXED_SCHEMA: ClassVar[pa.Schema] = schema({"n": pa.int64()})
|
|
83
|
+
|
|
84
|
+
@classmethod
|
|
85
|
+
def process( # noqa: D102
|
|
86
|
+
cls, params: ProcessParams[CountedRowsArgs], state: None, out: OutputCollector
|
|
87
|
+
) -> None:
|
|
88
|
+
out.emit(
|
|
89
|
+
pa.RecordBatch.from_pydict(
|
|
90
|
+
{"n": list(range(params.args.count))},
|
|
91
|
+
schema=params.output_schema,
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
out.finish()
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class CountedRowsInsert(TableInOutGenerator[None, None]):
|
|
98
|
+
"""Stub insert function, for the write-path arg-propagation test."""
|
|
99
|
+
|
|
100
|
+
class Meta: # noqa: D106
|
|
101
|
+
name = "counted_rows_insert"
|
|
102
|
+
|
|
103
|
+
|
|
64
104
|
@init_single_worker
|
|
65
105
|
@bind_fixed_schema
|
|
66
106
|
class UsersFunction(TableFunctionGenerator[EmptyArgs]):
|
|
@@ -262,6 +302,87 @@ class TestTableWithFunction:
|
|
|
262
302
|
assert info.update_function is None
|
|
263
303
|
assert info.delete_function is None
|
|
264
304
|
|
|
305
|
+
def test_inlined_scan_function_carries_declared_positional_arguments(self) -> None:
|
|
306
|
+
"""``Table.arguments`` must reach the scan-time bind, not just ``bind()``.
|
|
307
|
+
|
|
308
|
+
Regression: the inlined ``ScanFunctionResult`` used to hardcode empty
|
|
309
|
+
arguments, so a backing function with a required positional ``Arg(0)``
|
|
310
|
+
saw zero positional args at scan and failed with
|
|
311
|
+
``IndexError: Argument 0: index out of range``.
|
|
312
|
+
"""
|
|
313
|
+
from vgi_rpc.utils import deserialize_record_batch
|
|
314
|
+
|
|
315
|
+
table = Table(
|
|
316
|
+
name="counted",
|
|
317
|
+
function=CountedRowsFunction,
|
|
318
|
+
arguments=Arguments(positional=(pa.scalar(7),)),
|
|
319
|
+
)
|
|
320
|
+
info = table.to_table_info("main")
|
|
321
|
+
assert info.scan_function is not None
|
|
322
|
+
batch, _ = deserialize_record_batch(info.scan_function)
|
|
323
|
+
sfr = ScanFunctionResult.deserialize(batch)
|
|
324
|
+
assert sfr.function_name == "counted_rows"
|
|
325
|
+
assert [s.as_py() for s in sfr.positional_arguments] == [7]
|
|
326
|
+
assert sfr.named_arguments == {}
|
|
327
|
+
|
|
328
|
+
def test_inlined_scan_function_carries_declared_named_arguments(self) -> None:
|
|
329
|
+
"""Named args declared on the Table also reach the scan-time bind."""
|
|
330
|
+
from vgi_rpc.utils import deserialize_record_batch
|
|
331
|
+
|
|
332
|
+
table = Table(
|
|
333
|
+
name="counted",
|
|
334
|
+
function=CountedRowsFunction,
|
|
335
|
+
arguments=Arguments(
|
|
336
|
+
positional=(pa.scalar(3),),
|
|
337
|
+
named={"label": pa.scalar("widgets")},
|
|
338
|
+
),
|
|
339
|
+
)
|
|
340
|
+
info = table.to_table_info("main")
|
|
341
|
+
assert info.scan_function is not None
|
|
342
|
+
batch, _ = deserialize_record_batch(info.scan_function)
|
|
343
|
+
sfr = ScanFunctionResult.deserialize(batch)
|
|
344
|
+
assert [s.as_py() for s in sfr.positional_arguments] == [3]
|
|
345
|
+
assert {k: v.as_py() for k, v in sfr.named_arguments.items()} == {"label": "widgets"}
|
|
346
|
+
|
|
347
|
+
def test_inlined_write_functions_ignore_table_arguments(self) -> None:
|
|
348
|
+
"""Only the *scan* function is parameterized by ``Table.arguments``.
|
|
349
|
+
|
|
350
|
+
Insert/update/delete functions receive their rows via the streaming table
|
|
351
|
+
input, so their inlined results stay argument-free.
|
|
352
|
+
"""
|
|
353
|
+
from vgi_rpc.utils import deserialize_record_batch
|
|
354
|
+
|
|
355
|
+
table = Table(
|
|
356
|
+
name="counted",
|
|
357
|
+
function=CountedRowsFunction,
|
|
358
|
+
arguments=Arguments(positional=(pa.scalar(7),)),
|
|
359
|
+
insert_function=CountedRowsInsert,
|
|
360
|
+
)
|
|
361
|
+
info = table.to_table_info("main")
|
|
362
|
+
assert info.insert_function is not None
|
|
363
|
+
batch, _ = deserialize_record_batch(info.insert_function)
|
|
364
|
+
sfr = ScanFunctionResult.deserialize(batch)
|
|
365
|
+
assert sfr.positional_arguments == []
|
|
366
|
+
assert sfr.named_arguments == {}
|
|
367
|
+
|
|
368
|
+
def test_none_positional_slot_is_rejected(self) -> None:
|
|
369
|
+
"""A ``None`` positional slot would shift later args — reject it loudly.
|
|
370
|
+
|
|
371
|
+
Exercised on the ``scan_arguments_from`` helper directly: a Table carrying
|
|
372
|
+
such a slot already fails earlier, in bind()-based schema derivation. This
|
|
373
|
+
guards the serializer against ever silently dropping the slot instead.
|
|
374
|
+
"""
|
|
375
|
+
from vgi.catalog.catalog_interface import scan_arguments_from
|
|
376
|
+
|
|
377
|
+
with pytest.raises(ValueError, match="positional slot 0 is None"):
|
|
378
|
+
scan_arguments_from(Arguments(positional=(None, pa.scalar(7))))
|
|
379
|
+
|
|
380
|
+
def test_scan_arguments_from_none_is_empty(self) -> None:
|
|
381
|
+
"""A table declaring no arguments serializes empty args (unchanged behavior)."""
|
|
382
|
+
from vgi.catalog.catalog_interface import scan_arguments_from
|
|
383
|
+
|
|
384
|
+
assert scan_arguments_from(None) == ([], {})
|
|
385
|
+
|
|
265
386
|
def test_table_propagates_cardinality_to_table_info(self) -> None:
|
|
266
387
|
"""``Table.cardinality_estimate`` / ``cardinality_max`` flow into TableInfo.
|
|
267
388
|
|
|
@@ -1121,8 +1242,6 @@ class TestSchemaDescriptor:
|
|
|
1121
1242
|
client hits a cold miss. Reporting an explicit ``0`` for empty
|
|
1122
1243
|
categories lets the client skip the bulk RPC entirely.
|
|
1123
1244
|
"""
|
|
1124
|
-
from typing import Annotated
|
|
1125
|
-
|
|
1126
1245
|
from vgi.arguments import Param, Returns
|
|
1127
1246
|
from vgi.scalar_function import ScalarFunction
|
|
1128
1247
|
|
|
@@ -1174,8 +1293,6 @@ class TestLegacyFunctionsListSchemaInfo:
|
|
|
1174
1293
|
"""
|
|
1175
1294
|
|
|
1176
1295
|
def _interface(self) -> ReadOnlyCatalogInterface:
|
|
1177
|
-
from typing import Annotated
|
|
1178
|
-
|
|
1179
1296
|
from vgi.arguments import Param, Returns
|
|
1180
1297
|
from vgi.scalar_function import ScalarFunction
|
|
1181
1298
|
|
|
@@ -1694,6 +1811,70 @@ class TestTableScanFunctionGet:
|
|
|
1694
1811
|
)
|
|
1695
1812
|
assert isinstance(result, ScanFunctionResult)
|
|
1696
1813
|
assert result.function_name == "users"
|
|
1814
|
+
# No declared Table.arguments => empty args, unchanged behavior.
|
|
1815
|
+
assert result.positional_arguments == []
|
|
1816
|
+
assert result.named_arguments == {}
|
|
1817
|
+
|
|
1818
|
+
def test_auto_scan_forwards_declared_arguments(self) -> None:
|
|
1819
|
+
"""The RPC auto-impl forwards ``Table.arguments`` to the scan bind.
|
|
1820
|
+
|
|
1821
|
+
Companion to the inlined-path regression: workers that don't inline
|
|
1822
|
+
``TableInfo.scan_function`` reach the scan through this RPC instead.
|
|
1823
|
+
"""
|
|
1824
|
+
counted = Table(
|
|
1825
|
+
name="counted",
|
|
1826
|
+
function=CountedRowsFunction,
|
|
1827
|
+
arguments=Arguments(
|
|
1828
|
+
positional=(pa.scalar(7),),
|
|
1829
|
+
named={"label": pa.scalar("widgets")},
|
|
1830
|
+
),
|
|
1831
|
+
)
|
|
1832
|
+
|
|
1833
|
+
class TestCatalog(ReadOnlyCatalogInterface):
|
|
1834
|
+
catalog = Catalog(
|
|
1835
|
+
name="test",
|
|
1836
|
+
schemas=[Schema(name="main", tables=[counted])],
|
|
1837
|
+
)
|
|
1838
|
+
|
|
1839
|
+
result = TestCatalog().table_scan_function_get(
|
|
1840
|
+
attach_opaque_data=AttachOpaqueData(b"test"),
|
|
1841
|
+
transaction_opaque_data=None,
|
|
1842
|
+
schema_name="main",
|
|
1843
|
+
name="counted",
|
|
1844
|
+
at_unit=None,
|
|
1845
|
+
at_value=None,
|
|
1846
|
+
)
|
|
1847
|
+
assert result.function_name == "counted_rows"
|
|
1848
|
+
assert [s.as_py() for s in result.positional_arguments] == [7]
|
|
1849
|
+
assert {k: v.as_py() for k, v in result.named_arguments.items()} == {"label": "widgets"}
|
|
1850
|
+
|
|
1851
|
+
def test_scan_branches_default_inherits_declared_arguments(self) -> None:
|
|
1852
|
+
"""The default ``table_scan_branches_get`` delegates to the legacy method.
|
|
1853
|
+
|
|
1854
|
+
So the one-branch synthesis must carry the declared arguments too.
|
|
1855
|
+
"""
|
|
1856
|
+
counted = Table(
|
|
1857
|
+
name="counted",
|
|
1858
|
+
function=CountedRowsFunction,
|
|
1859
|
+
arguments=Arguments(positional=(pa.scalar(7),)),
|
|
1860
|
+
)
|
|
1861
|
+
|
|
1862
|
+
class TestCatalog(ReadOnlyCatalogInterface):
|
|
1863
|
+
catalog = Catalog(
|
|
1864
|
+
name="test",
|
|
1865
|
+
schemas=[Schema(name="main", tables=[counted])],
|
|
1866
|
+
)
|
|
1867
|
+
|
|
1868
|
+
result = TestCatalog().table_scan_branches_get(
|
|
1869
|
+
attach_opaque_data=AttachOpaqueData(b"test"),
|
|
1870
|
+
transaction_opaque_data=None,
|
|
1871
|
+
schema_name="main",
|
|
1872
|
+
name="counted",
|
|
1873
|
+
at_unit=None,
|
|
1874
|
+
at_value=None,
|
|
1875
|
+
)
|
|
1876
|
+
assert len(result.branches) == 1
|
|
1877
|
+
assert [s.as_py() for s in result.branches[0].positional_arguments] == [7]
|
|
1697
1878
|
|
|
1698
1879
|
def test_explicit_columns_table_raises(self) -> None:
|
|
1699
1880
|
"""Tables with explicit columns raise NotImplementedError."""
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""Unit tests for the ``Table.required_filters`` field.
|
|
2
|
+
|
|
3
|
+
The field is purely declarative on the Python side — enforcement runs in the C++
|
|
4
|
+
optimizer extension. It is conjunctive normal form: an AND (outer tuple) of
|
|
5
|
+
OR-groups (inner tuples) of dotted-path column references. These tests cover:
|
|
6
|
+
|
|
7
|
+
1. Default-empty behaviour (no field set → ``TableInfo`` ships an empty list).
|
|
8
|
+
2. Populated round-trip (singleton groups + a multi-path OR-group preserved).
|
|
9
|
+
3. Validation: each path's leading dotted segment must be a real column.
|
|
10
|
+
4. Empty-string paths and empty OR-groups are rejected loudly.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import pyarrow as pa
|
|
16
|
+
import pytest
|
|
17
|
+
|
|
18
|
+
from vgi.catalog.descriptors import Table
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TestRequiredFiltersField:
|
|
22
|
+
"""Behaviour of the declarative required_filters field."""
|
|
23
|
+
|
|
24
|
+
def _bbox_columns(self) -> pa.Schema:
|
|
25
|
+
"""Return a small schema with a ``bbox`` STRUCT plus flat id/ticker."""
|
|
26
|
+
return pa.schema(
|
|
27
|
+
[
|
|
28
|
+
("id", pa.int64()),
|
|
29
|
+
("ticker", pa.string()),
|
|
30
|
+
(
|
|
31
|
+
"bbox",
|
|
32
|
+
pa.struct(
|
|
33
|
+
[
|
|
34
|
+
("xmin", pa.float64()),
|
|
35
|
+
("ymin", pa.float64()),
|
|
36
|
+
("xmax", pa.float64()),
|
|
37
|
+
("ymax", pa.float64()),
|
|
38
|
+
]
|
|
39
|
+
),
|
|
40
|
+
),
|
|
41
|
+
]
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
def test_default_is_empty_tuple(self) -> None:
|
|
45
|
+
"""Default is an empty tuple; TableInfo wire field is an empty list."""
|
|
46
|
+
t = Table(name="t", columns=self._bbox_columns())
|
|
47
|
+
assert t.required_filters == ()
|
|
48
|
+
info = t.to_table_info("main")
|
|
49
|
+
assert info.required_filters == []
|
|
50
|
+
|
|
51
|
+
def test_singleton_groups_round_trip(self) -> None:
|
|
52
|
+
"""Singleton groups (the AND-only case) survive as a list of lists."""
|
|
53
|
+
groups = (("bbox.xmin",), ("bbox.xmax",), ("bbox.ymin",), ("bbox.ymax",))
|
|
54
|
+
t = Table(name="place", columns=self._bbox_columns(), required_filters=groups)
|
|
55
|
+
assert t.required_filters == groups
|
|
56
|
+
info = t.to_table_info("main")
|
|
57
|
+
assert info.required_filters == [list(g) for g in groups]
|
|
58
|
+
|
|
59
|
+
def test_or_group_round_trip(self) -> None:
|
|
60
|
+
"""A multi-path OR-group survives alongside a singleton mandatory group."""
|
|
61
|
+
groups = (("id",), ("id", "ticker"))
|
|
62
|
+
t = Table(name="t", columns=self._bbox_columns(), required_filters=groups)
|
|
63
|
+
info = t.to_table_info("main")
|
|
64
|
+
assert info.required_filters == [["id"], ["id", "ticker"]]
|
|
65
|
+
|
|
66
|
+
def test_top_level_path(self) -> None:
|
|
67
|
+
"""A top-level column name (no dots) is a valid path."""
|
|
68
|
+
t = Table(name="t", columns=self._bbox_columns(), required_filters=(("id",),))
|
|
69
|
+
assert t.to_table_info("main").required_filters == [["id"]]
|
|
70
|
+
|
|
71
|
+
def test_nested_path_is_not_unpacked_for_validation(self) -> None:
|
|
72
|
+
"""Only the leading dotted segment is validated; deeper segments pass through."""
|
|
73
|
+
# Subfield validity isn't checked here (descriptor doesn't unpack struct
|
|
74
|
+
# schemas) — only the leading segment matters. Typos like ``bbox.nope``
|
|
75
|
+
# go through and DuckDB catches them at scan time.
|
|
76
|
+
t = Table(name="t", columns=self._bbox_columns(), required_filters=(("bbox.nope",),))
|
|
77
|
+
assert t.required_filters == (("bbox.nope",),)
|
|
78
|
+
|
|
79
|
+
def test_unknown_leading_segment_raises(self) -> None:
|
|
80
|
+
"""A path whose leading segment is not a real column is rejected."""
|
|
81
|
+
with pytest.raises(ValueError, match=r"unknown column 'nope'"):
|
|
82
|
+
Table(name="t", columns=self._bbox_columns(), required_filters=(("nope.xmin",),))
|
|
83
|
+
|
|
84
|
+
def test_empty_string_path_raises(self) -> None:
|
|
85
|
+
"""An empty string path is rejected loudly rather than silently accepted."""
|
|
86
|
+
with pytest.raises(ValueError, match="must not contain empty strings"):
|
|
87
|
+
Table(name="t", columns=self._bbox_columns(), required_filters=(("",),))
|
|
88
|
+
|
|
89
|
+
def test_empty_group_raises(self) -> None:
|
|
90
|
+
"""An empty OR-group is rejected loudly."""
|
|
91
|
+
with pytest.raises(ValueError, match="must not contain empty groups"):
|
|
92
|
+
Table(name="t", columns=self._bbox_columns(), required_filters=((),))
|
|
@@ -1149,10 +1149,10 @@ class TestArrowSchemaCorrectness:
|
|
|
1149
1149
|
assert schema.field("cardinality_estimate").type == pa.int64()
|
|
1150
1150
|
assert schema.field("column_statistics").type == pa.binary()
|
|
1151
1151
|
assert schema.field("bind_result").type == pa.binary()
|
|
1152
|
-
assert schema.field("
|
|
1153
|
-
#
|
|
1154
|
-
#
|
|
1155
|
-
assert schema.field(len(schema) - 1).name == "
|
|
1152
|
+
assert schema.field("required_filters").type == pa.list_(pa.list_(pa.string()))
|
|
1153
|
+
# required_filters is the LAST field (positional schema compatibility:
|
|
1154
|
+
# old C++ extensions ignore-by-position trailing fields).
|
|
1155
|
+
assert schema.field(len(schema) - 1).name == "required_filters"
|
|
1156
1156
|
|
|
1157
1157
|
def test_view_info_schema(self) -> None:
|
|
1158
1158
|
"""Verify ViewInfo Arrow schema."""
|
|
@@ -33,6 +33,15 @@ _EXEMPTIONS: dict[str, str] = {
|
|
|
33
33
|
"lifecycle/schema/table surfaces are mirrored by test_attach.py, "
|
|
34
34
|
"test_table.py, test_view.py, and test_macro.py."
|
|
35
35
|
),
|
|
36
|
+
"cache": (
|
|
37
|
+
"The table-function result cache lives entirely in the C++ extension "
|
|
38
|
+
"(key/eligibility, in-memory + content-addressed disk tiers, serve/"
|
|
39
|
+
"capture, conditional revalidation). The Python worker's only role is "
|
|
40
|
+
"advertising vgi.cache.* metadata + answering 304 not_modified, which is "
|
|
41
|
+
"unit-tested by tests/test_cache_control.py (rendering, the emit merge "
|
|
42
|
+
"path, ProcessParams.if_none_match threading, and the revalidatable "
|
|
43
|
+
"fixture's 304 behavior)."
|
|
44
|
+
),
|
|
36
45
|
"filter_pushdown": (
|
|
37
46
|
"Per-type filter-pushdown coverage is mirrored by tests/test_filter_pushdown.py "
|
|
38
47
|
"and tests/test_filter_pushdown_extension.py, which drive the same predicate "
|