vgi-python 0.14.0__tar.gz → 0.15.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (389) hide show
  1. {vgi_python-0.14.0 → vgi_python-0.15.0}/PKG-INFO +1 -1
  2. {vgi_python-0.14.0 → vgi_python-0.15.0}/ci/run-integration.sh +34 -3
  3. {vgi_python-0.14.0 → vgi_python-0.15.0}/pyproject.toml +1 -1
  4. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/catalog/test_declarative.py +187 -6
  5. vgi_python-0.15.0/tests/catalog/test_required_filters.py +92 -0
  6. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/catalog/test_serialization.py +4 -4
  7. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/landing/describe.expected.json +11 -6
  8. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/required_filters.py +7 -7
  9. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/worker.py +42 -32
  10. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/catalog/catalog_interface.py +68 -15
  11. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/catalog/descriptors.py +49 -32
  12. vgi_python-0.14.0/tests/catalog/test_required_field_filter_paths.py +0 -98
  13. {vgi_python-0.14.0 → vgi_python-0.15.0}/.gitattributes +0 -0
  14. {vgi_python-0.14.0 → vgi_python-0.15.0}/.github/dependabot.yml +0 -0
  15. {vgi_python-0.14.0 → vgi_python-0.15.0}/.github/styles/config/vocabularies/VGI/accept.txt +0 -0
  16. {vgi_python-0.14.0 → vgi_python-0.15.0}/.github/workflows/ci.yml +0 -0
  17. {vgi_python-0.14.0 → vgi_python-0.15.0}/.github/workflows/docs.yml +0 -0
  18. {vgi_python-0.14.0 → vgi_python-0.15.0}/.github/workflows/integration.yml +0 -0
  19. {vgi_python-0.14.0 → vgi_python-0.15.0}/.github/workflows/release.yml +0 -0
  20. {vgi_python-0.14.0 → vgi_python-0.15.0}/.gitignore +0 -0
  21. {vgi_python-0.14.0 → vgi_python-0.15.0}/.python-version +0 -0
  22. {vgi_python-0.14.0 → vgi_python-0.15.0}/.vale.ini +0 -0
  23. {vgi_python-0.14.0 → vgi_python-0.15.0}/CLAUDE.md +0 -0
  24. {vgi_python-0.14.0 → vgi_python-0.15.0}/DOCS_ACCEPTANCE_CRITERIA.md +0 -0
  25. {vgi_python-0.14.0 → vgi_python-0.15.0}/DOCS_REVIEW_RUBRIC.md +0 -0
  26. {vgi_python-0.14.0 → vgi_python-0.15.0}/DOCS_USABILITY_TEST.md +0 -0
  27. {vgi_python-0.14.0 → vgi_python-0.15.0}/LICENSE +0 -0
  28. {vgi_python-0.14.0 → vgi_python-0.15.0}/README.md +0 -0
  29. {vgi_python-0.14.0 → vgi_python-0.15.0}/SECURITY.md +0 -0
  30. {vgi_python-0.14.0 → vgi_python-0.15.0}/ci/README.md +0 -0
  31. {vgi_python-0.14.0 → vgi_python-0.15.0}/ci/preprocess-require.awk +0 -0
  32. {vgi_python-0.14.0 → vgi_python-0.15.0}/dist-vgi/.gitignore +0 -0
  33. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/aggregate-functions.md +0 -0
  34. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/api/arguments.md +0 -0
  35. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/api/auth.md +0 -0
  36. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/api/catalogs.md +0 -0
  37. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/api/client.md +0 -0
  38. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/api/exceptions.md +0 -0
  39. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/api/filters.md +0 -0
  40. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/api/functions.md +0 -0
  41. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/api/http.md +0 -0
  42. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/api/index.md +0 -0
  43. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/api/metadata.md +0 -0
  44. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/api/observability.md +0 -0
  45. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/api/storage.md +0 -0
  46. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/api/transactor.md +0 -0
  47. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/api/worker.md +0 -0
  48. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/argument-serialization.md +0 -0
  49. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/assets/apple-touch-icon.png +0 -0
  50. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/assets/favicon-16x16.png +0 -0
  51. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/assets/favicon-32x32.png +0 -0
  52. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/assets/favicon.ico +0 -0
  53. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/assets/kinds/aggregate.svg +0 -0
  54. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/assets/kinds/buffering.svg +0 -0
  55. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/assets/kinds/scalar.svg +0 -0
  56. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/assets/kinds/table-in-out.svg +0 -0
  57. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/assets/kinds/table.svg +0 -0
  58. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/assets/logo.png +0 -0
  59. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/assets/social-card.png +0 -0
  60. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/authentication.md +0 -0
  61. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/catalog-interface.md +0 -0
  62. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/cli.md +0 -0
  63. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/column-statistics.md +0 -0
  64. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/concepts/index.md +0 -0
  65. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/contributing-docs.md +0 -0
  66. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/filter-pushdown.md +0 -0
  67. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/generator-api.md +0 -0
  68. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/how-to/catalogs.md +0 -0
  69. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/how-to/function-patterns.md +0 -0
  70. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/how-to/http-auth.md +0 -0
  71. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/how-to/index.md +0 -0
  72. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/how-to/pushdown-and-statistics.md +0 -0
  73. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/how-to/state-storage.md +0 -0
  74. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/index.md +0 -0
  75. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/lifecycle.md +0 -0
  76. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/metadata.md +0 -0
  77. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/overrides/main.html +0 -0
  78. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/robots.txt +0 -0
  79. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/shared-storage.md +0 -0
  80. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/stylesheets/extra.css +0 -0
  81. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/tutorial/index.md +0 -0
  82. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/tutorial/scalar.md +0 -0
  83. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/tutorial/table.md +0 -0
  84. {vgi_python-0.14.0 → vgi_python-0.15.0}/docs/vgi-logo.png +0 -0
  85. {vgi_python-0.14.0 → vgi_python-0.15.0}/examples/calc_scalar_worker.py +0 -0
  86. {vgi_python-0.14.0 → vgi_python-0.15.0}/examples/calc_worker.py +0 -0
  87. {vgi_python-0.14.0 → vgi_python-0.15.0}/examples/filter_worker.py +0 -0
  88. {vgi_python-0.14.0 → vgi_python-0.15.0}/examples/greeting_scalar_worker.py +0 -0
  89. {vgi_python-0.14.0 → vgi_python-0.15.0}/examples/row_count_worker.py +0 -0
  90. {vgi_python-0.14.0 → vgi_python-0.15.0}/examples/series_streaming_worker.py +0 -0
  91. {vgi_python-0.14.0 → vgi_python-0.15.0}/examples/sum_worker.py +0 -0
  92. {vgi_python-0.14.0 → vgi_python-0.15.0}/mkdocs.yml +0 -0
  93. {vgi_python-0.14.0 → vgi_python-0.15.0}/packages/vgi-fixtures/LICENSE +0 -0
  94. {vgi_python-0.14.0 → vgi_python-0.15.0}/packages/vgi-fixtures/README.md +0 -0
  95. {vgi_python-0.14.0 → vgi_python-0.15.0}/packages/vgi-fixtures/docker/Dockerfile +0 -0
  96. {vgi_python-0.14.0 → vgi_python-0.15.0}/packages/vgi-fixtures/docker/docker-entrypoint.sh +0 -0
  97. {vgi_python-0.14.0 → vgi_python-0.15.0}/packages/vgi-fixtures/pyproject.toml +0 -0
  98. {vgi_python-0.14.0 → vgi_python-0.15.0}/scripts/measure_startup.py +0 -0
  99. {vgi_python-0.14.0 → vgi_python-0.15.0}/scripts/run_all_tests.sh +0 -0
  100. {vgi_python-0.14.0 → vgi_python-0.15.0}/test-data/generate.sh +0 -0
  101. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/__init__.py +0 -0
  102. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/_http_fixtures.py +0 -0
  103. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/catalog/__init__.py +0 -0
  104. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/catalog/test_catalog_interface.py +0 -0
  105. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/catalog/test_client_catalog.py +0 -0
  106. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/catalog/test_column_statistics.py +0 -0
  107. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/catalog/test_example_worker_catalog.py +0 -0
  108. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/catalog/test_integration.py +0 -0
  109. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/catalog/test_scan_branches.py +0 -0
  110. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/catalog/test_setting.py +0 -0
  111. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/catalog/test_storage.py +0 -0
  112. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/catalog/test_time_travel.py +0 -0
  113. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/catalog/test_writable_table.py +0 -0
  114. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/client/__init__.py +0 -0
  115. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/client/test_broken_pipe.py +0 -0
  116. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/client/test_cli.py +0 -0
  117. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/client/test_cli_catalog_functions.py +0 -0
  118. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/client/test_worker_debug.py +0 -0
  119. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/__init__.py +0 -0
  120. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/_stub.py +0 -0
  121. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/conftest.py +0 -0
  122. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_accumulate.py +0 -0
  123. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_aggregate.py +0 -0
  124. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_attach.py +0 -0
  125. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_bearer_auth.py +0 -0
  126. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_const_param_enforcement.py +0 -0
  127. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_container.py +0 -0
  128. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_copy_from.py +0 -0
  129. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_copy_to.py +0 -0
  130. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_directory_parity.py +0 -0
  131. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_function_inventory.py +0 -0
  132. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_github.py +0 -0
  133. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_http_client.py +0 -0
  134. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_http_external_location.py +0 -0
  135. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_http_upload_url.py +0 -0
  136. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_macro.py +0 -0
  137. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_overload.py +0 -0
  138. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_protocol_inventory.py +0 -0
  139. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_protocol_version.py +0 -0
  140. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_resumable_scan.py +0 -0
  141. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_scalar.py +0 -0
  142. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_scalar_attach_opaque_data.py +0 -0
  143. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_secret.py +0 -0
  144. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_settings.py +0 -0
  145. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_table.py +0 -0
  146. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_table_in_out.py +0 -0
  147. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_view.py +0 -0
  148. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conformance/test_writable.py +0 -0
  149. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/conftest.py +0 -0
  150. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/landing/_checker.py +0 -0
  151. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/landing/describe.schema.json +0 -0
  152. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/scalar/__init__.py +0 -0
  153. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/scalar/test_bernoulli_function.py +0 -0
  154. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/scalar/test_binary_packet_function.py +0 -0
  155. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/scalar/test_client.py +0 -0
  156. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/scalar/test_conditional_message_function.py +0 -0
  157. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/scalar/test_hash_seed_function.py +0 -0
  158. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/scalar/test_multiply_by_setting_function.py +0 -0
  159. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/scalar/test_multiply_function.py +0 -0
  160. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/scalar/test_random_bytes_function.py +0 -0
  161. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/scalar/test_return_secret_value_function.py +0 -0
  162. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table/__init__.py +0 -0
  163. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table/generator/__init__.py +0 -0
  164. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table/generator/test_constant_columns_function.py +0 -0
  165. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table/generator/test_double_sequence_function.py +0 -0
  166. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table/generator/test_exception_function.py +0 -0
  167. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table/generator/test_filter_echo_function.py +0 -0
  168. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table/generator/test_logging_function.py +0 -0
  169. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table/generator/test_nested_sequence_function.py +0 -0
  170. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table/generator/test_partitioned_function.py +0 -0
  171. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table/generator/test_projected_data_function.py +0 -0
  172. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table/generator/test_sequence_function.py +0 -0
  173. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table/generator/test_settings_function.py +0 -0
  174. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table/generator/test_struct_settings_function.py +0 -0
  175. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table/generator/test_ten_thousand_function.py +0 -0
  176. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table_in_out/__init__.py +0 -0
  177. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table_in_out/generator/__init__.py +0 -0
  178. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table_in_out/generator/test_buffer_input_function.py +0 -0
  179. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table_in_out/generator/test_echo_function.py +0 -0
  180. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table_in_out/generator/test_exception_functions.py +0 -0
  181. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table_in_out/generator/test_filter_by_setting_function.py +0 -0
  182. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table_in_out/generator/test_repeat_inputs_function.py +0 -0
  183. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table_in_out/generator/test_sum_all_columns_function.py +0 -0
  184. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/table_in_out/test_client.py +0 -0
  185. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_access_log_audit.py +0 -0
  186. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_aggregate_function.py +0 -0
  187. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_argument_spec.py +0 -0
  188. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_auth.py +0 -0
  189. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_bind_exceptions.py +0 -0
  190. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_bind_request_at_clause.py +0 -0
  191. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_bound_storage_conformance.py +0 -0
  192. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_cache_control.py +0 -0
  193. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_catalog_auth_binding.py +0 -0
  194. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_copy_from_function.py +0 -0
  195. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_copy_to_function.py +0 -0
  196. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_docstrings.py +0 -0
  197. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_documentation_examples.py +0 -0
  198. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_example_function_arg_types.py +0 -0
  199. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_examples_workers.py +0 -0
  200. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_exception_handling.py +0 -0
  201. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_exceptions.py +0 -0
  202. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_filter_pushdown.py +0 -0
  203. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_filter_pushdown_extension.py +0 -0
  204. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_function_storage.py +0 -0
  205. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_function_storage_azure_sql.py +0 -0
  206. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_function_storage_cf_do.py +0 -0
  207. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_function_storage_cf_do_integration.py +0 -0
  208. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_function_storage_conformance.py +0 -0
  209. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_generated_cpp_constants.py +0 -0
  210. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_generated_cpp_protocol_version.py +0 -0
  211. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_generated_cpp_request_builders.py +0 -0
  212. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_generated_cpp_schemas.py +0 -0
  213. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_generated_cpp_secret.py +0 -0
  214. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_generated_go_schemas.py +0 -0
  215. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_generated_protocol_version.py +0 -0
  216. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_generated_schemas_cross_lang.py +0 -0
  217. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_generated_ts_client.py +0 -0
  218. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_generated_ts_schemas.py +0 -0
  219. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_http_demo_storage.py +0 -0
  220. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_http_s3_offload_input.py +0 -0
  221. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_http_s3_offload_output.py +0 -0
  222. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_landing_conformance.py +0 -0
  223. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_metadata.py +0 -0
  224. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_mypy_consolidated.py +0 -0
  225. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_nest_tensor.py +0 -0
  226. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_otel.py +0 -0
  227. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_projection_enforcement.py +0 -0
  228. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_projection_repro.py +0 -0
  229. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_protocol_classes.py +0 -0
  230. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_resolved_secrets.py +0 -0
  231. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_schema_utils.py +0 -0
  232. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_serve.py +0 -0
  233. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_setting_secret_annotations.py +0 -0
  234. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_table_buffering_function.py +0 -0
  235. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_table_function_dynamic_to_string.py +0 -0
  236. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_tcp_transport.py +0 -0
  237. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_type_bounds.py +0 -0
  238. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_union_argument.py +0 -0
  239. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_worker.py +0 -0
  240. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_worker_cli.py +0 -0
  241. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/test_worker_page.py +0 -0
  242. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/transactor/__init__.py +0 -0
  243. {vgi_python-0.14.0 → vgi_python-0.15.0}/tests/transactor/test_transactor.py +0 -0
  244. {vgi_python-0.14.0 → vgi_python-0.15.0}/uv.lock +0 -0
  245. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/__init__.py +0 -0
  246. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_duckdb.py +0 -0
  247. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_storage_profile.py +0 -0
  248. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/__init__.py +0 -0
  249. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/accumulate/__init__.py +0 -0
  250. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/accumulate/worker.py +0 -0
  251. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/__init__.py +0 -0
  252. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/_common.py +0 -0
  253. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/basic.py +0 -0
  254. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/dynamic.py +0 -0
  255. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/generic.py +0 -0
  256. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/listagg.py +0 -0
  257. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/percentile.py +0 -0
  258. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/secret_typed.py +0 -0
  259. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/streaming.py +0 -0
  260. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/varargs.py +0 -0
  261. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/aggregate/window.py +0 -0
  262. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/attach_options.py +0 -0
  263. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/bad_enum.py +0 -0
  264. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/bad_protocol.py +0 -0
  265. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/cancellable.py +0 -0
  266. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/catalog.py +0 -0
  267. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/companion.py +0 -0
  268. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/copy_from.py +0 -0
  269. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/copy_to.py +0 -0
  270. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/http_server.py +0 -0
  271. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/narrow_bind/__init__.py +0 -0
  272. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/narrow_bind/worker.py +0 -0
  273. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/nest_tensor.py +0 -0
  274. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/orchard_catalog.py +0 -0
  275. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/projection_repro/__init__.py +0 -0
  276. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/projection_repro/worker.py +0 -0
  277. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/__init__.py +0 -0
  278. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/_common.py +0 -0
  279. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/arithmetic.py +0 -0
  280. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/binary.py +0 -0
  281. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/formatting.py +0 -0
  282. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/geo.py +0 -0
  283. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/null_handling.py +0 -0
  284. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/random_demo.py +0 -0
  285. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/settings_secrets.py +0 -0
  286. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/scalar/type_info.py +0 -0
  287. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/schema_reconcile/__init__.py +0 -0
  288. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/schema_reconcile/worker.py +0 -0
  289. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/simple_writable.py +0 -0
  290. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/__init__.py +0 -0
  291. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/_common.py +0 -0
  292. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/batch_index.py +0 -0
  293. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/batch_index_broken.py +0 -0
  294. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/cache.py +0 -0
  295. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/catalog_scans.py +0 -0
  296. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/filters.py +0 -0
  297. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/late_materialization.py +0 -0
  298. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/make_series.py +0 -0
  299. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/misc.py +0 -0
  300. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/order_modes.py +0 -0
  301. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/pairs.py +0 -0
  302. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/partition_columns.py +0 -0
  303. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/partition_columns_broken.py +0 -0
  304. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/profiling_example.py +0 -0
  305. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/sequence.py +0 -0
  306. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/settings.py +0 -0
  307. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/transaction_storage.py +0 -0
  308. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/tt_pushdown.py +0 -0
  309. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/typed_probe.py +0 -0
  310. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table/versioned.py +0 -0
  311. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/table_in_out.py +0 -0
  312. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/versioned.py +0 -0
  313. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/versioned_tables.py +0 -0
  314. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/writable/__init__.py +0 -0
  315. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/writable/generic.py +0 -0
  316. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/writable/table.py +0 -0
  317. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/_test_fixtures/writable/worker.py +0 -0
  318. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/aggregate_function.py +0 -0
  319. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/argument_spec.py +0 -0
  320. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/arguments.py +0 -0
  321. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/auth.py +0 -0
  322. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/cache_control.py +0 -0
  323. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/catalog/__init__.py +0 -0
  324. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/catalog/_descriptor_spec.py +0 -0
  325. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/catalog/attach_option.py +0 -0
  326. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/catalog/duckdb_statistics.py +0 -0
  327. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/catalog/secret_type.py +0 -0
  328. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/catalog/setting.py +0 -0
  329. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/catalog/storage.py +0 -0
  330. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/client/__init__.py +0 -0
  331. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/client/catalog_mixin.py +0 -0
  332. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/client/cli.py +0 -0
  333. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/client/cli_catalog.py +0 -0
  334. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/client/cli_schema.py +0 -0
  335. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/client/cli_table.py +0 -0
  336. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/client/cli_transaction.py +0 -0
  337. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/client/cli_utils.py +0 -0
  338. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/client/cli_view.py +0 -0
  339. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/client/client.py +0 -0
  340. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/codegen/__init__.py +0 -0
  341. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/codegen/_common.py +0 -0
  342. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/codegen/cpp_constants.py +0 -0
  343. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/codegen/cpp_protocol_version.py +0 -0
  344. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/codegen/cpp_request_builders.py +0 -0
  345. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/codegen/cpp_schemas.py +0 -0
  346. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/codegen/cpp_secret_protocol_version.py +0 -0
  347. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/codegen/cpp_secret_request_builders.py +0 -0
  348. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/codegen/cpp_secret_schemas.py +0 -0
  349. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/codegen/go_schemas.py +0 -0
  350. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/codegen/protocol_version.py +0 -0
  351. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/codegen/ts_client.py +0 -0
  352. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/codegen/ts_schemas.py +0 -0
  353. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/copy_from_function.py +0 -0
  354. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/copy_to_function.py +0 -0
  355. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/exceptions.py +0 -0
  356. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/function.py +0 -0
  357. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/function_storage.py +0 -0
  358. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/function_storage_azure_sql.py +0 -0
  359. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/function_storage_cf_do.py +0 -0
  360. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/http/__init__.py +0 -0
  361. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/http/demo_storage.py +0 -0
  362. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/http/describe_json.py +0 -0
  363. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/http/landing.html +0 -0
  364. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/http/landing_page.py +0 -0
  365. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/http/worker_page.py +0 -0
  366. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/invocation.py +0 -0
  367. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/logging_config.py +0 -0
  368. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/meta_worker.py +0 -0
  369. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/metadata.py +0 -0
  370. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/otel.py +0 -0
  371. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/protocol.py +0 -0
  372. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/protocol_version.txt +0 -0
  373. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/py.typed +0 -0
  374. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/scalar_function.py +0 -0
  375. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/schema_utils.py +0 -0
  376. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/secret_protocol.py +0 -0
  377. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/secret_service.py +0 -0
  378. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/serve.py +0 -0
  379. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/table_buffering_function.py +0 -0
  380. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/table_filter_pushdown.py +0 -0
  381. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/table_function.py +0 -0
  382. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/table_in_out_function.py +0 -0
  383. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/transactor/__init__.py +0 -0
  384. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/transactor/_duckdb_compat.py +0 -0
  385. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/transactor/client.py +0 -0
  386. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/transactor/protocol.py +0 -0
  387. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/transactor/server.py +0 -0
  388. {vgi_python-0.14.0 → vgi_python-0.15.0}/vgi/worker.py +0 -0
  389. {vgi_python-0.14.0 → vgi_python-0.15.0}/wrangler.jsonc +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vgi-python
