vgi-python 0.8.11__tar.gz → 0.10.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 (378) hide show
  1. {vgi_python-0.8.11 → vgi_python-0.10.0}/.github/workflows/integration.yml +3 -1
  2. {vgi_python-0.8.11 → vgi_python-0.10.0}/PKG-INFO +1 -1
  3. {vgi_python-0.8.11 → vgi_python-0.10.0}/packages/vgi-fixtures/pyproject.toml +1 -0
  4. {vgi_python-0.8.11 → vgi_python-0.10.0}/pyproject.toml +1 -1
  5. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/catalog/test_declarative.py +39 -1
  6. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/catalog/test_serialization.py +2 -1
  7. vgi_python-0.10.0/tests/conformance/test_const_param_enforcement.py +69 -0
  8. vgi_python-0.10.0/tests/conformance/test_container.py +17 -0
  9. vgi_python-0.10.0/tests/conformance/test_copy_from.py +16 -0
  10. vgi_python-0.10.0/tests/conformance/test_copy_to.py +21 -0
  11. vgi_python-0.10.0/tests/conformance/test_github.py +15 -0
  12. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_secret.py +3 -0
  13. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_aggregate_function.py +51 -1
  14. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_argument_spec.py +101 -0
  15. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_copy_to_function.py +82 -1
  16. {vgi_python-0.8.11 → vgi_python-0.10.0}/uv.lock +58 -58
  17. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/aggregate/__init__.py +2 -0
  18. vgi_python-0.10.0/vgi/_test_fixtures/aggregate/secret_typed.py +115 -0
  19. vgi_python-0.10.0/vgi/_test_fixtures/companion.py +169 -0
  20. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/copy_from.py +58 -2
  21. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/copy_to.py +78 -1
  22. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/scalar/formatting.py +2 -2
  23. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table_in_out.py +46 -0
  24. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/worker.py +56 -2
  25. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/argument_spec.py +146 -1
  26. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/arguments.py +71 -1
  27. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/catalog/__init__.py +2 -0
  28. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/catalog/catalog_interface.py +96 -2
  29. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/catalog/descriptors.py +15 -1
  30. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/codegen/_common.py +2 -0
  31. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/copy_from_function.py +22 -0
  32. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/copy_to_function.py +32 -1
  33. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/scalar_function.py +33 -1
  34. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/worker.py +16 -1
  35. {vgi_python-0.8.11 → vgi_python-0.10.0}/.gitattributes +0 -0
  36. {vgi_python-0.8.11 → vgi_python-0.10.0}/.github/dependabot.yml +0 -0
  37. {vgi_python-0.8.11 → vgi_python-0.10.0}/.github/styles/config/vocabularies/VGI/accept.txt +0 -0
  38. {vgi_python-0.8.11 → vgi_python-0.10.0}/.github/workflows/ci.yml +0 -0
  39. {vgi_python-0.8.11 → vgi_python-0.10.0}/.github/workflows/docs.yml +0 -0
  40. {vgi_python-0.8.11 → vgi_python-0.10.0}/.github/workflows/release.yml +0 -0
  41. {vgi_python-0.8.11 → vgi_python-0.10.0}/.gitignore +0 -0
  42. {vgi_python-0.8.11 → vgi_python-0.10.0}/.python-version +0 -0
  43. {vgi_python-0.8.11 → vgi_python-0.10.0}/.vale.ini +0 -0
  44. {vgi_python-0.8.11 → vgi_python-0.10.0}/CLAUDE.md +0 -0
  45. {vgi_python-0.8.11 → vgi_python-0.10.0}/DOCS_ACCEPTANCE_CRITERIA.md +0 -0
  46. {vgi_python-0.8.11 → vgi_python-0.10.0}/DOCS_REVIEW_RUBRIC.md +0 -0
  47. {vgi_python-0.8.11 → vgi_python-0.10.0}/DOCS_USABILITY_TEST.md +0 -0
  48. {vgi_python-0.8.11 → vgi_python-0.10.0}/LICENSE +0 -0
  49. {vgi_python-0.8.11 → vgi_python-0.10.0}/README.md +0 -0
  50. {vgi_python-0.8.11 → vgi_python-0.10.0}/SECURITY.md +0 -0
  51. {vgi_python-0.8.11 → vgi_python-0.10.0}/ci/README.md +0 -0
  52. {vgi_python-0.8.11 → vgi_python-0.10.0}/ci/preprocess-require.awk +0 -0
  53. {vgi_python-0.8.11 → vgi_python-0.10.0}/ci/run-integration.sh +0 -0
  54. {vgi_python-0.8.11 → vgi_python-0.10.0}/dist-vgi/.gitignore +0 -0
  55. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/aggregate-functions.md +0 -0
  56. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/api/arguments.md +0 -0
  57. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/api/auth.md +0 -0
  58. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/api/catalogs.md +0 -0
  59. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/api/client.md +0 -0
  60. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/api/exceptions.md +0 -0
  61. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/api/filters.md +0 -0
  62. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/api/functions.md +0 -0
  63. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/api/http.md +0 -0
  64. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/api/index.md +0 -0
  65. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/api/metadata.md +0 -0
  66. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/api/observability.md +0 -0
  67. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/api/storage.md +0 -0
  68. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/api/transactor.md +0 -0
  69. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/api/worker.md +0 -0
  70. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/argument-serialization.md +0 -0
  71. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/assets/apple-touch-icon.png +0 -0
  72. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/assets/favicon-16x16.png +0 -0
  73. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/assets/favicon-32x32.png +0 -0
  74. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/assets/favicon.ico +0 -0
  75. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/assets/kinds/aggregate.svg +0 -0
  76. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/assets/kinds/buffering.svg +0 -0
  77. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/assets/kinds/scalar.svg +0 -0
  78. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/assets/kinds/table-in-out.svg +0 -0
  79. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/assets/kinds/table.svg +0 -0
  80. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/assets/logo.png +0 -0
  81. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/assets/social-card.png +0 -0
  82. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/authentication.md +0 -0
  83. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/catalog-interface.md +0 -0
  84. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/cli.md +0 -0
  85. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/column-statistics.md +0 -0
  86. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/concepts/index.md +0 -0
  87. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/contributing-docs.md +0 -0
  88. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/filter-pushdown.md +0 -0
  89. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/generator-api.md +0 -0
  90. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/how-to/catalogs.md +0 -0
  91. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/how-to/function-patterns.md +0 -0
  92. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/how-to/http-auth.md +0 -0
  93. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/how-to/index.md +0 -0
  94. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/how-to/pushdown-and-statistics.md +0 -0
  95. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/how-to/state-storage.md +0 -0
  96. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/index.md +0 -0
  97. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/lifecycle.md +0 -0
  98. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/metadata.md +0 -0
  99. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/overrides/main.html +0 -0
  100. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/robots.txt +0 -0
  101. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/shared-storage.md +0 -0
  102. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/stylesheets/extra.css +0 -0
  103. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/tutorial/index.md +0 -0
  104. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/tutorial/scalar.md +0 -0
  105. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/tutorial/table.md +0 -0
  106. {vgi_python-0.8.11 → vgi_python-0.10.0}/docs/vgi-logo.png +0 -0
  107. {vgi_python-0.8.11 → vgi_python-0.10.0}/examples/calc_scalar_worker.py +0 -0
  108. {vgi_python-0.8.11 → vgi_python-0.10.0}/examples/calc_worker.py +0 -0
  109. {vgi_python-0.8.11 → vgi_python-0.10.0}/examples/filter_worker.py +0 -0
  110. {vgi_python-0.8.11 → vgi_python-0.10.0}/examples/greeting_scalar_worker.py +0 -0
  111. {vgi_python-0.8.11 → vgi_python-0.10.0}/examples/row_count_worker.py +0 -0
  112. {vgi_python-0.8.11 → vgi_python-0.10.0}/examples/series_streaming_worker.py +0 -0
  113. {vgi_python-0.8.11 → vgi_python-0.10.0}/examples/sum_worker.py +0 -0
  114. {vgi_python-0.8.11 → vgi_python-0.10.0}/mkdocs.yml +0 -0
  115. {vgi_python-0.8.11 → vgi_python-0.10.0}/packages/vgi-fixtures/LICENSE +0 -0
  116. {vgi_python-0.8.11 → vgi_python-0.10.0}/packages/vgi-fixtures/README.md +0 -0
  117. {vgi_python-0.8.11 → vgi_python-0.10.0}/packages/vgi-fixtures/docker/Dockerfile +0 -0
  118. {vgi_python-0.8.11 → vgi_python-0.10.0}/packages/vgi-fixtures/docker/docker-entrypoint.sh +0 -0
  119. {vgi_python-0.8.11 → vgi_python-0.10.0}/scripts/measure_startup.py +0 -0
  120. {vgi_python-0.8.11 → vgi_python-0.10.0}/scripts/run_all_tests.sh +0 -0
  121. {vgi_python-0.8.11 → vgi_python-0.10.0}/test-data/generate.sh +0 -0
  122. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/__init__.py +0 -0
  123. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/_http_fixtures.py +0 -0
  124. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/catalog/__init__.py +0 -0
  125. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/catalog/test_catalog_interface.py +0 -0
  126. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/catalog/test_client_catalog.py +0 -0
  127. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/catalog/test_column_statistics.py +0 -0
  128. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/catalog/test_example_worker_catalog.py +0 -0
  129. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/catalog/test_integration.py +0 -0
  130. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/catalog/test_required_field_filter_paths.py +0 -0
  131. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/catalog/test_scan_branches.py +0 -0
  132. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/catalog/test_setting.py +0 -0
  133. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/catalog/test_storage.py +0 -0
  134. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/catalog/test_time_travel.py +0 -0
  135. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/catalog/test_writable_table.py +0 -0
  136. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/client/__init__.py +0 -0
  137. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/client/test_broken_pipe.py +0 -0
  138. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/client/test_cli.py +0 -0
  139. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/client/test_cli_catalog_functions.py +0 -0
  140. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/client/test_worker_debug.py +0 -0
  141. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/__init__.py +0 -0
  142. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/_stub.py +0 -0
  143. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/conftest.py +0 -0
  144. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_accumulate.py +0 -0
  145. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_aggregate.py +0 -0
  146. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_attach.py +0 -0
  147. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_bearer_auth.py +0 -0
  148. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_directory_parity.py +0 -0
  149. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_function_inventory.py +0 -0
  150. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_http_client.py +0 -0
  151. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_http_external_location.py +0 -0
  152. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_http_upload_url.py +0 -0
  153. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_macro.py +0 -0
  154. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_overload.py +0 -0
  155. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_protocol_inventory.py +0 -0
  156. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_protocol_version.py +0 -0
  157. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_resumable_scan.py +0 -0
  158. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_scalar.py +0 -0
  159. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_scalar_attach_opaque_data.py +0 -0
  160. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_settings.py +0 -0
  161. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_table.py +0 -0
  162. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_table_in_out.py +0 -0
  163. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_view.py +0 -0
  164. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conformance/test_writable.py +0 -0
  165. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/conftest.py +0 -0
  166. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/scalar/__init__.py +0 -0
  167. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/scalar/test_bernoulli_function.py +0 -0
  168. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/scalar/test_binary_packet_function.py +0 -0
  169. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/scalar/test_client.py +0 -0
  170. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/scalar/test_conditional_message_function.py +0 -0
  171. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/scalar/test_hash_seed_function.py +0 -0
  172. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/scalar/test_multiply_by_setting_function.py +0 -0
  173. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/scalar/test_multiply_function.py +0 -0
  174. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/scalar/test_random_bytes_function.py +0 -0
  175. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/scalar/test_return_secret_value_function.py +0 -0
  176. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table/__init__.py +0 -0
  177. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table/generator/__init__.py +0 -0
  178. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table/generator/test_constant_columns_function.py +0 -0
  179. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table/generator/test_double_sequence_function.py +0 -0
  180. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table/generator/test_exception_function.py +0 -0
  181. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table/generator/test_filter_echo_function.py +0 -0
  182. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table/generator/test_logging_function.py +0 -0
  183. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table/generator/test_nested_sequence_function.py +0 -0
  184. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table/generator/test_partitioned_function.py +0 -0
  185. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table/generator/test_projected_data_function.py +0 -0
  186. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table/generator/test_sequence_function.py +0 -0
  187. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table/generator/test_settings_function.py +0 -0
  188. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table/generator/test_struct_settings_function.py +0 -0
  189. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table/generator/test_ten_thousand_function.py +0 -0
  190. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table_in_out/__init__.py +0 -0
  191. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table_in_out/generator/__init__.py +0 -0
  192. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table_in_out/generator/test_buffer_input_function.py +0 -0
  193. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table_in_out/generator/test_echo_function.py +0 -0
  194. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table_in_out/generator/test_exception_functions.py +0 -0
  195. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table_in_out/generator/test_filter_by_setting_function.py +0 -0
  196. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table_in_out/generator/test_repeat_inputs_function.py +0 -0
  197. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table_in_out/generator/test_sum_all_columns_function.py +0 -0
  198. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/table_in_out/test_client.py +0 -0
  199. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_access_log_audit.py +0 -0
  200. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_auth.py +0 -0
  201. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_bind_exceptions.py +0 -0
  202. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_bind_request_at_clause.py +0 -0
  203. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_bound_storage_conformance.py +0 -0
  204. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_catalog_auth_binding.py +0 -0
  205. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_copy_from_function.py +0 -0
  206. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_docstrings.py +0 -0
  207. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_documentation_examples.py +0 -0
  208. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_example_function_arg_types.py +0 -0
  209. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_examples_workers.py +0 -0
  210. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_exception_handling.py +0 -0
  211. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_exceptions.py +0 -0
  212. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_filter_pushdown.py +0 -0
  213. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_filter_pushdown_extension.py +0 -0
  214. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_function_storage.py +0 -0
  215. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_function_storage_azure_sql.py +0 -0
  216. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_function_storage_cf_do.py +0 -0
  217. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_function_storage_cf_do_integration.py +0 -0
  218. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_function_storage_conformance.py +0 -0
  219. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_generated_cpp_constants.py +0 -0
  220. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_generated_cpp_protocol_version.py +0 -0
  221. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_generated_cpp_request_builders.py +0 -0
  222. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_generated_cpp_schemas.py +0 -0
  223. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_generated_cpp_secret.py +0 -0
  224. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_generated_go_schemas.py +0 -0
  225. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_generated_protocol_version.py +0 -0
  226. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_generated_schemas_cross_lang.py +0 -0
  227. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_generated_ts_client.py +0 -0
  228. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_generated_ts_schemas.py +0 -0
  229. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_http_demo_storage.py +0 -0
  230. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_http_s3_offload_input.py +0 -0
  231. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_http_s3_offload_output.py +0 -0
  232. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_metadata.py +0 -0
  233. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_mypy_consolidated.py +0 -0
  234. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_nest_tensor.py +0 -0
  235. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_otel.py +0 -0
  236. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_projection_enforcement.py +0 -0
  237. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_projection_repro.py +0 -0
  238. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_protocol_classes.py +0 -0
  239. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_resolved_secrets.py +0 -0
  240. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_schema_utils.py +0 -0
  241. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_serve.py +0 -0
  242. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_setting_secret_annotations.py +0 -0
  243. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_table_buffering_function.py +0 -0
  244. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_table_function_dynamic_to_string.py +0 -0
  245. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_tcp_transport.py +0 -0
  246. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_type_bounds.py +0 -0
  247. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_union_argument.py +0 -0
  248. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_worker.py +0 -0
  249. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_worker_cli.py +0 -0
  250. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/test_worker_page.py +0 -0
  251. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/transactor/__init__.py +0 -0
  252. {vgi_python-0.8.11 → vgi_python-0.10.0}/tests/transactor/test_transactor.py +0 -0
  253. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/__init__.py +0 -0
  254. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_duckdb.py +0 -0
  255. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_storage_profile.py +0 -0
  256. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/__init__.py +0 -0
  257. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/accumulate/__init__.py +0 -0
  258. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/accumulate/worker.py +0 -0
  259. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/aggregate/_common.py +0 -0
  260. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/aggregate/basic.py +0 -0
  261. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/aggregate/dynamic.py +0 -0
  262. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/aggregate/generic.py +0 -0
  263. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/aggregate/listagg.py +0 -0
  264. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/aggregate/percentile.py +0 -0
  265. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/aggregate/streaming.py +0 -0
  266. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/aggregate/varargs.py +0 -0
  267. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/aggregate/window.py +0 -0
  268. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/attach_options.py +0 -0
  269. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/bad_enum.py +0 -0
  270. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/bad_protocol.py +0 -0
  271. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/cancellable.py +0 -0
  272. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/catalog.py +0 -0
  273. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/http_server.py +0 -0
  274. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/narrow_bind/__init__.py +0 -0
  275. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/narrow_bind/worker.py +0 -0
  276. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/nest_tensor.py +0 -0
  277. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/orchard_catalog.py +0 -0
  278. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/projection_repro/__init__.py +0 -0
  279. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/projection_repro/worker.py +0 -0
  280. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/scalar/__init__.py +0 -0
  281. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/scalar/_common.py +0 -0
  282. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/scalar/arithmetic.py +0 -0
  283. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/scalar/binary.py +0 -0
  284. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/scalar/geo.py +0 -0
  285. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/scalar/null_handling.py +0 -0
  286. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/scalar/random_demo.py +0 -0
  287. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/scalar/settings_secrets.py +0 -0
  288. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/scalar/type_info.py +0 -0
  289. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/schema_reconcile/__init__.py +0 -0
  290. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/schema_reconcile/worker.py +0 -0
  291. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/simple_writable.py +0 -0
  292. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/__init__.py +0 -0
  293. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/_common.py +0 -0
  294. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/batch_index.py +0 -0
  295. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/batch_index_broken.py +0 -0
  296. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/catalog_scans.py +0 -0
  297. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/filters.py +0 -0
  298. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/late_materialization.py +0 -0
  299. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/make_series.py +0 -0
  300. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/misc.py +0 -0
  301. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/order_modes.py +0 -0
  302. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/pairs.py +0 -0
  303. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/partition_columns.py +0 -0
  304. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/partition_columns_broken.py +0 -0
  305. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/profiling_example.py +0 -0
  306. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/required_filters.py +0 -0
  307. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/sequence.py +0 -0
  308. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/settings.py +0 -0
  309. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/transaction_storage.py +0 -0
  310. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/tt_pushdown.py +0 -0
  311. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/typed_probe.py +0 -0
  312. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/table/versioned.py +0 -0
  313. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/versioned.py +0 -0
  314. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/versioned_tables.py +0 -0
  315. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/writable/__init__.py +0 -0
  316. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/writable/generic.py +0 -0
  317. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/writable/table.py +0 -0
  318. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/_test_fixtures/writable/worker.py +0 -0
  319. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/aggregate_function.py +0 -0
  320. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/auth.py +0 -0
  321. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/catalog/_descriptor_spec.py +0 -0
  322. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/catalog/attach_option.py +0 -0
  323. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/catalog/duckdb_statistics.py +0 -0
  324. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/catalog/secret_type.py +0 -0
  325. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/catalog/setting.py +0 -0
  326. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/catalog/storage.py +0 -0
  327. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/client/__init__.py +0 -0
  328. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/client/catalog_mixin.py +0 -0
  329. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/client/cli.py +0 -0
  330. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/client/cli_catalog.py +0 -0
  331. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/client/cli_schema.py +0 -0
  332. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/client/cli_table.py +0 -0
  333. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/client/cli_transaction.py +0 -0
  334. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/client/cli_utils.py +0 -0
  335. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/client/cli_view.py +0 -0
  336. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/client/client.py +0 -0
  337. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/codegen/__init__.py +0 -0
  338. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/codegen/cpp_constants.py +0 -0
  339. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/codegen/cpp_protocol_version.py +0 -0
  340. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/codegen/cpp_request_builders.py +0 -0
  341. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/codegen/cpp_schemas.py +0 -0
  342. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/codegen/cpp_secret_protocol_version.py +0 -0
  343. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/codegen/cpp_secret_request_builders.py +0 -0
  344. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/codegen/cpp_secret_schemas.py +0 -0
  345. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/codegen/go_schemas.py +0 -0
  346. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/codegen/protocol_version.py +0 -0
  347. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/codegen/ts_client.py +0 -0
  348. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/codegen/ts_schemas.py +0 -0
  349. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/exceptions.py +0 -0
  350. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/function.py +0 -0
  351. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/function_storage.py +0 -0
  352. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/function_storage_azure_sql.py +0 -0
  353. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/function_storage_cf_do.py +0 -0
  354. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/http/__init__.py +0 -0
  355. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/http/demo_storage.py +0 -0
  356. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/http/worker_page.py +0 -0
  357. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/invocation.py +0 -0
  358. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/logging_config.py +0 -0
  359. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/meta_worker.py +0 -0
  360. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/metadata.py +0 -0
  361. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/otel.py +0 -0
  362. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/protocol.py +0 -0
  363. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/protocol_version.txt +0 -0
  364. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/py.typed +0 -0
  365. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/schema_utils.py +0 -0
  366. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/secret_protocol.py +0 -0
  367. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/secret_service.py +0 -0
  368. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/serve.py +0 -0
  369. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/table_buffering_function.py +0 -0
  370. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/table_filter_pushdown.py +0 -0
  371. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/table_function.py +0 -0
  372. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/table_in_out_function.py +0 -0
  373. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/transactor/__init__.py +0 -0
  374. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/transactor/_duckdb_compat.py +0 -0
  375. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/transactor/client.py +0 -0
  376. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/transactor/protocol.py +0 -0
  377. {vgi_python-0.8.11 → vgi_python-0.10.0}/vgi/transactor/server.py +0 -0
  378. {vgi_python-0.8.11 → vgi_python-0.10.0}/wrangler.jsonc +0 -0
