pixeltable 0.1.2__py3-none-any.whl → 0.2.1__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.
Potentially problematic release.
This version of pixeltable might be problematic. Click here for more details.
- pixeltable/__init__.py +21 -4
- pixeltable/catalog/__init__.py +13 -0
- pixeltable/catalog/catalog.py +159 -0
- pixeltable/catalog/column.py +200 -0
- pixeltable/catalog/dir.py +32 -0
- pixeltable/catalog/globals.py +33 -0
- pixeltable/catalog/insertable_table.py +191 -0
- pixeltable/catalog/named_function.py +36 -0
- pixeltable/catalog/path.py +58 -0
- pixeltable/catalog/path_dict.py +139 -0
- pixeltable/catalog/schema_object.py +39 -0
- pixeltable/catalog/table.py +581 -0
- pixeltable/catalog/table_version.py +749 -0
- pixeltable/catalog/table_version_path.py +133 -0
- pixeltable/catalog/view.py +203 -0
- pixeltable/client.py +520 -31
- pixeltable/dataframe.py +540 -349
- pixeltable/env.py +373 -48
- pixeltable/exceptions.py +12 -21
- pixeltable/exec/__init__.py +9 -0
- pixeltable/exec/aggregation_node.py +78 -0
- pixeltable/exec/cache_prefetch_node.py +113 -0
- pixeltable/exec/component_iteration_node.py +79 -0
- pixeltable/exec/data_row_batch.py +95 -0
- pixeltable/exec/exec_context.py +22 -0
- pixeltable/exec/exec_node.py +61 -0
- pixeltable/exec/expr_eval_node.py +217 -0
- pixeltable/exec/in_memory_data_node.py +69 -0
- pixeltable/exec/media_validation_node.py +43 -0
- pixeltable/exec/sql_scan_node.py +225 -0
- pixeltable/exprs/__init__.py +24 -0
- pixeltable/exprs/arithmetic_expr.py +102 -0
- pixeltable/exprs/array_slice.py +71 -0
- pixeltable/exprs/column_property_ref.py +77 -0
- pixeltable/exprs/column_ref.py +105 -0
- pixeltable/exprs/comparison.py +77 -0
- pixeltable/exprs/compound_predicate.py +98 -0
- pixeltable/exprs/data_row.py +187 -0
- pixeltable/exprs/expr.py +586 -0
- pixeltable/exprs/expr_set.py +39 -0
- pixeltable/exprs/function_call.py +380 -0
- pixeltable/exprs/globals.py +69 -0
- pixeltable/exprs/image_member_access.py +115 -0
- pixeltable/exprs/image_similarity_predicate.py +58 -0
- pixeltable/exprs/inline_array.py +107 -0
- pixeltable/exprs/inline_dict.py +101 -0
- pixeltable/exprs/is_null.py +38 -0
- pixeltable/exprs/json_mapper.py +121 -0
- pixeltable/exprs/json_path.py +159 -0
- pixeltable/exprs/literal.py +54 -0
- pixeltable/exprs/object_ref.py +41 -0
- pixeltable/exprs/predicate.py +44 -0
- pixeltable/exprs/row_builder.py +355 -0
- pixeltable/exprs/rowid_ref.py +94 -0
- pixeltable/exprs/type_cast.py +53 -0
- pixeltable/exprs/variable.py +45 -0
- pixeltable/func/__init__.py +9 -0
- pixeltable/func/aggregate_function.py +194 -0
- pixeltable/func/batched_function.py +53 -0
- pixeltable/func/callable_function.py +69 -0
- pixeltable/func/expr_template_function.py +82 -0
- pixeltable/func/function.py +110 -0
- pixeltable/func/function_registry.py +227 -0
- pixeltable/func/globals.py +36 -0
- pixeltable/func/nos_function.py +202 -0
- pixeltable/func/signature.py +166 -0
- pixeltable/func/udf.py +163 -0
- pixeltable/functions/__init__.py +52 -103
- pixeltable/functions/eval.py +216 -0
- pixeltable/functions/fireworks.py +61 -0
- pixeltable/functions/huggingface.py +120 -0
- pixeltable/functions/image.py +16 -0
- pixeltable/functions/openai.py +88 -0
- pixeltable/functions/pil/image.py +148 -7
- pixeltable/functions/string.py +13 -0
- pixeltable/functions/together.py +27 -0
- pixeltable/functions/util.py +41 -0
- pixeltable/functions/video.py +62 -0
- pixeltable/iterators/__init__.py +3 -0
- pixeltable/iterators/base.py +48 -0
- pixeltable/iterators/document.py +311 -0
- pixeltable/iterators/video.py +89 -0
- pixeltable/metadata/__init__.py +54 -0
- pixeltable/metadata/converters/convert_10.py +18 -0
- pixeltable/metadata/schema.py +211 -0
- pixeltable/plan.py +656 -0
- pixeltable/store.py +413 -182
- pixeltable/tests/conftest.py +143 -86
- pixeltable/tests/test_audio.py +65 -0
- pixeltable/tests/test_catalog.py +27 -0
- pixeltable/tests/test_client.py +14 -14
- pixeltable/tests/test_component_view.py +372 -0
- pixeltable/tests/test_dataframe.py +433 -0
- pixeltable/tests/test_dirs.py +78 -62
- pixeltable/tests/test_document.py +117 -0
- pixeltable/tests/test_exprs.py +591 -135
- pixeltable/tests/test_function.py +297 -67
- pixeltable/tests/test_functions.py +283 -1
- pixeltable/tests/test_migration.py +43 -0
- pixeltable/tests/test_nos.py +54 -0
- pixeltable/tests/test_snapshot.py +208 -0
- pixeltable/tests/test_table.py +1086 -258
- pixeltable/tests/test_transactional_directory.py +42 -0
- pixeltable/tests/test_types.py +5 -11
- pixeltable/tests/test_video.py +149 -34
- pixeltable/tests/test_view.py +530 -0
- pixeltable/tests/utils.py +186 -45
- pixeltable/tool/create_test_db_dump.py +149 -0
- pixeltable/type_system.py +490 -133
- pixeltable/utils/__init__.py +17 -46
- pixeltable/utils/clip.py +12 -15
- pixeltable/utils/coco.py +136 -0
- pixeltable/utils/documents.py +39 -0
- pixeltable/utils/filecache.py +195 -0
- pixeltable/utils/help.py +11 -0
- pixeltable/utils/media_store.py +76 -0
- pixeltable/utils/parquet.py +126 -0
- pixeltable/utils/pytorch.py +172 -0
- pixeltable/utils/s3.py +13 -0
- pixeltable/utils/sql.py +17 -0
- pixeltable/utils/transactional_directory.py +35 -0
- pixeltable-0.2.1.dist-info/LICENSE +18 -0
- pixeltable-0.2.1.dist-info/METADATA +119 -0
- pixeltable-0.2.1.dist-info/RECORD +125 -0
- {pixeltable-0.1.2.dist-info → pixeltable-0.2.1.dist-info}/WHEEL +1 -1
- pixeltable/catalog.py +0 -1421
- pixeltable/exprs.py +0 -1745
- pixeltable/function.py +0 -269
- pixeltable/functions/clip.py +0 -10
- pixeltable/functions/pil/__init__.py +0 -23
- pixeltable/functions/tf.py +0 -21
- pixeltable/index.py +0 -57
- pixeltable/tests/test_dict.py +0 -24
- pixeltable/tests/test_tf.py +0 -69
- pixeltable/tf.py +0 -33
- pixeltable/utils/tf.py +0 -33
- pixeltable/utils/video.py +0 -32
- pixeltable-0.1.2.dist-info/LICENSE +0 -201
- pixeltable-0.1.2.dist-info/METADATA +0 -89
- pixeltable-0.1.2.dist-info/RECORD +0 -37
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import PIL.Image
|
|
3
|
+
import io
|
|
4
|
+
import pyarrow.parquet as pq
|
|
5
|
+
import pyarrow as pa
|
|
6
|
+
import numpy as np
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from collections import deque
|
|
9
|
+
|
|
10
|
+
from typing import List, Tuple, Any, Dict
|
|
11
|
+
from pixeltable.utils.transactional_directory import transactional_directory
|
|
12
|
+
|
|
13
|
+
def _write_batch(value_batch : Dict[str, deque], schema : pa.Schema, output_path : Path) -> None:
|
|
14
|
+
pydict = {}
|
|
15
|
+
for field in schema:
|
|
16
|
+
if isinstance(field.type, pa.FixedShapeTensorType):
|
|
17
|
+
stacked_arr = np.stack(value_batch[field.name])
|
|
18
|
+
pydict[field.name] = pa.FixedShapeTensorArray.from_numpy_ndarray(stacked_arr)
|
|
19
|
+
else:
|
|
20
|
+
pydict[field.name] = value_batch[field.name]
|
|
21
|
+
|
|
22
|
+
tab = pa.Table.from_pydict(pydict, schema=schema)
|
|
23
|
+
pq.write_table(tab, output_path)
|
|
24
|
+
|
|
25
|
+
def save_parquet(df: 'pixeltable.DataFrame', dest_path: Path, partition_size_bytes: int = 100_000_000) -> None:
|
|
26
|
+
"""
|
|
27
|
+
Internal method to stream dataframe data to parquet format.
|
|
28
|
+
Does not materialize the dataset to memory.
|
|
29
|
+
|
|
30
|
+
It preserves pixeltable type metadata in a json file, which would otherwise
|
|
31
|
+
not be available in the parquet format.
|
|
32
|
+
|
|
33
|
+
Images are stored inline in a compressed format in their parquet file.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
df : dataframe to save.
|
|
37
|
+
dest_path : path to directory to save the parquet files to.
|
|
38
|
+
partition_size_bytes : maximum target size for each chunk. Default 100_000_000 bytes.
|
|
39
|
+
"""
|
|
40
|
+
column_names = df.get_column_names()
|
|
41
|
+
column_types = df.get_column_types()
|
|
42
|
+
|
|
43
|
+
type_dict = {k: v.as_dict() for k, v in zip(column_names, column_types)}
|
|
44
|
+
|
|
45
|
+
arrow_schema = pa.schema([pa.field(name, column_types[i].to_arrow_type()) for i, name in enumerate(column_names)])
|
|
46
|
+
# store the changes atomically
|
|
47
|
+
with transactional_directory(dest_path) as temp_path:
|
|
48
|
+
# dump metadata json file so we can inspect what was the source of the parquet file later on.
|
|
49
|
+
json.dump(df._as_dict(), (temp_path / '.pixeltable.json').open('w')) # pylint: disable=protected-access
|
|
50
|
+
json.dump(type_dict, (temp_path / '.pixeltable.column_types.json').open('w')) # keep type metadata
|
|
51
|
+
|
|
52
|
+
batch_num = 0
|
|
53
|
+
current_value_batch : Dict[str, deque] = {k:deque() for k in column_names}
|
|
54
|
+
current_byte_estimate = 0
|
|
55
|
+
|
|
56
|
+
for data_row in df._exec(): # pylint: disable=protected-access
|
|
57
|
+
for (col_name, col_type, e) in zip(column_names, column_types, df._select_list_exprs): # pylint: disable=protected-access
|
|
58
|
+
val = data_row[e.slot_idx]
|
|
59
|
+
if val is None:
|
|
60
|
+
current_value_batch[col_name].append(val)
|
|
61
|
+
continue
|
|
62
|
+
|
|
63
|
+
assert val is not None
|
|
64
|
+
if col_type.is_image_type():
|
|
65
|
+
# images get inlined into the parquet file
|
|
66
|
+
if data_row.file_paths is not None and data_row.file_paths[e.slot_idx] is not None:
|
|
67
|
+
# if there is a file, read directly to preserve information
|
|
68
|
+
val = open(data_row.file_paths[e.slot_idx], 'rb').read()
|
|
69
|
+
elif isinstance(val, PIL.Image.Image):
|
|
70
|
+
# if no file available, eg. bc it is computed, convert to png
|
|
71
|
+
buf = io.BytesIO()
|
|
72
|
+
val.save(buf, format='PNG')
|
|
73
|
+
val = buf.getvalue()
|
|
74
|
+
else:
|
|
75
|
+
assert False, f'unknown image type {type(val)}'
|
|
76
|
+
length = len(val)
|
|
77
|
+
elif col_type.is_string_type():
|
|
78
|
+
length = len(val)
|
|
79
|
+
elif col_type.is_video_type():
|
|
80
|
+
if data_row.file_paths is not None and data_row.file_paths[e.slot_idx] is not None:
|
|
81
|
+
val = data_row.file_paths[e.slot_idx]
|
|
82
|
+
else:
|
|
83
|
+
assert False, f'unknown video type {type(val)}'
|
|
84
|
+
length = len(val)
|
|
85
|
+
elif col_type.is_json_type():
|
|
86
|
+
val = json.dumps(val)
|
|
87
|
+
length = len(val)
|
|
88
|
+
elif col_type.is_array_type():
|
|
89
|
+
length = val.nbytes
|
|
90
|
+
elif col_type.is_int_type():
|
|
91
|
+
length = 8
|
|
92
|
+
elif col_type.is_float_type():
|
|
93
|
+
length = 8
|
|
94
|
+
elif col_type.is_bool_type():
|
|
95
|
+
length = 1
|
|
96
|
+
elif col_type.is_timestamp_type():
|
|
97
|
+
length = 8
|
|
98
|
+
else:
|
|
99
|
+
assert False, f'unknown type {col_type} for {col_name}'
|
|
100
|
+
|
|
101
|
+
current_value_batch[col_name].append(val)
|
|
102
|
+
current_byte_estimate += length
|
|
103
|
+
if current_byte_estimate > partition_size_bytes:
|
|
104
|
+
assert batch_num < 100_000, 'wrote too many parquet files, unclear ordering'
|
|
105
|
+
_write_batch(current_value_batch, arrow_schema, temp_path / f'part-{batch_num:05d}.parquet')
|
|
106
|
+
batch_num += 1
|
|
107
|
+
current_value_batch = {k:deque() for k in column_names}
|
|
108
|
+
current_byte_estimate = 0
|
|
109
|
+
|
|
110
|
+
_write_batch(current_value_batch, arrow_schema, temp_path / f'part-{batch_num:05d}.parquet')
|
|
111
|
+
|
|
112
|
+
def get_part_metadata(path : Path) -> List[Tuple[str, int]]:
|
|
113
|
+
"""
|
|
114
|
+
Args:
|
|
115
|
+
path: path to directory containing parquet files.
|
|
116
|
+
Returns:
|
|
117
|
+
A list of (file_name, num_rows) tuples for the parquet files in file name order.
|
|
118
|
+
"""
|
|
119
|
+
parts = sorted([f for f in path.iterdir() if f.suffix == '.parquet'])
|
|
120
|
+
rows_per_file = {}
|
|
121
|
+
|
|
122
|
+
for part in parts:
|
|
123
|
+
parquet_file = pq.ParquetFile(str(part))
|
|
124
|
+
rows_per_file[part] = parquet_file.metadata.num_rows
|
|
125
|
+
|
|
126
|
+
return [(file, num_rows) for file, num_rows in rows_per_file.items()]
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import io
|
|
2
|
+
import pyarrow as pa
|
|
3
|
+
import pyarrow.parquet as pq
|
|
4
|
+
import torch
|
|
5
|
+
import torch.utils.data
|
|
6
|
+
import math
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
import PIL.Image
|
|
9
|
+
import json
|
|
10
|
+
from typing import Dict, Tuple, Generator, Any
|
|
11
|
+
import datetime
|
|
12
|
+
|
|
13
|
+
from pixeltable.type_system import ColumnType
|
|
14
|
+
from pixeltable.utils.parquet import get_part_metadata
|
|
15
|
+
import numpy as np
|
|
16
|
+
|
|
17
|
+
def _cumsum(lst):
|
|
18
|
+
acc = [0]
|
|
19
|
+
for x in lst:
|
|
20
|
+
acc.append(acc[-1] + x)
|
|
21
|
+
return acc
|
|
22
|
+
|
|
23
|
+
class PixeltablePytorchDataset(torch.utils.data.IterableDataset):
|
|
24
|
+
"""
|
|
25
|
+
PyTorch dataset interface for pixeltable data.
|
|
26
|
+
NB. This class must inherit from torch.utils.data.IterableDataset for it
|
|
27
|
+
to work with torch.utils.data.DataLoader.
|
|
28
|
+
"""
|
|
29
|
+
def __init__(
|
|
30
|
+
self,
|
|
31
|
+
path: Path,
|
|
32
|
+
image_format: str,
|
|
33
|
+
):
|
|
34
|
+
"""
|
|
35
|
+
Args:
|
|
36
|
+
path: path to directory containing parquet files
|
|
37
|
+
image_format: 'np' or 'pt'. 'np' is RGB uint8 array,
|
|
38
|
+
'pt' is result of torchvision.transforms.ToTensor()
|
|
39
|
+
"""
|
|
40
|
+
super().__init__()
|
|
41
|
+
|
|
42
|
+
self.path = path
|
|
43
|
+
self.image_format = image_format
|
|
44
|
+
assert image_format in ["np", "pt"]
|
|
45
|
+
column_type_path = path / '.pixeltable.column_types.json'
|
|
46
|
+
assert column_type_path.exists(), f"missing {column_type_path}"
|
|
47
|
+
with column_type_path.open() as f:
|
|
48
|
+
column_types = json.load(f)
|
|
49
|
+
self.column_types = {k: ColumnType.from_dict(v) for k, v in column_types.items()}
|
|
50
|
+
self.part_metadata = get_part_metadata(self.path)
|
|
51
|
+
self._totals = _cumsum([x[1] for x in self.part_metadata])
|
|
52
|
+
|
|
53
|
+
def _get_start_position(self, row_start: int) -> Tuple[int, int]:
|
|
54
|
+
"""
|
|
55
|
+
Returns the starting parquet file and row within that file for a given 'global' row number.
|
|
56
|
+
based on the individual sizes of each part
|
|
57
|
+
"""
|
|
58
|
+
assert row_start >= self._totals[0]
|
|
59
|
+
assert row_start < self._totals[-1]
|
|
60
|
+
|
|
61
|
+
prev_acc = 0
|
|
62
|
+
for i, acc in enumerate(self._totals[1:], start=1):
|
|
63
|
+
if acc > row_start:
|
|
64
|
+
return (i - 1, row_start - prev_acc)
|
|
65
|
+
prev_acc = acc
|
|
66
|
+
|
|
67
|
+
assert False, "unreachable"
|
|
68
|
+
|
|
69
|
+
def _unmarshall(self, k: str, v: Any) -> Any:
|
|
70
|
+
if self.column_types[k].is_image_type():
|
|
71
|
+
assert isinstance(v, bytes)
|
|
72
|
+
im = PIL.Image.open(io.BytesIO(v))
|
|
73
|
+
arr = np.array(im) # will copy data to guarantee "WRITEABLE" flag assertion below.
|
|
74
|
+
assert arr.flags["WRITEABLE"]
|
|
75
|
+
|
|
76
|
+
if self.image_format == "np":
|
|
77
|
+
return arr
|
|
78
|
+
|
|
79
|
+
assert self.image_format == "pt"
|
|
80
|
+
import torchvision # pylint: disable = import-outside-toplevel
|
|
81
|
+
|
|
82
|
+
# use arr instead of im in ToTensor() to guarantee array input
|
|
83
|
+
# to torch.from_numpy is writable. Using im is a suspected cause of
|
|
84
|
+
# https://github.com/pixeltable/pixeltable/issues/69
|
|
85
|
+
return torchvision.transforms.ToTensor()(arr)
|
|
86
|
+
elif self.column_types[k].is_json_type():
|
|
87
|
+
assert isinstance(v, str)
|
|
88
|
+
return json.loads(v)
|
|
89
|
+
elif self.column_types[k].is_array_type():
|
|
90
|
+
assert isinstance(v, np.ndarray)
|
|
91
|
+
# WRITEABLE is required for torch collate function, or undefined behavior
|
|
92
|
+
if not v.flags["WRITEABLE"]:
|
|
93
|
+
vout = v.copy()
|
|
94
|
+
assert vout.flags["WRITEABLE"]
|
|
95
|
+
return vout
|
|
96
|
+
else:
|
|
97
|
+
return v
|
|
98
|
+
elif self.column_types[k].is_timestamp_type():
|
|
99
|
+
# pytorch default collation only supports numeric types
|
|
100
|
+
assert isinstance(v, datetime.datetime)
|
|
101
|
+
return v.timestamp()
|
|
102
|
+
else:
|
|
103
|
+
assert not isinstance(v, np.ndarray) # all array outputs should be handled above
|
|
104
|
+
return v
|
|
105
|
+
|
|
106
|
+
def __iter__(self) -> Generator[Dict[str, Any], None, None]:
|
|
107
|
+
worker_info = torch.utils.data.get_worker_info()
|
|
108
|
+
if worker_info is None: # single-process data loading, return the full iterator
|
|
109
|
+
start_row = 0
|
|
110
|
+
end_row = self._totals[-1]
|
|
111
|
+
else: # in a worker process
|
|
112
|
+
num_workers = [
|
|
113
|
+
math.floor(self._totals[-1] / float(worker_info.num_workers))
|
|
114
|
+
for _ in range(worker_info.num_workers)
|
|
115
|
+
]
|
|
116
|
+
assert self._totals[-1] - sum(num_workers) < worker_info.num_workers
|
|
117
|
+
for i in range(self._totals[-1] - sum(num_workers)):
|
|
118
|
+
num_workers[i] += 1
|
|
119
|
+
|
|
120
|
+
assert sum(num_workers) == self._totals[-1]
|
|
121
|
+
start_rows = _cumsum(num_workers)
|
|
122
|
+
start_row = start_rows[worker_info.id]
|
|
123
|
+
end_row = start_rows[worker_info.id + 1]
|
|
124
|
+
|
|
125
|
+
if start_row == end_row:
|
|
126
|
+
return iter([]) # type: ignore
|
|
127
|
+
else:
|
|
128
|
+
return self._iter_range(start_row, end_row)
|
|
129
|
+
|
|
130
|
+
def _iter_range(self, start_row : int, end_row : int) -> Generator[Dict[str, Any], None, None]:
|
|
131
|
+
(part_no, iter_start) = self._get_start_position(start_row)
|
|
132
|
+
total = end_row - start_row
|
|
133
|
+
|
|
134
|
+
acc = 0
|
|
135
|
+
part_pos = part_no
|
|
136
|
+
iter_pos = iter_start
|
|
137
|
+
|
|
138
|
+
def _to_column_dict(tab : pa.Table) -> Dict[str, Any]:
|
|
139
|
+
column_dict = {}
|
|
140
|
+
for k in tab.column_names:
|
|
141
|
+
if self.column_types[k].is_array_type():
|
|
142
|
+
# treat array columns as numpy arrays to easily preserve numpy type
|
|
143
|
+
column_dict[k] = tab.column(k).to_numpy()
|
|
144
|
+
else:
|
|
145
|
+
# for the rest, use pydict to preserve python types
|
|
146
|
+
column_dict[k] = tab.column(k).to_pylist()
|
|
147
|
+
return column_dict
|
|
148
|
+
|
|
149
|
+
tab: pa.Table = pq.read_table(self.path / self.part_metadata[part_no][0])
|
|
150
|
+
column_dict = _to_column_dict(tab)
|
|
151
|
+
assert tab.num_rows == self.part_metadata[part_no][1]
|
|
152
|
+
|
|
153
|
+
while True:
|
|
154
|
+
while iter_pos < tab.num_rows and acc < total:
|
|
155
|
+
next_tup = {}
|
|
156
|
+
for col_name, col_vals in column_dict.items():
|
|
157
|
+
raw_val = col_vals[iter_pos]
|
|
158
|
+
next_tup[col_name] = self._unmarshall(col_name, raw_val)
|
|
159
|
+
|
|
160
|
+
yield next_tup
|
|
161
|
+
acc += 1
|
|
162
|
+
iter_pos += 1
|
|
163
|
+
|
|
164
|
+
if acc == total:
|
|
165
|
+
break
|
|
166
|
+
|
|
167
|
+
# move on to next part
|
|
168
|
+
part_pos += 1
|
|
169
|
+
assert part_pos < len(self.part_metadata)
|
|
170
|
+
iter_pos = 0
|
|
171
|
+
tab = pq.read_table(self.path / self.part_metadata[part_pos][0])
|
|
172
|
+
column_dict = _to_column_dict(tab)
|
pixeltable/utils/s3.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def get_client() -> Any:
|
|
5
|
+
import boto3
|
|
6
|
+
import botocore
|
|
7
|
+
try:
|
|
8
|
+
boto3.Session().get_credentials().get_frozen_credentials()
|
|
9
|
+
return boto3.client('s3') # credentials are available
|
|
10
|
+
except AttributeError:
|
|
11
|
+
# No credentials available, use unsigned mode
|
|
12
|
+
config = botocore.config.Config(signature_version=botocore.UNSIGNED)
|
|
13
|
+
return boto3.client('s3', config=config)
|
pixeltable/utils/sql.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import sqlalchemy as sql
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def log_stmt(logger: logging.Logger, stmt) -> None:
|
|
7
|
+
logger.debug(f'executing {str(stmt.compile(dialect=sql.dialects.postgresql.dialect()))}')
|
|
8
|
+
|
|
9
|
+
def log_explain(logger: logging.Logger, stmt: sql.sql.ClauseElement, conn: sql.engine.Connection) -> None:
|
|
10
|
+
try:
|
|
11
|
+
# don't set dialect=Env.get().engine.dialect: x % y turns into x %% y, which results in a syntax error
|
|
12
|
+
stmt_str = str(stmt.compile(compile_kwargs={'literal_binds': True}))
|
|
13
|
+
explain_result = conn.execute(sql.text(f'EXPLAIN {stmt_str}'))
|
|
14
|
+
explain_str = '\n'.join([str(row) for row in explain_result])
|
|
15
|
+
logger.debug(f'SqlScanNode explain:\n{explain_str}')
|
|
16
|
+
except Exception as e:
|
|
17
|
+
logger.warning(f'EXPLAIN failed')
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
from contextlib import contextmanager
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Any, Generator
|
|
5
|
+
|
|
6
|
+
import pixeltable.exceptions as excs
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@contextmanager
|
|
10
|
+
def transactional_directory(folder_path: Path) -> Generator[Path, Any, Any]:
|
|
11
|
+
"""
|
|
12
|
+
Args:
|
|
13
|
+
folder_path: path to the folder we want to create
|
|
14
|
+
|
|
15
|
+
Yields:
|
|
16
|
+
A pathlib.Path to a hidden temporary folder, which can be used to accumulate changes.
|
|
17
|
+
If everything succeeds, the changes are committed via an atomic move operation upon exiting the 'with' block (os.replace)
|
|
18
|
+
If an exception occurred, no changes are visible in the original folder.
|
|
19
|
+
|
|
20
|
+
Example:
|
|
21
|
+
folder_path = pathlib.Path("path/to/folder")
|
|
22
|
+
with transactional_folder(folder_path) as temp_folder:
|
|
23
|
+
(temp_folder / "subfolder1").mkdir()
|
|
24
|
+
(temp_folder / "subfolder2").mkdir()
|
|
25
|
+
"""
|
|
26
|
+
if folder_path.exists():
|
|
27
|
+
raise excs.Error(f"Folder {folder_path} already exists")
|
|
28
|
+
|
|
29
|
+
tmp_folder = folder_path.parent / f".tmp_{folder_path.name}"
|
|
30
|
+
# Remove the temporary folder if it already exists, eg if the previous run crashed
|
|
31
|
+
shutil.rmtree(str(tmp_folder), ignore_errors=True)
|
|
32
|
+
tmp_folder.mkdir(parents=True)
|
|
33
|
+
yield tmp_folder
|
|
34
|
+
# If everything succeeds, `commit' the changes by moving the temporary folder
|
|
35
|
+
tmp_folder.rename(folder_path)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
Copyright 2023 Marcel Kornacker
|
|
7
|
+
|
|
8
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
you may not use this file except in compliance with the License.
|
|
10
|
+
You may obtain a copy of the License at
|
|
11
|
+
|
|
12
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
|
|
14
|
+
Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
See the License for the specific language governing permissions and
|
|
18
|
+
limitations under the License.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pixeltable
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Pixeltable: The Multimodal AI Data Plane
|
|
5
|
+
Author: Marcel Kornacker
|
|
6
|
+
Author-email: marcelk@gmail.com
|
|
7
|
+
Requires-Python: >=3.9,<4.0
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Requires-Dist: av (>=10.0.0)
|
|
14
|
+
Requires-Dist: cloudpickle (>=2.2.1,<3.0.0)
|
|
15
|
+
Requires-Dist: jinja2 (>=3.1.3,<4.0.0)
|
|
16
|
+
Requires-Dist: jmespath (>=1.0.1,<2.0.0)
|
|
17
|
+
Requires-Dist: numpy (>=1.24.1,<2.0.0)
|
|
18
|
+
Requires-Dist: opencv-python-headless (>=4.7.0.68,<5.0.0.0)
|
|
19
|
+
Requires-Dist: pandas (>=1.5.3,<2.0.0)
|
|
20
|
+
Requires-Dist: pgserver (==0.0.5)
|
|
21
|
+
Requires-Dist: pgvector (>=0.2.1,<0.3.0)
|
|
22
|
+
Requires-Dist: pillow (>=9.4.0,<10.0.0)
|
|
23
|
+
Requires-Dist: psutil (>=5.9.5,<6.0.0)
|
|
24
|
+
Requires-Dist: psycopg2-binary (>=2.9.5,<3.0.0)
|
|
25
|
+
Requires-Dist: pyyaml (>=6.0.1,<7.0.0)
|
|
26
|
+
Requires-Dist: regex (>=2022.10.31,<2023.0.0)
|
|
27
|
+
Requires-Dist: sqlalchemy-utils (>=0.41.1,<0.42.0)
|
|
28
|
+
Requires-Dist: sqlalchemy[mypy] (>=2.0.23,<3.0.0)
|
|
29
|
+
Requires-Dist: tqdm (>=4.64.1,<5.0.0)
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
<img src="docs/pixeltable-banner.png" width="45%"/>
|
|
33
|
+
|
|
34
|
+
# Pixeltable: The Multimodal AI Data Plane
|
|
35
|
+
|
|
36
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
37
|
+
|
|
38
|
+