3
- Version: 0.14.0
3
+ Version: 0.15.0
4
4
  Summary: Vector Gateway Interface - Connect DuckDB to external programs via Apache Arrow
5
5
  Project-URL: Homepage, https://query.farm
6
6
  Project-URL: Repository, https://github.com/Query-farm/vgi-python
@@ -257,12 +257,43 @@ rm -f "$STAGE/test/_warm.test"
257
257
  # simple_writable); the http lane's writes self-skip.
258
258
  echo "Running suite ($SUITE_GLOB, transport=$TRANSPORT) ..."
259
259
  suite_rc=0
260
+
261
+ # run_unittest — invoke haybarn-unittest, streaming its output, and additionally
262
+ # fail on a fatal-signal report that the process's own exit code cannot express.
263
+ #
264
+ # Catch2 arms handlers for SIGTERM/SIGINT/SIGSEGV/... for the duration of a test
265
+ # case. Those handlers are inherited by any process the extension fork()s, and
266
+ # run in the child if a signal lands before it execs. The child then prints a
267
+ # full "FAILED: ... due to a fatal error condition: SIGTERM" block plus a run
268
+ # summary — the *parent's* accumulated counters, since it's an address-space
269
+ # copy — and dies. The parent never sees it, records no failure, and exits 0.
270
+ # The only trace is on stdout, so that is what we scan. Seen on the shm lane in
271
+ # https://github.com/Query-farm/vgi-python/actions/runs/29051359074.
272
+ run_unittest() {
273
+ local log rc=0
274
+ log="$(mktemp)"
275
+ # `set +e` rather than `|| true`: the latter runs before PIPESTATUS is read and
276
+ # overwrites it with true's 0, silently swallowing every real test failure.
277
+ set +e
278
+ "$HAYBARN_UNITTEST" "$@" 2>&1 | tee "$log"
279
+ rc="${PIPESTATUS[0]}"
280
+ set -e
281
+ if grep -q 'due to a fatal error condition' "$log"; then
282
+ echo "::error::a forked child ran the test harness's signal handler (see the" \
283
+ "'fatal error condition' block above). The parent exited $rc and would" \
284
+ "otherwise have passed. This is invisible to the exit code by construction."
285
+ rc=1
286
+ fi
287
+ rm -f "$log"
288
+ return "$rc"
289
+ }
290
+
260
291
  if [ "$TRANSPORT" = "launch" ]; then
