vgi-python 0.29.3__tar.gz → 0.29.4__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.
Files changed (440) hide show
  1. {vgi_python-0.29.3 → vgi_python-0.29.4}/PKG-INFO +6 -3
  2. {vgi_python-0.29.3 → vgi_python-0.29.4}/pyproject.toml +9 -4
  3. vgi_python-0.29.4/tests/test_launch_transport.py +114 -0
  4. {vgi_python-0.29.3 → vgi_python-0.29.4}/uv.lock +27 -9
  5. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/client/catalog_mixin.py +31 -4
  6. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/client/client.py +150 -8
  7. {vgi_python-0.29.3 → vgi_python-0.29.4}/.gitattributes +0 -0
  8. {vgi_python-0.29.3 → vgi_python-0.29.4}/.github/dependabot.yml +0 -0
  9. {vgi_python-0.29.3 → vgi_python-0.29.4}/.github/styles/config/vocabularies/VGI/accept.txt +0 -0
  10. {vgi_python-0.29.3 → vgi_python-0.29.4}/.github/workflows/ci.yml +0 -0
  11. {vgi_python-0.29.3 → vgi_python-0.29.4}/.github/workflows/docs.yml +0 -0
  12. {vgi_python-0.29.3 → vgi_python-0.29.4}/.github/workflows/integration.yml +0 -0
  13. {vgi_python-0.29.3 → vgi_python-0.29.4}/.github/workflows/release.yml +0 -0
  14. {vgi_python-0.29.3 → vgi_python-0.29.4}/.gitignore +0 -0
  15. {vgi_python-0.29.3 → vgi_python-0.29.4}/.python-version +0 -0
  16. {vgi_python-0.29.3 → vgi_python-0.29.4}/.vale.ini +0 -0
  17. {vgi_python-0.29.3 → vgi_python-0.29.4}/CLAUDE.md +0 -0
  18. {vgi_python-0.29.3 → vgi_python-0.29.4}/DOCS_ACCEPTANCE_CRITERIA.md +0 -0
  19. {vgi_python-0.29.3 → vgi_python-0.29.4}/DOCS_REVIEW_RUBRIC.md +0 -0
  20. {vgi_python-0.29.3 → vgi_python-0.29.4}/DOCS_USABILITY_TEST.md +0 -0
  21. {vgi_python-0.29.3 → vgi_python-0.29.4}/LICENSE +0 -0
  22. {vgi_python-0.29.3 → vgi_python-0.29.4}/README.md +0 -0
  23. {vgi_python-0.29.3 → vgi_python-0.29.4}/RELEASE-RUNBOOK.md +0 -0
  24. {vgi_python-0.29.3 → vgi_python-0.29.4}/SECURITY.md +0 -0
  25. {vgi_python-0.29.3 → vgi_python-0.29.4}/ci/README.md +0 -0
  26. {vgi_python-0.29.3 → vgi_python-0.29.4}/ci/preprocess-require.awk +0 -0
  27. {vgi_python-0.29.3 → vgi_python-0.29.4}/ci/run-integration.sh +0 -0
  28. {vgi_python-0.29.3 → vgi_python-0.29.4}/dist-vgi/.gitignore +0 -0
  29. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/aggregate-functions.md +0 -0
  30. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/api/arguments.md +0 -0
  31. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/api/auth.md +0 -0
  32. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/api/catalogs.md +0 -0
  33. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/api/client.md +0 -0
  34. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/api/exceptions.md +0 -0
  35. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/api/filters.md +0 -0
  36. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/api/functions.md +0 -0
  37. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/api/http.md +0 -0
  38. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/api/index.md +0 -0
  39. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/api/metadata.md +0 -0
  40. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/api/observability.md +0 -0
  41. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/api/storage.md +0 -0
  42. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/api/transactor.md +0 -0
  43. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/api/worker.md +0 -0
  44. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/argument-serialization.md +0 -0
  45. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/assets/apple-touch-icon.png +0 -0
  46. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/assets/favicon-16x16.png +0 -0
  47. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/assets/favicon-32x32.png +0 -0
  48. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/assets/favicon.ico +0 -0
  49. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/assets/kinds/aggregate.svg +0 -0
  50. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/assets/kinds/buffering.svg +0 -0
  51. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/assets/kinds/scalar.svg +0 -0
  52. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/assets/kinds/table-in-out.svg +0 -0
  53. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/assets/kinds/table.svg +0 -0
  54. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/assets/logo.png +0 -0
  55. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/assets/social-card.png +0 -0
  56. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/authentication.md +0 -0
  57. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/catalog-interface.md +0 -0
  58. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/cli.md +0 -0
  59. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/column-statistics.md +0 -0
  60. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/concepts/index.md +0 -0
  61. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/contributing-docs.md +0 -0
  62. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/filter-pushdown.md +0 -0
  63. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/generator-api.md +0 -0
  64. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/global-functions.md +0 -0
  65. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/how-to/catalogs.md +0 -0
  66. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/how-to/function-patterns.md +0 -0
  67. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/how-to/http-auth.md +0 -0
  68. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/how-to/index.md +0 -0
  69. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/how-to/pushdown-and-statistics.md +0 -0
  70. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/how-to/state-storage.md +0 -0
  71. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/index.md +0 -0
  72. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/lifecycle.md +0 -0
  73. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/metadata.md +0 -0
  74. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/overrides/main.html +0 -0
  75. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/robots.txt +0 -0
  76. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/shared-storage.md +0 -0
  77. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/stylesheets/extra.css +0 -0
  78. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/tutorial/index.md +0 -0
  79. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/tutorial/scalar.md +0 -0
  80. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/tutorial/table.md +0 -0
  81. {vgi_python-0.29.3 → vgi_python-0.29.4}/docs/vgi-logo.png +0 -0
  82. {vgi_python-0.29.3 → vgi_python-0.29.4}/examples/batch_index_worker.py +0 -0
  83. {vgi_python-0.29.3 → vgi_python-0.29.4}/examples/cache_worker.py +0 -0
  84. {vgi_python-0.29.3 → vgi_python-0.29.4}/examples/calc_scalar_worker.py +0 -0
  85. {vgi_python-0.29.3 → vgi_python-0.29.4}/examples/calc_worker.py +0 -0
  86. {vgi_python-0.29.3 → vgi_python-0.29.4}/examples/copy_format_worker.py +0 -0
  87. {vgi_python-0.29.3 → vgi_python-0.29.4}/examples/filter_worker.py +0 -0
  88. {vgi_python-0.29.3 → vgi_python-0.29.4}/examples/greeting_scalar_worker.py +0 -0
  89. {vgi_python-0.29.3 → vgi_python-0.29.4}/examples/row_count_worker.py +0 -0
  90. {vgi_python-0.29.3 → vgi_python-0.29.4}/examples/series_streaming_worker.py +0 -0
  91. {vgi_python-0.29.3 → vgi_python-0.29.4}/examples/sum_worker.py +0 -0
  92. {vgi_python-0.29.3 → vgi_python-0.29.4}/mkdocs.yml +0 -0
  93. {vgi_python-0.29.3 → vgi_python-0.29.4}/packages/vgi-fixtures/LICENSE +0 -0
  94. {vgi_python-0.29.3 → vgi_python-0.29.4}/packages/vgi-fixtures/README.md +0 -0
  95. {vgi_python-0.29.3 → vgi_python-0.29.4}/packages/vgi-fixtures/docker/Dockerfile +0 -0
  96. {vgi_python-0.29.3 → vgi_python-0.29.4}/packages/vgi-fixtures/docker/docker-entrypoint.sh +0 -0
  97. {vgi_python-0.29.3 → vgi_python-0.29.4}/packages/vgi-fixtures/pyproject.toml +0 -0
  98. {vgi_python-0.29.3 → vgi_python-0.29.4}/scripts/measure_startup.py +0 -0
  99. {vgi_python-0.29.3 → vgi_python-0.29.4}/scripts/run_all_tests.sh +0 -0
  100. {vgi_python-0.29.3 → vgi_python-0.29.4}/test-data/generate.sh +0 -0
  101. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/__init__.py +0 -0
  102. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/_http_fixtures.py +0 -0
  103. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/catalog/__init__.py +0 -0
  104. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/catalog/test_attach_option.py +0 -0
  105. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/catalog/test_catalog_interface.py +0 -0
  106. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/catalog/test_client_catalog.py +0 -0
  107. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/catalog/test_column_statistics.py +0 -0
  108. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/catalog/test_declarative.py +0 -0
  109. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/catalog/test_example_worker_catalog.py +0 -0
  110. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/catalog/test_integration.py +0 -0
  111. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/catalog/test_required_filters.py +0 -0
  112. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/catalog/test_scan_branches.py +0 -0
  113. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/catalog/test_serialization.py +0 -0
  114. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/catalog/test_setting.py +0 -0
  115. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/catalog/test_storage.py +0 -0
  116. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/catalog/test_time_travel.py +0 -0
  117. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/catalog/test_writable_table.py +0 -0
  118. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/client/__init__.py +0 -0
  119. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/client/test_aggregate_client.py +0 -0
  120. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/client/test_batch_metadata_callback.py +0 -0
  121. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/client/test_broken_pipe.py +0 -0
  122. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/client/test_cli.py +0 -0
  123. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/client/test_cli_catalog_functions.py +0 -0
  124. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/client/test_copy_client.py +0 -0
  125. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/client/test_scan_branches_client.py +0 -0
  126. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/client/test_split_client.py +0 -0
  127. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/client/test_stop_force.py +0 -0
  128. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/client/test_table_column_statistics.py +0 -0
  129. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/client/test_time_travel_client.py +0 -0
  130. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/client/test_worker_debug.py +0 -0
  131. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/__init__.py +0 -0
  132. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/_stub.py +0 -0
  133. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/conftest.py +0 -0
  134. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_accumulate.py +0 -0
  135. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_aggregate.py +0 -0
  136. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_attach.py +0 -0
  137. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_bearer_auth.py +0 -0
  138. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_const_param_enforcement.py +0 -0
  139. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_container.py +0 -0
  140. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_copy_from.py +0 -0
  141. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_copy_to.py +0 -0
  142. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_directory_parity.py +0 -0
  143. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_function_inventory.py +0 -0
  144. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_github.py +0 -0
  145. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_http_client.py +0 -0
  146. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_http_external_location.py +0 -0
  147. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_http_upload_url.py +0 -0
  148. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_macro.py +0 -0
  149. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_overload.py +0 -0
  150. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_protocol_inventory.py +0 -0
  151. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_protocol_version.py +0 -0
  152. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_resumable_scan.py +0 -0
  153. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_scalar.py +0 -0
  154. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_scalar_attach_opaque_data.py +0 -0
  155. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_secret.py +0 -0
  156. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_settings.py +0 -0
  157. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_splits.py +0 -0
  158. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_table.py +0 -0
  159. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_table_in_out.py +0 -0
  160. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_view.py +0 -0
  161. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conformance/test_writable.py +0 -0
  162. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/conftest.py +0 -0
  163. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/data/split_tokens/anchor_len_overrun.bin +0 -0
  164. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/data/split_tokens/bad_fingerprint.bin +0 -0
  165. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/data/split_tokens/bad_flags_unsealed_but_key_present.bin +0 -0
  166. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/data/split_tokens/bad_version.bin +0 -0
  167. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/data/split_tokens/generate.py +0 -0
  168. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/data/split_tokens/manifest.json +0 -0
  169. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/data/split_tokens/reserved_flag_bit.bin +0 -0
  170. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/data/split_tokens/stale_anchor.bin +0 -0
  171. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/data/split_tokens/truncated.bin +0 -0
  172. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/data/split_tokens/valid_sealed.bin +0 -0
  173. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/data/split_tokens/valid_unsealed.bin +0 -0
  174. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/scalar/__init__.py +0 -0
  175. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/scalar/test_bernoulli_function.py +0 -0
  176. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/scalar/test_binary_packet_function.py +0 -0
  177. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/scalar/test_client.py +0 -0
  178. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/scalar/test_conditional_message_function.py +0 -0
  179. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/scalar/test_hash_seed_function.py +0 -0
  180. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/scalar/test_multiply_by_setting_function.py +0 -0
  181. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/scalar/test_multiply_function.py +0 -0
  182. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/scalar/test_random_bytes_function.py +0 -0
  183. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/scalar/test_return_secret_value_function.py +0 -0
  184. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table/__init__.py +0 -0
  185. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table/generator/__init__.py +0 -0
  186. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table/generator/test_constant_columns_function.py +0 -0
  187. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table/generator/test_double_sequence_function.py +0 -0
  188. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table/generator/test_exception_function.py +0 -0
  189. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table/generator/test_filter_echo_function.py +0 -0
  190. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table/generator/test_logging_function.py +0 -0
  191. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table/generator/test_nested_sequence_function.py +0 -0
  192. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table/generator/test_partitioned_function.py +0 -0
  193. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table/generator/test_projected_data_function.py +0 -0
  194. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table/generator/test_sequence_function.py +0 -0
  195. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table/generator/test_settings_function.py +0 -0
  196. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table/generator/test_struct_settings_function.py +0 -0
  197. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table/generator/test_ten_thousand_function.py +0 -0
  198. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table/test_wide_columns.py +0 -0
  199. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table_in_out/__init__.py +0 -0
  200. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table_in_out/generator/__init__.py +0 -0
  201. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table_in_out/generator/test_buffer_input_function.py +0 -0
  202. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table_in_out/generator/test_echo_function.py +0 -0
  203. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table_in_out/generator/test_exception_functions.py +0 -0
  204. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table_in_out/generator/test_filter_by_setting_function.py +0 -0
  205. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table_in_out/generator/test_repeat_inputs_function.py +0 -0
  206. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table_in_out/generator/test_substream_partial_sum_function.py +0 -0
  207. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table_in_out/generator/test_sum_all_columns_function.py +0 -0
  208. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table_in_out/test_blended_metadata.py +0 -0
  209. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/table_in_out/test_client.py +0 -0
  210. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_access_log_audit.py +0 -0
  211. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_aggregate_function.py +0 -0
  212. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_argument_spec.py +0 -0
  213. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_auth.py +0 -0
  214. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_bind_exceptions.py +0 -0
  215. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_bind_request_at_clause.py +0 -0
  216. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_bound_storage_conformance.py +0 -0
  217. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_cache_control.py +0 -0
  218. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_call_state_attach.py +0 -0
  219. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_catalog_auth_binding.py +0 -0
  220. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_copy_from_function.py +0 -0
  221. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_copy_to_function.py +0 -0
  222. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_docstrings.py +0 -0
  223. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_documentation_examples.py +0 -0
  224. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_example_function_arg_types.py +0 -0
  225. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_examples_workers.py +0 -0
  226. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_exception_handling.py +0 -0
  227. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_exceptions.py +0 -0
  228. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_filter_pushdown.py +0 -0
  229. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_filter_pushdown_extension.py +0 -0
  230. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_fixture_catalog_parity.py +0 -0
  231. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_function_storage.py +0 -0
  232. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_function_storage_azure_sql.py +0 -0
  233. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_function_storage_cf_do.py +0 -0
  234. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_function_storage_cf_do_integration.py +0 -0
  235. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_function_storage_conformance.py +0 -0
  236. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_generated_cpp_constants.py +0 -0
  237. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_generated_cpp_protocol_version.py +0 -0
  238. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_generated_cpp_request_builders.py +0 -0
  239. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_generated_cpp_schemas.py +0 -0
  240. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_generated_cpp_secret.py +0 -0
  241. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_generated_go_schemas.py +0 -0
  242. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_generated_java_schemas.py +0 -0
  243. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_generated_protocol_version.py +0 -0
  244. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_generated_rust_request_builders.py +0 -0
  245. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_generated_rust_schemas.py +0 -0
  246. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_generated_schemas_cross_lang.py +0 -0
  247. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_generated_ts_client.py +0 -0
  248. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_generated_ts_schemas.py +0 -0
  249. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_http_demo_storage.py +0 -0
  250. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_http_s3_offload_input.py +0 -0
  251. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_http_s3_offload_output.py +0 -0
  252. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_metadata.py +0 -0
  253. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_mypy_consolidated.py +0 -0
  254. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_nest_tensor.py +0 -0
  255. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_otel.py +0 -0
  256. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_projection_enforcement.py +0 -0
  257. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_projection_repro.py +0 -0
  258. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_protocol_classes.py +0 -0
  259. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_resolved_secrets.py +0 -0
  260. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_schema_scoped_functions.py +0 -0
  261. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_schema_utils.py +0 -0
  262. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_serve.py +0 -0
  263. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_setting_secret_annotations.py +0 -0
  264. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_signing_key.py +0 -0
  265. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_split_token.py +0 -0
  266. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_table_buffering_function.py +0 -0
  267. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_table_function_dynamic_to_string.py +0 -0
  268. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_tcp_transport.py +0 -0
  269. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_type_bounds.py +0 -0
  270. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_union_argument.py +0 -0
  271. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_wire_record_schema_parity.py +0 -0
  272. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_worker.py +0 -0
  273. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_worker_cli.py +0 -0
  274. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/test_worker_page.py +0 -0
  275. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/transactor/__init__.py +0 -0
  276. {vgi_python-0.29.3 → vgi_python-0.29.4}/tests/transactor/test_transactor.py +0 -0
  277. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/__init__.py +0 -0
  278. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_duckdb.py +0 -0
  279. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_storage_profile.py +0 -0
  280. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/__init__.py +0 -0
  281. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/accumulate/__init__.py +0 -0
  282. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/accumulate/worker.py +0 -0
  283. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/__init__.py +0 -0
  284. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/_common.py +0 -0
  285. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/basic.py +0 -0
  286. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/dynamic.py +0 -0
  287. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/generic.py +0 -0
  288. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/listagg.py +0 -0
  289. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/percentile.py +0 -0
  290. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/same_name.py +0 -0
  291. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/secret_typed.py +0 -0
  292. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/streaming.py +0 -0
  293. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/varargs.py +0 -0
  294. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/aggregate/window.py +0 -0
  295. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/attach_options.py +0 -0
  296. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/bad_enum.py +0 -0
  297. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/bad_protocol.py +0 -0
  298. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/cancellable.py +0 -0
  299. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/catalog.py +0 -0
  300. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/companion.py +0 -0
  301. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/copy_from.py +0 -0
  302. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/copy_to.py +0 -0
  303. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/global_functions.py +0 -0
  304. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/http_server.py +0 -0
  305. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/narrow_bind/__init__.py +0 -0
  306. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/narrow_bind/worker.py +0 -0
  307. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/nest_tensor.py +0 -0
  308. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/orchard_catalog.py +0 -0
  309. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/projection_repro/__init__.py +0 -0
  310. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/projection_repro/worker.py +0 -0
  311. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/__init__.py +0 -0
  312. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/_common.py +0 -0
  313. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/arithmetic.py +0 -0
  314. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/bench_ladder.py +0 -0
  315. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/binary.py +0 -0
  316. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/formatting.py +0 -0
  317. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/geo.py +0 -0
  318. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/null_handling.py +0 -0
  319. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/random_demo.py +0 -0
  320. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/same_name.py +0 -0
  321. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/settings_secrets.py +0 -0
  322. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/scalar/type_info.py +0 -0
  323. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/schema_reconcile/__init__.py +0 -0
  324. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/schema_reconcile/worker.py +0 -0
  325. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/simple_writable.py +0 -0
  326. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/__init__.py +0 -0
  327. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/_common.py +0 -0
  328. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/batch_index.py +0 -0
  329. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/batch_index_broken.py +0 -0
  330. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/cache.py +0 -0
  331. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/catalog_scans.py +0 -0
  332. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/filters.py +0 -0
  333. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/late_materialization.py +0 -0
  334. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/make_series.py +0 -0
  335. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/misc.py +0 -0
  336. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/order_modes.py +0 -0
  337. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/pairs.py +0 -0
  338. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/partition_columns.py +0 -0
  339. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/partition_columns_broken.py +0 -0
  340. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/profiling_example.py +0 -0
  341. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/required_filters.py +0 -0
  342. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/same_name_cached.py +0 -0
  343. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/sequence.py +0 -0
  344. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/settings.py +0 -0
  345. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/splits.py +0 -0
  346. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/transaction_storage.py +0 -0
  347. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/tt_pushdown.py +0 -0
  348. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/typed_probe.py +0 -0
  349. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/versioned.py +0 -0
  350. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table/wide.py +0 -0
  351. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table_in_out.py +0 -0
  352. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/table_in_out_same_name.py +0 -0
  353. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/twin_catalogs.py +0 -0
  354. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/versioned.py +0 -0
  355. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/versioned_tables.py +0 -0
  356. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/worker.py +0 -0
  357. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/writable/__init__.py +0 -0
  358. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/writable/generic.py +0 -0
  359. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/writable/table.py +0 -0
  360. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/_test_fixtures/writable/worker.py +0 -0
  361. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/aggregate_function.py +0 -0
  362. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/argument_spec.py +0 -0
  363. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/arguments.py +0 -0
  364. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/attach_header.py +0 -0
  365. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/auth.py +0 -0
  366. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/cache_control.py +0 -0
  367. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/catalog/__init__.py +0 -0
  368. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/catalog/_descriptor_spec.py +0 -0
  369. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/catalog/attach_option.py +0 -0
  370. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/catalog/catalog_interface.py +0 -0
  371. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/catalog/descriptors.py +0 -0
  372. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/catalog/duckdb_statistics.py +0 -0
  373. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/catalog/secret_type.py +0 -0
  374. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/catalog/setting.py +0 -0
  375. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/catalog/storage.py +0 -0
  376. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/client/__init__.py +0 -0
  377. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/client/aggregate.py +0 -0
  378. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/client/cli.py +0 -0
  379. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/client/cli_catalog.py +0 -0
  380. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/client/cli_schema.py +0 -0
  381. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/client/cli_table.py +0 -0
  382. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/client/cli_transaction.py +0 -0
  383. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/client/cli_utils.py +0 -0
  384. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/client/cli_view.py +0 -0
  385. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/client/errors.py +0 -0
  386. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/codegen/__init__.py +0 -0
  387. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/codegen/_common.py +0 -0
  388. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/codegen/cpp_constants.py +0 -0
  389. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/codegen/cpp_protocol_version.py +0 -0
  390. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/codegen/cpp_request_builders.py +0 -0
  391. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/codegen/cpp_schemas.py +0 -0
  392. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/codegen/cpp_secret_protocol_version.py +0 -0
  393. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/codegen/cpp_secret_request_builders.py +0 -0
  394. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/codegen/cpp_secret_schemas.py +0 -0
  395. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/codegen/go_schemas.py +0 -0
  396. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/codegen/java_schemas.py +0 -0
  397. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/codegen/protocol_version.py +0 -0
  398. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/codegen/rust_request_builders.py +0 -0
  399. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/codegen/rust_schemas.py +0 -0
  400. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/codegen/ts_client.py +0 -0
  401. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/codegen/ts_schemas.py +0 -0
  402. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/copy_from_function.py +0 -0
  403. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/copy_to_function.py +0 -0
  404. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/exceptions.py +0 -0
  405. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/function.py +0 -0
  406. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/function_storage.py +0 -0
  407. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/function_storage_azure_sql.py +0 -0
  408. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/function_storage_cf_do.py +0 -0
  409. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/http/__init__.py +0 -0
  410. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/http/demo_storage.py +0 -0
  411. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/http/landing.html +0 -0
  412. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/http/landing_page.py +0 -0
  413. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/http/vgi-client.js +0 -0
  414. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/http/worker_page.py +0 -0
  415. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/invocation.py +0 -0
  416. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/logging_config.py +0 -0
  417. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/meta_worker.py +0 -0
  418. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/metadata.py +0 -0
  419. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/otel.py +0 -0
  420. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/profiling.py +0 -0
  421. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/protocol.py +0 -0
  422. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/protocol_version.txt +0 -0
  423. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/py.typed +0 -0
  424. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/scalar_function.py +0 -0
  425. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/schema_utils.py +0 -0
  426. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/secret_protocol.py +0 -0
  427. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/secret_service.py +0 -0
  428. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/serve.py +0 -0
  429. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/split_token.py +0 -0
  430. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/table_buffering_function.py +0 -0
  431. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/table_filter_pushdown.py +0 -0
  432. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/table_function.py +0 -0
  433. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/table_in_out_function.py +0 -0
  434. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/transactor/__init__.py +0 -0
  435. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/transactor/_duckdb_compat.py +0 -0
  436. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/transactor/client.py +0 -0
  437. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/transactor/protocol.py +0 -0
  438. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/transactor/server.py +0 -0
  439. {vgi_python-0.29.3 → vgi_python-0.29.4}/vgi/worker.py +0 -0
  440. {vgi_python-0.29.3 → vgi_python-0.29.4}/wrangler.jsonc +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: vgi-python
