vgi-python 0.20.0__tar.gz → 0.22.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.20.0 → vgi_python-0.22.0}/PKG-INFO +2 -2
- {vgi_python-0.20.0 → vgi_python-0.22.0}/pyproject.toml +8 -2
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/catalog/test_serialization.py +12 -6
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_protocol_classes.py +58 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/uv.lock +26 -26
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/http_server.py +14 -4
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/catalog/catalog_interface.py +4 -3
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/protocol.py +4 -4
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/serve.py +80 -6
- {vgi_python-0.20.0 → vgi_python-0.22.0}/.gitattributes +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/.github/dependabot.yml +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/.github/styles/config/vocabularies/VGI/accept.txt +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/.github/workflows/ci.yml +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/.github/workflows/docs.yml +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/.github/workflows/integration.yml +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/.github/workflows/release.yml +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/.gitignore +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/.python-version +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/.vale.ini +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/CLAUDE.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/DOCS_ACCEPTANCE_CRITERIA.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/DOCS_REVIEW_RUBRIC.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/DOCS_USABILITY_TEST.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/LICENSE +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/README.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/SECURITY.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/ci/README.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/ci/preprocess-require.awk +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/ci/run-integration.sh +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/dist-vgi/.gitignore +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/aggregate-functions.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/api/arguments.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/api/auth.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/api/catalogs.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/api/client.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/api/exceptions.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/api/filters.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/api/functions.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/api/http.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/api/index.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/api/metadata.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/api/observability.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/api/storage.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/api/transactor.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/api/worker.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/argument-serialization.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/assets/apple-touch-icon.png +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/assets/favicon-16x16.png +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/assets/favicon-32x32.png +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/assets/favicon.ico +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/assets/kinds/aggregate.svg +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/assets/kinds/buffering.svg +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/assets/kinds/scalar.svg +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/assets/kinds/table-in-out.svg +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/assets/kinds/table.svg +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/assets/logo.png +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/assets/social-card.png +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/authentication.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/catalog-interface.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/cli.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/column-statistics.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/concepts/index.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/contributing-docs.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/filter-pushdown.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/generator-api.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/how-to/catalogs.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/how-to/function-patterns.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/how-to/http-auth.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/how-to/index.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/how-to/pushdown-and-statistics.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/how-to/state-storage.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/index.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/lifecycle.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/metadata.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/overrides/main.html +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/robots.txt +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/shared-storage.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/stylesheets/extra.css +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/tutorial/index.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/tutorial/scalar.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/tutorial/table.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/docs/vgi-logo.png +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/examples/calc_scalar_worker.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/examples/calc_worker.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/examples/filter_worker.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/examples/greeting_scalar_worker.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/examples/row_count_worker.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/examples/series_streaming_worker.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/examples/sum_worker.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/mkdocs.yml +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/packages/vgi-fixtures/LICENSE +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/packages/vgi-fixtures/README.md +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/packages/vgi-fixtures/docker/Dockerfile +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/packages/vgi-fixtures/docker/docker-entrypoint.sh +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/packages/vgi-fixtures/pyproject.toml +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/scripts/measure_startup.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/scripts/run_all_tests.sh +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/test-data/generate.sh +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/_http_fixtures.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/catalog/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/catalog/test_catalog_interface.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/catalog/test_client_catalog.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/catalog/test_column_statistics.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/catalog/test_declarative.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/catalog/test_example_worker_catalog.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/catalog/test_integration.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/catalog/test_required_filters.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/catalog/test_scan_branches.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/catalog/test_setting.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/catalog/test_storage.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/catalog/test_time_travel.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/catalog/test_writable_table.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/client/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/client/test_broken_pipe.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/client/test_cli.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/client/test_cli_catalog_functions.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/client/test_worker_debug.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/_stub.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/conftest.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_accumulate.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_aggregate.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_attach.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_bearer_auth.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_const_param_enforcement.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_container.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_copy_from.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_copy_to.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_directory_parity.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_function_inventory.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_github.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_http_client.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_http_external_location.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_http_upload_url.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_macro.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_overload.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_protocol_inventory.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_protocol_version.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_resumable_scan.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_scalar.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_scalar_attach_opaque_data.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_secret.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_settings.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_table.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_table_in_out.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_view.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conformance/test_writable.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/conftest.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/landing/_checker.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/landing/describe.expected.json +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/landing/describe.schema.json +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/scalar/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/scalar/test_bernoulli_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/scalar/test_binary_packet_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/scalar/test_client.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/scalar/test_conditional_message_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/scalar/test_hash_seed_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/scalar/test_multiply_by_setting_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/scalar/test_multiply_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/scalar/test_random_bytes_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/scalar/test_return_secret_value_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table/generator/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table/generator/test_constant_columns_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table/generator/test_double_sequence_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table/generator/test_exception_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table/generator/test_filter_echo_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table/generator/test_logging_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table/generator/test_nested_sequence_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table/generator/test_partitioned_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table/generator/test_projected_data_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table/generator/test_sequence_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table/generator/test_settings_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table/generator/test_struct_settings_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table/generator/test_ten_thousand_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table_in_out/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table_in_out/generator/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table_in_out/generator/test_buffer_input_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table_in_out/generator/test_echo_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table_in_out/generator/test_exception_functions.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table_in_out/generator/test_filter_by_setting_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table_in_out/generator/test_repeat_inputs_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table_in_out/generator/test_substream_partial_sum_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table_in_out/generator/test_sum_all_columns_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table_in_out/test_blended_metadata.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/table_in_out/test_client.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_access_log_audit.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_aggregate_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_argument_spec.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_auth.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_bind_exceptions.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_bind_request_at_clause.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_bound_storage_conformance.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_cache_control.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_catalog_auth_binding.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_copy_from_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_copy_to_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_docstrings.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_documentation_examples.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_example_function_arg_types.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_examples_workers.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_exception_handling.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_exceptions.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_filter_pushdown.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_filter_pushdown_extension.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_function_storage.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_function_storage_azure_sql.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_function_storage_cf_do.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_function_storage_cf_do_integration.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_function_storage_conformance.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_generated_cpp_constants.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_generated_cpp_protocol_version.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_generated_cpp_request_builders.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_generated_cpp_schemas.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_generated_cpp_secret.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_generated_go_schemas.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_generated_protocol_version.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_generated_schemas_cross_lang.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_generated_ts_client.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_generated_ts_schemas.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_http_demo_storage.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_http_s3_offload_input.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_http_s3_offload_output.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_landing_conformance.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_metadata.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_mypy_consolidated.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_nest_tensor.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_otel.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_projection_enforcement.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_projection_repro.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_resolved_secrets.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_schema_scoped_functions.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_schema_utils.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_serve.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_setting_secret_annotations.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_table_buffering_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_table_function_dynamic_to_string.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_tcp_transport.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_type_bounds.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_union_argument.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_worker.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_worker_cli.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/test_worker_page.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/transactor/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/tests/transactor/test_transactor.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_duckdb.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_storage_profile.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/accumulate/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/accumulate/worker.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/aggregate/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/aggregate/_common.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/aggregate/basic.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/aggregate/dynamic.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/aggregate/generic.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/aggregate/listagg.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/aggregate/percentile.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/aggregate/same_name.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/aggregate/secret_typed.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/aggregate/streaming.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/aggregate/varargs.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/aggregate/window.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/attach_options.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/bad_enum.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/bad_protocol.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/cancellable.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/catalog.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/companion.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/copy_from.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/copy_to.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/narrow_bind/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/narrow_bind/worker.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/nest_tensor.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/orchard_catalog.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/projection_repro/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/projection_repro/worker.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/scalar/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/scalar/_common.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/scalar/arithmetic.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/scalar/bench_ladder.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/scalar/binary.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/scalar/formatting.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/scalar/geo.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/scalar/null_handling.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/scalar/random_demo.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/scalar/same_name.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/scalar/settings_secrets.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/scalar/type_info.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/schema_reconcile/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/schema_reconcile/worker.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/simple_writable.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/_common.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/batch_index.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/batch_index_broken.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/cache.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/catalog_scans.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/filters.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/late_materialization.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/make_series.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/misc.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/order_modes.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/pairs.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/partition_columns.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/partition_columns_broken.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/profiling_example.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/required_filters.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/same_name_cached.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/sequence.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/settings.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/transaction_storage.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/tt_pushdown.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/typed_probe.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table/versioned.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table_in_out.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/table_in_out_same_name.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/twin_catalogs.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/versioned.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/versioned_tables.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/worker.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/writable/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/writable/generic.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/writable/table.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/_test_fixtures/writable/worker.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/aggregate_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/argument_spec.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/arguments.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/attach_header.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/auth.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/cache_control.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/catalog/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/catalog/_descriptor_spec.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/catalog/attach_option.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/catalog/descriptors.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/catalog/duckdb_statistics.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/catalog/secret_type.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/catalog/setting.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/catalog/storage.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/client/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/client/catalog_mixin.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/client/cli.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/client/cli_catalog.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/client/cli_schema.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/client/cli_table.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/client/cli_transaction.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/client/cli_utils.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/client/cli_view.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/client/client.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/codegen/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/codegen/_common.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/codegen/cpp_constants.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/codegen/cpp_protocol_version.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/codegen/cpp_request_builders.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/codegen/cpp_schemas.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/codegen/cpp_secret_protocol_version.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/codegen/cpp_secret_request_builders.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/codegen/cpp_secret_schemas.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/codegen/go_schemas.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/codegen/protocol_version.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/codegen/ts_client.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/codegen/ts_schemas.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/copy_from_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/copy_to_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/exceptions.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/function_storage.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/function_storage_azure_sql.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/function_storage_cf_do.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/http/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/http/demo_storage.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/http/describe_json.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/http/landing.html +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/http/landing_page.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/http/worker_page.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/invocation.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/logging_config.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/meta_worker.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/metadata.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/otel.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/protocol_version.txt +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/py.typed +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/scalar_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/schema_utils.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/secret_protocol.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/secret_service.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/table_buffering_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/table_filter_pushdown.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/table_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/table_in_out_function.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/transactor/__init__.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/transactor/_duckdb_compat.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/transactor/client.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/transactor/protocol.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/transactor/server.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.0}/vgi/worker.py +0 -0
- {vgi_python-0.20.0 → vgi_python-0.22.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.22.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.28.2
|
|
166
166
|
Provides-Extra: azure
|
|
167
167
|
Requires-Dist: azure-identity>=1.16.0; extra == 'azure'
|
|
168
168
|
Requires-Dist: pymssql>=2.3.0; extra == 'azure'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "vgi-python"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.22.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.28.2",
|
|
44
44
|
"httpx>=0.24",
|
|
45
45
|
]
|
|
46
46
|
|
|
@@ -142,6 +142,12 @@ convention = "google"
|
|
|
142
142
|
|
|
143
143
|
[tool.ruff.format]
|
|
144
144
|
quote-style = "double"
|
|
145
|
+
# ruff >=0.16 formats Python code blocks embedded in Markdown. Our docs use
|
|
146
|
+
# mkdocs `pymdownx.snippets` includes (`--8<-- "examples/foo.py"`) inside
|
|
147
|
+
# ```python fences; ruff parses those as Python and rewrites them to
|
|
148
|
+
# `--8 < --"..."`, breaking both the docs build and the doc-example tests.
|
|
149
|
+
# Keep Markdown out.
|
|
150
|
+
exclude = ["*.md"]
|
|
145
151
|
|
|
146
152
|
[tool.pydoclint]
|
|
147
153
|
# Docstring consistency gate (complements ruff's `D` rules, which only check
|
|
@@ -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:
|
|
@@ -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__
|
|
@@ -2061,27 +2061,27 @@ wheels = [
|
|
|
2061
2061
|
|
|
2062
2062
|
[[package]]
|
|
2063
2063
|
name = "ruff"
|
|
2064
|
-
version = "0.
|
|
2065
|
-
source = { registry = "https://pypi.org/simple" }
|
|
2066
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
2067
|
-
wheels = [
|
|
2068
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2069
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2070
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2071
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2072
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2073
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2074
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2075
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2076
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2077
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2078
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2079
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2080
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2081
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2082
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2083
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2084
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2064
|
+
version = "0.16.0"
|
|
2065
|
+
source = { registry = "https://pypi.org/simple" }
|
|
2066
|
+
sdist = { url = "https://files.pythonhosted.org/packages/4d/94/1e5e4967626faf12fa56999cd6222dff6992ceb086ad7945756baf70c7a7/ruff-0.16.0.tar.gz", hash = "sha256:e460aafd5495ec89efaa6ced2e4a9a581116451e1c88b9d37ef497e0f8e93982", size = 4790557, upload-time = "2026-07-23T19:11:30.981Z" }
|
|
2067
|
+
wheels = [
|
|
2068
|
+
{ url = "https://files.pythonhosted.org/packages/4b/81/1c8818fee7ce1a04cd7d1b3172e0a8f8e4f1dc4feb7fc390e16daa8af323/ruff-0.16.0-py3-none-linux_armv6l.whl", hash = "sha256:e5115729eb08c585e5121978ba5d5b60caeae394ce21b9fb5e6cd33a1c6c9b1e", size = 10754633, upload-time = "2026-07-23T19:10:46.415Z" },
|
|
2069
|
+
{ url = "https://files.pythonhosted.org/packages/23/df/beaf59c09d68db84304d555f188b276a77132a5d5b0b67a5c762aa143628/ruff-0.16.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:3c954b1d580bfa035b41654f7858cc7e71d5fc3ac5b723dd62bd9133830ed522", size = 10969164, upload-time = "2026-07-23T19:10:50.271Z" },
|
|
2070
|
+
{ url = "https://files.pythonhosted.org/packages/42/ce/741cd197496a1abbf51352710fd15ed995d2a2be87189c1da26a450d6e83/ruff-0.16.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e01c21d10eb1b29f47b7454e1f4056db9a3f0260c646aa88457c610291db9f81", size = 10488846, upload-time = "2026-07-23T19:10:52.639Z" },
|
|
2071
|
+
{ url = "https://files.pythonhosted.org/packages/52/2a/a2db8e88cade358f5cdcb05674a917751074109315d014eb6352d9a893f7/ruff-0.16.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e364e5ed22ed8dc05082fd78e35308618260907ac2d3c1d637b2e682415b6c9", size = 10889729, upload-time = "2026-07-23T19:10:54.89Z" },
|
|
2072
|
+
{ url = "https://files.pythonhosted.org/packages/42/65/62a771694ebd63029dc953e27dbad40e1588bd4860ff9fe881018fddaa49/ruff-0.16.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d327b8fc113a1d4421a04f3839d3752057c8dd1ee320223a6f3f52d04ada462a", size = 10568275, upload-time = "2026-07-23T19:10:56.993Z" },
|
|
2073
|
+
{ url = "https://files.pythonhosted.org/packages/3f/e2/ced249fe8af5f086c5c58cc21cc3356d50f32f7401c5df87050c999620a7/ruff-0.16.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9b50c55e263103586b3dcf5f73d479eb8cb5fdb6098fec59a62891dab653717", size = 11385112, upload-time = "2026-07-23T19:10:59.615Z" },
|
|
2074
|
+
{ url = "https://files.pythonhosted.org/packages/87/0b/05154977a8fd69eeb6c103271f55403bfd8711f5c0f8ed07489d95a504e7/ruff-0.16.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0ff4a79ce3ec0172f3241943835de1c4cb4e2dcd07f0f8c2d02603dbbbee4b17", size = 12207008, upload-time = "2026-07-23T19:11:02.154Z" },
|
|
2075
|
+
{ url = "https://files.pythonhosted.org/packages/fb/29/98225831a3a1eab0e02f4acc6ca6559a98611dcc68b6965ff4b7234627c1/ruff-0.16.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e95c448fca1fb2a18372a9440926c5a6ee789639bb975c72e7ae6d0b04218ab4", size = 11650842, upload-time = "2026-07-23T19:11:04.557Z" },
|
|
2076
|
+
{ url = "https://files.pythonhosted.org/packages/91/66/6bd3cf90500653d55dc0ffc8507aa8300bd49d0214b2e8cb4d3fef2943ba/ruff-0.16.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f11a8d11010301d0a398a2fdef67691feca7294da6aef55e2150e8fa2cd520b", size = 11400718, upload-time = "2026-07-23T19:11:09.233Z" },
|
|
2077
|
+
{ url = "https://files.pythonhosted.org/packages/8e/a2/a54eb4eae05d66364050a5d3b8a9c5ef88196531b3cbe7109d873f87f819/ruff-0.16.0-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:48044c678e9cb8698246c99b14aaccfa6601dea7379eb48a6f8f73f7a6d86cd0", size = 11426177, upload-time = "2026-07-23T19:11:11.994Z" },
|
|
2078
|
+
{ url = "https://files.pythonhosted.org/packages/1a/be/16e3eea4b2a478a496919f5e36f17c4559e54620bd3bbac5d6affa068006/ruff-0.16.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7aa0959bad8eb8bef50340154fc9b58678dae31fa4293afa38b44b6e552c0213", size = 10856126, upload-time = "2026-07-23T19:11:14.221Z" },
|
|
2079
|
+
{ url = "https://files.pythonhosted.org/packages/a2/84/252eb8b868a16eec7257c14f504f77537e734b2d69c762e639e588e304a3/ruff-0.16.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:28ea2b7df8ebf7f9da6b7d47b230ab48f387c0a29be3b474c4d0740e197bb9af", size = 10571208, upload-time = "2026-07-23T19:11:16.378Z" },
|
|
2080
|
+
{ url = "https://files.pythonhosted.org/packages/21/09/817a482f542f7570cbb4554b26e896610c7114f539b1d9e2d2145bf6bef6/ruff-0.16.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:33a3dfac8c35f81498dea9181bccc2f4c4bc8f1521a1dd9406e77643e0f0fb09", size = 11063329, upload-time = "2026-07-23T19:11:19.173Z" },
|
|
2081
|
+
{ url = "https://files.pythonhosted.org/packages/2e/23/9403c180ca1cb9b1f7335f5c3e5305c09d49ea5b345196682a36028bde4a/ruff-0.16.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a5237a0bda500d30d81b8e07a6973a5cbc772864cbf746ae2f4e8a2e01c9f4ed", size = 11489751, upload-time = "2026-07-23T19:11:21.74Z" },
|
|
2082
|
+
{ url = "https://files.pythonhosted.org/packages/b2/1d/1b2ef7bcde851c78d7f17f1cca13fd6dc695fc4b3d6197941e72cae5b132/ruff-0.16.0-py3-none-win32.whl", hash = "sha256:7fab76fa065c873f41ff744347c6e77bcc3dfec4bcc754dc26b63d23c0f7f5fb", size = 10785885, upload-time = "2026-07-23T19:11:23.947Z" },
|
|
2083
|
+
{ url = "https://files.pythonhosted.org/packages/b2/a3/d5e4ef7a56be3f928ffb90b94c25ba7d3cb9c7fe0736aeaaedf361770712/ruff-0.16.0-py3-none-win_amd64.whl", hash = "sha256:429c117f022bf481fabd9d551e7a3952b24c65e6ef44337ea09d90bebef14472", size = 11923141, upload-time = "2026-07-23T19:11:26.409Z" },
|
|
2084
|
+
{ url = "https://files.pythonhosted.org/packages/cb/9a/8415f2657cbe200f41a4531ccededf135505a92d4a012229121f885b26f9/ruff-0.16.0-py3-none-win_arm64.whl", hash = "sha256:14296fedcd2705c77ab8235439278bbb38f285cf7da5528b00b3e330c3d4872d", size = 11273407, upload-time = "2026-07-23T19:11:28.705Z" },
|
|
2085
2085
|
]
|
|
2086
2086
|
|
|
2087
2087
|
[[package]]
|
|
@@ -2228,7 +2228,7 @@ requires-dist = [
|
|
|
2228
2228
|
|
|
2229
2229
|
[[package]]
|
|
2230
2230
|
name = "vgi-python"
|
|
2231
|
-
version = "0.
|
|
2231
|
+
version = "0.22.0"
|
|
2232
2232
|
source = { editable = "." }
|
|
2233
2233
|
dependencies = [
|
|
2234
2234
|
{ name = "click" },
|
|
@@ -2338,7 +2338,7 @@ requires-dist = [
|
|
|
2338
2338
|
{ name = "vgi-python", extras = ["test-fixtures"], marker = "extra == 'test-fixtures-writable'" },
|
|
2339
2339
|
{ name = "vgi-python", extras = ["test-fixtures", "test-fixtures-writable", "http", "oauth", "otel", "sentry", "azure"], marker = "extra == 'dev'" },
|
|
2340
2340
|
{ name = "vgi-python", extras = ["transactor"], marker = "extra == 'test-fixtures-writable'" },
|
|
2341
|
-
{ name = "vgi-rpc", specifier = ">=0.
|
|
2341
|
+
{ name = "vgi-rpc", specifier = ">=0.28.2" },
|
|
2342
2342
|
{ name = "vgi-rpc", extras = ["conformance", "external", "http", "oauth", "otel", "sentry"], marker = "extra == 'dev'" },
|
|
2343
2343
|
{ name = "vgi-rpc", extras = ["http"], marker = "extra == 'http'" },
|
|
2344
2344
|
{ name = "vgi-rpc", extras = ["oauth"], marker = "extra == 'oauth'" },
|
|
@@ -2367,7 +2367,7 @@ docs = [
|
|
|
2367
2367
|
|
|
2368
2368
|
[[package]]
|
|
2369
2369
|
name = "vgi-rpc"
|
|
2370
|
-
version = "0.
|
|
2370
|
+
version = "0.28.2"
|
|
2371
2371
|
source = { registry = "https://pypi.org/simple" }
|
|
2372
2372
|
dependencies = [
|
|
2373
2373
|
{ name = "docstring-parser" },
|
|
@@ -2375,9 +2375,9 @@ dependencies = [
|
|
|
2375
2375
|
{ name = "pywin32", marker = "sys_platform == 'win32'" },
|
|
2376
2376
|
{ name = "tzdata", marker = "sys_platform == 'win32'" },
|
|
2377
2377
|
]
|
|
2378
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
2378
|
+
sdist = { url = "https://files.pythonhosted.org/packages/89/a0/00252e2d6986094c13bf35b7f7e1e95b0a3b0497c210b2c88cc72b82b3c7/vgi_rpc-0.28.2.tar.gz", hash = "sha256:4fcfcd5c42a0242aee9d1f40e16fab6559f6401feccf44fe50ad91ee473dc5f4", size = 905341, upload-time = "2026-07-27T13:56:23.482Z" }
|
|
2379
2379
|
wheels = [
|
|
2380
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2380
|
+
{ url = "https://files.pythonhosted.org/packages/3c/1d/0a34b627d4f6d3bf83e61a5897fb32e5bf1543708380ee1a6eaeeb56a8d7/vgi_rpc-0.28.2-py3-none-any.whl", hash = "sha256:dc96d11b2ced0fa36e653ed475c653f4124748b2372da1866028da4975eb9b8f", size = 404897, upload-time = "2026-07-27T13:56:21.549Z" },
|
|
2381
2381
|
]
|
|
2382
2382
|
|
|
2383
2383
|
[package.optional-dependencies]
|
|
@@ -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:
|
|
@@ -1188,9 +1188,10 @@ class ScanBranchesResult:
|
|
|
1188
1188
|
)
|
|
1189
1189
|
|
|
1190
1190
|
branch_blobs = cast("list[bytes]", row["branches"])
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1191
|
+
# An empty branch list is valid: a multi-branch scan can prune to zero
|
|
1192
|
+
# branches (see catalog/multi_branch_empty_branches) — it scans nothing.
|
|
1193
|
+
# Lenient producers (the Rust/Go/Java SDKs, tolerated by the DuckDB C++
|
|
1194
|
+
# client) send it; don't reject.
|
|
1194
1195
|
branches: list[ScanBranch] = []
|
|
1195
1196
|
for blob in branch_blobs:
|
|
1196
1197
|
branch_batch, _ = deserialize_record_batch(blob)
|
|
@@ -288,7 +288,7 @@ class InitRequest(ArrowSerializableDataclass):
|
|
|
288
288
|
"""
|
|
289
289
|
|
|
290
290
|
# Core (always present)
|
|
291
|
-
bind_call: BindRequest
|
|
291
|
+
bind_call: Annotated[BindRequest, ArrowType(pa.binary())]
|
|
292
292
|
output_schema: Annotated[pa.Schema, ArrowType(pa.binary())]
|
|
293
293
|
bind_opaque_data: Annotated[bytes | None, ArrowType(pa.binary())] = None
|
|
294
294
|
|
|
@@ -348,7 +348,7 @@ class TableFunctionCardinalityRequest(ArrowSerializableDataclass):
|
|
|
348
348
|
``InitRequest.bind_opaque_data``).
|
|
349
349
|
"""
|
|
350
350
|
|
|
351
|
-
bind_call: BindRequest
|
|
351
|
+
bind_call: Annotated[BindRequest, ArrowType(pa.binary())]
|
|
352
352
|
bind_opaque_data: Annotated[bytes | None, ArrowType(pa.binary())] = None
|
|
353
353
|
|
|
354
354
|
|
|
@@ -368,7 +368,7 @@ class TableFunctionStatisticsRequest(ArrowSerializableDataclass):
|
|
|
368
368
|
``InitRequest.bind_opaque_data``).
|
|
369
369
|
"""
|
|
370
370
|
|
|
371
|
-
bind_call: BindRequest
|
|
371
|
+
bind_call: Annotated[BindRequest, ArrowType(pa.binary())]
|
|
372
372
|
bind_opaque_data: Annotated[bytes | None, ArrowType(pa.binary())] = None
|
|
373
373
|
|
|
374
374
|
|
|
@@ -392,7 +392,7 @@ class TableFunctionDynamicToStringRequest(ArrowSerializableDataclass):
|
|
|
392
392
|
persisted the diagnostics this RPC retrieves.
|
|
393
393
|
"""
|
|
394
394
|
|
|
395
|
-
bind_call: BindRequest
|
|
395
|
+
bind_call: Annotated[BindRequest, ArrowType(pa.binary())]
|
|
396
396
|
bind_opaque_data: Annotated[bytes | None, ArrowType(pa.binary())] = None
|
|
397
397
|
global_execution_id: bytes
|
|
398
398
|
|
|
@@ -32,7 +32,7 @@ import os
|
|
|
32
32
|
import sys
|
|
33
33
|
from collections.abc import Callable
|
|
34
34
|
from types import ModuleType
|
|
35
|
-
from typing import TYPE_CHECKING, Any
|
|
35
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
36
36
|
|
|
37
37
|
from vgi.logging_config import LogFormat, LogLevel
|
|
38
38
|
|
|
@@ -429,6 +429,10 @@ def _resolve_authenticate() -> Callable[..., Any] | None:
|
|
|
429
429
|
- ``VGI_JWT_ISSUER`` + ``VGI_JWT_AUDIENCE``: JWT/JWKS auth
|
|
430
430
|
(requires ``vgi[oauth]`` extra). Optional ``VGI_JWT_JWKS_URI``.
|
|
431
431
|
- When both bearer and JWT are set, they are chained (JWT first).
|
|
432
|
+
- ``VGI_PROXY_PROOF_MODE``: ``allow`` or ``require`` gates every request
|
|
433
|
+
on proof that it arrived through a trusted proxy. This is a
|
|
434
|
+
precondition ANDed with whichever credential above is configured, not
|
|
435
|
+
an alternative to one.
|
|
432
436
|
|
|
433
437
|
Returns:
|
|
434
438
|
An authenticate callback, or None if no auth env vars are set.
|
|
@@ -438,14 +442,84 @@ def _resolve_authenticate() -> Callable[..., Any] | None:
|
|
|
438
442
|
JWT issuer without audience).
|
|
439
443
|
|
|
440
444
|
"""
|
|
441
|
-
|
|
442
|
-
|
|
445
|
+
# Ordered by cost: JWT resolves a signature, bearer does a constant-time
|
|
446
|
+
# scan over the token set, so the cheaper one goes last.
|
|
447
|
+
candidates = [fn for fn in (_resolve_jwt_authenticate(), _resolve_bearer_authenticate()) if fn is not None]
|
|
443
448
|
|
|
444
|
-
|
|
449
|
+
inner: Callable[..., Any] | None
|
|
450
|
+
if len(candidates) > 1:
|
|
445
451
|
from vgi_rpc.http import chain_authenticate
|
|
446
452
|
|
|
447
|
-
|
|
448
|
-
|
|
453
|
+
inner = chain_authenticate(*candidates)
|
|
454
|
+
else:
|
|
455
|
+
inner = candidates[0] if candidates else None
|
|
456
|
+
|
|
457
|
+
gate = _resolve_proxy_proof_gate()
|
|
458
|
+
if gate is None:
|
|
459
|
+
return inner
|
|
460
|
+
|
|
461
|
+
# AND, not OR: chaining the gate would let any later credential satisfy
|
|
462
|
+
# the request on its own, which is exactly the bypass the gate exists to
|
|
463
|
+
# close. `inner` may be None — proof alone means "only my proxy may call
|
|
464
|
+
# this worker", with user identity handled upstream.
|
|
465
|
+
from vgi_rpc.http import require_all
|
|
466
|
+
|
|
467
|
+
return require_all(gate, inner)
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
def _resolve_proxy_proof_gate() -> Any | None:
|
|
471
|
+
"""Build a proxy-proof gate from ``VGI_PROXY_PROOF_*`` environment variables.
|
|
472
|
+
|
|
473
|
+
Env vars:
|
|
474
|
+
|
|
475
|
+
- ``VGI_PROXY_PROOF_MODE``: ``off`` (default), ``allow`` or ``require``.
|
|
476
|
+
- ``VGI_PROXY_PROOF_ORIGIN_ID``: this worker's identifier. Folded into
|
|
477
|
+
every MAC but never transmitted, so it must match what the proxy is
|
|
478
|
+
configured to prove to.
|
|
479
|
+
- ``VGI_PROXY_PROOF_SECRETS``: ``kid:hex`` pairs, comma-separated. The
|
|
480
|
+
``kid`` doubles as the proxy's label in the audit trail.
|
|
481
|
+
- ``VGI_PROXY_PROOF_SKEW``: acceptance half-window in seconds (default 30).
|
|
482
|
+
|
|
483
|
+
Returns:
|
|
484
|
+
A gate for ``require_all``, or None when the feature is off.
|
|
485
|
+
|
|
486
|
+
Raises:
|
|
487
|
+
SystemExit: On any malformed value. Deliberately fail-closed: the
|
|
488
|
+
secret is shared with an independently-deployed proxy, so a typo
|
|
489
|
+
would otherwise silently reject every request with no diagnostic.
|
|
490
|
+
|
|
491
|
+
"""
|
|
492
|
+
raw_mode = (os.environ.get("VGI_PROXY_PROOF_MODE") or "off").strip().lower()
|
|
493
|
+
if raw_mode == "off":
|
|
494
|
+
return None
|
|
495
|
+
if raw_mode not in ("allow", "require"):
|
|
496
|
+
sys.stderr.write(
|
|
497
|
+
f"Error: VGI_PROXY_PROOF_MODE must be 'off', 'allow' or 'require', got {raw_mode!r}\n",
|
|
498
|
+
)
|
|
499
|
+
sys.exit(1)
|
|
500
|
+
mode: Literal["allow", "require"] = "allow" if raw_mode == "allow" else "require"
|
|
501
|
+
|
|
502
|
+
from vgi_rpc.http import ProxyProofConfig, parse_secrets, proxy_proof_gate
|
|
503
|
+
|
|
504
|
+
raw_secrets = os.environ.get("VGI_PROXY_PROOF_SECRETS") or ""
|
|
505
|
+
skew_raw = os.environ.get("VGI_PROXY_PROOF_SKEW") or "30"
|
|
506
|
+
try:
|
|
507
|
+
secrets = parse_secrets(raw_secrets)
|
|
508
|
+
config = ProxyProofConfig(
|
|
509
|
+
mode=mode,
|
|
510
|
+
origin_id=os.environ.get("VGI_PROXY_PROOF_ORIGIN_ID") or "",
|
|
511
|
+
secrets=secrets,
|
|
512
|
+
skew_seconds=int(skew_raw),
|
|
513
|
+
)
|
|
514
|
+
except ValueError as exc:
|
|
515
|
+
sys.stderr.write(
|
|
516
|
+
f"Error: invalid proxy-proof configuration: {exc}\n"
|
|
517
|
+
"Set VGI_PROXY_PROOF_MODE=off to disable, or fix "
|
|
518
|
+
"VGI_PROXY_PROOF_ORIGIN_ID / VGI_PROXY_PROOF_SECRETS "
|
|
519
|
+
"(kid:hex pairs, 64 hex chars each; generate with 'openssl rand -hex 32').\n",
|
|
520
|
+
)
|
|
521
|
+
sys.exit(1)
|
|
522
|
+
return proxy_proof_gate(config)
|
|
449
523
|
|
|
450
524
|
|
|
451
525
|
def _resolve_bearer_authenticate() -> Callable[..., Any] | None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|