vgi-python 0.36.0__tar.gz → 0.36.2__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 (660) hide show
  1. {vgi_python-0.36.0 → vgi_python-0.36.2}/PKG-INFO +1 -1
  2. vgi_python-0.36.2/conformance/filter-v2/cases/positive/boolean-column-predicate.json +32 -0
  3. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/manifest.json +5 -0
  4. {vgi_python-0.36.0 → vgi_python-0.36.2}/pyproject.toml +1 -1
  5. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_filter_v2.py +166 -1
  6. {vgi_python-0.36.0 → vgi_python-0.36.2}/uv.lock +1 -1
  7. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/__init__.py +2 -0
  8. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/filters.py +123 -0
  9. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/splits.py +5 -3
  10. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/worker.py +2 -0
  11. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/aggregate_function.py +8 -1
  12. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/client/aggregate.py +4 -1
  13. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/filter_v2.py +18 -5
  14. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/protocol.py +4 -1
  15. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/table_filter_pushdown.py +79 -1
  16. {vgi_python-0.36.0 → vgi_python-0.36.2}/.dockerignore +0 -0
  17. {vgi_python-0.36.0 → vgi_python-0.36.2}/.gitattributes +0 -0
  18. {vgi_python-0.36.0 → vgi_python-0.36.2}/.github/dependabot.yml +0 -0
  19. {vgi_python-0.36.0 → vgi_python-0.36.2}/.github/styles/config/vocabularies/VGI/accept.txt +0 -0
  20. {vgi_python-0.36.0 → vgi_python-0.36.2}/.github/workflows/ci.yml +0 -0
  21. {vgi_python-0.36.0 → vgi_python-0.36.2}/.github/workflows/docs.yml +0 -0
  22. {vgi_python-0.36.0 → vgi_python-0.36.2}/.github/workflows/integration.yml +0 -0
  23. {vgi_python-0.36.0 → vgi_python-0.36.2}/.github/workflows/release.yml +0 -0
  24. {vgi_python-0.36.0 → vgi_python-0.36.2}/.github/workflows/tailnet-integration.yml +0 -0
  25. {vgi_python-0.36.0 → vgi_python-0.36.2}/.gitignore +0 -0
  26. {vgi_python-0.36.0 → vgi_python-0.36.2}/.python-version +0 -0
  27. {vgi_python-0.36.0 → vgi_python-0.36.2}/.vale.ini +0 -0
  28. {vgi_python-0.36.0 → vgi_python-0.36.2}/CLAUDE.md +0 -0
  29. {vgi_python-0.36.0 → vgi_python-0.36.2}/DOCS_ACCEPTANCE_CRITERIA.md +0 -0
  30. {vgi_python-0.36.0 → vgi_python-0.36.2}/DOCS_REVIEW_RUBRIC.md +0 -0
  31. {vgi_python-0.36.0 → vgi_python-0.36.2}/DOCS_USABILITY_TEST.md +0 -0
  32. {vgi_python-0.36.0 → vgi_python-0.36.2}/LICENSE +0 -0
  33. {vgi_python-0.36.0 → vgi_python-0.36.2}/PROTOCOL.md +0 -0
  34. {vgi_python-0.36.0 → vgi_python-0.36.2}/README.md +0 -0
  35. {vgi_python-0.36.0 → vgi_python-0.36.2}/RELEASE-RUNBOOK.md +0 -0
  36. {vgi_python-0.36.0 → vgi_python-0.36.2}/SECURITY.md +0 -0
  37. {vgi_python-0.36.0 → vgi_python-0.36.2}/ci/README.md +0 -0
  38. {vgi_python-0.36.0 → vgi_python-0.36.2}/ci/preprocess-require.awk +0 -0
  39. {vgi_python-0.36.0 → vgi_python-0.36.2}/ci/run-integration.sh +0 -0
  40. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/README.md +0 -0
  41. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/cases/negative/and-too-few-children.json +0 -0
  42. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/cases/negative/delta-required-upsert.json +0 -0
  43. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/cases/negative/nested-runtime-filter.json +0 -0
  44. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/cases/negative/remove-with-expression.json +0 -0
  45. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/cases/negative/required-runtime-filter.json +0 -0
  46. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/cases/negative/snapshot-nonzero-revision.json +0 -0
  47. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/cases/negative/unknown-document-property.json +0 -0
  48. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/cases/negative/unknown-node.json +0 -0
  49. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/cases/positive/advisory-upsert-delta.json +0 -0
  50. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/cases/positive/empty-snapshot.json +0 -0
  51. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/cases/positive/nested-required-snapshot.json +0 -0
  52. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/cases/positive/remove-delta.json +0 -0
  53. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/cases/positive/runtime-filter-snapshot.json +0 -0
  54. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/filter-v2.schema.json +0 -0
  55. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/generate_runtime.py +0 -0
  56. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/run_worker.py +0 -0
  57. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/arithmetic-add/expected.arrow +0 -0
  58. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/arithmetic-add/filter.arrow +0 -0
  59. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/arithmetic-add/input.arrow +0 -0
  60. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/arithmetic-multiply/expected.arrow +0 -0
  61. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/arithmetic-multiply/filter.arrow +0 -0
  62. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/arithmetic-multiply/input.arrow +0 -0
  63. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/arithmetic-negate/expected.arrow +0 -0
  64. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/arithmetic-negate/filter.arrow +0 -0
  65. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/arithmetic-negate/input.arrow +0 -0
  66. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/arithmetic-subtract/expected.arrow +0 -0
  67. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/arithmetic-subtract/filter.arrow +0 -0
  68. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/arithmetic-subtract/input.arrow +0 -0
  69. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/cast-integer-to-double/expected.arrow +0 -0
  70. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/cast-integer-to-double/filter.arrow +0 -0
  71. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/cast-integer-to-double/input.arrow +0 -0
  72. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-distinct_from/expected.arrow +0 -0
  73. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-distinct_from/filter.arrow +0 -0
  74. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-distinct_from/input.arrow +0 -0
  75. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-distinct_from/worker-expected.arrow +0 -0
  76. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-eq/expected.arrow +0 -0
  77. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-eq/filter.arrow +0 -0
  78. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-eq/input.arrow +0 -0
  79. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-eq/worker-expected.arrow +0 -0
  80. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-ge/expected.arrow +0 -0
  81. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-ge/filter.arrow +0 -0
  82. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-ge/input.arrow +0 -0
  83. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-ge/worker-expected.arrow +0 -0
  84. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-gt/expected.arrow +0 -0
  85. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-gt/filter.arrow +0 -0
  86. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-gt/input.arrow +0 -0
  87. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-gt/worker-expected.arrow +0 -0
  88. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-le/expected.arrow +0 -0
  89. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-le/filter.arrow +0 -0
  90. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-le/input.arrow +0 -0
  91. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-le/worker-expected.arrow +0 -0
  92. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-lt/expected.arrow +0 -0
  93. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-lt/filter.arrow +0 -0
  94. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-lt/input.arrow +0 -0
  95. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-lt/worker-expected.arrow +0 -0
  96. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-ne/expected.arrow +0 -0
  97. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-ne/filter.arrow +0 -0
  98. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-ne/input.arrow +0 -0
  99. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-ne/worker-expected.arrow +0 -0
  100. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-not_distinct_from/expected.arrow +0 -0
  101. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-not_distinct_from/filter.arrow +0 -0
  102. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-not_distinct_from/input.arrow +0 -0
  103. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/comparison-not_distinct_from/worker-expected.arrow +0 -0
  104. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/delta-atomic-multi-update/delta-0.arrow +0 -0
  105. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/delta-atomic-multi-update/expected.arrow +0 -0
  106. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/delta-atomic-multi-update/filter.arrow +0 -0
  107. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/delta-atomic-multi-update/input.arrow +0 -0
  108. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/delta-empty-noop/delta-0.arrow +0 -0
  109. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/delta-empty-noop/expected.arrow +0 -0
  110. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/delta-empty-noop/filter.arrow +0 -0
  111. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/delta-empty-noop/input.arrow +0 -0
  112. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/delta-upsert-remove-stale/delta-0.arrow +0 -0
  113. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/delta-upsert-remove-stale/delta-1.arrow +0 -0
  114. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/delta-upsert-remove-stale/delta-2.arrow +0 -0
  115. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/delta-upsert-remove-stale/expected.arrow +0 -0
  116. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/delta-upsert-remove-stale/filter.arrow +0 -0
  117. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/delta-upsert-remove-stale/input.arrow +0 -0
  118. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/empty-snapshot/expected.arrow +0 -0
  119. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/empty-snapshot/filter.arrow +0 -0
  120. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/empty-snapshot/input.arrow +0 -0
  121. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/empty-snapshot/worker-expected.arrow +0 -0
  122. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-cast-type-not-null/filter.arrow +0 -0
  123. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-cast-type-not-null/input.arrow +0 -0
  124. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-column-index/filter.arrow +0 -0
  125. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-column-index/input.arrow +0 -0
  126. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-column-name/filter.arrow +0 -0
  127. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-column-name/input.arrow +0 -0
  128. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-contextual-cast-without-session/filter.arrow +0 -0
  129. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-contextual-cast-without-session/input.arrow +0 -0
  130. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-duplicate-predicate-id/filter.arrow +0 -0
  131. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-duplicate-predicate-id/input.arrow +0 -0
  132. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-external-column-index/filter.arrow +0 -0
  133. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-external-column-index/input.arrow +0 -0
  134. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-external-column-index/join-keys-0.arrow +0 -0
  135. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-external-column-name/filter.arrow +0 -0
  136. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-external-column-name/input.arrow +0 -0
  137. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-external-column-name/join-keys-0.arrow +0 -0
  138. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-field-non-struct/filter.arrow +0 -0
  139. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-field-non-struct/input.arrow +0 -0
  140. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-in-payload-not-list/filter.arrow +0 -0
  141. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-in-payload-not-list/input.arrow +0 -0
  142. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-in-payload-null-list/filter.arrow +0 -0
  143. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-in-payload-null-list/input.arrow +0 -0
  144. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-invalid-overload/filter.arrow +0 -0
  145. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-invalid-overload/input.arrow +0 -0
  146. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-missing-literal/filter.arrow +0 -0
  147. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-missing-literal/input.arrow +0 -0
  148. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-non-boolean-root/filter.arrow +0 -0
  149. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-non-boolean-root/input.arrow +0 -0
  150. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-unknown-standard-function/filter.arrow +0 -0
  151. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/error-unknown-standard-function/input.arrow +0 -0
  152. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/external-in-nonzero-column/expected.arrow +0 -0
  153. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/external-in-nonzero-column/filter.arrow +0 -0
  154. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/external-in-nonzero-column/input.arrow +0 -0
  155. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/external-in-nonzero-column/join-keys-0.arrow +0 -0
  156. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/external-in-nonzero-column/worker-expected.arrow +0 -0
  157. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/function-contains/expected.arrow +0 -0
  158. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/function-contains/filter.arrow +0 -0
  159. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/function-contains/input.arrow +0 -0
  160. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/function-ends-with/expected.arrow +0 -0
  161. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/function-ends-with/filter.arrow +0 -0
  162. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/function-ends-with/input.arrow +0 -0
  163. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/function-list-contains/expected.arrow +0 -0
  164. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/function-list-contains/filter.arrow +0 -0
  165. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/function-list-contains/input.arrow +0 -0
  166. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/function-starts-with/expected.arrow +0 -0
  167. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/function-starts-with/filter.arrow +0 -0
  168. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/function-starts-with/input.arrow +0 -0
  169. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/in-empty/expected.arrow +0 -0
  170. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/in-empty/filter.arrow +0 -0
  171. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/in-empty/input.arrow +0 -0
  172. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/in-empty/worker-expected.arrow +0 -0
  173. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/in-with-null/expected.arrow +0 -0
  174. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/in-with-null/filter.arrow +0 -0
  175. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/in-with-null/input.arrow +0 -0
  176. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/in-with-null/worker-expected.arrow +0 -0
  177. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/is-not-null/expected.arrow +0 -0
  178. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/is-not-null/filter.arrow +0 -0
  179. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/is-not-null/input.arrow +0 -0
  180. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/is-not-null/worker-expected.arrow +0 -0
  181. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/is-null/expected.arrow +0 -0
  182. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/is-null/filter.arrow +0 -0
  183. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/is-null/input.arrow +0 -0
  184. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/is-null/worker-expected.arrow +0 -0
  185. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/kleene-and/expected.arrow +0 -0
  186. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/kleene-and/filter.arrow +0 -0
  187. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/kleene-and/input.arrow +0 -0
  188. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/kleene-not/expected.arrow +0 -0
  189. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/kleene-not/filter.arrow +0 -0
  190. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/kleene-not/input.arrow +0 -0
  191. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/kleene-or/expected.arrow +0 -0
  192. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/kleene-or/filter.arrow +0 -0
  193. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/kleene-or/input.arrow +0 -0
  194. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/nan-comparison/expected.arrow +0 -0
  195. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/nan-comparison/filter.arrow +0 -0
  196. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/nan-comparison/input.arrow +0 -0
  197. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/negative-zero-membership/expected.arrow +0 -0
  198. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/negative-zero-membership/filter.arrow +0 -0
  199. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/negative-zero-membership/input.arrow +0 -0
  200. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/nested-null-propagation/expected.arrow +0 -0
  201. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/nested-null-propagation/filter.arrow +0 -0
  202. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/nested-null-propagation/input.arrow +0 -0
  203. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/not-in-empty/expected.arrow +0 -0
  204. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/not-in-empty/filter.arrow +0 -0
  205. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/not-in-empty/input.arrow +0 -0
  206. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/not-in-empty/worker-expected.arrow +0 -0
  207. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/not-in-with-null/expected.arrow +0 -0
  208. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/not-in-with-null/filter.arrow +0 -0
  209. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/not-in-with-null/input.arrow +0 -0
  210. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/not-in-with-null/worker-expected.arrow +0 -0
  211. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/session-integer-division/expected.arrow +0 -0
  212. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/session-integer-division/filter.arrow +0 -0
  213. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime/session-integer-division/input.arrow +0 -0
  214. {vgi_python-0.36.0 → vgi_python-0.36.2}/conformance/filter-v2/runtime-manifest.json +0 -0
  215. {vgi_python-0.36.0 → vgi_python-0.36.2}/dist-vgi/.gitignore +0 -0
  216. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/aggregate-functions.md +0 -0
  217. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/api/arguments.md +0 -0
  218. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/api/auth.md +0 -0
  219. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/api/catalogs.md +0 -0
  220. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/api/client.md +0 -0
  221. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/api/exceptions.md +0 -0
  222. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/api/filters.md +0 -0
  223. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/api/functions.md +0 -0
  224. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/api/http.md +0 -0
  225. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/api/index.md +0 -0
  226. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/api/metadata.md +0 -0
  227. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/api/observability.md +0 -0
  228. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/api/storage.md +0 -0
  229. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/api/transactor.md +0 -0
  230. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/api/worker.md +0 -0
  231. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/argument-serialization.md +0 -0
  232. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/assets/apple-touch-icon.png +0 -0
  233. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/assets/favicon-16x16.png +0 -0
  234. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/assets/favicon-32x32.png +0 -0
  235. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/assets/favicon.ico +0 -0
  236. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/assets/kinds/aggregate.svg +0 -0
  237. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/assets/kinds/buffering.svg +0 -0
  238. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/assets/kinds/scalar.svg +0 -0
  239. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/assets/kinds/table-in-out.svg +0 -0
  240. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/assets/kinds/table.svg +0 -0
  241. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/assets/logo.png +0 -0
  242. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/assets/social-card.png +0 -0
  243. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/authentication.md +0 -0
  244. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/catalog-interface.md +0 -0
  245. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/cli.md +0 -0
  246. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/column-statistics.md +0 -0
  247. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/concepts/index.md +0 -0
  248. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/contributing-docs.md +0 -0
  249. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/filter-pushdown.md +0 -0
  250. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/generator-api.md +0 -0
  251. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/global-functions.md +0 -0
  252. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/how-to/catalogs.md +0 -0
  253. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/how-to/function-patterns.md +0 -0
  254. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/how-to/http-auth.md +0 -0
  255. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/how-to/index.md +0 -0
  256. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/how-to/iroh.md +0 -0
  257. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/how-to/pushdown-and-statistics.md +0 -0
  258. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/how-to/state-storage.md +0 -0
  259. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/how-to/tailnet.md +0 -0
  260. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/index.md +0 -0
  261. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/lifecycle.md +0 -0
  262. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/metadata.md +0 -0
  263. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/overrides/main.html +0 -0
  264. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/protocol/index.md +0 -0
  265. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/protocol/vgi-catalog-query-pushdown-design.md +0 -0
  266. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/protocol/vgi-duckdb-filter-adapter.md +0 -0
  267. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/protocol/vgi-filter-encoding-v2-spec.md +0 -0
  268. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/protocol/vgi-protocol-proposed-changes.md +0 -0
  269. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/protocol/vgi-runtime-filter-artifacts.md +0 -0
  270. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/robots.txt +0 -0
  271. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/shared-storage.md +0 -0
  272. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/stylesheets/extra.css +0 -0
  273. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/tutorial/index.md +0 -0
  274. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/tutorial/scalar.md +0 -0
  275. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/tutorial/table.md +0 -0
  276. {vgi_python-0.36.0 → vgi_python-0.36.2}/docs/vgi-logo.png +0 -0
  277. {vgi_python-0.36.0 → vgi_python-0.36.2}/examples/batch_index_worker.py +0 -0
  278. {vgi_python-0.36.0 → vgi_python-0.36.2}/examples/cache_worker.py +0 -0
  279. {vgi_python-0.36.0 → vgi_python-0.36.2}/examples/calc_scalar_worker.py +0 -0
  280. {vgi_python-0.36.0 → vgi_python-0.36.2}/examples/calc_worker.py +0 -0
  281. {vgi_python-0.36.0 → vgi_python-0.36.2}/examples/copy_format_worker.py +0 -0
  282. {vgi_python-0.36.0 → vgi_python-0.36.2}/examples/filter_worker.py +0 -0
  283. {vgi_python-0.36.0 → vgi_python-0.36.2}/examples/greeting_scalar_worker.py +0 -0
  284. {vgi_python-0.36.0 → vgi_python-0.36.2}/examples/row_count_worker.py +0 -0
  285. {vgi_python-0.36.0 → vgi_python-0.36.2}/examples/series_streaming_worker.py +0 -0
  286. {vgi_python-0.36.0 → vgi_python-0.36.2}/examples/sum_worker.py +0 -0
  287. {vgi_python-0.36.0 → vgi_python-0.36.2}/identity.png +0 -0
  288. {vgi_python-0.36.0 → vgi_python-0.36.2}/mkdocs.yml +0 -0
  289. {vgi_python-0.36.0 → vgi_python-0.36.2}/packages/vgi-fixtures/LICENSE +0 -0
  290. {vgi_python-0.36.0 → vgi_python-0.36.2}/packages/vgi-fixtures/README.md +0 -0
  291. {vgi_python-0.36.0 → vgi_python-0.36.2}/packages/vgi-fixtures/docker/Dockerfile +0 -0
  292. {vgi_python-0.36.0 → vgi_python-0.36.2}/packages/vgi-fixtures/docker/docker-entrypoint.sh +0 -0
  293. {vgi_python-0.36.0 → vgi_python-0.36.2}/packages/vgi-fixtures/pyproject.toml +0 -0
  294. {vgi_python-0.36.0 → vgi_python-0.36.2}/scripts/measure_startup.py +0 -0
  295. {vgi_python-0.36.0 → vgi_python-0.36.2}/scripts/regen_generated.py +0 -0
  296. {vgi_python-0.36.0 → vgi_python-0.36.2}/scripts/run_all_tests.sh +0 -0
  297. {vgi_python-0.36.0 → vgi_python-0.36.2}/test-data/generate.sh +0 -0
  298. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/__init__.py +0 -0
  299. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/_http_fixtures.py +0 -0
  300. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/catalog/__init__.py +0 -0
  301. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/catalog/test_attach_option.py +0 -0
  302. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/catalog/test_catalog_interface.py +0 -0
  303. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/catalog/test_client_catalog.py +0 -0
  304. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/catalog/test_column_statistics.py +0 -0
  305. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/catalog/test_declarative.py +0 -0
  306. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/catalog/test_example_worker_catalog.py +0 -0
  307. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/catalog/test_integration.py +0 -0
  308. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/catalog/test_required_filters.py +0 -0
  309. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/catalog/test_scan_branches.py +0 -0
  310. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/catalog/test_serialization.py +0 -0
  311. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/catalog/test_setting.py +0 -0
  312. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/catalog/test_storage.py +0 -0
  313. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/catalog/test_time_travel.py +0 -0
  314. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/catalog/test_writable_table.py +0 -0
  315. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/client/__init__.py +0 -0
  316. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/client/test_aggregate_client.py +0 -0
  317. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/client/test_batch_metadata_callback.py +0 -0
  318. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/client/test_bind_and_join_keys.py +0 -0
  319. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/client/test_broken_pipe.py +0 -0
  320. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/client/test_cli.py +0 -0
  321. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/client/test_cli_catalog_functions.py +0 -0
  322. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/client/test_copy_client.py +0 -0
  323. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/client/test_http_response_budget.py +0 -0
  324. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/client/test_iroh_client.py +0 -0
  325. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/client/test_scan_branches_client.py +0 -0
  326. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/client/test_split_client.py +0 -0
  327. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/client/test_stop_force.py +0 -0
  328. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/client/test_table_column_statistics.py +0 -0
  329. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/client/test_time_travel_client.py +0 -0
  330. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/client/test_worker_debug.py +0 -0
  331. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/__init__.py +0 -0
  332. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/_stub.py +0 -0
  333. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/conftest.py +0 -0
  334. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_accumulate.py +0 -0
  335. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_aggregate.py +0 -0
  336. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_attach.py +0 -0
  337. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_bearer_auth.py +0 -0
  338. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_const_param_enforcement.py +0 -0
  339. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_container.py +0 -0
  340. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_copy_from.py +0 -0
  341. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_copy_to.py +0 -0
  342. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_directory_parity.py +0 -0
  343. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_function_inventory.py +0 -0
  344. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_github.py +0 -0
  345. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_http_client.py +0 -0
  346. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_http_external_location.py +0 -0
  347. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_http_upload_url.py +0 -0
  348. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_macro.py +0 -0
  349. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_overload.py +0 -0
  350. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_protocol_inventory.py +0 -0
  351. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_protocol_version.py +0 -0
  352. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_resumable_scan.py +0 -0
  353. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_scalar.py +0 -0
  354. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_scalar_attach_opaque_data.py +0 -0
  355. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_secret.py +0 -0
  356. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_settings.py +0 -0
  357. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_splits.py +0 -0
  358. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_table.py +0 -0
  359. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_table_in_out.py +0 -0
  360. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_view.py +0 -0
  361. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conformance/test_writable.py +0 -0
  362. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/conftest.py +0 -0
  363. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/data/split_tokens/anchor_len_overrun.bin +0 -0
  364. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/data/split_tokens/bad_fingerprint.bin +0 -0
  365. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/data/split_tokens/bad_flags_unsealed_but_key_present.bin +0 -0
  366. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/data/split_tokens/bad_version.bin +0 -0
  367. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/data/split_tokens/generate.py +0 -0
  368. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/data/split_tokens/manifest.json +0 -0
  369. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/data/split_tokens/reserved_flag_bit.bin +0 -0
  370. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/data/split_tokens/stale_anchor.bin +0 -0
  371. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/data/split_tokens/truncated.bin +0 -0
  372. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/data/split_tokens/valid_sealed.bin +0 -0
  373. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/data/split_tokens/valid_unsealed.bin +0 -0
  374. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/scalar/__init__.py +0 -0
  375. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/scalar/test_bernoulli_function.py +0 -0
  376. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/scalar/test_binary_packet_function.py +0 -0
  377. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/scalar/test_client.py +0 -0
  378. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/scalar/test_conditional_message_function.py +0 -0
  379. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/scalar/test_hash_seed_function.py +0 -0
  380. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/scalar/test_multiply_by_setting_function.py +0 -0
  381. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/scalar/test_multiply_function.py +0 -0
  382. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/scalar/test_random_bytes_function.py +0 -0
  383. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/scalar/test_return_secret_value_function.py +0 -0
  384. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table/__init__.py +0 -0
  385. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table/generator/__init__.py +0 -0
  386. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table/generator/test_constant_columns_function.py +0 -0
  387. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table/generator/test_double_sequence_function.py +0 -0
  388. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table/generator/test_exception_function.py +0 -0
  389. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table/generator/test_filter_echo_function.py +0 -0
  390. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table/generator/test_logging_function.py +0 -0
  391. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table/generator/test_nested_sequence_function.py +0 -0
  392. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table/generator/test_partitioned_function.py +0 -0
  393. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table/generator/test_projected_data_function.py +0 -0
  394. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table/generator/test_sequence_function.py +0 -0
  395. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table/generator/test_settings_function.py +0 -0
  396. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table/generator/test_struct_settings_function.py +0 -0
  397. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table/generator/test_ten_thousand_function.py +0 -0
  398. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table/test_wide_columns.py +0 -0
  399. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table_in_out/__init__.py +0 -0
  400. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table_in_out/generator/__init__.py +0 -0
  401. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table_in_out/generator/test_buffer_input_function.py +0 -0
  402. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table_in_out/generator/test_echo_function.py +0 -0
  403. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table_in_out/generator/test_exception_functions.py +0 -0
  404. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table_in_out/generator/test_filter_by_setting_function.py +0 -0
  405. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table_in_out/generator/test_repeat_inputs_function.py +0 -0
  406. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table_in_out/generator/test_substream_partial_sum_function.py +0 -0
  407. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table_in_out/generator/test_sum_all_columns_function.py +0 -0
  408. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table_in_out/test_blended_exchange.py +0 -0
  409. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table_in_out/test_blended_metadata.py +0 -0
  410. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/table_in_out/test_client.py +0 -0
  411. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/tailnet/Dockerfile +0 -0
  412. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/tailnet/__init__.py +0 -0
  413. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/tailnet/compose.yaml +0 -0
  414. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/tailnet/probe.py +0 -0
  415. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/tailnet/run.sh +0 -0
  416. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/tailnet/test_worker.py +0 -0
  417. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/tailnet/worker.py +0 -0
  418. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_access_log_audit.py +0 -0
  419. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_aggregate_function.py +0 -0
  420. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_argument_spec.py +0 -0
  421. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_auth.py +0 -0
  422. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_bind_exceptions.py +0 -0
  423. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_bind_request_at_clause.py +0 -0
  424. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_bound_storage_conformance.py +0 -0
  425. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_cache_control.py +0 -0
  426. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_call_state_attach.py +0 -0
  427. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_catalog_auth_binding.py +0 -0
  428. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_client_oauth.py +0 -0
  429. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_codegen_request_inventory.py +0 -0
  430. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_copy_from_function.py +0 -0
  431. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_copy_to_function.py +0 -0
  432. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_docstrings.py +0 -0
  433. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_documentation_examples.py +0 -0
  434. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_dynamic_filter_http_turns.py +0 -0
  435. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_example_function_arg_types.py +0 -0
  436. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_examples_workers.py +0 -0
  437. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_exception_handling.py +0 -0
  438. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_exceptions.py +0 -0
  439. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_filter_pushdown.py +0 -0
  440. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_filter_pushdown_extension.py +0 -0
  441. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_filter_v2_builder.py +0 -0
  442. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_filter_v2_runtime_corpus.py +0 -0
  443. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_filter_v2_spec_schema.py +0 -0
  444. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_fixture_catalog_parity.py +0 -0
  445. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_function_shape_mismatch.py +0 -0
  446. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_function_storage.py +0 -0
  447. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_function_storage_azure_sql.py +0 -0
  448. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_function_storage_cf_do.py +0 -0
  449. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_function_storage_cf_do_integration.py +0 -0
  450. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_function_storage_conformance.py +0 -0
  451. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_generated_cpp_constants.py +0 -0
  452. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_generated_cpp_protocol_name.py +0 -0
  453. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_generated_cpp_protocol_version.py +0 -0
  454. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_generated_cpp_request_builders.py +0 -0
  455. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_generated_cpp_schemas.py +0 -0
  456. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_generated_cpp_secret.py +0 -0
  457. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_generated_go_schemas.py +0 -0
  458. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_generated_java_schemas.py +0 -0
  459. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_generated_protocol_version.py +0 -0
  460. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_generated_rust_request_builders.py +0 -0
  461. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_generated_rust_schemas.py +0 -0
  462. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_generated_schemas_cross_lang.py +0 -0
  463. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_generated_ts_client.py +0 -0
  464. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_generated_ts_schemas.py +0 -0
  465. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_http_demo_storage.py +0 -0
  466. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_http_s3_offload_input.py +0 -0
  467. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_http_s3_offload_output.py +0 -0
  468. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_import_side_effects.py +0 -0
  469. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_launch_transport.py +0 -0
  470. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_metadata.py +0 -0
  471. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_mypy_consolidated.py +0 -0
  472. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_nest_tensor.py +0 -0
  473. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_otel.py +0 -0
  474. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_projection_enforcement.py +0 -0
  475. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_projection_repro.py +0 -0
  476. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_protocol_classes.py +0 -0
  477. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_resolved_secrets.py +0 -0
  478. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_schema_paths_v2.py +0 -0
  479. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_schema_scoped_functions.py +0 -0
  480. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_schema_utils.py +0 -0
  481. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_serve.py +0 -0
  482. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_setting_secret_annotations.py +0 -0
  483. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_signing_key.py +0 -0
  484. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_split_token.py +0 -0
  485. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_subprocess_transport.py +0 -0
  486. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_table_buffering_function.py +0 -0
  487. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_table_function_dynamic_to_string.py +0 -0
  488. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_tcp_transport.py +0 -0
  489. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_type_bounds.py +0 -0
  490. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_union_argument.py +0 -0
  491. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_wire_record_schema_parity.py +0 -0
  492. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_worker.py +0 -0
  493. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_worker_cli.py +0 -0
  494. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_worker_page.py +0 -0
  495. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/test_write_results.py +0 -0
  496. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/transactor/__init__.py +0 -0
  497. {vgi_python-0.36.0 → vgi_python-0.36.2}/tests/transactor/test_transactor.py +0 -0
  498. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/__init__.py +0 -0
  499. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_duckdb.py +0 -0
  500. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_storage_profile.py +0 -0
  501. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/__init__.py +0 -0
  502. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/accumulate/__init__.py +0 -0
  503. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/accumulate/worker.py +0 -0
  504. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/aggregate/__init__.py +0 -0
  505. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/aggregate/_common.py +0 -0
  506. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/aggregate/basic.py +0 -0
  507. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/aggregate/dynamic.py +0 -0
  508. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/aggregate/generic.py +0 -0
  509. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/aggregate/listagg.py +0 -0
  510. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/aggregate/percentile.py +0 -0
  511. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/aggregate/same_name.py +0 -0
  512. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/aggregate/secret_typed.py +0 -0
  513. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/aggregate/streaming.py +0 -0
  514. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/aggregate/varargs.py +0 -0
  515. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/aggregate/window.py +0 -0
  516. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/attach_options.py +0 -0
  517. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/bad_enum.py +0 -0
  518. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/bad_protocol.py +0 -0
  519. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/cancellable.py +0 -0
  520. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/catalog.py +0 -0
  521. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/companion.py +0 -0
  522. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/copy_from.py +0 -0
  523. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/copy_to.py +0 -0
  524. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/global_functions.py +0 -0
  525. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/http_server.py +0 -0
  526. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/narrow_bind/__init__.py +0 -0
  527. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/narrow_bind/worker.py +0 -0
  528. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/nest_tensor.py +0 -0
  529. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/orchard_catalog.py +0 -0
  530. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/projection_repro/__init__.py +0 -0
  531. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/projection_repro/worker.py +0 -0
  532. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/scalar/__init__.py +0 -0
  533. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/scalar/_common.py +0 -0
  534. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/scalar/arithmetic.py +0 -0
  535. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/scalar/bench_ladder.py +0 -0
  536. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/scalar/binary.py +0 -0
  537. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/scalar/formatting.py +0 -0
  538. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/scalar/geo.py +0 -0
  539. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/scalar/null_handling.py +0 -0
  540. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/scalar/random_demo.py +0 -0
  541. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/scalar/same_name.py +0 -0
  542. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/scalar/settings_secrets.py +0 -0
  543. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/scalar/type_info.py +0 -0
  544. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/schema_reconcile/__init__.py +0 -0
  545. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/schema_reconcile/worker.py +0 -0
  546. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/simple_writable.py +0 -0
  547. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/_common.py +0 -0
  548. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/batch_index.py +0 -0
  549. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/batch_index_broken.py +0 -0
  550. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/cache.py +0 -0
  551. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/catalog_scans.py +0 -0
  552. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/late_materialization.py +0 -0
  553. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/make_series.py +0 -0
  554. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/misc.py +0 -0
  555. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/order_modes.py +0 -0
  556. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/pairs.py +0 -0
  557. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/partition_columns.py +0 -0
  558. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/partition_columns_broken.py +0 -0
  559. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/profiling_example.py +0 -0
  560. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/required_filters.py +0 -0
  561. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/same_name_cached.py +0 -0
  562. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/same_name_schemas.py +0 -0
  563. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/sequence.py +0 -0
  564. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/settings.py +0 -0
  565. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/transaction_storage.py +0 -0
  566. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/tt_pushdown.py +0 -0
  567. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/typed_probe.py +0 -0
  568. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/versioned.py +0 -0
  569. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table/wide.py +0 -0
  570. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table_in_out.py +0 -0
  571. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/table_in_out_same_name.py +0 -0
  572. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/twin_catalogs.py +0 -0
  573. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/versioned.py +0 -0
  574. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/versioned_tables.py +0 -0
  575. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/writable/__init__.py +0 -0
  576. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/writable/generic.py +0 -0
  577. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/writable/table.py +0 -0
  578. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/_test_fixtures/writable/worker.py +0 -0
  579. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/argument_spec.py +0 -0
  580. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/arguments.py +0 -0
  581. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/attach_header.py +0 -0
  582. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/auth.py +0 -0
  583. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/cache_control.py +0 -0
  584. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/catalog/__init__.py +0 -0
  585. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/catalog/_descriptor_spec.py +0 -0
  586. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/catalog/attach_option.py +0 -0
  587. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/catalog/catalog_interface.py +0 -0
  588. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/catalog/descriptors.py +0 -0
  589. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/catalog/duckdb_statistics.py +0 -0
  590. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/catalog/secret_type.py +0 -0
  591. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/catalog/setting.py +0 -0
  592. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/catalog/storage.py +0 -0
  593. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/client/__init__.py +0 -0
  594. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/client/catalog_mixin.py +0 -0
  595. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/client/cli.py +0 -0
  596. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/client/cli_catalog.py +0 -0
  597. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/client/cli_schema.py +0 -0
  598. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/client/cli_table.py +0 -0
  599. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/client/cli_transaction.py +0 -0
  600. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/client/cli_utils.py +0 -0
  601. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/client/cli_view.py +0 -0
  602. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/client/client.py +0 -0
  603. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/client/errors.py +0 -0
  604. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/codegen/__init__.py +0 -0
  605. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/codegen/_common.py +0 -0
  606. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/codegen/cpp_constants.py +0 -0
  607. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/codegen/cpp_protocol_name.py +0 -0
  608. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/codegen/cpp_protocol_version.py +0 -0
  609. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/codegen/cpp_request_builders.py +0 -0
  610. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/codegen/cpp_schemas.py +0 -0
  611. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/codegen/cpp_secret_protocol_version.py +0 -0
  612. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/codegen/cpp_secret_request_builders.py +0 -0
  613. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/codegen/cpp_secret_schemas.py +0 -0
  614. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/codegen/go_schemas.py +0 -0
  615. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/codegen/java_schemas.py +0 -0
  616. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/codegen/protocol_version.py +0 -0
  617. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/codegen/rust_request_builders.py +0 -0
  618. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/codegen/rust_schemas.py +0 -0
  619. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/codegen/ts_client.py +0 -0
  620. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/codegen/ts_schemas.py +0 -0
  621. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/copy_from_function.py +0 -0
  622. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/copy_to_function.py +0 -0
  623. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/exceptions.py +0 -0
  624. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/filter_v2_builder.py +0 -0
  625. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/function.py +0 -0
  626. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/function_storage.py +0 -0
  627. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/function_storage_azure_sql.py +0 -0
  628. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/function_storage_cf_do.py +0 -0
  629. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/http/__init__.py +0 -0
  630. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/http/demo_storage.py +0 -0
  631. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/http/landing.html +0 -0
  632. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/http/landing_page.py +0 -0
  633. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/http/vgi-client.js +0 -0
  634. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/http/worker_page.py +0 -0
  635. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/invocation.py +0 -0
  636. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/logging_config.py +0 -0
  637. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/meta_worker.py +0 -0
  638. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/metadata.py +0 -0
  639. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/otel.py +0 -0
  640. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/profiling.py +0 -0
  641. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/protocol_version.txt +0 -0
  642. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/py.typed +0 -0
  643. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/scalar_function.py +0 -0
  644. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/schema_path.py +0 -0
  645. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/schema_utils.py +0 -0
  646. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/secret_protocol.py +0 -0
  647. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/secret_service.py +0 -0
  648. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/serve.py +0 -0
  649. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/split_token.py +0 -0
  650. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/table_buffering_function.py +0 -0
  651. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/table_function.py +0 -0
  652. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/table_in_out_function.py +0 -0
  653. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/transactor/__init__.py +0 -0
  654. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/transactor/_duckdb_compat.py +0 -0
  655. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/transactor/client.py +0 -0
  656. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/transactor/protocol.py +0 -0
  657. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/transactor/server.py +0 -0
  658. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/worker.py +0 -0
  659. {vgi_python-0.36.0 → vgi_python-0.36.2}/vgi/write_results.py +0 -0
  660. {vgi_python-0.36.0 → vgi_python-0.36.2}/wrangler.jsonc +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: vgi-python
