vgi-python 0.8.5__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.
Files changed (362) hide show
  1. {vgi_python-0.8.5 → vgi_python-0.8.7}/PKG-INFO +2 -2
  2. {vgi_python-0.8.5 → vgi_python-0.8.7}/pyproject.toml +2 -2
  3. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/catalog/test_serialization.py +134 -0
  4. vgi_python-0.8.7/tests/test_tcp_transport.py +122 -0
  5. {vgi_python-0.8.5 → vgi_python-0.8.7}/uv.lock +5 -5
  6. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/catalog.py +2 -0
  7. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/worker.py +10 -0
  8. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/argument_spec.py +82 -0
  9. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/catalog/catalog_interface.py +28 -1
  10. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/catalog/descriptors.py +20 -1
  11. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/client/catalog_mixin.py +29 -7
  12. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/client/client.py +92 -6
  13. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/codegen/go_schemas.py +10 -4
  14. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/protocol.py +8 -0
  15. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/worker.py +60 -3
  16. {vgi_python-0.8.5 → vgi_python-0.8.7}/.gitattributes +0 -0
  17. {vgi_python-0.8.5 → vgi_python-0.8.7}/.github/dependabot.yml +0 -0
  18. {vgi_python-0.8.5 → vgi_python-0.8.7}/.github/styles/config/vocabularies/VGI/accept.txt +0 -0
  19. {vgi_python-0.8.5 → vgi_python-0.8.7}/.github/workflows/ci.yml +0 -0
  20. {vgi_python-0.8.5 → vgi_python-0.8.7}/.github/workflows/docs.yml +0 -0
  21. {vgi_python-0.8.5 → vgi_python-0.8.7}/.github/workflows/integration.yml +0 -0
  22. {vgi_python-0.8.5 → vgi_python-0.8.7}/.github/workflows/release.yml +0 -0
  23. {vgi_python-0.8.5 → vgi_python-0.8.7}/.gitignore +0 -0
  24. {vgi_python-0.8.5 → vgi_python-0.8.7}/.python-version +0 -0
  25. {vgi_python-0.8.5 → vgi_python-0.8.7}/.vale.ini +0 -0
  26. {vgi_python-0.8.5 → vgi_python-0.8.7}/CLAUDE.md +0 -0
  27. {vgi_python-0.8.5 → vgi_python-0.8.7}/DOCS_ACCEPTANCE_CRITERIA.md +0 -0
  28. {vgi_python-0.8.5 → vgi_python-0.8.7}/DOCS_REVIEW_RUBRIC.md +0 -0
  29. {vgi_python-0.8.5 → vgi_python-0.8.7}/DOCS_USABILITY_TEST.md +0 -0
  30. {vgi_python-0.8.5 → vgi_python-0.8.7}/LICENSE +0 -0
  31. {vgi_python-0.8.5 → vgi_python-0.8.7}/README.md +0 -0
  32. {vgi_python-0.8.5 → vgi_python-0.8.7}/SECURITY.md +0 -0
  33. {vgi_python-0.8.5 → vgi_python-0.8.7}/ci/README.md +0 -0
  34. {vgi_python-0.8.5 → vgi_python-0.8.7}/ci/preprocess-require.awk +0 -0
  35. {vgi_python-0.8.5 → vgi_python-0.8.7}/ci/run-integration.sh +0 -0
  36. {vgi_python-0.8.5 → vgi_python-0.8.7}/dist-vgi/.gitignore +0 -0
  37. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/aggregate-functions.md +0 -0
  38. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/api/arguments.md +0 -0
  39. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/api/auth.md +0 -0
  40. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/api/catalogs.md +0 -0
  41. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/api/client.md +0 -0
  42. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/api/exceptions.md +0 -0
  43. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/api/filters.md +0 -0
  44. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/api/functions.md +0 -0
  45. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/api/http.md +0 -0
  46. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/api/index.md +0 -0
  47. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/api/metadata.md +0 -0
  48. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/api/observability.md +0 -0
  49. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/api/storage.md +0 -0
  50. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/api/transactor.md +0 -0
  51. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/api/worker.md +0 -0
  52. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/argument-serialization.md +0 -0
  53. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/assets/apple-touch-icon.png +0 -0
  54. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/assets/favicon-16x16.png +0 -0
  55. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/assets/favicon-32x32.png +0 -0
  56. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/assets/favicon.ico +0 -0
  57. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/assets/kinds/aggregate.svg +0 -0
  58. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/assets/kinds/buffering.svg +0 -0
  59. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/assets/kinds/scalar.svg +0 -0
  60. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/assets/kinds/table-in-out.svg +0 -0
  61. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/assets/kinds/table.svg +0 -0
  62. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/assets/logo.png +0 -0
  63. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/assets/social-card.png +0 -0
  64. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/authentication.md +0 -0
  65. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/catalog-interface.md +0 -0
  66. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/cli.md +0 -0
  67. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/column-statistics.md +0 -0
  68. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/concepts/index.md +0 -0
  69. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/contributing-docs.md +0 -0
  70. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/filter-pushdown.md +0 -0
  71. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/generator-api.md +0 -0
  72. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/how-to/catalogs.md +0 -0
  73. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/how-to/function-patterns.md +0 -0
  74. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/how-to/http-auth.md +0 -0
  75. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/how-to/index.md +0 -0
  76. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/how-to/pushdown-and-statistics.md +0 -0
  77. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/how-to/state-storage.md +0 -0
  78. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/index.md +0 -0
  79. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/lifecycle.md +0 -0
  80. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/metadata.md +0 -0
  81. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/overrides/main.html +0 -0
  82. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/robots.txt +0 -0
  83. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/shared-storage.md +0 -0
  84. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/stylesheets/extra.css +0 -0
  85. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/tutorial/index.md +0 -0
  86. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/tutorial/scalar.md +0 -0
  87. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/tutorial/table.md +0 -0
  88. {vgi_python-0.8.5 → vgi_python-0.8.7}/docs/vgi-logo.png +0 -0
  89. {vgi_python-0.8.5 → vgi_python-0.8.7}/examples/calc_scalar_worker.py +0 -0
  90. {vgi_python-0.8.5 → vgi_python-0.8.7}/examples/calc_worker.py +0 -0
  91. {vgi_python-0.8.5 → vgi_python-0.8.7}/examples/filter_worker.py +0 -0
  92. {vgi_python-0.8.5 → vgi_python-0.8.7}/examples/greeting_scalar_worker.py +0 -0
  93. {vgi_python-0.8.5 → vgi_python-0.8.7}/examples/row_count_worker.py +0 -0
  94. {vgi_python-0.8.5 → vgi_python-0.8.7}/examples/series_streaming_worker.py +0 -0
  95. {vgi_python-0.8.5 → vgi_python-0.8.7}/examples/sum_worker.py +0 -0
  96. {vgi_python-0.8.5 → vgi_python-0.8.7}/mkdocs.yml +0 -0
  97. {vgi_python-0.8.5 → vgi_python-0.8.7}/packages/vgi-fixtures/LICENSE +0 -0
  98. {vgi_python-0.8.5 → vgi_python-0.8.7}/packages/vgi-fixtures/README.md +0 -0
  99. {vgi_python-0.8.5 → vgi_python-0.8.7}/packages/vgi-fixtures/pyproject.toml +0 -0
  100. {vgi_python-0.8.5 → vgi_python-0.8.7}/scripts/measure_startup.py +0 -0
  101. {vgi_python-0.8.5 → vgi_python-0.8.7}/scripts/run_all_tests.sh +0 -0
  102. {vgi_python-0.8.5 → vgi_python-0.8.7}/test-data/generate.sh +0 -0
  103. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/__init__.py +0 -0
  104. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/_http_fixtures.py +0 -0
  105. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/catalog/__init__.py +0 -0
  106. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/catalog/test_catalog_interface.py +0 -0
  107. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/catalog/test_client_catalog.py +0 -0
  108. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/catalog/test_column_statistics.py +0 -0
  109. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/catalog/test_declarative.py +0 -0
  110. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/catalog/test_example_worker_catalog.py +0 -0
  111. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/catalog/test_integration.py +0 -0
  112. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/catalog/test_required_field_filter_paths.py +0 -0
  113. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/catalog/test_scan_branches.py +0 -0
  114. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/catalog/test_setting.py +0 -0
  115. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/catalog/test_storage.py +0 -0
  116. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/catalog/test_time_travel.py +0 -0
  117. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/catalog/test_writable_table.py +0 -0
  118. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/client/__init__.py +0 -0
  119. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/client/test_broken_pipe.py +0 -0
  120. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/client/test_cli.py +0 -0
  121. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/client/test_cli_catalog_functions.py +0 -0
  122. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/client/test_worker_debug.py +0 -0
  123. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/__init__.py +0 -0
  124. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/_stub.py +0 -0
  125. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/conftest.py +0 -0
  126. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_accumulate.py +0 -0
  127. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_aggregate.py +0 -0
  128. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_attach.py +0 -0
  129. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_bearer_auth.py +0 -0
  130. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_directory_parity.py +0 -0
  131. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_function_inventory.py +0 -0
  132. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_http_client.py +0 -0
  133. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_http_external_location.py +0 -0
  134. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_http_upload_url.py +0 -0
  135. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_macro.py +0 -0
  136. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_overload.py +0 -0
  137. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_protocol_inventory.py +0 -0
  138. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_protocol_version.py +0 -0
  139. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_resumable_scan.py +0 -0
  140. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_scalar.py +0 -0
  141. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_scalar_attach_opaque_data.py +0 -0
  142. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_secret.py +0 -0
  143. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_settings.py +0 -0
  144. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_table.py +0 -0
  145. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_table_in_out.py +0 -0
  146. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_view.py +0 -0
  147. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conformance/test_writable.py +0 -0
  148. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/conftest.py +0 -0
  149. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/scalar/__init__.py +0 -0
  150. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/scalar/test_bernoulli_function.py +0 -0
  151. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/scalar/test_binary_packet_function.py +0 -0
  152. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/scalar/test_client.py +0 -0
  153. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/scalar/test_conditional_message_function.py +0 -0
  154. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/scalar/test_hash_seed_function.py +0 -0
  155. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/scalar/test_multiply_by_setting_function.py +0 -0
  156. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/scalar/test_multiply_function.py +0 -0
  157. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/scalar/test_random_bytes_function.py +0 -0
  158. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/scalar/test_return_secret_value_function.py +0 -0
  159. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table/__init__.py +0 -0
  160. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table/generator/__init__.py +0 -0
  161. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table/generator/test_constant_columns_function.py +0 -0
  162. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table/generator/test_double_sequence_function.py +0 -0
  163. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table/generator/test_exception_function.py +0 -0
  164. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table/generator/test_filter_echo_function.py +0 -0
  165. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table/generator/test_logging_function.py +0 -0
  166. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table/generator/test_nested_sequence_function.py +0 -0
  167. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table/generator/test_partitioned_function.py +0 -0
  168. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table/generator/test_projected_data_function.py +0 -0
  169. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table/generator/test_sequence_function.py +0 -0
  170. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table/generator/test_settings_function.py +0 -0
  171. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table/generator/test_struct_settings_function.py +0 -0
  172. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table/generator/test_ten_thousand_function.py +0 -0
  173. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table_in_out/__init__.py +0 -0
  174. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table_in_out/generator/__init__.py +0 -0
  175. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table_in_out/generator/test_buffer_input_function.py +0 -0
  176. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table_in_out/generator/test_echo_function.py +0 -0
  177. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table_in_out/generator/test_exception_functions.py +0 -0
  178. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table_in_out/generator/test_filter_by_setting_function.py +0 -0
  179. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table_in_out/generator/test_repeat_inputs_function.py +0 -0
  180. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table_in_out/generator/test_sum_all_columns_function.py +0 -0
  181. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/table_in_out/test_client.py +0 -0
  182. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_access_log_audit.py +0 -0
  183. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_aggregate_function.py +0 -0
  184. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_argument_spec.py +0 -0
  185. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_auth.py +0 -0
  186. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_bind_exceptions.py +0 -0
  187. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_bind_request_at_clause.py +0 -0
  188. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_bound_storage_conformance.py +0 -0
  189. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_catalog_auth_binding.py +0 -0
  190. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_docstrings.py +0 -0
  191. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_documentation_examples.py +0 -0
  192. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_example_function_arg_types.py +0 -0
  193. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_examples_workers.py +0 -0
  194. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_exception_handling.py +0 -0
  195. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_exceptions.py +0 -0
  196. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_filter_pushdown.py +0 -0
  197. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_filter_pushdown_extension.py +0 -0
  198. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_function_storage.py +0 -0
  199. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_function_storage_azure_sql.py +0 -0
  200. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_function_storage_cf_do.py +0 -0
  201. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_function_storage_cf_do_integration.py +0 -0
  202. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_function_storage_conformance.py +0 -0
  203. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_generated_cpp_constants.py +0 -0
  204. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_generated_cpp_protocol_version.py +0 -0
  205. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_generated_cpp_request_builders.py +0 -0
  206. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_generated_cpp_schemas.py +0 -0
  207. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_generated_cpp_secret.py +0 -0
  208. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_generated_go_schemas.py +0 -0
  209. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_generated_protocol_version.py +0 -0
  210. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_generated_schemas_cross_lang.py +0 -0
  211. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_generated_ts_client.py +0 -0
  212. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_generated_ts_schemas.py +0 -0
  213. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_http_demo_storage.py +0 -0
  214. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_http_s3_offload_input.py +0 -0
  215. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_http_s3_offload_output.py +0 -0
  216. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_metadata.py +0 -0
  217. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_mypy_consolidated.py +0 -0
  218. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_nest_tensor.py +0 -0
  219. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_otel.py +0 -0
  220. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_projection_enforcement.py +0 -0
  221. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_projection_repro.py +0 -0
  222. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_protocol_classes.py +0 -0
  223. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_schema_utils.py +0 -0
  224. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_serve.py +0 -0
  225. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_setting_secret_annotations.py +0 -0
  226. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_table_buffering_function.py +0 -0
  227. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_table_function_dynamic_to_string.py +0 -0
  228. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_type_bounds.py +0 -0
  229. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_union_argument.py +0 -0
  230. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_worker.py +0 -0
  231. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_worker_cli.py +0 -0
  232. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/test_worker_page.py +0 -0
  233. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/transactor/__init__.py +0 -0
  234. {vgi_python-0.8.5 → vgi_python-0.8.7}/tests/transactor/test_transactor.py +0 -0
  235. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/__init__.py +0 -0
  236. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_duckdb.py +0 -0
  237. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_storage_profile.py +0 -0
  238. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/__init__.py +0 -0
  239. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/accumulate/__init__.py +0 -0
  240. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/accumulate/worker.py +0 -0
  241. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/__init__.py +0 -0
  242. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/_common.py +0 -0
  243. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/basic.py +0 -0
  244. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/dynamic.py +0 -0
  245. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/generic.py +0 -0
  246. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/listagg.py +0 -0
  247. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/percentile.py +0 -0
  248. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/streaming.py +0 -0
  249. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/varargs.py +0 -0
  250. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/aggregate/window.py +0 -0
  251. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/attach_options.py +0 -0
  252. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/bad_enum.py +0 -0
  253. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/bad_protocol.py +0 -0
  254. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/cancellable.py +0 -0
  255. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/http_server.py +0 -0
  256. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/narrow_bind/__init__.py +0 -0
  257. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/narrow_bind/worker.py +0 -0
  258. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/nest_tensor.py +0 -0
  259. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/orchard_catalog.py +0 -0
  260. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/projection_repro/__init__.py +0 -0
  261. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/projection_repro/worker.py +0 -0
  262. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/__init__.py +0 -0
  263. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/_common.py +0 -0
  264. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/arithmetic.py +0 -0
  265. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/binary.py +0 -0
  266. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/formatting.py +0 -0
  267. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/geo.py +0 -0
  268. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/null_handling.py +0 -0
  269. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/random_demo.py +0 -0
  270. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/settings_secrets.py +0 -0
  271. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/scalar/type_info.py +0 -0
  272. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/schema_reconcile/__init__.py +0 -0
  273. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/schema_reconcile/worker.py +0 -0
  274. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/simple_writable.py +0 -0
  275. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/__init__.py +0 -0
  276. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/_common.py +0 -0
  277. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/batch_index.py +0 -0
  278. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/batch_index_broken.py +0 -0
  279. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/catalog_scans.py +0 -0
  280. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/filters.py +0 -0
  281. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/late_materialization.py +0 -0
  282. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/make_series.py +0 -0
  283. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/misc.py +0 -0
  284. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/order_modes.py +0 -0
  285. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/pairs.py +0 -0
  286. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/partition_columns.py +0 -0
  287. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/partition_columns_broken.py +0 -0
  288. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/profiling_example.py +0 -0
  289. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/required_filters.py +0 -0
  290. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/sequence.py +0 -0
  291. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/settings.py +0 -0
  292. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/transaction_storage.py +0 -0
  293. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/tt_pushdown.py +0 -0
  294. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/typed_probe.py +0 -0
  295. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table/versioned.py +0 -0
  296. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/table_in_out.py +0 -0
  297. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/versioned.py +0 -0
  298. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/versioned_tables.py +0 -0
  299. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/writable/__init__.py +0 -0
  300. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/writable/generic.py +0 -0
  301. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/writable/table.py +0 -0
  302. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/_test_fixtures/writable/worker.py +0 -0
  303. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/aggregate_function.py +0 -0
  304. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/arguments.py +0 -0
  305. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/auth.py +0 -0
  306. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/catalog/__init__.py +0 -0
  307. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/catalog/_descriptor_spec.py +0 -0
  308. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/catalog/attach_option.py +0 -0
  309. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/catalog/duckdb_statistics.py +0 -0
  310. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/catalog/secret_type.py +0 -0
  311. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/catalog/setting.py +0 -0
  312. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/catalog/storage.py +0 -0
  313. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/client/__init__.py +0 -0
  314. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/client/cli.py +0 -0
  315. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/client/cli_catalog.py +0 -0
  316. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/client/cli_schema.py +0 -0
  317. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/client/cli_table.py +0 -0
  318. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/client/cli_transaction.py +0 -0
  319. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/client/cli_utils.py +0 -0
  320. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/client/cli_view.py +0 -0
  321. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/codegen/__init__.py +0 -0
  322. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/codegen/_common.py +0 -0
  323. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/codegen/cpp_constants.py +0 -0
  324. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/codegen/cpp_protocol_version.py +0 -0
  325. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/codegen/cpp_request_builders.py +0 -0
  326. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/codegen/cpp_schemas.py +0 -0
  327. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/codegen/cpp_secret_protocol_version.py +0 -0
  328. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/codegen/cpp_secret_request_builders.py +0 -0
  329. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/codegen/cpp_secret_schemas.py +0 -0
  330. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/codegen/protocol_version.py +0 -0
  331. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/codegen/ts_client.py +0 -0
  332. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/codegen/ts_schemas.py +0 -0
  333. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/exceptions.py +0 -0
  334. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/function.py +0 -0
  335. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/function_storage.py +0 -0
  336. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/function_storage_azure_sql.py +0 -0
  337. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/function_storage_cf_do.py +0 -0
  338. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/http/__init__.py +0 -0
  339. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/http/demo_storage.py +0 -0
  340. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/http/worker_page.py +0 -0
  341. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/invocation.py +0 -0
  342. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/logging_config.py +0 -0
  343. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/meta_worker.py +0 -0
  344. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/metadata.py +0 -0
  345. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/otel.py +0 -0
  346. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/protocol_version.txt +0 -0
  347. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/py.typed +0 -0
  348. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/scalar_function.py +0 -0
  349. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/schema_utils.py +0 -0
  350. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/secret_protocol.py +0 -0
  351. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/secret_service.py +0 -0
  352. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/serve.py +0 -0
  353. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/table_buffering_function.py +0 -0
  354. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/table_filter_pushdown.py +0 -0
  355. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/table_function.py +0 -0
  356. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/table_in_out_function.py +0 -0
  357. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/transactor/__init__.py +0 -0
  358. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/transactor/_duckdb_compat.py +0 -0
  359. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/transactor/client.py +0 -0
  360. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/transactor/protocol.py +0 -0
  361. {vgi_python-0.8.5 → vgi_python-0.8.7}/vgi/transactor/server.py +0 -0
  362. {vgi_python-0.8.5 → 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.5
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.20.5
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.5"
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.20.5",
43
+ "vgi-rpc>=0.21.0",
44
44
  "httpx>=0.24",
45
45
  ]