@@ -39,7 +39,9 @@ jobs:
39
39
  runs-on: ubuntu-latest
40
40
  timeout-minutes: 45
41
41
  strategy:
42
- fail-fast: false
42
+ # If any transport leg fails, cancel the rest — one broken transport means
43
+ # the build is broken; no value in burning ~45 min finishing the others.
44
+ fail-fast: true
43
45
  matrix:
44
46
  include:
45
47
  # stdio: the subprocess transport (whole suite — the primary lane).
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vgi-python
3
- Version: 0.8.11
3
+ Version: 0.10.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
@@ -38,6 +38,7 @@ dependencies = ["vgi-python[test-fixtures-writable]", "vgi-python[duckdb]"]
38
38
 
39
39
  [project.scripts]
40
40
  vgi-fixture-worker = "vgi._test_fixtures.worker:main"
41
+ vgi-fixture-companion-worker = "vgi._test_fixtures.companion:main"
41
42
  vgi-fixture-http = "vgi._test_fixtures.http_server:main"
42
43
  vgi-fixture-versioned-worker = "vgi._test_fixtures.versioned:main"
43
44
  vgi-fixture-versioned-tables-worker = "vgi._test_fixtures.versioned_tables:main"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "vgi-python"
3
- version = "0.8.11"
3
+ version = "0.10.0"
4
4
  description = "Vector Gateway Interface - Connect DuckDB to external programs via Apache Arrow"