3
- Version: 0.29.3
3
+ Version: 0.29.4
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: httpx2>=2.9.1
162
162
  Requires-Dist: platformdirs
163
163
  Requires-Dist: pyarrow
164
164
  Requires-Dist: typer>=0.9
165
- Requires-Dist: vgi-rpc>=0.43.0
165
+ Requires-Dist: vgi-rpc>=0.43.2
166
166
  Provides-Extra: azure
167
167
  Requires-Dist: azure-identity>=1.16.0; extra == 'azure'
168
168
  Requires-Dist: pymssql>=2.3.0; extra == 'azure'
@@ -181,7 +181,8 @@ Requires-Dist: pytest-ruff; extra == 'dev'
181
181
  Requires-Dist: pytest-xdist; extra == 'dev'
182
182
  Requires-Dist: ruff; extra == 'dev'
183
183
  Requires-Dist: sqlglot; extra == 'dev'
184
- Requires-Dist: vgi-rpc[conformance,external,http,oauth,otel,sentry]; extra == 'dev'
184
+ Requires-Dist: vgi-rpc[cli,conformance,external,http,oauth,otel,sentry]; extra == 'dev'
185
+ Requires-Dist: vgi-rpc[cli]; extra == 'dev'
185
186
  Requires-Dist: vgi-rpc[http]; extra == 'dev'
