vgi-python 0.21.0__tar.gz → 0.22.1__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 (398) hide show
  1. {vgi_python-0.21.0 → vgi_python-0.22.1}/PKG-INFO +2 -2
  2. {vgi_python-0.21.0 → vgi_python-0.22.1}/pyproject.toml +8 -2
  3. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_serve.py +51 -0
  4. {vgi_python-0.21.0 → vgi_python-0.22.1}/uv.lock +26 -26
  5. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/serve.py +91 -6
  6. {vgi_python-0.21.0 → vgi_python-0.22.1}/.gitattributes +0 -0
  7. {vgi_python-0.21.0 → vgi_python-0.22.1}/.github/dependabot.yml +0 -0
  8. {vgi_python-0.21.0 → vgi_python-0.22.1}/.github/styles/config/vocabularies/VGI/accept.txt +0 -0
  9. {vgi_python-0.21.0 → vgi_python-0.22.1}/.github/workflows/ci.yml +0 -0
  10. {vgi_python-0.21.0 → vgi_python-0.22.1}/.github/workflows/docs.yml +0 -0
  11. {vgi_python-0.21.0 → vgi_python-0.22.1}/.github/workflows/integration.yml +0 -0
  12. {vgi_python-0.21.0 → vgi_python-0.22.1}/.github/workflows/release.yml +0 -0
  13. {vgi_python-0.21.0 → vgi_python-0.22.1}/.gitignore +0 -0
  14. {vgi_python-0.21.0 → vgi_python-0.22.1}/.python-version +0 -0
  15. {vgi_python-0.21.0 → vgi_python-0.22.1}/.vale.ini +0 -0
  16. {vgi_python-0.21.0 → vgi_python-0.22.1}/CLAUDE.md +0 -0
  17. {vgi_python-0.21.0 → vgi_python-0.22.1}/DOCS_ACCEPTANCE_CRITERIA.md +0 -0
  18. {vgi_python-0.21.0 → vgi_python-0.22.1}/DOCS_REVIEW_RUBRIC.md +0 -0
  19. {vgi_python-0.21.0 → vgi_python-0.22.1}/DOCS_USABILITY_TEST.md +0 -0
  20. {vgi_python-0.21.0 → vgi_python-0.22.1}/LICENSE +0 -0
  21. {vgi_python-0.21.0 → vgi_python-0.22.1}/README.md +0 -0
  22. {vgi_python-0.21.0 → vgi_python-0.22.1}/SECURITY.md +0 -0
  23. {vgi_python-0.21.0 → vgi_python-0.22.1}/ci/README.md +0 -0
  24. {vgi_python-0.21.0 → vgi_python-0.22.1}/ci/preprocess-require.awk +0 -0
  25. {vgi_python-0.21.0 → vgi_python-0.22.1}/ci/run-integration.sh +0 -0
  26. {vgi_python-0.21.0 → vgi_python-0.22.1}/dist-vgi/.gitignore +0 -0
  27. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/aggregate-functions.md +0 -0
  28. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/api/arguments.md +0 -0
  29. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/api/auth.md +0 -0
  30. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/api/catalogs.md +0 -0
  31. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/api/client.md +0 -0
  32. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/api/exceptions.md +0 -0
  33. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/api/filters.md +0 -0
  34. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/api/functions.md +0 -0
  35. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/api/http.md +0 -0
  36. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/api/index.md +0 -0
  37. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/api/metadata.md +0 -0
  38. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/api/observability.md +0 -0
  39. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/api/storage.md +0 -0
  40. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/api/transactor.md +0 -0
  41. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/api/worker.md +0 -0
  42. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/argument-serialization.md +0 -0
  43. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/assets/apple-touch-icon.png +0 -0
  44. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/assets/favicon-16x16.png +0 -0
  45. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/assets/favicon-32x32.png +0 -0
  46. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/assets/favicon.ico +0 -0
  47. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/assets/kinds/aggregate.svg +0 -0
  48. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/assets/kinds/buffering.svg +0 -0
  49. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/assets/kinds/scalar.svg +0 -0
  50. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/assets/kinds/table-in-out.svg +0 -0
  51. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/assets/kinds/table.svg +0 -0
  52. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/assets/logo.png +0 -0
  53. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/assets/social-card.png +0 -0
  54. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/authentication.md +0 -0
  55. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/catalog-interface.md +0 -0
  56. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/cli.md +0 -0
  57. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/column-statistics.md +0 -0
  58. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/concepts/index.md +0 -0
  59. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/contributing-docs.md +0 -0
  60. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/filter-pushdown.md +0 -0
  61. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/generator-api.md +0 -0
  62. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/how-to/catalogs.md +0 -0
  63. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/how-to/function-patterns.md +0 -0
  64. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/how-to/http-auth.md +0 -0
  65. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/how-to/index.md +0 -0
  66. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/how-to/pushdown-and-statistics.md +0 -0
  67. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/how-to/state-storage.md +0 -0
  68. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/index.md +0 -0
  69. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/lifecycle.md +0 -0
  70. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/metadata.md +0 -0
  71. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/overrides/main.html +0 -0
  72. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/robots.txt +0 -0
  73. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/shared-storage.md +0 -0
  74. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/stylesheets/extra.css +0 -0
  75. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/tutorial/index.md +0 -0
  76. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/tutorial/scalar.md +0 -0
  77. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/tutorial/table.md +0 -0
  78. {vgi_python-0.21.0 → vgi_python-0.22.1}/docs/vgi-logo.png +0 -0
  79. {vgi_python-0.21.0 → vgi_python-0.22.1}/examples/calc_scalar_worker.py +0 -0
  80. {vgi_python-0.21.0 → vgi_python-0.22.1}/examples/calc_worker.py +0 -0
  81. {vgi_python-0.21.0 → vgi_python-0.22.1}/examples/filter_worker.py +0 -0
  82. {vgi_python-0.21.0 → vgi_python-0.22.1}/examples/greeting_scalar_worker.py +0 -0
  83. {vgi_python-0.21.0 → vgi_python-0.22.1}/examples/row_count_worker.py +0 -0
  84. {vgi_python-0.21.0 → vgi_python-0.22.1}/examples/series_streaming_worker.py +0 -0
  85. {vgi_python-0.21.0 → vgi_python-0.22.1}/examples/sum_worker.py +0 -0
  86. {vgi_python-0.21.0 → vgi_python-0.22.1}/mkdocs.yml +0 -0
  87. {vgi_python-0.21.0 → vgi_python-0.22.1}/packages/vgi-fixtures/LICENSE +0 -0
  88. {vgi_python-0.21.0 → vgi_python-0.22.1}/packages/vgi-fixtures/README.md +0 -0
  89. {vgi_python-0.21.0 → vgi_python-0.22.1}/packages/vgi-fixtures/docker/Dockerfile +0 -0
  90. {vgi_python-0.21.0 → vgi_python-0.22.1}/packages/vgi-fixtures/docker/docker-entrypoint.sh +0 -0
  91. {vgi_python-0.21.0 → vgi_python-0.22.1}/packages/vgi-fixtures/pyproject.toml +0 -0
  92. {vgi_python-0.21.0 → vgi_python-0.22.1}/scripts/measure_startup.py +0 -0
  93. {vgi_python-0.21.0 → vgi_python-0.22.1}/scripts/run_all_tests.sh +0 -0
  94. {vgi_python-0.21.0 → vgi_python-0.22.1}/test-data/generate.sh +0 -0
  95. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/__init__.py +0 -0
  96. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/_http_fixtures.py +0 -0
  97. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/catalog/__init__.py +0 -0
  98. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/catalog/test_catalog_interface.py +0 -0
  99. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/catalog/test_client_catalog.py +0 -0
  100. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/catalog/test_column_statistics.py +0 -0
  101. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/catalog/test_declarative.py +0 -0
  102. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/catalog/test_example_worker_catalog.py +0 -0
  103. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/catalog/test_integration.py +0 -0
  104. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/catalog/test_required_filters.py +0 -0
  105. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/catalog/test_scan_branches.py +0 -0
  106. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/catalog/test_serialization.py +0 -0
  107. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/catalog/test_setting.py +0 -0
  108. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/catalog/test_storage.py +0 -0
  109. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/catalog/test_time_travel.py +0 -0
  110. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/catalog/test_writable_table.py +0 -0
  111. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/client/__init__.py +0 -0
  112. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/client/test_broken_pipe.py +0 -0
  113. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/client/test_cli.py +0 -0
  114. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/client/test_cli_catalog_functions.py +0 -0
  115. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/client/test_worker_debug.py +0 -0
  116. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/__init__.py +0 -0
  117. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/_stub.py +0 -0
  118. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/conftest.py +0 -0
  119. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_accumulate.py +0 -0
  120. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_aggregate.py +0 -0
  121. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_attach.py +0 -0
  122. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_bearer_auth.py +0 -0
  123. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_const_param_enforcement.py +0 -0
  124. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_container.py +0 -0
  125. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_copy_from.py +0 -0
  126. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_copy_to.py +0 -0
  127. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_directory_parity.py +0 -0
  128. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_function_inventory.py +0 -0
  129. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_github.py +0 -0
  130. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_http_client.py +0 -0
  131. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_http_external_location.py +0 -0
  132. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_http_upload_url.py +0 -0
  133. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_macro.py +0 -0
  134. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_overload.py +0 -0
  135. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_protocol_inventory.py +0 -0
  136. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_protocol_version.py +0 -0
  137. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_resumable_scan.py +0 -0
  138. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_scalar.py +0 -0
  139. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_scalar_attach_opaque_data.py +0 -0
  140. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_secret.py +0 -0
  141. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_settings.py +0 -0
  142. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_table.py +0 -0
  143. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_table_in_out.py +0 -0
  144. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_view.py +0 -0
  145. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conformance/test_writable.py +0 -0
  146. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/conftest.py +0 -0
  147. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/landing/_checker.py +0 -0
  148. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/landing/describe.expected.json +0 -0
  149. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/landing/describe.schema.json +0 -0
  150. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/scalar/__init__.py +0 -0
  151. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/scalar/test_bernoulli_function.py +0 -0
  152. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/scalar/test_binary_packet_function.py +0 -0
  153. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/scalar/test_client.py +0 -0
  154. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/scalar/test_conditional_message_function.py +0 -0
  155. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/scalar/test_hash_seed_function.py +0 -0
  156. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/scalar/test_multiply_by_setting_function.py +0 -0
  157. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/scalar/test_multiply_function.py +0 -0
  158. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/scalar/test_random_bytes_function.py +0 -0
  159. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/scalar/test_return_secret_value_function.py +0 -0
  160. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table/__init__.py +0 -0
  161. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table/generator/__init__.py +0 -0
  162. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table/generator/test_constant_columns_function.py +0 -0
  163. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table/generator/test_double_sequence_function.py +0 -0
  164. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table/generator/test_exception_function.py +0 -0
  165. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table/generator/test_filter_echo_function.py +0 -0
  166. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table/generator/test_logging_function.py +0 -0
  167. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table/generator/test_nested_sequence_function.py +0 -0
  168. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table/generator/test_partitioned_function.py +0 -0
  169. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table/generator/test_projected_data_function.py +0 -0
  170. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table/generator/test_sequence_function.py +0 -0
  171. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table/generator/test_settings_function.py +0 -0
  172. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table/generator/test_struct_settings_function.py +0 -0
  173. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table/generator/test_ten_thousand_function.py +0 -0
  174. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table_in_out/__init__.py +0 -0
  175. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table_in_out/generator/__init__.py +0 -0
  176. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table_in_out/generator/test_buffer_input_function.py +0 -0
  177. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table_in_out/generator/test_echo_function.py +0 -0
  178. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table_in_out/generator/test_exception_functions.py +0 -0
  179. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table_in_out/generator/test_filter_by_setting_function.py +0 -0
  180. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table_in_out/generator/test_repeat_inputs_function.py +0 -0
  181. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table_in_out/generator/test_substream_partial_sum_function.py +0 -0
  182. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table_in_out/generator/test_sum_all_columns_function.py +0 -0
  183. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table_in_out/test_blended_metadata.py +0 -0
  184. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/table_in_out/test_client.py +0 -0
  185. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_access_log_audit.py +0 -0
  186. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_aggregate_function.py +0 -0
  187. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_argument_spec.py +0 -0
  188. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_auth.py +0 -0
  189. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_bind_exceptions.py +0 -0
  190. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_bind_request_at_clause.py +0 -0
  191. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_bound_storage_conformance.py +0 -0
  192. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_cache_control.py +0 -0
  193. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_catalog_auth_binding.py +0 -0
  194. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_copy_from_function.py +0 -0
  195. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_copy_to_function.py +0 -0
  196. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_docstrings.py +0 -0
  197. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_documentation_examples.py +0 -0
  198. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_example_function_arg_types.py +0 -0
  199. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_examples_workers.py +0 -0
  200. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_exception_handling.py +0 -0
  201. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_exceptions.py +0 -0
  202. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_filter_pushdown.py +0 -0
  203. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_filter_pushdown_extension.py +0 -0
  204. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_function_storage.py +0 -0
  205. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_function_storage_azure_sql.py +0 -0
  206. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_function_storage_cf_do.py +0 -0
  207. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_function_storage_cf_do_integration.py +0 -0
  208. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_function_storage_conformance.py +0 -0
  209. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_generated_cpp_constants.py +0 -0
  210. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_generated_cpp_protocol_version.py +0 -0
  211. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_generated_cpp_request_builders.py +0 -0
  212. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_generated_cpp_schemas.py +0 -0
  213. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_generated_cpp_secret.py +0 -0
  214. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_generated_go_schemas.py +0 -0
  215. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_generated_protocol_version.py +0 -0
  216. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_generated_schemas_cross_lang.py +0 -0
  217. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_generated_ts_client.py +0 -0
  218. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_generated_ts_schemas.py +0 -0
  219. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_http_demo_storage.py +0 -0
  220. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_http_s3_offload_input.py +0 -0
  221. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_http_s3_offload_output.py +0 -0
  222. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_landing_conformance.py +0 -0
  223. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_metadata.py +0 -0
  224. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_mypy_consolidated.py +0 -0
  225. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_nest_tensor.py +0 -0
  226. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_otel.py +0 -0
  227. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_projection_enforcement.py +0 -0
  228. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_projection_repro.py +0 -0
  229. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_protocol_classes.py +0 -0
  230. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_resolved_secrets.py +0 -0
  231. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_schema_scoped_functions.py +0 -0
  232. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_schema_utils.py +0 -0
  233. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_setting_secret_annotations.py +0 -0
  234. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_table_buffering_function.py +0 -0
  235. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_table_function_dynamic_to_string.py +0 -0
  236. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_tcp_transport.py +0 -0
  237. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_type_bounds.py +0 -0
  238. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_union_argument.py +0 -0
  239. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_worker.py +0 -0
  240. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_worker_cli.py +0 -0
  241. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/test_worker_page.py +0 -0
  242. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/transactor/__init__.py +0 -0
  243. {vgi_python-0.21.0 → vgi_python-0.22.1}/tests/transactor/test_transactor.py +0 -0
  244. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/__init__.py +0 -0
  245. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_duckdb.py +0 -0
  246. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_storage_profile.py +0 -0
  247. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/__init__.py +0 -0
  248. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/accumulate/__init__.py +0 -0
  249. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/accumulate/worker.py +0 -0
  250. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/aggregate/__init__.py +0 -0
  251. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/aggregate/_common.py +0 -0
  252. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/aggregate/basic.py +0 -0
  253. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/aggregate/dynamic.py +0 -0
  254. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/aggregate/generic.py +0 -0
  255. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/aggregate/listagg.py +0 -0
  256. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/aggregate/percentile.py +0 -0
  257. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/aggregate/same_name.py +0 -0
  258. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/aggregate/secret_typed.py +0 -0
  259. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/aggregate/streaming.py +0 -0
  260. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/aggregate/varargs.py +0 -0
  261. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/aggregate/window.py +0 -0
  262. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/attach_options.py +0 -0
  263. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/bad_enum.py +0 -0
  264. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/bad_protocol.py +0 -0
  265. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/cancellable.py +0 -0
  266. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/catalog.py +0 -0
  267. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/companion.py +0 -0
  268. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/copy_from.py +0 -0
  269. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/copy_to.py +0 -0
  270. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/http_server.py +0 -0
  271. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/narrow_bind/__init__.py +0 -0
  272. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/narrow_bind/worker.py +0 -0
  273. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/nest_tensor.py +0 -0
  274. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/orchard_catalog.py +0 -0
  275. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/projection_repro/__init__.py +0 -0
  276. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/projection_repro/worker.py +0 -0
  277. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/scalar/__init__.py +0 -0
  278. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/scalar/_common.py +0 -0
  279. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/scalar/arithmetic.py +0 -0
  280. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/scalar/bench_ladder.py +0 -0
  281. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/scalar/binary.py +0 -0
  282. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/scalar/formatting.py +0 -0
  283. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/scalar/geo.py +0 -0
  284. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/scalar/null_handling.py +0 -0
  285. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/scalar/random_demo.py +0 -0
  286. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/scalar/same_name.py +0 -0
  287. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/scalar/settings_secrets.py +0 -0
  288. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/scalar/type_info.py +0 -0
  289. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/schema_reconcile/__init__.py +0 -0
  290. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/schema_reconcile/worker.py +0 -0
  291. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/simple_writable.py +0 -0
  292. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/__init__.py +0 -0
  293. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/_common.py +0 -0
  294. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/batch_index.py +0 -0
  295. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/batch_index_broken.py +0 -0
  296. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/cache.py +0 -0
  297. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/catalog_scans.py +0 -0
  298. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/filters.py +0 -0
  299. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/late_materialization.py +0 -0
  300. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/make_series.py +0 -0
  301. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/misc.py +0 -0
  302. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/order_modes.py +0 -0
  303. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/pairs.py +0 -0
  304. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/partition_columns.py +0 -0
  305. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/partition_columns_broken.py +0 -0
  306. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/profiling_example.py +0 -0
  307. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/required_filters.py +0 -0
  308. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/same_name_cached.py +0 -0
  309. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/sequence.py +0 -0
  310. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/settings.py +0 -0
  311. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/transaction_storage.py +0 -0
  312. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/tt_pushdown.py +0 -0
  313. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/typed_probe.py +0 -0
  314. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table/versioned.py +0 -0
  315. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table_in_out.py +0 -0
  316. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/table_in_out_same_name.py +0 -0
  317. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/twin_catalogs.py +0 -0
  318. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/versioned.py +0 -0
  319. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/versioned_tables.py +0 -0
  320. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/worker.py +0 -0
  321. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/writable/__init__.py +0 -0
  322. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/writable/generic.py +0 -0
  323. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/writable/table.py +0 -0
  324. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/_test_fixtures/writable/worker.py +0 -0
  325. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/aggregate_function.py +0 -0
  326. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/argument_spec.py +0 -0
  327. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/arguments.py +0 -0
  328. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/attach_header.py +0 -0
  329. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/auth.py +0 -0
  330. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/cache_control.py +0 -0
  331. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/catalog/__init__.py +0 -0
  332. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/catalog/_descriptor_spec.py +0 -0
  333. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/catalog/attach_option.py +0 -0
  334. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/catalog/catalog_interface.py +0 -0
  335. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/catalog/descriptors.py +0 -0
  336. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/catalog/duckdb_statistics.py +0 -0
  337. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/catalog/secret_type.py +0 -0
  338. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/catalog/setting.py +0 -0
  339. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/catalog/storage.py +0 -0
  340. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/client/__init__.py +0 -0
  341. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/client/catalog_mixin.py +0 -0
  342. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/client/cli.py +0 -0
  343. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/client/cli_catalog.py +0 -0
  344. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/client/cli_schema.py +0 -0
  345. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/client/cli_table.py +0 -0
  346. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/client/cli_transaction.py +0 -0
  347. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/client/cli_utils.py +0 -0
  348. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/client/cli_view.py +0 -0
  349. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/client/client.py +0 -0
  350. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/codegen/__init__.py +0 -0
  351. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/codegen/_common.py +0 -0
  352. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/codegen/cpp_constants.py +0 -0
  353. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/codegen/cpp_protocol_version.py +0 -0
  354. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/codegen/cpp_request_builders.py +0 -0
  355. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/codegen/cpp_schemas.py +0 -0
  356. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/codegen/cpp_secret_protocol_version.py +0 -0
  357. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/codegen/cpp_secret_request_builders.py +0 -0
  358. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/codegen/cpp_secret_schemas.py +0 -0
  359. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/codegen/go_schemas.py +0 -0
  360. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/codegen/protocol_version.py +0 -0
  361. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/codegen/ts_client.py +0 -0
  362. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/codegen/ts_schemas.py +0 -0
  363. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/copy_from_function.py +0 -0
  364. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/copy_to_function.py +0 -0
  365. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/exceptions.py +0 -0
  366. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/function.py +0 -0
  367. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/function_storage.py +0 -0
  368. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/function_storage_azure_sql.py +0 -0
  369. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/function_storage_cf_do.py +0 -0
  370. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/http/__init__.py +0 -0
  371. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/http/demo_storage.py +0 -0
  372. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/http/describe_json.py +0 -0
  373. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/http/landing.html +0 -0
  374. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/http/landing_page.py +0 -0
  375. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/http/worker_page.py +0 -0
  376. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/invocation.py +0 -0
  377. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/logging_config.py +0 -0
  378. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/meta_worker.py +0 -0
  379. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/metadata.py +0 -0
  380. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/otel.py +0 -0
  381. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/protocol.py +0 -0
  382. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/protocol_version.txt +0 -0
  383. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/py.typed +0 -0
  384. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/scalar_function.py +0 -0
  385. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/schema_utils.py +0 -0
  386. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/secret_protocol.py +0 -0
  387. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/secret_service.py +0 -0
  388. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/table_buffering_function.py +0 -0
  389. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/table_filter_pushdown.py +0 -0
  390. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/table_function.py +0 -0
  391. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/table_in_out_function.py +0 -0
  392. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/transactor/__init__.py +0 -0
  393. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/transactor/_duckdb_compat.py +0 -0
  394. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/transactor/client.py +0 -0
  395. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/transactor/protocol.py +0 -0
  396. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/transactor/server.py +0 -0
  397. {vgi_python-0.21.0 → vgi_python-0.22.1}/vgi/worker.py +0 -0
  398. {vgi_python-0.21.0 → vgi_python-0.22.1}/wrangler.jsonc +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vgi-python