46
46
 
@@ -615,6 +615,140 @@ class TestMacroInfoSerialization:
615
615
  restored = MacroInfo.deserialize_from_batch(batch)
616
616
  assert restored.macro_type == macro_type
617
617
 
618
+ def test_arguments_schema_round_trip(self) -> None:
619
+ """arguments_schema carries vgi_doc per documented param; absent doc -> no key."""
620
+ from vgi.argument_spec import VGI_DOC_KEY, macro_arguments_schema, macro_parameter_docs_from_schema
621
+
622
+ defaults = pa.RecordBatch.from_pydict({"lo": pa.array([0], type=pa.int64())})
623
+ args = macro_arguments_schema(
624
+ parameters=["val", "lo", "hi"],
625
+ parameter_default_values=defaults,
626
+ parameter_docs={"val": "value to clamp", "hi": "upper bound"},
627
+ )
628
+ original = MacroInfo(
629
+ name="clamp",
630
+ schema_name="main",
631
+ macro_type=MacroType.SCALAR,
632
+ parameters=["val", "lo", "hi"],
633
+ parameter_default_values=defaults,
634
+ definition="GREATEST(lo, LEAST(hi, val))",
635
+ comment=None,
636
+ tags={},
637
+ arguments_schema=args,
638
+ )
639
+ serialized = original.serialize_to_bytes()
640
+ batch, _ = deserialize_record_batch(serialized)
641
+ restored = MacroInfo.deserialize_from_batch(batch)
642
+
643
+ assert restored.arguments_schema is not None
644
+ rs = restored.arguments_schema
645
+ # One field per parameter, in order.
646
+ assert rs.names == ["val", "lo", "hi"]
647
+ # Field type tracks the default value type when known, else null.
648
+ assert rs.field("lo").type == pa.int64()
649
+ assert rs.field("val").type == pa.null()
650
+ assert rs.field("hi").type == pa.null()
651
+ # Documented params carry vgi_doc; undocumented (lo) has no key.
652
+ assert (rs.field("val").metadata or {}).get(VGI_DOC_KEY) == b"value to clamp"
653
+ assert (rs.field("hi").metadata or {}).get(VGI_DOC_KEY) == b"upper bound"
654
+ assert VGI_DOC_KEY not in (rs.field("lo").metadata or {})
655
+ # Convenience extractor returns only documented params.
656
+ assert macro_parameter_docs_from_schema(rs) == {"val": "value to clamp", "hi": "upper bound"}
657
+
658
+ def test_none_arguments_schema(self) -> None:
659
+ """arguments_schema defaults to None (older workers) and survives round-trip."""
660
+ original = MacroInfo(
661
+ name="simple",
662
+ schema_name="main",
663
+ macro_type=MacroType.SCALAR,
664
+ parameters=["x"],
665
+ definition="x",
666
+ comment=None,
667
+ tags={},
668
+ )
669
+ serialized = original.serialize_to_bytes()
670
+ batch, _ = deserialize_record_batch(serialized)
671
+ restored = MacroInfo.deserialize_from_batch(batch)
672
+ assert restored.arguments_schema is None
673
+
674
+
675
+ class TestMacroArgumentsSchemaWire:
676
+ """Macro per-parameter docs flow over create/list wire types."""
677
+
678
+ def test_declarative_macro_to_info_carries_docs(self) -> None:
679
+ """Declarative Macro.parameter_docs -> MacroInfo.arguments_schema vgi_doc."""
680
+ from vgi.argument_spec import macro_parameter_docs_from_schema
681
+ from vgi.catalog.descriptors import Macro
682
+
683
+ m = Macro(
684
+ name="clamp",
685
+ macro_type=MacroType.SCALAR,
686
+ parameters=["x", "lo", "hi"],
687
+ parameter_default_values=pa.RecordBatch.from_pydict(
688
+ {"lo": pa.array([0], type=pa.int64()), "hi": pa.array([100], type=pa.int64())}
689
+ ),
690
+ parameter_docs={"x": "value to clamp"},
691
+ definition="GREATEST(lo, LEAST(hi, x))",
692
+ )
693
+ info = m.to_macro_info("main")
694
+ assert info.arguments_schema is not None
695
+ assert info.arguments_schema.names == ["x", "lo", "hi"]
696
+ assert macro_parameter_docs_from_schema(info.arguments_schema) == {"x": "value to clamp"}
697
+
698
+ def test_declarative_macro_rejects_unknown_doc_param(self) -> None:
699
+ """parameter_docs keys must be in parameters (validated like defaults)."""
700
+ from vgi.catalog.descriptors import Macro
701
+
702
+ with pytest.raises(ValueError, match="documented parameter 'bogus' not found"):
703
+ Macro(
704
+ name="bad",
705
+ macro_type=MacroType.SCALAR,
706
+ parameters=["x"],
707
+ parameter_docs={"bogus": "nope"},
708
+ definition="x",
709
+ )
710
+
711
+ def test_macro_create_request_round_trip(self) -> None:
712
+ """MacroCreateRequest carries arguments_schema over the wire."""
713
+ from vgi.argument_spec import macro_arguments_schema, macro_parameter_docs_from_schema
714
+ from vgi.catalog import OnConflict
715
+ from vgi.protocol import MacroCreateRequest
716
+
717
+ args = macro_arguments_schema(
718
+ parameters=["x", "y"],
719
+ parameter_docs={"x": "first", "y": "second"},
720
+ )
721
+ req = MacroCreateRequest(
722
+ attach_opaque_data=b"attach",
723
+ schema_name="main",
724
+ name="add",
725
+ macro_type=MacroType.SCALAR,
726
+ parameters=["x", "y"],
727
+ definition="x + y",
728
+ on_conflict=OnConflict.ERROR,
729
+ arguments_schema=args,
730
+ )
731
+ restored = MacroCreateRequest.deserialize_from_bytes(req.serialize_to_bytes())
732
+ assert restored.arguments_schema is not None
733
+ assert macro_parameter_docs_from_schema(restored.arguments_schema) == {"x": "first", "y": "second"}
734
+
735
+ def test_macro_create_request_none_arguments_schema(self) -> None:
736
+ """MacroCreateRequest.arguments_schema defaults to None and round-trips."""
737
+ from vgi.catalog import OnConflict
738
+ from vgi.protocol import MacroCreateRequest
739
+
740
+ req = MacroCreateRequest(
741
+ attach_opaque_data=b"attach",
742
+ schema_name="main",
743
+ name="add",
744
+ macro_type=MacroType.SCALAR,
745
+ parameters=["x", "y"],
746
+ definition="x + y",
747
+ on_conflict=OnConflict.ERROR,
748
+ )
749
+ restored = MacroCreateRequest.deserialize_from_bytes(req.serialize_to_bytes())
750
+ assert restored.arguments_schema is None
751
+
618
752
 