3
- Version: 0.36.0
3
+ Version: 0.36.2
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
@@ -0,0 +1,32 @@
1
+ {
2
+ "encoding": "vgi.filters.v2",
3
+ "semantics": "vgi.duckdb.standard.v1",
4
+ "kind": "snapshot",
5
+ "predicates": [
6
+ {
7
+ "id": "query:bare-boolean-column",
8
+ "revision": 0,
9
+ "mode": "required",
10
+ "source": "query",
11
+ "expression": {
12
+ "node": "column_ref",
13
+ "column_index": 0,
14
+ "column_name": "flag"
15
+ }
16
+ },
17
+ {
18
+ "id": "query:negated-boolean-column",
19
+ "revision": 0,
20
+ "mode": "required",
21
+ "source": "query",
22
+ "expression": {
23
+ "node": "not",
24
+ "expression": {
25
+ "node": "column_ref",
26
+ "column_index": 1,
27
+ "column_name": "other_flag"
28
+ }
29
+ }
30
+ }
31
+ ]
32
+ }
@@ -30,6 +30,11 @@
30
30
  "document": "cases/positive/runtime-filter-snapshot.json",
31
31
  "expected": "valid"
32
32
  },
33
+ {
34
+ "id": "structural.boolean-column-predicate",
35
+ "document": "cases/positive/boolean-column-predicate.json",
36
+ "expected": "valid"
37
+ },
33
38
  {
34
39
  "id": "structural.and-too-few-children",
35
40
  "document": "cases/negative/and-too-few-children.json",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "vgi-python"
3
- version = "0.36.0"
3
+ version = "0.36.2"
4
4
  description = "Vector Gateway Interface - Connect DuckDB to external programs via Apache Arrow"
5
5
  readme = "README.md"
6
6
  keywords = [
@@ -6,7 +6,7 @@ from __future__ import annotations
6
6
 
7
7
  import json
8
8
  from collections.abc import Mapping
9
- from typing import cast
9
+ from typing import Any, cast
10
10
 
11
11
  import pyarrow as pa
12
12
  import pytest
@@ -531,3 +531,168 @@ def test_unknown_arrow_extension_metadata_is_rejected() -> None:
531
531
  _batch(_document([_predicate(_comparison())]), (extension_field, b"opaque")),
532
532
  output_schema=pa.schema([("n", pa.int64())]),
533
533
  )
534
+
535
+
536
+ # ---------------------------------------------------------------------------
537
+ # A boolean column is a predicate on its own
538
+ #
539
+ # `WHERE flag` / `WHERE NOT flag` is idiomatic SQL, and DuckDB pushes it down as
540
+ # a bare `column_ref` rather than rewriting it to `flag = true`. The schema
541
+ # admits that -- `coreExpression` lists `columnRef` first -- but the decoder's
542
+ # boolean gate used to enumerate node *kinds* instead of asking for the resolved
543
+ # *type*, so it refused every one of them: "predicate root must resolve to
544
+ # BOOLEAN", on a node whose type it had already resolved to BOOLEAN and stored.
545
+ # ---------------------------------------------------------------------------
546
+
547
+ _BOOL_FIELDS: list[pa.Field[Any]] = [pa.field("flag", pa.bool_()), pa.field("n", pa.int64())]
548
+ _BOOL_SCHEMA = pa.schema(_BOOL_FIELDS)
549
+
550
+
551
+ def _flag(index: int = 0) -> dict[str, object]:
552
+ return {"node": "column_ref", "column_index": index, "column_name": "flag"}
553
+
554
+
555
+ def test_bare_boolean_column_is_a_valid_predicate_root() -> None:
556
+ """`WHERE flag` -- the column itself is the predicate."""
557
+ filters = deserialize_filters(
558
+ _batch(_document([_predicate(_flag())])),
559
+ output_schema=_BOOL_SCHEMA,
560
+ )
561
+ batch = pa.RecordBatch.from_pydict(
562
+ {"flag": [True, False, None, True], "n": [1, 2, 3, 4]},
563
+ schema=_BOOL_SCHEMA,
564
+ )
565
+ # evaluate() is the raw three-valued predicate: NULL stays NULL.
566
+ assert filters.evaluate(batch).to_pylist() == [True, False, None, True]
567
+ # apply() is what selects rows, and there a NULL predicate is not satisfied
568
+ # -- the same rows `flag = true` would keep, which is what makes the SQL
569
+ # rewrite below a projection rather than a change of meaning.
570
+ assert filters.apply(batch).to_pydict()["n"] == [1, 4]
571
+
572
+
573
+ def test_negated_boolean_column_is_a_valid_predicate_root() -> None:
574
+ """`WHERE NOT flag` -- `not` over a bare column, which the gate also refused."""
575
+ filters = deserialize_filters(
576
+ _batch(_document([_predicate({"node": "not", "expression": _flag()})])),
577
+ output_schema=_BOOL_SCHEMA,
578
+ )
579
+ batch = pa.RecordBatch.from_pydict(
580
+ {"flag": [True, False, None, True], "n": [1, 2, 3, 4]},
581
+ schema=_BOOL_SCHEMA,
582
+ )
583
+ assert filters.evaluate(batch).to_pylist() == [False, True, None, False]
584
+ # NOT NULL is NULL, so row 3 is not kept -- exactly `flag = false`.
585
+ assert filters.apply(batch).to_pydict()["n"] == [2]
586
+
587
+
588
+ def test_boolean_column_predicates_render_as_sql() -> None:
589
+ """They must reach SQL, not just the evaluator.
590
+
591
+ Left as a generic v2 expression a bare column renders no SQL at all, so a
592
+ SQL-backed worker loses pushdown on the commonest boolean predicate there
593
+ is -- and DuckDB does not re-apply what it pushed down, so that is a wrong
594
+ answer, not a slow one.
595
+ """
596
+ positive = deserialize_filters(_batch(_document([_predicate(_flag())])), output_schema=_BOOL_SCHEMA)
597
+ where, params = positive.to_sql()
598
+ assert where == '"flag" = ?'
599
+ assert params == [True]
600
+
601
+ negative = deserialize_filters(
602
+ _batch(_document([_predicate({"node": "not", "expression": _flag()})])),
603
+ output_schema=_BOOL_SCHEMA,
604
+ )
605
+ where, params = negative.to_sql()
606
+ assert where == '"flag" = ?'
607
+ assert params == [False]
608
+
609
+
610
+ def test_boolean_column_inside_a_conjunction_still_pushes_down() -> None:
611
+ """The shape that actually showed up: `WHERE other = x AND NOT flag`.
612
+
613
+ One unrenderable child used to cost the whole conjunction its pushdown.
614
+ """
615
+ document = _document(
616
+ [
617
+ _predicate(
618
+ {
619
+ "node": "and",
620
+ "children": [
621
+ {
622
+ "node": "comparison",
623
+ "op": "gt",
624
+ "left": _column(name="n", index=1),
625
+ "right": {"node": "literal", "value_ref": 0},
626
+ },
627
+ {"node": "not", "expression": _flag()},
628
+ ],
629
+ }
630
+ )
631
+ ]
632
+ )
633
+ filters = deserialize_filters(
634
+ _batch(document, (pa.field("value_0", pa.int64()), 2)),
635
+ output_schema=_BOOL_SCHEMA,
636
+ )
637
+ where, params = filters.to_sql()
638
+ assert where == '("n" > ? AND "flag" = ?)'
639
+ assert params == [2, False]
640
+
641
+
642
+ def test_an_unresolved_column_is_not_assumed_boolean() -> None:
643
+ """Without a bind schema the column's type is unknown -- refuse, don't guess."""
644
+ with pytest.raises(FilterDeserializationError, match="predicate root"):
645
+ deserialize_filters(_batch(_document([_predicate(_flag())])))
646
+
647
+
648
+ def test_a_non_boolean_column_is_still_refused() -> None:
649
+ """`WHERE n` where n is BIGINT is not a predicate."""
650
+ with pytest.raises(FilterDeserializationError, match="predicate root"):
651
+ deserialize_filters(
652
+ _batch(_document([_predicate(_column(name="n", index=1))])),
653
+ output_schema=_BOOL_SCHEMA,
654
+ )
655
+
656
+
657
+ def test_an_unrenderable_filter_raises_rather_than_vanishing() -> None:
658
+ """`to_sql()` must never quietly drop a predicate it cannot render.
659
+
660
+ DuckDB does not re-apply a filter it pushed into a table function, so the
661
+ worker's WHERE clause is the only thing standing between the caller and
662
+ rows the predicate excludes. A skipped filter is therefore a wrong answer,
663
+ not a slow one -- which is why this raises instead of degrading.
664
+ """
665
+ from vgi.table_filter_pushdown import FilterSQLUnsupportedError
666
+
667
+ # `n + 1 > 2` -- arithmetic has no legacy leaf shape and no SQL rendering.
668
+ document = _document(
669
+ [
670
+ _predicate(
671
+ {
672
+ "node": "comparison",
673
+ "op": "gt",
674
+ "left": {
675
+ "node": "arithmetic",
676
+ "op": "add",
677
+ "left": _column(name="n", index=1),
678
+ "right": {"node": "literal", "value_ref": 0},
679
+ },
680
+ "right": {"node": "literal", "value_ref": 1},
681
+ }
682
+ )
683
+ ]
684
+ )
685
+ filters = deserialize_filters(
686
+ _batch(
687
+ document,
688
+ (pa.field("value_0", pa.int64()), 1),
689
+ (pa.field("value_1", pa.int64()), 2),
690
+ ),
691
+ output_schema=_BOOL_SCHEMA,
692
+ )
693
+ # It evaluates correctly -- there is simply no SQL for it.
694
+ batch = pa.RecordBatch.from_pydict({"flag": [True, True, True], "n": [0, 2, 5]}, schema=_BOOL_SCHEMA)
695
+ assert filters.apply(batch).to_pydict()["n"] == [2, 5]
696
+
697
+ with pytest.raises(FilterSQLUnsupportedError, match="no SQL rendering"):
698
+ filters.to_sql()
@@ -2580,7 +2580,7 @@ requires-dist = [
2580
2580
 
2581
2581
  [[package]]
2582
2582
  name = "vgi-python"
2583
- version = "0.36.0"
2583
+ version = "0.36.2"
2584
2584
  source = { editable = "." }
2585
2585
  dependencies = [
2586
2586
  { name = "click" },
@@ -65,6 +65,7 @@ from vgi._test_fixtures.table.catalog_scans import (
65
65
  ProjectsScanFunction,
66
66
  )
67
67
  from vgi._test_fixtures.table.filters import (
68
+ BoolFilterEchoFunction,
68
69
  DictFilterEchoFunction,
69
70
  DynamicFilterEchoFunction,
70
71
  ExpressionFilterTestFunction,
@@ -216,6 +217,7 @@ __all__ = [
216
217
  "ConstantColumnsFunction",
217
218
  "CountryPartitionedSalesFunction",
218
219
  "DepartmentsScanFunction",
220
+ "BoolFilterEchoFunction",
219
221
  "DictFilterEchoFunction",
220
222
  "DisjointRangePartitionedFunction",
221
223
  "DoubleSequenceFunction",
@@ -191,6 +191,129 @@ class FilterEchoFunction(TableFunctionGenerator[FilterEchoFunctionArgs, FilterEc
191
191
  state.remaining -= size
192
192
 
193
193
 
194
+ # ============================================================================
195
+ # BoolFilterEchoFunction — a table function with a BOOLEAN column, so the
196
+ # bare-column predicate shapes (`WHERE flag`, `WHERE NOT flag`) can be driven
197
+ # end to end.
198
+ #
199
+ # filter_echo cannot cover these: its schema has no boolean column, so the
200
+ # predicate cannot even be written. The table-in-out `echo` path cannot either
201
+ # — DuckDB does not hand it a bare boolean column as a pushed predicate, so a
202
+ # test written there passes whether or not the worker can decode one. It takes
203
+ # a TABLE FUNCTION with a boolean column to see the shape at all, which is why
204
+ # a decoder that refused every one of them ("predicate root must resolve to
205
+ # BOOLEAN", vgi-python < 0.36.2) went unnoticed by a filter-pushdown suite of
206
+ # 348 files including one dedicated to booleans.
207
+ #
208
+ # `pushed_filters` echoes the SQL rendering, so this covers both halves: the
209
+ # decode (the rows are auto-applied and must be right) and `to_sql()` (a shape
210
+ # that parses but renders nothing would show up here as "(none)").
211
+ # ============================================================================
212
+
213
+
214
+ @dataclass(slots=True, frozen=True)
215
+ class _BoolFilterEchoArgs:
216
+ """Arguments for BoolFilterEchoFunction."""
217
+
218
+ count: Annotated[int, Arg(0, doc="Number of rows to generate", ge=0)]
219
+
220
+
221
+ @dataclass(kw_only=True)
222
+ class _BoolFilterEchoState(ArrowSerializableDataclass):
223
+ """Remaining rows plus the echoed SQL rendering of the pushed filters."""
224
+
225
+ remaining: int
226
+ current_index: int = 0
227
+ filter_str: str = "(none)"
228
+
229
+
230
+ @init_single_worker
231
+ @bind_fixed_schema
232
+ @_cardinality_from_count
233
+ class BoolFilterEchoFunction(TableFunctionGenerator[_BoolFilterEchoArgs, _BoolFilterEchoState]):
234
+ """Rows with a nullable BOOLEAN column, echoing the pushed-down filters.
235
+
236
+ SCHEMA
237
+ ------
238
+ Output: {"n": int64, "flag": bool, "pushed_filters": string}
239
+
240
+ ``flag`` cycles TRUE, FALSE, NULL so every predicate is exercised against
241
+ all three truth values -- the NULL row is what distinguishes ``WHERE flag``
242
+ from ``WHERE flag IS NOT FALSE``, and ``WHERE NOT flag`` from
243
+ ``WHERE flag IS NOT TRUE``.
244
+
245
+ Attributes:
246
+ FIXED_SCHEMA: The fixed Arrow output schema this function always produces.
247
+
248
+ """
249
+
250
+ class Meta:
251
+ """Metadata for BoolFilterEchoFunction."""
252
+
253
+ name = "bool_filter_echo"
254
+ description = "Rows with a nullable BOOLEAN column, echoing pushed-down filters"
255
+ categories = ["generator", "diagnostic"]
256
+ filter_pushdown = True
257
+ auto_apply_filters = True
258
+ projection_pushdown = True
259
+ examples = [
260
+ FunctionExample(
261
+ sql="SELECT * FROM bool_filter_echo(6) WHERE flag",
262
+ description="A boolean column is a predicate on its own",
263
+ ),
264
+ ]
265
+
266
+ FIXED_SCHEMA: ClassVar[pa.Schema] = schema({"n": pa.int64(), "flag": pa.bool_(), "pushed_filters": pa.utf8()})
267
+
268
+ @classmethod
269
+ def initial_state(cls, params: ProcessParams[_BoolFilterEchoArgs]) -> _BoolFilterEchoState:
270
+ """Create initial state, caching the SQL rendering of the pushed filters."""
271
+ assert params.init_call is not None
272
+ pf = params.init_call.pushdown_filters
273
+ filters = (
274
+ cls.pushdown_filters(
275
+ pf,
276
+ join_keys=params.init_call.join_keys,
277
+ output_schema=params.init_call.output_schema,
278
+ )
279
+ if pf is not None
280
+ else None
281
+ )
282
+ return _BoolFilterEchoState(
283
+ remaining=params.args.count,
284
+ filter_str=_format_pushed_filters(filters),
285
+ )
286
+
287
+ @classmethod
288
+ def process(
289
+ cls,
290
+ params: ProcessParams[_BoolFilterEchoArgs],
291
+ state: _BoolFilterEchoState,
292
+ out: OutputCollector,
293
+ ) -> None:
294
+ """Emit rows whose ``flag`` cycles TRUE, FALSE, NULL."""
295
+ if state.remaining <= 0:
296
+ out.finish()
297
+ return
298
+
299
+ n_values = list(range(state.current_index, state.current_index + state.remaining))
300
+ flags: list[bool | None] = [(True, False, None)[i % 3] for i in n_values]
301
+
302
+ out.emit(
303
+ pa.RecordBatch.from_pydict(
304
+ {
305
+ "n": n_values,
306
+ "flag": flags,
307
+ "pushed_filters": [state.filter_str] * len(n_values),
308
+ },
309
+ schema=params.output_schema,
310
+ )
311
+ )
312
+
313
+ state.current_index += state.remaining
314
+ state.remaining = 0
315
+
316
+
194
317
  # ============================================================================
195
318
  # ValuePruneFunction — exercises PushdownFilters.get_column_values('n'), the
196
319
  # partition-pruning idiom (resolve the discrete value set up front, fetch only
@@ -18,8 +18,8 @@ ways it goes right:
18
18
  shape that silently truncates a scan if a reader treats an empty split as EOS.
19
19
  * ``split_skewed(n)`` — one split ~100x the others, so greedy claiming can be
20
20
  told apart from static assignment.
21
- * ``split_many(n, splits := 1000)`` — far more splits than reader threads, which
22
- forces sequential re-init on a reused connection.
21
+ * ``split_many(n, splits)`` — far more splits than reader threads (pass them), which
22
+ forces sequential re-init on a reused connection. ``splits <= 0`` means 1000.
23
23
  * ``split_echo_filters(n)`` — reports the pushdown it saw *per split*, so a
24
24
  pushdown regression is visible without inferring it from row counts.
25
25
  """
@@ -322,7 +322,9 @@ class SplitManyFunction(_SplitBase):
322
322
 
323
323
  @classmethod
324
324
  def _split_count(cls, params: BindParams[SplitSequenceArgs]) -> int:
325
- return max(params.args.splits, 1000)
325
+ # Honour the caller's count, as every other SDK's twin does; a floor here
326
+ # made a test that asks for 64 splits pay for 1000 HTTP round trips.
327
+ return params.args.splits if params.args.splits > 0 else 1000
326
328
 
327
329
 
328
330
  @dataclass(frozen=True)
@@ -140,6 +140,7 @@ from vgi._test_fixtures.table import (
140
140
  RFF_SIMPLE_COLUMNS,
141
141
  RFF_STRUCT_COLUMNS,
142
142
  BatchIndexOverflowFunction,
143
+ BoolFilterEchoFunction,
143
144
  BrokenMissingPartitionValuesFunction,
144
145
  BrokenPartitionColumnAbsentFromBatchFunction,
145
146
  BrokenPartitionMinNeqMaxFunction,
@@ -486,6 +487,7 @@ _EXAMPLE_CATALOG = Catalog(
486
487
  # TableFunctionGenerator - generate output without input
487
488
  ConstantColumnsFunction,
488
489
  SlowCancellableFunction,
490
+ BoolFilterEchoFunction,
489
491
  FilterEchoFunction,
490
492
  FilterEchoPartitionedFunction,
491
493
  FilterEchoTableScanFunction,
@@ -518,7 +518,14 @@ class AggregateFunction[TState: StreamStateCodec](vgi.function.Function):
518
518
  """Compute the aggregate value for one output row.
519
519
 
520
520
  Args:
521
- rid: Partition-local row index being filled.
521
+ rid: Identifies the output row being filled; do not use it to
522
+ index the partition. Over the per-row ``aggregate_window``
523
+ RPC it is DuckDB's own ``rid``: the row's index within the
524
+ current output chunk (``0 <= rid < 2048``), not its row in
525
+ the partition. When the default :meth:`window_batch` calls
526
+ this, it passes the partition row index instead. Either way
527
+ ``subframes`` are partition-relative: use them to find the
528
+ rows to aggregate.
522
529
  subframes: Frame ranges ``[(begin, end), ...]`` — 1 for the default
523
530
  frame, 3 when ``EXCLUDE`` produces multiple subframes.
524
531
  partition: The cached partition data.
@@ -371,7 +371,10 @@ class AggregateSession:
371
371
 
372
372
  Args:
373
373
  partition_id: The partition previously shipped by :meth:`window_init`.
374
- rid: Row index within the partition of the output row being computed.
374
+ rid: Identifies the output row. The DuckDB extension sends DuckDB's
375
+ own per-row ``rid``, the row's index within the current output
376
+ chunk rather than its row in the partition; ``frames`` carry the
377
+ partition-relative bounds, and a worker must use those.
375
378
  frames: The row's subframes as ``(begin, end)`` half-open offsets
376
379
  into the partition. One entry normally; two or three for
377
380
  ``EXCLUDE TIES`` / ``EXCLUDE GROUP``.
@@ -740,11 +740,24 @@ class _Parser:
740
740
 
741
741
  @staticmethod
742
742
  def _is_boolean(expression: FilterExpression) -> bool:
743
- if isinstance(expression, Literal):
744
- return pa.types.is_boolean(expression.field.type)
745
- if isinstance(expression, (Comparison, BooleanExpression, Not, IsNull, In, RuntimeFilter)):
746
- return True
747
- return isinstance(expression, Call)
743
+ """Whether *expression* resolves to BOOLEAN.
744
+
745
+ Ask the type, never the node kind. The two agree for every node whose
746
+ type is structurally fixed -- a comparison is BOOLEAN whatever its
747
+ operands -- and that is exactly why enumerating kinds looked sufficient.
748
+ It is not: ``column_ref``, ``field_ref``, ``cast`` and ``arithmetic``
749
+ are BOOLEAN or not depending on a type resolved from elsewhere (the
750
+ bind output schema, or a parent expression), and the schema admits all
751
+ four as a predicate root -- ``coreExpression`` lists ``columnRef``
752
+ first. Enumerating kinds rejected the lot, so the idiomatic
753
+ ``WHERE flag`` / ``WHERE NOT flag`` -- which DuckDB pushes down as a
754
+ bare column reference rather than rewriting to ``flag = true`` -- was
755
+ refused as "predicate root must resolve to BOOLEAN" even though the
756
+ parser had already resolved the column to BOOLEAN and stored it on the
757
+ node.
758
+ """
759
+ data_type = expression_type(expression)
760
+ return data_type is not None and pa.types.is_boolean(data_type)
748
761
 
749
762
  def _payload(self, prefix: str, ref: object) -> tuple[pa.Field[Any], pa.Scalar[Any]]:
750
763
  index = _uint(ref, f"{prefix}_ref")
@@ -2887,7 +2887,10 @@ class AggregateWindowRequest(ArrowSerializableDataclass):
2887
2887
  execution_id: Identifier for one query execution, stable across the
2888
2888
  coordinator and any secondary workers; keys worker-owned state.
2889
2889
  partition_id: Identifier of the window partition this call addresses.
2890
- rid: Row index within the partition for the output row being computed.
2890
+ rid: Which output row this call fills, as DuckDB's per-row window callback
2891
+ reports it: the row's index within the current output chunk
2892
+ (``0 <= rid < STANDARD_VECTOR_SIZE``), NOT its row in the partition.
2893
+ The frames below are partition-relative; use them to find the rows.
2891
2894
  frame_starts: Subframe start offsets (inclusive) within the partition, one
2892
2895
  per subframe.
2893
2896
  frame_ends: Subframe end offsets (exclusive) within the partition, parallel
@@ -63,6 +63,9 @@ from vgi.filter_v2 import (
63
63
  from vgi.filter_v2 import (
64
64
  Literal as V2Literal,
65
65
  )
66
+ from vgi.filter_v2 import (
67
+ Not as V2Not,
68
+ )
66
69
  from vgi.filter_v2 import (
67
70
  RuntimeFilter as V2RuntimeFilter,
68
71
  )
@@ -72,6 +75,9 @@ from vgi.filter_v2 import (
72
75
  from vgi.filter_v2 import (
73
76
  expression_columns as v2_expression_columns,
74
77
  )
78
+ from vgi.filter_v2 import (
79
+ expression_type as v2_expression_type,
80
+ )
75
81
 
76
82
  if TYPE_CHECKING:
77
83
  from collections.abc import Callable, Iterator
@@ -207,6 +213,7 @@ __all__ = [
207
213
  "OrFilter",
208
214
  "StructFilter",
209
215
  "ExpressionFilter",
216
+ "FilterSQLUnsupportedError",
210
217
  "V2ExpressionFilter",
211
218
  # Expression node classes
212
219
  "ExpressionNode",
@@ -1638,6 +1645,22 @@ class PushdownFilters:
1638
1645
  # =============================================================================
1639
1646
 
1640
1647
 
1648
+ class FilterSQLUnsupportedError(ValueError):
1649
+ """A filter that `to_sql()` cannot render as a SQL fragment.
1650
+
1651
+ Raised rather than skipped, and that is the whole point: DuckDB does **not**
1652
+ re-apply a predicate it pushed into a table function, so a WHERE clause that
1653
+ silently omits one does not return the same rows more slowly -- it returns
1654
+ the wrong rows. Degrading quietly here would turn an unrenderable filter
1655
+ into a wrong answer with no error anywhere.
1656
+
1657
+ A worker that catches this has two honest options: evaluate the filters in
1658
+ memory instead (`PushdownFilters.apply()` / `evaluate()` handle every v2
1659
+ expression), or decline the scan. Subclasses `ValueError` so existing
1660
+ callers that catch the old error keep working.
1661
+ """
1662
+
1663
+
1641
1664
  def _filter_to_sql(
1642
1665
  f: Filter,
1643
1666
  quote: Callable[[str], str],
@@ -1713,8 +1736,19 @@ def _filter_to_sql(
1713
1736
  # Constants are embedded directly in the SQL string.
1714
1737
  return expr.to_sql(f.column_name), []
1715
1738
 
1739
+ case V2ExpressionFilter(expression=expression):
1740
+ # A v2 expression the legacy projection could not reduce to a leaf
1741
+ # shape (arithmetic, casts, extension calls, ...). It evaluates
1742
+ # correctly -- `V2ExpressionFilter.evaluate()` runs the v2 reference
1743
+ # evaluator -- there is simply no SQL rendering for it yet.
1744
+ raise FilterSQLUnsupportedError(
1745
+ f"filter on {f.column_name!r} is a v2 expression with no SQL rendering "
1746
+ f"({type(expression).__name__}); evaluate it with PushdownFilters.apply() "
1747
+ f"instead, or the scan will return rows the predicate excludes"
1748
+ )
1749
+
1716
1750
  case _:
1717
- raise ValueError(f"Unknown filter type: {type(f)}")
1751
+ raise FilterSQLUnsupportedError(f"Unknown filter type: {type(f)}")
1718
1752
 
1719
1753
 
1720
1754
  # =============================================================================
@@ -1787,6 +1821,48 @@ def _pushdown_from_v2_state(state: V2FilterState) -> PushdownFilters:
1787
1821
  )
1788
1822
 
1789
1823
 
1824
+ def _v2_boolean_column_view(expression: V2FilterExpression) -> Filter | None:
1825
+ """Project ``WHERE flag`` / ``WHERE NOT flag`` onto the legacy equality leaf.
1826
+
1827
+ DuckDB pushes a predicate that *is* a boolean column down as a bare
1828
+ ``column_ref``, not as ``flag = true``. Left as a generic v2 expression it
1829
+ becomes a `V2ExpressionFilter`, which evaluates fine but renders no SQL --
1830
+ so every SQL-backed worker loses pushdown on the most ordinary boolean
1831
+ predicate there is, and on the commonest shape of all, a conjunction with
1832
+ one, it loses pushdown for the whole conjunction.
1833
+
1834
+ The rewrite is exact rather than approximate, including under NULLs:
1835
+ ``WHERE flag`` keeps only TRUE (a NULL predicate is not satisfied), and so
1836
+ does ``flag = true``; ``WHERE NOT flag`` keeps only FALSE, and so does
1837
+ ``flag = false``. Three-valued logic makes the two pairs agree on every
1838
+ input, which is what lets this be a projection and not a semantic change.
1839
+
1840
+ Args:
1841
+ expression: A v2 expression that may be a bare boolean column or its
1842
+ negation.
1843
+
1844
+ Returns:
1845
+ The equivalent `ConstantFilter`, or None when *expression* is neither.
1846
+
1847
+ """
1848
+
1849
+ def boolean_column(node: V2FilterExpression) -> V2ColumnRef | None:
1850
+ if not isinstance(node, V2ColumnRef):
1851
+ return None
1852
+ node_type = v2_expression_type(node)
1853
+ # An unresolved column (no bind schema) is not known to be boolean, and
1854
+ # guessing here would rewrite a non-boolean predicate into `= true`.
1855
+ if node_type is None or not pa.types.is_boolean(node_type):
1856
+ return None
1857
+ return node
1858
+
1859
+ if ref := boolean_column(expression):
1860
+ return ConstantFilter(ref.column_name, ref.column_index, ComparisonOp.EQ, pa.scalar(True))
1861
+ if isinstance(expression, V2Not) and (ref := boolean_column(expression.expression)):
1862
+ return ConstantFilter(ref.column_name, ref.column_index, ComparisonOp.EQ, pa.scalar(False))
1863
+ return None
1864
+
1865
+
1790
1866
  def _v2_filter_view(expression: V2FilterExpression, context: EvaluationContext) -> Filter | None:
1791
1867
  """Project common v2 shapes into the longstanding convenience classes."""
1792
1868
  if isinstance(expression, V2Comparison):
@@ -1802,6 +1878,8 @@ def _v2_filter_view(expression: V2FilterExpression, context: EvaluationContext)
1802
1878
  }
1803
1879
  if op := mapping.get(expression.op):
1804
1880
  return ConstantFilter(operands[0].column_name, operands[0].column_index, op, operands[1].value)
1881
+ if boolean_leaf := _v2_boolean_column_view(expression):
1882
+ return boolean_leaf
1805
1883
  if isinstance(expression, V2IsNull) and isinstance(expression.expression, V2ColumnRef):
1806
1884
  ref = expression.expression
1807
1885
  if expression.negated:
File without changes
File without changes
File without changes
File without changes