vgi-python 0.8.6__tar.gz → 0.8.7__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.6 → vgi_python-0.8.7}/PKG-INFO +2 -2
- {vgi_python-0.8.6 → vgi_python-0.8.7}/pyproject.toml +2 -2
- vgi_python-0.8.7/tests/test_tcp_transport.py +122 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/uv.lock +5 -5
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/client/catalog_mixin.py +23 -7
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/client/client.py +92 -6
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/worker.py +59 -3
- {vgi_python-0.8.6 → vgi_python-0.8.7}/.gitattributes +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/.github/dependabot.yml +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/.github/styles/config/vocabularies/VGI/accept.txt +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/.github/workflows/ci.yml +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/.github/workflows/docs.yml +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/.github/workflows/integration.yml +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/.github/workflows/release.yml +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/.gitignore +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/.python-version +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/.vale.ini +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/CLAUDE.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/DOCS_ACCEPTANCE_CRITERIA.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/DOCS_REVIEW_RUBRIC.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/DOCS_USABILITY_TEST.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/LICENSE +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/README.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/SECURITY.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/ci/README.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/ci/preprocess-require.awk +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/ci/run-integration.sh +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/dist-vgi/.gitignore +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/aggregate-functions.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/api/arguments.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/api/auth.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/api/catalogs.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/api/client.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/api/exceptions.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/api/filters.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/api/functions.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/api/http.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/api/index.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/api/metadata.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/api/observability.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/api/storage.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/api/transactor.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/api/worker.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/argument-serialization.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/assets/apple-touch-icon.png +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/assets/favicon-16x16.png +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/assets/favicon-32x32.png +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/assets/favicon.ico +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/assets/kinds/aggregate.svg +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/assets/kinds/buffering.svg +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/assets/kinds/scalar.svg +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/assets/kinds/table-in-out.svg +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/assets/kinds/table.svg +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/assets/logo.png +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/assets/social-card.png +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/authentication.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/catalog-interface.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/cli.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/column-statistics.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/concepts/index.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/contributing-docs.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/filter-pushdown.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/generator-api.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/how-to/catalogs.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/how-to/function-patterns.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/how-to/http-auth.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/how-to/index.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/how-to/pushdown-and-statistics.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/how-to/state-storage.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/index.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/lifecycle.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/metadata.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/overrides/main.html +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/robots.txt +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/shared-storage.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/stylesheets/extra.css +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/tutorial/index.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/tutorial/scalar.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/tutorial/table.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/docs/vgi-logo.png +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/examples/calc_scalar_worker.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/examples/calc_worker.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/examples/filter_worker.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/examples/greeting_scalar_worker.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/examples/row_count_worker.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/examples/series_streaming_worker.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/examples/sum_worker.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/mkdocs.yml +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/packages/vgi-fixtures/LICENSE +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/packages/vgi-fixtures/README.md +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/packages/vgi-fixtures/pyproject.toml +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/scripts/measure_startup.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/scripts/run_all_tests.sh +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/test-data/generate.sh +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/_http_fixtures.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/catalog/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/catalog/test_catalog_interface.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/catalog/test_client_catalog.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/catalog/test_column_statistics.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/catalog/test_declarative.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/catalog/test_example_worker_catalog.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/catalog/test_integration.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/catalog/test_required_field_filter_paths.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/catalog/test_scan_branches.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/catalog/test_serialization.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/catalog/test_setting.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/catalog/test_storage.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/catalog/test_time_travel.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/catalog/test_writable_table.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/client/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/client/test_broken_pipe.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/client/test_cli.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/client/test_cli_catalog_functions.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/client/test_worker_debug.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/_stub.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/conftest.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_accumulate.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_aggregate.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_attach.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_bearer_auth.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_directory_parity.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_function_inventory.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_http_client.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_http_external_location.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_http_upload_url.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_macro.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_overload.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_protocol_inventory.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_protocol_version.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_resumable_scan.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_scalar.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_scalar_attach_opaque_data.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_secret.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_settings.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_table.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_table_in_out.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_view.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conformance/test_writable.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/conftest.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/scalar/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/scalar/test_bernoulli_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/scalar/test_binary_packet_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/scalar/test_client.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/scalar/test_conditional_message_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/scalar/test_hash_seed_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/scalar/test_multiply_by_setting_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/scalar/test_multiply_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/scalar/test_random_bytes_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/scalar/test_return_secret_value_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table/generator/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table/generator/test_constant_columns_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table/generator/test_double_sequence_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table/generator/test_exception_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table/generator/test_filter_echo_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table/generator/test_logging_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table/generator/test_nested_sequence_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table/generator/test_partitioned_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table/generator/test_projected_data_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table/generator/test_sequence_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table/generator/test_settings_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table/generator/test_struct_settings_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table/generator/test_ten_thousand_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table_in_out/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table_in_out/generator/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table_in_out/generator/test_buffer_input_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table_in_out/generator/test_echo_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table_in_out/generator/test_exception_functions.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table_in_out/generator/test_filter_by_setting_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table_in_out/generator/test_repeat_inputs_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table_in_out/generator/test_sum_all_columns_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/table_in_out/test_client.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_access_log_audit.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_aggregate_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_argument_spec.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_auth.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_bind_exceptions.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_bind_request_at_clause.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_bound_storage_conformance.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_catalog_auth_binding.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_docstrings.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_documentation_examples.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_example_function_arg_types.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_examples_workers.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_exception_handling.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_exceptions.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_filter_pushdown.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_filter_pushdown_extension.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_function_storage.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_function_storage_azure_sql.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_function_storage_cf_do.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_function_storage_cf_do_integration.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_function_storage_conformance.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_generated_cpp_constants.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_generated_cpp_protocol_version.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_generated_cpp_request_builders.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_generated_cpp_schemas.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_generated_cpp_secret.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_generated_go_schemas.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_generated_protocol_version.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_generated_schemas_cross_lang.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_generated_ts_client.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_generated_ts_schemas.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_http_demo_storage.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_http_s3_offload_input.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_http_s3_offload_output.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_metadata.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_mypy_consolidated.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_nest_tensor.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_otel.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_projection_enforcement.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_projection_repro.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_protocol_classes.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_schema_utils.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_serve.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_setting_secret_annotations.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_table_buffering_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_table_function_dynamic_to_string.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_type_bounds.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_union_argument.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_worker.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_worker_cli.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/test_worker_page.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/transactor/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/tests/transactor/test_transactor.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_duckdb.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_storage_profile.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/accumulate/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/accumulate/worker.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/_common.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/basic.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/dynamic.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/generic.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/listagg.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/percentile.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/streaming.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/varargs.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/window.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/attach_options.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/bad_enum.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/bad_protocol.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/cancellable.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/catalog.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/http_server.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/narrow_bind/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/narrow_bind/worker.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/nest_tensor.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/orchard_catalog.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/projection_repro/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/projection_repro/worker.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/_common.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/arithmetic.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/binary.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/formatting.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/geo.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/null_handling.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/random_demo.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/settings_secrets.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/type_info.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/schema_reconcile/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/schema_reconcile/worker.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/simple_writable.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/_common.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/batch_index.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/batch_index_broken.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/catalog_scans.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/filters.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/late_materialization.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/make_series.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/misc.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/order_modes.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/pairs.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/partition_columns.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/partition_columns_broken.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/profiling_example.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/required_filters.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/sequence.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/settings.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/transaction_storage.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/tt_pushdown.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/typed_probe.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table/versioned.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/table_in_out.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/versioned.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/versioned_tables.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/worker.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/writable/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/writable/generic.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/writable/table.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/_test_fixtures/writable/worker.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/aggregate_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/argument_spec.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/arguments.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/auth.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/catalog/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/catalog/_descriptor_spec.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/catalog/attach_option.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/catalog/catalog_interface.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/catalog/descriptors.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/catalog/duckdb_statistics.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/catalog/secret_type.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/catalog/setting.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/catalog/storage.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/client/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/client/cli.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/client/cli_catalog.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/client/cli_schema.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/client/cli_table.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/client/cli_transaction.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/client/cli_utils.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/client/cli_view.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/codegen/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/codegen/_common.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/codegen/cpp_constants.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/codegen/cpp_protocol_version.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/codegen/cpp_request_builders.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/codegen/cpp_schemas.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/codegen/cpp_secret_protocol_version.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/codegen/cpp_secret_request_builders.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/codegen/cpp_secret_schemas.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/codegen/go_schemas.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/codegen/protocol_version.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/codegen/ts_client.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/codegen/ts_schemas.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/exceptions.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/function_storage.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/function_storage_azure_sql.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/function_storage_cf_do.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/http/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/http/demo_storage.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/http/worker_page.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/invocation.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/logging_config.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/meta_worker.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/metadata.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/otel.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/protocol.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/protocol_version.txt +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/py.typed +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/scalar_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/schema_utils.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/secret_protocol.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/secret_service.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/serve.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/table_buffering_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/table_filter_pushdown.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/table_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/table_in_out_function.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/transactor/__init__.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/transactor/_duckdb_compat.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/transactor/client.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/transactor/protocol.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/vgi/transactor/server.py +0 -0
- {vgi_python-0.8.6 → vgi_python-0.8.7}/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.7
|
|
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.21.0
|
|
166
166
|
Provides-Extra: azure
|
|
167
167
|
Requires-Dist: azure-identity>=1.16.0; extra == 'azure'
|
|
168
168
|
Requires-Dist: pymssql>=2.3.0; extra == 'azure'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "vgi-python"
|
|
3
|
-
version = "0.8.
|
|
3
|
+
version = "0.8.7"
|
|
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.21.0",
|
|
44
44
|
"httpx>=0.24",
|
|
45
45
|
]
|
|
46
46
|
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Copyright 2025, 2026 Query Farm LLC - https://query.farm
|
|
2
|
+
|
|
3
|
+
"""Round-trip tests for the TCP transport.
|
|
4
|
+
|
|
5
|
+
Spawns ``vgi-fixture-worker --tcp 127.0.0.1:0`` (raw Arrow-IPC framing over a
|
|
6
|
+
TCP socket, served by ``vgi_rpc.rpc.run_server``), parses the ``TCP:host:port``
|
|
7
|
+
discovery line it prints on stdout, then drives it through
|
|
8
|
+
``Client.from_tcp(...)`` — the TCP analog of the HTTP round-trip in
|
|
9
|
+
``tests/_http_fixtures.py``.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import queue
|
|
15
|
+
import subprocess
|
|
16
|
+
import sys
|
|
17
|
+
import threading
|
|
18
|
+
from collections.abc import Iterator
|
|
19
|
+
from contextlib import contextmanager
|
|
20
|
+
|
|
21
|
+
import pyarrow as pa
|
|
22
|
+
import pytest
|
|
23
|
+
|
|
24
|
+
from vgi.arguments import Arguments
|
|
25
|
+
from vgi.client import Client
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@contextmanager
|
|
29
|
+
def run_tcp_worker(*, bind: str = "127.0.0.1:0") -> Iterator[tuple[str, int]]:
|
|
30
|
+
"""Run ``vgi-fixture-worker --tcp`` and yield the bound ``(host, port)``.
|
|
31
|
+
|
|
32
|
+
The worker prints ``TCP:<host>:<port>`` once bound and then must not write
|
|
33
|
+
further to stdout (the cross-language launcher discovery contract), so we
|
|
34
|
+
read exactly one line to learn the port. stderr is drained in the
|
|
35
|
+
background to keep the worker from blocking on a full pipe buffer.
|
|
36
|
+
"""
|
|
37
|
+
proc = subprocess.Popen(
|
|
38
|
+
[sys.executable, "-m", "vgi._test_fixtures.worker", "--tcp", bind],
|
|
39
|
+
stdout=subprocess.PIPE,
|
|
40
|
+
stderr=subprocess.PIPE,
|
|
41
|
+
text=True,
|
|
42
|
+
bufsize=1,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
def _drain(pipe: object) -> None:
|
|
46
|
+
for _ in pipe: # type: ignore[attr-defined]
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
stderr_thread = threading.Thread(target=_drain, args=(proc.stderr,), daemon=True)
|
|
50
|
+
stderr_thread.start()
|
|
51
|
+
|
|
52
|
+
# Read the discovery line off stdout with a timeout so a worker that never
|
|
53
|
+
# binds fails the test instead of hanging it.
|
|
54
|
+
line_q: queue.Queue[str] = queue.Queue(maxsize=1)
|
|
55
|
+
|
|
56
|
+
def _read_line() -> None:
|
|
57
|
+
assert proc.stdout is not None
|
|
58
|
+
for line in proc.stdout:
|
|
59
|
+
if line.startswith("TCP:"):
|
|
60
|
+
line_q.put(line.strip())
|
|
61
|
+
return
|
|
62
|
+
|
|
63
|
+
reader = threading.Thread(target=_read_line, daemon=True)
|
|
64
|
+
reader.start()
|
|
65
|
+
try:
|
|
66
|
+
discovery = line_q.get(timeout=30)
|
|
67
|
+
except queue.Empty:
|
|
68
|
+
proc.terminate()
|
|
69
|
+
raise TimeoutError("worker did not emit a TCP: discovery line within 30s") from None
|
|
70
|
+
|
|
71
|
+
_, host, port_str = discovery.split(":", 2)
|
|
72
|
+
try:
|
|
73
|
+
yield host, int(port_str)
|
|
74
|
+
finally:
|
|
75
|
+
proc.terminate()
|
|
76
|
+
try:
|
|
77
|
+
proc.wait(timeout=10)
|
|
78
|
+
except subprocess.TimeoutExpired:
|
|
79
|
+
proc.kill()
|
|
80
|
+
proc.wait(timeout=5)
|
|
81
|
+
stderr_thread.join(timeout=5)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def test_tcp_round_trip_table_function() -> None:
|
|
85
|
+
"""A table function streams rows correctly over the TCP transport."""
|
|
86
|
+
with run_tcp_worker() as (host, port), Client.from_tcp(host, port) as client:
|
|
87
|
+
batches = list(
|
|
88
|
+
client.table_function(
|
|
89
|
+
function_name="sequence",
|
|
90
|
+
arguments=Arguments(positional=(pa.scalar(5),)),
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
table = pa.Table.from_batches(batches)
|
|
95
|
+
assert table.column("n").to_pylist() == [0, 1, 2, 3, 4]
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def test_tcp_round_trip_catalog_listing() -> None:
|
|
99
|
+
"""Catalog discovery works over the TCP transport (catalog_mixin path)."""
|
|
100
|
+
with run_tcp_worker() as (host, port), Client.from_tcp(host, port) as client:
|
|
101
|
+
catalogs = client.catalogs()
|
|
102
|
+
|
|
103
|
+
assert any(c.name == "example" for c in catalogs)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class TestTcpConstructorValidation:
|
|
107
|
+
"""``transport='tcp'`` argument validation."""
|
|
108
|
+
|
|
109
|
+
def test_requires_host_and_port(self) -> None:
|
|
110
|
+
"""Tcp transport without host/port is rejected."""
|
|
111
|
+
with pytest.raises(ValueError, match="requires tcp_host and tcp_port"):
|
|
112
|
+
Client(transport="tcp", pool=None)
|
|
113
|
+
|
|
114
|
+
def test_rejects_server_path(self) -> None:
|
|
115
|
+
"""server_path is subprocess-only."""
|
|
116
|
+
with pytest.raises(ValueError, match="server_path is only meaningful"):
|
|
117
|
+
Client("some-worker", transport="tcp", tcp_host="127.0.0.1", tcp_port=1, pool=None)
|
|
118
|
+
|
|
119
|
+
def test_rejects_base_url(self) -> None:
|
|
120
|
+
"""base_url is http-only."""
|
|
121
|
+
with pytest.raises(ValueError, match="base_url is only meaningful"):
|
|
122
|
+
Client(transport="tcp", tcp_host="127.0.0.1", tcp_port=1, base_url="http://x", pool=None)
|
|
@@ -2250,7 +2250,7 @@ requires-dist = [
|
|
|
2250
2250
|
|
|
2251
2251
|
[[package]]
|
|
2252
2252
|
name = "vgi-python"
|
|
2253
|
-
version = "0.8.
|
|
2253
|
+
version = "0.8.7"
|
|
2254
2254
|
source = { editable = "." }
|
|
2255
2255
|
dependencies = [
|
|
2256
2256
|
{ name = "click" },
|
|
@@ -2360,7 +2360,7 @@ requires-dist = [
|
|
|
2360
2360
|
{ name = "vgi-python", extras = ["test-fixtures"], marker = "extra == 'test-fixtures-writable'" },
|
|
2361
2361
|
{ name = "vgi-python", extras = ["test-fixtures", "test-fixtures-writable", "http", "oauth", "otel", "sentry", "azure"], marker = "extra == 'dev'" },
|
|
2362
2362
|
{ name = "vgi-python", extras = ["transactor"], marker = "extra == 'test-fixtures-writable'" },
|
|
2363
|
-
{ name = "vgi-rpc", specifier = ">=0.
|
|
2363
|
+
{ name = "vgi-rpc", specifier = ">=0.21.0" },
|
|
2364
2364
|
{ name = "vgi-rpc", extras = ["conformance", "external", "http", "oauth", "otel", "sentry"], marker = "extra == 'dev'" },
|
|
2365
2365
|
{ name = "vgi-rpc", extras = ["http"], marker = "extra == 'http'" },
|
|
2366
2366
|
{ name = "vgi-rpc", extras = ["oauth"], marker = "extra == 'oauth'" },
|
|
@@ -2389,7 +2389,7 @@ docs = [
|
|
|
2389
2389
|
|
|
2390
2390
|
[[package]]
|
|
2391
2391
|
name = "vgi-rpc"
|
|
2392
|
-
version = "0.
|
|
2392
|
+
version = "0.21.0"
|
|
2393
2393
|
source = { registry = "https://pypi.org/simple" }
|
|
2394
2394
|
dependencies = [
|
|
2395
2395
|
{ name = "docstring-parser" },
|
|
@@ -2397,9 +2397,9 @@ dependencies = [
|
|
|
2397
2397
|
{ name = "pywin32", marker = "sys_platform == 'win32'" },
|
|
2398
2398
|
{ name = "tzdata", marker = "sys_platform == 'win32'" },
|
|
2399
2399
|
]
|
|
2400
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
2400
|
+
sdist = { url = "https://files.pythonhosted.org/packages/3d/7b/0de17f5f638414188829f8bb4952e9a6116145ad402512ead8d0f035b705/vgi_rpc-0.21.0.tar.gz", hash = "sha256:c82c17149c0977080184d4728bdebe38aebcd1374984f6c81a3ce39be0aca367", size = 857916, upload-time = "2026-06-26T00:05:14.045Z" }
|
|
2401
2401
|
wheels = [
|
|
2402
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2402
|
+
{ url = "https://files.pythonhosted.org/packages/40/71/1607a7b093e2477d64a0193d21ec9b9fdfe8bc09f0165ce378fc214ef0a9/vgi_rpc-0.21.0-py3-none-any.whl", hash = "sha256:5e5b1ef8585f459eb0761c9232a6e4eeedef69be7b61ead61e0993f4a15b8698", size = 378442, upload-time = "2026-06-26T00:05:11.821Z" },
|
|
2403
2403
|
]
|
|
2404
2404
|
|
|
2405
2405
|
[package.optional-dependencies]
|
|
@@ -90,12 +90,14 @@ class CatalogClientMixin:
|
|
|
90
90
|
Catalog methods spawn ephemeral connections under the hood — for
|
|
91
91
|
subprocess transport a pooled subprocess worker; for HTTP transport a
|
|
92
92
|
short-lived ``http_connect`` session reusing the ``Client``'s shared
|
|
93
|
-
``httpx.Client`` (bearer token, headers)
|
|
94
|
-
|
|
93
|
+
``httpx.Client`` (bearer token, headers); for TCP transport a short-lived
|
|
94
|
+
``tcp_connect`` session. Browsing catalogs over HTTP is the canonical
|
|
95
|
+
non-DuckDB use case this mixin supports.
|
|
95
96
|
|
|
96
|
-
Other attributes expected from ``Client``: ``_transport`` (subprocess
|
|
97
|
-
http), ``_base_url`` (HTTP base URL),
|
|
98
|
-
(shared HTTP client
|
|
97
|
+
Other attributes expected from ``Client``: ``_transport`` (subprocess,
|
|
98
|
+
http, or tcp), ``_base_url`` (HTTP base URL), ``_tcp_host`` / ``_tcp_port``
|
|
99
|
+
(TCP endpoint), and ``_get_or_create_httpx_client()`` (shared HTTP client
|
|
100
|
+
factory).
|
|
99
101
|
|
|
100
102
|
Attributes:
|
|
101
103
|
server_path: Worker shell command used for subprocess transport.
|
|
@@ -103,8 +105,10 @@ class CatalogClientMixin:
|
|
|
103
105
|
|
|
104
106
|
# Type hints for attributes expected from Client
|
|
105
107
|
server_path: str
|
|
106
|
-
_transport: Literal["subprocess", "http"]
|
|
108
|
+
_transport: Literal["subprocess", "http", "tcp"]
|
|
107
109
|
_base_url: str | None
|
|
110
|
+
_tcp_host: str | None
|
|
111
|
+
_tcp_port: int | None
|
|
108
112
|
_external_location: Any | None
|
|
109
113
|
|
|
110
114
|
def _get_or_create_httpx_client(self) -> Any: # implemented by Client
|
|
@@ -128,7 +132,8 @@ class CatalogClientMixin:
|
|
|
128
132
|
A typed `[`VgiProtocol`][]` proxy bound to the active transport.
|
|
129
133
|
"""
|
|
130
134
|
try:
|
|
131
|
-
|
|
135
|
+
transport = getattr(self, "_transport", "subprocess")
|
|
136
|
+
if transport == "http":
|
|
132
137
|
from vgi_rpc.http import http_connect
|
|
133
138
|
|
|
134
139
|
httpx_client = self._get_or_create_httpx_client()
|
|
@@ -139,6 +144,17 @@ class CatalogClientMixin:
|
|
|
139
144
|
external_location=getattr(self, "_external_location", None),
|
|
140
145
|
) as proxy:
|
|
141
146
|
yield proxy
|
|
147
|
+
elif transport == "tcp":
|
|
148
|
+
from vgi_rpc.rpc import tcp_connect
|
|
149
|
+
|
|
150
|
+
assert self._tcp_host is not None and self._tcp_port is not None
|
|
151
|
+
with tcp_connect(
|
|
152
|
+
VgiProtocol, # type: ignore[type-abstract]
|
|
153
|
+
self._tcp_host,
|
|
154
|
+
self._tcp_port,
|
|
155
|
+
external_location=getattr(self, "_external_location", None),
|
|
156
|
+
) as proxy:
|
|
157
|
+
yield proxy
|
|
142
158
|
else:
|
|
143
159
|
cmd = shlex.split(self.server_path, posix=sys.platform != "win32")
|
|
144
160
|
with _catalog_pool.connect(VgiProtocol, cmd) as proxy: # type: ignore[type-abstract]
|
|
@@ -197,10 +197,10 @@ _HTTP_TRANSPORT_READY = True
|
|
|
197
197
|
|
|
198
198
|
@dataclass
|
|
199
199
|
class WorkerConnection:
|
|
200
|
-
"""Holds state for a single worker connection (subprocess or
|
|
200
|
+
"""Holds state for a single worker connection (subprocess, HTTP, or TCP).
|
|
201
201
|
|
|
202
|
-
Exactly one of {proc+connection, _pool_ctx, _http_ctx} is active
|
|
203
|
-
connection — transport-specific teardown inspects these fields.
|
|
202
|
+
Exactly one of {proc+connection, _pool_ctx, _http_ctx, _tcp_ctx} is active
|
|
203
|
+
per connection — transport-specific teardown inspects these fields.
|
|
204
204
|
|
|
205
205
|
Attributes:
|
|
206
206
|
proxy: The typed `[`VgiProtocol`][]` proxy used to invoke the worker.
|
|
@@ -220,6 +220,8 @@ class WorkerConnection:
|
|
|
220
220
|
_pool_ctx: AbstractContextManager[Any] | None = field(default=None, repr=False)
|
|
221
221
|
# HTTP transport: context manager from vgi_rpc.http.http_connect.
|
|
222
222
|
_http_ctx: AbstractContextManager[Any] | None = field(default=None, repr=False)
|
|
223
|
+
# TCP transport: context manager from vgi_rpc.rpc.tcp_connect.
|
|
224
|
+
_tcp_ctx: AbstractContextManager[Any] | None = field(default=None, repr=False)
|
|
223
225
|
|
|
224
226
|
|
|
225
227
|
class Client(CatalogClientMixin):
|
|
@@ -381,8 +383,10 @@ class Client(CatalogClientMixin):
|
|
|
381
383
|
attach_opaque_data: bytes | None = None,
|
|
382
384
|
pool: WorkerPool | None = _default_pool,
|
|
383
385
|
*,
|
|
384
|
-
transport: Literal["subprocess", "http"] = "subprocess",
|
|
386
|
+
transport: Literal["subprocess", "http", "tcp"] = "subprocess",
|
|
385
387
|
base_url: str | None = None,
|
|
388
|
+
tcp_host: str | None = None,
|
|
389
|
+
tcp_port: int | None = None,
|
|
386
390
|
bearer_token: str | None = None,
|
|
387
391
|
httpx_client: Any | None = None,
|
|
388
392
|
external_location: Any | None = None,
|
|
@@ -413,9 +417,14 @@ class Client(CatalogClientMixin):
|
|
|
413
417
|
management.
|
|
414
418
|
transport: Which transport to use. ``"subprocess"`` (default)
|
|
415
419
|
spawns a local subprocess per worker; ``"http"`` connects to
|
|
416
|
-
a running worker via ``vgi_rpc.http.http_connect
|
|
420
|
+
a running worker via ``vgi_rpc.http.http_connect``; ``"tcp"``
|
|
421
|
+
connects to a running worker via ``vgi_rpc.rpc.tcp_connect``
|
|
422
|
+
(raw Arrow-IPC framing, no auth/encryption — loopback /
|
|
423
|
+
trusted networks only; use ``Client.from_tcp(...)``).
|
|
417
424
|
base_url: HTTP-only. Base URL of the running worker, e.g.
|
|
418
425
|
``"http://127.0.0.1:8765"``.
|
|
426
|
+
tcp_host: TCP-only. Hostname or IP of the running worker.
|
|
427
|
+
tcp_port: TCP-only. Port of the running worker.
|
|
419
428
|
bearer_token: HTTP-only. When set, every request carries an
|
|
420
429
|
``Authorization: Bearer <token>`` header. Static token
|
|
421
430
|
support only — no JWT / OAuth flows.
|
|
@@ -446,12 +455,21 @@ class Client(CatalogClientMixin):
|
|
|
446
455
|
raise ValueError("transport='http' requires base_url")
|
|
447
456
|
if server_path is not None:
|
|
448
457
|
raise ValueError("server_path is only meaningful for transport='subprocess'")
|
|
458
|
+
elif transport == "tcp":
|
|
459
|
+
if tcp_host is None or tcp_port is None:
|
|
460
|
+
raise ValueError("transport='tcp' requires tcp_host and tcp_port")
|
|
461
|
+
if server_path is not None:
|
|
462
|
+
raise ValueError("server_path is only meaningful for transport='subprocess'")
|
|
463
|
+
if base_url is not None:
|
|
464
|
+
raise ValueError("base_url is only meaningful for transport='http'")
|
|
449
465
|
else:
|
|
450
466
|
raise ValueError(f"unknown transport {transport!r}")
|
|
451
467
|
|
|
452
468
|
self.server_path = server_path or ""
|
|
453
469
|
self._transport = transport
|
|
454
470
|
self._base_url = base_url
|
|
471
|
+
self._tcp_host = tcp_host
|
|
472
|
+
self._tcp_port = tcp_port
|
|
455
473
|
self._bearer_token = bearer_token
|
|
456
474
|
self._httpx_client = httpx_client
|
|
457
475
|
# True when ``_get_or_create_httpx_client`` constructed the client and
|
|
@@ -460,7 +478,7 @@ class Client(CatalogClientMixin):
|
|
|
460
478
|
self._httpx_client_owned = False
|
|
461
479
|
# Auto-enable pointer-batch resolution for HTTP unless the caller
|
|
462
480
|
# asked for something different. See ``external_location`` docs above.
|
|
463
|
-
if transport
|
|
481
|
+
if transport in ("http", "tcp") and external_location is None:
|
|
464
482
|
from vgi_rpc.external import ExternalLocationConfig
|
|
465
483
|
|
|
466
484
|
external_location = ExternalLocationConfig()
|
|
@@ -509,6 +527,34 @@ class Client(CatalogClientMixin):
|
|
|
509
527
|
pool=None,
|
|
510
528
|
)
|
|
511
529
|
|
|
530
|
+
@classmethod
|
|
531
|
+
def from_tcp(
|
|
532
|
+
cls,
|
|
533
|
+
host: str,
|
|
534
|
+
port: int,
|
|
535
|
+
*,
|
|
536
|
+
external_location: Any | None = None,
|
|
537
|
+
worker_limit: int | None = None,
|
|
538
|
+
attach_opaque_data: bytes | None = None,
|
|
539
|
+
) -> Client:
|
|
540
|
+
"""Create a `[`Client`][]` bound to a running TCP VGI worker.
|
|
541
|
+
|
|
542
|
+
Connects via ``vgi_rpc.rpc.tcp_connect`` (raw Arrow-IPC framing). The
|
|
543
|
+
framing carries **no authentication or encryption** — only connect to
|
|
544
|
+
trusted endpoints on loopback or a trusted network; use
|
|
545
|
+
``Client.from_http(...)`` for untrusted networks. Spin up a matching
|
|
546
|
+
worker with ``vgi-fixture-worker --tcp [HOST:]PORT``.
|
|
547
|
+
"""
|
|
548
|
+
return cls(
|
|
549
|
+
transport="tcp",
|
|
550
|
+
tcp_host=host,
|
|
551
|
+
tcp_port=port,
|
|
552
|
+
external_location=external_location,
|
|
553
|
+
worker_limit=worker_limit,
|
|
554
|
+
attach_opaque_data=attach_opaque_data,
|
|
555
|
+
pool=None,
|
|
556
|
+
)
|
|
557
|
+
|
|
512
558
|
def _drain_stderr(self, stderr: IO[bytes]) -> None:
|
|
513
559
|
"""Background thread that continuously reads stderr.
|
|
514
560
|
|
|
@@ -577,8 +623,40 @@ class Client(CatalogClientMixin):
|
|
|
577
623
|
"""
|
|
578
624
|
if self._transport == "http":
|
|
579
625
|
return self._spawn_http_connection(worker_index)
|
|
626
|
+
if self._transport == "tcp":
|
|
627
|
+
return self._spawn_tcp_connection(worker_index)
|
|
580
628
|
return self._spawn_subprocess_connection(worker_index)
|
|
581
629
|
|
|
630
|
+
def _spawn_tcp_connection(self, worker_index: int) -> WorkerConnection:
|
|
631
|
+
"""Connect to a running TCP worker via ``vgi_rpc.rpc.tcp_connect``.
|
|
632
|
+
|
|
633
|
+
Raw Arrow-IPC framing with no auth/encryption — see ``from_tcp``.
|
|
634
|
+
Multiple ``worker_index`` values open independent TCP connections to
|
|
635
|
+
the same ``host:port``.
|
|
636
|
+
"""
|
|
637
|
+
from vgi_rpc.rpc import tcp_connect
|
|
638
|
+
|
|
639
|
+
assert self._tcp_host is not None and self._tcp_port is not None # enforced in __init__
|
|
640
|
+
ctx: AbstractContextManager[VgiProtocol] = tcp_connect(
|
|
641
|
+
VgiProtocol, # type: ignore[type-abstract]
|
|
642
|
+
self._tcp_host,
|
|
643
|
+
self._tcp_port,
|
|
644
|
+
on_log=self._on_worker_log,
|
|
645
|
+
external_location=self._external_location,
|
|
646
|
+
)
|
|
647
|
+
proxy = ctx.__enter__()
|
|
648
|
+
_logger.debug(
|
|
649
|
+
"tcp_connection_opened worker_index=%s host=%s port=%s",
|
|
650
|
+
worker_index,
|
|
651
|
+
self._tcp_host,
|
|
652
|
+
self._tcp_port,
|
|
653
|
+
)
|
|
654
|
+
return WorkerConnection(
|
|
655
|
+
proxy=proxy,
|
|
656
|
+
worker_index=worker_index,
|
|
657
|
+
_tcp_ctx=ctx,
|
|
658
|
+
)
|
|
659
|
+
|
|
582
660
|
def _spawn_http_connection(self, worker_index: int) -> WorkerConnection:
|
|
583
661
|
"""Connect to a remote HTTP worker via ``vgi_rpc.http.http_connect``.
|
|
584
662
|
|
|
@@ -724,6 +802,12 @@ class Client(CatalogClientMixin):
|
|
|
724
802
|
_logger.debug("http_connection_closed worker_index=%s", worker.worker_index)
|
|
725
803
|
return 0
|
|
726
804
|
|
|
805
|
+
if worker._tcp_ctx is not None:
|
|
806
|
+
# TCP transport — close the RPC proxy (and its socket).
|
|
807
|
+
worker._tcp_ctx.__exit__(None, None, None)
|
|
808
|
+
_logger.debug("tcp_connection_closed worker_index=%s", worker.worker_index)
|
|
809
|
+
return 0
|
|
810
|
+
|
|
727
811
|
if worker._pool_ctx is not None:
|
|
728
812
|
# Return to pool — pool handles subprocess lifecycle
|
|
729
813
|
worker._pool_ctx.__exit__(None, None, None)
|
|
@@ -805,6 +889,8 @@ class Client(CatalogClientMixin):
|
|
|
805
889
|
id_repr: Any = self._primary.proc.pid
|
|
806
890
|
elif self._primary._http_ctx is not None:
|
|
807
891
|
id_repr = f"http({self._base_url})"
|
|
892
|
+
elif self._primary._tcp_ctx is not None:
|
|
893
|
+
id_repr = f"tcp({self._tcp_host}:{self._tcp_port})"
|
|
808
894
|
else:
|
|
809
895
|
id_repr = "pooled"
|
|
810
896
|
_logger.debug("server_started id=%s", id_repr)
|
|
@@ -1276,10 +1276,25 @@ class Worker:
|
|
|
1276
1276
|
"--unix",
|
|
1277
1277
|
help="Bind to this AF_UNIX socket path instead of stdin/stdout (mutex with --http).",
|
|
1278
1278
|
),
|
|
1279
|
+
# TCP launcher contract — mutually exclusive with --http/--unix.
|
|
1280
|
+
# Accepts ``[HOST:]PORT``; host defaults to loopback (127.0.0.1)
|
|
1281
|
+
# and ``PORT`` may be 0 to auto-select a free port. After binding
|
|
1282
|
+
# the worker prints TCP:<host>:<port> to stdout and self-shuts-down
|
|
1283
|
+
# after --idle-timeout seconds with zero connected clients. The raw
|
|
1284
|
+
# framing carries no auth/encryption — bind loopback only; use
|
|
1285
|
+
# --http for untrusted networks.
|
|
1286
|
+
tcp: str | None = typer.Option(
|
|
1287
|
+
None,
|
|
1288
|
+
"--tcp",
|
|
1289
|
+
help=(
|
|
1290
|
+
"Bind a TCP socket ([HOST:]PORT, host defaults to 127.0.0.1, PORT 0 "
|
|
1291
|
+
"auto-selects) instead of stdin/stdout (mutex with --http/--unix)."
|
|
1292
|
+
),
|
|
1293
|
+
),
|
|
1279
1294
|
idle_timeout: float = typer.Option(
|
|
1280
1295
|
300.0,
|
|
1281
1296
|
"--idle-timeout",
|
|
1282
|
-
help="Self-shutdown after N seconds idle when serving --unix.",
|
|
1297
|
+
help="Self-shutdown after N seconds idle when serving --unix/--tcp.",
|
|
1283
1298
|
),
|
|
1284
1299
|
http_threads: int | None = typer.Option( # noqa: B008
|
|
1285
1300
|
None,
|
|
@@ -1300,8 +1315,8 @@ class Worker:
|
|
|
1300
1315
|
log_format=log_format,
|
|
1301
1316
|
)
|
|
1302
1317
|
|
|
1303
|
-
if http
|
|
1304
|
-
raise typer.BadParameter("--http and --
|
|
1318
|
+
if sum(x for x in (http, unix is not None, tcp is not None)) > 1:
|
|
1319
|
+
raise typer.BadParameter("--http, --unix, and --tcp are mutually exclusive")
|
|
1305
1320
|
|
|
1306
1321
|
if http:
|
|
1307
1322
|
from vgi.serve import (
|
|
@@ -1358,6 +1373,47 @@ class Worker:
|
|
|
1358
1373
|
idle_timeout=effective_idle,
|
|
1359
1374
|
on_bound=_emit,
|
|
1360
1375
|
)
|
|
1376
|
+
elif tcp is not None:
|
|
1377
|
+
# TCP launcher path. Bind to [HOST:]PORT, print
|
|
1378
|
+
# TCP:<host>:<port> on stdout (mirrors run_server's
|
|
1379
|
+
# cross-language discovery contract), idle-shutdown after
|
|
1380
|
+
# idle_timeout seconds.
|
|
1381
|
+
from vgi_rpc.rpc import serve_tcp
|
|
1382
|
+
|
|
1383
|
+
from vgi.serve import _maybe_init_sentry, _resolve_otel_config
|
|
1384
|
+
|
|
1385
|
+
if ":" in tcp:
|
|
1386
|
+
host_part, _, port_part = tcp.rpartition(":")
|
|
1387
|
+
tcp_host = host_part or "127.0.0.1"
|
|
1388
|
+
else:
|
|
1389
|
+
tcp_host, port_part = "127.0.0.1", tcp
|
|
1390
|
+
try:
|
|
1391
|
+
tcp_port = int(port_part)
|
|
1392
|
+
except ValueError:
|
|
1393
|
+
raise typer.BadParameter(f"--tcp expects [HOST:]PORT, got {tcp!r}") from None
|
|
1394
|
+
|
|
1395
|
+
_maybe_init_sentry()
|
|
1396
|
+
otel_config = _resolve_otel_config()
|
|
1397
|
+
worker = cls(quiet=quiet, log_level=effective_level)
|
|
1398
|
+
server = RpcServer(cls.protocol_class, worker, server_version=_get_vgi_version())
|
|
1399
|
+
if otel_config is not None:
|
|
1400
|
+
from vgi_rpc.otel import instrument_server
|
|
1401
|
+
|
|
1402
|
+
instrument_server(server, otel_config)
|
|
1403
|
+
worker._vgi_tracer = VgiTracer.create(otel_config)
|
|
1404
|
+
effective_idle = idle_timeout if idle_timeout > 0 else None
|
|
1405
|
+
|
|
1406
|
+
def _emit_tcp(bound_host: str, bound_port: int) -> None:
|
|
1407
|
+
print(f"TCP:{bound_host}:{bound_port}", flush=True)
|
|
1408
|
+
|
|
1409
|
+
serve_tcp(
|
|
1410
|
+
server,
|
|
1411
|
+
tcp_host,
|
|
1412
|
+
tcp_port,
|
|
1413
|
+
threaded=True,
|
|
1414
|
+
idle_timeout=effective_idle,
|
|
1415
|
+
on_bound=_emit_tcp,
|
|
1416
|
+
)
|
|
1361
1417
|
else:
|
|
1362
1418
|
from vgi.serve import _maybe_init_sentry, _resolve_otel_config
|
|
1363
1419
|
|
|
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
|