619
753
  class TestFunctionInfoSerialization:
620
754
  """Test FunctionInfo serialization round-trip."""
@@ -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.4"
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.20.5" },
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.20.6"
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/40/76/4a2c35af34928c6ab17fcb9b1b50639241bf9d015d45b23ce004d0d70d51/vgi_rpc-0.20.6.tar.gz", hash = "sha256:3172d5041b901b0d1a32c9b45da32363195bbca18adb7e305456f19c241cf8fe", size = 847271, upload-time = "2026-06-22T18:24:18.969Z" }
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/d3/3c/9ccc888e725ad9d7091e8ec6fd7504eec15dc2ccfabedabd7d072123b0e8/vgi_rpc-0.20.6-py3-none-any.whl", hash = "sha256:74f8b7c0685f1c28a3ff754d76f8c0179c782e33aa5915ad0343bb9955d7509d", size = 371735, upload-time = "2026-06-22T18:24:17.458Z" },
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]
@@ -752,6 +752,7 @@ class InMemoryCatalog(CatalogInterface):
752
752
  definition: str,
753
753
  on_conflict: OnConflict,
754
754
  parameter_default_values: pa.RecordBatch | None = None,
755
+ arguments_schema: pa.Schema | None = None,
755
756
  ) -> None:
756
757
  """Create a new macro."""
