pyspiral 0.7.18__cp312-abi3-manylinux_2_28_x86_64.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 (110) hide show
  1. pyspiral-0.7.18.dist-info/METADATA +52 -0
  2. pyspiral-0.7.18.dist-info/RECORD +110 -0
  3. pyspiral-0.7.18.dist-info/WHEEL +4 -0
  4. pyspiral-0.7.18.dist-info/entry_points.txt +3 -0
  5. spiral/__init__.py +55 -0
  6. spiral/_lib.abi3.so +0 -0
  7. spiral/adbc.py +411 -0
  8. spiral/api/__init__.py +78 -0
  9. spiral/api/admin.py +15 -0
  10. spiral/api/client.py +164 -0
  11. spiral/api/filesystems.py +134 -0
  12. spiral/api/key_space_indexes.py +23 -0
  13. spiral/api/organizations.py +77 -0
  14. spiral/api/projects.py +219 -0
  15. spiral/api/telemetry.py +19 -0
  16. spiral/api/text_indexes.py +56 -0
  17. spiral/api/types.py +23 -0
  18. spiral/api/workers.py +40 -0
  19. spiral/api/workloads.py +52 -0
  20. spiral/arrow_.py +216 -0
  21. spiral/cli/__init__.py +88 -0
  22. spiral/cli/__main__.py +4 -0
  23. spiral/cli/admin.py +14 -0
  24. spiral/cli/app.py +108 -0
  25. spiral/cli/console.py +95 -0
  26. spiral/cli/fs.py +76 -0
  27. spiral/cli/iceberg.py +97 -0
  28. spiral/cli/key_spaces.py +103 -0
  29. spiral/cli/login.py +25 -0
  30. spiral/cli/orgs.py +90 -0
  31. spiral/cli/printer.py +53 -0
  32. spiral/cli/projects.py +147 -0
  33. spiral/cli/state.py +7 -0
  34. spiral/cli/tables.py +197 -0
  35. spiral/cli/telemetry.py +17 -0
  36. spiral/cli/text.py +115 -0
  37. spiral/cli/types.py +50 -0
  38. spiral/cli/workloads.py +58 -0
  39. spiral/client.py +256 -0
  40. spiral/core/__init__.pyi +0 -0
  41. spiral/core/_tools/__init__.pyi +5 -0
  42. spiral/core/authn/__init__.pyi +21 -0
  43. spiral/core/client/__init__.pyi +285 -0
  44. spiral/core/config/__init__.pyi +35 -0
  45. spiral/core/expr/__init__.pyi +15 -0
  46. spiral/core/expr/images/__init__.pyi +3 -0
  47. spiral/core/expr/list_/__init__.pyi +4 -0
  48. spiral/core/expr/refs/__init__.pyi +4 -0
  49. spiral/core/expr/str_/__init__.pyi +3 -0
  50. spiral/core/expr/struct_/__init__.pyi +6 -0
  51. spiral/core/expr/text/__init__.pyi +5 -0
  52. spiral/core/expr/udf/__init__.pyi +14 -0
  53. spiral/core/expr/video/__init__.pyi +3 -0
  54. spiral/core/table/__init__.pyi +141 -0
  55. spiral/core/table/manifests/__init__.pyi +35 -0
  56. spiral/core/table/metastore/__init__.pyi +58 -0
  57. spiral/core/table/spec/__init__.pyi +215 -0
  58. spiral/dataloader.py +299 -0
  59. spiral/dataset.py +264 -0
  60. spiral/datetime_.py +27 -0
  61. spiral/debug/__init__.py +0 -0
  62. spiral/debug/manifests.py +87 -0
  63. spiral/debug/metrics.py +56 -0
  64. spiral/debug/scan.py +266 -0
  65. spiral/enrichment.py +306 -0
  66. spiral/expressions/__init__.py +274 -0
  67. spiral/expressions/base.py +167 -0
  68. spiral/expressions/file.py +17 -0
  69. spiral/expressions/http.py +17 -0
  70. spiral/expressions/list_.py +68 -0
  71. spiral/expressions/s3.py +16 -0
  72. spiral/expressions/str_.py +39 -0
  73. spiral/expressions/struct.py +59 -0
  74. spiral/expressions/text.py +62 -0
  75. spiral/expressions/tiff.py +222 -0
  76. spiral/expressions/udf.py +60 -0
  77. spiral/grpc_.py +32 -0
  78. spiral/iceberg.py +31 -0
  79. spiral/iterable_dataset.py +106 -0
  80. spiral/key_space_index.py +44 -0
  81. spiral/project.py +227 -0
  82. spiral/protogen/_/__init__.py +0 -0
  83. spiral/protogen/_/arrow/__init__.py +0 -0
  84. spiral/protogen/_/arrow/flight/__init__.py +0 -0
  85. spiral/protogen/_/arrow/flight/protocol/__init__.py +0 -0
  86. spiral/protogen/_/arrow/flight/protocol/sql/__init__.py +2548 -0
  87. spiral/protogen/_/google/__init__.py +0 -0
  88. spiral/protogen/_/google/protobuf/__init__.py +2310 -0
  89. spiral/protogen/_/message_pool.py +3 -0
  90. spiral/protogen/_/py.typed +0 -0
  91. spiral/protogen/_/scandal/__init__.py +190 -0
  92. spiral/protogen/_/spfs/__init__.py +72 -0
  93. spiral/protogen/_/spql/__init__.py +61 -0
  94. spiral/protogen/_/substrait/__init__.py +6196 -0
  95. spiral/protogen/_/substrait/extensions/__init__.py +169 -0
  96. spiral/protogen/__init__.py +0 -0
  97. spiral/protogen/util.py +41 -0
  98. spiral/py.typed +0 -0
  99. spiral/scan.py +363 -0
  100. spiral/server.py +17 -0
  101. spiral/settings.py +36 -0
  102. spiral/snapshot.py +56 -0
  103. spiral/streaming_/__init__.py +3 -0
  104. spiral/streaming_/reader.py +133 -0
  105. spiral/streaming_/stream.py +157 -0
  106. spiral/substrait_.py +274 -0
  107. spiral/table.py +224 -0
  108. spiral/text_index.py +17 -0
  109. spiral/transaction.py +155 -0
  110. spiral/types_.py +6 -0