186
187
  Requires-Dist: vgi-rpc[oauth]; extra == 'dev'
187
188
  Requires-Dist: vgi-rpc[otel]; extra == 'dev'
@@ -197,6 +198,8 @@ Provides-Extra: haybarn
197
198
  Requires-Dist: haybarn>=1.5.5rc1; extra == 'haybarn'
198
199
  Provides-Extra: http
199
200
  Requires-Dist: vgi-rpc[http]; extra == 'http'
201
+ Provides-Extra: launch
202
+ Requires-Dist: vgi-rpc[cli]; extra == 'launch'
200
203
  Provides-Extra: oauth
201
204
  Requires-Dist: vgi-rpc[oauth]; extra == 'oauth'
202
205
  Provides-Extra: otel
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "vgi-python"
3
- version = "0.29.3"
3
+ version = "0.29.4"
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.0",
43
+ "vgi-rpc>=0.43.2",
44
44
  "httpx2>=2.9.1",
45
45
  ]
46
46
 
@@ -52,6 +52,11 @@ dependencies = [
52
52
  haybarn = ["haybarn>=1.5.5rc1"]
53
53
  duckdb = ["duckdb>=1.5.3"]
54
54
  http = ["vgi-rpc[http]"]
55
+ # transport="launch": vgi_rpc.launcher imports filelock unconditionally at
56
+ # module level, which lives behind vgi-rpc's own `cli` extra (alongside
57
+ # typer, already a core dependency here, and httpx2, ditto) rather than in
58
+ # vgi-rpc's core dependency set.
59
+ launch = ["vgi-rpc[cli]"]
55
60
  # Alternative HTTP server: granian moves socket I/O and HTTP parsing into Rust,
56
61
  # off the GIL. Optional because it is a compiled extension where waitress is
57
62
  # pure Python; select it with `vgi-serve --http --server granian`.
@@ -93,8 +98,8 @@ dev = [
93
98
  "pytest-ruff",
94
99
  "pytest-xdist",
95
100
  "ruff",
96
- "vgi-python[test-fixtures,test-fixtures-writable,http,oauth,otel,sentry,azure]",
97
- "vgi-rpc[conformance,external,http,oauth,otel,sentry]",
101
+ "vgi-python[test-fixtures,test-fixtures-writable,http,launch,oauth,otel,sentry,azure]",
102
+ "vgi-rpc[cli,conformance,external,http,oauth,otel,sentry]",
98
103
  ]
99
104
  [project.scripts]
100
105
  vgi-serve = "vgi.serve:main"
@@ -0,0 +1,114 @@
1
+ # Copyright 2025, 2026 Query Farm LLC - https://query.farm
2
+
3
+ """Round-trip tests for the launcher-managed (``transport="launch"``) transport.
4
+
5
+ Drives ``vgi._test_fixtures.worker`` (the same fixture module ``test_tcp_transport.py``
6
+ uses) through ``Client.from_launch(...)`` — no separate fixture worker needed, since
7
+ ``MetaWorker.serve`` already passes argv through to ``vgi_rpc.rpc.run_server()``, which
8
+ participates in the AF_UNIX launcher path (``--unix PATH --idle-timeout SEC``) the same
9
+ way it participates in the TCP path (``--tcp HOST:PORT``).
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import shutil
15
+ import sys
16
+ import tempfile
17
+ import uuid
18
+ from collections.abc import Iterator
19
+ from pathlib import Path
20
+
21
+ import pyarrow as pa
22
+ import pytest
23
+ from vgi_rpc.launcher import status_rows
24
+
25
+ from vgi.arguments import Arguments
26
+ from vgi.client import Client
27
+
28
+ _WORKER_ARGV = (sys.executable, "-m", "vgi._test_fixtures.worker")
29
+
30
+
31
+ @pytest.fixture
32
+ def state_dir() -> Iterator[str]:
33
+ """Per-test state dir under ``/tmp`` to stay under macOS's 104-byte AF_UNIX limit.
34
+
35
+ Mirrors ``vgi-rpc``'s own ``test_launcher.py`` fixture — ``tmp_path`` resolves to a
36
+ deeply nested path that, concatenated with ``<hash>.sock``, blows past the cap.
37
+ """
38
+ d = Path(tempfile.gettempdir()) / f"vgi-launch-test-{uuid.uuid4().hex[:8]}"
39
+ d.mkdir(mode=0o700)
40
+ try:
41
+ yield str(d)
42
+ finally:
43
+ shutil.rmtree(d, ignore_errors=True)
44
+
45
+
46
+ def test_launch_round_trip_table_function(state_dir: str) -> None:
47
+ """A table function streams rows correctly over the launch transport."""
48
+ with Client.from_launch(_WORKER_ARGV, idle_timeout=10.0, state_dir=state_dir) as client:
49
+ batches = list(
50
+ client.table_function(
51
+ function_name="sequence",
52
+ schema_name="main",
53
+ arguments=Arguments(positional=(pa.scalar(5),)),
54
+ )
55
+ )
56
+
57
+ table = pa.Table.from_batches(batches)
58
+ assert table.column("n").to_pylist() == [0, 1, 2, 3, 4]
59
+
60
+
61
+ def test_launch_round_trip_catalog_listing(state_dir: str) -> None:
62
+ """Catalog discovery works over the launch transport (catalog_mixin path)."""
63
+ with Client.from_launch(_WORKER_ARGV, idle_timeout=10.0, state_dir=state_dir) as client:
64
+ catalogs = client.catalogs()
65
+
66
+ assert any(c.name == "example" for c in catalogs)
67
+
68
+
69
+ def test_launch_shares_one_worker_across_clients(state_dir: str) -> None:
70
+ """Two `Client`s with the same worker_argv + state_dir share one warm worker.
71
+
72
+ The whole point of the launcher over plain subprocess/TCP: a second client
73
+ pointing at the same command must reuse the first client's worker rather than
74
+ spawning its own. Proven by checking exactly one tracked worker exists in the
75
+ shared state dir after both clients have connected, not by any client-visible
76
+ process identity (the client has no API for that, by design — it shouldn't need
77
+ to know or care).
78
+ """
79
+ with Client.from_launch(_WORKER_ARGV, idle_timeout=10.0, state_dir=state_dir) as client_a:
80
+ assert client_a.catalogs()
81
+ with Client.from_launch(_WORKER_ARGV, idle_timeout=10.0, state_dir=state_dir) as client_b:
82
+ assert client_b.catalogs()
83
+ rows = status_rows(Path(state_dir))
84
+ assert len(rows) == 1, f"expected exactly one shared worker, found {len(rows)}: {rows}"
85
+ assert rows[0].alive
86
+
87
+
88
+ class TestLaunchConstructorValidation:
89
+ """``transport='launch'`` argument validation."""
90
+
91
+ def test_requires_launch_argv(self) -> None:
92
+ """Launch transport without launch_argv is rejected."""
93
+ with pytest.raises(ValueError, match="requires a non-empty launch_argv"):
94
+ Client(transport="launch", pool=None)
95
+
96
+ def test_rejects_empty_launch_argv(self) -> None:
97
+ """An explicitly empty launch_argv is rejected the same as omitting it."""
98
+ with pytest.raises(ValueError, match="requires a non-empty launch_argv"):
99
+ Client(transport="launch", launch_argv=(), pool=None)
100
+
101
+ def test_rejects_server_path(self) -> None:
102
+ """server_path is subprocess-only."""
103
+ with pytest.raises(ValueError, match="server_path is only meaningful"):
104
+ Client("some-worker", transport="launch", launch_argv=("x",), pool=None)
105
+
106
+ def test_rejects_base_url(self) -> None:
107
+ """base_url is http-only."""
108
+ with pytest.raises(ValueError, match="base_url is only meaningful"):
109
+ Client(transport="launch", launch_argv=("x",), base_url="http://x", pool=None)
110
+
111
+ def test_rejects_tcp_host_and_port(self) -> None:
112
+ """tcp_host/tcp_port are tcp-only."""
113
+ with pytest.raises(ValueError, match="tcp_host/tcp_port are only meaningful"):
114
+ Client(transport="launch", launch_argv=("x",), tcp_host="127.0.0.1", tcp_port=1, pool=None)
@@ -714,6 +714,15 @@ wheels = [
714
714
  { url = "https://files.pythonhosted.org/packages/da/ef/5790e74a7b39d2c085554f347be22a1882649a29a7a65e9c81bfaf9e8fc6/falcon-4.3.1-py3-none-any.whl", hash = "sha256:5402602d14bc426afc01c388538f2ad402ac4c8c2477415dfe972a2deee17248", size = 332719, upload-time = "2026-06-16T05:31:23.373Z" },
715
715
  ]
716
716
 
717
+ [[package]]
718
+ name = "filelock"
719
+ version = "3.32.4"
720
+ source = { registry = "https://pypi.org/simple" }
721
+ sdist = { url = "https://files.pythonhosted.org/packages/6d/30/03b03951873a1a0ffc7e8ca0e10c15597b59e8d0e39260704cd2ea087bc4/filelock-3.32.4.tar.gz", hash = "sha256:2bde2e4cf732e0153406d8a7bc80620ecf5e621fe0d25e41143c4e3b4733ff30", size = 222126, upload-time = "2026-08-23T17:37:55.363Z" }
722
+ wheels = [
723
+ { url = "https://files.pythonhosted.org/packages/01/a4/9b63d595d748e3aff8812b65eacc1a2c4bd90b7c2012e08e72373b4835eb/filelock-3.32.4-py3-none-any.whl", hash = "sha256:22e58ca3b1ae3b98993b762d7338367ae64fe50252bf78d59da3bfebcdf1cedd", size = 99864, upload-time = "2026-08-23T17:37:53.913Z" },
724
+ ]
725
+
717
726
  [[package]]
718
727
  name = "frozenlist"
719
728
  version = "1.8.0"
@@ -2560,7 +2569,7 @@ requires-dist = [
2560
2569
 
2561
2570
  [[package]]
2562
2571
  name = "vgi-python"
2563
- version = "0.29.2"
2572
+ version = "0.29.4"
2564
2573
  source = { editable = "." }
2565
2574
  dependencies = [
2566
2575
  { name = "click" },
@@ -2591,7 +2600,7 @@ dev = [
2591
2600
  { name = "pytest-xdist" },
2592
2601
  { name = "ruff" },
2593
2602
  { name = "sqlglot" },
2594
- { name = "vgi-rpc", extra = ["conformance", "external", "http", "oauth", "otel", "sentry"] },
2603
+ { name = "vgi-rpc", extra = ["cli", "conformance", "external", "http", "oauth", "otel", "sentry"] },
2595
2604
  ]
2596
2605
  duckdb = [
2597
2606
  { name = "duckdb" },
@@ -2609,6 +2618,9 @@ haybarn = [
2609
2618
  http = [
2610
2619
  { name = "vgi-rpc", extra = ["http"] },
2611
2620
  ]
2621
+ launch = [
2622
+ { name = "vgi-rpc", extra = ["cli"] },
2623
+ ]
2612
2624
  oauth = [
2613
2625
  { name = "vgi-rpc", extra = ["oauth"] },
2614
2626
  ]
@@ -2672,17 +2684,18 @@ requires-dist = [
2672
2684
  { name = "typer", specifier = ">=0.9" },
2673
2685
  { name = "vgi-fixtures", marker = "extra == 'fixtures'", editable = "packages/vgi-fixtures" },
2674
2686
  { name = "vgi-python", extras = ["test-fixtures"], marker = "extra == 'test-fixtures-writable'" },
2675
- { name = "vgi-python", extras = ["test-fixtures", "test-fixtures-writable", "http", "oauth", "otel", "sentry", "azure"], marker = "extra == 'dev'" },
2687
+ { name = "vgi-python", extras = ["test-fixtures", "test-fixtures-writable", "http", "launch", "oauth", "otel", "sentry", "azure"], marker = "extra == 'dev'" },
2676
2688
  { name = "vgi-python", extras = ["transactor"], marker = "extra == 'test-fixtures-writable'" },
2677
- { name = "vgi-rpc", specifier = ">=0.43.0" },
2678
- { name = "vgi-rpc", extras = ["conformance", "external", "http", "oauth", "otel", "sentry"], marker = "extra == 'dev'" },
2689
+ { name = "vgi-rpc", specifier = ">=0.43.2" },
2690
+ { name = "vgi-rpc", extras = ["cli"], marker = "extra == 'launch'" },
2691
+ { name = "vgi-rpc", extras = ["cli", "conformance", "external", "http", "oauth", "otel", "sentry"], marker = "extra == 'dev'" },
2679
2692
  { name = "vgi-rpc", extras = ["http"], marker = "extra == 'granian'" },
2680
2693
  { name = "vgi-rpc", extras = ["http"], marker = "extra == 'http'" },
2681
2694
  { name = "vgi-rpc", extras = ["oauth"], marker = "extra == 'oauth'" },
2682
2695
  { name = "vgi-rpc", extras = ["otel"], marker = "extra == 'otel'" },
2683
2696
  { name = "vgi-rpc", extras = ["sentry"], marker = "extra == 'sentry'" },
2684
2697
  ]
2685
- provides-extras = ["haybarn", "duckdb", "http", "granian", "oauth", "otel", "sentry", "azure", "test-fixtures", "transactor", "fixtures", "test-fixtures-writable", "dev"]
2698
+ provides-extras = ["haybarn", "duckdb", "http", "launch", "granian", "oauth", "otel", "sentry", "azure", "test-fixtures", "transactor", "fixtures", "test-fixtures-writable", "dev"]
2686
2699
 
2687
2700
  [package.metadata.requires-dev]
2688
2701
  dev = [
@@ -2703,7 +2716,7 @@ docs = [
2703
2716
 
2704
2717
  [[package]]
2705
2718
  name = "vgi-rpc"
2706
- version = "0.43.1"
2719
+ version = "0.43.2"
2707
2720
  source = { registry = "https://pypi.org/simple" }
2708
2721
  dependencies = [
2709
2722
  { name = "docstring-parser" },
@@ -2711,12 +2724,17 @@ dependencies = [
2711
2724
  { name = "pywin32", marker = "sys_platform == 'win32'" },
2712
2725
  { name = "tzdata", marker = "sys_platform == 'win32'" },
2713
2726
  ]
2714
- sdist = { url = "https://files.pythonhosted.org/packages/27/a0/b308cc62cde38fe2a7bc7a2c57bbb8e956084dd04134a4b0d805378daf16/vgi_rpc-0.43.1.tar.gz", hash = "sha256:d94a3c2cfcf90e1122b2b7ec23a47912f1b3e2d265267aa6704bd64c3a7f2a55", size = 1145519, upload-time = "2026-08-27T14:51:14.923Z" }
2727
+ sdist = { url = "https://files.pythonhosted.org/packages/ce/04/efb99f0fb56535bcba110e6c12448c31b429e0861aae4bc2f7136299cfc2/vgi_rpc-0.43.2.tar.gz", hash = "sha256:6a06437af17442451bfe07186bc472a2efb57e030b0e5b38a28922034a814123", size = 1147340, upload-time = "2026-08-27T18:33:54.608Z" }
2715
2728
  wheels = [
2716
- { url = "https://files.pythonhosted.org/packages/96/f2/15bd8a76ee3534c4d911b0f76c948378db4c175a40ceeb30325e6ab994a6/vgi_rpc-0.43.1-py3-none-any.whl", hash = "sha256:1eecd6c17f06d6fadae332be33998d22cdd01e5caaaae7889b747f0c1eaac498", size = 526753, upload-time = "2026-08-27T14:51:12.975Z" },
2729
+ { url = "https://files.pythonhosted.org/packages/ac/b9/33cdb4fe27ef3893e1cded63f396af8bc517e390615f34db6f4bd227ef4c/vgi_rpc-0.43.2-py3-none-any.whl", hash = "sha256:b112ab76828367176a41f1b9a4ceeaba8979629e4e5972f64bf769c94b3e36a4", size = 528134, upload-time = "2026-08-27T18:33:52.829Z" },
2717
2730
  ]
2718
2731
 
2719
2732
  [package.optional-dependencies]
2733
+ cli = [
2734
+ { name = "filelock" },
2735
+ { name = "httpx2" },
2736
+ { name = "typer" },
2737
+ ]
2720
2738
  conformance = [
2721
2739
  { name = "jsonschema" },
2722
2740
  { name = "psutil" },
@@ -100,9 +100,11 @@ class CatalogClientMixin:
100
100
  non-DuckDB use case this mixin supports.
101
101
 
102
102
  Other attributes expected from ``Client``: ``_transport`` (subprocess,
103
- http, or tcp), ``_base_url`` (HTTP base URL), ``_tcp_host`` / ``_tcp_port``
104
- (TCP endpoint), and ``_get_or_create_httpx_client()`` (shared HTTP client
105
- factory).
103
+ http, tcp, or launch), ``_base_url`` (HTTP base URL), ``_tcp_host`` /
104
+ ``_tcp_port`` (TCP endpoint), ``_launch_argv`` / ``_launch_idle_timeout`` /
105
+ ``_launch_state_dir`` / ``_launch_socket_path`` (launcher worker
106
+ identity + lifecycle), and ``_get_or_create_httpx_client()`` (shared
107
+ HTTP client factory).
106
108
 
107
109
  Attributes:
108
110
  server_path: Worker command used for subprocess transport — a string to
@@ -111,10 +113,14 @@ class CatalogClientMixin:
111
113
 
112
114
  # Type hints for attributes expected from Client
113
115
  server_path: str | Sequence[str]
114
- _transport: Literal["subprocess", "http", "tcp"]
116
+ _transport: Literal["subprocess", "http", "tcp", "launch"]
115
117
  _base_url: str | None
116
118
  _tcp_host: str | None
117
119
  _tcp_port: int | None
120
+ _launch_argv: tuple[str, ...] | None
121
+ _launch_idle_timeout: float
122
+ _launch_state_dir: str | None
123
+ _launch_socket_path: str | None
118
124
  _external_location: Any | None
119
125
 
120
126
  def _worker_argv(self) -> list[str]:
@@ -144,6 +150,11 @@ class CatalogClientMixin:
144
150
  ``Client._get_or_create_httpx_client`` so auth headers and
145
151
  connection pooling are consistent.
146
152
 
153
+ Launch: opens a short-lived ``resolve_and_connect`` session per call
154
+ against the launcher-managed shared worker — same warm-worker sharing
155
+ as exchange-mode calls (``Client._spawn_launch_connection``), just a
156
+ fresh connection to it per catalog RPC rather than one held open.
157
+
147
158
  Worker errors are caught and re-raised as ``CatalogClientError``.
148
159
 
149
160
  Yields:
@@ -173,6 +184,22 @@ class CatalogClientMixin:
173
184
  external_location=getattr(self, "_external_location", None),
174
185
  ) as proxy:
175
186
  yield proxy
187
+ elif transport == "launch":
188
+ from vgi_rpc.launcher import LaunchConfig, resolve_and_connect
189
+
190
+ assert self._launch_argv is not None
191
+ config = LaunchConfig(
192
+ worker_argv=self._launch_argv,
193
+ socket_path=self._launch_socket_path,
194
+ idle_timeout=self._launch_idle_timeout,
195
+ state_dir=self._launch_state_dir,
196
+ )
197
+ with resolve_and_connect(
198
+ VgiProtocol, # type: ignore[type-abstract]
199
+ config,
200
+ external_location=getattr(self, "_external_location", None),
201
+ ) as proxy:
202
+ yield proxy
176
203
  else:
177
204
  cmd = self._worker_argv()
178
205
  with _catalog_pool.connect(VgiProtocol, cmd) as proxy: # type: ignore[type-abstract]
@@ -184,10 +184,10 @@ _HTTP_TRANSPORT_READY = True
184
184
 
185
185
  @dataclass
186
186
  class WorkerConnection:
187
- """Holds state for a single worker connection (subprocess, HTTP, or TCP).
187
+ """Holds state for a single worker connection (subprocess, HTTP, TCP, or launch).
188
188
 
189
- Exactly one of {proc+connection, _pool_ctx, _http_ctx, _tcp_ctx} is active
190
- per connection — transport-specific teardown inspects these fields.
189
+ Exactly one of {proc+connection, _pool_ctx, _http_ctx, _tcp_ctx, _launch_ctx}
190
+ is active per connection — transport-specific teardown inspects these fields.
191
191
 
192
192
  Attributes:
193
193
  proxy: The typed `[`VgiProtocol`][]` proxy used to invoke the worker.
@@ -209,6 +209,8 @@ class WorkerConnection:
209
209
  _http_ctx: AbstractContextManager[Any] | None = field(default=None, repr=False)
210
210
  # TCP transport: context manager from vgi_rpc.rpc.tcp_connect.
211
211
  _tcp_ctx: AbstractContextManager[Any] | None = field(default=None, repr=False)
212
+ # Launch transport: context manager from vgi_rpc.launcher.resolve_and_connect.
213
+ _launch_ctx: AbstractContextManager[Any] | None = field(default=None, repr=False)
212
214
 
213
215
 
214
216
  class Client(CatalogClientMixin, AggregateClientMixin):
@@ -389,13 +391,17 @@ class Client(CatalogClientMixin, AggregateClientMixin):
389
391
  attach_opaque_data: bytes | None = None,
390
392
  pool: WorkerPool | None = _default_pool,
391
393
  *,
392
- transport: Literal["subprocess", "http", "tcp"] = "subprocess",
394
+ transport: Literal["subprocess", "http", "tcp", "launch"] = "subprocess",
393
395
  base_url: str | None = None,
394
396
  tcp_host: str | None = None,
395
397
  tcp_port: int | None = None,
396
398
  bearer_token: str | None = None,
397
399
  httpx_client: Any | None = None,
398
400
  external_location: Any | None = None,
401
+ launch_argv: Sequence[str] | None = None,
402
+ launch_idle_timeout: float = 300.0,
403
+ launch_state_dir: str | None = None,
404
+ launch_socket_path: str | None = None,
399
405
  ):
400
406
  """Initialize the VGI client.
401
407
 
@@ -430,7 +436,10 @@ class Client(CatalogClientMixin, AggregateClientMixin):
430
436
  a running worker via ``vgi_rpc.http.http_connect``; ``"tcp"``
431
437
  connects to a running worker via ``vgi_rpc.rpc.tcp_connect``
432
438
  (raw Arrow-IPC framing, no auth/encryption — loopback /
433
- trusted networks only; use ``Client.from_tcp(...)``).
439
+ trusted networks only; use ``Client.from_tcp(...)``); ``"launch"``
440
+ spawns-or-reuses a warm worker shared across every client
441
+ pointing at the same command, coordinated via
442
+ ``vgi_rpc.launcher`` (use ``Client.from_launch(...)``).
434
443
  base_url: HTTP-only. Base URL of the running worker, e.g.