757
758
  schema_data = self._get_schema(attach_opaque_data, schema_name)
@@ -773,6 +774,7 @@ class InMemoryCatalog(CatalogInterface):
773
774
  definition=definition,
774
775
  comment=None,
775
776
  tags={},
777
+ arguments_schema=arguments_schema,
776
778
  )
777
779
  )
778
780
  self._increment_version(attach_opaque_data)
@@ -519,6 +519,10 @@ _EXAMPLE_CATALOG = Catalog(
519
519
  parameters=["x", "y"],
520
520
  definition="x * y",
521
521
  comment="Multiply two values",
522
+ parameter_docs={
523
+ "x": "First factor",
524
+ "y": "Second factor",
525
+ },
522
526
  ),
523
527
  Macro(
524
528
  name="vgi_clamp",
@@ -530,6 +534,11 @@ _EXAMPLE_CATALOG = Catalog(
530
534
  ),
531
535
  definition="GREATEST(lo, LEAST(hi, val))",
532
536
  comment="Clamp a value between lo and hi (defaults: 0..100)",
537
+ parameter_docs={
538
+ "val": "Value to clamp",
539
+ "lo": "Lower bound (inclusive)",
540
+ "hi": "Upper bound (inclusive)",
541
+ },
533
542
  ),
534
543
  Macro(
535
544
  name="vgi_range_table",
@@ -537,6 +546,7 @@ _EXAMPLE_CATALOG = Catalog(
537
546
  parameters=["n"],
538
547
  definition="SELECT * FROM range(n)",
539
548
  comment="Table macro returning range of values",
549
+ parameter_docs={"n": "Number of rows to generate"},
540
550
  ),
541
551
  ],