spiral/project.py ADDED
@@ -0,0 +1,227 @@
1
+ from typing import TYPE_CHECKING, Any
2
+
3
+ import pyarrow as pa
4
+
5
+ from spiral.api.projects import KeySpaceIndexResource, TableResource, TextIndexResource
6
+ from spiral.core.table.spec import Schema
7
+ from spiral.expressions import ExprLike
8
+ from spiral.key_space_index import KeySpaceIndex
9
+ from spiral.table import Table
10
+ from spiral.text_index import TextIndex
11
+ from spiral.types_ import Uri
12
+
13
+ if TYPE_CHECKING:
14
+ from spiral.client import Spiral
15
+
16
+
17
+ class Project:
18
+ def __init__(self, spiral: "Spiral", project_id: str, name: str | None = None):
19
+ self._spiral = spiral
20
+ self._id = project_id
21
+ self._name = name
22
+
23
+ def __str__(self):
24
+ return self._id
25
+
26
+ def __repr__(self):
27
+ return f"Project(id={self._id}{', name=' + self._name if self._name else ''})"
28
+
29
+ @property
30
+ def id(self) -> str:
31
+ return self._id
32
+
33
+ @property
34
+ def name(self) -> str:
35
+ return self._name or self._id
36
+
37
+ def list_tables(self) -> list[TableResource]:
38
+ return list(self._spiral.api.project.list_tables(self._id))
39
+
40
+ def list_text_indexes(self) -> list[TextIndexResource]:
41
+ return list(self._spiral.api.project.list_text_indexes(self._id))
42
+
43
+ def list_key_space_indexes(self) -> list[KeySpaceIndexResource]:
44
+ return list(self._spiral.api.project.list_key_space_indexes(self._id))
45
+
46
+ def table(self, identifier: str) -> Table:
47
+ """Open a table with a `dataset.table` identifier, or `table` name using the `default` dataset."""
48
+ dataset, table = self._parse_table_identifier(identifier)
49
+
50
+ res = list(self._spiral.api.project.list_tables(project_id=self._id, dataset=dataset, table=table))
51
+ if len(res) == 0:
52
+ raise ValueError(f"Table not found: {self._id}.{dataset}.{table}")
53
+ res = res[0]
54
+
55
+ return Table(
56
+ self._spiral, self._spiral.core.table(res.id), identifier=f"{res.project_id}.{res.dataset}.{res.table}"
57
+ )
58
+
59
+ def create_table(
60
+ self,
61
+ identifier: str,
62
+ *,
63
+ key_schema: pa.Schema | Any,
64
+ root_uri: Uri | None = None,
65
+ exist_ok: bool = False,
66
+ ) -> Table:
67
+ """Create a new table in the project.
68
+
69
+ Args:
70
+ identifier: The table identifier, in the form `dataset.table` or `table`.
71
+ key_schema: The schema of the table's keys.
72
+ root_uri: The root URI for the table.
73
+ exist_ok: If True, do not raise an error if the table already exists.
74
+ """
75
+ dataset, table = self._parse_table_identifier(identifier)
76
+
77
+ if not isinstance(key_schema, pa.Schema):
78
+ key_schema = pa.schema(key_schema)
79
+ key_schema = Schema.from_arrow(key_schema)
80
+
81
+ core_table = self._spiral.core.create_table(
82
+ project_id=self._id,
83
+ dataset=dataset,
84
+ table=table,
85
+ key_schema=key_schema,
86
+ root_uri=root_uri,
87
+ exist_ok=exist_ok,
88
+ )
89
+
90
+ return Table(self._spiral, core_table, identifier=f"{self._id}.{dataset}.{table}")
91
+
92
+ def move_table(self, identifier: str, new_dataset: str):
93
+ """Move a table to a new dataset in the project.
94
+
95
+ Args:
96
+ identifier: The table identifier, in the form `dataset.table` or `table`.
97
+ new_dataset: The dataset into which to move this table.
98
+ """
99
+ table = self.table(identifier)
100
+
101
+ self._spiral.core.move_table(
102
+ table_id=table.table_id,
103
+ new_dataset=new_dataset,
104
+ )
105
+
106
+ def rename_table(self, identifier: str, new_table: str):
107
+ """Move a table to a new dataset in the project.
108
+
109
+ Args:
110
+ identifier: The table identifier, in the form `dataset.table` or `table`.
111
+ new_dataset: The dataset into which to move this table.
112
+ """
113
+ table = self.table(identifier)
114
+
115
+ self._spiral.core.rename_table(
116
+ table_id=table.table_id,
117
+ new_table=new_table,
118
+ )
119
+
120
+ def _parse_table_identifier(self, identifier: str) -> tuple[str, str]:
121
+ parts = identifier.split(".")
122
+ if len(parts) == 1:
123
+ return "default", parts[0]
124
+ elif len(parts) == 2:
125
+ return parts[0], parts[1]
126
+ else:
127
+ raise ValueError(f"Invalid table identifier: {self._id}.{identifier}")
128
+
129
+ def text_index(self, name: str) -> TextIndex:
130
+ """Returns the index with the given name."""
131
+ res = list(self._spiral.api.project.list_text_indexes(project_id=self._id, name=name))
132
+ if len(res) == 0:
133
+ raise ValueError(f"Index not found: {name}")
134
+ res = res[0]
135
+
136
+ return TextIndex(self._spiral.core.text_index(res.id), name=name)
137
+
138
+ def create_text_index(
139
+ self,
140
+ name: str,
141
+ *projections: ExprLike,
142
+ where: ExprLike | None = None,
143
+ root_uri: Uri | None = None,
144
+ exist_ok: bool = False,
145
+ ) -> TextIndex:
146
+ """Creates a text index over the table projection.
147
+
148
+ See `se.text.field` for how to create and configure indexable fields.
149
+
150
+ Args:
151
+ name: The index name. Must be unique within the project.
152
+ projections: At least one projection expression is required.
153
+ All projections must reference the same table.
154
+ where: An optional filter expression to apply to the index.
155
+ root_uri: The root URI for the index.
156
+ exist_ok: If True, do not raise an error if the index already exists.
157
+ """
158
+ from spiral import expressions as se
159
+
160
+ if not projections:
161
+ raise ValueError("At least one projection is required.")
162
+ projection = se.merge(*projections)
163
+ if where is not None:
164
+ where = se.lift(where)
165
+
166
+ core_index = self._spiral.core.create_text_index(
167
+ project_id=self._id,
168
+ name=name,
169
+ projection=projection.__expr__,
170
+ filter=where.__expr__ if where else None,
171
+ root_uri=root_uri,
172
+ # TODO(marko): Validate that if an index exists, it's the same?
173
+ exist_ok=exist_ok,
174
+ )
175
+
176
+ return TextIndex(core_index, name=name)
177
+
178
+ def key_space_index(self, name: str) -> KeySpaceIndex:
179
+ """Returns the index with the given name."""
180
+ res = list(self._spiral.api.project.list_key_space_indexes(project_id=self._id, name=name))
181
+ if len(res) == 0:
182
+ raise ValueError(f"Index not found: {name}")
183
+ res = res[0]
184
+
185
+ return KeySpaceIndex(self._spiral.core.key_space_index(res.id), name=name)
186
+
187
+ def create_key_space_index(
188
+ self,
189
+ name: str,
190
+ granularity: int,
191
+ *projections: ExprLike,
192
+ where: ExprLike | None = None,
193
+ root_uri: Uri | None = None,
194
+ exist_ok: bool = False,
195
+ ) -> KeySpaceIndex:
196
+ """Creates a key space index over the table projection.
197
+
198
+ Args:
199
+ name: The index name. Must be unique within the project.
200
+ granularity: The granularity at which to store keys, i.e. the size of desired key ranges.
201
+ The key ranges will not be greater than 2x the granularity, but may be smaller.
202
+ projections: At least one projection expression is required.
203
+ All projections must reference the same table.
204
+ where: An optional filter expression to apply to the index.
205
+ root_uri: The root URI for the index.
206
+ exist_ok: If True, do not raise an error if the index already exists.
207
+ """
208
+ from spiral import expressions as se
209
+
210
+ if not projections:
211
+ raise ValueError("At least one projection is required.")
212
+ projection = se.merge(*projections)
213
+ if where is not None:
214
+ where = se.lift(where)
215
+
216
+ core_index = self._spiral.core.create_key_space_index(
217
+ project_id=self._id,
218
+ name=name,
219
+ granularity=granularity,
220
+ projection=projection.__expr__,
221
+ filter=where.__expr__ if where else None,
222
+ root_uri=root_uri,
223
+ # TODO(marko): Validate that if an index exists, it's the same?
224
+ exist_ok=exist_ok,
225
+ )
226
+
227
+ return KeySpaceIndex(core_index, name=name)
File without changes
File without changes
File without changes
File without changes