pyspiral 0.6.9__cp312-abi3-macosx_11_0_arm64.whl → 0.7.12__cp312-abi3-macosx_11_0_arm64.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.
- {pyspiral-0.6.9.dist-info → pyspiral-0.7.12.dist-info}/METADATA +9 -8
- {pyspiral-0.6.9.dist-info → pyspiral-0.7.12.dist-info}/RECORD +53 -45
- {pyspiral-0.6.9.dist-info → pyspiral-0.7.12.dist-info}/entry_points.txt +1 -0
- spiral/__init__.py +20 -0
- spiral/_lib.abi3.so +0 -0
- spiral/api/__init__.py +1 -1
- spiral/api/client.py +1 -1
- spiral/api/types.py +1 -0
- spiral/cli/admin.py +2 -2
- spiral/cli/app.py +8 -4
- spiral/cli/fs.py +4 -4
- spiral/cli/iceberg.py +1 -1
- spiral/cli/key_spaces.py +15 -1
- spiral/cli/login.py +4 -3
- spiral/cli/orgs.py +8 -7
- spiral/cli/projects.py +4 -4
- spiral/cli/state.py +5 -3
- spiral/cli/tables.py +59 -36
- spiral/cli/telemetry.py +1 -1
- spiral/cli/types.py +2 -2
- spiral/cli/workloads.py +3 -3
- spiral/client.py +69 -22
- spiral/core/client/__init__.pyi +48 -13
- spiral/core/config/__init__.pyi +47 -0
- spiral/core/expr/__init__.pyi +15 -0
- spiral/core/expr/images/__init__.pyi +3 -0
- spiral/core/expr/list_/__init__.pyi +4 -0
- spiral/core/expr/refs/__init__.pyi +4 -0
- spiral/core/expr/str_/__init__.pyi +3 -0
- spiral/core/expr/struct_/__init__.pyi +6 -0
- spiral/core/expr/text/__init__.pyi +5 -0
- spiral/core/expr/udf/__init__.pyi +14 -0
- spiral/core/expr/video/__init__.pyi +3 -0
- spiral/core/table/__init__.pyi +37 -2
- spiral/core/table/spec/__init__.pyi +6 -4
- spiral/dataloader.py +52 -38
- spiral/dataset.py +10 -1
- spiral/enrichment.py +304 -0
- spiral/expressions/__init__.py +21 -23
- spiral/expressions/base.py +9 -4
- spiral/expressions/file.py +17 -0
- spiral/expressions/http.py +11 -80
- spiral/expressions/s3.py +16 -0
- spiral/expressions/tiff.py +2 -3
- spiral/expressions/udf.py +38 -24
- spiral/iceberg.py +3 -3
- spiral/project.py +34 -6
- spiral/scan.py +80 -33
- spiral/settings.py +19 -97
- spiral/streaming_/stream.py +1 -1
- spiral/table.py +40 -10
- spiral/transaction.py +99 -2
- spiral/expressions/io.py +0 -100
- spiral/expressions/mp4.py +0 -62
- spiral/expressions/png.py +0 -18
- spiral/expressions/qoi.py +0 -18
- spiral/expressions/refs.py +0 -58
- {pyspiral-0.6.9.dist-info → pyspiral-0.7.12.dist-info}/WHEEL +0 -0
spiral/cli/telemetry.py
CHANGED
|
@@ -8,7 +8,7 @@ app = AsyncTyper(short_help="Client-side telemetry.")
|
|
|
8
8
|
|
|
9
9
|
@app.command(help="Issue new telemetry export token.")
|
|
10
10
|
def export():
|
|
11
|
-
res: IssueExportTokenResponse = state.
|
|
11
|
+
res: IssueExportTokenResponse = state.spiral.api.telemetry.issue_export_token()
|
|
12
12
|
|
|
13
13
|
command = f"export SPIRAL_OTEL_TOKEN={res.token}"
|
|
14
14
|
pyperclip.copy(command)
|
spiral/cli/types.py
CHANGED
|
@@ -10,7 +10,7 @@ from spiral.cli import ERR_CONSOLE, state
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def ask_project(title="Select a project"):
|
|
13
|
-
projects = list(state.
|
|
13
|
+
projects = list(state.spiral.api.project.list())
|
|
14
14
|
|
|
15
15
|
if not projects:
|
|
16
16
|
ERR_CONSOLE.print("No projects found")
|
|
@@ -29,7 +29,7 @@ ProjectArg = Annotated[ProjectId, Argument(help="Project ID", show_default=False
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
def _org_default():
|
|
32
|
-
memberships = list(state.
|
|
32
|
+
memberships = list(state.spiral.api.organization.list_memberships())
|
|
33
33
|
|
|
34
34
|
if not memberships:
|
|
35
35
|
ERR_CONSOLE.print("No organizations found")
|
spiral/cli/workloads.py
CHANGED
|
@@ -17,7 +17,7 @@ def create(
|
|
|
17
17
|
project: ProjectArg,
|
|
18
18
|
name: Annotated[str | None, Option(help="Friendly name for the workload.")] = None,
|
|
19
19
|
):
|
|
20
|
-
res = state.
|
|
20
|
+
res = state.spiral.api.workload.create(project, CreateWorkloadRequest(name=name))
|
|
21
21
|
CONSOLE.print(f"Created workload {res.workload.id}")
|
|
22
22
|
|
|
23
23
|
|
|
@@ -25,13 +25,13 @@ def create(
|
|
|
25
25
|
def ls(
|
|
26
26
|
project: ProjectArg,
|
|
27
27
|
):
|
|
28
|
-
workloads = list(state.
|
|
28
|
+
workloads = list(state.spiral.api.workload.list(project))
|
|
29
29
|
CONSOLE.print(printer.table_of_models(Workload, workloads, fields=["id", "project_id", "name"]))
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
@app.command(help="Issue new workflow credentials.")
|
|
33
33
|
def issue_credentials(workload_id: Annotated[str, Argument(help="Workload ID.")]):
|
|
34
|
-
res: IssueWorkloadCredentialsResponse = state.
|
|
34
|
+
res: IssueWorkloadCredentialsResponse = state.spiral.api.workload.issue_credentials(workload_id)
|
|
35
35
|
|
|
36
36
|
while True:
|
|
37
37
|
choice = questionary.select(
|
spiral/client.py
CHANGED
|
@@ -6,12 +6,13 @@ import pyarrow as pa
|
|
|
6
6
|
|
|
7
7
|
from spiral.api import SpiralAPI
|
|
8
8
|
from spiral.api.projects import CreateProjectRequest, CreateProjectResponse
|
|
9
|
-
from spiral.core.
|
|
9
|
+
from spiral.core.authn import Authn
|
|
10
|
+
from spiral.core.client import Internal, KeyColumns
|
|
10
11
|
from spiral.core.client import Spiral as CoreSpiral
|
|
12
|
+
from spiral.core.config import ClientSettings
|
|
11
13
|
from spiral.datetime_ import timestamp_micros
|
|
12
14
|
from spiral.expressions import ExprLike
|
|
13
15
|
from spiral.scan import Scan
|
|
14
|
-
from spiral.settings import Settings, settings
|
|
15
16
|
|
|
16
17
|
if TYPE_CHECKING:
|
|
17
18
|
from spiral.iceberg import Iceberg
|
|
@@ -22,26 +23,74 @@ if TYPE_CHECKING:
|
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
class Spiral:
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
"""Main client for interacting with the Spiral data platform.
|
|
27
|
+
|
|
28
|
+
Configuration is loaded with the following priority (highest to lowest):
|
|
29
|
+
1. Explicit parameters.
|
|
30
|
+
2. Environment variables (`SPIRAL__*`)
|
|
31
|
+
3. Config file (`~/.spiral.toml`)
|
|
32
|
+
4. Default values (production URLs)
|
|
33
|
+
|
|
34
|
+
Examples:
|
|
35
|
+
```python
|
|
36
|
+
# Default configuration
|
|
37
|
+
client = Spiral()
|
|
38
|
+
|
|
39
|
+
# With config overrides
|
|
40
|
+
client = Spiral(overrides={"limits.concurrency": "16"})
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
config: Custom ClientSettings object. Defaults to global settings.
|
|
45
|
+
overrides: Configuration overrides using dot notation,
|
|
46
|
+
see the [Client Configuration](/python-client.md) page for a full list.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
def __init__(
|
|
50
|
+
self,
|
|
51
|
+
config: ClientSettings | None = None,
|
|
52
|
+
overrides: dict[str, str] | None = None,
|
|
53
|
+
):
|
|
54
|
+
self._overrides = overrides
|
|
55
|
+
self._config = config
|
|
27
56
|
self._org = None
|
|
57
|
+
self._core = None
|
|
58
|
+
self._api = None
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def config(self) -> ClientSettings:
|
|
62
|
+
"""Returns the client's configuration"""
|
|
63
|
+
return self.core.config()
|
|
28
64
|
|
|
29
65
|
@property
|
|
30
|
-
def
|
|
31
|
-
|
|
66
|
+
def authn(self) -> Authn:
|
|
67
|
+
"""Get the authentication handler for this client."""
|
|
68
|
+
return self.core.authn()
|
|
32
69
|
|
|
33
70
|
@property
|
|
34
71
|
def api(self) -> SpiralAPI:
|
|
35
|
-
|
|
72
|
+
if self._api is None:
|
|
73
|
+
self._api = SpiralAPI(self.authn, base_url=self.config.server_url)
|
|
74
|
+
return self._api
|
|
36
75
|
|
|
37
76
|
@property
|
|
38
|
-
def
|
|
39
|
-
|
|
77
|
+
def core(self) -> CoreSpiral:
|
|
78
|
+
if self._core is None:
|
|
79
|
+
self._core = CoreSpiral(
|
|
80
|
+
config=self._config,
|
|
81
|
+
overrides=self._overrides,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
return self._core
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def internal(self) -> Internal:
|
|
88
|
+
return self.core.internal(format=self.config.file_format)
|
|
40
89
|
|
|
41
90
|
@property
|
|
42
91
|
def organization(self) -> str:
|
|
43
92
|
if self._org is None:
|
|
44
|
-
token = self.
|
|
93
|
+
token = self.authn.token()
|
|
45
94
|
if token is None:
|
|
46
95
|
raise ValueError("Authentication failed.")
|
|
47
96
|
token_payload = jwt.decode(token.expose_secret(), options={"verify_signature": False})
|
|
@@ -79,25 +128,26 @@ class Spiral:
|
|
|
79
128
|
"""Open a table using an ID."""
|
|
80
129
|
from spiral.table import Table
|
|
81
130
|
|
|
82
|
-
return Table(self, self.
|
|
131
|
+
return Table(self, self.core.table(table_id))
|
|
83
132
|
|
|
84
133
|
def text_index(self, index_id: str) -> "TextIndex":
|
|
85
134
|
"""Open a text index using an ID."""
|
|
86
135
|
from spiral.text_index import TextIndex
|
|
87
136
|
|
|
88
|
-
return TextIndex(self.
|
|
137
|
+
return TextIndex(self.core.text_index(index_id))
|
|
89
138
|
|
|
90
139
|
def key_space_index(self, index_id: str) -> "KeySpaceIndex":
|
|
91
140
|
"""Open a key space index using an ID."""
|
|
92
141
|
from spiral.key_space_index import KeySpaceIndex
|
|
93
142
|
|
|
94
|
-
return KeySpaceIndex(self.
|
|
143
|
+
return KeySpaceIndex(self.core.key_space_index(index_id))
|
|
95
144
|
|
|
96
145
|
def scan(
|
|
97
146
|
self,
|
|
98
147
|
*projections: ExprLike,
|
|
99
148
|
where: ExprLike | None = None,
|
|
100
149
|
asof: datetime | int | None = None,
|
|
150
|
+
_key_columns: KeyColumns | None = None,
|
|
101
151
|
) -> Scan:
|
|
102
152
|
"""Starts a read transaction on the Spiral.
|
|
103
153
|
|
|
@@ -112,15 +162,16 @@ class Spiral:
|
|
|
112
162
|
asof = timestamp_micros(asof)
|
|
113
163
|
|
|
114
164
|
# Combine all projections into a single struct.
|
|
165
|
+
if not projections:
|
|
166
|
+
raise ValueError("At least one projection is required.")
|
|
115
167
|
projection = se.merge(*projections)
|
|
116
168
|
if where is not None:
|
|
117
169
|
where = se.lift(where)
|
|
118
170
|
|
|
119
171
|
return Scan(
|
|
120
|
-
self
|
|
121
|
-
|
|
122
|
-
filter=where.__expr__ if where else None,
|
|
123
|
-
asof=asof,
|
|
172
|
+
self,
|
|
173
|
+
self.core.scan(
|
|
174
|
+
projection.__expr__, filter=where.__expr__ if where else None, asof=asof, key_columns=_key_columns
|
|
124
175
|
),
|
|
125
176
|
)
|
|
126
177
|
|
|
@@ -155,17 +206,13 @@ class Spiral:
|
|
|
155
206
|
freshness_window = timedelta(seconds=0)
|
|
156
207
|
freshness_window_s = int(freshness_window.total_seconds())
|
|
157
208
|
|
|
158
|
-
return self.
|
|
209
|
+
return self.core.search(
|
|
159
210
|
top_k=top_k,
|
|
160
211
|
rank_by=rank_by.__expr__,
|
|
161
212
|
filters=filters.__expr__ if filters else None,
|
|
162
213
|
freshness_window_s=freshness_window_s,
|
|
163
214
|
)
|
|
164
215
|
|
|
165
|
-
def _ops(self) -> Operations:
|
|
166
|
-
"""Access maintenance operations."""
|
|
167
|
-
return self._core._ops(format=settings().file_format)
|
|
168
|
-
|
|
169
216
|
@property
|
|
170
217
|
def iceberg(self) -> "Iceberg":
|
|
171
218
|
"""
|
spiral/core/client/__init__.pyi
CHANGED
|
@@ -1,22 +1,36 @@
|
|
|
1
|
+
from enum import Enum
|
|
1
2
|
from typing import Any, Literal
|
|
2
3
|
|
|
3
4
|
import pyarrow as pa
|
|
4
|
-
from spiral.api.types import DatasetName, IndexName, ProjectId, RootUri, TableName
|
|
5
|
+
from spiral.api.types import DatasetName, IndexName, ProjectId, RootUri, TableId, TableName
|
|
5
6
|
from spiral.core.authn import Authn
|
|
6
|
-
from spiral.core.
|
|
7
|
+
from spiral.core.config import ClientSettings
|
|
8
|
+
from spiral.core.table import ColumnGroupState, KeyRange, KeySpaceState, Scan, ScanState, Snapshot, Table, Transaction
|
|
7
9
|
from spiral.core.table.spec import ColumnGroup, Schema
|
|
8
10
|
from spiral.expressions import Expr
|
|
9
11
|
|
|
12
|
+
# Only for typing, the actual definition is in Rust.
|
|
13
|
+
class KeyColumns(Enum):
|
|
14
|
+
IfProjected = 0
|
|
15
|
+
Included = 1
|
|
16
|
+
Only = 2
|
|
17
|
+
|
|
10
18
|
class Spiral:
|
|
11
19
|
"""A client for Spiral database"""
|
|
12
20
|
def __init__(
|
|
13
21
|
self,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
authn: Authn | None = None,
|
|
22
|
+
config: ClientSettings | None = None,
|
|
23
|
+
overrides: dict[str, str] | None = None,
|
|
17
24
|
):
|
|
18
|
-
"""Initialize the Spiral client.
|
|
25
|
+
"""Initialize the Spiral client.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
config: Client configuration, defaults to the global config.
|
|
29
|
+
overrides: Configuration overrides using dot notation,
|
|
30
|
+
see the [Client Configuration](/python-client) page for a full list.
|
|
31
|
+
"""
|
|
19
32
|
...
|
|
33
|
+
|
|
20
34
|
def authn(self) -> Authn:
|
|
21
35
|
"""Get the current authentication context."""
|
|
22
36
|
...
|
|
@@ -26,10 +40,15 @@ class Spiral:
|
|
|
26
40
|
projection: Expr,
|
|
27
41
|
filter: Expr | None = None,
|
|
28
42
|
asof: int | None = None,
|
|
43
|
+
key_columns: KeyColumns | None = None,
|
|
29
44
|
) -> Scan:
|
|
30
45
|
"""Construct a table scan."""
|
|
31
46
|
...
|
|
32
47
|
|
|
48
|
+
def load_scan(self, plan_state: ScanState) -> Scan:
|
|
49
|
+
"""Load a scan from a serialized scan state."""
|
|
50
|
+
...
|
|
51
|
+
|
|
33
52
|
def transaction(self, table: Table, format: str | None = None, retries: int | None = 3) -> Transaction:
|
|
34
53
|
"""Being a table transaction."""
|
|
35
54
|
...
|
|
@@ -65,6 +84,22 @@ class Spiral:
|
|
|
65
84
|
"""Create a new table in the specified project."""
|
|
66
85
|
...
|
|
67
86
|
|
|
87
|
+
def move_table(
|
|
88
|
+
self,
|
|
89
|
+
table_id: TableId,
|
|
90
|
+
new_dataset: DatasetName,
|
|
91
|
+
):
|
|
92
|
+
"""Move a table to a dataset in the same project."""
|
|
93
|
+
...
|
|
94
|
+
|
|
95
|
+
def rename_table(
|
|
96
|
+
self,
|
|
97
|
+
table_id: TableId,
|
|
98
|
+
new_table: TableName,
|
|
99
|
+
):
|
|
100
|
+
"""Rename a table."""
|
|
101
|
+
...
|
|
102
|
+
|
|
68
103
|
def text_index(self, index_id: str) -> TextIndex:
|
|
69
104
|
"""Get a text index."""
|
|
70
105
|
...
|
|
@@ -100,12 +135,12 @@ class Spiral:
|
|
|
100
135
|
"""Create a new key space index in the specified project."""
|
|
101
136
|
...
|
|
102
137
|
|
|
103
|
-
def
|
|
104
|
-
"""
|
|
138
|
+
def internal(self, *, format: str | None = None) -> Internal:
|
|
139
|
+
"""Internal client APIs. It can change without notice."""
|
|
140
|
+
...
|
|
105
141
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
"""
|
|
142
|
+
def config(self) -> ClientSettings:
|
|
143
|
+
"""Client-side configuration."""
|
|
109
144
|
...
|
|
110
145
|
|
|
111
146
|
class TextIndex:
|
|
@@ -158,8 +193,8 @@ class ShuffleConfig:
|
|
|
158
193
|
max_batch_size: int | None = None,
|
|
159
194
|
): ...
|
|
160
195
|
|
|
161
|
-
class
|
|
162
|
-
def flush_wal(self, table: Table
|
|
196
|
+
class Internal:
|
|
197
|
+
def flush_wal(self, table: Table) -> None:
|
|
163
198
|
"""
|
|
164
199
|
Flush the write-ahead log of the table.
|
|
165
200
|
"""
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from spiral.core.authn import Token
|
|
2
|
+
|
|
3
|
+
class ClientSettings:
|
|
4
|
+
"""Client configuration loaded from ~/.spiral.toml and environment variables."""
|
|
5
|
+
|
|
6
|
+
@staticmethod
|
|
7
|
+
def load() -> ClientSettings:
|
|
8
|
+
"""Load ClientSettings from ~/.spiral.toml and environment variables.
|
|
9
|
+
|
|
10
|
+
Configuration priority (highest to lowest):
|
|
11
|
+
1. Environment variables (SPIRAL__*)
|
|
12
|
+
2. Config file (~/.spiral.toml)
|
|
13
|
+
3. Default values
|
|
14
|
+
"""
|
|
15
|
+
...
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def server_url(self) -> str:
|
|
19
|
+
"""The Spiral API endpoint URL."""
|
|
20
|
+
...
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def spfs_url(self) -> str:
|
|
24
|
+
"""The SpFS endpoint URL."""
|
|
25
|
+
...
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def file_format(self) -> str:
|
|
29
|
+
"""File format for table storage (vortex or parquet)."""
|
|
30
|
+
...
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def token(self) -> Token | None:
|
|
34
|
+
"""Authentication token (if provided via SPIRAL__TOKEN)."""
|
|
35
|
+
...
|
|
36
|
+
|
|
37
|
+
@token.setter
|
|
38
|
+
def token(self, token: Token):
|
|
39
|
+
"""Set the config's authentication token"""
|
|
40
|
+
...
|
|
41
|
+
|
|
42
|
+
def to_json(self) -> str:
|
|
43
|
+
"""Serialize to a JSON string"""
|
|
44
|
+
...
|
|
45
|
+
@staticmethod
|
|
46
|
+
def from_json(json: str) -> ClientSettings:
|
|
47
|
+
"""Deserialize from a JSON-formatted string"""
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from pyarrow import Array, DataType, Scalar
|
|
2
|
+
|
|
3
|
+
class Expr:
|
|
4
|
+
"""Low level expression class."""
|
|
5
|
+
|
|
6
|
+
def aux(name: str, data_type: DataType) -> Expr: ...
|
|
7
|
+
|
|
8
|
+
# Array is correct (there is no ArrayData), see the table here:
|
|
9
|
+
# https://arrow.apache.org/rust/arrow_pyarrow/index.html
|
|
10
|
+
def scalar(array: Array[Scalar[DataType]]) -> Expr: ...
|
|
11
|
+
def not_(expr: Expr) -> Expr: ...
|
|
12
|
+
def is_null(expr: Expr) -> Expr: ...
|
|
13
|
+
def binary(op: str, expr: Expr, Expr: Expr) -> Expr: ...
|
|
14
|
+
def cast(_expr: Expr, _data_type: DataType) -> Expr: ...
|
|
15
|
+
def array_lit(array: Array[Scalar[DataType]]) -> Expr: ...
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
from .. import Expr
|
|
2
|
+
|
|
3
|
+
def getitem(expr: Expr, item: str) -> Expr: ...
|
|
4
|
+
def select(expr: Expr, including: list[str] | None = None, excluding: list[str] | None = None) -> Expr: ...
|
|
5
|
+
def pack(names: list[str], children: list[str], nullable: bool) -> Expr: ...
|
|
6
|
+
def merge(names: list[Expr]) -> Expr: ...
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
|
|
3
|
+
from pyarrow import Array, DataType, Scalar
|
|
4
|
+
|
|
5
|
+
from .. import Expr
|
|
6
|
+
|
|
7
|
+
class UDF:
|
|
8
|
+
def __call__(self, args: list[Expr]) -> Expr: ...
|
|
9
|
+
|
|
10
|
+
def create(
|
|
11
|
+
name: str,
|
|
12
|
+
return_type: Callable[[tuple[DataType, ...]], DataType],
|
|
13
|
+
invoke: Callable[[tuple[Array[Scalar[DataType]], ...]], Array[Scalar[DataType]]],
|
|
14
|
+
) -> UDF: ...
|
spiral/core/table/__init__.pyi
CHANGED
|
@@ -5,7 +5,7 @@ from spiral.core.client import Shard, ShuffleConfig
|
|
|
5
5
|
|
|
6
6
|
from .manifests import FragmentManifest
|
|
7
7
|
from .metastore import PyMetastore
|
|
8
|
-
from .spec import ColumnGroup, Key, Schema, WriteAheadLog
|
|
8
|
+
from .spec import ColumnGroup, Key, Operation, Schema, WriteAheadLog
|
|
9
9
|
|
|
10
10
|
class KeyRange:
|
|
11
11
|
"""A right-exclusive range of keys."""
|
|
@@ -52,6 +52,21 @@ class Snapshot:
|
|
|
52
52
|
table: Table
|
|
53
53
|
wal: WriteAheadLog
|
|
54
54
|
|
|
55
|
+
class ScanState:
|
|
56
|
+
def to_json(self) -> str: ...
|
|
57
|
+
@staticmethod
|
|
58
|
+
def from_json(json: str) -> ScanState: ...
|
|
59
|
+
|
|
60
|
+
class MaterializablePlan:
|
|
61
|
+
pass
|
|
62
|
+
|
|
63
|
+
class EvaluatedExecutablePlan:
|
|
64
|
+
pass
|
|
65
|
+
|
|
66
|
+
class EvaluatedPlanStream:
|
|
67
|
+
def __next__(self) -> EvaluatedExecutablePlan: ...
|
|
68
|
+
def __iter__(self) -> EvaluatedPlanStream: ...
|
|
69
|
+
|
|
55
70
|
class Scan:
|
|
56
71
|
def key_schema(self) -> Schema: ...
|
|
57
72
|
def schema(self) -> Schema: ...
|
|
@@ -62,10 +77,14 @@ class Scan:
|
|
|
62
77
|
def column_groups(self) -> list[ColumnGroup]: ...
|
|
63
78
|
def column_group_state(self, column_group: ColumnGroup) -> ColumnGroupState: ...
|
|
64
79
|
def key_space_state(self, table_id: str) -> KeySpaceState: ...
|
|
80
|
+
def plan_state(self) -> ScanState: ...
|
|
81
|
+
def materializable_plan(self) -> MaterializablePlan: ...
|
|
65
82
|
def to_record_batches(
|
|
66
83
|
self,
|
|
84
|
+
key_range: KeyRange | None = None,
|
|
67
85
|
key_table: pa.Table | pa.RecordBatch | None = None,
|
|
68
86
|
batch_readahead: int | None = None,
|
|
87
|
+
progress: bool = True,
|
|
69
88
|
) -> pa.RecordBatchReader: ...
|
|
70
89
|
def to_shuffled_record_batches(
|
|
71
90
|
self,
|
|
@@ -78,6 +97,10 @@ class Scan:
|
|
|
78
97
|
# If `infinite` is True, shards are shuffled after exhausted but not before the first pass.
|
|
79
98
|
# Otherwise, shards are not shuffle and shuffle config is only used for shuffle buffer.
|
|
80
99
|
...
|
|
100
|
+
|
|
101
|
+
def evaluate_analyze(
|
|
102
|
+
self, key_table: pa.Table | pa.RecordBatch | None = None, batch_readahead: int | None = None
|
|
103
|
+
) -> EvaluatedPlanStream: ...
|
|
81
104
|
def metrics(self) -> dict[str, Any]: ...
|
|
82
105
|
|
|
83
106
|
class KeySpaceState:
|
|
@@ -95,7 +118,19 @@ class Transaction:
|
|
|
95
118
|
status: str
|
|
96
119
|
|
|
97
120
|
def write(self, table: pa.RecordBatchReader, *, partition_size_bytes: int | None = None): ...
|
|
121
|
+
def writeback(
|
|
122
|
+
self,
|
|
123
|
+
scan: Scan,
|
|
124
|
+
*,
|
|
125
|
+
key_range: KeyRange | None = None,
|
|
126
|
+
partition_size_bytes: int | None = None,
|
|
127
|
+
batch_readahead: int | None = None,
|
|
128
|
+
): ...
|
|
98
129
|
def drop_columns(self, column_paths: list[str]): ...
|
|
99
|
-
def
|
|
130
|
+
def ops(self) -> list[Operation]: ...
|
|
131
|
+
def take(self) -> list[Operation]: ...
|
|
132
|
+
def include(self, ops: list[Operation]): ...
|
|
133
|
+
def commit(self, *, compact: bool = False): ...
|
|
100
134
|
def abort(self): ...
|
|
135
|
+
def is_empty(self) -> bool: ...
|
|
101
136
|
def metrics(self) -> dict[str, Any]: ...
|
|
@@ -62,6 +62,12 @@ class ColumnGroupMetadata:
|
|
|
62
62
|
def apply_wal(self, wal: WriteAheadLog) -> ColumnGroupMetadata:
|
|
63
63
|
"""Applies the given WAL to the metadata."""
|
|
64
64
|
|
|
65
|
+
class Operation:
|
|
66
|
+
# Base class for all operations in the WAL.
|
|
67
|
+
def to_json(self) -> str: ...
|
|
68
|
+
@staticmethod
|
|
69
|
+
def from_json(json: str) -> Operation: ...
|
|
70
|
+
|
|
65
71
|
class LogEntry:
|
|
66
72
|
ts: int
|
|
67
73
|
operation: (
|
|
@@ -172,11 +178,7 @@ class KeySpaceWriteOp:
|
|
|
172
178
|
|
|
173
179
|
class ColumnGroupWriteOp:
|
|
174
180
|
column_group: ColumnGroup
|
|
175
|
-
level: FragmentLevel
|
|
176
181
|
manifest_handle: ManifestHandle
|
|
177
|
-
key_span: KeySpan
|
|
178
|
-
key_extent: KeyExtent
|
|
179
|
-
column_ids: list[str]
|
|
180
182
|
|
|
181
183
|
class SchemaEvolutionOp:
|
|
182
184
|
column_group: ColumnGroup
|