pyspiral 0.2.5__cp310-abi3-macosx_11_0_arm64.whl → 0.3.1__cp310-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.2.5.dist-info → pyspiral-0.3.1.dist-info}/METADATA +8 -6
- {pyspiral-0.2.5.dist-info → pyspiral-0.3.1.dist-info}/RECORD +29 -25
- {pyspiral-0.2.5.dist-info → pyspiral-0.3.1.dist-info}/WHEEL +1 -1
- spiral/__init__.py +3 -1
- spiral/_lib.abi3.so +0 -0
- spiral/api/__init__.py +8 -4
- spiral/api/filesystems.py +1 -1
- spiral/api/tables.py +3 -6
- spiral/catalog.py +15 -0
- spiral/cli/fs.py +2 -2
- spiral/cli/project.py +5 -3
- spiral/core/core/__init__.pyi +34 -6
- spiral/core/spec/__init__.pyi +8 -26
- spiral/dataset.py +221 -20
- spiral/expressions/__init__.py +19 -4
- spiral/expressions/mp4.py +69 -0
- spiral/expressions/png.py +18 -0
- spiral/expressions/qoi.py +18 -0
- spiral/expressions/refs.py +23 -3
- spiral/expressions/tiff.py +88 -88
- spiral/maintenance.py +12 -0
- spiral/proto/_/scandal/__init__.py +78 -11
- spiral/proto/_/spiral/table/__init__.py +53 -2
- spiral/scan_.py +75 -24
- spiral/settings.py +6 -0
- spiral/substrait_.py +1 -1
- spiral/table.py +35 -21
- spiral/txn.py +48 -0
- spiral/config.py +0 -26
- {pyspiral-0.2.5.dist-info → pyspiral-0.3.1.dist-info}/entry_points.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: pyspiral
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.3.1
|
4
4
|
Classifier: Intended Audience :: Science/Research
|
5
5
|
Classifier: Operating System :: OS Independent
|
6
6
|
Classifier: Programming Language :: Python
|
@@ -18,22 +18,24 @@ Requires-Dist: grpclib>=0.4.7
|
|
18
18
|
Requires-Dist: hishel>=0.0.30
|
19
19
|
Requires-Dist: httpx>=0.27.0
|
20
20
|
Requires-Dist: numpy>=1.26.3
|
21
|
-
Requires-Dist: opentelemetry-api>=1.27.0
|
22
|
-
Requires-Dist: opentelemetry-sdk>=1.27.0
|
23
|
-
Requires-Dist: polars>=1.6.0
|
24
21
|
Requires-Dist: pyarrow>=17.0.0
|
25
22
|
Requires-Dist: pydantic-settings>=2.3.4
|
26
23
|
Requires-Dist: pydantic[email]>=2.5.3
|
27
24
|
Requires-Dist: pyjwt[crypto]>=2.9.0
|
28
|
-
Requires-Dist: pyroaring>=0.4.4
|
29
25
|
Requires-Dist: questionary>=2.0.1
|
30
26
|
Requires-Dist: tqdm>=4.66.5
|
31
27
|
Requires-Dist: typer>=0.12.3
|
32
28
|
Requires-Dist: xxhash>=3.4.1
|
33
29
|
Requires-Dist: nanoid>=2.0.0
|
34
30
|
Requires-Dist: sqlglot[rs]>=25.25.1
|
35
|
-
Requires-Dist: duckdb>=1.1.1
|
36
31
|
Requires-Dist: pyperclip>=1.9.0
|
32
|
+
Requires-Dist: boto3>=1.35.36
|
33
|
+
Requires-Dist: polars>=1.6.0 ; extra == 'polars'
|
34
|
+
Requires-Dist: duckdb>=1.1.1 ; extra == 'duckdb'
|
35
|
+
Requires-Dist: pyiceberg>=0.9.0 ; extra == 'pyiceberg'
|
36
|
+
Provides-Extra: polars
|
37
|
+
Provides-Extra: duckdb
|
38
|
+
Provides-Extra: pyiceberg
|
37
39
|
Summary: Python implementation of Spiral table format.
|
38
40
|
Keywords: vortex,spiraldb
|
39
41
|
Home-Page: https://spiraldb.com
|
@@ -1,12 +1,11 @@
|
|
1
|
-
pyspiral-0.
|
2
|
-
pyspiral-0.
|
3
|
-
pyspiral-0.
|
4
|
-
spiral/catalog.py,sha256=
|
5
|
-
spiral/scan_.py,sha256=
|
6
|
-
spiral/substrait_.py,sha256=
|
7
|
-
spiral/
|
8
|
-
spiral/core/
|
9
|
-
spiral/core/spec/__init__.pyi,sha256=zwOPhpBS_iOrPkOdc4ySpgzICZNbteMZf4c2wdkWw1Y,7251
|
1
|
+
pyspiral-0.3.1.dist-info/METADATA,sha256=QWHcYqfg46JUluQy_NZ3TKilWdvRFwOCqcJPYMo4g3c,1782
|
2
|
+
pyspiral-0.3.1.dist-info/WHEEL,sha256=WcVLymwUFXZZBOS7GhUoID5qvQcDPxnkUAYBKypRBtM,103
|
3
|
+
pyspiral-0.3.1.dist-info/entry_points.txt,sha256=uft7u-a6g40NLt4Q6BleWbK4NY0M8nZuYPpP8DV0EOk,45
|
4
|
+
spiral/catalog.py,sha256=o6b8yhVzHmk_CPNZMKyJU0H8xpjJKKcf2rjcopTSBKc,2912
|
5
|
+
spiral/scan_.py,sha256=TNAR_ELKRMJec6fIxhOwpW12WTwZc4sDLtfGdiok-lw,8239
|
6
|
+
spiral/substrait_.py,sha256=LmdRhyTX7vhgEbpxV6FUssyL-BiBEIPBeUZApeaKDM4,12671
|
7
|
+
spiral/core/core/__init__.pyi,sha256=zQhEB9X0B4EJGZf6AJYZdRt1tDQelF5tCsUaVdH7p4I,2706
|
8
|
+
spiral/core/spec/__init__.pyi,sha256=RAnvJjuQPxbcyPtjldvOU8zjVlHhnTKHAFa77sqxBdw,6714
|
10
9
|
spiral/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
10
|
spiral/core/manifests/__init__.pyi,sha256=DXr4Ab_Xo11AzrJlSj7FTSJc8qoO-SkL-_ik4kB855U,1516
|
12
11
|
spiral/core/metastore/__init__.pyi,sha256=pdKED91GVJ9XWxTWc9gwkHvVHV_RKxvL43Ofs5ndmew,3145
|
@@ -16,21 +15,22 @@ spiral/proto/util.py,sha256=smnvVo6nYH3FfDm9jqhNLaXz4bbTBaQezHQDCTvZyiQ,1486
|
|
16
15
|
spiral/proto/spiral/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
16
|
spiral/proto/spiral/table/__init__.py,sha256=_F1f52RMkZsXofPXpJb2KE8KR5l6zxCtrGrabR1uDxo,2816
|
18
17
|
spiral/proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
|
-
spiral/proto/_/scandal/__init__.py,sha256=
|
18
|
+
spiral/proto/_/scandal/__init__.py,sha256=4UV2TipI1dJWCM2gFNmZM1qbM1_C_pilO3DTI1Kqq8M,8655
|
20
19
|
spiral/proto/_/arrow/flight/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
20
|
spiral/proto/_/arrow/flight/protocol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
21
|
spiral/proto/_/arrow/flight/protocol/sql/__init__.py,sha256=_xhj9QkWEW1qZ-iVxcQ8k4EjYr7KJ5ofitJGqVUGQi4,79921
|
23
22
|
spiral/proto/_/arrow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
23
|
spiral/proto/_/spiral/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
|
-
spiral/proto/_/spiral/table/__init__.py,sha256=
|
24
|
+
spiral/proto/_/spiral/table/__init__.py,sha256=WnBvPPGHphSIa5K6ct6G3S3pK5BJtcC0EIce7r4Jam4,8818
|
26
25
|
spiral/proto/_/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
27
26
|
spiral/proto/_/spiraldb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
28
27
|
spiral/proto/_/spiraldb/metastore/__init__.py,sha256=40Egtg8MRYTaTTYRKOHkwuiyXEkw3Yg7ETCQskIzpIg,16873
|
29
28
|
spiral/proto/_/spfs/__init__.py,sha256=9WtIXr7HGslKWRHHieFDo8N_qnGL4QQyLOCWEkOKRvk,1017
|
30
29
|
spiral/proto/substrait/__init__.py,sha256=pV4-T-lwAHKkfFrNYSUGY4IkbIvuKjSo_imzF7BLj_s,126526
|
31
30
|
spiral/proto/substrait/extensions/__init__.py,sha256=yD7dg0TBqn-GK_L0qeVof1GKnwSLg_kPyQSV3kcSljs,3655
|
31
|
+
spiral/maintenance.py,sha256=UFvWBLf9L0qDxJa2VdyBzxQxN4W3D9F3QHFKWp1yWZU,304
|
32
32
|
spiral/arrow.py,sha256=LBPwZcGkP4kXb42_kl5IUwWW3DO84CV3QJDwCHjG5Dg,7225
|
33
|
-
spiral/__init__.py,sha256=
|
33
|
+
spiral/__init__.py,sha256=Dlaha3kfmzIri8A3-d69tOC2iQrK5fXlYVSI6uU4Fus,394
|
34
34
|
spiral/cli/console.py,sha256=-OP0bB_efxhWh4lZ95KRdu-SRgSUMJ47Rbi9FHv1TlY,2577
|
35
35
|
spiral/cli/org.py,sha256=ezWhoGUkJQQAwI1jKvDP8uZPNlnou_hXtRDa1us5cSE,2935
|
36
36
|
spiral/cli/token.py,sha256=dv30aa745bbS-c3tyzQUTSxGG_N0kCt8G4bip9fP_EM,968
|
@@ -38,38 +38,42 @@ spiral/cli/__init__.py,sha256=CoiAJ7FDgqjG_TrU-6SpP1hyZloIlEP4wcwnrF8flHM,2237
|
|
38
38
|
spiral/cli/types.py,sha256=4cphJs-i0vfq_CcnHxT9FpHiZdGwxME5GnOmIGB6Thw,1436
|
39
39
|
spiral/cli/workload.py,sha256=-XreFPJcX7kZvcYE3oQMeGkkYoXi25R5nuktJPg-PuY,2000
|
40
40
|
spiral/cli/admin.py,sha256=3pIs6PxDugMtdgzfRpn_HfBDv-cwAYtF0cJP2INB01A,579
|
41
|
-
spiral/cli/fs.py,sha256=
|
41
|
+
spiral/cli/fs.py,sha256=rgI3QNKg0_B-3T2d0KgjcLYQNc2M6sRK95cJ_J0nth0,1523
|
42
42
|
spiral/cli/app.py,sha256=2oZfDTgj_gZ-lFMMzzJJTnvVzQhp_iedvH-FJnaaMW0,1487
|
43
43
|
spiral/cli/table.py,sha256=eh2NAk0GlfvthwRNeIbcZTsRWU3ypFx_uu9OaOLHPUo,628
|
44
44
|
spiral/cli/login.py,sha256=C7VpqVyYO2daUeIWHoelWnSGN7cju8YEuqOy12ImH4c,381
|
45
45
|
spiral/cli/printer.py,sha256=5HD3UcszFfPk-dK8U5akuvtXqMB7PMgOB1DFYMqspG8,1625
|
46
46
|
spiral/cli/__main__.py,sha256=kNaKM2xgJo7GRogf83nYldLM-RGUR6vymdGwZxywQu0,71
|
47
|
-
spiral/cli/project.py,sha256=
|
47
|
+
spiral/cli/project.py,sha256=N9ocPRtjLT5lfrPMGbX_-bUXP6o5gq3RpoGYQR3CJ74,4524
|
48
48
|
spiral/cli/state.py,sha256=1quvei8TnDTT6mDRo58P8FUfy4w16Z9sggBz7cFgllY,70
|
49
|
-
spiral/dataset.py,sha256=
|
49
|
+
spiral/dataset.py,sha256=53s1JGM9lQkzbZes9nXnax6XtMtCUDR0TBOeTA8wC38,14019
|
50
50
|
spiral/grpc_.py,sha256=f3czdP1Mxme42Y5--a5ogYq1TTiWn-J_MlGjwJ2mWwM,1015
|
51
51
|
spiral/debug.py,sha256=t590eAUtNWwMTsSdkjVNN7J1iMqY2p4PRJ3BWR_ozho,8999
|
52
|
-
spiral/expressions/tiff.py,sha256=
|
52
|
+
spiral/expressions/tiff.py,sha256=fQwIn0kLFBM2Y3YYIHmTgb_EIRHKT2fNc77nioDQQw4,8044
|
53
53
|
spiral/expressions/io.py,sha256=gJ2a0FKMmdxarWKENulPRwH7KDvSJTIh_OUxX306xAM,3045
|
54
|
-
spiral/expressions/__init__.py,sha256=
|
54
|
+
spiral/expressions/__init__.py,sha256=LqvssKQTvoyX4s5UIG_HtYZbt5i5EkghkEpsE_37MWg,6118
|
55
|
+
spiral/expressions/png.py,sha256=3SjreqYcnDL4_EWMENcaGpZVoXR49KAfJiERkFSdT-w,511
|
55
56
|
spiral/expressions/list_.py,sha256=nbo4xQAuqBsQGajq_JgORaJl8_CDvOAv14zMbqmtZh4,1814
|
56
57
|
spiral/expressions/http.py,sha256=begUydWoFHEqjeLkATvI_v66Ez6_rR-OQBWO5cHbb9c,2742
|
57
|
-
spiral/expressions/refs.py,sha256=
|
58
|
+
spiral/expressions/refs.py,sha256=EndnGTLSA-s3hD6QOkxfUSWpw2IUm1hnKyyiPIlhZ7I,2370
|
58
59
|
spiral/expressions/udf.py,sha256=vOlrdxiVpt7vdSgiTKX_XR86YKyu02Fdwb9xlINCby4,1363
|
60
|
+
spiral/expressions/mp4.py,sha256=0qhTP4HGI0WL-nVhke-ykqEnOYcb64Aqryplgelv-BA,2437
|
59
61
|
spiral/expressions/str_.py,sha256=tY8RXW3JWvr1-bEfCZtk5FAf11wKJnXPuA9EoeJ9tA4,1265
|
62
|
+
spiral/expressions/qoi.py,sha256=FCAsoF-3ur7CMIk2Oz5Hm4qDdb901E_7_-aKT8yss6E,511
|
60
63
|
spiral/expressions/base.py,sha256=mTBwS6CwdDaV8uotjZUiKi7GHQzX2TRPpnseJJUDrR0,4776
|
61
64
|
spiral/expressions/struct.py,sha256=MuxoBP6ESpwmjzusG-_HxHGYKvQQz6AZWzvw7vNUHJM,2007
|
62
|
-
spiral/settings.py,sha256=
|
65
|
+
spiral/settings.py,sha256=H0ELgA1k_YENufIWscXV7gzdU8t7JOCw0AdUDVvCFH0,4704
|
63
66
|
spiral/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
64
|
-
spiral/api/filesystems.py,sha256=
|
67
|
+
spiral/api/filesystems.py,sha256=_JWFbggORWOAg0yKASsEXbu8Vk-hIMOiiVrwcEcm_RA,3424
|
65
68
|
spiral/api/workloads.py,sha256=4MWs2pp9AWvx6cZhgyW-ehyCRxpHc_NAQgHaoYOEBfg,1266
|
66
|
-
spiral/api/__init__.py,sha256=
|
69
|
+
spiral/api/__init__.py,sha256=Wy2ZEL0balniPP7LuYLhazxI9p3ZcgZ9g_MAZLWF3Hg,6828
|
67
70
|
spiral/api/tokens.py,sha256=WaSRr_l3i81t5u2qi3kWW-fySbyKFm-PQK1ZlmoSByc,1464
|
68
71
|
spiral/api/admin.py,sha256=HJBrRJScbcdDuFhF_06E0EyE-_Y0osfYPxVoRAyEoTc,837
|
69
72
|
spiral/api/organizations.py,sha256=-PO93HTX02IxhXM6SJpAhnAXpVW1WjthFO4-AOzZAC4,2670
|
70
|
-
spiral/api/tables.py,sha256=
|
73
|
+
spiral/api/tables.py,sha256=3Kt0tPfu3jQGIIAMUSNAMRtDRGK-STRYoHHgzZ4qFNU,2532
|
71
74
|
spiral/api/projects.py,sha256=-VGlu5V3TJ3XLCGu85bPHRFiktIADnAxfLWIH8Rmxug,4986
|
72
|
-
spiral/
|
75
|
+
spiral/txn.py,sha256=SIww2vAazE1nPxyAkeiN7NMvXmBK6jHhFM_uMkEUW0o,1508
|
76
|
+
spiral/table.py,sha256=HzSRNQAI9YscdfmeHlwZcIdrK2SJ9wWq-GRRCmint_M,5541
|
73
77
|
spiral/authn/modal_.py,sha256=agcnR3dYTslkH2K_a2Eis_2JWn9Ps11FVrGG_jkOdGk,472
|
74
78
|
spiral/authn/device.py,sha256=ohHSVLW3a-qLNYQGN-3kXxV_836xOe0UYBN8i63cqAQ,6796
|
75
79
|
spiral/authn/authn.py,sha256=OCGJAUfoKLiXw9xAcAnX6i6mBRlvsl6qEFcimqQOu7g,2555
|
@@ -77,5 +81,5 @@ spiral/authn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
77
81
|
spiral/authn/github_.py,sha256=K-0RUHDreINjnCDHyT9aeVDRk6WtNP7noBYEcwdz2W4,1313
|
78
82
|
spiral/adbc.py,sha256=H_bzevPy5teyZKzjczh1gQ_zPcfk5sNASiJKQvyab9E,13830
|
79
83
|
spiral/project.py,sha256=q9jHql7hz5OQzPfDfvE_hN3K9cZotD0cxkdug9EUTwM,4889
|
80
|
-
spiral/_lib.abi3.so,sha256=
|
81
|
-
pyspiral-0.
|
84
|
+
spiral/_lib.abi3.so,sha256=p285aXvfZS7XzjXERyb5tsrH0fwq9rVdZ0hX4rvbkrA,64644032
|
85
|
+
pyspiral-0.3.1.dist-info/RECORD,,
|
spiral/__init__.py
CHANGED
@@ -2,10 +2,12 @@
|
|
2
2
|
|
3
3
|
from spiral import _lib
|
4
4
|
from spiral.catalog import Spiral
|
5
|
+
from spiral.maintenance import Maintenance
|
5
6
|
from spiral.scan_ import Scan, scan
|
6
7
|
from spiral.table import Table
|
8
|
+
from spiral.txn import Transaction
|
7
9
|
|
8
10
|
# Eagerly import the Spiral library
|
9
11
|
assert _lib, "Spiral library"
|
10
12
|
|
11
|
-
__all__ = ["scan", "Scan", "Table", "Spiral"]
|
13
|
+
__all__ = ["scan", "Scan", "Table", "Spiral", "Transaction", "Maintenance"]
|
spiral/_lib.abi3.so
CHANGED
Binary file
|
spiral/api/__init__.py
CHANGED
@@ -118,20 +118,25 @@ class _Client:
|
|
118
118
|
self.http = http
|
119
119
|
self.authn = authn
|
120
120
|
|
121
|
+
def get(self, path: str, response_cls: type[ResponseT]) -> ResponseT:
|
122
|
+
return self.request("GET", path, None, response_cls)
|
123
|
+
|
121
124
|
def post(self, path: str, req: RequestT, response_cls: type[ResponseT]) -> ResponseT:
|
122
125
|
return self.request("POST", path, req, response_cls)
|
123
126
|
|
124
127
|
def put(self, path: str, req: RequestT, response_cls: type[ResponseT]) -> ResponseT:
|
125
128
|
return self.request("PUT", path, req, response_cls)
|
126
129
|
|
127
|
-
def request(self, method: str, path: str, req: RequestT, response_cls: type[ResponseT]) -> ResponseT:
|
130
|
+
def request(self, method: str, path: str, req: RequestT | None, response_cls: type[ResponseT]) -> ResponseT:
|
128
131
|
if isinstance(req, betterproto.Message):
|
129
132
|
try:
|
130
133
|
req = dict(content=bytes(req))
|
131
134
|
except:
|
132
135
|
raise
|
133
|
-
|
136
|
+
elif req is not None:
|
134
137
|
req = dict(json=TypeAdapter(req.__class__).dump_python(req, mode="json") if req is not None else None)
|
138
|
+
else:
|
139
|
+
req = dict()
|
135
140
|
|
136
141
|
token = self.authn.token()
|
137
142
|
resp = self.http.request(method, path, headers={"authorization": f"Bearer {token}" if token else None}, **req)
|
@@ -157,8 +162,7 @@ class SpiralAPI:
|
|
157
162
|
self.client = _Client(
|
158
163
|
httpx.Client(
|
159
164
|
base_url=self.base_url,
|
160
|
-
timeout=60,
|
161
|
-
# timeout=None if ("PYTEST_VERSION" in os.environ or bool(os.environ.get("SPIRAL_DEV", None))) else 60,
|
165
|
+
timeout=None if ("PYTEST_VERSION" in os.environ or bool(os.environ.get("SPIRAL_DEV", None))) else 60,
|
162
166
|
),
|
163
167
|
authn,
|
164
168
|
)
|
spiral/api/filesystems.py
CHANGED
@@ -122,4 +122,4 @@ class FileSystemService(ServiceBase):
|
|
122
122
|
return self.client.post("/file-system/create-mount", request, CreateMount.Response)
|
123
123
|
|
124
124
|
def create_mount_token(self, request: CreateMountToken.Request) -> CreateMountToken.Response:
|
125
|
-
return self.client.post("/file-system/
|
125
|
+
return self.client.post("/file-system/mount-token", request, CreateMountToken.Response)
|
spiral/api/tables.py
CHANGED
@@ -1,10 +1,6 @@
|
|
1
1
|
from typing import Annotated
|
2
2
|
|
3
|
-
from pydantic import
|
4
|
-
AfterValidator,
|
5
|
-
BaseModel,
|
6
|
-
StringConstraints,
|
7
|
-
)
|
3
|
+
from pydantic import AfterValidator, BaseModel, StringConstraints
|
8
4
|
|
9
5
|
from . import ArrowSchema, Paged, PagedRequest, PagedResponse, ProjectId, ServiceBase
|
10
6
|
|
@@ -21,10 +17,11 @@ TableName = Annotated[str, StringConstraints(max_length=128, pattern=r"^[a-zA-Z_
|
|
21
17
|
|
22
18
|
|
23
19
|
class TableMetadata(BaseModel):
|
24
|
-
key_schema: ArrowSchema
|
25
20
|
root_uri: RootUri
|
26
21
|
spfs_mount_id: str | None = None
|
27
22
|
|
23
|
+
key_schema: ArrowSchema
|
24
|
+
|
28
25
|
# TODO(marko): Randomize this on creation of metadata.
|
29
26
|
# Column group salt is used to compute column group IDs.
|
30
27
|
# It's used to ensure that column group IDs are unique
|
spiral/catalog.py
CHANGED
@@ -7,6 +7,8 @@ from spiral.api.projects import CreateProject
|
|
7
7
|
from spiral.settings import Settings, settings
|
8
8
|
|
9
9
|
if TYPE_CHECKING:
|
10
|
+
from pyiceberg import catalog
|
11
|
+
|
10
12
|
from spiral.project import Project
|
11
13
|
from spiral.table import Table
|
12
14
|
|
@@ -76,3 +78,16 @@ class Spiral:
|
|
76
78
|
project_id, dataset, table = parts
|
77
79
|
|
78
80
|
return self.project(project_id).table(f"{dataset}.{table}")
|
81
|
+
|
82
|
+
def iceberg_catalog(self) -> "catalog.Catalog":
|
83
|
+
"""Open the Iceberg catalog."""
|
84
|
+
from pyiceberg.catalog import load_catalog
|
85
|
+
|
86
|
+
return load_catalog(
|
87
|
+
"default",
|
88
|
+
**{
|
89
|
+
"type": "rest",
|
90
|
+
"uri": self._config.spiraldb.uri_iceberg,
|
91
|
+
"token": self._config.authn.token(),
|
92
|
+
},
|
93
|
+
)
|
spiral/cli/fs.py
CHANGED
@@ -23,7 +23,7 @@ def show(project: ProjectArg):
|
|
23
23
|
|
24
24
|
def _provider_default():
|
25
25
|
res = state.settings.api.file_system.list_providers()
|
26
|
-
questionary.select("Select a file system provider", choices=res.providers).ask()
|
26
|
+
return questionary.select("Select a file system provider", choices=res.providers).ask()
|
27
27
|
|
28
28
|
|
29
29
|
ProviderOpt = Annotated[
|
@@ -37,7 +37,7 @@ def update(project: ProjectArg, provider: ProviderOpt):
|
|
37
37
|
res = state.settings.api.file_system.update_file_system(
|
38
38
|
UpdateFileSystem.Request(project_id=project, file_system=BuiltinFileSystem(provider=provider))
|
39
39
|
)
|
40
|
-
rich.print(res.file_system
|
40
|
+
rich.print(res.file_system)
|
41
41
|
|
42
42
|
|
43
43
|
@app.command(help="Lists the available built-in file system providers.")
|
spiral/cli/project.py
CHANGED
@@ -55,11 +55,13 @@ def grant(
|
|
55
55
|
OptionalStr,
|
56
56
|
Option(help="Pass a `<workspace_id>/<env_name>` string to grant a role to a job running in Modal environment."),
|
57
57
|
] = None,
|
58
|
-
conditions: list[str] = Option(
|
59
|
-
|
58
|
+
conditions: list[str] | None = Option(
|
59
|
+
default=None,
|
60
60
|
help="`<key>=<value>` token conditions to apply to the grant when using --github or --modal.",
|
61
61
|
),
|
62
62
|
):
|
63
|
+
conditions = conditions or []
|
64
|
+
|
63
65
|
# Check mutual exclusion
|
64
66
|
if sum(int(bool(opt)) for opt in {org_id, workload_id, github, modal}) != 1:
|
65
67
|
raise typer.BadParameter("Only one of --org-id, --github or --modal may be specified.")
|
@@ -81,7 +83,7 @@ def grant(
|
|
81
83
|
|
82
84
|
if user_id is not None:
|
83
85
|
principal = GrantRole.OrgUserPrincipal(org_id=org_id, user_id=user_id)
|
84
|
-
elif org_role is None:
|
86
|
+
elif org_role is not None:
|
85
87
|
principal = GrantRole.OrgRolePrincipal(org_id=org_id, role=OrganizationRole(org_role))
|
86
88
|
else:
|
87
89
|
raise NotImplementedError("Only user or role principal is supported at this time.")
|
spiral/core/core/__init__.pyi
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
from typing import Any
|
1
|
+
from typing import Any, Literal
|
2
2
|
|
3
3
|
import pyarrow as pa
|
4
4
|
from spiral.core.manifests import FragmentManifest
|
5
5
|
from spiral.core.metastore import PyMetastore
|
6
|
-
from spiral.core.spec import ColumnGroup, ColumnGroupMetadata, KeyRange, Schema, WriteAheadLog
|
6
|
+
from spiral.core.spec import ColumnGroup, ColumnGroupMetadata, FileFormat, KeyRange, Schema, WriteAheadLog
|
7
7
|
from spiral.expressions import Expr
|
8
8
|
|
9
9
|
class Table:
|
@@ -15,9 +15,9 @@ class Table:
|
|
15
15
|
metastore: PyMetastore
|
16
16
|
|
17
17
|
def get_wal(self, *, asof: int | None) -> WriteAheadLog: ...
|
18
|
+
def get_schema(self, *, asof: int | None) -> Schema: ...
|
18
19
|
def get_column_group_metadata(self, column_group: ColumnGroup, *, asof: int | None) -> ColumnGroupMetadata: ...
|
19
20
|
def list_column_groups(self, *, asof: int | None) -> list[ColumnGroup] | None: ...
|
20
|
-
def get_schema(self, *, asof: int | None) -> Schema: ...
|
21
21
|
|
22
22
|
class TableScan:
|
23
23
|
def __init__(
|
@@ -34,7 +34,11 @@ class TableScan:
|
|
34
34
|
def split(self) -> list[KeyRange]: ...
|
35
35
|
def table_ids(self) -> list[str]: ...
|
36
36
|
def column_groups(self) -> list[ColumnGroup]: ...
|
37
|
-
def to_record_batches(
|
37
|
+
def to_record_batches(
|
38
|
+
self,
|
39
|
+
key_table: pa.Table | pa.RecordBatch | None = None,
|
40
|
+
batch_readahead: int | None = None,
|
41
|
+
) -> pa.RecordBatchReader: ...
|
38
42
|
def column_group_scan(self, column_group: ColumnGroup) -> ColumnGroupScan: ...
|
39
43
|
def key_space_scan(self, table_id: str) -> KeySpaceScan: ...
|
40
44
|
def metrics(self) -> dict[str, Any]: ...
|
@@ -49,5 +53,29 @@ class ColumnGroupScan:
|
|
49
53
|
|
50
54
|
def schema(self) -> Schema: ...
|
51
55
|
|
52
|
-
|
53
|
-
def
|
56
|
+
class TableTransaction:
|
57
|
+
def __init__(self, metastore: PyMetastore, format: FileFormat): ...
|
58
|
+
@property
|
59
|
+
def status(self) -> str: ...
|
60
|
+
def write(self, expr: Expr, *, partition_size_bytes: int | None = None): ...
|
61
|
+
def commit(self): ...
|
62
|
+
def abort(self): ...
|
63
|
+
def metrics(self) -> dict[str, Any]: ...
|
64
|
+
|
65
|
+
class TableMaintenance:
|
66
|
+
def __init__(self, metastore: PyMetastore, format: FileFormat): ...
|
67
|
+
def flush_wal(self): ...
|
68
|
+
def compact_key_space(
|
69
|
+
self,
|
70
|
+
*,
|
71
|
+
mode: Literal["plan", "read", "write"] | None = None,
|
72
|
+
partition_bytes_min: int | None = None,
|
73
|
+
): ...
|
74
|
+
def compact_column_group(
|
75
|
+
self,
|
76
|
+
column_group: ColumnGroup,
|
77
|
+
*,
|
78
|
+
mode: Literal["plan", "read", "write"] | None = None,
|
79
|
+
partition_bytes_min: int | None = None,
|
80
|
+
): ...
|
81
|
+
def metrics(self) -> dict[str, Any]: ...
|
spiral/core/spec/__init__.pyi
CHANGED
@@ -59,37 +59,13 @@ class LogEntry:
|
|
59
59
|
def column_group(self) -> ColumnGroup | None:
|
60
60
|
"""Returns the column group of the entry if it is associated with one."""
|
61
61
|
|
62
|
-
def replace_timestamp(self, ts: int) -> LogEntry:
|
63
|
-
"""Returns a copy of the entry with the timestamp replaced."""
|
64
|
-
|
65
|
-
@staticmethod
|
66
|
-
def schema_break(*, column_group: ColumnGroup, removed_column_names: list[str]) -> LogEntry: ...
|
67
|
-
@staticmethod
|
68
|
-
def schema_evolution(*, column_group: ColumnGroup, new_schema: Schema) -> LogEntry: ...
|
69
|
-
@staticmethod
|
70
|
-
def ks_write(
|
71
|
-
*,
|
72
|
-
ks_id: str,
|
73
|
-
manifest_handle: ManifestHandle,
|
74
|
-
) -> LogEntry: ...
|
75
|
-
@staticmethod
|
76
|
-
def fs_write(
|
77
|
-
*,
|
78
|
-
column_group: ColumnGroup,
|
79
|
-
fs_id: str,
|
80
|
-
fs_level: FragmentLevel,
|
81
|
-
manifest_handle: ManifestHandle,
|
82
|
-
key_span: KeySpan,
|
83
|
-
key_extent: KeyExtent,
|
84
|
-
column_ids: list[str],
|
85
|
-
) -> LogEntry: ...
|
86
|
-
|
87
62
|
class FileFormat:
|
88
63
|
def __init__(self, value: int): ...
|
89
64
|
|
90
65
|
Parquet: FileFormat
|
91
66
|
Protobuf: FileFormat
|
92
67
|
BinaryArray: FileFormat
|
68
|
+
Vortex: FileFormat
|
93
69
|
|
94
70
|
def __int__(self) -> int:
|
95
71
|
"""Returns the protobuf enum int value."""
|
@@ -194,11 +170,17 @@ class Schema:
|
|
194
170
|
def to_arrow(self) -> pa.Schema:
|
195
171
|
"""Returns the Arrow schema."""
|
196
172
|
...
|
197
|
-
|
198
173
|
@staticmethod
|
199
174
|
def from_arrow(arrow: pa.Schema) -> Schema:
|
200
175
|
"""Creates a Schema from an Arrow schema."""
|
201
176
|
...
|
177
|
+
def __len__(self):
|
178
|
+
"""Returns the number of columns in the schema."""
|
179
|
+
...
|
180
|
+
@property
|
181
|
+
def names(self) -> list[str]:
|
182
|
+
"""Returns the names of the columns in the schema."""
|
183
|
+
...
|
202
184
|
|
203
185
|
class VersionedSchema:
|
204
186
|
ts: int
|