435
444
  ``"http://127.0.0.1:8765"``.
436
445
  tcp_host: TCP-only. Hostname or IP of the running worker.
@@ -449,6 +458,20 @@ class Client(CatalogClientMixin, AggregateClientMixin):
449
458
  transport so pointer batches are resolved automatically.
450
459
  Subprocess transport ignores this — subprocess workers
451
460
  don't return pointer batches.
461
+ launch_argv: Launch-only. The worker command and arguments (an
462
+ argv sequence, not a shell string — matches
463
+ ``vgi_rpc.launcher.LaunchConfig.worker_argv``). Requires the
464
+ ``vgi-python[launch]`` extra (pulls in ``vgi-rpc[cli]`` for
465
+ ``filelock``, which ``vgi_rpc.launcher`` imports unconditionally).
466
+ launch_idle_timeout: Launch-only. The shared worker self-terminates
467
+ after this many idle seconds with zero connected clients.
468
+ Forwarded to ``LaunchConfig.idle_timeout``.
469
+ launch_state_dir: Launch-only. Override the launcher's default
470
+ per-user state directory (lockfiles + sockets). Forwarded to
471
+ ``LaunchConfig.state_dir``.
472
+ launch_socket_path: Launch-only. Explicit socket path, skipping
473
+ the hash-derived default. Forwarded to
474
+ ``LaunchConfig.socket_path``.
452
475
 