|
|
39
|
+
|
|
40
|
+
Pixeltable is a Python library that lets AI engineers and data scientists focus on
|
|
41
|
+
exploration, modeling, and app development without having to deal with the customary
|
|
42
|
+
data plumbing.
|
|
43
|
+
|
|
44
|
+
**Pixeltable redefines data infrastructure and workflow orchestration for AI development.**
|
|
45
|
+
It brings together data storage, versioning, and indexing with orchestration and model
|
|
46
|
+
versioning under a declarative table interface, with transformations, model inference,
|
|
47
|
+
and custom logic represented as computed columns.
|
|
48
|
+
<!--
|
|
49
|
+
## Quick Start
|
|
50
|
+
|
|
51
|
+
If you just want to play around with Pixeltable to see what it's capable of, the easiest way is to run
|
|
52
|
+
the Pixeltable Basics tutorial in colab:
|
|
53
|
+
|
|
54
|
+
<a target="_blank" href="https://colab.research.google.com/github/pixeltable/pixeltable/blob/docs/tutorials/pixeltable-basics.ipynb">
|
|
55
|
+
<img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
|
|
56
|
+
</a>
|
|
57
|
+
-->
|
|
58
|
+
## Installation
|
|
59
|
+
|
|
60
|
+
Pixeltable works with Python 3.9, 3.10, or 3.11 running on Linux or MacOS.
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
pip install pixeltable
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
To verify that it's working:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
import pixeltable as pxt
|
|
70
|
+
cl = pxt.Client()
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
For more detailed installation instructions, see the
|
|
74
|
+
[Getting Started with Pixeltable](https://pixeltable.github.io/pixeltable/getting-started/)
|
|
75
|
+
guide. Then, check out the
|
|
76
|
+
[Pixeltable Basics](https://pixeltable.github.io/pixeltable/tutorials/pixeltable-basics/)
|
|
77
|
+
tutorial for a tour of its most important features.
|
|
78
|
+
|
|
79
|
+
## What problems does Pixeltable solve?
|
|
80
|
+
|
|
81
|
+
Today’s solutions for AI app development require extensive custom coding and infrastructure
|
|
82
|
+
plumbing. Tracking lineage and versions between and across data transformations, models, and
|
|
83
|
+
deployment is cumbersome. Pixeltable is a replacement for traditional data plumbing, providing
|
|
84
|
+
a unified plane for data, models, and orchestration. It removes the data plumbing overhead in
|
|
85
|
+
building and productionizing AI applications.
|
|
86
|
+
|
|
87
|
+
## Why should you use Pixeltable?
|
|
88
|
+
|
|
89
|
+
- It gives you transparency and reproducibility
|
|
90
|
+
- All generated data is automatically recorded and versioned
|
|
91
|
+
- You will never need to re-run a workload because you lost track of the input data
|
|
92
|
+
- It saves you money
|
|
93
|
+
- All data changes are automatically incremental
|
|
94
|
+
- You never need to re-run pipelines from scratch because you’re adding data
|
|
95
|
+
- It integrates with any existing Python code or libraries
|
|
96
|
+
- Bring your ever-changing code and workloads
|
|
97
|
+
- You choose the models, tools, and AI practices (e.g., your embedding model for a vector index); Pixeltable orchestrates the data
|
|
98
|
+
|
|
99
|
+
## Example Use Cases
|
|
100
|
+
|
|
101
|
+
* Interact with video data at the frame level without having to think about frame extraction,
|
|
102
|
+
intermediate file storage, or storage space explosion.
|
|
103
|
+
* Augment your data incrementally and interactively with built-in functions and UDFs, such as
|
|
104
|
+
image transformations, model inference, and visualizations, without having to think about data pipelines,
|
|
105
|
+
incremental updates, or capturing function output.
|
|
106
|
+
* Interact with all the data relevant to your AI application (video, images, documents, audio, structured data, JSON) through
|
|
107
|
+
a simple dataframe-style API directly in Python. This includes:
|
|
108
|
+
* similarity search on embeddings, supported by high-dimensional vector indexing
|
|
109
|
+
* path expressions and transformations on JSON data
|
|
110
|
+
* PIL and OpenCV image operations
|
|
111
|
+
* assembling frames into videos
|
|
112
|
+
* Perform keyword and image similarity search at the video frame level without having to worry about frame
|
|
113
|
+
storage.
|
|
114
|
+
* Access all Pixeltable-resident data directly as a PyTorch dataset in your training scripts.
|
|
115
|
+
* Understand the compute and storage costs of your data at the granularity of individual augmentations and
|
|
116
|
+
get cost projections before adding new data and new augmentations.
|
|
117
|
+
* Rely on Pixeltable's automatic versioning and snapshot functionality to protect against regressions
|
|
118
|
+
and to ensure reproducibility.
|
|
119
|
+
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
pixeltable/__init__.py,sha256=enh38lhZ_38Ys3rCy_XC_BlPNPK9H2CKV4KePaqnV4E,959
|
|
2
|
+
pixeltable/catalog/__init__.py,sha256=E41bxaPeQIcgRYzTWc2vkDOboQhRymrJf4IcHQO7o_8,453
|
|
3
|
+
pixeltable/catalog/catalog.py,sha256=0TYWB1R6YBp9qCkWF7kCcX2Yw70UuburKKIemv5L1Js,7908
|
|
4
|
+
pixeltable/catalog/column.py,sha256=7PU5yECislpR_PNZTT3Z5sZiE34DnI6SR3WDsI-WgCg,8661
|
|
5
|
+
pixeltable/catalog/dir.py,sha256=pG1nMpG123POo6WMSHhAmnwXOQ26uUJfUcbzL-Jb4ws,919
|
|
6
|
+
pixeltable/catalog/globals.py,sha256=yLEGNbsSnLzjWNHVJacfjA9hbw13Q6QXLOSCRmdTlq0,943
|
|
7
|
+
pixeltable/catalog/insertable_table.py,sha256=1JGZqmx5tKbm_UmJLIalntFDs81s-mvTv0gOqk98b3Q,8280
|
|
8
|
+
pixeltable/catalog/named_function.py,sha256=a96gnKtx-nz5_MzDIiD4t4Hxqdjkg9ZtijRQxvWA5WQ,1147
|
|
9
|
+
pixeltable/catalog/path.py,sha256=QgccEi_QOfaKt8YsR2zLtd_z7z7QQkU_1kprJFi2SPQ,1677
|
|
10
|
+
pixeltable/catalog/path_dict.py,sha256=xfvxg1Ze5jZCARUGASF2DRbQPh7pRVTYhuJ_u82gYUo,5941
|
|
11
|
+
pixeltable/catalog/schema_object.py,sha256=-UxmPLbuEBqJiJi_GGRbFdr7arAFxTqs4bt6TFmSt3M,1059
|
|
12
|
+
pixeltable/catalog/table.py,sha256=CJQc2NnebfL1ekMcaZhJEZ0CI408-F7R90_czjDKy-g,25499
|
|
13
|
+
pixeltable/catalog/table_version.py,sha256=Q1NSaeLmFw7gYgARyyW6JJ79GRhjtp0_Q410KH27e1Q,35680
|
|
14
|
+
pixeltable/catalog/table_version_path.py,sha256=kn5T0m5XBqphlDqCKsqD-s159diCjKvrSrtzYZHwKuw,5461
|
|
15
|
+
pixeltable/catalog/view.py,sha256=BIL3s4DV3tWbOcqtqnhn46B2UvLaBhppfJUlNEt5nec,9734
|
|
16
|
+
pixeltable/client.py,sha256=HiqGNRQoyBPXF2rAhTJFE3ZSUUaSLpGo28pLZjubh8Y,20548
|
|
17
|
+
pixeltable/dataframe.py,sha256=rLgeYdVhAyeCZcgTDJWbCwR59OVp5vmpwL4PrIaEcDM,28327
|
|
18
|
+
pixeltable/env.py,sha256=NdjLCAYCYqb2IlOJXTgLROondJim9adkj6hX3atCbNE,16225
|
|
19
|
+
pixeltable/exceptions.py,sha256=MSP9zeL0AmXT93XqjdvgGN4rzno1_KRrGriq6hpemnw,376
|
|
20
|
+
pixeltable/exec/__init__.py,sha256=FOQBSMQ3buGg5kRzymkfDCk5fnVfICn3LrsJtbyNC6E,412
|
|
21
|
+
pixeltable/exec/aggregation_node.py,sha256=cf6rVAgrGh_uaMrCIgXJIwQTmbcboJlnrH_MmPIQSd0,3321
|
|
22
|
+
pixeltable/exec/cache_prefetch_node.py,sha256=UE5LgZQzyhoiG1XNJgpXQ1CRJWVpiheJEAlcV9pc0ss,5104
|
|
23
|
+
pixeltable/exec/component_iteration_node.py,sha256=Uz6zEeaJMcbvF3S0W0qmLI_uWsZsaSspHKNzuAMrasg,4069
|
|
24
|
+
pixeltable/exec/data_row_batch.py,sha256=ZaS_ciyYhoP50Aoszhgtnh_yDRR6z9H43crnaJdP-xA,3505
|
|
25
|
+
pixeltable/exec/exec_context.py,sha256=E82Q2bJMJ1ulud5L5D9dh2Z8vEUQ659SgT614YKDO34,924
|
|
26
|
+
pixeltable/exec/exec_node.py,sha256=Hji5NCPHfa50IWyjladXrBm4I0zseV7AV4cVdx0Q8Ew,2170
|
|
27
|
+
pixeltable/exec/expr_eval_node.py,sha256=mqACyEy48fsiWkbHSkkMc8gG2nL-WT6eJSG3nltM85c,10810
|
|
28
|
+
pixeltable/exec/in_memory_data_node.py,sha256=x2Jn_AGx52YcDPORH8sZZRD0s64Ng1NvfMpqAW-bVwY,2949
|
|
29
|
+
pixeltable/exec/media_validation_node.py,sha256=OKfRyKpcn7AZdACy_HD4NsDC87ZfNFs1tdrQz2NiIVw,1514
|
|
30
|
+
pixeltable/exec/sql_scan_node.py,sha256=zKJ2_iM0ah748Vz8jD0Lkm7TRyUChIejnGUPNmYPgbs,10318
|
|
31
|
+
pixeltable/exprs/__init__.py,sha256=EkpjeEW-8rriE9hVb9PdiknHQ3-Y8jPp37yJ-NC_oWA,935
|
|
32
|
+
pixeltable/exprs/arithmetic_expr.py,sha256=sWBYCBKI6IHj9ASwDcm2BlkQ5gleVtKtmpiPvzFNBJM,4386
|
|
33
|
+
pixeltable/exprs/array_slice.py,sha256=VmWc6iFusrM85MjyEBBCfXG1Jnt8-Gr6-J88BXxNoOE,2131
|
|
34
|
+
pixeltable/exprs/column_property_ref.py,sha256=0PHiBys0fxe2LgjaMId5UHob4E-ZggyPLnnW41RgA0E,2706
|
|
35
|
+
pixeltable/exprs/column_ref.py,sha256=5-mbWV8-cWWu0ynxPSQ0L8oLewDrLp17xh8DOCmQ36s,4794
|
|
36
|
+
pixeltable/exprs/comparison.py,sha256=jwwvKG0nLOHiNyjZm8AWKn59qBtTYH98vTF_hhwn0Og,3000
|
|
37
|
+
pixeltable/exprs/compound_predicate.py,sha256=Gh22MKi625m5A_RunVRd-a1XFi-fitikqBVz2VNXKrs,3830
|
|
38
|
+
pixeltable/exprs/data_row.py,sha256=gKlRbzG4KoObR27zFK0QYlbc07IznIfYTwmknUyL5zo,7535
|
|
39
|
+
pixeltable/exprs/expr.py,sha256=JyEmP8F9LXmxOrVswih1Aq0SrpGcboSRinOYIMWYfKM,23748
|
|
40
|
+
pixeltable/exprs/expr_set.py,sha256=Q64Q2yI0CTq2Ma_E-BUYlMotSstVuMm4OFZnBCedHRk,1222
|
|
41
|
+
pixeltable/exprs/function_call.py,sha256=QFzkb2gKjeALGTgCet-o0HETwTXoFBzsncbghgScmOE,16961
|
|
42
|
+
pixeltable/exprs/globals.py,sha256=liPgUTccTkyDRs4kG2r9ehRkwGZERmrCSJDZRdJoMqk,1537
|
|
43
|
+
pixeltable/exprs/image_member_access.py,sha256=aLRpSu3fhAph86jYMQEdE4ZLoN96xDXlf4t4-MUX2_s,4663
|
|
44
|
+
pixeltable/exprs/image_similarity_predicate.py,sha256=PVoPaYP9-Wds1jZvr0AsUAjklkk2AxyokgcAykWs0g4,1906
|
|
45
|
+
pixeltable/exprs/inline_array.py,sha256=i9Q7kD11X5X-j-NiuMx8kigdEnKBEL8HKBX6fQ8TmyE,4312
|
|
46
|
+
pixeltable/exprs/inline_dict.py,sha256=Lb3VS3Mkxb72mWL4qipOQjUgY8AMxk1POj225Xqjtos,3695
|
|
47
|
+
pixeltable/exprs/is_null.py,sha256=nvpOXtQj1UeYJpkCWzbaGuQElzrA2HSG3XNQugOv-pw,1041
|
|
48
|
+
pixeltable/exprs/json_mapper.py,sha256=I60VNgus64ai80gnFCIsRn0VRWYXMkqH5VNvnATsN9s,4559
|
|
49
|
+
pixeltable/exprs/json_path.py,sha256=Wz_5zFsyc9TPhsSbsDjDmQ3Nb0uVIwMCx5nh-cQYBiE,6526
|
|
50
|
+
pixeltable/exprs/literal.py,sha256=LOeD0aN_V7Kg332xzCHWUlzKPupXiptpU_rg-X0bEt0,1885
|
|
51
|
+
pixeltable/exprs/object_ref.py,sha256=eTcx84aWRI59fIiGvbdv3_cfL0XW4xEFQ4lwpLpJkM8,1250
|
|
52
|
+
pixeltable/exprs/predicate.py,sha256=OSDgjfSqiK7J_5GZMUXMvjfyomKEGi0JNxeB073SGXw,1859
|
|
53
|
+
pixeltable/exprs/row_builder.py,sha256=sOW2zG6MwqOT8BFgmlveqIiRGPZinuK0_dY6IgmCWT0,16992
|
|
54
|
+
pixeltable/exprs/rowid_ref.py,sha256=74w4rEy21YysTVbyKNc3op-pYFqDAx8VJdtl7ZPpxHs,4268
|
|
55
|
+
pixeltable/exprs/type_cast.py,sha256=JMg8p1qYoFfiAXfJPSbTEnfrK7lRO_JMaqlPHOrhNQU,1793
|
|
56
|
+
pixeltable/exprs/variable.py,sha256=Kg_O4ytcHYZFijIyMHYBJn063cTKU1-YE583FAz8Qaw,1361
|
|
57
|
+
pixeltable/func/__init__.py,sha256=4qvDnK_S5yljwtIrxCkeQlz6vuTVfwSU4zl-MBT2TMU,457
|
|
58
|
+
pixeltable/func/aggregate_function.py,sha256=E11lVKBR4MZQ6VT0G4oo5xWR907BqHqJog-widXcJt0,9177
|
|
59
|
+
pixeltable/func/batched_function.py,sha256=nrfmykJps4QkgzeC4ZroGy8mJ-BACNKbRJABHHG6-Ac,2350
|
|
60
|
+
pixeltable/func/callable_function.py,sha256=WGUwjNEzXGDJ1jzdZ-mrn2cnfEHmFZIh_DRl_Yk89D0,2357
|
|
61
|
+
pixeltable/func/expr_template_function.py,sha256=Nj-FDDozSuvcoQ7KsJcQrzzQn7foeCY7zSEFkusiLqQ,3392
|
|
62
|
+
pixeltable/func/function.py,sha256=NcGyKp7ds6bMzg1qzuaK8pBQH_DhknmSiZzsfXi-z2k,4023
|
|
63
|
+
pixeltable/func/function_registry.py,sha256=1ibSQxEPm3Zd3r497vSlckQiDG9sfCnyJx3zcSm9t7c,11456
|
|
64
|
+
pixeltable/func/globals.py,sha256=UP4hAkEVKD_3lr7l_VVUUCetJP85sydUYiVAU4m5-aw,1220
|
|
65
|
+
pixeltable/func/nos_function.py,sha256=HzIKK4XjTo1E6pML-EbhuX3u_LYibFWUuTkIxoIih7c,9650
|
|
66
|
+
pixeltable/func/signature.py,sha256=5Xo3hIVSXoYtkU-BvUi21b6FghIQABm48UfVjQr9QYU,7107
|
|
67
|
+
pixeltable/func/udf.py,sha256=XlB7dzOc98XinUrs4tMGUAetV0SmQ_Z2oKPDBsx46o0,6457
|
|
68
|
+
pixeltable/functions/__init__.py,sha256=kFepRTpg-YOeeXG9076s9v-lm8ZUNqicaPUfX-CrW5c,3419
|
|
69
|
+
pixeltable/functions/eval.py,sha256=qLc_55VTwi_IDnAJFq79Hy7FLi7Gb26DxdykYiBTMrM,8453
|
|
70
|
+
pixeltable/functions/fireworks.py,sha256=7h1gxcGhG8jepS_Gi1nwp8zCw1gdRaTzufS6U08mmLc,1596
|
|
71
|
+
pixeltable/functions/huggingface.py,sha256=Wg8AgCsoGFx8AX3AThko66L7uSg9cUEjL8_QxKoA4dg,4804
|
|
72
|
+
pixeltable/functions/image.py,sha256=xR_S_0BuX6Ycc5E366GpOfP0JptD7beQwHE_fLl8ZVM,431
|
|
73
|
+
pixeltable/functions/openai.py,sha256=SkwUBnnTT6olQCMHzQGO0vpvApgAaBk_88W7YM8QQuo,2863
|
|
74
|
+
pixeltable/functions/pil/image.py,sha256=8gItSXXuJaCkq9FHEJE9qFpRM3WAoa59x89Xa0DgksQ,6217
|
|
75
|
+
pixeltable/functions/string.py,sha256=RYOgZwifjC943YloEMi3PdflnjFqOYB2FddrUvzgtXs,516
|
|
76
|
+
pixeltable/functions/together.py,sha256=TGo72RJuHqofwJHSrHqsJoO6RQm6Iipqhy49V3JiBss,650
|
|
77
|
+
pixeltable/functions/util.py,sha256=v094FgixHchzKMj4YvfHExDRGIVhCL2D-NL3pl-92oo,1596
|
|
78
|
+
pixeltable/functions/video.py,sha256=WZF4G3tV-_LfRQHUinXe_rnu1-4N68Ht60JCR_s7Bew,2403
|
|
79
|
+
pixeltable/iterators/__init__.py,sha256=sfsasCypAq5rNOTMlr4j2ROXxzdl4M8L2KvQIEbd0cQ,70
|
|
80
|
+
pixeltable/iterators/base.py,sha256=sugU9mG19xf9I4c_lEQDI_xrXPLuyuIYlKc-9OiS1HQ,1545
|
|
81
|
+
pixeltable/iterators/document.py,sha256=LWqF8dK5sLMLemyYfEOSGXC8z8yrTev4cbgHbORPyQ0,13088
|
|
82
|
+
pixeltable/iterators/video.py,sha256=mUdHev0f_XJIfHTB-mejjToURh10Ud7l096eZm2aPjM,3444
|
|
83
|
+
pixeltable/metadata/__init__.py,sha256=6rLGFpWzQMCk0EcSKLp4Bnbk8tLK1cxuONBPqwDCMzU,2083
|
|
84
|
+
pixeltable/metadata/converters/convert_10.py,sha256=0mSGCn7vqtef63riPi9msUaaUvsSQIj-NFj9QFDYPdA,733
|
|
85
|
+
pixeltable/metadata/schema.py,sha256=oTxtFSvbmCEcr54F929_NYFVp76N8gpN4nHDr9VnA9M,7761
|
|
86
|
+
pixeltable/plan.py,sha256=BQMCxOCy7lO4dqBCt5W9GUFdBWkuhr13-T8_2E97fUk,34710
|
|
87
|
+
pixeltable/store.py,sha256=91WSmmYcvf_dXZEchj4jcBC7GavPFGZbwHGoPMKlfjU,19230
|
|
88
|
+
pixeltable/tests/conftest.py,sha256=8H8llMTdc7l9tUKuPqI-KzJYdM_G_X-mGPx9RhxNPYU,6581
|
|
89
|
+
pixeltable/tests/test_audio.py,sha256=92PMPrMtYzLoaLiW92MupEfWPEcfoLlYlZKlxmWQXdI,3186
|
|
90
|
+
pixeltable/tests/test_catalog.py,sha256=Npxt72g5aZkfg1fqE-19L8rGilzicAiTC0ithIy3woI,1189
|
|
91
|
+
pixeltable/tests/test_client.py,sha256=9acrjElh1YVX8WXWO04VQ-S6mNx9ZtqAHoh4uBc81y4,531
|
|
92
|
+
pixeltable/tests/test_component_view.py,sha256=I_IQalmd79LocI3bgwQ4Ad91fOHS1E9AOVhe--NH4Io,17704
|
|
93
|
+
pixeltable/tests/test_dataframe.py,sha256=zu1Zw3c7k96afWqUyFwUnOBebzLxTRZ0xA3v7tnM2n8,17686
|
|
94
|
+
pixeltable/tests/test_dirs.py,sha256=WuWGOcpUFPCl1PGZgOMcU5bpzv1ClUqZ5AxavrDeCic,3611
|
|
95
|
+
pixeltable/tests/test_document.py,sha256=KUHZmjpI94rHdwOPBrhsSpeaqYbBTzIKa2gX98WGE7E,5657
|
|
96
|
+
pixeltable/tests/test_exprs.py,sha256=A4rhwONnOjovgenYF81n_q8NMJaGisT1kq8kJdDAqQ4,32695
|
|
97
|
+
pixeltable/tests/test_function.py,sha256=6sA_3Oe1p4sUhL5L5hYyW-mG1TPGfFDmW1BPVPnGXek,12817
|
|
98
|
+
pixeltable/tests/test_functions.py,sha256=XmqIwcZ5lVouSowtVImJPgIv0bSEYHR-J0BzgLDHkm8,14477
|
|
99
|
+
pixeltable/tests/test_migration.py,sha256=UjJhhg061TtyTAa1CAB-BdlT9YwLJkl8yIGSetnqcKw,1535
|
|
100
|
+
pixeltable/tests/test_nos.py,sha256=ITE7FNEaNreJ_XTz4wYLWuidFSUQMFp3ShuHTz05OrE,2649
|
|
101
|
+
pixeltable/tests/test_snapshot.py,sha256=J8wepLOaOrJkqDWq1dkou8MIR5Hf1DEseAqlUrb7BFg,9297
|
|
102
|
+
pixeltable/tests/test_table.py,sha256=rnB8LxER2hwXhFGWpZI_XgV_ZYfiYSw4x8zmbh-eln8,48202
|
|
103
|
+
pixeltable/tests/test_transactional_directory.py,sha256=Jx55PZgrkHTI0Eli09puwMckvwfCM9arPTQUT9g6Tbg,1308
|
|
104
|
+
pixeltable/tests/test_types.py,sha256=4_LR5Poc8Fa5fOpRBaAc_qAN21SsVxFP54Npq_6n9G8,970
|
|
105
|
+
pixeltable/tests/test_video.py,sha256=GiSQjvobVdMvjGqvpZCc778sGpqX4LEy84zfgNSpjtA,7676
|
|
106
|
+
pixeltable/tests/test_view.py,sha256=vbKEk9kWF5U6B78uNLSQsGw46s2oOOhHnJy8p9NmNTo,21859
|
|
107
|
+
pixeltable/tests/utils.py,sha256=z_dj69xN3iLA2-nL7dy98tvZdlPFKjZHNuWogAWO75Y,9914
|
|
108
|
+
pixeltable/tool/create_test_db_dump.py,sha256=ARlLUfOs4stxIPFl-hGl_KX-ck6JRWmUiXqTwTtS1GU,5148
|
|
109
|
+
pixeltable/type_system.py,sha256=w3UMqk3U1IXyo-gAfoeiaOB26iSgYKAeGmTDzpwQkRk,31781
|
|
110
|
+
pixeltable/utils/__init__.py,sha256=UYlrf6TIWJT0g-Hac0b34-dEk478B5Qx8dGco34YlIk,439
|
|
111
|
+
pixeltable/utils/clip.py,sha256=HXXWFBJXW9XysdMk9_3hP1V1S-3B8Hwd5rNMbJFjjnI,720
|
|
112
|
+
pixeltable/utils/coco.py,sha256=mk1cxjKYQC0ABm2ZQ9SNu9MvBPECmmKvnASpxnFXdL0,5604
|
|
113
|
+
pixeltable/utils/documents.py,sha256=MGtWZs93Bt_pdExxT9yjH7VWbawSd5A2O5_YdxEZlMk,1094
|
|
114
|
+
pixeltable/utils/filecache.py,sha256=UoNONG2VaAc2IBB0e3sQdsvyOPOes2XSDc5_CsA4qek,7839
|
|
115
|
+
pixeltable/utils/help.py,sha256=cCnxJ4VP9MJ57iDqExmnDcM-JG3a1lw_q7g-D7bpSVI,252
|
|
116
|
+
pixeltable/utils/media_store.py,sha256=x71wnJDZDHcdd13VCfL4AkHQ6IJB41gNA-zBvXJwFos,3116
|
|
117
|
+
pixeltable/utils/parquet.py,sha256=3cjC1vibPHQ24cQS0xPwTjkhxK9TVkITkSxkf29bdaQ,5775
|
|
118
|
+
pixeltable/utils/pytorch.py,sha256=h7q-7q3gXThDoTVA8k9vIvMc4VgnNAQy3ScDIU6h3IE,6515
|
|
119
|
+
pixeltable/utils/s3.py,sha256=rkanuhk9DWvSfmbOLQW1j1Iov4sl2KhxGGKN-AJ8LSE,432
|
|
120
|
+
pixeltable/utils/sql.py,sha256=5n5_OmXAGtqFdL6z5XvgnU-vlx6Ba6f1WJrO1ZwUle8,765
|
|
121
|
+
pixeltable/utils/transactional_directory.py,sha256=UGzCrGtLR3hEEf8sYGuWBzLVFAEQml3vdIavigWeTBM,1349
|
|
122
|
+
pixeltable-0.2.1.dist-info/LICENSE,sha256=0UNMmwuqWPC0xDY1NWMm4uNJ2_MyA1pnTNRgQTvuBiQ,746
|
|
123
|
+
pixeltable-0.2.1.dist-info/METADATA,sha256=kGc8hDA7BwNSqw_uM-c-rytQbY8iZPFJKs_X8jQv0DY,5392
|
|
124
|
+
pixeltable-0.2.1.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
125
|
+
pixeltable-0.2.1.dist-info/RECORD,,
|