vgi-python 0.8.8__tar.gz → 0.8.10__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.8.8 → vgi_python-0.8.10}/PKG-INFO +1 -2
- {vgi_python-0.8.8 → vgi_python-0.8.10}/ci/run-integration.sh +12 -1
- {vgi_python-0.8.8 → vgi_python-0.8.10}/pyproject.toml +10 -4
- vgi_python-0.8.10/tests/test_docstrings.py +65 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/uv.lock +1 -25
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/copy_from.py +1 -1
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/arithmetic.py +10 -2
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/arguments.py +41 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/catalog/__init__.py +2 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/protocol.py +4 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/scalar_function.py +45 -3
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/table_function.py +3 -3
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/worker.py +10 -9
- vgi_python-0.8.8/tests/test_docstrings.py +0 -60
- {vgi_python-0.8.8 → vgi_python-0.8.10}/.gitattributes +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/.github/dependabot.yml +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/.github/styles/config/vocabularies/VGI/accept.txt +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/.github/workflows/ci.yml +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/.github/workflows/docs.yml +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/.github/workflows/integration.yml +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/.github/workflows/release.yml +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/.gitignore +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/.python-version +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/.vale.ini +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/CLAUDE.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/DOCS_ACCEPTANCE_CRITERIA.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/DOCS_REVIEW_RUBRIC.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/DOCS_USABILITY_TEST.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/LICENSE +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/README.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/SECURITY.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/ci/README.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/ci/preprocess-require.awk +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/dist-vgi/.gitignore +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/aggregate-functions.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/arguments.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/auth.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/catalogs.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/client.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/exceptions.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/filters.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/functions.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/http.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/index.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/metadata.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/observability.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/storage.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/transactor.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/worker.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/argument-serialization.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/apple-touch-icon.png +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/favicon-16x16.png +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/favicon-32x32.png +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/favicon.ico +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/kinds/aggregate.svg +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/kinds/buffering.svg +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/kinds/scalar.svg +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/kinds/table-in-out.svg +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/kinds/table.svg +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/logo.png +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/social-card.png +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/authentication.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/catalog-interface.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/cli.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/column-statistics.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/concepts/index.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/contributing-docs.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/filter-pushdown.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/generator-api.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/how-to/catalogs.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/how-to/function-patterns.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/how-to/http-auth.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/how-to/index.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/how-to/pushdown-and-statistics.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/how-to/state-storage.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/index.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/lifecycle.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/metadata.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/overrides/main.html +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/robots.txt +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/shared-storage.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/stylesheets/extra.css +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/tutorial/index.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/tutorial/scalar.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/tutorial/table.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/vgi-logo.png +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/examples/calc_scalar_worker.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/examples/calc_worker.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/examples/filter_worker.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/examples/greeting_scalar_worker.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/examples/row_count_worker.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/examples/series_streaming_worker.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/examples/sum_worker.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/mkdocs.yml +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/packages/vgi-fixtures/LICENSE +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/packages/vgi-fixtures/README.md +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/packages/vgi-fixtures/pyproject.toml +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/scripts/measure_startup.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/scripts/run_all_tests.sh +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/test-data/generate.sh +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/_http_fixtures.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_catalog_interface.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_client_catalog.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_column_statistics.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_declarative.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_example_worker_catalog.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_integration.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_required_field_filter_paths.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_scan_branches.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_serialization.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_setting.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_storage.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_time_travel.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_writable_table.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/client/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/client/test_broken_pipe.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/client/test_cli.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/client/test_cli_catalog_functions.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/client/test_worker_debug.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/_stub.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/conftest.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_accumulate.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_aggregate.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_attach.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_bearer_auth.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_directory_parity.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_function_inventory.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_http_client.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_http_external_location.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_http_upload_url.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_macro.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_overload.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_protocol_inventory.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_protocol_version.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_resumable_scan.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_scalar.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_scalar_attach_opaque_data.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_secret.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_settings.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_table.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_table_in_out.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_view.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_writable.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conftest.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/test_bernoulli_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/test_binary_packet_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/test_client.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/test_conditional_message_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/test_hash_seed_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/test_multiply_by_setting_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/test_multiply_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/test_random_bytes_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/test_return_secret_value_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_constant_columns_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_double_sequence_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_exception_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_filter_echo_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_logging_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_nested_sequence_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_partitioned_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_projected_data_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_sequence_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_settings_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_struct_settings_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_ten_thousand_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table_in_out/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table_in_out/generator/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table_in_out/generator/test_buffer_input_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table_in_out/generator/test_echo_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table_in_out/generator/test_exception_functions.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table_in_out/generator/test_filter_by_setting_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table_in_out/generator/test_repeat_inputs_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table_in_out/generator/test_sum_all_columns_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table_in_out/test_client.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_access_log_audit.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_aggregate_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_argument_spec.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_auth.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_bind_exceptions.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_bind_request_at_clause.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_bound_storage_conformance.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_catalog_auth_binding.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_copy_from_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_copy_to_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_documentation_examples.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_example_function_arg_types.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_examples_workers.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_exception_handling.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_exceptions.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_filter_pushdown.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_filter_pushdown_extension.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_function_storage.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_function_storage_azure_sql.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_function_storage_cf_do.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_function_storage_cf_do_integration.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_function_storage_conformance.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_cpp_constants.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_cpp_protocol_version.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_cpp_request_builders.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_cpp_schemas.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_cpp_secret.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_go_schemas.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_protocol_version.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_schemas_cross_lang.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_ts_client.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_ts_schemas.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_http_demo_storage.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_http_s3_offload_input.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_http_s3_offload_output.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_metadata.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_mypy_consolidated.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_nest_tensor.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_otel.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_projection_enforcement.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_projection_repro.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_protocol_classes.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_resolved_secrets.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_schema_utils.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_serve.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_setting_secret_annotations.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_table_buffering_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_table_function_dynamic_to_string.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_tcp_transport.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_type_bounds.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_union_argument.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_worker.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_worker_cli.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_worker_page.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/transactor/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/transactor/test_transactor.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_duckdb.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_storage_profile.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/accumulate/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/accumulate/worker.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/_common.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/basic.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/dynamic.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/generic.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/listagg.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/percentile.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/streaming.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/varargs.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/window.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/attach_options.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/bad_enum.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/bad_protocol.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/cancellable.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/catalog.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/copy_to.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/http_server.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/narrow_bind/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/narrow_bind/worker.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/nest_tensor.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/orchard_catalog.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/projection_repro/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/projection_repro/worker.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/_common.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/binary.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/formatting.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/geo.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/null_handling.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/random_demo.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/settings_secrets.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/type_info.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/schema_reconcile/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/schema_reconcile/worker.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/simple_writable.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/_common.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/batch_index.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/batch_index_broken.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/catalog_scans.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/filters.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/late_materialization.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/make_series.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/misc.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/order_modes.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/pairs.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/partition_columns.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/partition_columns_broken.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/profiling_example.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/required_filters.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/sequence.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/settings.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/transaction_storage.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/tt_pushdown.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/typed_probe.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/versioned.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table_in_out.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/versioned.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/versioned_tables.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/worker.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/writable/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/writable/generic.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/writable/table.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/writable/worker.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/aggregate_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/argument_spec.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/auth.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/catalog/_descriptor_spec.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/catalog/attach_option.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/catalog/catalog_interface.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/catalog/descriptors.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/catalog/duckdb_statistics.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/catalog/secret_type.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/catalog/setting.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/catalog/storage.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/catalog_mixin.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/cli.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/cli_catalog.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/cli_schema.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/cli_table.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/cli_transaction.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/cli_utils.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/cli_view.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/client.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/_common.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/cpp_constants.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/cpp_protocol_version.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/cpp_request_builders.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/cpp_schemas.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/cpp_secret_protocol_version.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/cpp_secret_request_builders.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/cpp_secret_schemas.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/go_schemas.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/protocol_version.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/ts_client.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/ts_schemas.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/copy_from_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/copy_to_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/exceptions.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/function_storage.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/function_storage_azure_sql.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/function_storage_cf_do.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/http/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/http/demo_storage.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/http/worker_page.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/invocation.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/logging_config.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/meta_worker.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/metadata.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/otel.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/protocol_version.txt +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/py.typed +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/schema_utils.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/secret_protocol.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/secret_service.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/serve.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/table_buffering_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/table_filter_pushdown.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/table_in_out_function.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/transactor/__init__.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/transactor/_duckdb_compat.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/transactor/client.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/transactor/protocol.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/transactor/server.py +0 -0
- {vgi_python-0.8.8 → vgi_python-0.8.10}/wrangler.jsonc +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vgi-python
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.10
|
|
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
|
|
@@ -172,7 +172,6 @@ Requires-Dist: duckdb>=1.5.3; extra == 'dev'
|
|
|
172
172
|
Requires-Dist: mypy; extra == 'dev'
|
|
173
173
|
Requires-Dist: numpy>=2.4.1; extra == 'dev'
|
|
174
174
|
Requires-Dist: pyarrow-stubs; extra == 'dev'
|
|
175
|
-
Requires-Dist: pydoclint; extra == 'dev'
|
|
176
175
|
Requires-Dist: pymssql>=2.3.0; extra == 'dev'
|
|
177
176
|
Requires-Dist: pytest; extra == 'dev'
|
|
178
177
|
Requires-Dist: pytest-cov; extra == 'dev'
|
|
@@ -133,12 +133,23 @@ trap cleanup EXIT
|
|
|
133
133
|
# set BOOTED_PORT to the port it reports (PORT:<n>, the worker's readiness
|
|
134
134
|
# contract). Sets a global rather than echoing so the backgrounded worker stays a
|
|
135
135
|
# child of this shell (a $(...) subshell would reparent it and break teardown).
|
|
136
|
+
#
|
|
137
|
+
# The worker is spawned with cwd=$STAGE — the same directory the unittest binary
|
|
138
|
+
# runs from below (`cd "$STAGE"`). copy_from/copy_to tests have DuckDB write a
|
|
139
|
+
# source file under a relative `__TEST_DIR__` (duckdb_unittest_tempdir/...) that
|
|
140
|
+
# the worker then opens by the same relative path; the worker only resolves it
|
|
141
|
+
# if it shares DuckDB's cwd. On the stdio lane the C++ extension spawns the
|
|
142
|
+
# worker as a subprocess that inherits DuckDB's cwd, so it matches for free; the
|
|
143
|
+
# `( cd … ; exec … )` subshell gives the http worker the same footing (and
|
|
144
|
+
# mirrors the vgi repo's run_http_integration.sh, which boots server and DuckDB
|
|
145
|
+
# from one cwd). exec keeps the worker on the subshell's pid so teardown via the
|
|
146
|
+
# captured `$!` still works.
|
|
136
147
|
BOOTED_PORT=""
|
|
137
148
|
boot_http_worker() {
|
|
138
149
|
local exe="$1" log pid port=""
|
|
139
150
|
BOOTED_PORT=""
|
|
140
151
|
log="$(mktemp)"
|
|
141
|
-
"$exe" --http --port 0 >"$log" 2>&1 &
|
|
152
|
+
( cd "$STAGE" && exec "$exe" --http --port 0 ) >"$log" 2>&1 &
|
|
142
153
|
pid=$!
|
|
143
154
|
echo "$pid" >> "$BG_PIDS_FILE"
|
|
144
155
|
for _ in $(seq 1 60); do
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "vgi-python"
|
|
3
|
-
version = "0.8.
|
|
3
|
+
version = "0.8.10"
|
|
4
4
|
description = "Vector Gateway Interface - Connect DuckDB to external programs via Apache Arrow"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
keywords = [
|
|
@@ -77,7 +77,11 @@ dev = [
|
|
|
77
77
|
"duckdb>=1.5.3",
|
|
78
78
|
"mypy",
|
|
79
79
|
"pyarrow-stubs",
|
|
80
|
-
|
|
80
|
+
# pydoclint is intentionally NOT a project dependency: it pulls
|
|
81
|
+
# docstring-parser-fork, which clobbers the canonical docstring-parser
|
|
82
|
+
# (a vgi-rpc dependency) in the shared `docstring_parser` namespace,
|
|
83
|
+
# non-deterministically breaking imports. tests/test_docstrings.py runs it
|
|
84
|
+
# in an isolated env via `uvx pydoclint` instead.
|
|
81
85
|
"pytest",
|
|
82
86
|
"pytest-cov",
|
|
83
87
|
"pytest-examples",
|
|
@@ -142,7 +146,9 @@ quote-style = "double"
|
|
|
142
146
|
# Docstring consistency gate (complements ruff's `D` rules, which only check
|
|
143
147
|
# docstring *shape*, not whether documented args/attributes match the code).
|
|
144
148
|
# Enforced families: DOC001 (parse), DOC101/102/103 (arg<->signature), DOC4xx
|
|
145
|
-
# (yields), DOC60x (dataclass attributes).
|
|
149
|
+
# (yields), DOC60x (dataclass attributes). pydoclint is NOT a project dependency
|
|
150
|
+
# (it pulls docstring-parser-fork, which clobbers vgi-rpc's docstring-parser);
|
|
151
|
+
# run it isolated: `uvx --python $(which python) pydoclint --config pyproject.toml vgi/`.
|
|
146
152
|
style = "google"
|
|
147
153
|
# We keep types in signatures, not docstrings (Google style) — so don't ask for
|
|
148
154
|
# them in docstrings, and don't try to match return/yield *types* against prose.
|
|
@@ -162,7 +168,7 @@ allow_init_docstring = true
|
|
|
162
168
|
# No baseline: vgi/ is fully clean under this config, so the gate enforces
|
|
163
169
|
# every in-scope violation with no grandfathered exceptions. If a future change
|
|
164
170
|
# needs to defer cleanup, freeze the current state and re-add `baseline`:
|
|
165
|
-
#
|
|
171
|
+
# uvx pydoclint --config pyproject.toml --generate-baseline=True --baseline=.pydoclint-baseline vgi/
|
|
166
172
|
|
|
167
173
|
[tool.mypy]
|
|
168
174
|
python_version = "3.13"
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Copyright 2025, 2026 Query Farm LLC - https://query.farm
|
|
2
|
+
|
|
3
|
+
"""Docstring-consistency gate.
|
|
4
|
+
|
|
5
|
+
Runs pydoclint over the ``vgi/`` package as part of the test suite. pydoclint
|
|
6
|
+
complements ruff's ``D`` rules: ruff checks docstring *shape*, while pydoclint
|
|
7
|
+
verifies that documented arguments, return values, yields, and dataclass
|
|
8
|
+
attributes actually match the code. Configuration lives in ``[tool.pydoclint]``
|
|
9
|
+
in ``pyproject.toml`` — this test invokes the same CLI, so there is no
|
|
10
|
+
duplicated rule set.
|
|
11
|
+
|
|
12
|
+
pydoclint runs through ``uvx`` (an isolated, ephemeral environment) rather than
|
|
13
|
+
as a project dependency. It requires ``docstring-parser-fork`` while ``vgi-rpc``
|
|
14
|
+
(a runtime dependency) requires the upstream ``docstring-parser``; both own the
|
|
15
|
+
``docstring_parser`` import namespace, so installing pydoclint into the project
|
|
16
|
+
env clobbers it non-deterministically and breaks unrelated imports (e.g.
|
|
17
|
+
``conftest`` collection). Running via uvx keeps the fork out of the project tree.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import re
|
|
21
|
+
import shutil
|
|
22
|
+
import subprocess
|
|
23
|
+
import sys
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
|
|
26
|
+
import pytest
|
|
27
|
+
|
|
28
|
+
_REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
29
|
+
|
|
30
|
+
# A real violation line looks like `` 42: DOC101: ...``. If pydoclint exits
|
|
31
|
+
# non-zero without emitting any such code, it failed to *run* rather than finding
|
|
32
|
+
# violations.
|
|
33
|
+
_VIOLATION_RE = re.compile(r"\bDOC\d{3}\b")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_pydoclint_clean() -> None:
|
|
37
|
+
"""``vgi/`` must pass the pydoclint docstring gate (config in pyproject.toml)."""
|
|
38
|
+
uvx = shutil.which("uvx") or shutil.which("uv")
|
|
39
|
+
if uvx is None: # pragma: no cover - uv is always present in dev/CI
|
|
40
|
+
pytest.skip("uv/uvx is not available to run pydoclint")
|
|
41
|
+
|
|
42
|
+
# `uvx pydoclint ...` == `uv tool run pydoclint ...`; both run pydoclint in an
|
|
43
|
+
# isolated env so docstring-parser-fork never enters the project tree.
|
|
44
|
+
# Pin the ephemeral env to *this* interpreter (``--python sys.executable``):
|
|
45
|
+
# pydoclint parses with its own runtime's AST, so it must run on a Python new
|
|
46
|
+
# enough for the repo's syntax (PEP 695 generics need 3.12+); uvx's default
|
|
47
|
+
# interpreter may be older and would report spurious DOC002 syntax errors.
|
|
48
|
+
base = [uvx] if Path(uvx).name == "uvx" else [uvx, "tool", "run"]
|
|
49
|
+
cmd = [*base, "--python", sys.executable, "pydoclint", "--config", "pyproject.toml", "vgi/"]
|
|
50
|
+
result = subprocess.run(cmd, cwd=_REPO_ROOT, capture_output=True, text=True)
|
|
51
|
+
output = result.stdout + result.stderr
|
|
52
|
+
|
|
53
|
+
if result.returncode == 0:
|
|
54
|
+
return
|
|
55
|
+
|
|
56
|
+
if not _VIOLATION_RE.search(output): # pragma: no cover - env-dependent (e.g. offline uvx)
|
|
57
|
+
pytest.skip(f"pydoclint could not run via uvx:\n{output}")
|
|
58
|
+
|
|
59
|
+
pytest.fail(
|
|
60
|
+
"pydoclint found docstring violations:\n\n"
|
|
61
|
+
f"{output}\n"
|
|
62
|
+
"Fix the docstrings, or run `uvx pydoclint --config pyproject.toml "
|
|
63
|
+
"--generate-baseline=True --baseline=.pydoclint-baseline vgi/` "
|
|
64
|
+
"to defer them (see [tool.pydoclint] in pyproject.toml)."
|
|
65
|
+
)
|
|
@@ -516,15 +516,6 @@ wheels = [
|
|
|
516
516
|
{ url = "https://files.pythonhosted.org/packages/a7/5f/ed01f9a3cdffbd5a008556fc7b2a08ddb1cc6ace7effa7340604b1d16699/docstring_parser-0.18.0-py3-none-any.whl", hash = "sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b", size = 22484, upload-time = "2026-04-14T04:09:18.638Z" },
|
|
517
517
|
]
|
|
518
518
|
|
|
519
|
-
[[package]]
|
|
520
|
-
name = "docstring-parser-fork"
|
|
521
|
-
version = "0.0.14"
|
|
522
|
-
source = { registry = "https://pypi.org/simple" }
|
|
523
|
-
sdist = { url = "https://files.pythonhosted.org/packages/66/bf/27f9cab2f0cd1d17a4420572088bbc19f36d726fbcf165edf226a8926dbc/docstring_parser_fork-0.0.14.tar.gz", hash = "sha256:a2743a63d8d36c09650594f7b4ab5b2758fee8629dcf794d1b221b23179baa5c", size = 34551, upload-time = "2025-09-07T17:27:38.272Z" }
|
|
524
|
-
wheels = [
|
|
525
|
-
{ url = "https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl", hash = "sha256:4c544f234ef2cc2749a3df32b70c437d77888b1099143a1ad5454452c574b9af", size = 43063, upload-time = "2025-09-07T17:27:37.012Z" },
|
|
526
|
-
]
|
|
527
|
-
|
|
528
519
|
[[package]]
|
|
529
520
|
name = "duckdb"
|
|
530
521
|
version = "1.5.4"
|
|
@@ -1657,19 +1648,6 @@ wheels = [
|
|
|
1657
1648
|
{ url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" },
|
|
1658
1649
|
]
|
|
1659
1650
|
|
|
1660
|
-
[[package]]
|
|
1661
|
-
name = "pydoclint"
|
|
1662
|
-
version = "0.8.7"
|
|
1663
|
-
source = { registry = "https://pypi.org/simple" }
|
|
1664
|
-
dependencies = [
|
|
1665
|
-
{ name = "click" },
|
|
1666
|
-
{ name = "docstring-parser-fork" },
|
|
1667
|
-
]
|
|
1668
|
-
sdist = { url = "https://files.pythonhosted.org/packages/bf/2e/e4df6b0cbb281cb6cf355f5d90b8c66939c7f3cd799c075fab23e0983dfb/pydoclint-0.8.7.tar.gz", hash = "sha256:1ce5055dfdaf2bc3c999d3ffd5494556b903b7090bb5fadac90819107f90629b", size = 199793, upload-time = "2026-06-22T01:24:20.117Z" }
|
|
1669
|
-
wheels = [
|
|
1670
|
-
{ url = "https://files.pythonhosted.org/packages/e9/d4/15fe5c3e66bbf3f60eb9c6ef7c2dca3931302f9acf317e65d70e7d8b338a/pydoclint-0.8.7-py3-none-any.whl", hash = "sha256:40f6b80e59129fe753f6a2f9edd76e4259c970eedc1ce3663adc43f54af439d3", size = 82963, upload-time = "2026-06-22T01:24:19.102Z" },
|
|
1671
|
-
]
|
|
1672
|
-
|
|
1673
1651
|
[[package]]
|
|
1674
1652
|
name = "pygments"
|
|
1675
1653
|
version = "2.20.0"
|
|
@@ -2250,7 +2228,7 @@ requires-dist = [
|
|
|
2250
2228
|
|
|
2251
2229
|
[[package]]
|
|
2252
2230
|
name = "vgi-python"
|
|
2253
|
-
version = "0.8.
|
|
2231
|
+
version = "0.8.10"
|
|
2254
2232
|
source = { editable = "." }
|
|
2255
2233
|
dependencies = [
|
|
2256
2234
|
{ name = "click" },
|
|
@@ -2272,7 +2250,6 @@ dev = [
|
|
|
2272
2250
|
{ name = "mypy" },
|
|
2273
2251
|
{ name = "numpy" },
|
|
2274
2252
|
{ name = "pyarrow-stubs" },
|
|
2275
|
-
{ name = "pydoclint" },
|
|
2276
2253
|
{ name = "pymssql" },
|
|
2277
2254
|
{ name = "pytest" },
|
|
2278
2255
|
{ name = "pytest-cov" },
|
|
@@ -2346,7 +2323,6 @@ requires-dist = [
|
|
|
2346
2323
|
{ name = "platformdirs" },
|
|
2347
2324
|
{ name = "pyarrow" },
|
|
2348
2325
|
{ name = "pyarrow-stubs", marker = "extra == 'dev'" },
|
|
2349
|
-
{ name = "pydoclint", marker = "extra == 'dev'" },
|
|
2350
2326
|
{ name = "pymssql", marker = "extra == 'azure'", specifier = ">=2.3.0" },
|
|
2351
2327
|
{ name = "pytest", marker = "extra == 'dev'" },
|
|
2352
2328
|
{ name = "pytest-cov", marker = "extra == 'dev'" },
|
|
@@ -91,7 +91,7 @@ class ExampleLinesCopyFromFunction(CopyFromFunction[ExampleLinesCopyFromArgs]):
|
|
|
91
91
|
|
|
92
92
|
# Column-major string arrays, NULL where the cell equals null_string,
|
|
93
93
|
# then cast each column to the target type (DuckDB inserts no cast).
|
|
94
|
-
columns = list(zip(*rows)) if rows else [() for _ in range(ncols)]
|
|
94
|
+
columns = list(zip(*rows, strict=True)) if rows else [() for _ in range(ncols)]
|
|
95
95
|
arrays = []
|
|
96
96
|
for idx, field in enumerate(expected_schema):
|
|
97
97
|
raw = [None if v == options.null_string else v for v in columns[idx]]
|
|
@@ -51,9 +51,17 @@ class MultiplyFunction(ScalarFunction):
|
|
|
51
51
|
def compute(
|
|
52
52
|
cls,
|
|
53
53
|
value: Annotated[pa.Int64Array, Param(doc="Integer value to multiply")],
|
|
54
|
-
factor: Annotated[
|
|
54
|
+
factor: Annotated[pa.Int64Scalar, ConstParam("Multiplication factor")],
|
|
55
55
|
) -> Annotated[pa.Int64Array, Returns()]:
|
|
56
|
-
"""Multiply values by the constant factor.
|
|
56
|
+
"""Multiply values by the constant factor.
|
|
57
|
+
|
|
58
|
+
``factor`` is annotated as a ``pa.Int64Scalar`` (not a Python ``int``), so
|
|
59
|
+
the SDK delivers the typed Arrow scalar straight through and it can be
|
|
60
|
+
passed directly into ``pc.multiply``. Passing a bare Python int instead
|
|
61
|
+
makes pyarrow infer an Arrow scalar on every call — ~40-50x slower on
|
|
62
|
+
Windows than a typed scalar, and the dominant per-batch cost for a scalar
|
|
63
|
+
UDF. This is the idiomatic fast pattern for compute-bound constants.
|
|
64
|
+
"""
|
|
57
65
|
return pc.multiply(value, factor)
|
|
58
66
|
|
|
59
67
|
|
|
@@ -109,6 +109,46 @@ COMPLEX_ARRAY_CLASSES: set[type] = {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
|
|
112
|
+
# Simple scalar classes that can be inferred automatically. Annotating a const
|
|
113
|
+
# parameter with one of these — ``Annotated[pa.Int64Scalar, ConstParam(...)]`` —
|
|
114
|
+
# makes the SDK deliver the typed ``pa.Scalar`` straight through to ``compute()``
|
|
115
|
+
# instead of converting it to a Python object via ``as_py()``. That lets the
|
|
116
|
+
# const be passed directly into ``pyarrow.compute`` with no per-call scalar
|
|
117
|
+
# re-inference, which is ~40-50x slower on Windows than a typed scalar. Built
|
|
118
|
+
# defensively so a pyarrow release missing a class name doesn't break import.
|
|
119
|
+
def _build_scalar_class_to_datatype() -> dict[type, pa.DataType]:
|
|
120
|
+
pairs: list[tuple[str, pa.DataType]] = [
|
|
121
|
+
("Int8Scalar", pa.int8()),
|
|
122
|
+
("Int16Scalar", pa.int16()),
|
|
123
|
+
("Int32Scalar", pa.int32()),
|
|
124
|
+
("Int64Scalar", pa.int64()),
|
|
125
|
+
("UInt8Scalar", pa.uint8()),
|
|
126
|
+
("UInt16Scalar", pa.uint16()),
|
|
127
|
+
("UInt32Scalar", pa.uint32()),
|
|
128
|
+
("UInt64Scalar", pa.uint64()),
|
|
129
|
+
("HalfFloatScalar", pa.float16()),
|
|
130
|
+
("FloatScalar", pa.float32()),
|
|
131
|
+
("DoubleScalar", pa.float64()),
|
|
132
|
+
("StringScalar", pa.string()),
|
|
133
|
+
("LargeStringScalar", pa.large_string()),
|
|
134
|
+
("BinaryScalar", pa.binary()),
|
|
135
|
+
("LargeBinaryScalar", pa.large_binary()),
|
|
136
|
+
("BooleanScalar", pa.bool_()),
|
|
137
|
+
("Date32Scalar", pa.date32()),
|
|
138
|
+
("Date64Scalar", pa.date64()),
|
|
139
|
+
("NullScalar", pa.null()),
|
|
140
|
+
]
|
|
141
|
+
out: dict[type, pa.DataType] = {}
|
|
142
|
+
for name, dt in pairs:
|
|
143
|
+
cls = getattr(pa, name, None)
|
|
144
|
+
if isinstance(cls, type):
|
|
145
|
+
out[cls] = dt
|
|
146
|
+
return out
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
SCALAR_CLASS_TO_DATATYPE: dict[type, pa.DataType] = _build_scalar_class_to_datatype()
|
|
150
|
+
|
|
151
|
+
|
|
112
152
|
# Sentinel for missing default value - proper type pattern
|
|
113
153
|
class _MissingType:
|
|
114
154
|
"""Sentinel type for missing default values.
|
|
@@ -158,6 +198,7 @@ __all__ = [
|
|
|
158
198
|
"Param",
|
|
159
199
|
"PYTHON_TO_ARROW",
|
|
160
200
|
"Returns",
|
|
201
|
+
"SCALAR_CLASS_TO_DATATYPE",
|
|
161
202
|
"TableInput",
|
|
162
203
|
"TaggedUnion",
|
|
163
204
|
"TypeBoundPredicate",
|
|
@@ -15,6 +15,7 @@ from vgi.catalog.catalog_interface import (
|
|
|
15
15
|
CatalogInterface,
|
|
16
16
|
CatalogObject,
|
|
17
17
|
CatalogSchemaObject,
|
|
18
|
+
CopyFromFormatInfo,
|
|
18
19
|
FunctionInfo,
|
|
19
20
|
FunctionType,
|
|
20
21
|
IndexConstraintType,
|
|
@@ -67,6 +68,7 @@ __all__ = [
|
|
|
67
68
|
"TableInfo",
|
|
68
69
|
"ViewInfo",
|
|
69
70
|
"FunctionInfo",
|
|
71
|
+
"CopyFromFormatInfo",
|
|
70
72
|
"ScanBranch",
|
|
71
73
|
"ScanBranchesResult",
|
|
72
74
|
"ScanFunctionResult",
|
|
@@ -196,6 +196,10 @@ class BindRequest(ArrowSerializableDataclass):
|
|
|
196
196
|
accessor), not at on_bind.
|
|
197
197
|
at_value: Value of the time-travel ``AT`` clause for this scan; ``None`` when
|
|
198
198
|
the scan has no AT clause. See ``at_unit`` for the inline-bind caveat.
|
|
199
|
+
copy_from: The ``COPY ... FROM`` context (source format + path); ``None``
|
|
200
|
+
unless this bind/init opens a COPY-FROM scan.
|
|
201
|
+
copy_to: The ``COPY ... TO`` context (destination format + path); ``None``
|
|
202
|
+
unless this bind/init opens a COPY-TO sink.
|
|
199
203
|
"""
|
|
200
204
|
|
|
201
205
|
function_name: str
|
|
@@ -48,6 +48,7 @@ from vgi.arguments import (
|
|
|
48
48
|
_PYTHON_TO_ARROW,
|
|
49
49
|
ARRAY_CLASS_TO_DATATYPE,
|
|
50
50
|
COMPLEX_ARRAY_CLASSES,
|
|
51
|
+
SCALAR_CLASS_TO_DATATYPE,
|
|
51
52
|
Arg,
|
|
52
53
|
Arguments,
|
|
53
54
|
ArgumentValidationError,
|
|
@@ -212,6 +213,25 @@ def _param_to_arg(param: Param, base_type: type, position: int) -> Arg[Any]:
|
|
|
212
213
|
)
|
|
213
214
|
|
|
214
215
|
|
|
216
|
+
def _is_scalar_annotation(base_type: object) -> bool:
|
|
217
|
+
"""Whether a [`ConstParam`][] is annotated with a pyarrow scalar class.
|
|
218
|
+
|
|
219
|
+
``Annotated[pa.Int64Scalar, ConstParam(...)]`` (or the generic ``pa.Scalar``)
|
|
220
|
+
signals that the typed Arrow scalar should be delivered to ``compute()``
|
|
221
|
+
unchanged, instead of converting it to a Python value via ``as_py()``. The
|
|
222
|
+
scalar can then flow straight into ``pyarrow.compute`` with no per-call scalar
|
|
223
|
+
re-inference (the latter is ~40-50x slower on Windows than a typed scalar).
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
base_type: The type from the ``Annotated`` first argument.
|
|
227
|
+
|
|
228
|
+
Returns:
|
|
229
|
+
True iff ``base_type`` is ``pa.Scalar`` or a subclass.
|
|
230
|
+
|
|
231
|
+
"""
|
|
232
|
+
return isinstance(base_type, type) and issubclass(base_type, pa.Scalar)
|
|
233
|
+
|
|
234
|
+
|
|
215
235
|
def _const_param_to_arg(const_param: ConstParam, base_type: type, position: int) -> Arg[Any]:
|
|
216
236
|
"""Convert [`ConstParam`][] dataclass to internal [`Arg`][] object.
|
|
217
237
|
|
|
@@ -235,6 +255,15 @@ def _const_param_to_arg(const_param: ConstParam, base_type: type, position: int)
|
|
|
235
255
|
elif base_type in _PYTHON_TO_ARROW:
|
|
236
256
|
# Infer from Annotated first argument
|
|
237
257
|
arrow_type = _PYTHON_TO_ARROW[base_type]
|
|
258
|
+
elif base_type in SCALAR_CLASS_TO_DATATYPE:
|
|
259
|
+
# Annotated[pa.Int64Scalar, ConstParam(...)] — infer from the scalar class
|
|
260
|
+
# and deliver the typed scalar through (see _is_scalar_annotation).
|
|
261
|
+
arrow_type = SCALAR_CLASS_TO_DATATYPE[base_type]
|
|
262
|
+
elif _is_scalar_annotation(base_type):
|
|
263
|
+
raise TypeError(
|
|
264
|
+
f"Cannot infer Arrow type from {getattr(base_type, '__name__', base_type)}. "
|
|
265
|
+
f"Use a concrete scalar class (e.g. pa.Int64Scalar) or set arrow_type=... on ConstParam()."
|
|
266
|
+
)
|
|
238
267
|
else:
|
|
239
268
|
raise TypeError(
|
|
240
269
|
f"Cannot infer Arrow type from {base_type}. "
|
|
@@ -791,6 +820,7 @@ class ScalarFunction(ScalarFunctionGenerator):
|
|
|
791
820
|
|
|
792
821
|
_compute_params: dict[str, Arg[Any]] # Regular Param() arguments (arrays)
|
|
793
822
|
_const_params: dict[str, Arg[Any]] # ConstParam() arguments (scalars)
|
|
823
|
+
_const_scalar_params: set[str] # ConstParams annotated as pa.Scalar — delivered un-as_py()'d
|
|
794
824
|
_setting_params: dict[str, str] # Setting params: param_name -> setting_key
|
|
795
825
|
_secret_params: dict[str, Secret] # Secret params: param_name -> Secret instance
|
|
796
826
|
_output_length_param: str | None # OutputLength param name (batch row count)
|
|
@@ -866,6 +896,7 @@ class ScalarFunction(ScalarFunctionGenerator):
|
|
|
866
896
|
|
|
867
897
|
compute_params: dict[str, Arg[Any]] = {}
|
|
868
898
|
const_params: dict[str, Arg[Any]] = {}
|
|
899
|
+
const_scalar_params: set[str] = set() # ConstParams annotated as pa.Scalar
|
|
869
900
|
output_length_param: str | None = None # param that receives batch row count
|
|
870
901
|
auth_param: str | None = None # param that receives AuthContext
|
|
871
902
|
returns_output_type: pa.DataType | None = None
|
|
@@ -940,6 +971,8 @@ class ScalarFunction(ScalarFunctionGenerator):
|
|
|
940
971
|
# _resolution_index points to Arguments.positional index
|
|
941
972
|
arg._resolution_index = const_index
|
|
942
973
|
const_params[name] = arg
|
|
974
|
+
if _is_scalar_annotation(base_type):
|
|
975
|
+
const_scalar_params.add(name)
|
|
943
976
|
setattr(cls, name, _ConstArgDescriptor(arg, name))
|
|
944
977
|
overall_position += 1
|
|
945
978
|
const_index += 1
|
|
@@ -966,6 +999,7 @@ class ScalarFunction(ScalarFunctionGenerator):
|
|
|
966
999
|
|
|
967
1000
|
cls._compute_params = compute_params
|
|
968
1001
|
cls._const_params = const_params
|
|
1002
|
+
cls._const_scalar_params = const_scalar_params
|
|
969
1003
|
cls._setting_params = setting_params
|
|
970
1004
|
cls._secret_params = secret_params
|
|
971
1005
|
cls._output_length_param = output_length_param
|
|
@@ -1051,14 +1085,22 @@ class ScalarFunction(ScalarFunctionGenerator):
|
|
|
1051
1085
|
# Regular param: extract column by index
|
|
1052
1086
|
kwargs[name] = batch.column(col_idx)
|
|
1053
1087
|
|
|
1054
|
-
# Const params: extract
|
|
1088
|
+
# Const params: extract values from the constant arguments. Params annotated
|
|
1089
|
+
# with a pyarrow scalar class (e.g. Annotated[pa.Int64Scalar, ConstParam(...)])
|
|
1090
|
+
# receive the typed pa.Scalar unchanged, so it can be passed straight into
|
|
1091
|
+
# pyarrow.compute with no per-call scalar re-inference; all others get the
|
|
1092
|
+
# Python value via as_py() (backward compatible).
|
|
1055
1093
|
for name, arg in cls._const_params.items():
|
|
1056
1094
|
# Use _resolution_index for Arguments.positional lookup
|
|
1057
1095
|
arg_idx = cast(int, arg._resolution_index)
|
|
1058
1096
|
# Get the scalar value from arguments
|
|
1059
1097
|
scalar = bind_call.arguments.positional[arg_idx]
|
|
1060
|
-
|
|
1061
|
-
|
|
1098
|
+
if scalar is None:
|
|
1099
|
+
kwargs[name] = None
|
|
1100
|
+
elif name in cls._const_scalar_params:
|
|
1101
|
+
kwargs[name] = scalar
|
|
1102
|
+
else:
|
|
1103
|
+
kwargs[name] = scalar.as_py()
|
|
1062
1104
|
|
|
1063
1105
|
# Setting params: extract pa.Scalar from settings RecordBatch
|
|
1064
1106
|
if bind_call.settings is not None and cls._setting_params:
|
|
@@ -300,7 +300,7 @@ def _secret_scalar_str(v: Any) -> str:
|
|
|
300
300
|
return "" if py is None else str(py)
|
|
301
301
|
|
|
302
302
|
|
|
303
|
-
class ResolvedSecrets(dict):
|
|
303
|
+
class ResolvedSecrets(dict[str, dict[str, Any]]):
|
|
304
304
|
"""Resolved secrets keyed by secret name, with type- and scope-aware lookup.
|
|
305
305
|
|
|
306
306
|
A plain ``dict`` (so ``secrets[name]`` and ``secrets.get(name)`` still work)
|
|
@@ -514,7 +514,7 @@ class InitParams[TArgs]:
|
|
|
514
514
|
output_schema: pa.Schema
|
|
515
515
|
|
|
516
516
|
settings: dict[str, pa.Scalar[Any]]
|
|
517
|
-
secrets:
|
|
517
|
+
secrets: ResolvedSecrets
|
|
518
518
|
|
|
519
519
|
storage: BoundStorage
|
|
520
520
|
auth_context: AuthContext = AuthContext.anonymous()
|
|
@@ -569,7 +569,7 @@ class ProcessParams[TArgs]:
|
|
|
569
569
|
output_schema: pa.Schema
|
|
570
570
|
|
|
571
571
|
settings: dict[str, pa.Scalar[Any]]
|
|
572
|
-
secrets:
|
|
572
|
+
secrets: ResolvedSecrets
|
|
573
573
|
|
|
574
574
|
storage: BoundStorage
|
|
575
575
|
auth_context: AuthContext = AuthContext.anonymous()
|
|
@@ -146,6 +146,7 @@ from vgi.table_buffering_function import (
|
|
|
146
146
|
)
|
|
147
147
|
from vgi.table_function import (
|
|
148
148
|
ProcessParams,
|
|
149
|
+
ResolvedSecrets,
|
|
149
150
|
SecretsAccessor,
|
|
150
151
|
TableCardinality,
|
|
151
152
|
TableFunctionBase,
|
|
@@ -2407,7 +2408,7 @@ class Worker:
|
|
|
2407
2408
|
init_response=None,
|
|
2408
2409
|
output_schema=pa.schema([]),
|
|
2409
2410
|
settings={},
|
|
2410
|
-
secrets=
|
|
2411
|
+
secrets=ResolvedSecrets(),
|
|
2411
2412
|
storage=storage,
|
|
2412
2413
|
auth_context=ctx.auth,
|
|
2413
2414
|
)
|
|
@@ -2513,7 +2514,7 @@ class Worker:
|
|
|
2513
2514
|
init_response=None,
|
|
2514
2515
|
output_schema=pa.schema([]),
|
|
2515
2516
|
settings={},
|
|
2516
|
-
secrets=
|
|
2517
|
+
secrets=ResolvedSecrets(),
|
|
2517
2518
|
storage=storage,
|
|
2518
2519
|
auth_context=ctx.auth,
|
|
2519
2520
|
)
|
|
@@ -2576,7 +2577,7 @@ class Worker:
|
|
|
2576
2577
|
init_response=None,
|
|
2577
2578
|
output_schema=request.output_schema,
|
|
2578
2579
|
settings={},
|
|
2579
|
-
secrets=
|
|
2580
|
+
secrets=ResolvedSecrets(),
|
|
2580
2581
|
storage=storage,
|
|
2581
2582
|
auth_context=ctx.auth,
|
|
2582
2583
|
)
|
|
@@ -2815,7 +2816,7 @@ class Worker:
|
|
|
2815
2816
|
init_response=None,
|
|
2816
2817
|
output_schema=request.output_schema,
|
|
2817
2818
|
settings={},
|
|
2818
|
-
secrets=
|
|
2819
|
+
secrets=ResolvedSecrets(),
|
|
2819
2820
|
storage=storage,
|
|
2820
2821
|
auth_context=ctx.auth,
|
|
2821
2822
|
)
|
|
@@ -2912,7 +2913,7 @@ class Worker:
|
|
|
2912
2913
|
init_response=None,
|
|
2913
2914
|
output_schema=output_schema,
|
|
2914
2915
|
settings={},
|
|
2915
|
-
secrets=
|
|
2916
|
+
secrets=ResolvedSecrets(),
|
|
2916
2917
|
storage=storage,
|
|
2917
2918
|
auth_context=ctx.auth,
|
|
2918
2919
|
)
|
|
@@ -3027,7 +3028,7 @@ class Worker:
|
|
|
3027
3028
|
init_response=None,
|
|
3028
3029
|
output_schema=output_schema,
|
|
3029
3030
|
settings={},
|
|
3030
|
-
secrets=
|
|
3031
|
+
secrets=ResolvedSecrets(),
|
|
3031
3032
|
storage=storage,
|
|
3032
3033
|
auth_context=ctx.auth,
|
|
3033
3034
|
)
|
|
@@ -3121,7 +3122,7 @@ class Worker:
|
|
|
3121
3122
|
init_response=None,
|
|
3122
3123
|
output_schema=request.output_schema,
|
|
3123
3124
|
settings=_batch_to_scalar_dict(request.settings),
|
|
3124
|
-
secrets=
|
|
3125
|
+
secrets=ResolvedSecrets(),
|
|
3125
3126
|
storage=storage,
|
|
3126
3127
|
auth_context=ctx.auth,
|
|
3127
3128
|
)
|
|
@@ -3187,7 +3188,7 @@ class Worker:
|
|
|
3187
3188
|
init_response=None,
|
|
3188
3189
|
output_schema=session.output_schema,
|
|
3189
3190
|
settings={},
|
|
3190
|
-
secrets=
|
|
3191
|
+
secrets=ResolvedSecrets(),
|
|
3191
3192
|
storage=storage,
|
|
3192
3193
|
auth_context=ctx.auth,
|
|
3193
3194
|
)
|
|
@@ -3280,7 +3281,7 @@ class Worker:
|
|
|
3280
3281
|
init_response=None,
|
|
3281
3282
|
output_schema=session.output_schema,
|
|
3282
3283
|
settings={},
|
|
3283
|
-
secrets=
|
|
3284
|
+
secrets=ResolvedSecrets(),
|
|
3284
3285
|
storage=storage,
|
|
3285
3286
|
auth_context=ctx.auth,
|
|
3286
3287
|
)
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
# Copyright 2025, 2026 Query Farm LLC - https://query.farm
|
|
2
|
-
|
|
3
|
-
"""Docstring-consistency gate.
|
|
4
|
-
|
|
5
|
-
Runs pydoclint over the ``vgi/`` package as part of the test suite, mirroring
|
|
6
|
-
the CI ``Docstring lint (pydoclint)`` step. pydoclint complements ruff's ``D``
|
|
7
|
-
rules: ruff checks docstring *shape*, while pydoclint verifies that documented
|
|
8
|
-
arguments, return values, yields, and dataclass attributes actually match the
|
|
9
|
-
code. Configuration lives in ``[tool.pydoclint]`` in ``pyproject.toml`` — this
|
|
10
|
-
test invokes the same CLI, so there is no duplicated rule set.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
import re
|
|
14
|
-
import shutil
|
|
15
|
-
import subprocess
|
|
16
|
-
from pathlib import Path
|
|
17
|
-
|
|
18
|
-
import pytest
|
|
19
|
-
|
|
20
|
-
_REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
21
|
-
|
|
22
|
-
# A real violation line looks like `` 42: DOC101: ...``. If pydoclint exits
|
|
23
|
-
# non-zero without emitting any such code, it failed to *run* (e.g. import
|
|
24
|
-
# error) rather than finding violations — see the environment note below.
|
|
25
|
-
_VIOLATION_RE = re.compile(r"\bDOC\d{3}\b")
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def test_pydoclint_clean() -> None:
|
|
29
|
-
"""``vgi/`` must pass the pydoclint docstring gate (config in pyproject.toml)."""
|
|
30
|
-
pydoclint = shutil.which("pydoclint")
|
|
31
|
-
if pydoclint is None: # pragma: no cover - dev dependency should always be present
|
|
32
|
-
pytest.skip("pydoclint is not installed")
|
|
33
|
-
|
|
34
|
-
result = subprocess.run(
|
|
35
|
-
[pydoclint, "vgi/"],
|
|
36
|
-
cwd=_REPO_ROOT,
|
|
37
|
-
capture_output=True,
|
|
38
|
-
text=True,
|
|
39
|
-
)
|
|
40
|
-
output = result.stdout + result.stderr
|
|
41
|
-
|
|
42
|
-
if result.returncode == 0:
|
|
43
|
-
return
|
|
44
|
-
|
|
45
|
-
# pydoclint depends on ``docstring-parser-fork`` while ``vgi-rpc`` depends on
|
|
46
|
-
# the upstream ``docstring-parser``; both claim the ``docstring_parser``
|
|
47
|
-
# import namespace, so on some interpreter/OS combinations the wrong files
|
|
48
|
-
# win and pydoclint crashes on import. That's a broken tool environment, not
|
|
49
|
-
# a docstring problem — skip rather than fail (the gate still runs on every
|
|
50
|
-
# other matrix cell where the tool is healthy).
|
|
51
|
-
if not _VIOLATION_RE.search(output): # pragma: no cover - env-dependent
|
|
52
|
-
pytest.skip(f"pydoclint could not run in this environment:\n{output}")
|
|
53
|
-
|
|
54
|
-
pytest.fail(
|
|
55
|
-
"pydoclint found docstring violations:\n\n"
|
|
56
|
-
f"{output}\n"
|
|
57
|
-
"Fix the docstrings, or run "
|
|
58
|
-
"`uv run pydoclint --generate-baseline=True --baseline=.pydoclint-baseline vgi/` "
|
|
59
|
-
"to defer them (see [tool.pydoclint] in pyproject.toml)."
|
|
60
|
-
)
|
|
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
|