453
476
  Raises:
454
477
  ValueError: If the transport / server_path / base_url
@@ -472,6 +495,15 @@ class Client(CatalogClientMixin, AggregateClientMixin):
472
495
  raise ValueError("server_path is only meaningful for transport='subprocess'")
473
496
  if base_url is not None:
474
497
  raise ValueError("base_url is only meaningful for transport='http'")
498
+ elif transport == "launch":
499
+ if not launch_argv:
500
+ raise ValueError("transport='launch' requires a non-empty launch_argv")
501
+ if server_path is not None:
502
+ raise ValueError("server_path is only meaningful for transport='subprocess'")
503
+ if base_url is not None:
504
+ raise ValueError("base_url is only meaningful for transport='http'")
505
+ if tcp_host is not None or tcp_port is not None:
506
+ raise ValueError("tcp_host/tcp_port are only meaningful for transport='tcp'")
475
507
  else:
476
508
  raise ValueError(f"unknown transport {transport!r}")
477
509
 
@@ -482,13 +514,19 @@ class Client(CatalogClientMixin, AggregateClientMixin):
482
514
  self._tcp_port = tcp_port
483
515
  self._bearer_token = bearer_token
484
516
  self._httpx_client = httpx_client
517
+ self._launch_argv = tuple(launch_argv) if launch_argv is not None else None
518
+ self._launch_idle_timeout = launch_idle_timeout
519
+ self._launch_state_dir = launch_state_dir
520
+ self._launch_socket_path = launch_socket_path
485
521
  # True when ``_get_or_create_httpx_client`` constructed the client and
