vgi-python 0.8.0__py3-none-any.whl

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 (124) hide show
  1. vgi/__init__.py +152 -0
  2. vgi/_duckdb.py +62 -0
  3. vgi/_storage_profile.py +132 -0
  4. vgi/_test_fixtures/__init__.py +20 -0
  5. vgi/_test_fixtures/accumulate/__init__.py +19 -0
  6. vgi/_test_fixtures/accumulate/worker.py +762 -0
  7. vgi/_test_fixtures/aggregate/__init__.py +62 -0
  8. vgi/_test_fixtures/aggregate/_common.py +21 -0
  9. vgi/_test_fixtures/aggregate/basic.py +232 -0
  10. vgi/_test_fixtures/aggregate/dynamic.py +409 -0
  11. vgi/_test_fixtures/aggregate/generic.py +86 -0
  12. vgi/_test_fixtures/aggregate/listagg.py +71 -0
  13. vgi/_test_fixtures/aggregate/percentile.py +107 -0
  14. vgi/_test_fixtures/aggregate/streaming.py +192 -0
  15. vgi/_test_fixtures/aggregate/varargs.py +75 -0
  16. vgi/_test_fixtures/aggregate/window.py +380 -0
  17. vgi/_test_fixtures/attach_options.py +308 -0
  18. vgi/_test_fixtures/bad_protocol.py +62 -0
  19. vgi/_test_fixtures/cancellable.py +336 -0
  20. vgi/_test_fixtures/catalog.py +813 -0
  21. vgi/_test_fixtures/http_server.py +394 -0
  22. vgi/_test_fixtures/nest_tensor.py +614 -0
  23. vgi/_test_fixtures/orchard_catalog.py +47 -0
  24. vgi/_test_fixtures/projection_repro/__init__.py +6 -0
  25. vgi/_test_fixtures/projection_repro/worker.py +454 -0
  26. vgi/_test_fixtures/scalar/__init__.py +116 -0
  27. vgi/_test_fixtures/scalar/_common.py +69 -0
  28. vgi/_test_fixtures/scalar/arithmetic.py +321 -0
  29. vgi/_test_fixtures/scalar/binary.py +120 -0
  30. vgi/_test_fixtures/scalar/formatting.py +176 -0
  31. vgi/_test_fixtures/scalar/geo.py +300 -0
  32. vgi/_test_fixtures/scalar/null_handling.py +107 -0
  33. vgi/_test_fixtures/scalar/random_demo.py +171 -0
  34. vgi/_test_fixtures/scalar/settings_secrets.py +102 -0
  35. vgi/_test_fixtures/scalar/type_info.py +219 -0
  36. vgi/_test_fixtures/schema_reconcile/__init__.py +29 -0
  37. vgi/_test_fixtures/schema_reconcile/worker.py +653 -0
  38. vgi/_test_fixtures/simple_writable.py +793 -0
  39. vgi/_test_fixtures/table/__init__.py +221 -0
  40. vgi/_test_fixtures/table/_common.py +162 -0
  41. vgi/_test_fixtures/table/batch_index.py +283 -0
  42. vgi/_test_fixtures/table/batch_index_broken.py +200 -0
  43. vgi/_test_fixtures/table/catalog_scans.py +162 -0
  44. vgi/_test_fixtures/table/filters.py +1005 -0
  45. vgi/_test_fixtures/table/late_materialization.py +249 -0
  46. vgi/_test_fixtures/table/make_series.py +273 -0
  47. vgi/_test_fixtures/table/misc.py +499 -0
  48. vgi/_test_fixtures/table/order_modes.py +164 -0
  49. vgi/_test_fixtures/table/pairs.py +437 -0
  50. vgi/_test_fixtures/table/partition_columns.py +472 -0
  51. vgi/_test_fixtures/table/partition_columns_broken.py +304 -0
  52. vgi/_test_fixtures/table/profiling_example.py +195 -0
  53. vgi/_test_fixtures/table/required_filters.py +234 -0
  54. vgi/_test_fixtures/table/sequence.py +710 -0
  55. vgi/_test_fixtures/table/settings.py +426 -0
  56. vgi/_test_fixtures/table/transaction_storage.py +162 -0
  57. vgi/_test_fixtures/table/tt_pushdown.py +191 -0
  58. vgi/_test_fixtures/table/versioned.py +230 -0
  59. vgi/_test_fixtures/table_in_out.py +1392 -0
  60. vgi/_test_fixtures/versioned.py +155 -0
  61. vgi/_test_fixtures/versioned_tables.py +595 -0
  62. vgi/_test_fixtures/worker.py +1631 -0
  63. vgi/_test_fixtures/writable/__init__.py +8 -0
  64. vgi/_test_fixtures/writable/generic.py +236 -0
  65. vgi/_test_fixtures/writable/table.py +149 -0
  66. vgi/_test_fixtures/writable/worker.py +1148 -0
  67. vgi/aggregate_function.py +607 -0
  68. vgi/argument_spec.py +472 -0
  69. vgi/arguments.py +1747 -0
  70. vgi/auth.py +55 -0
  71. vgi/catalog/__init__.py +88 -0
  72. vgi/catalog/attach_option.py +206 -0
  73. vgi/catalog/catalog_interface.py +2767 -0
  74. vgi/catalog/descriptors.py +870 -0
  75. vgi/catalog/duckdb_statistics.py +377 -0
  76. vgi/catalog/secret_type.py +96 -0
  77. vgi/catalog/setting.py +253 -0
  78. vgi/catalog/storage.py +372 -0
  79. vgi/client/__init__.py +67 -0
  80. vgi/client/catalog_mixin.py +1251 -0
  81. vgi/client/cli.py +582 -0
  82. vgi/client/cli_catalog.py +182 -0
  83. vgi/client/cli_schema.py +270 -0
  84. vgi/client/cli_table.py +907 -0
  85. vgi/client/cli_transaction.py +97 -0
  86. vgi/client/cli_utils.py +441 -0
  87. vgi/client/cli_view.py +303 -0
  88. vgi/client/client.py +2183 -0
  89. vgi/exceptions.py +205 -0
  90. vgi/function.py +245 -0
  91. vgi/function_storage.py +1636 -0
  92. vgi/function_storage_azure_sql.py +922 -0
  93. vgi/function_storage_cf_do.py +740 -0
  94. vgi/http/__init__.py +25 -0
  95. vgi/http/demo_storage.py +212 -0
  96. vgi/http/worker_page.py +1252 -0
  97. vgi/invocation.py +154 -0
  98. vgi/logging_config.py +93 -0
  99. vgi/meta_worker.py +661 -0
  100. vgi/metadata.py +1403 -0
  101. vgi/otel.py +406 -0
  102. vgi/protocol.py +2418 -0
  103. vgi/protocol_version.txt +1 -0
  104. vgi/py.typed +0 -0
  105. vgi/scalar_function.py +1211 -0
  106. vgi/schema_utils.py +234 -0
  107. vgi/secret_protocol.py +124 -0
  108. vgi/secret_service.py +238 -0
  109. vgi/serve.py +769 -0
  110. vgi/table_buffering_function.py +443 -0
  111. vgi/table_filter_pushdown.py +1528 -0
  112. vgi/table_function.py +1130 -0
  113. vgi/table_in_out_function.py +383 -0
  114. vgi/transactor/__init__.py +24 -0
  115. vgi/transactor/_duckdb_compat.py +27 -0
  116. vgi/transactor/client.py +137 -0
  117. vgi/transactor/protocol.py +149 -0
  118. vgi/transactor/server.py +740 -0
  119. vgi/worker.py +4761 -0
  120. vgi_python-0.8.0.dist-info/METADATA +735 -0
  121. vgi_python-0.8.0.dist-info/RECORD +124 -0
  122. vgi_python-0.8.0.dist-info/WHEEL +4 -0
  123. vgi_python-0.8.0.dist-info/entry_points.txt +5 -0
  124. vgi_python-0.8.0.dist-info/licenses/LICENSE +134 -0
