vgi-python 0.8.8__tar.gz → 0.8.10__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 (370) hide show
  1. {vgi_python-0.8.8 → vgi_python-0.8.10}/PKG-INFO +1 -2
  2. {vgi_python-0.8.8 → vgi_python-0.8.10}/ci/run-integration.sh +12 -1
  3. {vgi_python-0.8.8 → vgi_python-0.8.10}/pyproject.toml +10 -4
  4. vgi_python-0.8.10/tests/test_docstrings.py +65 -0
  5. {vgi_python-0.8.8 → vgi_python-0.8.10}/uv.lock +1 -25
  6. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/copy_from.py +1 -1
  7. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/arithmetic.py +10 -2
  8. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/arguments.py +41 -0
  9. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/catalog/__init__.py +2 -0
  10. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/protocol.py +4 -0
  11. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/scalar_function.py +45 -3
  12. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/table_function.py +3 -3
  13. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/worker.py +10 -9
  14. vgi_python-0.8.8/tests/test_docstrings.py +0 -60
  15. {vgi_python-0.8.8 → vgi_python-0.8.10}/.gitattributes +0 -0
  16. {vgi_python-0.8.8 → vgi_python-0.8.10}/.github/dependabot.yml +0 -0
  17. {vgi_python-0.8.8 → vgi_python-0.8.10}/.github/styles/config/vocabularies/VGI/accept.txt +0 -0
  18. {vgi_python-0.8.8 → vgi_python-0.8.10}/.github/workflows/ci.yml +0 -0
  19. {vgi_python-0.8.8 → vgi_python-0.8.10}/.github/workflows/docs.yml +0 -0
  20. {vgi_python-0.8.8 → vgi_python-0.8.10}/.github/workflows/integration.yml +0 -0
  21. {vgi_python-0.8.8 → vgi_python-0.8.10}/.github/workflows/release.yml +0 -0
  22. {vgi_python-0.8.8 → vgi_python-0.8.10}/.gitignore +0 -0
  23. {vgi_python-0.8.8 → vgi_python-0.8.10}/.python-version +0 -0
  24. {vgi_python-0.8.8 → vgi_python-0.8.10}/.vale.ini +0 -0
  25. {vgi_python-0.8.8 → vgi_python-0.8.10}/CLAUDE.md +0 -0
  26. {vgi_python-0.8.8 → vgi_python-0.8.10}/DOCS_ACCEPTANCE_CRITERIA.md +0 -0
  27. {vgi_python-0.8.8 → vgi_python-0.8.10}/DOCS_REVIEW_RUBRIC.md +0 -0
  28. {vgi_python-0.8.8 → vgi_python-0.8.10}/DOCS_USABILITY_TEST.md +0 -0
  29. {vgi_python-0.8.8 → vgi_python-0.8.10}/LICENSE +0 -0
  30. {vgi_python-0.8.8 → vgi_python-0.8.10}/README.md +0 -0
  31. {vgi_python-0.8.8 → vgi_python-0.8.10}/SECURITY.md +0 -0
  32. {vgi_python-0.8.8 → vgi_python-0.8.10}/ci/README.md +0 -0
  33. {vgi_python-0.8.8 → vgi_python-0.8.10}/ci/preprocess-require.awk +0 -0
  34. {vgi_python-0.8.8 → vgi_python-0.8.10}/dist-vgi/.gitignore +0 -0
  35. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/aggregate-functions.md +0 -0
  36. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/arguments.md +0 -0
  37. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/auth.md +0 -0
  38. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/catalogs.md +0 -0
  39. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/client.md +0 -0
  40. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/exceptions.md +0 -0
  41. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/filters.md +0 -0
  42. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/functions.md +0 -0
  43. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/http.md +0 -0
  44. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/index.md +0 -0
  45. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/metadata.md +0 -0
  46. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/observability.md +0 -0
  47. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/storage.md +0 -0
  48. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/transactor.md +0 -0
  49. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/api/worker.md +0 -0
  50. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/argument-serialization.md +0 -0
  51. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/apple-touch-icon.png +0 -0
  52. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/favicon-16x16.png +0 -0
  53. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/favicon-32x32.png +0 -0
  54. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/favicon.ico +0 -0
  55. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/kinds/aggregate.svg +0 -0
  56. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/kinds/buffering.svg +0 -0
  57. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/kinds/scalar.svg +0 -0
  58. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/kinds/table-in-out.svg +0 -0
  59. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/kinds/table.svg +0 -0
  60. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/logo.png +0 -0
  61. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/assets/social-card.png +0 -0
  62. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/authentication.md +0 -0
  63. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/catalog-interface.md +0 -0
  64. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/cli.md +0 -0
  65. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/column-statistics.md +0 -0
  66. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/concepts/index.md +0 -0
  67. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/contributing-docs.md +0 -0
  68. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/filter-pushdown.md +0 -0
  69. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/generator-api.md +0 -0
  70. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/how-to/catalogs.md +0 -0
  71. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/how-to/function-patterns.md +0 -0
  72. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/how-to/http-auth.md +0 -0
  73. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/how-to/index.md +0 -0
  74. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/how-to/pushdown-and-statistics.md +0 -0
  75. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/how-to/state-storage.md +0 -0
  76. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/index.md +0 -0
  77. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/lifecycle.md +0 -0
  78. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/metadata.md +0 -0
  79. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/overrides/main.html +0 -0
  80. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/robots.txt +0 -0
  81. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/shared-storage.md +0 -0
  82. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/stylesheets/extra.css +0 -0
  83. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/tutorial/index.md +0 -0
  84. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/tutorial/scalar.md +0 -0
  85. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/tutorial/table.md +0 -0
  86. {vgi_python-0.8.8 → vgi_python-0.8.10}/docs/vgi-logo.png +0 -0
  87. {vgi_python-0.8.8 → vgi_python-0.8.10}/examples/calc_scalar_worker.py +0 -0
  88. {vgi_python-0.8.8 → vgi_python-0.8.10}/examples/calc_worker.py +0 -0
  89. {vgi_python-0.8.8 → vgi_python-0.8.10}/examples/filter_worker.py +0 -0
  90. {vgi_python-0.8.8 → vgi_python-0.8.10}/examples/greeting_scalar_worker.py +0 -0
  91. {vgi_python-0.8.8 → vgi_python-0.8.10}/examples/row_count_worker.py +0 -0
  92. {vgi_python-0.8.8 → vgi_python-0.8.10}/examples/series_streaming_worker.py +0 -0
  93. {vgi_python-0.8.8 → vgi_python-0.8.10}/examples/sum_worker.py +0 -0
  94. {vgi_python-0.8.8 → vgi_python-0.8.10}/mkdocs.yml +0 -0
  95. {vgi_python-0.8.8 → vgi_python-0.8.10}/packages/vgi-fixtures/LICENSE +0 -0
  96. {vgi_python-0.8.8 → vgi_python-0.8.10}/packages/vgi-fixtures/README.md +0 -0
  97. {vgi_python-0.8.8 → vgi_python-0.8.10}/packages/vgi-fixtures/pyproject.toml +0 -0
  98. {vgi_python-0.8.8 → vgi_python-0.8.10}/scripts/measure_startup.py +0 -0
  99. {vgi_python-0.8.8 → vgi_python-0.8.10}/scripts/run_all_tests.sh +0 -0
  100. {vgi_python-0.8.8 → vgi_python-0.8.10}/test-data/generate.sh +0 -0
  101. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/__init__.py +0 -0
  102. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/_http_fixtures.py +0 -0
  103. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/__init__.py +0 -0
  104. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_catalog_interface.py +0 -0
  105. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_client_catalog.py +0 -0
  106. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_column_statistics.py +0 -0
  107. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_declarative.py +0 -0
  108. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_example_worker_catalog.py +0 -0
  109. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_integration.py +0 -0
  110. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_required_field_filter_paths.py +0 -0
  111. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_scan_branches.py +0 -0
  112. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_serialization.py +0 -0
  113. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_setting.py +0 -0
  114. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_storage.py +0 -0
  115. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_time_travel.py +0 -0
  116. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/catalog/test_writable_table.py +0 -0
  117. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/client/__init__.py +0 -0
  118. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/client/test_broken_pipe.py +0 -0
  119. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/client/test_cli.py +0 -0
  120. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/client/test_cli_catalog_functions.py +0 -0
  121. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/client/test_worker_debug.py +0 -0
  122. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/__init__.py +0 -0
  123. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/_stub.py +0 -0
  124. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/conftest.py +0 -0
  125. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_accumulate.py +0 -0
  126. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_aggregate.py +0 -0
  127. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_attach.py +0 -0
  128. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_bearer_auth.py +0 -0
  129. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_directory_parity.py +0 -0
  130. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_function_inventory.py +0 -0
  131. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_http_client.py +0 -0
  132. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_http_external_location.py +0 -0
  133. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_http_upload_url.py +0 -0
  134. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_macro.py +0 -0
  135. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_overload.py +0 -0
  136. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_protocol_inventory.py +0 -0
  137. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_protocol_version.py +0 -0
  138. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_resumable_scan.py +0 -0
  139. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_scalar.py +0 -0
  140. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_scalar_attach_opaque_data.py +0 -0
  141. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_secret.py +0 -0
  142. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_settings.py +0 -0
  143. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_table.py +0 -0
  144. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_table_in_out.py +0 -0
  145. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_view.py +0 -0
  146. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conformance/test_writable.py +0 -0
  147. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/conftest.py +0 -0
  148. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/__init__.py +0 -0
  149. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/test_bernoulli_function.py +0 -0
  150. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/test_binary_packet_function.py +0 -0
  151. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/test_client.py +0 -0
  152. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/test_conditional_message_function.py +0 -0
  153. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/test_hash_seed_function.py +0 -0
  154. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/test_multiply_by_setting_function.py +0 -0
  155. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/test_multiply_function.py +0 -0
  156. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/test_random_bytes_function.py +0 -0
  157. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/scalar/test_return_secret_value_function.py +0 -0
  158. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/__init__.py +0 -0
  159. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/__init__.py +0 -0
  160. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_constant_columns_function.py +0 -0
  161. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_double_sequence_function.py +0 -0
  162. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_exception_function.py +0 -0
  163. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_filter_echo_function.py +0 -0
  164. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_logging_function.py +0 -0
  165. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_nested_sequence_function.py +0 -0
  166. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_partitioned_function.py +0 -0
  167. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_projected_data_function.py +0 -0
  168. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_sequence_function.py +0 -0
  169. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_settings_function.py +0 -0
  170. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_struct_settings_function.py +0 -0
  171. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table/generator/test_ten_thousand_function.py +0 -0
  172. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table_in_out/__init__.py +0 -0
  173. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table_in_out/generator/__init__.py +0 -0
  174. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table_in_out/generator/test_buffer_input_function.py +0 -0
  175. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table_in_out/generator/test_echo_function.py +0 -0
  176. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table_in_out/generator/test_exception_functions.py +0 -0
  177. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table_in_out/generator/test_filter_by_setting_function.py +0 -0
  178. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table_in_out/generator/test_repeat_inputs_function.py +0 -0
  179. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table_in_out/generator/test_sum_all_columns_function.py +0 -0
  180. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/table_in_out/test_client.py +0 -0
  181. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_access_log_audit.py +0 -0
  182. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_aggregate_function.py +0 -0
  183. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_argument_spec.py +0 -0
  184. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_auth.py +0 -0
  185. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_bind_exceptions.py +0 -0
  186. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_bind_request_at_clause.py +0 -0
  187. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_bound_storage_conformance.py +0 -0
  188. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_catalog_auth_binding.py +0 -0
  189. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_copy_from_function.py +0 -0
  190. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_copy_to_function.py +0 -0
  191. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_documentation_examples.py +0 -0
  192. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_example_function_arg_types.py +0 -0
  193. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_examples_workers.py +0 -0
  194. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_exception_handling.py +0 -0
  195. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_exceptions.py +0 -0
  196. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_filter_pushdown.py +0 -0
  197. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_filter_pushdown_extension.py +0 -0
  198. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_function_storage.py +0 -0
  199. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_function_storage_azure_sql.py +0 -0
  200. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_function_storage_cf_do.py +0 -0
  201. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_function_storage_cf_do_integration.py +0 -0
  202. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_function_storage_conformance.py +0 -0
  203. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_cpp_constants.py +0 -0
  204. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_cpp_protocol_version.py +0 -0
  205. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_cpp_request_builders.py +0 -0
  206. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_cpp_schemas.py +0 -0
  207. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_cpp_secret.py +0 -0
  208. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_go_schemas.py +0 -0
  209. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_protocol_version.py +0 -0
  210. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_schemas_cross_lang.py +0 -0
  211. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_ts_client.py +0 -0
  212. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_generated_ts_schemas.py +0 -0
  213. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_http_demo_storage.py +0 -0
  214. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_http_s3_offload_input.py +0 -0
  215. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_http_s3_offload_output.py +0 -0
  216. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_metadata.py +0 -0
  217. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_mypy_consolidated.py +0 -0
  218. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_nest_tensor.py +0 -0
  219. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_otel.py +0 -0
  220. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_projection_enforcement.py +0 -0
  221. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_projection_repro.py +0 -0
  222. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_protocol_classes.py +0 -0
  223. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_resolved_secrets.py +0 -0
  224. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_schema_utils.py +0 -0
  225. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_serve.py +0 -0
  226. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_setting_secret_annotations.py +0 -0
  227. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_table_buffering_function.py +0 -0
  228. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_table_function_dynamic_to_string.py +0 -0
  229. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_tcp_transport.py +0 -0
  230. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_type_bounds.py +0 -0
  231. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_union_argument.py +0 -0
  232. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_worker.py +0 -0
  233. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_worker_cli.py +0 -0
  234. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/test_worker_page.py +0 -0
  235. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/transactor/__init__.py +0 -0
  236. {vgi_python-0.8.8 → vgi_python-0.8.10}/tests/transactor/test_transactor.py +0 -0
  237. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/__init__.py +0 -0
  238. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_duckdb.py +0 -0
  239. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_storage_profile.py +0 -0
  240. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/__init__.py +0 -0
  241. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/accumulate/__init__.py +0 -0
  242. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/accumulate/worker.py +0 -0
  243. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/__init__.py +0 -0
  244. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/_common.py +0 -0
  245. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/basic.py +0 -0
  246. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/dynamic.py +0 -0
  247. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/generic.py +0 -0
  248. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/listagg.py +0 -0
  249. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/percentile.py +0 -0
  250. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/streaming.py +0 -0
  251. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/varargs.py +0 -0
  252. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/aggregate/window.py +0 -0
  253. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/attach_options.py +0 -0
  254. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/bad_enum.py +0 -0
  255. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/bad_protocol.py +0 -0
  256. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/cancellable.py +0 -0
  257. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/catalog.py +0 -0
  258. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/copy_to.py +0 -0
  259. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/http_server.py +0 -0
  260. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/narrow_bind/__init__.py +0 -0
  261. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/narrow_bind/worker.py +0 -0
  262. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/nest_tensor.py +0 -0
  263. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/orchard_catalog.py +0 -0
  264. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/projection_repro/__init__.py +0 -0
  265. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/projection_repro/worker.py +0 -0
  266. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/__init__.py +0 -0
  267. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/_common.py +0 -0
  268. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/binary.py +0 -0
  269. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/formatting.py +0 -0
  270. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/geo.py +0 -0
  271. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/null_handling.py +0 -0
  272. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/random_demo.py +0 -0
  273. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/settings_secrets.py +0 -0
  274. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/scalar/type_info.py +0 -0
  275. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/schema_reconcile/__init__.py +0 -0
  276. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/schema_reconcile/worker.py +0 -0
  277. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/simple_writable.py +0 -0
  278. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/__init__.py +0 -0
  279. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/_common.py +0 -0
  280. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/batch_index.py +0 -0
  281. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/batch_index_broken.py +0 -0
  282. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/catalog_scans.py +0 -0
  283. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/filters.py +0 -0
  284. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/late_materialization.py +0 -0
  285. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/make_series.py +0 -0
  286. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/misc.py +0 -0
  287. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/order_modes.py +0 -0
  288. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/pairs.py +0 -0
  289. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/partition_columns.py +0 -0
  290. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/partition_columns_broken.py +0 -0
  291. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/profiling_example.py +0 -0
  292. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/required_filters.py +0 -0
  293. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/sequence.py +0 -0
  294. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/settings.py +0 -0
  295. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/transaction_storage.py +0 -0
  296. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/tt_pushdown.py +0 -0
  297. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/typed_probe.py +0 -0
  298. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table/versioned.py +0 -0
  299. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/table_in_out.py +0 -0
  300. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/versioned.py +0 -0
  301. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/versioned_tables.py +0 -0
  302. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/worker.py +0 -0
  303. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/writable/__init__.py +0 -0
  304. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/writable/generic.py +0 -0
  305. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/writable/table.py +0 -0
  306. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/_test_fixtures/writable/worker.py +0 -0
  307. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/aggregate_function.py +0 -0
  308. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/argument_spec.py +0 -0
  309. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/auth.py +0 -0
  310. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/catalog/_descriptor_spec.py +0 -0
  311. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/catalog/attach_option.py +0 -0
  312. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/catalog/catalog_interface.py +0 -0
  313. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/catalog/descriptors.py +0 -0
  314. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/catalog/duckdb_statistics.py +0 -0
  315. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/catalog/secret_type.py +0 -0
  316. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/catalog/setting.py +0 -0
  317. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/catalog/storage.py +0 -0
  318. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/__init__.py +0 -0
  319. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/catalog_mixin.py +0 -0
  320. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/cli.py +0 -0
  321. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/cli_catalog.py +0 -0
  322. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/cli_schema.py +0 -0
  323. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/cli_table.py +0 -0
  324. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/cli_transaction.py +0 -0
  325. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/cli_utils.py +0 -0
  326. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/cli_view.py +0 -0
  327. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/client/client.py +0 -0
  328. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/__init__.py +0 -0
  329. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/_common.py +0 -0
  330. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/cpp_constants.py +0 -0
  331. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/cpp_protocol_version.py +0 -0
  332. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/cpp_request_builders.py +0 -0
  333. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/cpp_schemas.py +0 -0
  334. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/cpp_secret_protocol_version.py +0 -0
  335. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/cpp_secret_request_builders.py +0 -0
  336. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/cpp_secret_schemas.py +0 -0
  337. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/go_schemas.py +0 -0
  338. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/protocol_version.py +0 -0
  339. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/ts_client.py +0 -0
  340. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/codegen/ts_schemas.py +0 -0
  341. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/copy_from_function.py +0 -0
  342. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/copy_to_function.py +0 -0
  343. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/exceptions.py +0 -0
  344. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/function.py +0 -0
  345. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/function_storage.py +0 -0
  346. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/function_storage_azure_sql.py +0 -0
  347. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/function_storage_cf_do.py +0 -0
  348. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/http/__init__.py +0 -0
  349. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/http/demo_storage.py +0 -0
  350. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/http/worker_page.py +0 -0
  351. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/invocation.py +0 -0
  352. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/logging_config.py +0 -0
  353. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/meta_worker.py +0 -0
  354. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/metadata.py +0 -0
  355. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/otel.py +0 -0
  356. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/protocol_version.txt +0 -0
  357. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/py.typed +0 -0
  358. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/schema_utils.py +0 -0
  359. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/secret_protocol.py +0 -0
  360. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/secret_service.py +0 -0
  361. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/serve.py +0 -0
  362. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/table_buffering_function.py +0 -0
  363. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/table_filter_pushdown.py +0 -0
  364. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/table_in_out_function.py +0 -0
  365. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/transactor/__init__.py +0 -0
  366. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/transactor/_duckdb_compat.py +0 -0
  367. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/transactor/client.py +0 -0
  368. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/transactor/protocol.py +0 -0
  369. {vgi_python-0.8.8 → vgi_python-0.8.10}/vgi/transactor/server.py +0 -0
  370. {vgi_python-0.8.8 → vgi_python-0.8.10}/wrangler.jsonc +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vgi-python