486
522
  # is therefore responsible for closing it on ``stop()``. False when
487
523
  # the caller passed ``httpx_client=`` — ownership stays with them.
488
524
  self._httpx_client_owned = False
489
- # Auto-enable pointer-batch resolution for HTTP unless the caller
490
- # asked for something different. See ``external_location`` docs above.
491
- if transport in ("http", "tcp") and external_location is None:
525
+ # Auto-enable pointer-batch resolution for HTTP/TCP/launch unless the
526
+ # caller asked for something different all three are ordinary RPC
527
+ # transports a worker can externalize batches over, unlike subprocess
528
+ # (which never returns pointer batches). See ``external_location`` docs above.
529
+ if transport in ("http", "tcp", "launch") and external_location is None:
492
530
  from vgi_rpc.external import ExternalLocationConfig
493
531
 
494
532
  external_location = ExternalLocationConfig()
@@ -565,6 +603,63 @@ class Client(CatalogClientMixin, AggregateClientMixin):
565
603
  pool=None,
566
604
  )
567
605
 
606
+ @classmethod
607
+ def from_launch(
608
+ cls,
609
+ worker_argv: Sequence[str],
610
+ *,
611
+ idle_timeout: float = 300.0,
612
+ state_dir: str | None = None,
613
+ socket_path: str | None = None,
614
+ external_location: Any | None = None,
615
+ worker_limit: int | None = None,
616
+ attach_opaque_data: bytes | None = None,
617
+ ) -> Client:
618
+ """Create a `[`Client`][]` bound to a launcher-managed warm worker.
619
+
620
+ Spawns (or reuses) a worker process serving over an ``AF_UNIX``
621
+ socket via ``vgi_rpc.launcher`` — every client across the machine
622
+ pointing at the same ``worker_argv`` shares one warm worker,
623
+ coordinated by a per-command-hash flock, and the worker
624
+ self-terminates after ``idle_timeout`` idle seconds with zero
625
+ connected clients. This is the Python client-side counterpart to the
626
+ VGI DuckDB extension's ``launch:<argv>`` LOCATION scheme. Requires
627
+ the ``vgi-python[launch]`` extra.
628
+
629
+ Args:
630
+ worker_argv: The worker command and arguments, as an argv
631
+ sequence — not a shell string, and not split with
632
+ ``shlex.split`` the way ``server_path`` is for
633
+ ``transport="subprocess"``.
634
+ idle_timeout: Shared worker self-shutdown after this many idle
635
+ seconds.
636
+ state_dir: Override the launcher's default per-user state
637
+ directory (lockfiles + sockets).
638
+ socket_path: Explicit socket path, skipping the hash-derived
639
+ default — every caller passing the same explicit path
640
+ shares that worker regardless of ``worker_argv`` differences.
641
+ external_location: Optional ``ExternalLocationConfig`` — see the
642
+ constructor's docstring.
643
+ worker_limit: Maximum number of parallel worker connections.
644
+ attach_opaque_data: Optional unique identifier for the DuckDB
645
+ database attachment.
646
+
647
+ Returns:
648
+ A `[`Client`][]` bound to the launcher-managed worker.
649
+
650
+ """
651
+ return cls(
652
+ transport="launch",
653
+ launch_argv=worker_argv,
654
+ launch_idle_timeout=idle_timeout,
655
+ launch_state_dir=state_dir,
656
+ launch_socket_path=socket_path,
657
+ external_location=external_location,
658
+ worker_limit=worker_limit,
659
+ attach_opaque_data=attach_opaque_data,
660
+ pool=None,
661
+ )
662
+
568
663
  def _drain_stderr(self, stderr: IO[bytes]) -> None:
569
664
  """Background thread that continuously reads stderr.
570
665
 
@@ -660,6 +755,8 @@ class Client(CatalogClientMixin, AggregateClientMixin):
660
755
  return self._spawn_http_connection(worker_index)
661
756
  if self._transport == "tcp":
662
757
  return self._spawn_tcp_connection(worker_index)
758
+ if self._transport == "launch":
759
+ return self._spawn_launch_connection(worker_index)
663
760
  return self._spawn_subprocess_connection(worker_index)
664
761
 
665
762
  def _spawn_tcp_connection(self, worker_index: int) -> WorkerConnection:
@@ -692,6 +789,41 @@ class Client(CatalogClientMixin, AggregateClientMixin):
692
789
  _tcp_ctx=ctx,
693
790
  )
694
791
 
792
+ def _spawn_launch_connection(self, worker_index: int) -> WorkerConnection:
793
+ """Connect to a launcher-managed worker via ``vgi_rpc.launcher.resolve_and_connect``.
794
+
795
+ Every ``Client`` (in this process or any other on the machine) built
796
+ with the same ``launch_argv`` shares one warm worker — see
797
+ ``from_launch``. Multiple ``worker_index`` values open independent
798
+ connections to that same shared worker.
799
+ """
800
+ from vgi_rpc.launcher import LaunchConfig, resolve_and_connect
801
+
802
+ assert self._launch_argv is not None # enforced in __init__
803
+ config = LaunchConfig(
804
+ worker_argv=self._launch_argv,
805
+ socket_path=self._launch_socket_path,
806
+ idle_timeout=self._launch_idle_timeout,
807
+ state_dir=self._launch_state_dir,
808
+ )
809
+ ctx: AbstractContextManager[VgiProtocol] = resolve_and_connect(
810
+ VgiProtocol, # type: ignore[type-abstract]
811
+ config,
812
+ on_log=self._on_worker_log,
813
+ external_location=self._external_location,
814
+ )
815
+ proxy = ctx.__enter__()
816
+ _logger.debug(
817
+ "launch_connection_opened worker_index=%s argv=%s",
818
+ worker_index,
819
+ self._launch_argv,
820
+ )
821
+ return WorkerConnection(
822
+ proxy=proxy,
823
+ worker_index=worker_index,
824
+ _launch_ctx=ctx,
825
+ )
826
+
695
827
  def _spawn_http_connection(self, worker_index: int) -> WorkerConnection:
696
828
  """Connect to a remote HTTP worker via ``vgi_rpc.http.http_connect``.
