vgi-python 0.48.1__py3-none-any.whl → 0.49.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/_test_fixtures/bad_protocol.py +10 -7
- vgi/_test_fixtures/table/splits.py +65 -7
- vgi/protocol.py +144 -21
- vgi/protocol_version.txt +1 -1
- {vgi_python-0.48.1.dist-info → vgi_python-0.49.0.dist-info}/METADATA +2 -1
- {vgi_python-0.48.1.dist-info → vgi_python-0.49.0.dist-info}/RECORD +9 -9
- {vgi_python-0.48.1.dist-info → vgi_python-0.49.0.dist-info}/WHEEL +0 -0
- {vgi_python-0.48.1.dist-info → vgi_python-0.49.0.dist-info}/entry_points.txt +0 -0
- {vgi_python-0.48.1.dist-info → vgi_python-0.49.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -15,10 +15,11 @@ own ``__dict__``, not an inherited attribute — so the redeclaration on this
|
|
|
15
15
|
subclass's body is what takes effect.
|
|
16
16
|
|
|
17
17
|
A normal client (Python ``Client`` or the C++ extension) declares
|
|
18
|
-
``protocol_version = "1.0
|
|
19
|
-
worker
|
|
20
|
-
boundary raises ``ProtocolVersionError`` with a directional
|
|
21
|
-
|
|
18
|
+
``protocol_version = "3.1.0"`` and sends it on every request. Because this
|
|
19
|
+
worker defaults to ``"99.0.0"``, the major/minor versions differ and the
|
|
20
|
+
dispatch boundary raises ``ProtocolVersionError`` with a directional upgrade
|
|
21
|
+
message that round-trips back to the caller. Tests may override the worker to
|
|
22
|
+
``"3.0.0"`` to exercise the real previous-minor rollout boundary.
|
|
22
23
|
|
|
23
24
|
Otherwise this is a drop-in replacement for ``vgi-fixture-worker``: it
|
|
24
25
|
inherits every function and the catalog from :class:`ExampleWorker`, so any
|
|
@@ -30,15 +31,17 @@ Registered as the ``vgi-fixture-bad-protocol-worker`` entry point.
|
|
|
30
31
|
|
|
31
32
|
from __future__ import annotations
|
|
32
33
|
|
|
34
|
+
import os
|
|
33
35
|
from typing import ClassVar
|
|
34
36
|
|
|
35
37
|
from vgi._test_fixtures.worker import ExampleWorker
|
|
36
38
|
from vgi.protocol import VgiProtocol
|
|
37
39
|
|
|
38
|
-
# A major-version bump guarantees a mismatch against any real client
|
|
39
|
-
#
|
|
40
|
+
# A major-version bump guarantees a mismatch against any real client. Tests can
|
|
41
|
+
# override this with a previous minor (for example 3.0.0 versus 3.1.0) to prove
|
|
42
|
+
# that the production rolling-upgrade boundary is enforced too. Declared on
|
|
40
43
|
# this class body so ``vars(BadProtocol)["protocol_version"]`` resolves to it.
|
|
41
|
-
BAD_PROTOCOL_VERSION = "99.0.0"
|
|
44
|
+
BAD_PROTOCOL_VERSION = os.environ.get("VGI_BAD_PROTOCOL_VERSION", "99.0.0")
|
|
42
45
|
|
|
43
46
|
|
|
44
47
|
class BadProtocol(VgiProtocol):
|
|
@@ -37,7 +37,18 @@ from vgi.arguments import Arg
|
|
|
37
37
|
from vgi.cache_control import CacheControl
|
|
38
38
|
from vgi.filter_v2 import replaying_accepted_state
|
|
39
39
|
from vgi.metadata import FunctionExample, PartitionKind
|
|
40
|
-
from vgi.protocol import
|
|
40
|
+
from vgi.protocol import (
|
|
41
|
+
FieldPath,
|
|
42
|
+
KeyGrouping,
|
|
43
|
+
OrderByDirection,
|
|
44
|
+
OrderByNullOrder,
|
|
45
|
+
PlanResponse,
|
|
46
|
+
RangeKey,
|
|
47
|
+
RangePartitioning,
|
|
48
|
+
ScanSplit,
|
|
49
|
+
TransformSpec,
|
|
50
|
+
VgiOutputCollector,
|
|
51
|
+
)
|
|
41
52
|
from vgi.schema_utils import partition_field, schema
|
|
42
53
|
|
|
43
54
|
if TYPE_CHECKING:
|
|
@@ -858,6 +869,14 @@ class SplitPartitionArgs:
|
|
|
858
869
|
"""Arguments for the partitioned split fixture."""
|
|
859
870
|
|
|
860
871
|
rows_per_country: Annotated[int, Arg("rows_per_country", default=5, doc="Rows in each partition", ge=0)]
|
|
872
|
+
key_mode: Annotated[
|
|
873
|
+
str,
|
|
874
|
+
Arg(
|
|
875
|
+
"key_mode",
|
|
876
|
+
default="valid",
|
|
877
|
+
doc="Test-only Protocol 3.1 key shape: valid, missing, two_rows, or wrong_type",
|
|
878
|
+
),
|
|
879
|
+
]
|
|
861
880
|
|
|
862
881
|
|
|
863
882
|
@bind_fixed_schema
|
|
@@ -889,17 +908,50 @@ class SplitPartitionedFunction(TableFunctionGenerator[SplitPartitionArgs, PartSp
|
|
|
889
908
|
|
|
890
909
|
@classmethod
|
|
891
910
|
def on_plan(cls, params: BindParams[SplitPartitionArgs], request: Any) -> PlanResponse:
|
|
892
|
-
"""One split per country,
|
|
911
|
+
"""One split per country, carrying its exact protocol-3.1 key."""
|
|
912
|
+
def key_value(country: str) -> pa.RecordBatch | None:
|
|
913
|
+
if params.args.key_mode == "missing":
|
|
914
|
+
return None
|
|
915
|
+
if params.args.key_mode == "two_rows":
|
|
916
|
+
return pa.RecordBatch.from_pydict({"country": [country, country]})
|
|
917
|
+
if params.args.key_mode == "wrong_type":
|
|
918
|
+
return pa.RecordBatch.from_pydict({"country": [1]})
|
|
919
|
+
if params.args.key_mode != "valid":
|
|
920
|
+
msg = f"unknown split_partitioned key_mode: {params.args.key_mode}"
|
|
921
|
+
raise ValueError(msg)
|
|
922
|
+
return pa.RecordBatch.from_pydict({"country": [country]})
|
|
923
|
+
|
|
924
|
+
identity = TransformSpec(
|
|
925
|
+
id="vgi.identity/1",
|
|
926
|
+
inputs=[FieldPath(components=["country"]).serialize_to_bytes()],
|
|
927
|
+
).serialize_to_bytes()
|
|
928
|
+
key_grouping = KeyGrouping(keys=[identity]).serialize_to_bytes()
|
|
929
|
+
range_key = RangeKey(
|
|
930
|
+
transform=identity,
|
|
931
|
+
direction=OrderByDirection.ASC,
|
|
932
|
+
null_order=OrderByNullOrder.NULLS_LAST,
|
|
933
|
+
).serialize_to_bytes()
|
|
934
|
+
range_partitioning = RangePartitioning(
|
|
935
|
+
keys=[range_key],
|
|
936
|
+
# Equality belongs to the range on the right, so these boundaries
|
|
937
|
+
# isolate BR, DE, JP and US into ranges 0 through 3 respectively.
|
|
938
|
+
split_points=pa.RecordBatch.from_pydict({"country": ["DE", "JP", "US"]}),
|
|
939
|
+
).serialize_to_bytes()
|
|
940
|
+
range_index = {"BR": 0, "DE": 1, "JP": 2, "US": 3}
|
|
893
941
|
return PlanResponse(
|
|
894
942
|
splits=[
|
|
895
943
|
ScanSplit(
|
|
896
944
|
payload=country.encode("ascii"),
|
|
897
945
|
estimated_rows=params.args.rows_per_country,
|
|
898
946
|
rows_exact=True,
|
|
947
|
+
key_value=key_value(country),
|
|
948
|
+
range_index=range_index[country],
|
|
899
949
|
)
|
|
900
950
|
for country in _PART_COUNTRIES
|
|
901
951
|
],
|
|
902
952
|
estimated_total_splits=len(_PART_COUNTRIES),
|
|
953
|
+
key_grouping=key_grouping,
|
|
954
|
+
range_partitioning=range_partitioning,
|
|
903
955
|
)
|
|
904
956
|
|
|
905
957
|
@classmethod
|
|
@@ -940,12 +992,18 @@ class SplitPartitionedFunction(TableFunctionGenerator[SplitPartitionArgs, PartSp
|
|
|
940
992
|
# assertion unchanged — the file could not detect the exact failure
|
|
941
993
|
# it exists to detect.
|
|
942
994
|
base = _PART_COUNTRIES.index(country) * 100
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
schema=_PART_ROW,
|
|
947
|
-
)
|
|
995
|
+
batch = pa.RecordBatch.from_pydict(
|
|
996
|
+
{"country": [country] * rows, "sales": [base + i + 1 for i in range(rows)]},
|
|
997
|
+
schema=_PART_ROW,
|
|
948
998
|
)
|
|
999
|
+
# Bypass the legacy per-batch vgi_partition_values metadata. The
|
|
1000
|
+
# DuckDB adapter must source this split's SINGLE_VALUE partition
|
|
1001
|
+
# tuple from ScanSplit.key_value; if it falls back, the existing
|
|
1002
|
+
# C++ missing-metadata check makes this integration test fail.
|
|
1003
|
+
inner = out
|
|
1004
|
+
while hasattr(inner, "_inner"):
|
|
1005
|
+
inner = inner._inner
|
|
1006
|
+
inner.emit(batch)
|
|
949
1007
|
return
|
|
950
1008
|
|
|
951
1009
|
|
vgi/protocol.py
CHANGED
|
@@ -101,6 +101,8 @@ from vgi.typed_values import TypedValueBatch
|
|
|
101
101
|
|
|
102
102
|
__all__ = [
|
|
103
103
|
"BindRequest",
|
|
104
|
+
"OrderByDirection",
|
|
105
|
+
"OrderByNullOrder",
|
|
104
106
|
"TableFunctionProjectionRequest",
|
|
105
107
|
"TableFunctionProjectionResponse",
|
|
106
108
|
"ClientCapabilities",
|
|
@@ -511,20 +513,12 @@ class TableFunctionStatisticsRequest(ArrowSerializableDataclass):
|
|
|
511
513
|
|
|
512
514
|
@dataclass(frozen=True, slots=True, kw_only=True)
|
|
513
515
|
class PartitionTransform(ArrowSerializableDataclass):
|
|
514
|
-
"""
|
|
515
|
-
|
|
516
|
-
Spark's ``KeyGroupedPartitioning`` needs the transform *expression*, not just the
|
|
517
|
-
partition values: ``country=US`` does not say whether partitions are
|
|
518
|
-
``identity(country)`` or ``bucket(16, user_id)``. This is Iceberg's vocabulary,
|
|
519
|
-
which ``Expressions.bucket(n, col)`` maps onto directly.
|
|
520
|
-
|
|
521
|
-
Attributes:
|
|
522
|
-
column: Name of the partition column in the function's output schema.
|
|
523
|
-
transform: Transform kind — one of ``identity``, ``bucket``, ``truncate``,
|
|
524
|
-
``year``, ``month``, ``day``, ``hour``.
|
|
525
|
-
param: Bucket count for ``bucket`` / width for ``truncate``; ``None`` for
|
|
526
|
-
the rest.
|
|
516
|
+
"""Deprecated protocol-2 partition-transform description.
|
|
527
517
|
|
|
518
|
+
Protocol 3.1 producers should use :class:`TransformSpec` inside
|
|
519
|
+
:class:`KeyGrouping` or :class:`RangePartitioning`. This record remains
|
|
520
|
+
available so existing producers can continue to populate the deprecated
|
|
521
|
+
:attr:`PlanResponse.partitioning` field while they migrate.
|
|
528
522
|
"""
|
|
529
523
|
|
|
530
524
|
column: str
|
|
@@ -532,6 +526,122 @@ class PartitionTransform(ArrowSerializableDataclass):
|
|
|
532
526
|
param: int | None = None
|
|
533
527
|
|
|
534
528
|
|
|
529
|
+
@dataclass(frozen=True, slots=True, kw_only=True)
|
|
530
|
+
class FieldPath(ArrowSerializableDataclass):
|
|
531
|
+
"""One raw, component-preserving field reference used by a transform."""
|
|
532
|
+
|
|
533
|
+
components: list[str]
|
|
534
|
+
|
|
535
|
+
def __post_init__(self) -> None:
|
|
536
|
+
if not self.components or any(not component for component in self.components):
|
|
537
|
+
raise ValueError("field path must contain only non-empty components")
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
@dataclass(frozen=True, slots=True, kw_only=True)
|
|
541
|
+
class TransformSpec(ArrowSerializableDataclass):
|
|
542
|
+
"""A versioned, registry-defined partition transform.
|
|
543
|
+
|
|
544
|
+
``id`` identifies normative semantics (for example ``vgi.identity/1`` or
|
|
545
|
+
``iceberg.bucket/1``). ``inputs`` contains serialized :class:`FieldPath`
|
|
546
|
+
records. ``parameters`` is either absent or a one-row Arrow batch, which
|
|
547
|
+
permits any number of named, typed parameters without admitting arbitrary
|
|
548
|
+
recursive expressions.
|
|
549
|
+
"""
|
|
550
|
+
|
|
551
|
+
id: str
|
|
552
|
+
inputs: Annotated[list[bytes], ArrowType(pa.list_(pa.binary()))] = field(default_factory=list)
|
|
553
|
+
parameters: Annotated[pa.RecordBatch | None, ArrowType(pa.binary())] = None
|
|
554
|
+
|
|
555
|
+
def __post_init__(self) -> None:
|
|
556
|
+
if not self.id or "/" not in self.id:
|
|
557
|
+
raise ValueError("transform id must be a non-empty, versioned name")
|
|
558
|
+
if not self.inputs:
|
|
559
|
+
raise ValueError("transform must reference at least one input field")
|
|
560
|
+
for value in self.inputs:
|
|
561
|
+
FieldPath.deserialize_from_bytes(value)
|
|
562
|
+
if self.parameters is not None and self.parameters.num_rows != 1:
|
|
563
|
+
raise ValueError("transform parameters must contain exactly one row")
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
@dataclass(frozen=True, slots=True, kw_only=True)
|
|
567
|
+
class KeyGrouping(ArrowSerializableDataclass):
|
|
568
|
+
"""Transforms whose exact result tuple is constant within every split."""
|
|
569
|
+
|
|
570
|
+
keys: Annotated[list[bytes], ArrowType(pa.list_(pa.binary()))]
|
|
571
|
+
|
|
572
|
+
def __post_init__(self) -> None:
|
|
573
|
+
if not self.keys:
|
|
574
|
+
raise ValueError("key grouping must contain at least one transform")
|
|
575
|
+
for value in self.keys:
|
|
576
|
+
TransformSpec.deserialize_from_bytes(value)
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
@dataclass(frozen=True, slots=True, kw_only=True)
|
|
580
|
+
class RangeKey(ArrowSerializableDataclass):
|
|
581
|
+
"""One transform and comparator component of a range key."""
|
|
582
|
+
|
|
583
|
+
transform: Annotated[bytes, ArrowType(pa.binary())]
|
|
584
|
+
direction: OrderByDirection
|
|
585
|
+
null_order: OrderByNullOrder
|
|
586
|
+
|
|
587
|
+
def __post_init__(self) -> None:
|
|
588
|
+
TransformSpec.deserialize_from_bytes(self.transform)
|
|
589
|
+
OrderByDirection(self.direction)
|
|
590
|
+
OrderByNullOrder(self.null_order)
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
@dataclass(frozen=True, slots=True, kw_only=True)
|
|
594
|
+
class RangePartitioning(ArrowSerializableDataclass):
|
|
595
|
+
"""Exact half-open range distribution shared by all splits in a plan.
|
|
596
|
+
|
|
597
|
+
``N`` split-point rows define ``N + 1`` ranges. Values equal to point ``i``
|
|
598
|
+
belong to range ``i + 1``. Each split names its range with
|
|
599
|
+
:attr:`ScanSplit.range_index`.
|
|
600
|
+
"""
|
|
601
|
+
|
|
602
|
+
keys: Annotated[list[bytes], ArrowType(pa.list_(pa.binary()))]
|
|
603
|
+
split_points: Annotated[pa.RecordBatch, ArrowType(pa.binary())]
|
|
604
|
+
|
|
605
|
+
def __post_init__(self) -> None:
|
|
606
|
+
if not self.keys:
|
|
607
|
+
raise ValueError("range partitioning must contain at least one key")
|
|
608
|
+
decoded_keys = [RangeKey.deserialize_from_bytes(value) for value in self.keys]
|
|
609
|
+
if self.split_points.num_columns != len(self.keys):
|
|
610
|
+
raise ValueError("range split-point width must match the range key width")
|
|
611
|
+
for row in range(1, self.split_points.num_rows):
|
|
612
|
+
if _compare_range_rows(self.split_points, row - 1, row, decoded_keys) >= 0:
|
|
613
|
+
raise ValueError("range split points must be strictly ordered by the declared comparator")
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
def _compare_range_rows(
|
|
617
|
+
batch: pa.RecordBatch,
|
|
618
|
+
left_row: int,
|
|
619
|
+
right_row: int,
|
|
620
|
+
keys: list[RangeKey],
|
|
621
|
+
) -> int:
|
|
622
|
+
"""Compare two split-point rows using the protocol's lexicographic order."""
|
|
623
|
+
for column, key in zip(batch.columns, keys, strict=True):
|
|
624
|
+
left = column[left_row]
|
|
625
|
+
right = column[right_row]
|
|
626
|
+
if not left.is_valid or not right.is_valid:
|
|
627
|
+
if not left.is_valid and not right.is_valid:
|
|
628
|
+
continue
|
|
629
|
+
left_first = key.null_order == OrderByNullOrder.NULLS_FIRST
|
|
630
|
+
return (-1 if left_first else 1) if not left.is_valid else (1 if left_first else -1)
|
|
631
|
+
try:
|
|
632
|
+
if pc.equal(left, right).as_py() is True:
|
|
633
|
+
continue
|
|
634
|
+
less = pc.less(left, right).as_py() is True
|
|
635
|
+
greater = pc.greater(left, right).as_py() is True
|
|
636
|
+
except (pa.ArrowInvalid, pa.ArrowNotImplementedError, TypeError) as error:
|
|
637
|
+
raise ValueError("range split points contain values that cannot be ordered") from error
|
|
638
|
+
if not less and not greater:
|
|
639
|
+
raise ValueError("range split points contain unordered values")
|
|
640
|
+
result = -1 if less else 1
|
|
641
|
+
return -result if key.direction == OrderByDirection.DESC else result
|
|
642
|
+
return 0
|
|
643
|
+
|
|
644
|
+
|
|
535
645
|
@dataclass(frozen=True, slots=True, kw_only=True)
|
|
536
646
|
class SortField(ArrowSerializableDataclass):
|
|
537
647
|
"""Ordering guaranteed *within* each split.
|
|
@@ -578,10 +688,15 @@ class ScanSplit(ArrowSerializableDataclass):
|
|
|
578
688
|
estimated_bytes: Byte estimate. Load-bearing for engines that bin-pack
|
|
579
689
|
(DataFusion weight, Trino SplitWeight); ``None`` degrades them to
|
|
580
690
|
round-robin by count. DuckDB claims greedily and does not need it.
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
691
|
+
key_value: One-row Arrow batch aligned with ``PlanResponse.key_grouping``.
|
|
692
|
+
Every row emitted by this split evaluates to this exact transformed
|
|
693
|
+
tuple under null-safe equality.
|
|
694
|
+
range_index: Zero-based range owned by this split when
|
|
695
|
+
``PlanResponse.range_partitioning`` is present.
|
|
696
|
+
column_bounds: 2-row (min, max) Arrow batch used only for containment and
|
|
697
|
+
pruning. It is not an exact grouping key or a range assignment.
|
|
698
|
+
partition_bounds: Deprecated compatibility spelling for older protocol-2
|
|
699
|
+
producers. New protocol-3 producers use ``column_bounds``.
|
|
585
700
|
column_statistics: Per-column statistics blob (same encoding as
|
|
586
701
|
``table_function_statistics``).
|
|
587
702
|
location_ids: Indices into ``PlanResponse.locations`` naming hosts where
|
|
@@ -603,6 +718,9 @@ class ScanSplit(ArrowSerializableDataclass):
|
|
|
603
718
|
estimated_rows: int | None = None
|
|
604
719
|
rows_exact: bool = False
|
|
605
720
|
estimated_bytes: int | None = None
|
|
721
|
+
key_value: Annotated[pa.RecordBatch | None, ArrowType(pa.binary())] = None
|
|
722
|
+
range_index: int | None = None
|
|
723
|
+
column_bounds: Annotated[pa.RecordBatch | None, ArrowType(pa.binary())] = None
|
|
606
724
|
partition_bounds: Annotated[pa.RecordBatch | None, ArrowType(pa.binary())] = None
|
|
607
725
|
column_statistics: Annotated[bytes | None, ArrowType(pa.binary())] = None
|
|
608
726
|
location_ids: list[int] | None = None
|
|
@@ -720,9 +838,12 @@ class PlanResponse(ArrowSerializableDataclass):
|
|
|
720
838
|
``transaction`` (reuses the CACHE_SCOPE_* vocabulary). Transaction-scoped
|
|
721
839
|
plans are not cacheable and are not redeemable after commit or rollback.
|
|
722
840
|
locations: Hoisted host list; splits index into it via ``location_ids``.
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
841
|
+
key_grouping: Serialized :class:`KeyGrouping` when each split has one
|
|
842
|
+
exact transformed key tuple.
|
|
843
|
+
range_partitioning: Serialized :class:`RangePartitioning` containing the
|
|
844
|
+
exact ordered split points and comparator.
|
|
845
|
+
partitioning: Deprecated protocol-2 partition-transform list. Protocol-3
|
|
846
|
+
producers use ``key_grouping`` and/or ``range_partitioning``.
|
|
726
847
|
sort_order: Serialized [`SortField`][] records describing ordering *within*
|
|
727
848
|
each split.
|
|
728
849
|
cache_max_age_seconds: How long this plan may be reused. Ignored for
|
|
@@ -757,6 +878,8 @@ class PlanResponse(ArrowSerializableDataclass):
|
|
|
757
878
|
scope: str = CACHE_SCOPE_CATALOG
|
|
758
879
|
|
|
759
880
|
locations: list[str] | None = None
|
|
881
|
+
key_grouping: Annotated[bytes | None, ArrowType(pa.binary())] = None
|
|
882
|
+
range_partitioning: Annotated[bytes | None, ArrowType(pa.binary())] = None
|
|
760
883
|
partitioning: Annotated[list[bytes] | None, ArrowType(pa.list_(pa.binary()))] = None
|
|
761
884
|
sort_order: Annotated[list[bytes] | None, ArrowType(pa.list_(pa.binary()))] = None
|
|
762
885
|
|
|
@@ -3483,7 +3606,7 @@ class VgiProtocol(Protocol):
|
|
|
3483
3606
|
# ``VgiProtocol``, Java and C# ``VgiService``, Go the framework default
|
|
3484
3607
|
# ``Service``, TypeScript ``vgi`` -- so no client could address them all.
|
|
3485
3608
|
protocol_name: ClassVar[str] = "vgi.v3"
|
|
3486
|
-
protocol_version: ClassVar[str] = "3.
|
|
3609
|
+
protocol_version: ClassVar[str] = "3.1.0"
|
|
3487
3610
|
|
|
3488
3611
|
def bind(self, request: BindRequest) -> BindResponse:
|
|
3489
3612
|
"""Resolve output schema and validate arguments."""
|
vgi/protocol_version.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.1.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: vgi-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.49.0
|
|
4
4
|
Summary: Vector Gateway Interface - Connect DuckDB to external programs via Apache Arrow
|
|
5
5
|
Project-URL: Homepage, https://query.farm
|
|
6
6
|
Project-URL: Repository, https://github.com/Query-farm/vgi-python
|
|
@@ -161,6 +161,7 @@ Requires-Dist: click
|
|
|
161
161
|
Requires-Dist: httpx2>=2.12.0
|
|
162
162
|
Requires-Dist: platformdirs
|
|
163
163
|
Requires-Dist: pyarrow
|
|
164
|
+
Requires-Dist: pycryptodome>=3.20
|
|
164
165
|
Requires-Dist: typer>=0.9
|
|
165
166
|
Requires-Dist: vgi-rpc>=0.52.3
|
|
166
167
|
Provides-Extra: azure
|
|
@@ -27,8 +27,8 @@ vgi/meta_worker.py,sha256=QctITX8rP2qv_3pTCqIgqhoC8zQ26U82LC7fov8Huog,38641
|
|
|
27
27
|
vgi/metadata.py,sha256=nk0tE5w0mlOA_5sVSCNJTWC09bcZkjXYnvEziGguYc8,77829
|
|
28
28
|
vgi/otel.py,sha256=JlUDnk2c0UXSo_j1PJdS67Y--t55sXPg054ADuvHANc,15452
|
|
29
29
|
vgi/profiling.py,sha256=rK7vij3oHhXC3JHI2BsMySsXh7_hrXi0aXpCW8iFSIc,3671
|
|
30
|
-
vgi/protocol.py,sha256=
|
|
31
|
-
vgi/protocol_version.txt,sha256=
|
|
30
|
+
vgi/protocol.py,sha256=uBqWXxPM85er7xm8Owi_41mG5YdcL3jV1zJOylWawX8,194395
|
|
31
|
+
vgi/protocol_version.txt,sha256=svRNO24p-LG3PqRzXwBq_8TRmOH9nH1Q5zYVmx72NsY,6
|
|
32
32
|
vgi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
33
|
vgi/query_execution.py,sha256=zsaRAKDsaoq4wvavHzeokBICAo3CCid86WDJVY04zxc,21353
|
|
34
34
|
vgi/query_parameters.py,sha256=nnMH_SnF_fAh4y0mI87aAQdl3G4JqP2NibEcFX5pijI,7926
|
|
@@ -52,7 +52,7 @@ vgi/_test_fixtures/__init__.py,sha256=xQq-QQLk8USQ6TZHsPiPcZldNNUdcJ2gToXMPGzScL
|
|
|
52
52
|
vgi/_test_fixtures/attach_options.py,sha256=mfzHW44G1hw5gazuAMwVHgp3VTRCXBifhWszMs7Tndc,12636
|
|
53
53
|
vgi/_test_fixtures/attach_ticket_vectors.json,sha256=Ny0U9Cyn-_2G-ZYlC3ZpeG6bCux_bhtJZXGanti47fw,143027
|
|
54
54
|
vgi/_test_fixtures/bad_enum.py,sha256=b8l-afmXgGR6iqgIUiVeqHu0C0F8Of8ahEmdQGtqd1g,2916
|
|
55
|
-
vgi/_test_fixtures/bad_protocol.py,sha256=
|
|
55
|
+
vgi/_test_fixtures/bad_protocol.py,sha256=nTlxgMc921CLZHKPhyieBvk5Pd-w_2j40arrW4YSy-Y,3228
|
|
56
56
|
vgi/_test_fixtures/cancellable.py,sha256=hetTRLyT4kkazPNcxAdfzj0pYzEmegMksamJbR0w3Ho,12151
|
|
57
57
|
vgi/_test_fixtures/catalog.py,sha256=Klz1BwU6iD9qa9k0Z0yZH-r1B95o-qCyx0jLvbSxzyM,31089
|
|
58
58
|
vgi/_test_fixtures/catalog_contents.py,sha256=FTX-UtBBIGxFvhSYe4ZLryL-yM6ULK7dmkk0aAdEkbw,12094
|
|
@@ -127,7 +127,7 @@ vgi/_test_fixtures/table/same_name_cached.py,sha256=JMXSXTcqyO7XwWqIizgddlTvLYuU
|
|
|
127
127
|
vgi/_test_fixtures/table/same_name_schemas.py,sha256=yRti9HXO3-Y9ahiLIHoaZ31LvWjtPSbjxmPJyoQ_0mQ,4930
|
|
128
128
|
vgi/_test_fixtures/table/sequence.py,sha256=0kOckCwRu19RMKgFrUcnnnDR8e0utjX_E2kD3w6NnRU,26352
|
|
129
129
|
vgi/_test_fixtures/table/settings.py,sha256=C4J5OKY3vgNbB09QAiQlzwhI3Tc5wtewHHLFhO5xvo4,16689
|
|
130
|
-
vgi/_test_fixtures/table/splits.py,sha256=
|
|
130
|
+
vgi/_test_fixtures/table/splits.py,sha256=08GrBXQu-J-S3BDcNt7J75bHquykXmaTrRO9VR5iXU0,51414
|
|
131
131
|
vgi/_test_fixtures/table/transaction_storage.py,sha256=cGSaM25cE6brwbUJ0-mchocX0UfwOb7uscCATKLYeME,6086
|
|
132
132
|
vgi/_test_fixtures/table/tt_pushdown.py,sha256=jMELJ2HkG5-yIuYqKRYaPSouJxs3N-tiWRPthoPZ9ko,7420
|
|
133
133
|
vgi/_test_fixtures/table/typed_probe.py,sha256=JjgLeHuhkXAVnCcezgqR7ayXMp3tTTixegftCwjKOSY,5122
|
|
@@ -206,8 +206,8 @@ vgi/transactor/_duckdb_compat.py,sha256=sXVZ9JLKAQyGR1BjWczSwdQEavtr-TcZPoVZZnTr
|
|
|
206
206
|
vgi/transactor/client.py,sha256=7DTeMksogsw6ANjQjGOPpKYrV76rg4_kGjktMJf54jg,4486
|
|
207
207
|
vgi/transactor/protocol.py,sha256=koHi8ZH_QvZRBjFI_m_o1SpbcilBv_wAjmaGq0k61BY,5201
|
|
208
208
|
vgi/transactor/server.py,sha256=fJi72oaS8PiOI3rFW0MdetGBFEzFBkLdlDAMmbB50Uw,32663
|
|
209
|
-
vgi_python-0.
|
|
210
|
-
vgi_python-0.
|
|
211
|
-
vgi_python-0.
|
|
212
|
-
vgi_python-0.
|
|
213
|
-
vgi_python-0.
|
|
209
|
+
vgi_python-0.49.0.dist-info/METADATA,sha256=PxwkTnK120eSbyppa7ziC3rQ8j6I_-W5gle-PwJMiKA,26066
|
|
210
|
+
vgi_python-0.49.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
|
|
211
|
+
vgi_python-0.49.0.dist-info/entry_points.txt,sha256=3Kz1vgodw3pOL_xjtSyDB55-ZRy-U2X-X_Bdr582x0Q,165
|
|
212
|
+
vgi_python-0.49.0.dist-info/licenses/LICENSE,sha256=pbJb4zZasP6n5ifEV81wFu017TarjydaYVmGbHcehtY,6103
|
|
213
|
+
vgi_python-0.49.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|