3
- Version: 0.8.8
3
+ Version: 0.8.10
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
@@ -172,7 +172,6 @@ Requires-Dist: duckdb>=1.5.3; extra == 'dev'
172
172
  Requires-Dist: mypy; extra == 'dev'
173
173
  Requires-Dist: numpy>=2.4.1; extra == 'dev'
174
174
  Requires-Dist: pyarrow-stubs; extra == 'dev'
175
- Requires-Dist: pydoclint; extra == 'dev'
176
175
  Requires-Dist: pymssql>=2.3.0; extra == 'dev'
177
176
  Requires-Dist: pytest; extra == 'dev'
178
177
  Requires-Dist: pytest-cov; extra == 'dev'
@@ -133,12 +133,23 @@ trap cleanup EXIT
133
133
  # set BOOTED_PORT to the port it reports (PORT:<n>, the worker's readiness
134
134
  # contract). Sets a global rather than echoing so the backgrounded worker stays a
135
135
  # child of this shell (a $(...) subshell would reparent it and break teardown).
136
+ #
137
+ # The worker is spawned with cwd=$STAGE — the same directory the unittest binary
138
+ # runs from below (`cd "$STAGE"`). copy_from/copy_to tests have DuckDB write a
139
+ # source file under a relative `__TEST_DIR__` (duckdb_unittest_tempdir/...) that
140
+ # the worker then opens by the same relative path; the worker only resolves it
141
+ # if it shares DuckDB's cwd. On the stdio lane the C++ extension spawns the
142
+ # worker as a subprocess that inherits DuckDB's cwd, so it matches for free; the
143
+ # `( cd … ; exec … )` subshell gives the http worker the same footing (and
144
+ # mirrors the vgi repo's run_http_integration.sh, which boots server and DuckDB
145
+ # from one cwd). exec keeps the worker on the subshell's pid so teardown via the
146
+ # captured `$!` still works.
136
147
  BOOTED_PORT=""