@@ -0,0 +1,219 @@
1
+ # Copyright 2025, 2026 Query Farm LLC - https://query.farm
2
+
3
+ """Type-introspection scalar fixtures (type_info_*, any_mixed_*, pair_type_*)."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import Annotated
8
+
9
+ import pyarrow as pa
10
+
11
+ from vgi.arguments import Param, Returns
12
+ from vgi.scalar_function import ScalarFunction
13
+
14
+
15
+ def _type_info_result(label: str, v: pa.Array) -> pa.StringArray: # type: ignore[type-arg]
16
+ """Shared compute logic for all type_info overloads."""
17
+ return pa.array([label if x is not None else None for x in v.to_pylist()], type=pa.string())
18
+
19
+
20
+ class TypeInfoInt32Function(ScalarFunction):
21
+ """Return type name for int32 input."""
22
+
23
+ class Meta:
24
+ """Function metadata."""
25
+
26
+ name = "type_info"
27
+ description = "Return type name for int32 input"
28
+
29
+ @classmethod
30
+ def compute(
31
+ cls,
32
+ v: Annotated[pa.Int32Array, Param(doc="Input value")],
33
+ ) -> Annotated[pa.StringArray, Returns()]:
34
+ """Return 'int32' for each row."""
35
+ return _type_info_result("int32", v)
36
+
37
+
38
+ class TypeInfoInt64Function(ScalarFunction):
39
+ """Return type name for int64 input."""
40
+
41
+ class Meta:
42
+ """Function metadata."""
43
+
44
+ name = "type_info"
45
+ description = "Return type name for int64 input"
46
+
47
+ @classmethod
48
+ def compute(
49
+ cls,
50
+ v: Annotated[pa.Int64Array, Param(doc="Input value")],
51
+ ) -> Annotated[pa.StringArray, Returns()]:
52
+ """Return 'int64' for each row."""
53
+ return _type_info_result("int64", v)
54
+
55
+
56
+ class TypeInfoUInt32Function(ScalarFunction):
57
+ """Return type name for uint32 input."""
58
+
59
+ class Meta:
60
+ """Function metadata."""
61
+
62
+ name = "type_info"
63
+ description = "Return type name for uint32 input"
64
+
65
+ @classmethod
66
+ def compute(
67
+ cls,
68
+ v: Annotated[pa.UInt32Array, Param(doc="Input value")],
69
+ ) -> Annotated[pa.StringArray, Returns()]:
70
+ """Return 'uint32' for each row."""
71
+ return _type_info_result("uint32", v)
72
+
73
+
74
+ class TypeInfoUInt64Function(ScalarFunction):
75
+ """Return type name for uint64 input."""
76
+
77
+ class Meta:
78
+ """Function metadata."""
79
+
80
+ name = "type_info"
81
+ description = "Return type name for uint64 input"
82
+
83
+ @classmethod
84
+ def compute(
85
+ cls,
86
+ v: Annotated[pa.UInt64Array, Param(doc="Input value")],
87
+ ) -> Annotated[pa.StringArray, Returns()]:
88
+ """Return 'uint64' for each row."""
89
+ return _type_info_result("uint64", v)
90
+
91
+
92
+ class TypeInfoStringFunction(ScalarFunction):
93
+ """Return type name for string input."""
94
+
95
+ class Meta:
96
+ """Function metadata."""
97
+
98
+ name = "type_info"
99
+ description = "Return type name for string input"
100
+
101
+ @classmethod
102
+ def compute(
103
+ cls,
104
+ v: Annotated[pa.StringArray, Param(doc="Input value")],
105
+ ) -> Annotated[pa.StringArray, Returns()]:
106
+ """Return 'varchar' for each row."""
107
+ return _type_info_result("varchar", v)
108
+
109
+
110
+ def _pair_type_result(label: str, a: pa.Array, b: pa.Array) -> pa.StringArray: # type: ignore[type-arg]
111
+ """Shared compute logic for all pair_type overloads."""
112
+ return pa.array(
113
+ [
114
+ label if (x is not None and y is not None) else None
115
+ for x, y in zip(a.to_pylist(), b.to_pylist(), strict=True)
116
+ ],
117
+ type=pa.string(),
118
+ )
119
+
120
+
121
+ class PairTypeIntIntFunction(ScalarFunction):
122
+ """Return 'int+int' for two int64 columns."""
123
+
124
+ class Meta:
125
+ """Function metadata."""
126
+
127
+ name = "pair_type"
128
+ description = "Return type pair name for int+int"
129
+
130
+ @classmethod
131
+ def compute(
132
+ cls,
133
+ a: Annotated[pa.Int64Array, Param(doc="First value")],
134
+ b: Annotated[pa.Int64Array, Param(doc="Second value")],
135
+ ) -> Annotated[pa.StringArray, Returns()]:
136
+ """Return 'int+int' for each row."""
137
+ return _pair_type_result("int+int", a, b)
138
+
139
+
140
+ class PairTypeStrStrFunction(ScalarFunction):
141
+ """Return 'str+str' for two string columns."""
142
+
143
+ class Meta:
144
+ """Function metadata."""
145
+
146
+ name = "pair_type"
147
+ description = "Return type pair name for str+str"
148
+
149
+ @classmethod
150
+ def compute(
151
+ cls,
152
+ a: Annotated[pa.StringArray, Param(doc="First value")],
153
+ b: Annotated[pa.StringArray, Param(doc="Second value")],
154
+ ) -> Annotated[pa.StringArray, Returns()]:
155
+ """Return 'str+str' for each row."""
156
+ return _pair_type_result("str+str", a, b)
157
+
158
+
159
+ class PairTypeIntStrFunction(ScalarFunction):
160
+ """Return 'int+str' for int64 + string columns."""
161
+
162
+ class Meta:
163
+ """Function metadata."""
164
+
165
+ name = "pair_type"
166
+ description = "Return type pair name for int+str"
167
+
168
+ @classmethod
169
+ def compute(
170
+ cls,
171
+ a: Annotated[pa.Int64Array, Param(doc="First value")],
172
+ b: Annotated[pa.StringArray, Param(doc="Second value")],
173
+ ) -> Annotated[pa.StringArray, Returns()]:
174
+ """Return 'int+str' for each row."""
175
+ return _pair_type_result("int+str", a, b)
176
+
177
+
178
+ class AnyMixedIntFunction(ScalarFunction):
179
+ """AnyArrow first param, Int64 second param."""
180
+
181
+ class Meta:
182
+ """Function metadata."""
183
+
184
+ name = "any_mixed"
185
+ description = "Any+int dispatch"
186
+
187
+ @classmethod
188
+ def compute(
189
+ cls,
190
+ a: Annotated[pa.Array, Param(doc="Any type value")], # type: ignore[type-arg]
191
+ b: Annotated[pa.Int64Array, Param(doc="Int value")],
192
+ ) -> Annotated[pa.StringArray, Returns()]:
193
+ """Return 'any+int: {b}' for each row."""
194
+ return pa.array(
195
+ [f"any+int: {y}" if y is not None else None for y in b.to_pylist()],
196
+ type=pa.string(),
197
+ )
198
+
199
+
200
+ class AnyMixedStrFunction(ScalarFunction):
201
+ """AnyArrow first param, String second param."""
202
+
203
+ class Meta:
204
+ """Function metadata."""
205
+
206
+ name = "any_mixed"
207
+ description = "Any+str dispatch"
208
+
209
+ @classmethod
210
+ def compute(
211
+ cls,
212
+ a: Annotated[pa.Array, Param(doc="Any type value")], # type: ignore[type-arg]
213
+ b: Annotated[pa.StringArray, Param(doc="String value")],
214
+ ) -> Annotated[pa.StringArray, Returns()]:
215
+ """Return 'any+str: {b}' for each row."""
216
+ return pa.array(
217
+ [f"any+str: {y}" if y is not None else None for y in b.to_pylist()],
218
+ type=pa.string(),
219
+ )
@@ -0,0 +1,29 @@
1
+ # Copyright 2025, 2026 Query Farm LLC - https://query.farm
2
+
3
+ """Self-contained schema-reconciliation test fixture.
4
+
5
+ Exposes one writable virtual table whose declared Arrow schema is
6
+ deliberately quirky:
7
+
8
+ - ``id`` int64 NOT NULL
9
+ - ``ts`` timestamp[ms, tz=UTC] NOT NULL
10
+ - ``nested`` struct{a int32 NOT NULL, b string, ts2 timestamp[ms, tz=UTC]} NOT NULL
11
+ - ``tags`` list<item: struct<k string NOT NULL, v binary>> NOT NULL
12
+ - ``rowid`` int64 NOT NULL (DuckDB pseudocolumn)
13
+
14
+ Every facet of this schema (top-level NOT NULL primitives, TZ-aware
15
+ millisecond timestamps, NOT NULL leaves inside structs and lists) is
16
+ something DuckDB's ``ArrowConverter::ToArrowSchema`` cannot preserve on
17
+ the round trip — so the C++ ``ReconcileBatchToSchema`` helper inside the
18
+ vgi extension must reshape/cast every batch DuckDB hands the worker.
19
+
20
+ The INSERT, UPDATE, and DELETE handlers assert on the exact Arrow schema
21
+ of each batch they receive. If reconciliation drops a flag or fails to
22
+ cast a timestamp, the test fixture raises a loud ``ValueError`` rather
23
+ than silently storing wrong data — which is exactly what we want a
24
+ regression to look like.
25
+
26
+ The fixture is dependency-free: no transactor, no DuckDB, no SQLite.
27
+ Storage is a process-local dict keyed by rowid. Concurrency is not a
28
+ concern (one worker process per test).
29
+ """