697
829
 
@@ -863,6 +995,14 @@ class Client(CatalogClientMixin, AggregateClientMixin):
863
995
  _logger.debug("tcp_connection_closed worker_index=%s", worker.worker_index)
864
996
  return 0
865
997
 
998
+ if worker._launch_ctx is not None:
999
+ # Launch transport — close the RPC proxy (and its socket). The
1000
+ # shared worker process itself is untouched: it lives on for other
1001
+ # clients and self-terminates via its own idle timer.
1002
+ worker._launch_ctx.__exit__(None, None, None)
1003
+ _logger.debug("launch_connection_closed worker_index=%s", worker.worker_index)
1004
+ return 0
1005
+
866
1006
  if worker._pool_ctx is not None:
867
1007
  # Return to pool — pool handles subprocess lifecycle
868
1008
  worker._pool_ctx.__exit__(None, None, None)
@@ -979,6 +1119,8 @@ class Client(CatalogClientMixin, AggregateClientMixin):
979
1119
  id_repr = f"http({self._base_url})"
980
1120
  elif self._primary._tcp_ctx is not None:
981
1121
  id_repr = f"tcp({self._tcp_host}:{self._tcp_port})"
1122
+ elif self._primary._launch_ctx is not None:
1123
+ id_repr = f"launch({' '.join(self._launch_argv or ())})"
982
1124
  else:
983
1125
  id_repr = "pooled"
984
1126
  _logger.debug("server_started id=%s", id_repr)
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