137
148
  boot_http_worker() {
138
149
  local exe="$1" log pid port=""
139
150
  BOOTED_PORT=""
140
151
  log="$(mktemp)"
141
- "$exe" --http --port 0 >"$log" 2>&1 &
152
+ ( cd "$STAGE" && exec "$exe" --http --port 0 ) >"$log" 2>&1 &
142
153
  pid=$!
143
154
  echo "$pid" >> "$BG_PIDS_FILE"
144
155
  for _ in $(seq 1 60); do
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "vgi-python"
3
- version = "0.8.8"
3
+ version = "0.8.10"
4
4
  description = "Vector Gateway Interface - Connect DuckDB to external programs via Apache Arrow"
5
5
  readme = "README.md"
6
6
  keywords = [
@@ -77,7 +77,11 @@ dev = [
77
77
  "duckdb>=1.5.3",
78
78
  "mypy",
79
79
  "pyarrow-stubs",
80
- "pydoclint",
80
+ # pydoclint is intentionally NOT a project dependency: it pulls
81
+ # docstring-parser-fork, which clobbers the canonical docstring-parser
82
+ # (a vgi-rpc dependency) in the shared `docstring_parser` namespace,
83
+ # non-deterministically breaking imports. tests/test_docstrings.py runs it
84
+ # in an isolated env via `uvx pydoclint` instead.
81
85
  "pytest",
82
86
  "pytest-cov",
83
87
  "pytest-examples",
@@ -142,7 +146,9 @@ quote-style = "double"
142
146
  # Docstring consistency gate (complements ruff's `D` rules, which only check
143
147
  # docstring *shape*, not whether documented args/attributes match the code).
144
148
  # Enforced families: DOC001 (parse), DOC101/102/103 (arg<->signature), DOC4xx
145
- # (yields), DOC60x (dataclass attributes). Run via `uv run pydoclint vgi/`.
149
+ # (yields), DOC60x (dataclass attributes). pydoclint is NOT a project dependency
150
+ # (it pulls docstring-parser-fork, which clobbers vgi-rpc's docstring-parser);
151
+ # run it isolated: `uvx --python $(which python) pydoclint --config pyproject.toml vgi/`.
146
152
  style = "google"
147
153
  # We keep types in signatures, not docstrings (Google style) — so don't ask for
148
154
  # them in docstrings, and don't try to match return/yield *types* against prose.
@@ -162,7 +168,7 @@ allow_init_docstring = true
162
168
  # No baseline: vgi/ is fully clean under this config, so the gate enforces
163
169
  # every in-scope violation with no grandfathered exceptions. If a future change
164
170
  # needs to defer cleanup, freeze the current state and re-add `baseline`:
165
- # uv run pydoclint --generate-baseline=True --baseline=.pydoclint-baseline vgi/
171
+ # uvx pydoclint --config pyproject.toml --generate-baseline=True --baseline=.pydoclint-baseline vgi/
166
172
 
167
173
  [tool.mypy]
168
174
  python_version = "3.13"
@@ -0,0 +1,65 @@
1
+ # Copyright 2025, 2026 Query Farm LLC - https://query.farm
2
+
3
+ """Docstring-consistency gate.
4
+
5
+ Runs pydoclint over the ``vgi/`` package as part of the test suite. pydoclint
6
+ complements ruff's ``D`` rules: ruff checks docstring *shape*, while pydoclint
7
+ verifies that documented arguments, return values, yields, and dataclass
8
+ attributes actually match the code. Configuration lives in ``[tool.pydoclint]``
9
+ in ``pyproject.toml`` — this test invokes the same CLI, so there is no
10
+ duplicated rule set.
11
+
12
+ pydoclint runs through ``uvx`` (an isolated, ephemeral environment) rather than
13
+ as a project dependency. It requires ``docstring-parser-fork`` while ``vgi-rpc``
14
+ (a runtime dependency) requires the upstream ``docstring-parser``; both own the
15
+ ``docstring_parser`` import namespace, so installing pydoclint into the project
16
+ env clobbers it non-deterministically and breaks unrelated imports (e.g.
17
+ ``conftest`` collection). Running via uvx keeps the fork out of the project tree.
18
+ """
19
+
20
+ import re
21
+ import shutil
22
+ import subprocess
23
+ import sys
24
+ from pathlib import Path
25
+
26
+ import pytest
27
+
28
+ _REPO_ROOT = Path(__file__).resolve().parents[1]
29
+
30
+ # A real violation line looks like `` 42: DOC101: ...``. If pydoclint exits
31
+ # non-zero without emitting any such code, it failed to *run* rather than finding
32
+ # violations.
33
+ _VIOLATION_RE = re.compile(r"\bDOC\d{3}\b")
34
+
35
+
36
+ def test_pydoclint_clean() -> None:
37
+ """``vgi/`` must pass the pydoclint docstring gate (config in pyproject.toml)."""
38
+ uvx = shutil.which("uvx") or shutil.which("uv")
39
+ if uvx is None: # pragma: no cover - uv is always present in dev/CI
40
+ pytest.skip("uv/uvx is not available to run pydoclint")
41
+
42
+ # `uvx pydoclint ...` == `uv tool run pydoclint ...`; both run pydoclint in an
43
+ # isolated env so docstring-parser-fork never enters the project tree.
44
+ # Pin the ephemeral env to *this* interpreter (``--python sys.executable``):
45
+ # pydoclint parses with its own runtime's AST, so it must run on a Python new
46
+ # enough for the repo's syntax (PEP 695 generics need 3.12+); uvx's default
47
+ # interpreter may be older and would report spurious DOC002 syntax errors.
48
+ base = [uvx] if Path(uvx).name == "uvx" else [uvx, "tool", "run"]
49
+ cmd = [*base, "--python", sys.executable, "pydoclint", "--config", "pyproject.toml", "vgi/"]
50
+ result = subprocess.run(cmd, cwd=_REPO_ROOT, capture_output=True, text=True)
51
+ output = result.stdout + result.stderr
52
+
53
+ if result.returncode == 0:
54
+ return
55
+
56
+ if not _VIOLATION_RE.search(output): # pragma: no cover - env-dependent (e.g. offline uvx)
57
+ pytest.skip(f"pydoclint could not run via uvx:\n{output}")
58
+
59
+ pytest.fail(
60
+ "pydoclint found docstring violations:\n\n"
61
+ f"{output}\n"
62
+ "Fix the docstrings, or run `uvx pydoclint --config pyproject.toml "
63
+ "--generate-baseline=True --baseline=.pydoclint-baseline vgi/` "
64
+ "to defer them (see [tool.pydoclint] in pyproject.toml)."
65
+ )
@@ -516,15 +516,6 @@ wheels = [
516
516
  { url = "https://files.pythonhosted.org/packages/a7/5f/ed01f9a3cdffbd5a008556fc7b2a08ddb1cc6ace7effa7340604b1d16699/docstring_parser-0.18.0-py3-none-any.whl", hash = "sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b", size = 22484, upload-time = "2026-04-14T04:09:18.638Z" },
517
517
  ]
518
518
 
519
- [[package]]
520
- name = "docstring-parser-fork"
521
- version = "0.0.14"
522
- source = { registry = "https://pypi.org/simple" }
523
- sdist = { url = "https://files.pythonhosted.org/packages/66/bf/27f9cab2f0cd1d17a4420572088bbc19f36d726fbcf165edf226a8926dbc/docstring_parser_fork-0.0.14.tar.gz", hash = "sha256:a2743a63d8d36c09650594f7b4ab5b2758fee8629dcf794d1b221b23179baa5c", size = 34551, upload-time = "2025-09-07T17:27:38.272Z" }
524
- wheels = [
525
- { url = "https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl", hash = "sha256:4c544f234ef2cc2749a3df32b70c437d77888b1099143a1ad5454452c574b9af", size = 43063, upload-time = "2025-09-07T17:27:37.012Z" },
526
- ]
527
-
528
519
  [[package]]
529
520
  name = "duckdb"
530
521
  version = "1.5.4"
@@ -1657,19 +1648,6 @@ wheels = [
1657
1648
  { url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" },
1658
1649
  ]
1659
1650
 
1660
- [[package]]
1661
- name = "pydoclint"
1662
- version = "0.8.7"
1663
- source = { registry = "https://pypi.org/simple" }
1664
- dependencies = [
1665
- { name = "click" },
1666
- { name = "docstring-parser-fork" },
1667
- ]
1668
- sdist = { url = "https://files.pythonhosted.org/packages/bf/2e/e4df6b0cbb281cb6cf355f5d90b8c66939c7f3cd799c075fab23e0983dfb/pydoclint-0.8.7.tar.gz", hash = "sha256:1ce5055dfdaf2bc3c999d3ffd5494556b903b7090bb5fadac90819107f90629b", size = 199793, upload-time = "2026-06-22T01:24:20.117Z" }
1669
- wheels = [
1670
- { url = "https://files.pythonhosted.org/packages/e9/d4/15fe5c3e66bbf3f60eb9c6ef7c2dca3931302f9acf317e65d70e7d8b338a/pydoclint-0.8.7-py3-none-any.whl", hash = "sha256:40f6b80e59129fe753f6a2f9edd76e4259c970eedc1ce3663adc43f54af439d3", size = 82963, upload-time = "2026-06-22T01:24:19.102Z" },
1671
- ]
1672
-
1673
1651
  [[package]]
1674
1652
  name = "pygments"
1675
1653
  version = "2.20.0"
@@ -2250,7 +2228,7 @@ requires-dist = [
2250
2228
 
2251
2229
  [[package]]
2252
2230
  name = "vgi-python"
2253
- version = "0.8.8"
2231
+ version = "0.8.10"
2254
2232
  source = { editable = "." }
2255
2233
  dependencies = [
2256
2234
  { name = "click" },
@@ -2272,7 +2250,6 @@ dev = [
2272
2250
  { name = "mypy" },
2273
2251
  { name = "numpy" },
2274
2252
  { name = "pyarrow-stubs" },
2275
- { name = "pydoclint" },
2276
2253
  { name = "pymssql" },
2277
2254
  { name = "pytest" },
2278
2255
  { name = "pytest-cov" },
@@ -2346,7 +2323,6 @@ requires-dist = [
2346
2323
  { name = "platformdirs" },
2347
2324
  { name = "pyarrow" },
2348
2325
  { name = "pyarrow-stubs", marker = "extra == 'dev'" },
2349
- { name = "pydoclint", marker = "extra == 'dev'" },
2350
2326
  { name = "pymssql", marker = "extra == 'azure'", specifier = ">=2.3.0" },
2351
2327
  { name = "pytest", marker = "extra == 'dev'" },
2352
2328
  { name = "pytest-cov", marker = "extra == 'dev'" },
@@ -91,7 +91,7 @@ class ExampleLinesCopyFromFunction(CopyFromFunction[ExampleLinesCopyFromArgs]):
91
91
 
92
92
  # Column-major string arrays, NULL where the cell equals null_string,
93
93
  # then cast each column to the target type (DuckDB inserts no cast).
94
- columns = list(zip(*rows)) if rows else [() for _ in range(ncols)]
94
+ columns = list(zip(*rows, strict=True)) if rows else [() for _ in range(ncols)]
95
95
  arrays = []
96
96
  for idx, field in enumerate(expected_schema):
97
97
  raw = [None if v == options.null_string else v for v in columns[idx]]
@@ -51,9 +51,17 @@ class MultiplyFunction(ScalarFunction):
51
51
  def compute(
52
52
  cls,
53
53
  value: Annotated[pa.Int64Array, Param(doc="Integer value to multiply")],
54
- factor: Annotated[int, ConstParam("Multiplication factor")],
54
+ factor: Annotated[pa.Int64Scalar, ConstParam("Multiplication factor")],
55
55
  ) -> Annotated[pa.Int64Array, Returns()]:
56
- """Multiply values by the constant factor."""
56
+ """Multiply values by the constant factor.
57
+
58
+ ``factor`` is annotated as a ``pa.Int64Scalar`` (not a Python ``int``), so
59
+ the SDK delivers the typed Arrow scalar straight through and it can be
60
+ passed directly into ``pc.multiply``. Passing a bare Python int instead
61
+ makes pyarrow infer an Arrow scalar on every call — ~40-50x slower on
62
+ Windows than a typed scalar, and the dominant per-batch cost for a scalar
63
+ UDF. This is the idiomatic fast pattern for compute-bound constants.
64
+ """
57
65
  return pc.multiply(value, factor)
58
66
 
59
67
 
@@ -109,6 +109,46 @@ COMPLEX_ARRAY_CLASSES: set[type] = {
109
109
  }
110
110
 
111
111
 
112
+ # Simple scalar classes that can be inferred automatically. Annotating a const
113
+ # parameter with one of these — ``Annotated[pa.Int64Scalar, ConstParam(...)]`` —
114
+ # makes the SDK deliver the typed ``pa.Scalar`` straight through to ``compute()``
115
+ # instead of converting it to a Python object via ``as_py()``. That lets the
116
+ # const be passed directly into ``pyarrow.compute`` with no per-call scalar
117
+ # re-inference, which is ~40-50x slower on Windows than a typed scalar. Built
118
+ # defensively so a pyarrow release missing a class name doesn't break import.
119
+ def _build_scalar_class_to_datatype() -> dict[type, pa.DataType]:
120
+ pairs: list[tuple[str, pa.DataType]] = [
121
+ ("Int8Scalar", pa.int8()),
122
+ ("Int16Scalar", pa.int16()),
123
+ ("Int32Scalar", pa.int32()),
124
+ ("Int64Scalar", pa.int64()),
125
+ ("UInt8Scalar", pa.uint8()),
126
+ ("UInt16Scalar", pa.uint16()),
127
+ ("UInt32Scalar", pa.uint32()),
128
+ ("UInt64Scalar", pa.uint64()),
129
+ ("HalfFloatScalar", pa.float16()),
130
+ ("FloatScalar", pa.float32()),
131
+ ("DoubleScalar", pa.float64()),
132
+ ("StringScalar", pa.string()),
133
+ ("LargeStringScalar", pa.large_string()),
134
+ ("BinaryScalar", pa.binary()),
135
+ ("LargeBinaryScalar", pa.large_binary()),
136
+ ("BooleanScalar", pa.bool_()),
137
+ ("Date32Scalar", pa.date32()),
138
+ ("Date64Scalar", pa.date64()),
139
+ ("NullScalar", pa.null()),
140
+ ]
141
+ out: dict[type, pa.DataType] = {}
142
+ for name, dt in pairs:
143
+ cls = getattr(pa, name, None)
144
+ if isinstance(cls, type):
145
+ out[cls] = dt
146
+ return out
147
+
148
+
149
+ SCALAR_CLASS_TO_DATATYPE: dict[type, pa.DataType] = _build_scalar_class_to_datatype()
150
+
151
+
112
152
  # Sentinel for missing default value - proper type pattern
113
153
  class _MissingType:
114
154
  """Sentinel type for missing default values.
@@ -158,6 +198,7 @@ __all__ = [
158
198
  "Param",
159
199
  "PYTHON_TO_ARROW",
160
200
  "Returns",
201
+ "SCALAR_CLASS_TO_DATATYPE",
161
202
  "TableInput",
162
203
  "TaggedUnion",
163
204
  "TypeBoundPredicate",
@@ -15,6 +15,7 @@ from vgi.catalog.catalog_interface import (
15
15
  CatalogInterface,
16
16
  CatalogObject,
17
17
  CatalogSchemaObject,
18
+ CopyFromFormatInfo,
18
19
  FunctionInfo,
19
20
  FunctionType,
20
21
  IndexConstraintType,
@@ -67,6 +68,7 @@ __all__ = [
67
68
  "TableInfo",
68
69
  "ViewInfo",
69
70
  "FunctionInfo",
71
+ "CopyFromFormatInfo",
70
72
  "ScanBranch",
71
73
  "ScanBranchesResult",
72
74
  "ScanFunctionResult",
@@ -196,6 +196,10 @@ class BindRequest(ArrowSerializableDataclass):
196
196
  accessor), not at on_bind.
197
197
  at_value: Value of the time-travel ``AT`` clause for this scan; ``None`` when
198
198
  the scan has no AT clause. See ``at_unit`` for the inline-bind caveat.
199
+ copy_from: The ``COPY ... FROM`` context (source format + path); ``None``
200
+ unless this bind/init opens a COPY-FROM scan.
201
+ copy_to: The ``COPY ... TO`` context (destination format + path); ``None``
202
+ unless this bind/init opens a COPY-TO sink.
199
203
  """
200
204
 
201
205
  function_name: str
@@ -48,6 +48,7 @@ from vgi.arguments import (
48
48
  _PYTHON_TO_ARROW,
49
49
  ARRAY_CLASS_TO_DATATYPE,
50
50
  COMPLEX_ARRAY_CLASSES,
51
+ SCALAR_CLASS_TO_DATATYPE,
51
52
  Arg,
52
53
  Arguments,
53
54
  ArgumentValidationError,
@@ -212,6 +213,25 @@ def _param_to_arg(param: Param, base_type: type, position: int) -> Arg[Any]:
212
213
  )
213
214
 
214
215
 
216
+ def _is_scalar_annotation(base_type: object) -> bool:
217
+ """Whether a [`ConstParam`][] is annotated with a pyarrow scalar class.
218
+
219
+ ``Annotated[pa.Int64Scalar, ConstParam(...)]`` (or the generic ``pa.Scalar``)
220
+ signals that the typed Arrow scalar should be delivered to ``compute()``
221
+ unchanged, instead of converting it to a Python value via ``as_py()``. The
222
+ scalar can then flow straight into ``pyarrow.compute`` with no per-call scalar
223
+ re-inference (the latter is ~40-50x slower on Windows than a typed scalar).
224
+
225
+ Args:
226
+ base_type: The type from the ``Annotated`` first argument.
227
+
228
+ Returns:
229
+ True iff ``base_type`` is ``pa.Scalar`` or a subclass.
230
+
231
+ """
232
+ return isinstance(base_type, type) and issubclass(base_type, pa.Scalar)
233
+
234
+
215
235
  def _const_param_to_arg(const_param: ConstParam, base_type: type, position: int) -> Arg[Any]:
216
236
  """Convert [`ConstParam`][] dataclass to internal [`Arg`][] object.
217
237
 
@@ -235,6 +255,15 @@ def _const_param_to_arg(const_param: ConstParam, base_type: type, position: int)
235
255
  elif base_type in _PYTHON_TO_ARROW:
236
256
  # Infer from Annotated first argument
237
257
  arrow_type = _PYTHON_TO_ARROW[base_type]
258
+ elif base_type in SCALAR_CLASS_TO_DATATYPE:
259
+ # Annotated[pa.Int64Scalar, ConstParam(...)] — infer from the scalar class
260
+ # and deliver the typed scalar through (see _is_scalar_annotation).
261
+ arrow_type = SCALAR_CLASS_TO_DATATYPE[base_type]
262
+ elif _is_scalar_annotation(base_type):
263
+ raise TypeError(
264
+ f"Cannot infer Arrow type from {getattr(base_type, '__name__', base_type)}. "
265
+ f"Use a concrete scalar class (e.g. pa.Int64Scalar) or set arrow_type=... on ConstParam()."
266
+ )
238
267
  else:
239
268
  raise TypeError(
240
269
  f"Cannot infer Arrow type from {base_type}. "
@@ -791,6 +820,7 @@ class ScalarFunction(ScalarFunctionGenerator):
791
820
 
792
821
  _compute_params: dict[str, Arg[Any]] # Regular Param() arguments (arrays)
793
822
  _const_params: dict[str, Arg[Any]] # ConstParam() arguments (scalars)
823
+ _const_scalar_params: set[str] # ConstParams annotated as pa.Scalar — delivered un-as_py()'d
794
824
  _setting_params: dict[str, str] # Setting params: param_name -> setting_key
795
825
  _secret_params: dict[str, Secret] # Secret params: param_name -> Secret instance
796
826
  _output_length_param: str | None # OutputLength param name (batch row count)
@@ -866,6 +896,7 @@ class ScalarFunction(ScalarFunctionGenerator):
866
896
 
867
897
  compute_params: dict[str, Arg[Any]] = {}
868
898
  const_params: dict[str, Arg[Any]] = {}
899
+ const_scalar_params: set[str] = set() # ConstParams annotated as pa.Scalar
869
900
  output_length_param: str | None = None # param that receives batch row count
870
901
  auth_param: str | None = None # param that receives AuthContext
871
902
  returns_output_type: pa.DataType | None = None
@@ -940,6 +971,8 @@ class ScalarFunction(ScalarFunctionGenerator):
940
971
  # _resolution_index points to Arguments.positional index
941
972
  arg._resolution_index = const_index
942
973
  const_params[name] = arg
974
+ if _is_scalar_annotation(base_type):
975
+ const_scalar_params.add(name)
943
976
  setattr(cls, name, _ConstArgDescriptor(arg, name))
944
977
  overall_position += 1
945
978
  const_index += 1
@@ -966,6 +999,7 @@ class ScalarFunction(ScalarFunctionGenerator):
966
999
 
967
1000
  cls._compute_params = compute_params
968
1001
  cls._const_params = const_params
1002
+ cls._const_scalar_params = const_scalar_params
969
1003
  cls._setting_params = setting_params
970
1004
  cls._secret_params = secret_params
971
1005
  cls._output_length_param = output_length_param
@@ -1051,14 +1085,22 @@ class ScalarFunction(ScalarFunctionGenerator):
1051
1085
  # Regular param: extract column by index
1052
1086
  kwargs[name] = batch.column(col_idx)
1053
1087
 
1054
- # Const params: extract scalar values from arguments
1088
+ # Const params: extract values from the constant arguments. Params annotated
1089
+ # with a pyarrow scalar class (e.g. Annotated[pa.Int64Scalar, ConstParam(...)])
1090
+ # receive the typed pa.Scalar unchanged, so it can be passed straight into
1091
+ # pyarrow.compute with no per-call scalar re-inference; all others get the
1092
+ # Python value via as_py() (backward compatible).
1055
1093
  for name, arg in cls._const_params.items():
1056
1094
  # Use _resolution_index for Arguments.positional lookup
1057
1095
  arg_idx = cast(int, arg._resolution_index)
1058
1096
  # Get the scalar value from arguments
1059
1097
  scalar = bind_call.arguments.positional[arg_idx]
1060
- # Convert to Python value
1061
- kwargs[name] = scalar.as_py() if scalar is not None else None
1098
+ if scalar is None:
1099
+ kwargs[name] = None
1100
+ elif name in cls._const_scalar_params:
1101
+ kwargs[name] = scalar
1102
+ else:
1103
+ kwargs[name] = scalar.as_py()
1062
1104
 
1063
1105
  # Setting params: extract pa.Scalar from settings RecordBatch
1064
1106
  if bind_call.settings is not None and cls._setting_params:
@@ -300,7 +300,7 @@ def _secret_scalar_str(v: Any) -> str:
300
300
  return "" if py is None else str(py)
301
301
 
302
302
 
303
- class ResolvedSecrets(dict):
303
+ class ResolvedSecrets(dict[str, dict[str, Any]]):
304
304
  """Resolved secrets keyed by secret name, with type- and scope-aware lookup.
305
305
 
306
306
  A plain ``dict`` (so ``secrets[name]`` and ``secrets.get(name)`` still work)
@@ -514,7 +514,7 @@ class InitParams[TArgs]:
514
514
  output_schema: pa.Schema
515
515
 
516
516
  settings: dict[str, pa.Scalar[Any]]
517
- secrets: dict[str, dict[str, pa.Scalar[Any]]]
517
+ secrets: ResolvedSecrets
518
518
 
519
519
  storage: BoundStorage
520
520
  auth_context: AuthContext = AuthContext.anonymous()
@@ -569,7 +569,7 @@ class ProcessParams[TArgs]:
569
569
  output_schema: pa.Schema
570
570
 
571
571
  settings: dict[str, pa.Scalar[Any]]
572
- secrets: dict[str, dict[str, pa.Scalar[Any]]]
572
+ secrets: ResolvedSecrets
573
573
 
574
574
  storage: BoundStorage
575
575
  auth_context: AuthContext = AuthContext.anonymous()
@@ -146,6 +146,7 @@ from vgi.table_buffering_function import (
146
146
  )
147
147
  from vgi.table_function import (
148
148
  ProcessParams,
149
+ ResolvedSecrets,
149
150
  SecretsAccessor,
150
151
  TableCardinality,
151
152
  TableFunctionBase,
@@ -2407,7 +2408,7 @@ class Worker:
2407
2408
  init_response=None,
2408
2409
  output_schema=pa.schema([]),
2409
2410
  settings={},
2410
- secrets={},
2411
+ secrets=ResolvedSecrets(),
2411
2412
  storage=storage,
2412
2413
  auth_context=ctx.auth,
2413
2414
  )
@@ -2513,7 +2514,7 @@ class Worker:
2513
2514
  init_response=None,
2514
2515
  output_schema=pa.schema([]),
2515
2516
  settings={},
2516
- secrets={},
2517
+ secrets=ResolvedSecrets(),
2517
2518
  storage=storage,
2518
2519
  auth_context=ctx.auth,
2519
2520
  )
@@ -2576,7 +2577,7 @@ class Worker:
2576
2577
  init_response=None,
2577
2578
  output_schema=request.output_schema,
2578
2579
  settings={},
2579
- secrets={},
2580
+ secrets=ResolvedSecrets(),
2580
2581
  storage=storage,
2581
2582
  auth_context=ctx.auth,
2582
2583
  )
@@ -2815,7 +2816,7 @@ class Worker:
2815
2816
  init_response=None,
2816
2817
  output_schema=request.output_schema,
2817
2818
  settings={},
2818
- secrets={},
2819
+ secrets=ResolvedSecrets(),
2819
2820
  storage=storage,
2820
2821
  auth_context=ctx.auth,
2821
2822
  )
@@ -2912,7 +2913,7 @@ class Worker:
2912
2913
  init_response=None,
2913
2914
  output_schema=output_schema,
2914
2915
  settings={},
2915
- secrets={},
2916
+ secrets=ResolvedSecrets(),
2916
2917
  storage=storage,
2917
2918
  auth_context=ctx.auth,
2918
2919
  )
@@ -3027,7 +3028,7 @@ class Worker:
3027
3028
  init_response=None,
3028
3029
  output_schema=output_schema,
3029
3030
  settings={},
3030
- secrets={},
3031
+ secrets=ResolvedSecrets(),
3031
3032
  storage=storage,
3032
3033
  auth_context=ctx.auth,
3033
3034
  )
@@ -3121,7 +3122,7 @@ class Worker:
3121
3122
  init_response=None,
3122
3123
  output_schema=request.output_schema,
3123
3124
  settings=_batch_to_scalar_dict(request.settings),
3124
- secrets={},
3125
+ secrets=ResolvedSecrets(),
3125
3126
  storage=storage,
3126
3127
  auth_context=ctx.auth,
3127
3128
  )
@@ -3187,7 +3188,7 @@ class Worker:
3187
3188
  init_response=None,
3188
3189
  output_schema=session.output_schema,
3189
3190
  settings={},
3190
- secrets={},
3191
+ secrets=ResolvedSecrets(),
3191
3192
  storage=storage,
3192
3193
  auth_context=ctx.auth,
3193
3194
  )
@@ -3280,7 +3281,7 @@ class Worker:
3280
3281
  init_response=None,
3281
3282
  output_schema=session.output_schema,
3282
3283
  settings={},
3283
- secrets={},
3284
+ secrets=ResolvedSecrets(),
3284
3285
  storage=storage,
3285
3286
  auth_context=ctx.auth,
3286
3287
  )