3
- Version: 0.21.0
3
+ Version: 0.22.1
4
4
  Summary: Vector Gateway Interface - Connect DuckDB to external programs via Apache Arrow
5
5
  Project-URL: Homepage, https://query.farm
6
6
  Project-URL: Repository, https://github.com/Query-farm/vgi-python
@@ -162,7 +162,7 @@ Requires-Dist: httpx>=0.24
162
162
  Requires-Dist: platformdirs
163
163
  Requires-Dist: pyarrow
164
164
  Requires-Dist: typer>=0.9
165
- Requires-Dist: vgi-rpc>=0.26.0
165
+ Requires-Dist: vgi-rpc>=0.28.3
166
166
  Provides-Extra: azure
167
167
  Requires-Dist: azure-identity>=1.16.0; extra == 'azure'
168
168
  Requires-Dist: pymssql>=2.3.0; extra == 'azure'
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "vgi-python"
3
- version = "0.21.0"
3
+ version = "0.22.1"
4
4
  description = "Vector Gateway Interface - Connect DuckDB to external programs via Apache Arrow"
5
5
  readme = "README.md"
6
6
  keywords = [
@@ -40,7 +40,7 @@ dependencies = [
40
40
  "pyarrow",
41
41
  "typer>=0.9",
42
42
  "platformdirs",
43
- "vgi-rpc>=0.26.0",
43
+ "vgi-rpc>=0.28.3",
44
44
  "httpx>=0.24",
45
45
  ]
46
46
 
@@ -142,6 +142,12 @@ convention = "google"
142
142
 
143
143
  [tool.ruff.format]
144
144
  quote-style = "double"
145
+ # ruff >=0.16 formats Python code blocks embedded in Markdown. Our docs use
146
+ # mkdocs `pymdownx.snippets` includes (`--8<-- "examples/foo.py"`) inside
147
+ # ```python fences; ruff parses those as Python and rewrites them to
148
+ # `--8 < --"..."`, breaking both the docs build and the doc-example tests.
149
+ # Keep Markdown out.
150
+ exclude = ["*.md"]
145
151
 
146
152
  [tool.pydoclint]
147
153
  # Docstring consistency gate (complements ruff's `D` rules, which only check
@@ -206,6 +206,57 @@ class TestCreateApp:
206
206
 
207
207
  assert isinstance(app, falcon.App)
208
208
 
209
+ @staticmethod
210
+ def _health_proof_header(**env: str) -> str | None:
211
+ """Serve an app under ``env`` and read the proof capability header.
212
+
213
+ Args:
214
+ **env: ``VGI_PROXY_PROOF_*`` values to set for the duration.
215
+
216
+ Returns:
217
+ The ``VGI-Proxy-Proof-Required`` value, or ``None`` when absent.
218
+
219
+ """
220
+ import falcon.testing
221
+
222
+ with pytest.MonkeyPatch.context() as mp:
223
+ for key in ("VGI_PROXY_PROOF_MODE", "VGI_PROXY_PROOF_ORIGIN_ID", "VGI_PROXY_PROOF_SECRETS"):
224
+ mp.delenv(key, raising=False)
225
+ for key, value in env.items():
226
+ mp.setenv(key, value)
227
+ app = create_app(_SingleWorker, prefix="/vgi", describe=False)
228
+ resp = falcon.testing.TestClient(app).simulate_get("/vgi/health")
229
+ assert resp.status_code == 200
230
+ return {k.lower(): v for k, v in resp.headers.items()}.get("vgi-proxy-proof-required")
231
+
232
+ def test_advertises_proof_required_in_require_mode(self) -> None:
233
+ """A ``require``-mode worker tells proxies it actually enforces.
234
+
235
+ Derived from ``VGI_PROXY_PROOF_MODE`` rather than passed separately,
236
+ because that env var is also where the gate itself comes from — so the
237
+ advertisement cannot drift from the posture it describes.
238
+ """
239
+ value = self._health_proof_header(
240
+ VGI_PROXY_PROOF_MODE="require",
241
+ VGI_PROXY_PROOF_ORIGIN_ID="worker-a",
242
+ VGI_PROXY_PROOF_SECRETS="k:" + "11" * 32,
243
+ )
244
+ assert value == "true"
245
+
246
+ @pytest.mark.parametrize("mode", ["off", "allow"])
247
+ def test_does_not_advertise_below_require(self, mode: str) -> None:
248
+ """Only ``require`` advertises — ``allow`` never denies, so it must not.
249
+
250
+ A proxy reads this to confirm a rollout landed; an ``allow``-mode worker
251
+ that claimed to require would report the rollout complete while every
252
+ unproofed direct caller still sailed through.
253
+ """
254
+ env = {"VGI_PROXY_PROOF_MODE": mode}
255
+ if mode != "off":
256
+ env["VGI_PROXY_PROOF_ORIGIN_ID"] = "worker-a"
257
+ env["VGI_PROXY_PROOF_SECRETS"] = "k:" + "11" * 32
258
+ assert self._health_proof_header(**env) is None
259
+
209
260
  def test_signing_key_passed(self) -> None:
210
261
  """Explicit signing_key is accepted without warning."""
211
262
  import warnings
@@ -2061,27 +2061,27 @@ wheels = [
2061
2061
 
2062
2062
  [[package]]
2063
2063
  name = "ruff"
2064
- version = "0.15.20"
2065
- source = { registry = "https://pypi.org/simple" }
2066
- sdist = { url = "https://files.pythonhosted.org/packages/43/dc/35b341fc554ba02f217fc10da57d1a75168cfbcf75b0ef2202176d4c4f2d/ruff-0.15.20.tar.gz", hash = "sha256:1416eb04349192646b54de98f146c4f59afe37d0decfc02c3cbbf396f3a28566", size = 4755489, upload-time = "2026-06-25T17:20:37.578Z" }
2067
- wheels = [
2068
- { url = "https://files.pythonhosted.org/packages/94/d9/2d5014f0253ba541d2061d9fa7193f48e941c8b21bb88a7ff9bbe0bd0596/ruff-0.15.20-py3-none-linux_armv6l.whl", hash = "sha256:00e188c53e499c3c1637f73c91dcf2fb56d576cab76ce1be50a27c4e80e37078", size = 10839665, upload-time = "2026-06-25T17:19:44.702Z" },
2069
- { url = "https://files.pythonhosted.org/packages/c6/d3/ac1798ba64f670698867fcfc591d50e7e421bef137db564858f619a30fcf/ruff-0.15.20-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9ebd1fd9b9c95fc0bd7b2761aebec1f030013d2e193a2901b224af68fe47251b", size = 11208649, upload-time = "2026-06-25T17:19:48.787Z" },
2070
- { url = "https://files.pythonhosted.org/packages/47/47/d3ac899991202095dfcf3d5176be4272642be3cf981a2f1a30f72a2afb95/ruff-0.15.20-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c5b16cdd67ca108185cd36dce98c576350c03b1660a751de725fb049193a0632", size = 10622638, upload-time = "2026-06-25T17:19:51.354Z" },
2071
- { url = "https://files.pythonhosted.org/packages/33/13/4e043fe30aa94d4ff5213a9881fc296d12960f5971b234a5263fdc225312/ruff-0.15.20-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3413bb3c3d2ca6a8208f1f4809cd2dca3c6de6d0b491c0e70847672bde6e6efd", size = 10984227, upload-time = "2026-06-25T17:19:54.044Z" },
2072
- { url = "https://files.pythonhosted.org/packages/76/e6/92e7bf40388bc5800073b96564f56264f7e48bfd1a498f5ced6ae6d5a769/ruff-0.15.20-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd7ec42b3bb3da066488db093308a69c4ac5ee6d2af333a86ba6e2eb2e7dd44b", size = 10622882, upload-time = "2026-06-25T17:19:57.037Z" },
2073
- { url = "https://files.pythonhosted.org/packages/13/7a/43460be3f24495a3aa46d4b16873e2c4941b3b5f0b00cf88c03b7b94b339/ruff-0.15.20-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1a36ad0eb77fba9aabfb69ede54de6f376d04ac18ebea022847046d340a8267", size = 11474808, upload-time = "2026-06-25T17:20:00.357Z" },
2074
- { url = "https://files.pythonhosted.org/packages/27/a0/f37077884873221c6b33b4ab49eb18f9f88e54a16a25a5bca59bef46dd66/ruff-0.15.20-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6df3b1e4610432f0386dba04d853b5f08cbbc903410c6fcc02f620f05aff53c", size = 12293094, upload-time = "2026-06-25T17:20:03.446Z" },
2075
- { url = "https://files.pythonhosted.org/packages/a6/74/165545b60256a9704c21ac0ec4a0d07933b320812f9584836c9f4aca4292/ruff-0.15.20-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e89f198a1ea6ef0d727c1cf16088bc91a6cb0ab947dedc966715691647186eae", size = 11526176, upload-time = "2026-06-25T17:20:06.301Z" },
2076
- { url = "https://files.pythonhosted.org/packages/86/b1/a976a136d40ade83ce743578399865f57001003a409acadc0ecbb3051082/ruff-0.15.20-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309809086c2acb67624950a3c8133e80f32d0d3e27106c0cd60ff26657c9f24b", size = 11520767, upload-time = "2026-06-25T17:20:09.191Z" },
2077
- { url = "https://files.pythonhosted.org/packages/19/0f/f032696cb01c9b54c0263fa393474d7758f1cdc021a01b04e3cbc2500999/ruff-0.15.20-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:2d2374caa2f2c2f9e2b7da0a50802cfb8b79f55a9b5e49379f564544fbf56487", size = 11500132, upload-time = "2026-06-25T17:20:13.602Z" },
2078
- { url = "https://files.pythonhosted.org/packages/4b/f4/51b1a14bc69e8c224b15dab9cce8e99b425e0455d462caa2b3c9be2b6a8e/ruff-0.15.20-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a1ed17b65293e0c2f22fc387bc13198a5de94bf4429589b0ff6946b0feaf21a3", size = 10943828, upload-time = "2026-06-25T17:20:16.635Z" },
2079
- { url = "https://files.pythonhosted.org/packages/71/4b/fe267640783cd02bf6c5cc290b1df1051be2ec294c678b5c15fe19e52343/ruff-0.15.20-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f701305e66b38ea6c91882490eb73459796808e4c6362a1b765255e0cdcd4053", size = 10645418, upload-time = "2026-06-25T17:20:19.4Z" },
2080
- { url = "https://files.pythonhosted.org/packages/b0/c0/a65aa4ec2f5e87a1df32dc3ec1fede434fe3dfd5cbcf3b503cafc676ab54/ruff-0.15.20-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5b9c0c367ad8e5d0d5b5b8537864c469a0a0e55417aadfbeca41fa61333be9f4", size = 11211770, upload-time = "2026-06-25T17:20:22.033Z" },
2081
- { url = "https://files.pythonhosted.org/packages/5a/a4/0caa331d954ae2723d729d351c989cb4ca8b6077d5c6c2cb6de75e98c041/ruff-0.15.20-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:01cc00dd58f0df339d0e902219dd53990ea99996a0344e5d9cc8d45d5307e460", size = 11618698, upload-time = "2026-06-25T17:20:25.259Z" },
2082
- { url = "https://files.pythonhosted.org/packages/10/9b/5f14927848d2fd4aa891fd88d883788c5a7baba561c7874732364045708c/ruff-0.15.20-py3-none-win32.whl", hash = "sha256:ed65ef510e43a137207e0f01cfcf998aeddb1aeeda5c9d35023e910284d7cf21", size = 10857322, upload-time = "2026-06-25T17:20:28.612Z" },
2083
- { url = "https://files.pythonhosted.org/packages/fa/f0/fe47c501f9dea92a26d788ff98bb5d92ed4cb4c88792c5c88af6b697dc8e/ruff-0.15.20-py3-none-win_amd64.whl", hash = "sha256:a525c81c70fb0380344dd1d8745d8cc1c890b7fc94a58d5a07bd8eb9557b8415", size = 11993274, upload-time = "2026-06-25T17:20:31.871Z" },
2084
- { url = "https://files.pythonhosted.org/packages/d7/2b/9555445e1201d92b3195f45cdb153a0b68f24e0a4273f6e3d5ab46e212bb/ruff-0.15.20-py3-none-win_arm64.whl", hash = "sha256:2f5b2a6d614e8700388806a14996c40fab2c47b819ef57d790a34878858ed9ca", size = 11343498, upload-time = "2026-06-25T17:20:35.03Z" },
2064
+ version = "0.16.0"
2065
+ source = { registry = "https://pypi.org/simple" }
2066
+ sdist = { url = "https://files.pythonhosted.org/packages/4d/94/1e5e4967626faf12fa56999cd6222dff6992ceb086ad7945756baf70c7a7/ruff-0.16.0.tar.gz", hash = "sha256:e460aafd5495ec89efaa6ced2e4a9a581116451e1c88b9d37ef497e0f8e93982", size = 4790557, upload-time = "2026-07-23T19:11:30.981Z" }
2067
+ wheels = [
2068
+ { url = "https://files.pythonhosted.org/packages/4b/81/1c8818fee7ce1a04cd7d1b3172e0a8f8e4f1dc4feb7fc390e16daa8af323/ruff-0.16.0-py3-none-linux_armv6l.whl", hash = "sha256:e5115729eb08c585e5121978ba5d5b60caeae394ce21b9fb5e6cd33a1c6c9b1e", size = 10754633, upload-time = "2026-07-23T19:10:46.415Z" },
2069
+ { url = "https://files.pythonhosted.org/packages/23/df/beaf59c09d68db84304d555f188b276a77132a5d5b0b67a5c762aa143628/ruff-0.16.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:3c954b1d580bfa035b41654f7858cc7e71d5fc3ac5b723dd62bd9133830ed522", size = 10969164, upload-time = "2026-07-23T19:10:50.271Z" },
2070
+ { url = "https://files.pythonhosted.org/packages/42/ce/741cd197496a1abbf51352710fd15ed995d2a2be87189c1da26a450d6e83/ruff-0.16.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e01c21d10eb1b29f47b7454e1f4056db9a3f0260c646aa88457c610291db9f81", size = 10488846, upload-time = "2026-07-23T19:10:52.639Z" },
2071
+ { url = "https://files.pythonhosted.org/packages/52/2a/a2db8e88cade358f5cdcb05674a917751074109315d014eb6352d9a893f7/ruff-0.16.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e364e5ed22ed8dc05082fd78e35308618260907ac2d3c1d637b2e682415b6c9", size = 10889729, upload-time = "2026-07-23T19:10:54.89Z" },
2072
+ { url = "https://files.pythonhosted.org/packages/42/65/62a771694ebd63029dc953e27dbad40e1588bd4860ff9fe881018fddaa49/ruff-0.16.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d327b8fc113a1d4421a04f3839d3752057c8dd1ee320223a6f3f52d04ada462a", size = 10568275, upload-time = "2026-07-23T19:10:56.993Z" },
2073
+ { url = "https://files.pythonhosted.org/packages/3f/e2/ced249fe8af5f086c5c58cc21cc3356d50f32f7401c5df87050c999620a7/ruff-0.16.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9b50c55e263103586b3dcf5f73d479eb8cb5fdb6098fec59a62891dab653717", size = 11385112, upload-time = "2026-07-23T19:10:59.615Z" },
2074
+ { url = "https://files.pythonhosted.org/packages/87/0b/05154977a8fd69eeb6c103271f55403bfd8711f5c0f8ed07489d95a504e7/ruff-0.16.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0ff4a79ce3ec0172f3241943835de1c4cb4e2dcd07f0f8c2d02603dbbbee4b17", size = 12207008, upload-time = "2026-07-23T19:11:02.154Z" },
2075
+ { url = "https://files.pythonhosted.org/packages/fb/29/98225831a3a1eab0e02f4acc6ca6559a98611dcc68b6965ff4b7234627c1/ruff-0.16.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e95c448fca1fb2a18372a9440926c5a6ee789639bb975c72e7ae6d0b04218ab4", size = 11650842, upload-time = "2026-07-23T19:11:04.557Z" },
2076
+ { url = "https://files.pythonhosted.org/packages/91/66/6bd3cf90500653d55dc0ffc8507aa8300bd49d0214b2e8cb4d3fef2943ba/ruff-0.16.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f11a8d11010301d0a398a2fdef67691feca7294da6aef55e2150e8fa2cd520b", size = 11400718, upload-time = "2026-07-23T19:11:09.233Z" },
2077
+ { url = "https://files.pythonhosted.org/packages/8e/a2/a54eb4eae05d66364050a5d3b8a9c5ef88196531b3cbe7109d873f87f819/ruff-0.16.0-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:48044c678e9cb8698246c99b14aaccfa6601dea7379eb48a6f8f73f7a6d86cd0", size = 11426177, upload-time = "2026-07-23T19:11:11.994Z" },
2078
+ { url = "https://files.pythonhosted.org/packages/1a/be/16e3eea4b2a478a496919f5e36f17c4559e54620bd3bbac5d6affa068006/ruff-0.16.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7aa0959bad8eb8bef50340154fc9b58678dae31fa4293afa38b44b6e552c0213", size = 10856126, upload-time = "2026-07-23T19:11:14.221Z" },
2079
+ { url = "https://files.pythonhosted.org/packages/a2/84/252eb8b868a16eec7257c14f504f77537e734b2d69c762e639e588e304a3/ruff-0.16.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:28ea2b7df8ebf7f9da6b7d47b230ab48f387c0a29be3b474c4d0740e197bb9af", size = 10571208, upload-time = "2026-07-23T19:11:16.378Z" },
2080
+ { url = "https://files.pythonhosted.org/packages/21/09/817a482f542f7570cbb4554b26e896610c7114f539b1d9e2d2145bf6bef6/ruff-0.16.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:33a3dfac8c35f81498dea9181bccc2f4c4bc8f1521a1dd9406e77643e0f0fb09", size = 11063329, upload-time = "2026-07-23T19:11:19.173Z" },
2081
+ { url = "https://files.pythonhosted.org/packages/2e/23/9403c180ca1cb9b1f7335f5c3e5305c09d49ea5b345196682a36028bde4a/ruff-0.16.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a5237a0bda500d30d81b8e07a6973a5cbc772864cbf746ae2f4e8a2e01c9f4ed", size = 11489751, upload-time = "2026-07-23T19:11:21.74Z" },
2082
+ { url = "https://files.pythonhosted.org/packages/b2/1d/1b2ef7bcde851c78d7f17f1cca13fd6dc695fc4b3d6197941e72cae5b132/ruff-0.16.0-py3-none-win32.whl", hash = "sha256:7fab76fa065c873f41ff744347c6e77bcc3dfec4bcc754dc26b63d23c0f7f5fb", size = 10785885, upload-time = "2026-07-23T19:11:23.947Z" },
2083
+ { url = "https://files.pythonhosted.org/packages/b2/a3/d5e4ef7a56be3f928ffb90b94c25ba7d3cb9c7fe0736aeaaedf361770712/ruff-0.16.0-py3-none-win_amd64.whl", hash = "sha256:429c117f022bf481fabd9d551e7a3952b24c65e6ef44337ea09d90bebef14472", size = 11923141, upload-time = "2026-07-23T19:11:26.409Z" },
2084
+ { url = "https://files.pythonhosted.org/packages/cb/9a/8415f2657cbe200f41a4531ccededf135505a92d4a012229121f885b26f9/ruff-0.16.0-py3-none-win_arm64.whl", hash = "sha256:14296fedcd2705c77ab8235439278bbb38f285cf7da5528b00b3e330c3d4872d", size = 11273407, upload-time = "2026-07-23T19:11:28.705Z" },
2085
2085
  ]
2086
2086
 
2087
2087
  [[package]]
@@ -2228,7 +2228,7 @@ requires-dist = [
2228
2228
 
2229
2229
  [[package]]
2230
2230
  name = "vgi-python"
2231
- version = "0.21.0"
2231
+ version = "0.22.1"
2232
2232
  source = { editable = "." }
2233
2233
  dependencies = [
2234
2234
  { name = "click" },
@@ -2338,7 +2338,7 @@ requires-dist = [
2338
2338
  { name = "vgi-python", extras = ["test-fixtures"], marker = "extra == 'test-fixtures-writable'" },
2339
2339
  { name = "vgi-python", extras = ["test-fixtures", "test-fixtures-writable", "http", "oauth", "otel", "sentry", "azure"], marker = "extra == 'dev'" },
2340
2340
  { name = "vgi-python", extras = ["transactor"], marker = "extra == 'test-fixtures-writable'" },
2341
- { name = "vgi-rpc", specifier = ">=0.26.0" },
2341
+ { name = "vgi-rpc", specifier = ">=0.28.3" },
2342
2342
  { name = "vgi-rpc", extras = ["conformance", "external", "http", "oauth", "otel", "sentry"], marker = "extra == 'dev'" },
2343
2343
  { name = "vgi-rpc", extras = ["http"], marker = "extra == 'http'" },
2344
2344
  { name = "vgi-rpc", extras = ["oauth"], marker = "extra == 'oauth'" },
@@ -2367,7 +2367,7 @@ docs = [
2367
2367
 
2368
2368
  [[package]]
2369
2369
  name = "vgi-rpc"
2370
- version = "0.26.0"
2370
+ version = "0.28.3"
2371
2371
  source = { registry = "https://pypi.org/simple" }
2372
2372
  dependencies = [
2373
2373
  { name = "docstring-parser" },
@@ -2375,9 +2375,9 @@ dependencies = [
2375
2375
  { name = "pywin32", marker = "sys_platform == 'win32'" },
2376
2376
  { name = "tzdata", marker = "sys_platform == 'win32'" },
2377
2377
  ]
2378
- sdist = { url = "https://files.pythonhosted.org/packages/b5/51/86d4c4466cf5311e80db28f535c02b92961f3d5160a0aae348112a03f7d5/vgi_rpc-0.26.0.tar.gz", hash = "sha256:c0966c99e087f923b228b2211877a8695bf42052d9cde05ce9a4bf077047cb78", size = 869625, upload-time = "2026-07-21T17:39:12.871Z" }
2378
+ sdist = { url = "https://files.pythonhosted.org/packages/a0/5a/1996a64ca9ecb0a030cee5a4b9944301f20d6269369b39a5d30f07bf71a9/vgi_rpc-0.28.3.tar.gz", hash = "sha256:772f535912926ce47c17c3eba33769ad226171277159c591f441169f642e14d6", size = 908548, upload-time = "2026-07-27T16:45:47.344Z" }
2379
2379
  wheels = [
2380
- { url = "https://files.pythonhosted.org/packages/57/51/d86efc32aef03d69d197916f9d18d0f3719ebd843424cfb9a782ced041c9/vgi_rpc-0.26.0-py3-none-any.whl", hash = "sha256:2c455edb517831867342ce2f105386b73b1fa23137477916c5e5d7a14b66e0fc", size = 386786, upload-time = "2026-07-21T17:39:11.142Z" },
2380
+ { url = "https://files.pythonhosted.org/packages/70/d1/db1b3aa48d1d0526bc30ad72e51ad8fd7f67f693310de8c143e707a87d0a/vgi_rpc-0.28.3-py3-none-any.whl", hash = "sha256:bf913b9b95ac4abde4e4ddad5b228c1d81bd748268773f9a2e5fa9626cc68bf7", size = 406388, upload-time = "2026-07-27T16:45:45.905Z" },
2381
2381
  ]
2382
2382
 
2383
2383
  [package.optional-dependencies]
@@ -32,7 +32,7 @@ import os
32
32
  import sys
33
33
  from collections.abc import Callable
34
34
  from types import ModuleType
35
- from typing import TYPE_CHECKING, Any
35
+ from typing import TYPE_CHECKING, Any, Literal
36
36
 
37
37
  from vgi.logging_config import LogFormat, LogLevel
38
38
 
@@ -202,6 +202,7 @@ def create_app(
202
202
  signing_key: bytes | None = None,
203
203
  log_level: int = logging.INFO,
204
204
  authenticate: Callable[[falcon.Request], AuthContext] | None = None,
205
+ proxy_proof_required: bool | None = None,
205
206
  oauth_resource_metadata: Any = None,
206
207
  otel_config: OtelConfig | None = None,
207
208
  max_stream_response_bytes: int | None = None,
@@ -224,6 +225,12 @@ def create_app(
224
225
  authenticate: Optional callback that validates each HTTP request
225
226
  and returns an `AuthContext`. When ``None``, all requests are
226
227
  anonymous.
228
+ proxy_proof_required: Whether to advertise ``VGI-Proxy-Proof-Required``
229
+ so a proxy can confirm this worker actually enforces the proof it
230
+ mints. ``None`` (the default) derives it from
231
+ ``VGI_PROXY_PROOF_MODE``, which is also where the gate itself comes
232
+ from — so the advertisement cannot drift from the posture. Pass a
233
+ bool only when supplying a hand-built gate via ``authenticate``.
227
234
  oauth_resource_metadata: Optional `OAuthResourceMetadata` for
228
235
  RFC 9728 discovery endpoint.
229
236
  otel_config: Optional OpenTelemetry configuration. When provided,
@@ -259,6 +266,9 @@ def create_app(
259
266
  if signing_key is None:
260
267
  signing_key = os.urandom(32)
261
268
 
269
+ if proxy_proof_required is None:
270
+ proxy_proof_required = (os.environ.get("VGI_PROXY_PROOF_MODE") or "").strip().lower() == "require"
271
+
262
272
  worker = worker_cls(quiet=True, log_level=log_level)
263
273
  worker._vgi_tracer = VgiTracer.create(otel_config)
264
274
  worker._signing_key = signing_key
@@ -271,6 +281,7 @@ def create_app(
271
281
  cors_origins=cors_origins,
272
282
  token_key=signing_key,
273
283
  authenticate=authenticate,
284
+ proxy_proof_required=proxy_proof_required,
274
285
  oauth_resource_metadata=oauth_resource_metadata,
275
286
  otel_config=otel_config,
276
287
  max_stream_response_bytes=max_stream_response_bytes,
@@ -429,6 +440,10 @@ def _resolve_authenticate() -> Callable[..., Any] | None:
429
440
  - ``VGI_JWT_ISSUER`` + ``VGI_JWT_AUDIENCE``: JWT/JWKS auth
430
441
  (requires ``vgi[oauth]`` extra). Optional ``VGI_JWT_JWKS_URI``.
431
442
  - When both bearer and JWT are set, they are chained (JWT first).
443
+ - ``VGI_PROXY_PROOF_MODE``: ``allow`` or ``require`` gates every request
444
+ on proof that it arrived through a trusted proxy. This is a
445
+ precondition ANDed with whichever credential above is configured, not
446
+ an alternative to one.
432
447
 
433
448
  Returns:
434
449
  An authenticate callback, or None if no auth env vars are set.
@@ -438,14 +453,84 @@ def _resolve_authenticate() -> Callable[..., Any] | None:
438
453
  JWT issuer without audience).
439
454
 
440
455
  """
441
- bearer_auth = _resolve_bearer_authenticate()
442
- jwt_auth = _resolve_jwt_authenticate()
456
+ # Ordered by cost: JWT resolves a signature, bearer does a constant-time
457
+ # scan over the token set, so the cheaper one goes last.
458
+ candidates = [fn for fn in (_resolve_jwt_authenticate(), _resolve_bearer_authenticate()) if fn is not None]
443
459
 
444
- if bearer_auth is not None and jwt_auth is not None:
460
+ inner: Callable[..., Any] | None
461
+ if len(candidates) > 1:
445
462
  from vgi_rpc.http import chain_authenticate
446
463
 
447
- return chain_authenticate(jwt_auth, bearer_auth)
448
- return jwt_auth or bearer_auth
464
+ inner = chain_authenticate(*candidates)
465
+ else:
466
+ inner = candidates[0] if candidates else None
467
+
468
+ gate = _resolve_proxy_proof_gate()
469
+ if gate is None:
470
+ return inner
471
+
472
+ # AND, not OR: chaining the gate would let any later credential satisfy
473
+ # the request on its own, which is exactly the bypass the gate exists to
474
+ # close. `inner` may be None — proof alone means "only my proxy may call
475
+ # this worker", with user identity handled upstream.
476
+ from vgi_rpc.http import require_all
477
+
478
+ return require_all(gate, inner)
479
+
480
+
481
+ def _resolve_proxy_proof_gate() -> Any | None:
482
+ """Build a proxy-proof gate from ``VGI_PROXY_PROOF_*`` environment variables.
483
+
484
+ Env vars:
485
+
486
+ - ``VGI_PROXY_PROOF_MODE``: ``off`` (default), ``allow`` or ``require``.
487
+ - ``VGI_PROXY_PROOF_ORIGIN_ID``: this worker's identifier. Folded into
488
+ every MAC but never transmitted, so it must match what the proxy is
489
+ configured to prove to.
490
+ - ``VGI_PROXY_PROOF_SECRETS``: ``kid:hex`` pairs, comma-separated. The
491
+ ``kid`` doubles as the proxy's label in the audit trail.
492
+ - ``VGI_PROXY_PROOF_SKEW``: acceptance half-window in seconds (default 30).
493
+
494
+ Returns:
495
+ A gate for ``require_all``, or None when the feature is off.
496
+
497
+ Raises:
498
+ SystemExit: On any malformed value. Deliberately fail-closed: the
499
+ secret is shared with an independently-deployed proxy, so a typo
500
+ would otherwise silently reject every request with no diagnostic.
501
+
502
+ """
503
+ raw_mode = (os.environ.get("VGI_PROXY_PROOF_MODE") or "off").strip().lower()
504
+ if raw_mode == "off":
505
+ return None
506
+ if raw_mode not in ("allow", "require"):
507
+ sys.stderr.write(
508
+ f"Error: VGI_PROXY_PROOF_MODE must be 'off', 'allow' or 'require', got {raw_mode!r}\n",
509
+ )
510
+ sys.exit(1)
511
+ mode: Literal["allow", "require"] = "allow" if raw_mode == "allow" else "require"
512
+
513
+ from vgi_rpc.http import ProxyProofConfig, parse_secrets, proxy_proof_gate
514
+
515
+ raw_secrets = os.environ.get("VGI_PROXY_PROOF_SECRETS") or ""
516
+ skew_raw = os.environ.get("VGI_PROXY_PROOF_SKEW") or "30"
517
+ try:
518
+ secrets = parse_secrets(raw_secrets)
519
+ config = ProxyProofConfig(
520
+ mode=mode,
521
+ origin_id=os.environ.get("VGI_PROXY_PROOF_ORIGIN_ID") or "",
522
+ secrets=secrets,
523
+ skew_seconds=int(skew_raw),
524
+ )
525
+ except ValueError as exc:
526
+ sys.stderr.write(
527
+ f"Error: invalid proxy-proof configuration: {exc}\n"
528
+ "Set VGI_PROXY_PROOF_MODE=off to disable, or fix "
529
+ "VGI_PROXY_PROOF_ORIGIN_ID / VGI_PROXY_PROOF_SECRETS "
530
+ "(kid:hex pairs, 64 hex chars each; generate with 'openssl rand -hex 32').\n",
531
+ )
532
+ sys.exit(1)
533
+ return proxy_proof_gate(config)
449
534
 
450
535
 
451
536
  def _resolve_bearer_authenticate() -> Callable[..., Any] | None:
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
File without changes
File without changes
File without changes
File without changes