542
552
  ),
@@ -27,6 +27,8 @@ __all__ = [
27
27
  "ArgumentSpec",
28
28
  "argument_specs_to_schema",
29
29
  "extract_argument_specs",
30
+ "macro_arguments_schema",
31
+ "macro_parameter_docs_from_schema",
30
32
  "schema_to_argument_specs",
31
33
  # Metadata constants for parsing schemas
32
34
  "VGI_ARG_KEY",
@@ -280,6 +282,86 @@ def schema_to_argument_specs(schema: pa.Schema) -> list[ArgumentSpec]:
280
282
  return specs
281
283
 
282
284
 
285
+ # =============================================================================
286
+ # Macro Argument Schemas
287
+ # =============================================================================
288
+
289
+
290
+ def macro_arguments_schema(
291
+ parameters: Sequence[str],
292
+ parameter_default_values: pa.RecordBatch | None = None,
293
+ parameter_docs: dict[str, str] | None = None,
294
+ ) -> pa.Schema:
295
+ """Build a macro ``arguments_schema`` describing macro parameters.
296
+
297
+ Mirrors the function ``arguments_schema`` mechanism: one Arrow field per
298
+ macro parameter, in ``parameters`` order, each nullable. The per-parameter
299
+ description is carried via the same ``vgi_doc`` field-metadata key functions
300
+ use (UTF-8, presence-only — the key is omitted entirely when there is no
301
+ doc). A parameter's field type is the type of its default value when one is
302
+ known (from ``parameter_default_values``), else ``pa.null()``.
303
+
304
+ Args:
305
+ parameters: Ordered list of macro parameter names.
306
+ parameter_default_values: Optional one-row ``RecordBatch`` whose columns
307
+ are parameter names with typed default values; used to infer each
308
+ parameter's field type.
309
+ parameter_docs: Optional mapping of parameter name to description. Empty
310
+ or missing descriptions yield no ``vgi_doc`` metadata on the field.
311
+
312
+ Returns:
313
+ Arrow schema with one nullable field per parameter, in order.
314
+
315
+ """
316
+ docs = parameter_docs or {}
317
+
318
+ # Map parameter name -> Arrow type from the typed default values, if any.
319
+ default_types: dict[str, pa.DataType] = {}
320
+ if parameter_default_values is not None:
321
+ for default_field in parameter_default_values.schema:
322
+ default_types[default_field.name] = default_field.type
323
+
324
+ fields: list[pa.Field[Any]] = []
325
+ for name in parameters:
326
+ metadata: dict[bytes, bytes] = {}
327
+ doc = docs.get(name, "")
328
+ if doc:
329
+ metadata[VGI_DOC_KEY] = doc.encode("utf-8")
330
+
331
+ field = pa.field(
332
+ name,
333
+ default_types.get(name, pa.null()),
334
+ nullable=True,
335
+ metadata=metadata if metadata else None,
336
+ )
337
+ fields.append(field)
338
+
339
+ return pa.schema(fields)
340
+
341
+
342
+ def macro_parameter_docs_from_schema(schema: pa.Schema) -> dict[str, str]:
343
+ """Extract per-parameter descriptions from a macro ``arguments_schema``.
344
+
345
+ Inverse of [`macro_arguments_schema`][]'s ``vgi_doc`` handling: reads the
346
+ ``vgi_doc`` field metadata (UTF-8) for each field. Fields without the key
347
+ (undocumented) are omitted from the result.
348
+
349
+ Args:
350
+ schema: A macro ``arguments_schema`` (one field per parameter).
351
+
352
+ Returns:
353
+ Mapping of parameter name to description, for documented parameters only.
354
+
355
+ """
356
+ docs: dict[str, str] = {}
357
+ for field in schema:
358
+ metadata = field.metadata or {}
359
+ doc_bytes = metadata.get(VGI_DOC_KEY)
360
+ if doc_bytes:
361
+ docs[field.name] = doc_bytes.decode("utf-8")
362
+ return docs
363
+
364
+
283
365
  # =============================================================================
284
366
  # Extraction from Function Classes
285
367
  # =============================================================================
@@ -435,6 +435,15 @@ class MacroInfo(CatalogSchemaObject, ArrowSerializableDataclass):
435
435
  names and values are typed defaults. None if no defaults.
436
436
  Serialized as IPC bytes over the wire.
437
437
  definition: The SQL expression (scalar) or query (table).
438
+ arguments_schema: Optional Arrow schema (serialized as IPC bytes) with one
439
+ nullable field per parameter, in ``parameters`` order. Each field's type
440
+ is the parameter's default value type when known (else null), and the
441
+ ``vgi_doc`` field metadata key carries the parameter's description (UTF-8,
442
+ presence-only — omitted when undocumented). Mirrors the per-argument doc
443
+ channel functions expose via ``FunctionInfo.arguments``. None means the
444
+ worker did not supply per-parameter docs (older workers); the extension
445
+ falls back to ``parameters`` for names. Built with
446
+ ``vgi.argument_spec.macro_arguments_schema``.
438
447
 