@@ -1,60 +0,0 @@
1
- # Copyright 2025, 2026 Query Farm LLC - https://query.farm
2
-
3
- """Docstring-consistency gate.
4
-
5
- Runs pydoclint over the ``vgi/`` package as part of the test suite, mirroring
6
- the CI ``Docstring lint (pydoclint)`` step. pydoclint complements ruff's ``D``
7
- rules: ruff checks docstring *shape*, while pydoclint verifies that documented
8
- arguments, return values, yields, and dataclass attributes actually match the
9
- code. Configuration lives in ``[tool.pydoclint]`` in ``pyproject.toml`` — this
10
- test invokes the same CLI, so there is no duplicated rule set.
11
- """
12
-
13
- import re
14
- import shutil
15
- import subprocess
16
- from pathlib import Path
17
-
18
- import pytest
19
-
20
- _REPO_ROOT = Path(__file__).resolve().parents[1]
21
-
22
- # A real violation line looks like `` 42: DOC101: ...``. If pydoclint exits
23
- # non-zero without emitting any such code, it failed to *run* (e.g. import
24
- # error) rather than finding violations — see the environment note below.
25
- _VIOLATION_RE = re.compile(r"\bDOC\d{3}\b")
26
-
27
-
28
- def test_pydoclint_clean() -> None:
29
- """``vgi/`` must pass the pydoclint docstring gate (config in pyproject.toml)."""
30
- pydoclint = shutil.which("pydoclint")
31
- if pydoclint is None: # pragma: no cover - dev dependency should always be present
32
- pytest.skip("pydoclint is not installed")
33
-
34
- result = subprocess.run(
35
- [pydoclint, "vgi/"],
36
- cwd=_REPO_ROOT,
37
- capture_output=True,
38
- text=True,
39
- )
40
- output = result.stdout + result.stderr
41
-
42
- if result.returncode == 0:
43
- return
44
-
45
- # pydoclint depends on ``docstring-parser-fork`` while ``vgi-rpc`` depends on
46
- # the upstream ``docstring-parser``; both claim the ``docstring_parser``
47
- # import namespace, so on some interpreter/OS combinations the wrong files
48
- # win and pydoclint crashes on import. That's a broken tool environment, not
49
- # a docstring problem — skip rather than fail (the gate still runs on every
50
- # other matrix cell where the tool is healthy).
51
- if not _VIOLATION_RE.search(output): # pragma: no cover - env-dependent
52
- pytest.skip(f"pydoclint could not run in this environment:\n{output}")
53
-
54
- pytest.fail(
55
- "pydoclint found docstring violations:\n\n"
56
- f"{output}\n"
57
- "Fix the docstrings, or run "
58
- "`uv run pydoclint --generate-baseline=True --baseline=.pydoclint-baseline vgi/` "
59
- "to defer them (see [tool.pydoclint] in pyproject.toml)."
60
- )
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes