pixeltable 0.2.26__py3-none-any.whl → 0.5.7__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.
- pixeltable/__init__.py +83 -19
- pixeltable/_query.py +1444 -0
- pixeltable/_version.py +1 -0
- pixeltable/catalog/__init__.py +7 -4
- pixeltable/catalog/catalog.py +2394 -119
- pixeltable/catalog/column.py +225 -104
- pixeltable/catalog/dir.py +38 -9
- pixeltable/catalog/globals.py +53 -34
- pixeltable/catalog/insertable_table.py +265 -115
- pixeltable/catalog/path.py +80 -17
- pixeltable/catalog/schema_object.py +28 -43
- pixeltable/catalog/table.py +1270 -677
- pixeltable/catalog/table_metadata.py +103 -0
- pixeltable/catalog/table_version.py +1270 -751
- pixeltable/catalog/table_version_handle.py +109 -0
- pixeltable/catalog/table_version_path.py +137 -42
- pixeltable/catalog/tbl_ops.py +53 -0
- pixeltable/catalog/update_status.py +191 -0
- pixeltable/catalog/view.py +251 -134
- pixeltable/config.py +215 -0
- pixeltable/env.py +736 -285
- pixeltable/exceptions.py +26 -2
- pixeltable/exec/__init__.py +7 -2
- pixeltable/exec/aggregation_node.py +39 -21
- pixeltable/exec/cache_prefetch_node.py +87 -109
- pixeltable/exec/cell_materialization_node.py +268 -0
- pixeltable/exec/cell_reconstruction_node.py +168 -0
- pixeltable/exec/component_iteration_node.py +25 -28
- pixeltable/exec/data_row_batch.py +11 -46
- pixeltable/exec/exec_context.py +26 -11
- pixeltable/exec/exec_node.py +35 -27
- pixeltable/exec/expr_eval/__init__.py +3 -0
- pixeltable/exec/expr_eval/evaluators.py +365 -0
- pixeltable/exec/expr_eval/expr_eval_node.py +413 -0
- pixeltable/exec/expr_eval/globals.py +200 -0
- pixeltable/exec/expr_eval/row_buffer.py +74 -0
- pixeltable/exec/expr_eval/schedulers.py +413 -0
- pixeltable/exec/globals.py +35 -0
- pixeltable/exec/in_memory_data_node.py +35 -27
- pixeltable/exec/object_store_save_node.py +293 -0
- pixeltable/exec/row_update_node.py +44 -29
- pixeltable/exec/sql_node.py +414 -115
- pixeltable/exprs/__init__.py +8 -5
- pixeltable/exprs/arithmetic_expr.py +79 -45
- pixeltable/exprs/array_slice.py +5 -5
- pixeltable/exprs/column_property_ref.py +40 -26
- pixeltable/exprs/column_ref.py +254 -61
- pixeltable/exprs/comparison.py +14 -9
- pixeltable/exprs/compound_predicate.py +9 -10
- pixeltable/exprs/data_row.py +213 -72
- pixeltable/exprs/expr.py +270 -104
- pixeltable/exprs/expr_dict.py +6 -5
- pixeltable/exprs/expr_set.py +20 -11
- pixeltable/exprs/function_call.py +383 -284
- pixeltable/exprs/globals.py +18 -5
- pixeltable/exprs/in_predicate.py +7 -7
- pixeltable/exprs/inline_expr.py +37 -37
- pixeltable/exprs/is_null.py +8 -4
- pixeltable/exprs/json_mapper.py +120 -54
- pixeltable/exprs/json_path.py +90 -60
- pixeltable/exprs/literal.py +61 -16
- pixeltable/exprs/method_ref.py +7 -6
- pixeltable/exprs/object_ref.py +19 -8
- pixeltable/exprs/row_builder.py +238 -75
- pixeltable/exprs/rowid_ref.py +53 -15
- pixeltable/exprs/similarity_expr.py +65 -50
- pixeltable/exprs/sql_element_cache.py +5 -5
- pixeltable/exprs/string_op.py +107 -0
- pixeltable/exprs/type_cast.py +25 -13
- pixeltable/exprs/variable.py +2 -2
- pixeltable/func/__init__.py +9 -5
- pixeltable/func/aggregate_function.py +197 -92
- pixeltable/func/callable_function.py +119 -35
- pixeltable/func/expr_template_function.py +101 -48
- pixeltable/func/function.py +375 -62
- pixeltable/func/function_registry.py +20 -19
- pixeltable/func/globals.py +6 -5
- pixeltable/func/mcp.py +74 -0
- pixeltable/func/query_template_function.py +151 -35
- pixeltable/func/signature.py +178 -49
- pixeltable/func/tools.py +164 -0
- pixeltable/func/udf.py +176 -53
- pixeltable/functions/__init__.py +44 -4
- pixeltable/functions/anthropic.py +226 -47
- pixeltable/functions/audio.py +148 -11
- pixeltable/functions/bedrock.py +137 -0
- pixeltable/functions/date.py +188 -0
- pixeltable/functions/deepseek.py +113 -0
- pixeltable/functions/document.py +81 -0
- pixeltable/functions/fal.py +76 -0
- pixeltable/functions/fireworks.py +72 -20
- pixeltable/functions/gemini.py +249 -0
- pixeltable/functions/globals.py +208 -53
- pixeltable/functions/groq.py +108 -0
- pixeltable/functions/huggingface.py +1088 -95
- pixeltable/functions/image.py +155 -84
- pixeltable/functions/json.py +8 -11
- pixeltable/functions/llama_cpp.py +31 -19
- pixeltable/functions/math.py +169 -0
- pixeltable/functions/mistralai.py +50 -75
- pixeltable/functions/net.py +70 -0
- pixeltable/functions/ollama.py +29 -36
- pixeltable/functions/openai.py +548 -160
- pixeltable/functions/openrouter.py +143 -0
- pixeltable/functions/replicate.py +15 -14
- pixeltable/functions/reve.py +250 -0
- pixeltable/functions/string.py +310 -85
- pixeltable/functions/timestamp.py +37 -19
- pixeltable/functions/together.py +77 -120
- pixeltable/functions/twelvelabs.py +188 -0
- pixeltable/functions/util.py +7 -2
- pixeltable/functions/uuid.py +30 -0
- pixeltable/functions/video.py +1528 -117
- pixeltable/functions/vision.py +26 -26
- pixeltable/functions/voyageai.py +289 -0
- pixeltable/functions/whisper.py +19 -10
- pixeltable/functions/whisperx.py +179 -0
- pixeltable/functions/yolox.py +112 -0
- pixeltable/globals.py +716 -236
- pixeltable/index/__init__.py +3 -1
- pixeltable/index/base.py +17 -21
- pixeltable/index/btree.py +32 -22
- pixeltable/index/embedding_index.py +155 -92
- pixeltable/io/__init__.py +12 -7
- pixeltable/io/datarows.py +140 -0
- pixeltable/io/external_store.py +83 -125
- pixeltable/io/fiftyone.py +24 -33
- pixeltable/io/globals.py +47 -182
- pixeltable/io/hf_datasets.py +96 -127
- pixeltable/io/label_studio.py +171 -156
- pixeltable/io/lancedb.py +3 -0
- pixeltable/io/pandas.py +136 -115
- pixeltable/io/parquet.py +40 -153
- pixeltable/io/table_data_conduit.py +702 -0
- pixeltable/io/utils.py +100 -0
- pixeltable/iterators/__init__.py +8 -4
- pixeltable/iterators/audio.py +207 -0
- pixeltable/iterators/base.py +9 -3
- pixeltable/iterators/document.py +144 -87
- pixeltable/iterators/image.py +17 -38
- pixeltable/iterators/string.py +15 -12
- pixeltable/iterators/video.py +523 -127
- pixeltable/metadata/__init__.py +33 -8
- pixeltable/metadata/converters/convert_10.py +2 -3
- pixeltable/metadata/converters/convert_13.py +2 -2
- pixeltable/metadata/converters/convert_15.py +15 -11
- pixeltable/metadata/converters/convert_16.py +4 -5
- pixeltable/metadata/converters/convert_17.py +4 -5
- pixeltable/metadata/converters/convert_18.py +4 -6
- pixeltable/metadata/converters/convert_19.py +6 -9
- pixeltable/metadata/converters/convert_20.py +3 -6
- pixeltable/metadata/converters/convert_21.py +6 -8
- pixeltable/metadata/converters/convert_22.py +3 -2
- pixeltable/metadata/converters/convert_23.py +33 -0
- pixeltable/metadata/converters/convert_24.py +55 -0
- pixeltable/metadata/converters/convert_25.py +19 -0
- pixeltable/metadata/converters/convert_26.py +23 -0
- pixeltable/metadata/converters/convert_27.py +29 -0
- pixeltable/metadata/converters/convert_28.py +13 -0
- pixeltable/metadata/converters/convert_29.py +110 -0
- pixeltable/metadata/converters/convert_30.py +63 -0
- pixeltable/metadata/converters/convert_31.py +11 -0
- pixeltable/metadata/converters/convert_32.py +15 -0
- pixeltable/metadata/converters/convert_33.py +17 -0
- pixeltable/metadata/converters/convert_34.py +21 -0
- pixeltable/metadata/converters/convert_35.py +9 -0
- pixeltable/metadata/converters/convert_36.py +38 -0
- pixeltable/metadata/converters/convert_37.py +15 -0
- pixeltable/metadata/converters/convert_38.py +39 -0
- pixeltable/metadata/converters/convert_39.py +124 -0
- pixeltable/metadata/converters/convert_40.py +73 -0
- pixeltable/metadata/converters/convert_41.py +12 -0
- pixeltable/metadata/converters/convert_42.py +9 -0
- pixeltable/metadata/converters/convert_43.py +44 -0
- pixeltable/metadata/converters/util.py +44 -18
- pixeltable/metadata/notes.py +21 -0
- pixeltable/metadata/schema.py +185 -42
- pixeltable/metadata/utils.py +74 -0
- pixeltable/mypy/__init__.py +3 -0
- pixeltable/mypy/mypy_plugin.py +123 -0
- pixeltable/plan.py +616 -225
- pixeltable/share/__init__.py +3 -0
- pixeltable/share/packager.py +797 -0
- pixeltable/share/protocol/__init__.py +33 -0
- pixeltable/share/protocol/common.py +165 -0
- pixeltable/share/protocol/operation_types.py +33 -0
- pixeltable/share/protocol/replica.py +119 -0
- pixeltable/share/publish.py +349 -0
- pixeltable/store.py +398 -232
- pixeltable/type_system.py +730 -267
- pixeltable/utils/__init__.py +40 -0
- pixeltable/utils/arrow.py +201 -29
- pixeltable/utils/av.py +298 -0
- pixeltable/utils/azure_store.py +346 -0
- pixeltable/utils/coco.py +26 -27
- pixeltable/utils/code.py +4 -4
- pixeltable/utils/console_output.py +46 -0
- pixeltable/utils/coroutine.py +24 -0
- pixeltable/utils/dbms.py +92 -0
- pixeltable/utils/description_helper.py +11 -12
- pixeltable/utils/documents.py +60 -61
- pixeltable/utils/exception_handler.py +36 -0
- pixeltable/utils/filecache.py +38 -22
- pixeltable/utils/formatter.py +88 -51
- pixeltable/utils/gcs_store.py +295 -0
- pixeltable/utils/http.py +133 -0
- pixeltable/utils/http_server.py +14 -13
- pixeltable/utils/iceberg.py +13 -0
- pixeltable/utils/image.py +17 -0
- pixeltable/utils/lancedb.py +90 -0
- pixeltable/utils/local_store.py +322 -0
- pixeltable/utils/misc.py +5 -0
- pixeltable/utils/object_stores.py +573 -0
- pixeltable/utils/pydantic.py +60 -0
- pixeltable/utils/pytorch.py +20 -20
- pixeltable/utils/s3_store.py +527 -0
- pixeltable/utils/sql.py +32 -5
- pixeltable/utils/system.py +30 -0
- pixeltable/utils/transactional_directory.py +4 -3
- pixeltable-0.5.7.dist-info/METADATA +579 -0
- pixeltable-0.5.7.dist-info/RECORD +227 -0
- {pixeltable-0.2.26.dist-info → pixeltable-0.5.7.dist-info}/WHEEL +1 -1
- pixeltable-0.5.7.dist-info/entry_points.txt +2 -0
- pixeltable/__version__.py +0 -3
- pixeltable/catalog/named_function.py +0 -36
- pixeltable/catalog/path_dict.py +0 -141
- pixeltable/dataframe.py +0 -894
- pixeltable/exec/expr_eval_node.py +0 -232
- pixeltable/ext/__init__.py +0 -14
- pixeltable/ext/functions/__init__.py +0 -8
- pixeltable/ext/functions/whisperx.py +0 -77
- pixeltable/ext/functions/yolox.py +0 -157
- pixeltable/tool/create_test_db_dump.py +0 -311
- pixeltable/tool/create_test_video.py +0 -81
- pixeltable/tool/doc_plugins/griffe.py +0 -50
- pixeltable/tool/doc_plugins/mkdocstrings.py +0 -6
- pixeltable/tool/doc_plugins/templates/material/udf.html.jinja +0 -135
- pixeltable/tool/embed_udf.py +0 -9
- pixeltable/tool/mypy_plugin.py +0 -55
- pixeltable/utils/media_store.py +0 -76
- pixeltable/utils/s3.py +0 -16
- pixeltable-0.2.26.dist-info/METADATA +0 -400
- pixeltable-0.2.26.dist-info/RECORD +0 -156
- pixeltable-0.2.26.dist-info/entry_points.txt +0 -3
- {pixeltable-0.2.26.dist-info → pixeltable-0.5.7.dist-info/licenses}/LICENSE +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pixeltable Core Protocol
|
|
3
|
+
|
|
4
|
+
This module contains the core protocol structures for pixeltable table operations
|
|
5
|
+
that can be shared between pixeltable core and cloud implementations.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .common import PxtUri, RequestBaseModel
|
|
9
|
+
from .operation_types import ReplicaOperationType
|
|
10
|
+
from .replica import (
|
|
11
|
+
DeleteRequest,
|
|
12
|
+
DeleteResponse,
|
|
13
|
+
FinalizeRequest,
|
|
14
|
+
FinalizeResponse,
|
|
15
|
+
PublishRequest,
|
|
16
|
+
PublishResponse,
|
|
17
|
+
ReplicateRequest,
|
|
18
|
+
ReplicateResponse,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
'DeleteRequest',
|
|
23
|
+
'DeleteResponse',
|
|
24
|
+
'FinalizeRequest',
|
|
25
|
+
'FinalizeResponse',
|
|
26
|
+
'PublishRequest',
|
|
27
|
+
'PublishResponse',
|
|
28
|
+
'PxtUri',
|
|
29
|
+
'ReplicaOperationType',
|
|
30
|
+
'ReplicateRequest',
|
|
31
|
+
'ReplicateResponse',
|
|
32
|
+
'RequestBaseModel',
|
|
33
|
+
]
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import uuid
|
|
4
|
+
from abc import ABC, abstractmethod
|
|
5
|
+
from typing import Any
|
|
6
|
+
from urllib.parse import urlparse
|
|
7
|
+
from uuid import UUID
|
|
8
|
+
|
|
9
|
+
from pydantic import BaseModel, model_validator
|
|
10
|
+
|
|
11
|
+
# Protocol version for replica operations. Used by both client and server
|
|
12
|
+
# to determine request/response format and maintain backward compatibility.
|
|
13
|
+
PROTOCOL_VERSION = 1
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def is_valid_uuid(uuid_string: str) -> bool:
|
|
17
|
+
"""Check if a string is a valid UUID."""
|
|
18
|
+
try:
|
|
19
|
+
uuid.UUID(uuid_string)
|
|
20
|
+
return True
|
|
21
|
+
except (ValueError, TypeError):
|
|
22
|
+
return False
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class PxtUri(BaseModel):
|
|
26
|
+
"""Pixeltable URI model for pxt:// URIs with validation and parsing."""
|
|
27
|
+
|
|
28
|
+
uri: str # The full URI string
|
|
29
|
+
|
|
30
|
+
# Parsed components
|
|
31
|
+
org: str # Organization slug from the URI
|
|
32
|
+
db: str | None # Database slug from the URI (optional)
|
|
33
|
+
path: str | None = None # The table or directory path (None if using UUID)
|
|
34
|
+
id: UUID | None = None # The table UUID (None if using path)
|
|
35
|
+
version: int | None = None # Optional version number parsed from URI (format: identifier:<version>)
|
|
36
|
+
|
|
37
|
+
def __init__(self, uri: str | dict | None = None, **kwargs: Any) -> None:
|
|
38
|
+
# Handle dict input directly (from JSON deserialization or explicit dict)
|
|
39
|
+
if isinstance(uri, dict):
|
|
40
|
+
# Dict input goes directly to Pydantic, which will call parse_uri
|
|
41
|
+
kwargs.update(uri)
|
|
42
|
+
elif uri is not None:
|
|
43
|
+
# Validate that uri is a string when passed as positional argument
|
|
44
|
+
if not isinstance(uri, str):
|
|
45
|
+
raise ValueError(f'Invalid data type for PxtUri: expected str or dict, got {type(uri)}')
|
|
46
|
+
kwargs['uri'] = uri
|
|
47
|
+
super().__init__(**kwargs)
|
|
48
|
+
|
|
49
|
+
@model_validator(mode='before')
|
|
50
|
+
@classmethod
|
|
51
|
+
def parse_uri(cls, data: Any) -> dict:
|
|
52
|
+
# Handle case where data is already a string (from JSON deserialization)
|
|
53
|
+
if isinstance(data, str):
|
|
54
|
+
uri = data
|
|
55
|
+
elif isinstance(data, dict):
|
|
56
|
+
uri = data.get('uri')
|
|
57
|
+
if uri is None:
|
|
58
|
+
raise ValueError('URI must be provided in dict with "uri" key')
|
|
59
|
+
if not isinstance(uri, str):
|
|
60
|
+
raise ValueError(f'URI in dict must be a string, got {type(uri)}')
|
|
61
|
+
else:
|
|
62
|
+
raise ValueError(f'Invalid data type for PxtUri: expected str or dict, got {type(data)}')
|
|
63
|
+
|
|
64
|
+
return {'uri': uri, **cls._parse_and_validate_uri(uri)}
|
|
65
|
+
|
|
66
|
+
def __str__(self) -> str:
|
|
67
|
+
"""Return the URI string."""
|
|
68
|
+
return self.uri
|
|
69
|
+
|
|
70
|
+
@classmethod
|
|
71
|
+
def _parse_and_validate_uri(cls, uri: str) -> dict:
|
|
72
|
+
"""Parse and validate a URI string, return parsed components."""
|
|
73
|
+
if not uri.startswith('pxt://'):
|
|
74
|
+
raise ValueError('URI must start with pxt://')
|
|
75
|
+
|
|
76
|
+
parsed = urlparse(uri)
|
|
77
|
+
if parsed.scheme != 'pxt':
|
|
78
|
+
raise ValueError('URI must use pxt:// scheme')
|
|
79
|
+
|
|
80
|
+
if not parsed.netloc:
|
|
81
|
+
raise ValueError('URI must have an organization')
|
|
82
|
+
|
|
83
|
+
# Parse netloc for org and optional db
|
|
84
|
+
netloc_parts = parsed.netloc.split(':')
|
|
85
|
+
org = netloc_parts[0]
|
|
86
|
+
if not org:
|
|
87
|
+
raise ValueError('URI must have an organization')
|
|
88
|
+
|
|
89
|
+
db = netloc_parts[1] if len(netloc_parts) > 1 else None
|
|
90
|
+
|
|
91
|
+
# Allow root path (/) as valid, but reject missing path
|
|
92
|
+
if parsed.path is None:
|
|
93
|
+
raise ValueError('URI must have a path')
|
|
94
|
+
|
|
95
|
+
# Get path and remove leading slash (but keep empty string for root path)
|
|
96
|
+
# path will be '/' for root directory or '/path/to/table' for regular paths
|
|
97
|
+
path_part = parsed.path.lstrip('/') if parsed.path else ''
|
|
98
|
+
|
|
99
|
+
# Handle version parsing (format: identifier:version)
|
|
100
|
+
# For root path, path_part will be empty string after lstrip
|
|
101
|
+
if path_part and ':' in path_part:
|
|
102
|
+
parts = path_part.rsplit(':', 1) # Split from right, only once
|
|
103
|
+
if len(parts) == 2 and parts[1].isdigit():
|
|
104
|
+
identifier, version = parts[0], int(parts[1])
|
|
105
|
+
else:
|
|
106
|
+
identifier, version = path_part, None
|
|
107
|
+
else:
|
|
108
|
+
identifier, version = path_part, None
|
|
109
|
+
|
|
110
|
+
# Parse identifier into either a path string or UUID
|
|
111
|
+
path: str | None = None
|
|
112
|
+
id: UUID | None = None
|
|
113
|
+
if identifier:
|
|
114
|
+
if is_valid_uuid(identifier):
|
|
115
|
+
# It's a UUID
|
|
116
|
+
id = UUID(identifier)
|
|
117
|
+
else:
|
|
118
|
+
# It's a path - keep as string (URI format uses / as separator)
|
|
119
|
+
# Empty string means root path
|
|
120
|
+
path = identifier or ''
|
|
121
|
+
else:
|
|
122
|
+
# Empty identifier means root path
|
|
123
|
+
path = ''
|
|
124
|
+
|
|
125
|
+
return {'org': org, 'db': db, 'path': path, 'id': id, 'version': version}
|
|
126
|
+
|
|
127
|
+
@classmethod
|
|
128
|
+
def from_components(
|
|
129
|
+
cls,
|
|
130
|
+
org: str,
|
|
131
|
+
path: str | None = None,
|
|
132
|
+
id: UUID | None = None,
|
|
133
|
+
db: str | None = None,
|
|
134
|
+
version: int | None = None,
|
|
135
|
+
) -> PxtUri:
|
|
136
|
+
"""Construct a PxtUri from its components."""
|
|
137
|
+
if path is None and id is None:
|
|
138
|
+
raise ValueError('Either path or id must be provided')
|
|
139
|
+
if path is not None and id is not None:
|
|
140
|
+
raise ValueError('Cannot specify both path and id')
|
|
141
|
+
|
|
142
|
+
# Build the URI string from components
|
|
143
|
+
netloc = org if db is None else f'{org}:{db}'
|
|
144
|
+
|
|
145
|
+
# Use path or UUID as identifier
|
|
146
|
+
if id is not None:
|
|
147
|
+
identifier = str(id)
|
|
148
|
+
elif path is not None:
|
|
149
|
+
# Path is already in URI format (slash-separated)
|
|
150
|
+
identifier = path or ''
|
|
151
|
+
else:
|
|
152
|
+
identifier = ''
|
|
153
|
+
|
|
154
|
+
path_part = f'{identifier}:{version}' if version is not None else identifier
|
|
155
|
+
uri = f'pxt://{netloc}/{path_part}'
|
|
156
|
+
return cls(uri=uri)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class RequestBaseModel(BaseModel, ABC):
|
|
160
|
+
"""Abstract base model for protocol requests that must have a PxtUri."""
|
|
161
|
+
|
|
162
|
+
@abstractmethod
|
|
163
|
+
def get_pxt_uri(self) -> PxtUri:
|
|
164
|
+
"""Get the PxtUri from this request. Must be implemented by subclasses."""
|
|
165
|
+
pass
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Replica operation types for pixeltable table replica operations.
|
|
3
|
+
|
|
4
|
+
This module defines the replica operation types that are shared between
|
|
5
|
+
pixeltable core and cloud implementations.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from enum import Enum
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ReplicaOperationType(str, Enum):
|
|
14
|
+
"""Replica operation types for table replica operations."""
|
|
15
|
+
|
|
16
|
+
# Table replica operations
|
|
17
|
+
PUBLISH_REPLICA = 'publish_replica'
|
|
18
|
+
FINALIZE_REPLICA = 'finalize_replica'
|
|
19
|
+
CLONE_REPLICA = 'clone_replica'
|
|
20
|
+
DELETE_REPLICA = 'delete_replica'
|
|
21
|
+
|
|
22
|
+
def is_replica_operation(self) -> bool:
|
|
23
|
+
"""Check if operation is a replica operation."""
|
|
24
|
+
return self in REPLICA_OPERATIONS
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# Define the operation sets as module-level constants
|
|
28
|
+
REPLICA_OPERATIONS: set[ReplicaOperationType] = {
|
|
29
|
+
ReplicaOperationType.PUBLISH_REPLICA,
|
|
30
|
+
ReplicaOperationType.FINALIZE_REPLICA,
|
|
31
|
+
ReplicaOperationType.CLONE_REPLICA,
|
|
32
|
+
ReplicaOperationType.DELETE_REPLICA,
|
|
33
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Core table protocol for pixeltable operations.
|
|
3
|
+
|
|
4
|
+
This module contains the core table protocol structures that can be shared
|
|
5
|
+
between pixeltable core and cloud implementations.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Any, Literal
|
|
11
|
+
from uuid import UUID
|
|
12
|
+
|
|
13
|
+
from pydantic import AnyUrl, BaseModel, field_validator
|
|
14
|
+
|
|
15
|
+
from pixeltable.catalog.table_version import TableVersionMd
|
|
16
|
+
from pixeltable.utils.object_stores import StorageTarget
|
|
17
|
+
|
|
18
|
+
from .common import PxtUri, RequestBaseModel
|
|
19
|
+
from .operation_types import ReplicaOperationType
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class PublishRequest(RequestBaseModel):
|
|
23
|
+
"""Request to publish or push table replica."""
|
|
24
|
+
|
|
25
|
+
operation_type: Literal[ReplicaOperationType.PUBLISH_REPLICA] = ReplicaOperationType.PUBLISH_REPLICA
|
|
26
|
+
table_uri: PxtUri # If PxtUri#id is not None then it's considered a push replica request
|
|
27
|
+
pxt_version: str
|
|
28
|
+
pxt_md_version: int
|
|
29
|
+
md: list[TableVersionMd]
|
|
30
|
+
is_public: bool = False
|
|
31
|
+
bucket_name: str | None = None # Optional bucket name, falls back to org's default bucket if not provided
|
|
32
|
+
|
|
33
|
+
def get_pxt_uri(self) -> PxtUri:
|
|
34
|
+
"""Get the PxtUri from this request."""
|
|
35
|
+
return self.table_uri
|
|
36
|
+
|
|
37
|
+
@field_validator('md')
|
|
38
|
+
@classmethod
|
|
39
|
+
def validate_md_not_empty(cls, v: list[TableVersionMd]) -> list[TableVersionMd]:
|
|
40
|
+
"""Ensure md list has at least one element."""
|
|
41
|
+
if len(v) == 0:
|
|
42
|
+
raise ValueError('md list must contain at least one element')
|
|
43
|
+
return v
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class PublishResponse(BaseModel):
|
|
47
|
+
"""Response from publishing a table replica."""
|
|
48
|
+
|
|
49
|
+
upload_id: UUID | None = None
|
|
50
|
+
destination: StorageTarget | None = None
|
|
51
|
+
destination_uri: AnyUrl | None = None
|
|
52
|
+
max_size: int | None = None # Maximum size that can be used by this replica, used for R2 home buckets
|
|
53
|
+
table_uri: PxtUri | None = None # If replica already exists, return the uri for it
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class FinalizeRequest(RequestBaseModel):
|
|
57
|
+
"""Request to finalize a table replica."""
|
|
58
|
+
|
|
59
|
+
operation_type: Literal[ReplicaOperationType.FINALIZE_REPLICA] = ReplicaOperationType.FINALIZE_REPLICA
|
|
60
|
+
table_uri: PxtUri # Use same table_uri that was given during publish replica request
|
|
61
|
+
upload_id: UUID
|
|
62
|
+
size: int
|
|
63
|
+
sha256: str
|
|
64
|
+
datafile: str
|
|
65
|
+
row_count: int
|
|
66
|
+
preview_header: dict[str, str]
|
|
67
|
+
preview_data: list[list[Any]]
|
|
68
|
+
|
|
69
|
+
def get_pxt_uri(self) -> PxtUri:
|
|
70
|
+
"""Get the PxtUri from this request."""
|
|
71
|
+
return self.table_uri
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class FinalizeResponse(BaseModel):
|
|
75
|
+
"""Response from finalizing a table replica."""
|
|
76
|
+
|
|
77
|
+
confirmed_table_uri: PxtUri
|
|
78
|
+
version: int | None = None # Version that was pushed to replica
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class DeleteRequest(RequestBaseModel):
|
|
82
|
+
"""Request to delete a table replica."""
|
|
83
|
+
|
|
84
|
+
operation_type: Literal[ReplicaOperationType.DELETE_REPLICA] = ReplicaOperationType.DELETE_REPLICA
|
|
85
|
+
table_uri: PxtUri
|
|
86
|
+
version: int | None = None # Delete a version in replica
|
|
87
|
+
|
|
88
|
+
def get_pxt_uri(self) -> PxtUri:
|
|
89
|
+
"""Get the PxtUri from this request."""
|
|
90
|
+
return self.table_uri
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class DeleteResponse(BaseModel):
|
|
94
|
+
"""Response from deleting a table replica."""
|
|
95
|
+
|
|
96
|
+
table_uri: PxtUri
|
|
97
|
+
version: int | None = None
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class ReplicateRequest(RequestBaseModel):
|
|
101
|
+
"""Request to clone a table replica."""
|
|
102
|
+
|
|
103
|
+
operation_type: Literal[ReplicaOperationType.CLONE_REPLICA] = ReplicaOperationType.CLONE_REPLICA
|
|
104
|
+
table_uri: PxtUri
|
|
105
|
+
|
|
106
|
+
def get_pxt_uri(self) -> PxtUri:
|
|
107
|
+
"""Get the PxtUri from this request."""
|
|
108
|
+
return self.table_uri
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class ReplicateResponse(BaseModel):
|
|
112
|
+
"""Response from cloning a table replica."""
|
|
113
|
+
|
|
114
|
+
table_uri: PxtUri
|
|
115
|
+
pxt_md_version: int
|
|
116
|
+
destination: StorageTarget
|
|
117
|
+
destination_uri: AnyUrl
|
|
118
|
+
md: list[TableVersionMd]
|
|
119
|
+
version: int | None = None
|