261
- "$HAYBARN_UNITTEST" "$SUITE_GLOB" || suite_rc=$?
292
+ run_unittest "$SUITE_GLOB" || suite_rc=$?
262
293
  else
263
- "$HAYBARN_UNITTEST" "$SUITE_GLOB" "~test/sql/integration/simple_writable/*" || suite_rc=$?
294
+ run_unittest "$SUITE_GLOB" "~test/sql/integration/simple_writable/*" || suite_rc=$?
264
295
  echo "Running simple_writable (isolated process) ..."
265
- "$HAYBARN_UNITTEST" "test/sql/integration/simple_writable/*" || suite_rc=$?
296
+ run_unittest "test/sql/integration/simple_writable/*" || suite_rc=$?
266
297
  fi
267
298
 
268
299
  exit "$suite_rc"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "vgi-python"
3
- version = "0.14.0"
3
+ version = "0.15.0"
4
4
  description = "Vector Gateway Interface - Connect DuckDB to external programs via Apache Arrow"
5
5
  readme = "README.md"
6
6
  keywords = [
@@ -14,13 +14,13 @@ Tests cover:
14
14
  from __future__ import annotations
15
15
 
16
16
  from dataclasses import dataclass
17
- from typing import ClassVar
17
+ from typing import Annotated, ClassVar
18
18
 
19
19
  import pyarrow as pa
20
20
  import pytest
21
21
  from vgi_rpc.rpc import OutputCollector
22
22
 
23
- from vgi import Worker
23
+ from vgi import Arg, Arguments, Worker
24
24
  from vgi.catalog import (
25
25
  AttachOpaqueData,
26
26
  Catalog,
@@ -50,6 +50,7 @@ from vgi.table_function import (
50
50
  bind_fixed_schema,
51
51
  init_single_worker,
52
52
  )
53
+ from vgi.table_in_out_function import TableInOutGenerator
53
54
 
54
55
  # =============================================================================
55
56
  # Test Fixtures: Example Functions for Function-Backed Tables
@@ -61,6 +62,45 @@ class EmptyArgs:
61
62
  """No arguments."""
62
63
 
63
64
 
65
+ @dataclass(frozen=True)
66
+ class CountedRowsArgs:
67
+ """A required positional argument plus an optional named one."""
68
+
69
+ count: Annotated[int, Arg(0, doc="Number of rows to generate", ge=0)]
70
+ label: Annotated[str, Arg("label", default="rows", doc="Label for the rows")]
71
+
72
+
73
+ @init_single_worker
74
+ @bind_fixed_schema
75
+ class CountedRowsFunction(TableFunctionGenerator[CountedRowsArgs]):
76
+ """Table function with a required positional arg, for arg-propagation tests."""
77
+
78
+ class Meta: # noqa: D106
79
+ name = "counted_rows"
80
+ description = "Generate N rows"
81
+
82
+ FIXED_SCHEMA: ClassVar[pa.Schema] = schema({"n": pa.int64()})
83
+
84
+ @classmethod
85
+ def process( # noqa: D102
86
+ cls, params: ProcessParams[CountedRowsArgs], state: None, out: OutputCollector
87
+ ) -> None:
88
+ out.emit(
89
+ pa.RecordBatch.from_pydict(
90
+ {"n": list(range(params.args.count))},
91
+ schema=params.output_schema,
92
+ )
93
+ )
94
+ out.finish()
95
+
96
+
97
+ class CountedRowsInsert(TableInOutGenerator[None, None]):
98
+ """Stub insert function, for the write-path arg-propagation test."""
99
+
100
+ class Meta: # noqa: D106
101
+ name = "counted_rows_insert"
102
+
103
+
64
104
  @init_single_worker
65
105
  @bind_fixed_schema
66
106
  class UsersFunction(TableFunctionGenerator[EmptyArgs]):
@@ -262,6 +302,87 @@ class TestTableWithFunction:
262
302
  assert info.update_function is None
263
303
  assert info.delete_function is None
264
304
 
305
+ def test_inlined_scan_function_carries_declared_positional_arguments(self) -> None:
306
+ """``Table.arguments`` must reach the scan-time bind, not just ``bind()``.
307
+
308
+ Regression: the inlined ``ScanFunctionResult`` used to hardcode empty
309
+ arguments, so a backing function with a required positional ``Arg(0)``
310
+ saw zero positional args at scan and failed with
311
+ ``IndexError: Argument 0: index out of range``.
312
+ """
313
+ from vgi_rpc.utils import deserialize_record_batch
314
+
315
+ table = Table(
316
+ name="counted",
317
+ function=CountedRowsFunction,
318
+ arguments=Arguments(positional=(pa.scalar(7),)),
319
+ )
320
+ info = table.to_table_info("main")
321
+ assert info.scan_function is not None
322
+ batch, _ = deserialize_record_batch(info.scan_function)
323
+ sfr = ScanFunctionResult.deserialize(batch)
324
+ assert sfr.function_name == "counted_rows"
325
+ assert [s.as_py() for s in sfr.positional_arguments] == [7]
326
+ assert sfr.named_arguments == {}
327
+
328
+ def test_inlined_scan_function_carries_declared_named_arguments(self) -> None:
329
+ """Named args declared on the Table also reach the scan-time bind."""
330
+ from vgi_rpc.utils import deserialize_record_batch
331
+
332
+ table = Table(
333
+ name="counted",
334
+ function=CountedRowsFunction,
335
+ arguments=Arguments(
336
+ positional=(pa.scalar(3),),
337
+ named={"label": pa.scalar("widgets")},
338
+ ),
339
+ )
340
+ info = table.to_table_info("main")
341
+ assert info.scan_function is not None
342
+ batch, _ = deserialize_record_batch(info.scan_function)
343
+ sfr = ScanFunctionResult.deserialize(batch)
344
+ assert [s.as_py() for s in sfr.positional_arguments] == [3]
345
+ assert {k: v.as_py() for k, v in sfr.named_arguments.items()} == {"label": "widgets"}
346
+
347
+ def test_inlined_write_functions_ignore_table_arguments(self) -> None:
348
+ """Only the *scan* function is parameterized by ``Table.arguments``.
349
+
350
+ Insert/update/delete functions receive their rows via the streaming table
351
+ input, so their inlined results stay argument-free.
352
+ """
353
+ from vgi_rpc.utils import deserialize_record_batch
354
+
355
+ table = Table(
356
+ name="counted",
357
+ function=CountedRowsFunction,
358
+ arguments=Arguments(positional=(pa.scalar(7),)),
359
+ insert_function=CountedRowsInsert,
360
+ )
361
+ info = table.to_table_info("main")
362
+ assert info.insert_function is not None
363
+ batch, _ = deserialize_record_batch(info.insert_function)
364
+ sfr = ScanFunctionResult.deserialize(batch)
365
+ assert sfr.positional_arguments == []
366
+ assert sfr.named_arguments == {}
367
+
368
+ def test_none_positional_slot_is_rejected(self) -> None:
369
+ """A ``None`` positional slot would shift later args — reject it loudly.
370
+
371
+ Exercised on the ``scan_arguments_from`` helper directly: a Table carrying
372
+ such a slot already fails earlier, in bind()-based schema derivation. This
373
+ guards the serializer against ever silently dropping the slot instead.
374
+ """
375
+ from vgi.catalog.catalog_interface import scan_arguments_from
376
+
377
+ with pytest.raises(ValueError, match="positional slot 0 is None"):
378
+ scan_arguments_from(Arguments(positional=(None, pa.scalar(7))))
379
+
380
+ def test_scan_arguments_from_none_is_empty(self) -> None:
381
+ """A table declaring no arguments serializes empty args (unchanged behavior)."""
382
+ from vgi.catalog.catalog_interface import scan_arguments_from
383
+
384
+ assert scan_arguments_from(None) == ([], {})
385
+
265
386
  def test_table_propagates_cardinality_to_table_info(self) -> None:
266
387
  """``Table.cardinality_estimate`` / ``cardinality_max`` flow into TableInfo.
267
388
 
@@ -1121,8 +1242,6 @@ class TestSchemaDescriptor:
1121
1242
  client hits a cold miss. Reporting an explicit ``0`` for empty
1122
1243
  categories lets the client skip the bulk RPC entirely.
1123
1244
  """
1124
- from typing import Annotated
1125
-
1126
1245
  from vgi.arguments import Param, Returns
1127
1246
  from vgi.scalar_function import ScalarFunction
1128
1247
 
@@ -1174,8 +1293,6 @@ class TestLegacyFunctionsListSchemaInfo:
1174
1293
  """
1175
1294
 
1176
1295
  def _interface(self) -> ReadOnlyCatalogInterface:
1177
- from typing import Annotated
1178
-
1179
1296
  from vgi.arguments import Param, Returns
1180
1297
  from vgi.scalar_function import ScalarFunction
1181
1298
 
@@ -1694,6 +1811,70 @@ class TestTableScanFunctionGet:
1694
1811
  )
1695
1812
  assert isinstance(result, ScanFunctionResult)
1696
1813
  assert result.function_name == "users"
1814
+ # No declared Table.arguments => empty args, unchanged behavior.
1815
+ assert result.positional_arguments == []
1816
+ assert result.named_arguments == {}
1817
+
1818
+ def test_auto_scan_forwards_declared_arguments(self) -> None:
1819
+ """The RPC auto-impl forwards ``Table.arguments`` to the scan bind.
1820
+
1821
+ Companion to the inlined-path regression: workers that don't inline
1822
+ ``TableInfo.scan_function`` reach the scan through this RPC instead.
1823
+ """
1824
+ counted = Table(
1825
+ name="counted",
1826
+ function=CountedRowsFunction,
1827
+ arguments=Arguments(
1828
+ positional=(pa.scalar(7),),
1829
+ named={"label": pa.scalar("widgets")},
1830
+ ),
1831
+ )
1832
+
1833
+ class TestCatalog(ReadOnlyCatalogInterface):
1834
+ catalog = Catalog(
1835
+ name="test",
1836
+ schemas=[Schema(name="main", tables=[counted])],
1837
+ )
1838
+
1839
+ result = TestCatalog().table_scan_function_get(
1840
+ attach_opaque_data=AttachOpaqueData(b"test"),
1841
+ transaction_opaque_data=None,
1842
+ schema_name="main",
1843
+ name="counted",
1844
+ at_unit=None,
1845
+ at_value=None,
1846
+ )
1847
+ assert result.function_name == "counted_rows"
1848
+ assert [s.as_py() for s in result.positional_arguments] == [7]
1849
+ assert {k: v.as_py() for k, v in result.named_arguments.items()} == {"label": "widgets"}
1850
+
1851
+ def test_scan_branches_default_inherits_declared_arguments(self) -> None:
1852
+ """The default ``table_scan_branches_get`` delegates to the legacy method.
1853
+
1854
+ So the one-branch synthesis must carry the declared arguments too.
1855
+ """
1856
+ counted = Table(
1857
+ name="counted",
1858
+ function=CountedRowsFunction,
1859
+ arguments=Arguments(positional=(pa.scalar(7),)),
1860
+ )
1861
+
1862
+ class TestCatalog(ReadOnlyCatalogInterface):
1863
+ catalog = Catalog(
1864
+ name="test",
1865
+ schemas=[Schema(name="main", tables=[counted])],
1866
+ )
1867
+
1868
+ result = TestCatalog().table_scan_branches_get(
1869
+ attach_opaque_data=AttachOpaqueData(b"test"),
1870
+ transaction_opaque_data=None,
1871
+ schema_name="main",
1872
+ name="counted",
1873
+ at_unit=None,
1874
+ at_value=None,
1875
+ )
1876
+ assert len(result.branches) == 1
1877
+ assert [s.as_py() for s in result.branches[0].positional_arguments] == [7]
1697
1878
 
1698
1879
  def test_explicit_columns_table_raises(self) -> None:
1699
1880
  """Tables with explicit columns raise NotImplementedError."""
@@ -0,0 +1,92 @@
1
+ """Unit tests for the ``Table.required_filters`` field.
2
+
3
+ The field is purely declarative on the Python side — enforcement runs in the C++
4
+ optimizer extension. It is conjunctive normal form: an AND (outer tuple) of
5
+ OR-groups (inner tuples) of dotted-path column references. These tests cover:
6
+
7
+ 1. Default-empty behaviour (no field set → ``TableInfo`` ships an empty list).
8
+ 2. Populated round-trip (singleton groups + a multi-path OR-group preserved).
9
+ 3. Validation: each path's leading dotted segment must be a real column.
10
+ 4. Empty-string paths and empty OR-groups are rejected loudly.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import pyarrow as pa
16
+ import pytest
17
+
18
+ from vgi.catalog.descriptors import Table
19
+
20
+
21
+ class TestRequiredFiltersField:
22
+ """Behaviour of the declarative required_filters field."""
23
+
24
+ def _bbox_columns(self) -> pa.Schema:
25
+ """Return a small schema with a ``bbox`` STRUCT plus flat id/ticker."""
26
+ return pa.schema(
27
+ [
28
+ ("id", pa.int64()),
29
+ ("ticker", pa.string()),
30
+ (
31
+ "bbox",
32
+ pa.struct(
33
+ [
34
+ ("xmin", pa.float64()),
35
+ ("ymin", pa.float64()),
36
+ ("xmax", pa.float64()),
37
+ ("ymax", pa.float64()),
38
+ ]
39
+ ),
40
+ ),
41
+ ]
42
+ )
43
+
44
+ def test_default_is_empty_tuple(self) -> None:
45
+ """Default is an empty tuple; TableInfo wire field is an empty list."""
46
+ t = Table(name="t", columns=self._bbox_columns())
47
+ assert t.required_filters == ()
48
+ info = t.to_table_info("main")
49
+ assert info.required_filters == []
50
+
51
+ def test_singleton_groups_round_trip(self) -> None:
52
+ """Singleton groups (the AND-only case) survive as a list of lists."""
53
+ groups = (("bbox.xmin",), ("bbox.xmax",), ("bbox.ymin",), ("bbox.ymax",))
54
+ t = Table(name="place", columns=self._bbox_columns(), required_filters=groups)
55
+ assert t.required_filters == groups
56
+ info = t.to_table_info("main")
57
+ assert info.required_filters == [list(g) for g in groups]
58
+
59
+ def test_or_group_round_trip(self) -> None:
60
+ """A multi-path OR-group survives alongside a singleton mandatory group."""
61
+ groups = (("id",), ("id", "ticker"))
62
+ t = Table(name="t", columns=self._bbox_columns(), required_filters=groups)
63
+ info = t.to_table_info("main")
64
+ assert info.required_filters == [["id"], ["id", "ticker"]]
65
+
66
+ def test_top_level_path(self) -> None:
67
+ """A top-level column name (no dots) is a valid path."""
68
+ t = Table(name="t", columns=self._bbox_columns(), required_filters=(("id",),))
69
+ assert t.to_table_info("main").required_filters == [["id"]]
70
+
71
+ def test_nested_path_is_not_unpacked_for_validation(self) -> None:
72
+ """Only the leading dotted segment is validated; deeper segments pass through."""
73
+ # Subfield validity isn't checked here (descriptor doesn't unpack struct
74
+ # schemas) — only the leading segment matters. Typos like ``bbox.nope``
75
+ # go through and DuckDB catches them at scan time.
76
+ t = Table(name="t", columns=self._bbox_columns(), required_filters=(("bbox.nope",),))
77
+ assert t.required_filters == (("bbox.nope",),)
78
+
79
+ def test_unknown_leading_segment_raises(self) -> None:
80
+ """A path whose leading segment is not a real column is rejected."""
81
+ with pytest.raises(ValueError, match=r"unknown column 'nope'"):
82
+ Table(name="t", columns=self._bbox_columns(), required_filters=(("nope.xmin",),))
83
+
84
+ def test_empty_string_path_raises(self) -> None:
85
+ """An empty string path is rejected loudly rather than silently accepted."""
86
+ with pytest.raises(ValueError, match="must not contain empty strings"):
87
+ Table(name="t", columns=self._bbox_columns(), required_filters=(("",),))
88
+
89
+ def test_empty_group_raises(self) -> None:
90
+ """An empty OR-group is rejected loudly."""
91
+ with pytest.raises(ValueError, match="must not contain empty groups"):
92
+ Table(name="t", columns=self._bbox_columns(), required_filters=((),))
@@ -1149,10 +1149,10 @@ class TestArrowSchemaCorrectness:
1149
1149
  assert schema.field("cardinality_estimate").type == pa.int64()
1150
1150
  assert schema.field("column_statistics").type == pa.binary()
1151
1151
  assert schema.field("bind_result").type == pa.binary()
1152
- assert schema.field("required_field_filter_paths").type == pa.list_(pa.string())
1153
- # required_field_filter_paths is the LAST field (positional schema
1154
- # compatibility: old C++ extensions ignore-by-position trailing fields).
1155
- assert schema.field(len(schema) - 1).name == "required_field_filter_paths"
1152
+ assert schema.field("required_filters").type == pa.list_(pa.list_(pa.string()))
1153
+ # required_filters is the LAST field (positional schema compatibility:
1154
+ # old C++ extensions ignore-by-position trailing fields).
1155
+ assert schema.field(len(schema) - 1).name == "required_filters"
1156
1156
 
1157
1157
  def test_view_info_schema(self) -> None:
1158
1158
  """Verify ViewInfo Arrow schema."""
@@ -5,7 +5,7 @@
5
5
  "counts": {
6
6
  "functions": 183,
7
7
  "schemas": 2,
8
- "tables": 58,
8
+ "tables": 59,
9
9
  "views": 3
10
10
  },
11
11
  "data_version_spec": null,
@@ -225,9 +225,14 @@
225
225
  },
226
226
  {
227
227
  "cols": 2,
228
- "comment": "rff_none — control table with no required_field_filter_paths (opt-out fast path).",
228
+ "comment": "rff_none — control table with no required_filters (opt-out fast path).",
229
229
  "name": "rff_none"
230
230
  },
231
+ {
232
+ "cols": 2,
233
+ "comment": "rff_or — requires a filter on 'a' OR 'b' (a single OR-group).",
234
+ "name": "rff_or"
235
+ },
231
236
  {
232
237
  "cols": 2,
233
238
  "comment": "rff_parquet — native read_parquet delegation with bbox.* required filters.",
@@ -2316,13 +2321,13 @@
2316
2321
  },
2317
2322
  {
2318
2323
  "args": [],
2319
- "doc": "rff_nested — nested STRUCT(wrapper.mid.leaf) for required_field_filter_paths tests",
2324
+ "doc": "rff_nested — nested STRUCT(wrapper.mid.leaf) for required_filters tests",
2320
2325
  "name": "rff_nested_scan",
2321
2326
  "type": "table"
2322
2327
  },
2323
2328
  {
2324
2329
  "args": [],
2325
- "doc": "rff_none — control table with no required_field_filter_paths",
2330
+ "doc": "rff_none — control table with no required_filters",
2326
2331
  "name": "rff_none_scan",
2327
2332
  "type": "table"
2328
2333
  },
@@ -2334,13 +2339,13 @@
2334
2339
  },