439
448
  """
440
449
 
@@ -442,6 +451,7 @@ class MacroInfo(CatalogSchemaObject, ArrowSerializableDataclass):
442
451
  parameters: list[str]
443
452
  parameter_default_values: Annotated[pa.RecordBatch | None, ArrowType(pa.binary())] = None
444
453
  definition: str = ""
454
+ arguments_schema: Annotated[pa.Schema | None, ArrowType(pa.binary())] = None
445
455
 
446
456
 
447
457
  class FunctionType(Enum):
@@ -1979,8 +1989,25 @@ class CatalogInterface(ABC):
1979
1989
  definition: str,
1980
1990
  on_conflict: OnConflict,
1981
1991
  parameter_default_values: pa.RecordBatch | None = None,
1992
+ arguments_schema: pa.Schema | None = None,
1982
1993
  ) -> None:
1983
- """Create a new macro with the given definition."""
1994
+ """Create a new macro with the given definition.
1995
+
1996
+ Args:
1997
+ attach_opaque_data: Per-attach catalog session token.
1998
+ transaction_opaque_data: Optional transaction handle.
1999
+ schema_name: Schema to create the macro in.
2000
+ name: Name for the new macro.
2001
+ macro_type: Whether this is a scalar or table macro.
2002
+ parameters: Ordered list of parameter names.
2003
+ definition: SQL expression (scalar) or query (table).
2004
+ on_conflict: Behavior if the macro already exists.
2005
+ parameter_default_values: One-row ``RecordBatch`` with typed defaults.
2006
+ arguments_schema: Optional Arrow schema (one nullable field per
2007
+ parameter, in ``parameters`` order) carrying per-parameter
2008
+ descriptions via the ``vgi_doc`` field metadata key. ``None`` when
2009
+ no per-parameter docs are supplied.
2010
+ """
1984
2011
  raise NotImplementedError("Macro create not implemented.")
1985
2012
 
1986
2013
  def macro_drop(
@@ -18,6 +18,7 @@ from typing import TYPE_CHECKING, Any, Union
18
18
 
19
19
  import pyarrow as pa
20
20
 
21
+ from vgi.argument_spec import macro_arguments_schema
21
22
  from vgi.arguments import Arguments
22
23
  from vgi.catalog.catalog_interface import (
23
24
  AttachOpaqueData,
@@ -695,6 +696,11 @@ class Macro:
695
696
  parameter_default_values: One-row `RecordBatch` where columns are parameter
696
697
  names and values are typed defaults. None if no defaults.
697
698
  Example: pa.RecordBatch.from_pydict({"b": [5]}) for b := 5.
699
+ parameter_docs: Optional mapping of parameter name to a human/agent-facing
700
+ description. Keys must appear in ``parameters``. Descriptions flow over
701
+ the wire via the macro ``arguments_schema``'s ``vgi_doc`` field metadata
702
+ (the same channel functions use), so the DuckDB extension's
703
+ ``vgi_function_arguments()`` can surface them. Empty/default = no docs.
698
704
  definition: SQL expression (scalar) or query (table).
699
705
  comment: Optional macro comment.
700
706
  tags: Optional metadata tags.
@@ -705,12 +711,14 @@ class Macro:
705
711
  macro_type: MacroType
706
712
  parameters: list[str] = field(default_factory=list)
707
713
  parameter_default_values: pa.RecordBatch | None = None
714
+ parameter_docs: dict[str, str] = field(default_factory=dict)
708
715
  definition: str = ""
709
716
  comment: str | None = None
710
717
  tags: dict[str, str] = field(default_factory=dict)
711
718
 
712
719
  def __post_init__(self) -> None:
713
720
  """Validate macro configuration."""
721
+ param_set = set(self.parameters)
714
722
  if self.parameter_default_values is not None:
715
723
  if self.parameter_default_values.num_rows != 1:
716
724
  raise ValueError(
@@ -718,13 +726,19 @@ class Macro:
718
726
  f"got {self.parameter_default_values.num_rows}"
719
727
  )
720
728
  # Validate that default param column names exist in parameters list
721
- param_set = set(self.parameters)
722
729
  for col_name in self.parameter_default_values.schema.names:
723
730
  if col_name not in param_set:
724
731
  raise ValueError(
725
732
  f"Macro '{self.name}': default parameter '{col_name}' not found "
726
733
  f"in parameters list {self.parameters}"
727
734
  )
735
+ # Validate that documented parameter names exist in parameters list
736
+ for doc_name in self.parameter_docs:
737
+ if doc_name not in param_set:
738
+ raise ValueError(
739
+ f"Macro '{self.name}': documented parameter '{doc_name}' not found "
740
+ f"in parameters list {self.parameters}"
741
+ )
728
742
 
729
743
  def to_macro_info(self, schema_name: str) -> MacroInfo:
730
744
  """Convert to [`MacroInfo`][] for catalog response."""
@@ -737,6 +751,11 @@ class Macro:
737
751
  definition=self.definition,
738
752
  comment=self.comment,
739
753
  tags=dict(self.tags),
754
+ arguments_schema=macro_arguments_schema(
755
+ self.parameters,
756
+ self.parameter_default_values,
757
+ self.parameter_docs,
758
+ ),
740
759
  )
741
760
 
742
761