5
5
  readme = "README.md"
6
6
  keywords = [
@@ -41,8 +41,10 @@ from vgi.catalog import (
41
41
  View,
42
42
  ViewInfo,
43
43
  )
44
+ from vgi.invocation import BindResponse
44
45
  from vgi.schema_utils import schema
45
46
  from vgi.table_function import (
47
+ BindParams,
46
48
  ProcessParams,
47
49
  TableFunctionGenerator,
48
50
  bind_fixed_schema,
@@ -81,6 +83,31 @@ class UsersFunction(TableFunctionGenerator[EmptyArgs]):
81
83
  out.finish()
82
84
 
83
85
 
86
+ @init_single_worker
87
+ class SecretLookupFunction(TableFunctionGenerator[EmptyArgs]):
88
+ """Backing function whose ``on_bind`` performs a two-phase secret lookup.
89
+
90
+ This exercises the bug where ``Table(function=...)`` schema derivation took
91
+ the empty secret-scope-request schema instead of retrying the bind.
92
+ """
93
+
94
+ class Meta: # noqa: D106
95
+ name = "secret_scan"
96
+ description = "Backing function that looks up a secret at bind time"
97
+
98
+ FIXED_SCHEMA: ClassVar[pa.Schema] = schema({"id": pa.int64(), "name": pa.string()})
99
+
100
+ @classmethod
101
+ def on_bind(cls, params: BindParams[EmptyArgs]) -> BindResponse: # noqa: D102
102
+ params.secrets.get("some_secret") # unresolved -> registers a two-phase lookup
103
+ return BindResponse(output_schema=cls.FIXED_SCHEMA)
104
+
105
+ @classmethod
106
+ def process(cls, params: ProcessParams[EmptyArgs], state: None, out: OutputCollector) -> None: # noqa: D102
107
+ out.emit(pa.RecordBatch.from_pydict({"id": [1], "name": ["x"]}, schema=params.output_schema))
108
+ out.finish()
109
+
110
+
84
111
  @init_single_worker
85
112
  @bind_fixed_schema
86
113
  class EventsFunction(TableFunctionGenerator[EmptyArgs]):
@@ -186,6 +213,18 @@ class TestTableWithFunction:
186
213
  assert resolved.field(0).name == "id"
187
214
  assert resolved.field(1).name == "name"
188
215
 
216
+ def test_function_backed_table_derives_schema_despite_secret_lookup(self) -> None:
217
+ """A backing function that calls secrets.get() in on_bind still yields its schema.
218
+
219
+ Regression: on_bind's two-phase secret lookup makes the first bind return an
220
+ empty secret-scope-request schema; schema derivation must retry with resolved
221
+ secrets rather than adopt the empty schema (which produced 0-column tables).
222
+ """
223
+ table = Table(name="things", function=SecretLookupFunction)
224
+ resolved = table.resolved_columns
225
+ assert [f.name for f in resolved] == ["id", "name"]
226
+ assert len(resolved) == 2
227
+
189
228
  def test_table_function_backed_with_constraints(self) -> None:
190
229
  """Function-backed table can have constraints validated."""
191
230
  table = Table(
@@ -336,7 +375,6 @@ class TestTableWithFunction:
336
375
  from typing import Any as _Any
337
376
 
338
377
  from vgi.invocation import BindResponse
339
- from vgi.table_function import BindParams
340
378
 
341
379
  @init_single_worker
342
380
  class _ManualBindFn(TableFunctionGenerator[EmptyArgs]):
@@ -1110,7 +1110,7 @@ class TestArrowSchemaCorrectness:
1110
1110
  def test_catalog_attach_result_schema(self) -> None:
1111
1111
  """Verify CatalogAttachResult Arrow schema."""
1112
1112
  schema = CatalogAttachResult.ARROW_SCHEMA
1113
- assert len(schema) == 14
1113
+ assert len(schema) == 15
1114
1114
  assert schema.field("attach_opaque_data").type == pa.binary()
1115
1115
  assert schema.field("supports_transactions").type == pa.bool_()
1116
1116
  assert schema.field("supports_time_travel").type == pa.bool_()
@@ -1120,6 +1120,7 @@ class TestArrowSchemaCorrectness:
1120
1120
  assert schema.field("default_schema").type == pa.string()
1121
1121
  assert schema.field("settings").type == pa.list_(pa.binary())
1122
1122
  assert schema.field("secret_types").type == pa.list_(pa.binary())
1123
+ assert schema.field("attach_catalogs").type == pa.list_(pa.binary())
1123
1124
  assert schema.field("resolved_data_version").type == pa.string()
1124
1125
  assert schema.field("resolved_implementation_version").type == pa.string()
1125
1126
 
@@ -0,0 +1,69 @@
1
+ # Copyright 2025, 2026 Query Farm LLC - https://query.farm
2
+
3
+ """Conformance test: ConstParam value constraints are enforced at bind.
4
+
5
+ A ``ConstParam`` may declare ``choices``/``ge``/``le``/``gt``/``lt``/``pattern``.
6
+ Those are surfaced for agent discovery (via ``vgi_function_arguments()``) AND
7
+ must be enforced: a const value that violates a declared constraint fails at
8
+ bind with ``ArgumentValidationError``, rather than silently reaching
9
+ ``compute()``. This mirrors the legacy ``Arg`` descriptor path.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from typing import Annotated
15
+
16
+ import pyarrow as pa
17
+ import pytest
18
+
19
+ from vgi.arguments import Arguments, ArgumentValidationError, ConstParam, Param, Returns
20
+ from vgi.protocol import BindRequest, FunctionType
21
+ from vgi.scalar_function import BindResult, ScalarFunction
22
+
23
+
24
+ class _Measure(ScalarFunction):
25
+ class Meta:
26
+ name = "measure"
27
+
28
+ @classmethod
29
+ def on_bind(cls, params: object) -> BindResult:
30
+ return BindResult(pa.string())
31
+
32
+ @classmethod
33
+ def compute(
34
+ cls,
35
+ unit: Annotated[str, ConstParam("Output unit", choices=["mm", "cm", "m"])],
36
+ precision: Annotated[int, ConstParam("Decimals", ge=0, le=10)],
37
+ value: Annotated[pa.DoubleArray, Param(doc="Value")],
38
+ ) -> Annotated[pa.StringArray, Returns()]:
39
+ return pa.array([str(value)], type=pa.string())
40
+
41
+
42
+ def _bind(unit: str, precision: int) -> None:
43
+ _Measure.bind(
44
+ BindRequest(
45
+ function_name="measure",
46
+ arguments=Arguments(positional=(pa.scalar(unit), pa.scalar(precision))),
47
+ function_type=FunctionType.SCALAR,
48
+ input_schema=pa.schema([("value", pa.float64())]),
49
+ )
50
+ )
51
+
52
+
53
+ def test_valid_const_values_bind() -> None:
54
+ """A const value inside every declared constraint binds cleanly."""
55
+ _bind("cm", 2)
56
+
57
+
58
+ def test_choice_violation_raises_at_bind() -> None:
59
+ """A const value outside the choice set fails at bind."""
60
+ with pytest.raises(ArgumentValidationError) as exc:
61
+ _bind("xx", 2)
62
+ assert "unit" in str(exc.value)
63
+
64
+
65
+ def test_range_violation_raises_at_bind() -> None:
66
+ """A const value outside the numeric range fails at bind."""
67
+ with pytest.raises(ArgumentValidationError) as exc:
68
+ _bind("cm", 99)
69
+ assert "precision" in str(exc.value)
@@ -0,0 +1,17 @@
1
+ # Copyright 2025, 2026 Query Farm LLC - https://query.farm
2
+
3
+ """Conformance stub for ``vgi/test/sql/integration/container/``."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from tests.conformance._stub import skip_area
8
+
9
+ skip_area(
10
+ "container",
11
+ [
12
+ "errors.test",
13
+ "shared_http.test",
14
+ "shared_tcp.test",
15
+ "sklearn_smoke.test",
16
+ ],
17
+ )
@@ -0,0 +1,16 @@
1
+ # Copyright 2025, 2026 Query Farm LLC - https://query.farm
2
+
3
+ """Conformance stub for ``vgi/test/sql/integration/copy_from/``."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from tests.conformance._stub import skip_area
8
+
9
+ skip_area(
10
+ "copy_from",
11
+ [
12
+ "basic.test",
13
+ "options.test",
14
+ "secrets.test",
15
+ ],
16
+ )
@@ -0,0 +1,21 @@
1
+ # Copyright 2025, 2026 Query Farm LLC - https://query.farm
2
+
3
+ """Conformance stub for ``vgi/test/sql/integration/copy_to/``."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from tests.conformance._stub import skip_area
8
+
9
+ skip_area(
10
+ "copy_to",
11
+ [
12
+ "basic.test",
13
+ "failure.test",
14
+ "options.test",
15
+ "ordered.test",
16
+ "parallel.test",
17
+ "secrets.test",
18
+ "tmp_file.test",
19
+ "types.test",
20
+ ],
21
+ )
@@ -0,0 +1,15 @@
1
+ # Copyright 2025, 2026 Query Farm LLC - https://query.farm
2
+
3
+ """Conformance stub for ``vgi/test/sql/integration/github/``."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from tests.conformance._stub import skip_area
8
+
9
+ skip_area(
10
+ "github",
11
+ [
12
+ "download.test",
13
+ "errors.test",
14
+ ],
15
+ )
@@ -9,10 +9,13 @@ from tests.conformance._stub import skip_area
9
9
  skip_area(
10
10
  "secret",
11
11
  [
12
+ "secret_aggregate.test",
13
+ "secret_function_backed_table.test",
12
14
  "secret_no_secret.test",
13
15
  "secret_registration.test",
14
16
  "secret_scalar.test",
15
17
  "secret_scoped.test",
16
18
  "secret_table_function.test",
19
+ "secret_table_in_out.test",
17
20
  ],
18
21
  )
@@ -13,7 +13,14 @@ import pytest
13
13
  from vgi_rpc import ArrowSerializableDataclass, ArrowType
14
14
 
15
15
  from vgi.aggregate_function import AggregateFunction
16
- from vgi.arguments import ConstParam, Param, Returns
16
+ from vgi.arguments import (
17
+ Arguments,
18
+ ArgumentValidationError,
19
+ ConstParam,
20
+ Param,
21
+ Returns,
22
+ validate_const_arg_constraints,
23
+ )
17
24
  from vgi.table_function import ProcessParams
18
25
 
19
26
  # ---------------------------------------------------------------------------
@@ -199,6 +206,49 @@ class TestInitSubclassParameterExtraction:
199
206
  assert arg.arrow_type == pa.float64()
200
207
  assert arg.const is True
201
208
 
209
+ def test_const_param_constraints_enforced(self) -> None:
210
+ """A ConstParam's declared constraints are enforced at bind (same as scalar)."""
211
+
212
+ class BoundedAgg(AggregateFunction[SimpleState]):
213
+ class Meta:
214
+ name = "test_bounded_agg"
215
+
216
+ @classmethod
217
+ def initial_state(cls, params: ProcessParams[Any]) -> SimpleState:
218
+ return SimpleState()
219
+
220
+ @classmethod
221
+ def update(
222
+ cls,
223
+ states: dict[int, SimpleState],
224
+ group_ids: pa.Int64Array,
225
+ value: Annotated[pa.DoubleArray, Param(doc="Values")],
226
+ mode: Annotated[str, ConstParam("Mode", choices=["min", "max"])] = "min",
227
+ ) -> None:
228
+ pass
229
+
230
+ @classmethod
231
+ def combine(cls, source: SimpleState, target: SimpleState, params: ProcessParams[Any]) -> SimpleState:
232
+ return SimpleState()
233
+
234
+ @classmethod
235
+ def finalize(
236
+ cls,
237
+ group_ids: pa.Int64Array,
238
+ states: dict[int, SimpleState],
239
+ params: ProcessParams[Any],
240
+ ) -> Annotated[pa.RecordBatch, Returns(pa.float64())]:
241
+ return pa.record_batch({"result": pa.array([], type=pa.float64())})
242
+
243
+ # The ConstParam carries its choices (threaded via _const_param_to_arg)...
244
+ const_params = BoundedAgg._const_params
245
+ assert const_params["mode"].choices == ["min", "max"]
246
+ # ...and the shared bind-time validator (called by aggregate_bind) enforces it.
247
+ validate_const_arg_constraints(const_params, Arguments(positional=(pa.scalar("max"),)))
248
+ with pytest.raises(ArgumentValidationError) as exc:
249
+ validate_const_arg_constraints(const_params, Arguments(positional=(pa.scalar("median"),)))
250
+ assert "mode" in str(exc.value)
251
+
202
252
  def test_const_param_phases(self) -> None:
203
253
  """ConstParam phase values are stored correctly."""
204
254
 
@@ -12,13 +12,18 @@ import pytest
12
12
  from vgi.argument_spec import (
13
13
  VGI_ARG_KEY,
14
14
  VGI_ARG_NAMED,
15
+ VGI_CHOICES_KEY,
16
+ VGI_DEFAULT_KEY,
15
17
  VGI_DOC_KEY,
18
+ VGI_PATTERN_KEY,
19
+ VGI_RANGE_KEY,
16
20
  VGI_TYPE_ANY,
17
21
  VGI_TYPE_KEY,
18
22
  VGI_TYPE_TABLE,
19
23
  VGI_VARARGS_KEY,
20
24
  VGI_VARARGS_TRUE,
21
25
  ArgumentSpec,
26
+ _format_range,
22
27
  argument_specs_to_schema,
23
28
  extract_argument_specs,
24
29
  schema_to_argument_specs,
@@ -722,3 +727,99 @@ class TestArgumentDoc:
722
727
  specs = {s.name: s for s in extract_argument_specs(FunctionWithDocs)}
723
728
  assert specs["unit"].doc == "Unit string, e.g. 'mi'"
724
729
  assert specs["scale"].doc == ""
730
+
731
+
732
+ class TestArgumentConstraints:
733
+ """Per-argument constraint metadata (choices / range / pattern / default)."""
734
+
735
+ def test_format_range_notation(self) -> None:
736
+ """Interval notation covers inclusive, exclusive, open, and empty bounds."""
737
+ assert _format_range(0, 100, None, None) == "[0, 100]"
738
+ assert _format_range(None, None, 0, None) == "(0, +inf)"
739
+ assert _format_range(1, None, None, 10) == "[1, 10)"
740
+ assert _format_range(None, 5, None, None) == "(-inf, 5]"
741
+ assert _format_range(None, None, None, None) is None
742
+
743
+ def test_writer_emits_constraint_keys(self) -> None:
744
+ """A constrained spec writes value-encoded constraint metadata keys."""
745
+ spec = ArgumentSpec(
746
+ name="unit",
747
+ position="unit",
748
+ arrow_type=pa.utf8(),
749
+ default_json='"mm"',
750
+ choices_json='["mm", "cm", "m"]',
751
+ range_notation="[0, 100]",
752
+ pattern="^[A-Z]{2}$",
753
+ )
754
+ meta = argument_specs_to_schema([spec])[0].metadata
755
+ assert meta[VGI_DEFAULT_KEY] == b'"mm"'
756
+ assert meta[VGI_CHOICES_KEY] == b'["mm", "cm", "m"]'
757
+ assert meta[VGI_RANGE_KEY] == b"[0, 100]"
758
+ assert meta[VGI_PATTERN_KEY] == b"^[A-Z]{2}$"
759
+
760
+ def test_unconstrained_arg_omits_keys(self) -> None:
761
+ """An arg without constraints yields none of the constraint keys."""
762
+ meta = argument_specs_to_schema([ArgumentSpec(name="v", position=0, arrow_type=pa.int64())])[0].metadata
763
+ for key in (VGI_DEFAULT_KEY, VGI_CHOICES_KEY, VGI_RANGE_KEY, VGI_PATTERN_KEY):
764
+ assert meta is None or key not in meta
765
+
766
+ def test_constraints_round_trip(self) -> None:
767
+ """Constraint metadata survives the schema round-trip."""
768
+ spec = ArgumentSpec(
769
+ name="mode",
770
+ position="mode",
771
+ arrow_type=pa.utf8(),
772
+ default_json='"add"',
773
+ choices_json='["add", "mul"]',
774
+ range_notation="[0, 10)",
775
+ pattern="^x+$",
776
+ )
777
+ out = schema_to_argument_specs(argument_specs_to_schema([spec]))[0]
778
+ assert out.default_json == '"add"'
779
+ assert out.choices_json == '["add", "mul"]'
780
+ assert out.range_notation == "[0, 10)"
781
+ assert out.pattern == "^x+$"
782
+
783
+ def test_extract_constraints_from_arg(self) -> None:
784
+ """extract_argument_specs reads choices/default/bounds/pattern off Arg."""
785
+
786
+ class FunctionWithConstraints(TableInOutFunction): # type: ignore[type-arg]
787
+ mode: str = Arg[str]( # type: ignore[assignment]
788
+ "mode", doc="Blend mode", choices=["add", "mul"], default="add"
789
+ )
790
+ level: int = Arg[int](0, ge=1, le=10) # type: ignore[assignment]
791
+ code: str = Arg[str](1, pattern="^[A-Z]{2}$") # type: ignore[assignment]
792
+
793
+ specs = {s.name: s for s in extract_argument_specs(FunctionWithConstraints)}
794
+ assert specs["mode"].choices_json == '["add", "mul"]'
795
+ assert specs["mode"].default_json == '"add"'
796
+ assert specs["level"].range_notation == "[1, 10]"
797
+ assert specs["code"].pattern == "^[A-Z]{2}$"
798
+
799
+ def test_const_param_constraints_surface(self) -> None:
800
+ """The modern Param/ConstParam API surfaces choices / range / pattern."""
801
+ from vgi.arguments import ConstParam, Param, Returns
802
+ from vgi.scalar_function import ScalarFunction
803
+
804
+ class ConstrainedScalar(ScalarFunction):
805
+ class Meta:
806
+ name = "constrained_scalar"
807
+ description = "constraint demo"
808
+
809
+ @classmethod
810
+ def compute(
811
+ cls,
812
+ unit: Annotated[str, ConstParam("Output unit", choices=["mm", "cm", "m"])],
813
+ precision: Annotated[int, ConstParam("Decimals", ge=0, le=10)],
814
+ code: Annotated[str, ConstParam("Label code", pattern="^[A-Z]{2}$")],
815
+ value: Annotated[pa.DoubleArray, Param(doc="Value")],
816
+ ) -> Annotated[pa.StringArray, Returns()]:
817
+ return value # never executed — the test only reads arg specs
818
+
819
+ specs = {s.name: s for s in extract_argument_specs(ConstrainedScalar)}
820
+ assert specs["unit"].choices_json == '["mm", "cm", "m"]'
821
+ assert specs["precision"].range_notation == "[0, 10]"
822
+ assert specs["code"].pattern == "^[A-Z]{2}$"
823
+ # The columnar Param carries no constraints.
824
+ assert specs["value"].choices_json is None
825
+ assert specs["value"].range_notation is None
@@ -9,8 +9,14 @@ import types
9
9
 
10
10
  import pyarrow as pa
11
11
 
12
- from vgi._test_fixtures.copy_to import ExampleLinesCopyToArgs, ExampleLinesCopyToFunction
12
+ from vgi._test_fixtures.copy_to import (
13
+ ExampleLinesCopyToArgs,
14
+ ExampleLinesCopyToFunction,
15
+ SecretLinesCopyToArgs,
16
+ SecretLinesCopyToFunction,
17
+ )
13
18
  from vgi._test_fixtures.worker import ExampleCatalog
19
+ from vgi.table_function import ResolvedSecrets, SecretsAccessor
14
20
 
15
21
  SCHEMA = pa.schema([("a", pa.int64()), ("b", pa.string())])
16
22
 
@@ -100,6 +106,81 @@ def test_close_empty_input_with_header_writes_header_only() -> None:
100
106
  assert _read(out_name) == "a,b\n"
101
107
 
102
108
 
109
+ # ---------------------------------------------------------------------------
110
+ # Secret forwarding (CopyToFunction.on_secrets hook)
111
+ # ---------------------------------------------------------------------------
112
+
113
+
114
+ def _secret_params(store: _Store, secrets: ResolvedSecrets) -> types.SimpleNamespace:
115
+ """A TableBufferingParams-shaped stub carrying resolved secrets for write/close."""
116
+ bind_call = types.SimpleNamespace(input_schema=SCHEMA)
117
+ init_call = types.SimpleNamespace(bind_call=bind_call)
118
+ return types.SimpleNamespace(storage=store, init_call=init_call, execution_id=b"x", secrets=secrets)
119
+
120
+
121
+ def test_on_secrets_requests_destination_scoped_secret() -> None:
122
+ """on_secrets() registers a pending lookup scoped to the COPY destination path."""
123
+ accessor = SecretsAccessor(None) # nothing resolved yet → first-call behavior
124
+ params = types.SimpleNamespace(
125
+ args=SecretLinesCopyToArgs(), # default secret_type='vgi_example'
126
+ bind_call=types.SimpleNamespace(copy_to=types.SimpleNamespace(file_path="s3://bucket/out.bin")),
127
+ secrets=accessor,
128
+ )
129
+ SecretLinesCopyToFunction.on_secrets(params)
130
+ # The hook must have asked the framework for a scoped two-phase resolution.
131
+ assert accessor.needs_resolution
132
+ pending = accessor.pending_lookups
133
+ assert len(pending) == 1
134
+ assert pending[0].secret_type == "vgi_example"
135
+ assert pending[0].scope == "s3://bucket/out.bin"
136
+
137
+
138
+ def test_close_forwards_resolved_secret_api_key() -> None:
139
+ """close() writes the resolved (destination-scoped) secret's api_key + row count."""
140
+ store = _Store()
141
+ out_name = _tmp_path()
142
+ secrets = ResolvedSecrets(
143
+ {
144
+ "writer_creds": {
145
+ "type": pa.scalar("vgi_example"),
146
+ "scope": pa.scalar(out_name),
147
+ "api_key": pa.scalar("WRITER_KEY"),
148
+ }
149
+ }
150
+ )
151
+ params = _secret_params(store, secrets)
152
+ opts = SecretLinesCopyToArgs()
153
+
154
+ SecretLinesCopyToFunction.write(
155
+ batch=pa.record_batch({"a": [1, 2], "b": ["x", "y"]}, schema=SCHEMA),
156
+ options=opts,
157
+ file_path=out_name,
158
+ params=params,
159
+ )
160
+ n = SecretLinesCopyToFunction.close(options=opts, file_path=out_name, params=params)
161
+ assert n == 2
162
+ assert _read(out_name) == "api_key=WRITER_KEY\nrows=2\n"
163
+
164
+
165
+ def test_close_writes_none_when_secret_absent() -> None:
166
+ """A genuinely missing secret resolves to 'NONE' (silent miss, not an error)."""
167
+ store = _Store()
168
+ out_name = _tmp_path()
169
+ params = _secret_params(store, ResolvedSecrets())
170
+ opts = SecretLinesCopyToArgs()
171
+ n = SecretLinesCopyToFunction.close(options=opts, file_path=out_name, params=params)
172
+ assert n == 0
173
+ assert _read(out_name) == "api_key=NONE\nrows=0\n"
174
+
175
+
176
+ def test_catalog_advertises_secret_lines_out_format() -> None:
177
+ """The secret-forwarding writer is advertised like any other COPY TO format."""
178
+ formats = ExampleCatalog().copy_from_formats(attach_opaque_data=b"", transaction_opaque_data=None)
179
+ by = {(f.direction, f.format_name): f for f in formats}
180
+ assert ("to", "secret_lines_out") in by
181
+ assert by[("to", "secret_lines_out")].handler == "secret_lines_writer"
182
+
183
+
103
184
  def test_catalog_advertises_copy_to_format() -> None:
104
185
  """The example catalog advertises example_lines_out with direction='to'."""
105
186
  formats = ExampleCatalog().copy_from_formats(attach_opaque_data=b"", transaction_opaque_data=None)