2335
2340
  {
2336
2341
  "args": [],
2337
- "doc": "rff_simple — flat columns (a, b) for required_field_filter_paths tests",
2342
+ "doc": "rff_simple — flat columns (a, b) for required_filters tests",
2338
2343
  "name": "rff_simple_scan",
2339
2344
  "type": "table"
2340
2345
  },
2341
2346
  {
2342
2347
  "args": [],
2343
- "doc": "rff_struct — STRUCT(s.a, s.b) + other for required_field_filter_paths tests",
2348
+ "doc": "rff_struct — STRUCT(s.a, s.b) + other for required_filters tests",
2344
2349
  "name": "rff_struct_scan",
2345
2350
  "type": "table"
2346
2351
  },
@@ -3,7 +3,7 @@
3
3
  """Scan functions backing the ``rff_*`` required-filter sqllogictest Tables.
4
4
 
5
5
  Used by the ``vgi_required_filters_*.test`` matrix. These fixtures exercise
6
- the ``Table.required_field_filter_paths`` field +
6
+ the ``Table.required_filters`` field +
7
7
  the C++ optimizer extension that enforces it. The five tables form a small
8
8
  matrix:
9
9
 
@@ -99,10 +99,10 @@ RFF_NONE_COLUMNS = pa.schema(
99
99
  )
100
100
 
101
101
  # rff_rowid — a row-id column (virtual, hidden from SELECT *) alongside a bbox
102
- # struct with required_field_filter_paths. A `WHERE rowid = N` predicate pushes
102
+ # struct with required_filters. A `WHERE rowid = N` predicate pushes
103
103
  # a table_filter keyed by the COLUMN_IDENTIFIER_ROW_ID sentinel (>> column
104
104
  # count), which the optimizer's required-filter check must skip rather than
105
- # index out of bounds. See required_field_filter_paths_native.test.
105
+ # index out of bounds. See required_filters_native.test.
106
106
  RFF_ROWID_COLUMNS = pa.schema(
107
107
  [
108
108
  pa.field("row_id", pa.int64(), metadata={b"is_row_id": b""}),
@@ -124,7 +124,7 @@ RFF_ROWID_COLUMNS = pa.schema(
124
124
 
125
125
  RffSimpleScanFunction = _static_scan_function(
126
126
  func_name="rff_simple_scan",
127
- func_description="rff_simple — flat columns (a, b) for required_field_filter_paths tests",
127
+ func_description="rff_simple — flat columns (a, b) for required_filters tests",
128
128
  output_schema=RFF_SIMPLE_COLUMNS,
129
129
  data={
130
130
  "a": [1, 2, 3],
@@ -134,7 +134,7 @@ RffSimpleScanFunction = _static_scan_function(
134
134
 
135
135
  RffStructScanFunction = _static_scan_function(
136
136
  func_name="rff_struct_scan",
137
- func_description="rff_struct — STRUCT(s.a, s.b) + other for required_field_filter_paths tests",
137
+ func_description="rff_struct — STRUCT(s.a, s.b) + other for required_filters tests",
138
138
  output_schema=RFF_STRUCT_COLUMNS,
139
139
  data={
140
140
  "s": [
@@ -148,7 +148,7 @@ RffStructScanFunction = _static_scan_function(
148
148
 
149
149
  RffNestedScanFunction = _static_scan_function(
150
150
  func_name="rff_nested_scan",
151
- func_description="rff_nested — nested STRUCT(wrapper.mid.leaf) for required_field_filter_paths tests",
151
+ func_description="rff_nested — nested STRUCT(wrapper.mid.leaf) for required_filters tests",
152
152
  output_schema=RFF_NESTED_COLUMNS,
153
153
  data={
154
154
  "wrapper": [
@@ -174,7 +174,7 @@ RffMultiScanFunction = _static_scan_function(
174
174
 
175
175
  RffNoneScanFunction = _static_scan_function(
176
176
  func_name="rff_none_scan",
177
- func_description="rff_none — control table with no required_field_filter_paths",
177
+ func_description="rff_none — control table with no required_filters",
178
178
  output_schema=RFF_NONE_COLUMNS,
179
179
  data={
180
180
  "a": [1, 2, 3],