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.
- vgi/__init__.py +152 -0
- vgi/_duckdb.py +62 -0
- vgi/_storage_profile.py +132 -0
- vgi/_test_fixtures/__init__.py +20 -0
- vgi/_test_fixtures/accumulate/__init__.py +19 -0
- vgi/_test_fixtures/accumulate/worker.py +762 -0
- vgi/_test_fixtures/aggregate/__init__.py +62 -0
- vgi/_test_fixtures/aggregate/_common.py +21 -0
- vgi/_test_fixtures/aggregate/basic.py +232 -0
- vgi/_test_fixtures/aggregate/dynamic.py +409 -0
- vgi/_test_fixtures/aggregate/generic.py +86 -0
- vgi/_test_fixtures/aggregate/listagg.py +71 -0
- vgi/_test_fixtures/aggregate/percentile.py +107 -0
- vgi/_test_fixtures/aggregate/streaming.py +192 -0
- vgi/_test_fixtures/aggregate/varargs.py +75 -0
- vgi/_test_fixtures/aggregate/window.py +380 -0
- vgi/_test_fixtures/attach_options.py +308 -0
- vgi/_test_fixtures/bad_protocol.py +62 -0
- vgi/_test_fixtures/cancellable.py +336 -0
- vgi/_test_fixtures/catalog.py +813 -0
- vgi/_test_fixtures/http_server.py +394 -0
- vgi/_test_fixtures/nest_tensor.py +614 -0
- vgi/_test_fixtures/orchard_catalog.py +47 -0
- vgi/_test_fixtures/projection_repro/__init__.py +6 -0
- vgi/_test_fixtures/projection_repro/worker.py +454 -0
- vgi/_test_fixtures/scalar/__init__.py +116 -0
- vgi/_test_fixtures/scalar/_common.py +69 -0
- vgi/_test_fixtures/scalar/arithmetic.py +321 -0
- vgi/_test_fixtures/scalar/binary.py +120 -0
- vgi/_test_fixtures/scalar/formatting.py +176 -0
- vgi/_test_fixtures/scalar/geo.py +300 -0
- vgi/_test_fixtures/scalar/null_handling.py +107 -0
- vgi/_test_fixtures/scalar/random_demo.py +171 -0
- vgi/_test_fixtures/scalar/settings_secrets.py +102 -0
- vgi/_test_fixtures/scalar/type_info.py +219 -0
- vgi/_test_fixtures/schema_reconcile/__init__.py +29 -0
- vgi/_test_fixtures/schema_reconcile/worker.py +653 -0
- vgi/_test_fixtures/simple_writable.py +793 -0
- vgi/_test_fixtures/table/__init__.py +221 -0
- vgi/_test_fixtures/table/_common.py +162 -0
- vgi/_test_fixtures/table/batch_index.py +283 -0
- vgi/_test_fixtures/table/batch_index_broken.py +200 -0
- vgi/_test_fixtures/table/catalog_scans.py +162 -0
- vgi/_test_fixtures/table/filters.py +1005 -0
- vgi/_test_fixtures/table/late_materialization.py +249 -0
- vgi/_test_fixtures/table/make_series.py +273 -0
- vgi/_test_fixtures/table/misc.py +499 -0
- vgi/_test_fixtures/table/order_modes.py +164 -0
- vgi/_test_fixtures/table/pairs.py +437 -0
- vgi/_test_fixtures/table/partition_columns.py +472 -0
- vgi/_test_fixtures/table/partition_columns_broken.py +304 -0
- vgi/_test_fixtures/table/profiling_example.py +195 -0
- vgi/_test_fixtures/table/required_filters.py +234 -0
- vgi/_test_fixtures/table/sequence.py +710 -0
- vgi/_test_fixtures/table/settings.py +426 -0
- vgi/_test_fixtures/table/transaction_storage.py +162 -0
- vgi/_test_fixtures/table/tt_pushdown.py +191 -0
- vgi/_test_fixtures/table/versioned.py +230 -0
- vgi/_test_fixtures/table_in_out.py +1392 -0
- vgi/_test_fixtures/versioned.py +155 -0
- vgi/_test_fixtures/versioned_tables.py +595 -0
- vgi/_test_fixtures/worker.py +1631 -0
- vgi/_test_fixtures/writable/__init__.py +8 -0
- vgi/_test_fixtures/writable/generic.py +236 -0
- vgi/_test_fixtures/writable/table.py +149 -0
- vgi/_test_fixtures/writable/worker.py +1148 -0
- vgi/aggregate_function.py +607 -0
- vgi/argument_spec.py +472 -0
- vgi/arguments.py +1747 -0
- vgi/auth.py +55 -0
- vgi/catalog/__init__.py +88 -0
- vgi/catalog/attach_option.py +206 -0
- vgi/catalog/catalog_interface.py +2767 -0
- vgi/catalog/descriptors.py +870 -0
- vgi/catalog/duckdb_statistics.py +377 -0
- vgi/catalog/secret_type.py +96 -0
- vgi/catalog/setting.py +253 -0
- vgi/catalog/storage.py +372 -0
- vgi/client/__init__.py +67 -0
- vgi/client/catalog_mixin.py +1251 -0
- vgi/client/cli.py +582 -0
- vgi/client/cli_catalog.py +182 -0
- vgi/client/cli_schema.py +270 -0
- vgi/client/cli_table.py +907 -0
- vgi/client/cli_transaction.py +97 -0
- vgi/client/cli_utils.py +441 -0
- vgi/client/cli_view.py +303 -0
- vgi/client/client.py +2183 -0
- vgi/exceptions.py +205 -0
- vgi/function.py +245 -0
- vgi/function_storage.py +1636 -0
- vgi/function_storage_azure_sql.py +922 -0
- vgi/function_storage_cf_do.py +740 -0
- vgi/http/__init__.py +25 -0
- vgi/http/demo_storage.py +212 -0
- vgi/http/worker_page.py +1252 -0
- vgi/invocation.py +154 -0
- vgi/logging_config.py +93 -0
- vgi/meta_worker.py +661 -0
- vgi/metadata.py +1403 -0
- vgi/otel.py +406 -0
- vgi/protocol.py +2418 -0
- vgi/protocol_version.txt +1 -0
- vgi/py.typed +0 -0
- vgi/scalar_function.py +1211 -0
- vgi/schema_utils.py +234 -0
- vgi/secret_protocol.py +124 -0
- vgi/secret_service.py +238 -0
- vgi/serve.py +769 -0
- vgi/table_buffering_function.py +443 -0
- vgi/table_filter_pushdown.py +1528 -0
- vgi/table_function.py +1130 -0
- vgi/table_in_out_function.py +383 -0
- vgi/transactor/__init__.py +24 -0
- vgi/transactor/_duckdb_compat.py +27 -0
- vgi/transactor/client.py +137 -0
- vgi/transactor/protocol.py +149 -0
- vgi/transactor/server.py +740 -0
- vgi/worker.py +4761 -0
- vgi_python-0.8.0.dist-info/METADATA +735 -0
- vgi_python-0.8.0.dist-info/RECORD +124 -0
- vgi_python-0.8.0.dist-info/WHEEL +4 -0
- vgi_python-0.8.0.dist-info/entry_points.txt +5 -0
- vgi_python-0.8.0.dist-info/licenses/LICENSE +134 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Copyright 2025, 2026 Query Farm LLC - https://query.farm
|
|
2
|
+
|
|
3
|
+
"""Example VGI worker that validates data_version_spec / implementation_version.
|
|
4
|
+
|
|
5
|
+
Demonstrates the ATTACH-time versioning protocol end-to-end:
|
|
6
|
+
|
|
7
|
+
* :meth:`VersionedCatalog.catalogs` advertises per-catalog
|
|
8
|
+
``implementation_version`` and ``data_version_spec`` discovery metadata.
|
|
9
|
+
* :meth:`VersionedCatalog.catalog_attach` validates the client's requested
|
|
10
|
+
versions against :data:`SUPPORTED_DATA_VERSIONS` and
|
|
11
|
+
:data:`IMPLEMENTATION_VERSION`. Unsatisfiable requests raise ``ValueError``;
|
|
12
|
+
the client surfaces this as the ATTACH failure. Successful attaches set
|
|
13
|
+
``ctx.set_cookie("vgi_sticky", ...)`` so any upstream HTTP proxy can pin
|
|
14
|
+
the session.
|
|
15
|
+
* :meth:`VersionedCatalog.catalog_version` asserts that subsequent requests
|
|
16
|
+
echo the ``vgi_sticky`` cookie — this proves the extension's HTTP cookie
|
|
17
|
+
jar plumbs Set-Cookie → Cookie round trips. For subprocess transport
|
|
18
|
+
``ctx.cookies`` is empty and the check is skipped.
|
|
19
|
+
|
|
20
|
+
Registered as the ``vgi-fixture-versioned-worker`` entry point.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
import contextlib
|
|
26
|
+
import uuid
|
|
27
|
+
from typing import TYPE_CHECKING, Any
|
|
28
|
+
|
|
29
|
+
from vgi.catalog import (
|
|
30
|
+
AttachOpaqueData,
|
|
31
|
+
CatalogAttachResult,
|
|
32
|
+
CatalogInfo,
|
|
33
|
+
ReadOnlyCatalogInterface,
|
|
34
|
+
TransactionOpaqueData,
|
|
35
|
+
)
|
|
36
|
+
from vgi.catalog.descriptors import Catalog, Schema
|
|
37
|
+
from vgi.worker import Worker
|
|
38
|
+
|
|
39
|
+
if TYPE_CHECKING:
|
|
40
|
+
from vgi_rpc.rpc import CallContext
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
IMPLEMENTATION_VERSION = "1.0.0"
|
|
44
|
+
DATA_VERSION_SPEC = ">=1.0.0,<2.0.0"
|
|
45
|
+
SUPPORTED_DATA_VERSIONS: frozenset[str] = frozenset({"1.0.0", "1.1.0", "1.2.0"})
|
|
46
|
+
DEFAULT_DATA_VERSION = "1.2.0"
|
|
47
|
+
STICKY_COOKIE_NAME = "vgi_sticky"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
_VERSIONED_CATALOG = Catalog(
|
|
51
|
+
name="versioned",
|
|
52
|
+
default_schema="main",
|
|
53
|
+
comment="Example catalog demonstrating data_version_spec validation and cookie stickiness",
|
|
54
|
+
tags={},
|
|
55
|
+
schemas=[Schema(name="main", tables=[])],
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class VersionedCatalog(ReadOnlyCatalogInterface):
|
|
60
|
+
"""Catalog interface that validates versions and exercises HTTP cookies."""
|
|
61
|
+
|
|
62
|
+
catalog = _VERSIONED_CATALOG
|
|
63
|
+
|
|
64
|
+
def catalogs(self) -> list[CatalogInfo]:
|
|
65
|
+
"""Advertise a single catalog with its implementation version and data-version range."""
|
|
66
|
+
return [
|
|
67
|
+
CatalogInfo(
|
|
68
|
+
name=_VERSIONED_CATALOG.name,
|
|
69
|
+
implementation_version=IMPLEMENTATION_VERSION,
|
|
70
|
+
data_version_spec=DATA_VERSION_SPEC,
|
|
71
|
+
),
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
def catalog_attach(
|
|
75
|
+
self,
|
|
76
|
+
*,
|
|
77
|
+
name: str,
|
|
78
|
+
options: dict[str, Any],
|
|
79
|
+
data_version_spec: str | None,
|
|
80
|
+
implementation_version: str | None,
|
|
81
|
+
ctx: CallContext | None = None,
|
|
82
|
+
) -> CatalogAttachResult:
|
|
83
|
+
"""Validate requested versions and pin an HTTP session."""
|
|
84
|
+
del options
|
|
85
|
+
if name != _VERSIONED_CATALOG.name:
|
|
86
|
+
raise ValueError(f"Unknown catalog: {name!r}. Available: {_VERSIONED_CATALOG.name}")
|
|
87
|
+
|
|
88
|
+
if implementation_version is not None and implementation_version != IMPLEMENTATION_VERSION:
|
|
89
|
+
raise ValueError(
|
|
90
|
+
f"Unsupported implementation_version {implementation_version!r}; "
|
|
91
|
+
f"this worker serves {IMPLEMENTATION_VERSION!r}",
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
if data_version_spec is not None and data_version_spec not in SUPPORTED_DATA_VERSIONS:
|
|
95
|
+
# Exact-match only — production workers would parse the range; this
|
|
96
|
+
# example keeps the matcher trivial so failures are unambiguous.
|
|
97
|
+
raise ValueError(
|
|
98
|
+
f"Unsupported data_version_spec {data_version_spec!r}; "
|
|
99
|
+
f"this worker serves one of {sorted(SUPPORTED_DATA_VERSIONS)}",
|
|
100
|
+
)
|
|
101
|
+
resolved_data_version = data_version_spec if data_version_spec is not None else DEFAULT_DATA_VERSION
|
|
102
|
+
|
|
103
|
+
# Pin the session for HTTP routing. On subprocess transport set_cookie
|
|
104
|
+
# raises RuntimeError — ignore it silently so the same worker works
|
|
105
|
+
# under both transports.
|
|
106
|
+
if ctx is not None:
|
|
107
|
+
with contextlib.suppress(RuntimeError):
|
|
108
|
+
ctx.set_cookie(STICKY_COOKIE_NAME, uuid.uuid4().hex)
|
|
109
|
+
|
|
110
|
+
return CatalogAttachResult(
|
|
111
|
+
attach_opaque_data=AttachOpaqueData(uuid.uuid4().bytes),
|
|
112
|
+
supports_transactions=False,
|
|
113
|
+
supports_time_travel=False,
|
|
114
|
+
catalog_version_frozen=True,
|
|
115
|
+
catalog_version=1,
|
|
116
|
+
attach_opaque_data_required=False,
|
|
117
|
+
default_schema=_VERSIONED_CATALOG.default_schema,
|
|
118
|
+
comment=_VERSIONED_CATALOG.comment,
|
|
119
|
+
tags=dict(_VERSIONED_CATALOG.tags),
|
|
120
|
+
resolved_data_version=resolved_data_version,
|
|
121
|
+
resolved_implementation_version=IMPLEMENTATION_VERSION,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
def catalog_version(
|
|
125
|
+
self,
|
|
126
|
+
*,
|
|
127
|
+
attach_opaque_data: AttachOpaqueData,
|
|
128
|
+
transaction_opaque_data: TransactionOpaqueData | None,
|
|
129
|
+
ctx: CallContext | None = None,
|
|
130
|
+
) -> int:
|
|
131
|
+
"""Assert that the routing cookie we set at ATTACH is echoed back."""
|
|
132
|
+
del attach_opaque_data, transaction_opaque_data
|
|
133
|
+
if ctx is not None and ctx.cookies and STICKY_COOKIE_NAME not in ctx.cookies:
|
|
134
|
+
# Over HTTP, missing the sticky cookie means the client's cookie jar
|
|
135
|
+
# is broken. Bail loudly so the test catches the regression.
|
|
136
|
+
raise ValueError(
|
|
137
|
+
f"expected cookie {STICKY_COOKIE_NAME!r} on follow-up request; got {sorted(ctx.cookies)}",
|
|
138
|
+
)
|
|
139
|
+
return 1
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
class VersionedWorker(Worker):
|
|
143
|
+
"""Worker exposing :class:`VersionedCatalog`."""
|
|
144
|
+
|
|
145
|
+
catalog_interface = VersionedCatalog
|
|
146
|
+
catalog = _VERSIONED_CATALOG
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def main() -> None:
|
|
150
|
+
"""Run the versioned-example worker process."""
|
|
151
|
+
VersionedWorker.main()
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
if __name__ == "__main__":
|
|
155
|
+
main()
|