vgi-python 0.31.4__tar.gz → 0.32.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (652) hide show
  1. {vgi_python-0.31.4 → vgi_python-0.32.0}/PKG-INFO +1 -1
  2. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/protocol/vgi-protocol-proposed-changes.md +54 -8
  3. {vgi_python-0.31.4 → vgi_python-0.32.0}/pyproject.toml +1 -1
  4. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_writable_table.py +47 -21
  5. vgi_python-0.32.0/tests/test_write_results.py +50 -0
  6. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/transactor/test_transactor.py +10 -5
  7. {vgi_python-0.31.4 → vgi_python-0.32.0}/uv.lock +1 -1
  8. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/__init__.py +5 -0
  9. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/schema_reconcile/worker.py +1 -3
  10. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/simple_writable.py +72 -32
  11. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/writable/generic.py +14 -10
  12. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/writable/table.py +10 -10
  13. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/writable/worker.py +1 -4
  14. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/catalog/__init__.py +5 -0
  15. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/catalog/catalog_interface.py +7 -11
  16. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/catalog/descriptors.py +27 -3
  17. vgi_python-0.32.0/vgi/http/vgi-client.js +22 -0
  18. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/transactor/protocol.py +4 -3
  19. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/transactor/server.py +54 -21
  20. vgi_python-0.32.0/vgi/write_results.py +73 -0
  21. vgi_python-0.31.4/vgi/http/vgi-client.js +0 -23
  22. {vgi_python-0.31.4 → vgi_python-0.32.0}/.dockerignore +0 -0
  23. {vgi_python-0.31.4 → vgi_python-0.32.0}/.gitattributes +0 -0
  24. {vgi_python-0.31.4 → vgi_python-0.32.0}/.github/dependabot.yml +0 -0
  25. {vgi_python-0.31.4 → vgi_python-0.32.0}/.github/styles/config/vocabularies/VGI/accept.txt +0 -0
  26. {vgi_python-0.31.4 → vgi_python-0.32.0}/.github/workflows/ci.yml +0 -0
  27. {vgi_python-0.31.4 → vgi_python-0.32.0}/.github/workflows/docs.yml +0 -0
  28. {vgi_python-0.31.4 → vgi_python-0.32.0}/.github/workflows/integration.yml +0 -0
  29. {vgi_python-0.31.4 → vgi_python-0.32.0}/.github/workflows/release.yml +0 -0
  30. {vgi_python-0.31.4 → vgi_python-0.32.0}/.github/workflows/tailnet-integration.yml +0 -0
  31. {vgi_python-0.31.4 → vgi_python-0.32.0}/.gitignore +0 -0
  32. {vgi_python-0.31.4 → vgi_python-0.32.0}/.python-version +0 -0
  33. {vgi_python-0.31.4 → vgi_python-0.32.0}/.vale.ini +0 -0
  34. {vgi_python-0.31.4 → vgi_python-0.32.0}/CLAUDE.md +0 -0
  35. {vgi_python-0.31.4 → vgi_python-0.32.0}/DOCS_ACCEPTANCE_CRITERIA.md +0 -0
  36. {vgi_python-0.31.4 → vgi_python-0.32.0}/DOCS_REVIEW_RUBRIC.md +0 -0
  37. {vgi_python-0.31.4 → vgi_python-0.32.0}/DOCS_USABILITY_TEST.md +0 -0
  38. {vgi_python-0.31.4 → vgi_python-0.32.0}/LICENSE +0 -0
  39. {vgi_python-0.31.4 → vgi_python-0.32.0}/PROTOCOL.md +0 -0
  40. {vgi_python-0.31.4 → vgi_python-0.32.0}/README.md +0 -0
  41. {vgi_python-0.31.4 → vgi_python-0.32.0}/RELEASE-RUNBOOK.md +0 -0
  42. {vgi_python-0.31.4 → vgi_python-0.32.0}/SECURITY.md +0 -0
  43. {vgi_python-0.31.4 → vgi_python-0.32.0}/ci/README.md +0 -0
  44. {vgi_python-0.31.4 → vgi_python-0.32.0}/ci/preprocess-require.awk +0 -0
  45. {vgi_python-0.31.4 → vgi_python-0.32.0}/ci/run-integration.sh +0 -0
  46. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/README.md +0 -0
  47. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/negative/and-too-few-children.json +0 -0
  48. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/negative/delta-required-upsert.json +0 -0
  49. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/negative/nested-runtime-filter.json +0 -0
  50. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/negative/remove-with-expression.json +0 -0
  51. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/negative/required-runtime-filter.json +0 -0
  52. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/negative/snapshot-nonzero-revision.json +0 -0
  53. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/negative/unknown-document-property.json +0 -0
  54. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/negative/unknown-node.json +0 -0
  55. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/positive/advisory-upsert-delta.json +0 -0
  56. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/positive/empty-snapshot.json +0 -0
  57. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/positive/nested-required-snapshot.json +0 -0
  58. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/positive/remove-delta.json +0 -0
  59. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/positive/runtime-filter-snapshot.json +0 -0
  60. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/filter-v2.schema.json +0 -0
  61. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/generate_runtime.py +0 -0
  62. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/manifest.json +0 -0
  63. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/run_worker.py +0 -0
  64. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-add/expected.arrow +0 -0
  65. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-add/filter.arrow +0 -0
  66. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-add/input.arrow +0 -0
  67. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-multiply/expected.arrow +0 -0
  68. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-multiply/filter.arrow +0 -0
  69. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-multiply/input.arrow +0 -0
  70. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-negate/expected.arrow +0 -0
  71. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-negate/filter.arrow +0 -0
  72. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-negate/input.arrow +0 -0
  73. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-subtract/expected.arrow +0 -0
  74. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-subtract/filter.arrow +0 -0
  75. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-subtract/input.arrow +0 -0
  76. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/cast-integer-to-double/expected.arrow +0 -0
  77. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/cast-integer-to-double/filter.arrow +0 -0
  78. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/cast-integer-to-double/input.arrow +0 -0
  79. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-distinct_from/expected.arrow +0 -0
  80. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-distinct_from/filter.arrow +0 -0
  81. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-distinct_from/input.arrow +0 -0
  82. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-distinct_from/worker-expected.arrow +0 -0
  83. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-eq/expected.arrow +0 -0
  84. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-eq/filter.arrow +0 -0
  85. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-eq/input.arrow +0 -0
  86. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-eq/worker-expected.arrow +0 -0
  87. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-ge/expected.arrow +0 -0
  88. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-ge/filter.arrow +0 -0
  89. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-ge/input.arrow +0 -0
  90. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-ge/worker-expected.arrow +0 -0
  91. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-gt/expected.arrow +0 -0
  92. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-gt/filter.arrow +0 -0
  93. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-gt/input.arrow +0 -0
  94. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-gt/worker-expected.arrow +0 -0
  95. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-le/expected.arrow +0 -0
  96. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-le/filter.arrow +0 -0
  97. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-le/input.arrow +0 -0
  98. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-le/worker-expected.arrow +0 -0
  99. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-lt/expected.arrow +0 -0
  100. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-lt/filter.arrow +0 -0
  101. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-lt/input.arrow +0 -0
  102. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-lt/worker-expected.arrow +0 -0
  103. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-ne/expected.arrow +0 -0
  104. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-ne/filter.arrow +0 -0
  105. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-ne/input.arrow +0 -0
  106. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-ne/worker-expected.arrow +0 -0
  107. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-not_distinct_from/expected.arrow +0 -0
  108. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-not_distinct_from/filter.arrow +0 -0
  109. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-not_distinct_from/input.arrow +0 -0
  110. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-not_distinct_from/worker-expected.arrow +0 -0
  111. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-atomic-multi-update/delta-0.arrow +0 -0
  112. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-atomic-multi-update/expected.arrow +0 -0
  113. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-atomic-multi-update/filter.arrow +0 -0
  114. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-atomic-multi-update/input.arrow +0 -0
  115. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-empty-noop/delta-0.arrow +0 -0
  116. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-empty-noop/expected.arrow +0 -0
  117. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-empty-noop/filter.arrow +0 -0
  118. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-empty-noop/input.arrow +0 -0
  119. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-upsert-remove-stale/delta-0.arrow +0 -0
  120. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-upsert-remove-stale/delta-1.arrow +0 -0
  121. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-upsert-remove-stale/delta-2.arrow +0 -0
  122. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-upsert-remove-stale/expected.arrow +0 -0
  123. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-upsert-remove-stale/filter.arrow +0 -0
  124. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-upsert-remove-stale/input.arrow +0 -0
  125. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/empty-snapshot/expected.arrow +0 -0
  126. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/empty-snapshot/filter.arrow +0 -0
  127. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/empty-snapshot/input.arrow +0 -0
  128. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/empty-snapshot/worker-expected.arrow +0 -0
  129. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-cast-type-not-null/filter.arrow +0 -0
  130. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-cast-type-not-null/input.arrow +0 -0
  131. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-column-index/filter.arrow +0 -0
  132. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-column-index/input.arrow +0 -0
  133. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-column-name/filter.arrow +0 -0
  134. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-column-name/input.arrow +0 -0
  135. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-contextual-cast-without-session/filter.arrow +0 -0
  136. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-contextual-cast-without-session/input.arrow +0 -0
  137. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-duplicate-predicate-id/filter.arrow +0 -0
  138. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-duplicate-predicate-id/input.arrow +0 -0
  139. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-external-column-index/filter.arrow +0 -0
  140. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-external-column-index/input.arrow +0 -0
  141. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-external-column-index/join-keys-0.arrow +0 -0
  142. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-external-column-name/filter.arrow +0 -0
  143. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-external-column-name/input.arrow +0 -0
  144. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-external-column-name/join-keys-0.arrow +0 -0
  145. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-field-non-struct/filter.arrow +0 -0
  146. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-field-non-struct/input.arrow +0 -0
  147. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-in-payload-not-list/filter.arrow +0 -0
  148. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-in-payload-not-list/input.arrow +0 -0
  149. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-in-payload-null-list/filter.arrow +0 -0
  150. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-in-payload-null-list/input.arrow +0 -0
  151. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-invalid-overload/filter.arrow +0 -0
  152. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-invalid-overload/input.arrow +0 -0
  153. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-missing-literal/filter.arrow +0 -0
  154. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-missing-literal/input.arrow +0 -0
  155. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-non-boolean-root/filter.arrow +0 -0
  156. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-non-boolean-root/input.arrow +0 -0
  157. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-unknown-standard-function/filter.arrow +0 -0
  158. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-unknown-standard-function/input.arrow +0 -0
  159. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/external-in-nonzero-column/expected.arrow +0 -0
  160. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/external-in-nonzero-column/filter.arrow +0 -0
  161. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/external-in-nonzero-column/input.arrow +0 -0
  162. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/external-in-nonzero-column/join-keys-0.arrow +0 -0
  163. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/external-in-nonzero-column/worker-expected.arrow +0 -0
  164. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-contains/expected.arrow +0 -0
  165. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-contains/filter.arrow +0 -0
  166. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-contains/input.arrow +0 -0
  167. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-ends-with/expected.arrow +0 -0
  168. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-ends-with/filter.arrow +0 -0
  169. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-ends-with/input.arrow +0 -0
  170. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-list-contains/expected.arrow +0 -0
  171. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-list-contains/filter.arrow +0 -0
  172. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-list-contains/input.arrow +0 -0
  173. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-starts-with/expected.arrow +0 -0
  174. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-starts-with/filter.arrow +0 -0
  175. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-starts-with/input.arrow +0 -0
  176. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/in-empty/expected.arrow +0 -0
  177. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/in-empty/filter.arrow +0 -0
  178. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/in-empty/input.arrow +0 -0
  179. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/in-empty/worker-expected.arrow +0 -0
  180. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/in-with-null/expected.arrow +0 -0
  181. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/in-with-null/filter.arrow +0 -0
  182. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/in-with-null/input.arrow +0 -0
  183. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/in-with-null/worker-expected.arrow +0 -0
  184. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/is-not-null/expected.arrow +0 -0
  185. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/is-not-null/filter.arrow +0 -0
  186. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/is-not-null/input.arrow +0 -0
  187. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/is-not-null/worker-expected.arrow +0 -0
  188. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/is-null/expected.arrow +0 -0
  189. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/is-null/filter.arrow +0 -0
  190. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/is-null/input.arrow +0 -0
  191. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/is-null/worker-expected.arrow +0 -0
  192. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/kleene-and/expected.arrow +0 -0
  193. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/kleene-and/filter.arrow +0 -0
  194. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/kleene-and/input.arrow +0 -0
  195. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/kleene-not/expected.arrow +0 -0
  196. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/kleene-not/filter.arrow +0 -0
  197. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/kleene-not/input.arrow +0 -0
  198. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/kleene-or/expected.arrow +0 -0
  199. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/kleene-or/filter.arrow +0 -0
  200. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/kleene-or/input.arrow +0 -0
  201. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/nan-comparison/expected.arrow +0 -0
  202. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/nan-comparison/filter.arrow +0 -0
  203. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/nan-comparison/input.arrow +0 -0
  204. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/negative-zero-membership/expected.arrow +0 -0
  205. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/negative-zero-membership/filter.arrow +0 -0
  206. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/negative-zero-membership/input.arrow +0 -0
  207. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/nested-null-propagation/expected.arrow +0 -0
  208. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/nested-null-propagation/filter.arrow +0 -0
  209. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/nested-null-propagation/input.arrow +0 -0
  210. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/not-in-empty/expected.arrow +0 -0
  211. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/not-in-empty/filter.arrow +0 -0
  212. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/not-in-empty/input.arrow +0 -0
  213. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/not-in-empty/worker-expected.arrow +0 -0
  214. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/not-in-with-null/expected.arrow +0 -0
  215. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/not-in-with-null/filter.arrow +0 -0
  216. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/not-in-with-null/input.arrow +0 -0
  217. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/not-in-with-null/worker-expected.arrow +0 -0
  218. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/session-integer-division/expected.arrow +0 -0
  219. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/session-integer-division/filter.arrow +0 -0
  220. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/session-integer-division/input.arrow +0 -0
  221. {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime-manifest.json +0 -0
  222. {vgi_python-0.31.4 → vgi_python-0.32.0}/dist-vgi/.gitignore +0 -0
  223. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/aggregate-functions.md +0 -0
  224. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/arguments.md +0 -0
  225. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/auth.md +0 -0
  226. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/catalogs.md +0 -0
  227. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/client.md +0 -0
  228. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/exceptions.md +0 -0
  229. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/filters.md +0 -0
  230. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/functions.md +0 -0
  231. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/http.md +0 -0
  232. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/index.md +0 -0
  233. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/metadata.md +0 -0
  234. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/observability.md +0 -0
  235. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/storage.md +0 -0
  236. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/transactor.md +0 -0
  237. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/worker.md +0 -0
  238. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/argument-serialization.md +0 -0
  239. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/apple-touch-icon.png +0 -0
  240. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/favicon-16x16.png +0 -0
  241. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/favicon-32x32.png +0 -0
  242. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/favicon.ico +0 -0
  243. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/kinds/aggregate.svg +0 -0
  244. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/kinds/buffering.svg +0 -0
  245. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/kinds/scalar.svg +0 -0
  246. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/kinds/table-in-out.svg +0 -0
  247. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/kinds/table.svg +0 -0
  248. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/logo.png +0 -0
  249. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/social-card.png +0 -0
  250. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/authentication.md +0 -0
  251. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/catalog-interface.md +0 -0
  252. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/cli.md +0 -0
  253. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/column-statistics.md +0 -0
  254. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/concepts/index.md +0 -0
  255. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/contributing-docs.md +0 -0
  256. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/filter-pushdown.md +0 -0
  257. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/generator-api.md +0 -0
  258. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/global-functions.md +0 -0
  259. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/how-to/catalogs.md +0 -0
  260. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/how-to/function-patterns.md +0 -0
  261. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/how-to/http-auth.md +0 -0
  262. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/how-to/index.md +0 -0
  263. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/how-to/iroh.md +0 -0
  264. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/how-to/pushdown-and-statistics.md +0 -0
  265. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/how-to/state-storage.md +0 -0
  266. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/how-to/tailnet.md +0 -0
  267. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/index.md +0 -0
  268. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/lifecycle.md +0 -0
  269. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/metadata.md +0 -0
  270. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/overrides/main.html +0 -0
  271. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/protocol/index.md +0 -0
  272. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/protocol/vgi-duckdb-filter-adapter.md +0 -0
  273. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/protocol/vgi-filter-encoding-v2-spec.md +0 -0
  274. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/protocol/vgi-runtime-filter-artifacts.md +0 -0
  275. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/robots.txt +0 -0
  276. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/shared-storage.md +0 -0
  277. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/stylesheets/extra.css +0 -0
  278. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/tutorial/index.md +0 -0
  279. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/tutorial/scalar.md +0 -0
  280. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/tutorial/table.md +0 -0
  281. {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/vgi-logo.png +0 -0
  282. {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/batch_index_worker.py +0 -0
  283. {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/cache_worker.py +0 -0
  284. {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/calc_scalar_worker.py +0 -0
  285. {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/calc_worker.py +0 -0
  286. {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/copy_format_worker.py +0 -0
  287. {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/filter_worker.py +0 -0
  288. {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/greeting_scalar_worker.py +0 -0
  289. {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/row_count_worker.py +0 -0
  290. {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/series_streaming_worker.py +0 -0
  291. {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/sum_worker.py +0 -0
  292. {vgi_python-0.31.4 → vgi_python-0.32.0}/mkdocs.yml +0 -0
  293. {vgi_python-0.31.4 → vgi_python-0.32.0}/packages/vgi-fixtures/LICENSE +0 -0
  294. {vgi_python-0.31.4 → vgi_python-0.32.0}/packages/vgi-fixtures/README.md +0 -0
  295. {vgi_python-0.31.4 → vgi_python-0.32.0}/packages/vgi-fixtures/docker/Dockerfile +0 -0
  296. {vgi_python-0.31.4 → vgi_python-0.32.0}/packages/vgi-fixtures/docker/docker-entrypoint.sh +0 -0
  297. {vgi_python-0.31.4 → vgi_python-0.32.0}/packages/vgi-fixtures/pyproject.toml +0 -0
  298. {vgi_python-0.31.4 → vgi_python-0.32.0}/scripts/measure_startup.py +0 -0
  299. {vgi_python-0.31.4 → vgi_python-0.32.0}/scripts/run_all_tests.sh +0 -0
  300. {vgi_python-0.31.4 → vgi_python-0.32.0}/test-data/generate.sh +0 -0
  301. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/__init__.py +0 -0
  302. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/_http_fixtures.py +0 -0
  303. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/__init__.py +0 -0
  304. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_attach_option.py +0 -0
  305. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_catalog_interface.py +0 -0
  306. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_client_catalog.py +0 -0
  307. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_column_statistics.py +0 -0
  308. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_declarative.py +0 -0
  309. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_example_worker_catalog.py +0 -0
  310. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_integration.py +0 -0
  311. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_required_filters.py +0 -0
  312. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_scan_branches.py +0 -0
  313. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_serialization.py +0 -0
  314. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_setting.py +0 -0
  315. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_storage.py +0 -0
  316. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_time_travel.py +0 -0
  317. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/__init__.py +0 -0
  318. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_aggregate_client.py +0 -0
  319. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_batch_metadata_callback.py +0 -0
  320. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_bind_and_join_keys.py +0 -0
  321. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_broken_pipe.py +0 -0
  322. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_cli.py +0 -0
  323. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_cli_catalog_functions.py +0 -0
  324. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_copy_client.py +0 -0
  325. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_http_response_budget.py +0 -0
  326. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_iroh_client.py +0 -0
  327. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_scan_branches_client.py +0 -0
  328. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_split_client.py +0 -0
  329. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_stop_force.py +0 -0
  330. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_table_column_statistics.py +0 -0
  331. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_time_travel_client.py +0 -0
  332. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_worker_debug.py +0 -0
  333. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/__init__.py +0 -0
  334. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/_stub.py +0 -0
  335. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/conftest.py +0 -0
  336. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_accumulate.py +0 -0
  337. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_aggregate.py +0 -0
  338. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_attach.py +0 -0
  339. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_bearer_auth.py +0 -0
  340. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_const_param_enforcement.py +0 -0
  341. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_container.py +0 -0
  342. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_copy_from.py +0 -0
  343. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_copy_to.py +0 -0
  344. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_directory_parity.py +0 -0
  345. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_function_inventory.py +0 -0
  346. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_github.py +0 -0
  347. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_http_client.py +0 -0
  348. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_http_external_location.py +0 -0
  349. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_http_upload_url.py +0 -0
  350. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_macro.py +0 -0
  351. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_overload.py +0 -0
  352. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_protocol_inventory.py +0 -0
  353. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_protocol_version.py +0 -0
  354. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_resumable_scan.py +0 -0
  355. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_scalar.py +0 -0
  356. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_scalar_attach_opaque_data.py +0 -0
  357. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_secret.py +0 -0
  358. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_settings.py +0 -0
  359. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_splits.py +0 -0
  360. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_table.py +0 -0
  361. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_table_in_out.py +0 -0
  362. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_view.py +0 -0
  363. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_writable.py +0 -0
  364. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conftest.py +0 -0
  365. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/anchor_len_overrun.bin +0 -0
  366. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/bad_fingerprint.bin +0 -0
  367. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/bad_flags_unsealed_but_key_present.bin +0 -0
  368. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/bad_version.bin +0 -0
  369. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/generate.py +0 -0
  370. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/manifest.json +0 -0
  371. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/reserved_flag_bit.bin +0 -0
  372. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/stale_anchor.bin +0 -0
  373. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/truncated.bin +0 -0
  374. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/valid_sealed.bin +0 -0
  375. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/valid_unsealed.bin +0 -0
  376. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/__init__.py +0 -0
  377. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/test_bernoulli_function.py +0 -0
  378. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/test_binary_packet_function.py +0 -0
  379. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/test_client.py +0 -0
  380. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/test_conditional_message_function.py +0 -0
  381. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/test_hash_seed_function.py +0 -0
  382. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/test_multiply_by_setting_function.py +0 -0
  383. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/test_multiply_function.py +0 -0
  384. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/test_random_bytes_function.py +0 -0
  385. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/test_return_secret_value_function.py +0 -0
  386. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/__init__.py +0 -0
  387. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/__init__.py +0 -0
  388. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_constant_columns_function.py +0 -0
  389. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_double_sequence_function.py +0 -0
  390. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_exception_function.py +0 -0
  391. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_filter_echo_function.py +0 -0
  392. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_logging_function.py +0 -0
  393. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_nested_sequence_function.py +0 -0
  394. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_partitioned_function.py +0 -0
  395. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_projected_data_function.py +0 -0
  396. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_sequence_function.py +0 -0
  397. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_settings_function.py +0 -0
  398. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_struct_settings_function.py +0 -0
  399. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_ten_thousand_function.py +0 -0
  400. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/test_wide_columns.py +0 -0
  401. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/__init__.py +0 -0
  402. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/generator/__init__.py +0 -0
  403. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/generator/test_buffer_input_function.py +0 -0
  404. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/generator/test_echo_function.py +0 -0
  405. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/generator/test_exception_functions.py +0 -0
  406. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/generator/test_filter_by_setting_function.py +0 -0
  407. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/generator/test_repeat_inputs_function.py +0 -0
  408. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/generator/test_substream_partial_sum_function.py +0 -0
  409. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/generator/test_sum_all_columns_function.py +0 -0
  410. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/test_blended_exchange.py +0 -0
  411. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/test_blended_metadata.py +0 -0
  412. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/test_client.py +0 -0
  413. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/tailnet/Dockerfile +0 -0
  414. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/tailnet/__init__.py +0 -0
  415. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/tailnet/compose.yaml +0 -0
  416. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/tailnet/probe.py +0 -0
  417. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/tailnet/run.sh +0 -0
  418. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/tailnet/test_worker.py +0 -0
  419. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/tailnet/worker.py +0 -0
  420. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_access_log_audit.py +0 -0
  421. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_aggregate_function.py +0 -0
  422. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_argument_spec.py +0 -0
  423. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_auth.py +0 -0
  424. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_bind_exceptions.py +0 -0
  425. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_bind_request_at_clause.py +0 -0
  426. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_bound_storage_conformance.py +0 -0
  427. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_cache_control.py +0 -0
  428. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_call_state_attach.py +0 -0
  429. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_catalog_auth_binding.py +0 -0
  430. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_client_oauth.py +0 -0
  431. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_codegen_request_inventory.py +0 -0
  432. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_copy_from_function.py +0 -0
  433. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_copy_to_function.py +0 -0
  434. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_docstrings.py +0 -0
  435. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_documentation_examples.py +0 -0
  436. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_example_function_arg_types.py +0 -0
  437. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_examples_workers.py +0 -0
  438. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_exception_handling.py +0 -0
  439. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_exceptions.py +0 -0
  440. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_filter_pushdown.py +0 -0
  441. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_filter_pushdown_extension.py +0 -0
  442. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_filter_v2.py +0 -0
  443. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_filter_v2_builder.py +0 -0
  444. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_filter_v2_runtime_corpus.py +0 -0
  445. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_filter_v2_spec_schema.py +0 -0
  446. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_fixture_catalog_parity.py +0 -0
  447. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_function_shape_mismatch.py +0 -0
  448. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_function_storage.py +0 -0
  449. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_function_storage_azure_sql.py +0 -0
  450. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_function_storage_cf_do.py +0 -0
  451. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_function_storage_cf_do_integration.py +0 -0
  452. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_function_storage_conformance.py +0 -0
  453. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_cpp_constants.py +0 -0
  454. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_cpp_protocol_version.py +0 -0
  455. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_cpp_request_builders.py +0 -0
  456. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_cpp_schemas.py +0 -0
  457. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_cpp_secret.py +0 -0
  458. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_go_schemas.py +0 -0
  459. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_java_schemas.py +0 -0
  460. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_protocol_version.py +0 -0
  461. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_rust_request_builders.py +0 -0
  462. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_rust_schemas.py +0 -0
  463. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_schemas_cross_lang.py +0 -0
  464. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_ts_client.py +0 -0
  465. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_ts_schemas.py +0 -0
  466. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_http_demo_storage.py +0 -0
  467. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_http_s3_offload_input.py +0 -0
  468. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_http_s3_offload_output.py +0 -0
  469. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_launch_transport.py +0 -0
  470. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_metadata.py +0 -0
  471. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_mypy_consolidated.py +0 -0
  472. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_nest_tensor.py +0 -0
  473. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_otel.py +0 -0
  474. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_projection_enforcement.py +0 -0
  475. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_projection_repro.py +0 -0
  476. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_protocol_classes.py +0 -0
  477. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_resolved_secrets.py +0 -0
  478. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_schema_paths_v2.py +0 -0
  479. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_schema_scoped_functions.py +0 -0
  480. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_schema_utils.py +0 -0
  481. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_serve.py +0 -0
  482. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_setting_secret_annotations.py +0 -0
  483. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_signing_key.py +0 -0
  484. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_split_token.py +0 -0
  485. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_table_buffering_function.py +0 -0
  486. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_table_function_dynamic_to_string.py +0 -0
  487. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_tcp_transport.py +0 -0
  488. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_type_bounds.py +0 -0
  489. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_union_argument.py +0 -0
  490. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_wire_record_schema_parity.py +0 -0
  491. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_worker.py +0 -0
  492. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_worker_cli.py +0 -0
  493. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_worker_page.py +0 -0
  494. {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/transactor/__init__.py +0 -0
  495. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_duckdb.py +0 -0
  496. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_storage_profile.py +0 -0
  497. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/__init__.py +0 -0
  498. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/accumulate/__init__.py +0 -0
  499. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/accumulate/worker.py +0 -0
  500. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/__init__.py +0 -0
  501. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/_common.py +0 -0
  502. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/basic.py +0 -0
  503. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/dynamic.py +0 -0
  504. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/generic.py +0 -0
  505. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/listagg.py +0 -0
  506. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/percentile.py +0 -0
  507. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/same_name.py +0 -0
  508. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/secret_typed.py +0 -0
  509. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/streaming.py +0 -0
  510. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/varargs.py +0 -0
  511. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/window.py +0 -0
  512. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/attach_options.py +0 -0
  513. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/bad_enum.py +0 -0
  514. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/bad_protocol.py +0 -0
  515. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/cancellable.py +0 -0
  516. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/catalog.py +0 -0
  517. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/companion.py +0 -0
  518. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/copy_from.py +0 -0
  519. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/copy_to.py +0 -0
  520. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/global_functions.py +0 -0
  521. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/http_server.py +0 -0
  522. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/narrow_bind/__init__.py +0 -0
  523. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/narrow_bind/worker.py +0 -0
  524. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/nest_tensor.py +0 -0
  525. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/orchard_catalog.py +0 -0
  526. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/projection_repro/__init__.py +0 -0
  527. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/projection_repro/worker.py +0 -0
  528. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/__init__.py +0 -0
  529. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/_common.py +0 -0
  530. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/arithmetic.py +0 -0
  531. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/bench_ladder.py +0 -0
  532. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/binary.py +0 -0
  533. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/formatting.py +0 -0
  534. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/geo.py +0 -0
  535. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/null_handling.py +0 -0
  536. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/random_demo.py +0 -0
  537. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/same_name.py +0 -0
  538. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/settings_secrets.py +0 -0
  539. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/type_info.py +0 -0
  540. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/schema_reconcile/__init__.py +0 -0
  541. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/__init__.py +0 -0
  542. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/_common.py +0 -0
  543. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/batch_index.py +0 -0
  544. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/batch_index_broken.py +0 -0
  545. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/cache.py +0 -0
  546. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/catalog_scans.py +0 -0
  547. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/filters.py +0 -0
  548. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/late_materialization.py +0 -0
  549. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/make_series.py +0 -0
  550. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/misc.py +0 -0
  551. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/order_modes.py +0 -0
  552. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/pairs.py +0 -0
  553. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/partition_columns.py +0 -0
  554. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/partition_columns_broken.py +0 -0
  555. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/profiling_example.py +0 -0
  556. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/required_filters.py +0 -0
  557. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/same_name_cached.py +0 -0
  558. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/same_name_schemas.py +0 -0
  559. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/sequence.py +0 -0
  560. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/settings.py +0 -0
  561. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/splits.py +0 -0
  562. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/transaction_storage.py +0 -0
  563. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/tt_pushdown.py +0 -0
  564. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/typed_probe.py +0 -0
  565. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/versioned.py +0 -0
  566. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/wide.py +0 -0
  567. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table_in_out.py +0 -0
  568. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table_in_out_same_name.py +0 -0
  569. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/twin_catalogs.py +0 -0
  570. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/versioned.py +0 -0
  571. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/versioned_tables.py +0 -0
  572. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/worker.py +0 -0
  573. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/writable/__init__.py +0 -0
  574. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/aggregate_function.py +0 -0
  575. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/argument_spec.py +0 -0
  576. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/arguments.py +0 -0
  577. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/attach_header.py +0 -0
  578. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/auth.py +0 -0
  579. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/cache_control.py +0 -0
  580. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/catalog/_descriptor_spec.py +0 -0
  581. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/catalog/attach_option.py +0 -0
  582. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/catalog/duckdb_statistics.py +0 -0
  583. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/catalog/secret_type.py +0 -0
  584. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/catalog/setting.py +0 -0
  585. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/catalog/storage.py +0 -0
  586. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/__init__.py +0 -0
  587. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/aggregate.py +0 -0
  588. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/catalog_mixin.py +0 -0
  589. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/cli.py +0 -0
  590. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/cli_catalog.py +0 -0
  591. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/cli_schema.py +0 -0
  592. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/cli_table.py +0 -0
  593. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/cli_transaction.py +0 -0
  594. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/cli_utils.py +0 -0
  595. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/cli_view.py +0 -0
  596. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/client.py +0 -0
  597. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/errors.py +0 -0
  598. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/__init__.py +0 -0
  599. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/_common.py +0 -0
  600. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/cpp_constants.py +0 -0
  601. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/cpp_protocol_version.py +0 -0
  602. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/cpp_request_builders.py +0 -0
  603. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/cpp_schemas.py +0 -0
  604. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/cpp_secret_protocol_version.py +0 -0
  605. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/cpp_secret_request_builders.py +0 -0
  606. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/cpp_secret_schemas.py +0 -0
  607. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/go_schemas.py +0 -0
  608. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/java_schemas.py +0 -0
  609. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/protocol_version.py +0 -0
  610. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/rust_request_builders.py +0 -0
  611. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/rust_schemas.py +0 -0
  612. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/ts_client.py +0 -0
  613. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/ts_schemas.py +0 -0
  614. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/copy_from_function.py +0 -0
  615. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/copy_to_function.py +0 -0
  616. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/exceptions.py +0 -0
  617. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/filter_v2.py +0 -0
  618. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/filter_v2_builder.py +0 -0
  619. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/function.py +0 -0
  620. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/function_storage.py +0 -0
  621. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/function_storage_azure_sql.py +0 -0
  622. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/function_storage_cf_do.py +0 -0
  623. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/http/__init__.py +0 -0
  624. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/http/demo_storage.py +0 -0
  625. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/http/landing.html +0 -0
  626. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/http/landing_page.py +0 -0
  627. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/http/worker_page.py +0 -0
  628. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/invocation.py +0 -0
  629. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/logging_config.py +0 -0
  630. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/meta_worker.py +0 -0
  631. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/metadata.py +0 -0
  632. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/otel.py +0 -0
  633. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/profiling.py +0 -0
  634. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/protocol.py +0 -0
  635. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/protocol_version.txt +0 -0
  636. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/py.typed +0 -0
  637. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/scalar_function.py +0 -0
  638. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/schema_path.py +0 -0
  639. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/schema_utils.py +0 -0
  640. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/secret_protocol.py +0 -0
  641. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/secret_service.py +0 -0
  642. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/serve.py +0 -0
  643. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/split_token.py +0 -0
  644. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/table_buffering_function.py +0 -0
  645. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/table_filter_pushdown.py +0 -0
  646. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/table_function.py +0 -0
  647. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/table_in_out_function.py +0 -0
  648. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/transactor/__init__.py +0 -0
  649. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/transactor/_duckdb_compat.py +0 -0
  650. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/transactor/client.py +0 -0
  651. {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/worker.py +0 -0
  652. {vgi_python-0.31.4 → vgi_python-0.32.0}/wrangler.jsonc +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: vgi-python
3
- Version: 0.31.4
3
+ Version: 0.32.0
4
4
  Summary: Vector Gateway Interface - Connect DuckDB to external programs via Apache Arrow
5
5
  Project-URL: Homepage, https://query.farm
6
6
  Project-URL: Repository, https://github.com/Query-farm/vgi-python
@@ -453,7 +453,34 @@ Triggers are different. Supporting a trigger in a virtual catalog would require
453
453
 
454
454
  The same principle applies to secure views, composable COPY, remote-plan pushdown, coordinate systems, and any catalog object VGI does not currently virtualize: they are not protocol requirements simply because DuckDB implements them. They should be gated through explicit catalog capabilities and fail early.
455
455
 
456
- ### 6.1 New catalog kinds in DuckDB 2.0
456
+ ### 6.1 Writable result modes and OLD/NEW images
457
+
458
+ VGI 2.0 replaces the four `TableInfo` booleans `supports_insert`,
459
+ `supports_update`, `supports_delete`, and `supports_returning` with one required,
460
+ non-null Arrow map:
461
+
462
+ ```text
463
+ write_result_modes: map<utf8, utf8>
464
+ ```
465
+
466
+ The only operation keys are `insert`, `update`, and `delete`; absence means the
467
+ operation is unsupported. Each value is the maximum supported mode in the
468
+ ordered lattice `count < rows < changes`, and therefore promises every lower
469
+ mode. Duplicate keys and unknown operations or modes are protocol errors.
470
+
471
+ The serialized `write_options` batch replaces `return_chunks: bool` with the
472
+ required `result_mode: utf8`. `count` returns `(count int64 not null)`. `rows`
473
+ returns NEW rows for INSERT/UPDATE and OLD rows for DELETE. `changes` returns
474
+ two nullable structs, `old` and `new`, each shaped exactly like the table:
475
+ INSERT populates only `new`, DELETE only `old`, and UPDATE both. The operation
476
+ is known from the invoked write function and is not repeated in each result row.
477
+
478
+ The DuckDB 1.5 adapter requests `count` for ordinary DML and `rows` for DML with
479
+ RETURNING. It validates and preserves `changes` capability metadata but never
480
+ requests that mode. A DuckDB 2.0 adapter can request `changes` when trigger
481
+ planning needs OLD/NEW images without another protocol revision.
482
+
483
+ ### 6.2 New catalog kinds in DuckDB 2.0
457
484
 
458
485
  The `CatalogType` enum has exactly two additions relative to DuckDB 1.5.5:
459
486
 
@@ -464,7 +491,7 @@ The `CatalogType` enum has exactly two additions relative to DuckDB 1.5.5:
464
491
 
465
492
  Nested schemas are recursively contained `SCHEMA_ENTRY` objects, not another kind. Secure views remain `VIEW_ENTRY`; changes to aggregate-state representation belong to the logical type system rather than the catalog enum.
466
493
 
467
- ### 6.2 How native DuckDB stores triggers
494
+ ### 6.3 How native DuckDB stores triggers
468
495
 
469
496
  Triggers are first-class `TriggerCatalogEntry` objects, but they do not live in the schema's ordinary catalog set. Each `DuckTableEntry` owns a separate transactional `CatalogSet`:
470
497
 
@@ -496,7 +523,7 @@ The dependency manager has special trigger identity/lookup handling because sche
496
523
 
497
524
  At bind time DuckDB scans the table's triggers and expands them into the DML plan. Statement triggers form a materialized CTE chain (BEFORE actions, base DML, AFTER actions), including materialized OLD/NEW transition tables when requested. Supported row triggers use `LogicalTrigger` and correlated `NEW.col`/`OLD.col` bindings. The current catalog set yields triggers in case-insensitive alphabetical name order.
498
525
 
499
- ### 6.3 DuckDB changes needed by custom table implementations
526
+ ### 6.4 DuckDB changes needed by custom table implementations
500
527
 
501
528
  DuckDB 2.0 already exposes virtual `TableCatalogEntry::CreateTrigger`, `ScanTriggers`, and `GetTrigger` hooks, and its trigger binder consumes the generic scan hook. Two remaining native-table assumptions should be fixed upstream:
502
529
 
@@ -509,7 +536,7 @@ Upstream PR: [duckdb/duckdb#25539 — Support triggers on custom table catalog e
509
536
 
510
537
  The `ScanTriggers` contract also implies that returned catalog entries remain alive beyond the callback: both trigger selection and introspection retain references. VGI should materialize trigger entries in a table-owned metadata cache, invalidated through the existing catalog-version mechanism, rather than returning callback-local objects.
511
538
 
512
- ### 6.4 Proposed VGI trigger protocol
539
+ ### 6.5 Proposed VGI trigger protocol
513
540
 
514
541
  The remote VGI catalog should be authoritative for persistent trigger definitions. Keeping definitions only in a local extension cache would lose them on detach and would give different clients inconsistent catalogs.
515
542
 
@@ -529,13 +556,22 @@ TriggerInfo
529
556
  for_each: statement | row
530
557
  referencing_new_table: optional<string>
531
558
  referencing_old_table: optional<string>
532
- action_sql: string
559
+ definitions: map<string, string>
533
560
  dependencies: list<TriggerDependency>
534
561
  comment: optional<string>
535
562
  tags: map<string, string>
536
563
  ```
537
564
 
538
- Use structured fields plus DuckDB-dialect action SQL. Do not put DuckDB's binary `QueryNode` serialization on the VGI wire: it is an internal, version-coupled representation. The local extension can parse the action and create cached `TriggerCatalogEntry` objects. Each resolved dependency should carry its qualified object reference plus ownership, drop-blocking, and alter-blocking flags so the remote catalog can enforce DDL integrity across clients.
565
+ Use structured fields plus engine-specific textual definitions keyed by stable
566
+ lowercase engine identifiers such as `duckdb`, `datafusion`, `spark`, and
567
+ `sqlite`. An engine executes only its matching definition; a missing entry means
568
+ that trigger is unavailable on that engine, with no implicit SQL-dialect
569
+ fallback. Do not put DuckDB's binary `QueryNode` serialization on the VGI wire:
570
+ it is an internal, version-coupled representation. The DuckDB extension parses
571
+ the `duckdb` definition and creates cached `TriggerCatalogEntry` objects. Each
572
+ resolved dependency should carry its qualified object reference plus ownership,
573
+ drop-blocking, and alter-blocking flags so the remote catalog can enforce DDL
574
+ integrity across clients.
539
575
 
540
576
  Suggested methods:
541
577
 
@@ -545,7 +581,10 @@ Suggested methods:
545
581
  - `catalog_table_trigger_drop`
546
582
  - optional trigger comment/tag alteration
547
583
 
548
- Add explicit catalog/table capability metadata such as `supports_triggers`. A trigger-capable table must also support exact affected-row RETURNING, because DuckDB's statement-trigger expansion internally materializes base DML with `RETURNING *` even when the user did not write a RETURNING clause. UPDATE must additionally expose captured OLD columns before OLD transition tables can be enabled.
584
+ Add explicit catalog/table capability metadata such as `supports_triggers`. A
585
+ DuckDB-managed trigger-capable table must advertise `changes` for every event it
586
+ uses, because DuckDB's statement-trigger expansion needs exact OLD/NEW images
587
+ even when the user did not write a RETURNING clause.
549
588
 
550
589
  All base and trigger-body writes must use the same VGI transaction token and roll back atomically. Stable statement/sub-operation identifiers are recommended so transport retries cannot apply a trigger side effect twice. Trigger support should be rejected when the VGI catalog cannot provide transactional atomicity.
551
590
 
@@ -673,4 +712,11 @@ The first protocol-breaking phase is now implemented in Python:
673
712
 
674
713
  `CatalogAttachResult.default_schema` intentionally remains a scalar root-schema identifier for the reason described in section 2.
675
714
 
676
- This phase does **not** implement the other proposed protocol areas: `vgi.filters.v2`, logical-type identity annotations, trigger RPCs, or standalone window-function catalog entries. The sibling C++, C#, Go, Java, Rust, and TypeScript schema-path migrations were completed afterward. The vendored browser `vgi-client.js` remains generated from the TypeScript SDK and must never be edited manually in the Python repository.
715
+ The writable-result phase replaces the legacy write booleans and
716
+ `return_chunks` option with the `write_result_modes`/`result_mode` contract from
717
+ section 6.1. Python implements and directly tests all three modes. The DuckDB
718
+ 1.5 extension consumes only `count` and `rows`; `changes` is reserved for the
719
+ future DuckDB 2.0 trigger adapter. Trigger catalog metadata and RPCs remain
720
+ unimplemented.
721
+
722
+ This phase does **not** implement the other proposed protocol areas: logical-type identity annotations, trigger RPCs, or standalone window-function catalog entries. The sibling C++, C#, Go, Java, Rust, and TypeScript schema migrations are maintained in their corresponding repositories. The vendored browser `vgi-client.js` remains generated from the TypeScript SDK and must never be edited manually in the Python repository.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "vgi-python"
3
- version = "0.31.4"
3
+ version = "0.32.0"
4
4
  description = "Vector Gateway Interface - Connect DuckDB to external programs via Apache Arrow"
5
5
  readme = "README.md"
6
6
  keywords = [
@@ -129,11 +129,11 @@ class TestTableDescriptorWriteFields:
129
129
  )
130
130
 
131
131
 
132
- class TestTableInfoWriteFlags:
133
- """TableInfo serialization includes write support flags."""
132
+ class TestTableInfoWriteResultModes:
133
+ """TableInfo serializes per-operation maximum result modes."""
134
134
 
135
- def test_write_flags_set_when_functions_present(self) -> None:
136
- """Write flags are True when corresponding functions are set."""
135
+ def test_count_modes_inferred_when_functions_present(self) -> None:
136
+ """Configured functions default to the count result mode."""
137
137
  table = Table(
138
138
  name="t",
139
139
  function=WritableTableScan,
@@ -142,35 +142,63 @@ class TestTableInfoWriteFlags:
142
142
  delete_function=WritableTableDelete,
143
143
  )
144
144
  info = table.to_table_info(["main"])
145
- assert info.supports_insert is True
146
- assert info.supports_update is True
147
- assert info.supports_delete is True
145
+ assert info.write_result_modes == {"insert": "count", "update": "count", "delete": "count"}
148
146
 
149
- def test_write_flags_false_by_default(self) -> None:
150
- """Write flags are False when no write functions are set."""
147
+ def test_read_only_table_has_empty_modes(self) -> None:
148
+ """An empty map describes a read-only table."""
151
149
  table = Table(
152
150
  name="t",
153
151
  function=WritableTableScan,
154
152
  )
155
153
  info = table.to_table_info(["main"])
156
- assert info.supports_insert is False
157
- assert info.supports_update is False
158
- assert info.supports_delete is False
154
+ assert info.write_result_modes == {}
159
155
 
160
- def test_partial_write_flags(self) -> None:
161
- """Only the flags for defined write functions are True."""
156
+ def test_partial_write_modes(self) -> None:
157
+ """Only operations with functions appear in the map."""
162
158
  table = Table(
163
159
  name="t",
164
160
  function=WritableTableScan,
165
161
  insert_function=WritableTableInsert,
166
162
  )
167
163
  info = table.to_table_info(["main"])
168
- assert info.supports_insert is True
169
- assert info.supports_update is False
170
- assert info.supports_delete is False
164
+ assert info.write_result_modes == {"insert": "count"}
165
+
166
+ def test_explicit_maximum_modes(self) -> None:
167
+ """Authors can opt each configured operation into rows or changes."""
168
+ table = Table(
169
+ name="t",
170
+ function=WritableTableScan,
171
+ insert_function=WritableTableInsert,
172
+ update_function=WritableTableUpdate,
173
+ write_result_modes={"insert": "rows", "update": "changes"},
174
+ )
175
+ assert table.to_table_info(["main"]).write_result_modes == {
176
+ "insert": "rows",
177
+ "update": "changes",
178
+ }
179
+
180
+ @pytest.mark.parametrize("modes", [{"merge": "count"}, {"insert": "invalid"}])
181
+ def test_invalid_modes_rejected(self, modes: dict[str, str]) -> None:
182
+ """Unknown operations and modes fail at descriptor construction."""
183
+ with pytest.raises(ValueError):
184
+ Table(
185
+ name="t",
186
+ columns=pa.schema([("id", pa.int64())]),
187
+ insert_function=WritableTableInsert,
188
+ write_result_modes=modes,
189
+ )
190
+
191
+ def test_mode_without_function_rejected(self) -> None:
192
+ """Capability metadata cannot claim a missing implementation."""
193
+ with pytest.raises(ValueError, match="without a corresponding update_function"):
194
+ Table(
195
+ name="t",
196
+ columns=pa.schema([("id", pa.int64())]),
197
+ write_result_modes={"update": "rows"},
198
+ )
171
199
 
172
200
  def test_table_info_serialization_roundtrip(self) -> None:
173
- """Write flags survive Arrow serialization roundtrip."""
201
+ """Write modes survive Arrow serialization roundtrip."""
174
202
  table = Table(
175
203
  name="t",
176
204
  function=WritableTableScan,
@@ -181,9 +209,7 @@ class TestTableInfoWriteFlags:
181
209
  info = table.to_table_info(["main"])
182
210
  data = info.serialize_to_bytes()
183
211
  restored = TableInfo.deserialize_from_bytes(data)
184
- assert restored.supports_insert is True
185
- assert restored.supports_update is True
186
- assert restored.supports_delete is True
212
+ assert restored.write_result_modes == {"insert": "count", "update": "count", "delete": "count"}
187
213
 
188
214
 
189
215
  class TestReadOnlyCatalogInterfaceWriteMethods:
@@ -0,0 +1,50 @@
1
+ # Copyright 2025, 2026 Query Farm LLC - https://query.farm
2
+
3
+ """Tests for the VGI 2.0 writable result-mode contract."""
4
+
5
+ import pyarrow as pa
6
+ import pytest
7
+
8
+ from vgi.schema_utils import schema
9
+ from vgi.write_results import supports_write_result_mode, write_changes_batch, write_result_schema
10
+
11
+
12
+ def test_ordered_result_modes() -> None:
13
+ """A maximum mode promises itself and every lower mode."""
14
+ assert supports_write_result_mode("count", "count")
15
+ assert not supports_write_result_mode("count", "rows")
16
+ assert supports_write_result_mode("rows", "count")
17
+ assert supports_write_result_mode("changes", "rows")
18
+ assert supports_write_result_mode("changes", "changes")
19
+
20
+
21
+ def test_result_schemas() -> None:
22
+ """Every mode has the exact canonical Arrow schema."""
23
+ table = schema(id=pa.int64(), name=pa.string())
24
+ assert write_result_schema("count", table) == pa.schema([pa.field("count", pa.int64(), nullable=False)])
25
+ assert write_result_schema("rows", table) == table
26
+ changes = write_result_schema("changes", table)
27
+ assert changes.names == ["old", "new"]
28
+ assert changes.field("old").nullable
29
+ assert changes.field("old").type == pa.struct(list(table))
30
+
31
+
32
+ @pytest.mark.parametrize(
33
+ ("old", "new"),
34
+ [
35
+ (None, {"id": 1, "name": "inserted"}),
36
+ ({"id": 1, "name": "old"}, {"id": 1, "name": "new"}),
37
+ ({"id": 1, "name": "deleted"}, None),
38
+ ],
39
+ )
40
+ def test_change_images(old: dict[str, object] | None, new: dict[str, object] | None) -> None:
41
+ """INSERT, UPDATE, and DELETE preserve the required OLD/NEW nullability."""
42
+ table = schema(id=pa.int64(), name=pa.string())
43
+ batch = write_changes_batch(table, [old], [new])
44
+ assert batch.to_pylist() == [{"old": old, "new": new}]
45
+
46
+
47
+ def test_change_image_lengths_must_match() -> None:
48
+ """Every output row must contain one OLD/NEW pair."""
49
+ with pytest.raises(ValueError, match="equal length"):
50
+ write_changes_batch(pa.schema([("id", pa.int64())]), [], [{"id": 1}])
@@ -24,7 +24,7 @@ pytestmark = pytest.mark.skip(reason="Transactor/write subsystem disabled — se
24
24
  # Helpers
25
25
  # ============================================================================
26
26
 
27
- _COUNT_SCHEMA = schema(count=pa.int64())
27
+ _COUNT_SCHEMA = pa.schema([pa.field("count", pa.int64(), nullable=False)])
28
28
  _FILTER_METADATA = {b"vgi_filter_version": b"1"}
29
29
 
30
30
 
@@ -66,7 +66,7 @@ def _insert_into(
66
66
  t: TransactorImpl, tx_id: bytes, table_name: str, rows: list[tuple[int, str]], *, returning: bool = False
67
67
  ) -> pa.RecordBatch:
68
68
  """Insert rows into an arbitrary table and return the response batch."""
69
- stream = t.insert(tx_id=tx_id, table_name=table_name, returning=returning)
69
+ stream = t.insert(tx_id=tx_id, table_name=table_name, result_mode="rows" if returning else "count")
70
70
  batch = pa.record_batch(
71
71
  {"id": [r[0] for r in rows], "name": [r[1] for r in rows]},
72
72
  schema=schema(id=pa.int64(), name=pa.string()),
@@ -79,7 +79,7 @@ def _insert_into(
79
79
 
80
80
  def _insert(t: TransactorImpl, tx_id: bytes, rows: list[tuple[int, str]], *, returning: bool = False) -> pa.RecordBatch:
81
81
  """Insert rows via the transactor and return the response batch."""
82
- stream = t.insert(tx_id=tx_id, table_name="data", returning=returning)
82
+ stream = t.insert(tx_id=tx_id, table_name="data", result_mode="rows" if returning else "count")
83
83
  batch = pa.record_batch(
84
84
  {"id": [r[0] for r in rows], "name": [r[1] for r in rows]},
85
85
  schema=schema(id=pa.int64(), name=pa.string()),
@@ -119,7 +119,7 @@ def _scan(
119
119
 
120
120
  def _delete(t: TransactorImpl, tx_id: bytes, rowids: list[int], *, returning: bool = False) -> pa.RecordBatch:
121
121
  """Delete rows by rowid, return the response batch."""
122
- stream = t.delete(tx_id=tx_id, table_name="data", returning=returning)
122
+ stream = t.delete(tx_id=tx_id, table_name="data", result_mode="rows" if returning else "count")
123
123
  batch = pa.record_batch({"rowid": rowids}, schema=schema(rowid=pa.int64()))
124
124
  out = OutputCollector(stream.output_schema, producer_mode=False)
125
125
  assert isinstance(stream.state, ExchangeState)
@@ -136,7 +136,12 @@ def _update(
136
136
  t: TransactorImpl, tx_id: bytes, rowids: list[int], names: list[str], *, returning: bool = False
137
137
  ) -> pa.RecordBatch:
138
138
  """Update name column by rowid, return the response batch."""
139
- stream = t.update(tx_id=tx_id, table_name="data", columns=["name"], returning=returning)
139
+ stream = t.update(
140
+ tx_id=tx_id,
141
+ table_name="data",
142
+ columns=["name"],
143
+ result_mode="rows" if returning else "count",
144
+ )
140
145
  batch = pa.record_batch(
141
146
  {"name": names, "rowid": rowids},
142
147
  schema=schema(name=pa.string(), rowid=pa.int64()),
@@ -2580,7 +2580,7 @@ requires-dist = [
2580
2580
 
2581
2581
  [[package]]
2582
2582
  name = "vgi-python"
2583
- version = "0.31.4"
2583
+ version = "0.32.0"
2584
2584
  source = { editable = "." }
2585
2585
  dependencies = [
2586
2586
  { name = "click" },
@@ -129,10 +129,15 @@ from vgi.table_in_out_function import (
129
129
  TableInOutGenerator,
130
130
  )
131
131
  from vgi.worker import Worker
132
+ from vgi.write_results import WriteOperation, WriteResultMode, write_changes_batch, write_result_schema
132
133
 
133
134
  __all__ = [
134
135
  "AggregateBindParams",
135
136
  "AggregateFunction",
137
+ "WriteOperation",
138
+ "WriteResultMode",
139
+ "write_result_schema",
140
+ "write_changes_batch",
136
141
  "AnyArrow",
137
142
  "AnyArrowValue",
138
143
  "Arg",
@@ -528,9 +528,7 @@ class SchemaReconcileCatalog(ReadOnlyCatalogInterface):
528
528
  not_null_constraints=[],
529
529
  unique_constraints=[],
530
530
  check_constraints=[],
531
- supports_insert=True,
532
- supports_update=True,
533
- supports_delete=True,
531
+ write_result_modes={"insert": "changes", "update": "changes", "delete": "changes"},
534
532
  )
535
533
 
536
534
  def schemas(
@@ -13,7 +13,7 @@ Three pre-defined tables are exposed under the ``main`` schema:
13
13
 
14
14
  * ``items`` — supports INSERT/UPDATE/DELETE with RETURNING.
15
15
  * ``items_no_returning`` — supports INSERT/UPDATE/DELETE *without* RETURNING.
16
- Used to exercise the supports_returning=False rejection path.
16
+ Used to exercise the ``count``-only RETURNING rejection path.
17
17
  * ``items_insert_only`` — supports INSERT only (no UPDATE/DELETE/RETURNING).
18
18
 
19
19
  State is held module-global, keyed by ``attach_opaque_data``. Per the
@@ -60,6 +60,7 @@ from vgi.schema_utils import schema as build_schema
60
60
  from vgi.table_function import BindParams, InitParams, ProcessParams, TableFunctionGenerator
61
61
  from vgi.table_in_out_function import TableInOutGenerator
62
62
  from vgi.worker import Worker
63
+ from vgi.write_results import WriteResultMode, coerce_write_result_mode, write_changes_batch, write_result_schema
63
64
 
64
65
  if TYPE_CHECKING:
65
66
  from vgi.catalog.catalog_interface import (
@@ -82,7 +83,7 @@ CATALOG_NAME = "simple_writable"
82
83
  _ROWID_FIELD = pa.field("rowid", pa.int64(), metadata={b"is_row_id": b""})
83
84
 
84
85
  # Output schema for write functions returning affected row counts.
85
- _COUNT_SCHEMA = build_schema(count=pa.int64())
86
+ _COUNT_SCHEMA = pa.schema([pa.field("count", pa.int64(), nullable=False)])
86
87
 
87
88
 
88
89
  # ============================================================================
@@ -116,7 +117,7 @@ def _table_specs() -> dict[str, pa.Schema]:
116
117
  "items": build_schema(id=pa.int64(), name=pa.string(), qty=pa.int64()),
117
118
  "items_no_returning": build_schema(id=pa.int64(), name=pa.string(), qty=pa.int64()),
118
119
  "items_insert_only": build_schema(id=pa.int64(), name=pa.string()),
119
- # Lies: catalog advertises supports_returning=True but the insert
120
+ # Lies: catalog advertises rows support but the insert
120
121
  # function always emits a (count BIGINT) batch. Used by tests to verify
121
122
  # the C++ extension rejects the mismatched batch with a clean IOException
122
123
  # instead of crashing inside ArrowToDuckDB.
@@ -124,8 +125,12 @@ def _table_specs() -> dict[str, pa.Schema]:
124
125
  }
125
126
 
126
127
 
127
- def _table_supports_returning(name: str) -> bool:
128
- return name != "items_no_returning"
128
+ def _table_result_mode(name: str) -> str:
129
+ if name == "items_no_returning":
130
+ return "count"
131
+ if name == "items_broken_returning":
132
+ return "rows"
133
+ return "changes"
129
134
 
130
135
 
131
136
  def _table_supports_update_delete(name: str) -> bool:
@@ -224,20 +229,25 @@ def _attach_opaque_data_from_process(params: ProcessParams[None]) -> bytes:
224
229
  return bytes(aid)
225
230
 
226
231
 
227
- def _parse_write_options(params: BindParams[None]) -> dict[str, Any]:
232
+ def _parse_write_options(params: BindParams[None] | ProcessParams[None]) -> dict[str, Any]:
228
233
  """Decode the write_options batch passed in named arguments."""
229
- defaults: dict[str, Any] = {"return_chunks": False, "on_conflict": "throw", "on_conflict_columns": []}
230
- if not (params.bind_call.arguments and params.bind_call.arguments.named):
234
+ defaults: dict[str, Any] = {"result_mode": "count", "on_conflict": "throw", "on_conflict_columns": []}
235
+ if isinstance(params, BindParams):
236
+ bind_call = params.bind_call
237
+ else:
238
+ assert params.init_call is not None
239
+ bind_call = params.init_call.bind_call
240
+ if not (bind_call.arguments and bind_call.arguments.named):
231
241
  return defaults
232
- val = params.bind_call.arguments.named.get("write_options")
242
+ val = bind_call.arguments.named.get("write_options")
233
243
  if val is None:
234
244
  return defaults
235
245
  from vgi_rpc.utils import deserialize_record_batch
236
246
 
237
247
  batch, _ = deserialize_record_batch(val.as_py())
238
248
  out = dict(defaults)
239
- if "return_chunks" in batch.schema.names:
240
- out["return_chunks"] = batch.column("return_chunks")[0].as_py()
249
+ if "result_mode" in batch.schema.names:
250
+ out["result_mode"] = coerce_write_result_mode(batch.column("result_mode")[0].as_py())
241
251
  if "on_conflict" in batch.schema.names:
242
252
  out["on_conflict"] = batch.column("on_conflict")[0].as_py()
243
253
  if "on_conflict_columns" in batch.schema.names:
@@ -245,6 +255,26 @@ def _parse_write_options(params: BindParams[None]) -> dict[str, Any]:
245
255
  return out
246
256
 
247
257
 
258
+ def _emit_changes(
259
+ out: OutputCollector,
260
+ table_schema: pa.Schema,
261
+ old_rows: Sequence[tuple[Any, ...] | None],
262
+ new_rows: Sequence[tuple[Any, ...] | None],
263
+ ) -> None:
264
+ names = table_schema.names
265
+
266
+ def as_struct(row: tuple[Any, ...] | None) -> dict[str, Any] | None:
267
+ return None if row is None else dict(zip(names, row, strict=True))
268
+
269
+ out.emit(
270
+ write_changes_batch(
271
+ table_schema,
272
+ [as_struct(row) for row in old_rows],
273
+ [as_struct(row) for row in new_rows],
274
+ )
275
+ )
276
+
277
+
248
278
  def _user_schema_from_bind(params: BindParams[None]) -> pa.Schema:
249
279
  qualified = _qualified_from_bind(params)
250
280
  return _get_user_schema(qualified)
@@ -329,9 +359,8 @@ class SimpleInsert(TableInOutGenerator[None, None]):
329
359
  @classmethod
330
360
  def on_bind(cls, params: BindParams[None]) -> BindResponse:
331
361
  opts = _parse_write_options(params)
332
- if opts["return_chunks"]:
333
- return BindResponse(output_schema=_user_schema_from_bind(params))
334
- return BindResponse(output_schema=_COUNT_SCHEMA)
362
+ mode = opts["result_mode"]
363
+ return BindResponse(output_schema=write_result_schema(mode, _user_schema_from_bind(params)))
335
364
 
336
365
  @classmethod
337
366
  def process(
@@ -345,7 +374,7 @@ class SimpleInsert(TableInOutGenerator[None, None]):
345
374
  attach_opaque_data = _attach_opaque_data_from_process(params)
346
375
  bare = _bare_name(qualified)
347
376
  user_schema = _get_user_schema(qualified)
348
- return_chunks = params.output_schema != _COUNT_SCHEMA
377
+ result_mode: WriteResultMode = _parse_write_options(params)["result_mode"]
349
378
 
350
379
  col_names = [f.name for f in user_schema]
351
380
  cols_sql = ", ".join(f'"{c}"' for c in col_names)
@@ -362,12 +391,14 @@ class SimpleInsert(TableInOutGenerator[None, None]):
362
391
  )
363
392
  conn.execute("COMMIT")
364
393
 
365
- if return_chunks:
394
+ if result_mode == "rows":
366
395
  out_cols: dict[str, list[Any]] = {c: [] for c in col_names}
367
396
  for row in rows_to_insert:
368
397
  for c, v in zip(col_names, row, strict=True):
369
398
  out_cols[c].append(v)
370
399
  out.emit(pa.RecordBatch.from_pydict(out_cols, schema=user_schema))
400
+ elif result_mode == "changes":
401
+ _emit_changes(out, user_schema, [None] * len(rows_to_insert), rows_to_insert)
371
402
  else:
372
403
  out.emit(pa.RecordBatch.from_pydict({"count": [batch.num_rows]}, schema=_COUNT_SCHEMA))
373
404
 
@@ -381,9 +412,8 @@ class SimpleUpdate(TableInOutGenerator[None, None]):
381
412
  @classmethod
382
413
  def on_bind(cls, params: BindParams[None]) -> BindResponse:
383
414
  opts = _parse_write_options(params)
384
- if opts["return_chunks"]:
385
- return BindResponse(output_schema=_user_schema_from_bind(params))
386
- return BindResponse(output_schema=_COUNT_SCHEMA)
415
+ mode = opts["result_mode"]
416
+ return BindResponse(output_schema=write_result_schema(mode, _user_schema_from_bind(params)))
387
417
 
388
418
  @classmethod
389
419
  def process(
@@ -397,7 +427,7 @@ class SimpleUpdate(TableInOutGenerator[None, None]):
397
427
  attach_opaque_data = _attach_opaque_data_from_process(params)
398
428
  bare = _bare_name(qualified)
399
429
  user_schema = _get_user_schema(qualified)
400
- return_chunks = params.output_schema != _COUNT_SCHEMA
430
+ result_mode: WriteResultMode = _parse_write_options(params)["result_mode"]
401
431
 
402
432
  update_cols = [n for n in batch.schema.names if n != "rowid"]
403
433
  set_clause = ", ".join(f'"{c}"=?' for c in update_cols)
@@ -405,23 +435,31 @@ class SimpleUpdate(TableInOutGenerator[None, None]):
405
435
  select_list = ", ".join(f'"{c}"' for c in user_col_names)
406
436
 
407
437
  rowid_col = batch.column("rowid")
438
+ old_rows: list[tuple[Any, ...]] = []
408
439
  updated: list[tuple[Any, ...]] = []
409
440
  with _connect(attach_opaque_data) as conn:
410
441
  conn.execute("BEGIN")
411
442
  for i in range(batch.num_rows):
412
443
  rowid = rowid_col[i].as_py()
444
+ old_row = conn.execute(f'SELECT {select_list} FROM "{bare}" WHERE rowid=?', (rowid,)).fetchone()
445
+ if old_row is None:
446
+ conn.execute("ROLLBACK")
447
+ raise ValueError(f"Update target rowid {rowid} not in table {qualified}")
413
448
  values = tuple(batch.column(c)[i].as_py() for c in update_cols)
414
449
  cur = conn.execute(f'UPDATE "{bare}" SET {set_clause} WHERE rowid=?', (*values, rowid))
415
450
  if cur.rowcount == 0:
416
451
  conn.execute("ROLLBACK")
417
452
  raise ValueError(f"Update target rowid {rowid} not in table {qualified}")
418
453
  row = conn.execute(f'SELECT {select_list} FROM "{bare}" WHERE rowid=?', (rowid,)).fetchone()
454
+ old_rows.append(old_row)
419
455
  updated.append(row)
420
456
  conn.execute("COMMIT")
421
457
 
422
- if return_chunks:
458
+ if result_mode == "rows":
423
459
  cols = {c: [row[i] for row in updated] for i, c in enumerate(user_col_names)}
424
460
  out.emit(pa.RecordBatch.from_pydict(cols, schema=user_schema))
461
+ elif result_mode == "changes":
462
+ _emit_changes(out, user_schema, old_rows, updated)
425
463
  else:
426
464
  out.emit(pa.RecordBatch.from_pydict({"count": [batch.num_rows]}, schema=_COUNT_SCHEMA))
427
465
 
@@ -435,9 +473,8 @@ class SimpleDelete(TableInOutGenerator[None, None]):
435
473
  @classmethod
436
474
  def on_bind(cls, params: BindParams[None]) -> BindResponse:
437
475
  opts = _parse_write_options(params)
438
- if opts["return_chunks"]:
439
- return BindResponse(output_schema=_user_schema_from_bind(params))
440
- return BindResponse(output_schema=_COUNT_SCHEMA)
476
+ mode = opts["result_mode"]
477
+ return BindResponse(output_schema=write_result_schema(mode, _user_schema_from_bind(params)))
441
478
 
442
479
  @classmethod
443
480
  def process(
@@ -451,7 +488,7 @@ class SimpleDelete(TableInOutGenerator[None, None]):
451
488
  attach_opaque_data = _attach_opaque_data_from_process(params)
452
489
  bare = _bare_name(qualified)
453
490
  user_schema = _get_user_schema(qualified)
454
- return_chunks = params.output_schema != _COUNT_SCHEMA
491
+ result_mode: WriteResultMode = _parse_write_options(params)["result_mode"]
455
492
 
456
493
  user_col_names = [f.name for f in user_schema]
457
494
  select_list = ", ".join(f'"{c}"' for c in user_col_names)
@@ -470,9 +507,11 @@ class SimpleDelete(TableInOutGenerator[None, None]):
470
507
  deleted.append(row)
471
508
  conn.execute("COMMIT")
472
509
 
473
- if return_chunks:
510
+ if result_mode == "rows":
474
511
  cols = {c: [row[i] for row in deleted] for i, c in enumerate(user_col_names)}
475
512
  out.emit(pa.RecordBatch.from_pydict(cols, schema=user_schema))
513
+ elif result_mode == "changes":
514
+ _emit_changes(out, user_schema, deleted, [None] * len(deleted))
476
515
  else:
477
516
  out.emit(pa.RecordBatch.from_pydict({"count": [batch.num_rows]}, schema=_COUNT_SCHEMA))
478
517
 
@@ -491,7 +530,7 @@ class BrokenReturningInsert(TableInOutGenerator[None, None]):
491
530
 
492
531
  @classmethod
493
532
  def on_bind(cls, params: BindParams[None]) -> BindResponse:
494
- # Always advertise the count surface, even when return_chunks=True.
533
+ # Always advertise the count surface, even when result_mode=rows.
495
534
  # The C++ side will see this at bind via the worker's output schema and
496
535
  # tries to route the responses through ArrowToDuckDB on the table-row
497
536
  # schema — that mismatch is what we want to catch at runtime.
@@ -524,7 +563,7 @@ class BrokenReturningInsert(TableInOutGenerator[None, None]):
524
563
  rows_to_insert,
525
564
  )
526
565
  conn.execute("COMMIT")
527
- # Always emit count, regardless of return_chunks — that's the bug.
566
+ # Always emit count, regardless of result_mode — that's the bug.
528
567
  out.emit(pa.RecordBatch.from_pydict({"count": [batch.num_rows]}, schema=_COUNT_SCHEMA))
529
568
 
530
569
 
@@ -619,10 +658,11 @@ class SimpleWritableCatalog(ReadOnlyCatalogInterface):
619
658
  check_constraints=[],
620
659
  primary_key_constraints=[],
621
660
  foreign_key_constraints=[],
622
- supports_insert=True,
623
- supports_update=ud,
624
- supports_delete=ud,
625
- supports_returning=_table_supports_returning(name),
661
+ write_result_modes={
662
+ operation: _table_result_mode(name)
663
+ for operation, supported in (("insert", True), ("update", ud), ("delete", ud))
664
+ if supported
665
+ },
626
666
  )
627
667
 
628
668
  def table_get(