pixeltable 0.1.1__py3-none-any.whl → 0.2.0__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.

Files changed (139) hide show
  1. pixeltable/__init__.py +34 -6
  2. pixeltable/catalog/__init__.py +13 -0
  3. pixeltable/catalog/catalog.py +159 -0
  4. pixeltable/catalog/column.py +200 -0
  5. pixeltable/catalog/dir.py +32 -0
  6. pixeltable/catalog/globals.py +33 -0
  7. pixeltable/catalog/insertable_table.py +191 -0
  8. pixeltable/catalog/named_function.py +36 -0
  9. pixeltable/catalog/path.py +58 -0
  10. pixeltable/catalog/path_dict.py +139 -0
  11. pixeltable/catalog/schema_object.py +39 -0
  12. pixeltable/catalog/table.py +581 -0
  13. pixeltable/catalog/table_version.py +749 -0
  14. pixeltable/catalog/table_version_path.py +133 -0
  15. pixeltable/catalog/view.py +203 -0
  16. pixeltable/client.py +520 -30
  17. pixeltable/dataframe.py +540 -349
  18. pixeltable/env.py +373 -45
  19. pixeltable/exceptions.py +12 -21
  20. pixeltable/exec/__init__.py +9 -0
  21. pixeltable/exec/aggregation_node.py +78 -0
  22. pixeltable/exec/cache_prefetch_node.py +113 -0
  23. pixeltable/exec/component_iteration_node.py +79 -0
  24. pixeltable/exec/data_row_batch.py +95 -0
  25. pixeltable/exec/exec_context.py +22 -0
  26. pixeltable/exec/exec_node.py +61 -0
  27. pixeltable/exec/expr_eval_node.py +217 -0
  28. pixeltable/exec/in_memory_data_node.py +69 -0
  29. pixeltable/exec/media_validation_node.py +43 -0
  30. pixeltable/exec/sql_scan_node.py +225 -0
  31. pixeltable/exprs/__init__.py +24 -0
  32. pixeltable/exprs/arithmetic_expr.py +102 -0
  33. pixeltable/exprs/array_slice.py +71 -0
  34. pixeltable/exprs/column_property_ref.py +77 -0
  35. pixeltable/exprs/column_ref.py +105 -0
  36. pixeltable/exprs/comparison.py +77 -0
  37. pixeltable/exprs/compound_predicate.py +98 -0
  38. pixeltable/exprs/data_row.py +187 -0
  39. pixeltable/exprs/expr.py +586 -0
  40. pixeltable/exprs/expr_set.py +39 -0
  41. pixeltable/exprs/function_call.py +380 -0
  42. pixeltable/exprs/globals.py +69 -0
  43. pixeltable/exprs/image_member_access.py +115 -0
  44. pixeltable/exprs/image_similarity_predicate.py +58 -0
  45. pixeltable/exprs/inline_array.py +107 -0
  46. pixeltable/exprs/inline_dict.py +101 -0
  47. pixeltable/exprs/is_null.py +38 -0
  48. pixeltable/exprs/json_mapper.py +121 -0
  49. pixeltable/exprs/json_path.py +159 -0
  50. pixeltable/exprs/literal.py +54 -0
  51. pixeltable/exprs/object_ref.py +41 -0
  52. pixeltable/exprs/predicate.py +44 -0
  53. pixeltable/exprs/row_builder.py +355 -0
  54. pixeltable/exprs/rowid_ref.py +94 -0
  55. pixeltable/exprs/type_cast.py +53 -0
  56. pixeltable/exprs/variable.py +45 -0
  57. pixeltable/func/__init__.py +9 -0
  58. pixeltable/func/aggregate_function.py +194 -0
  59. pixeltable/func/batched_function.py +53 -0
  60. pixeltable/func/callable_function.py +69 -0
  61. pixeltable/func/expr_template_function.py +82 -0
  62. pixeltable/func/function.py +110 -0
  63. pixeltable/func/function_registry.py +227 -0
  64. pixeltable/func/globals.py +36 -0
  65. pixeltable/func/nos_function.py +202 -0
  66. pixeltable/func/signature.py +166 -0
  67. pixeltable/func/udf.py +163 -0
  68. pixeltable/functions/__init__.py +52 -103
  69. pixeltable/functions/eval.py +216 -0
  70. pixeltable/functions/fireworks.py +61 -0
  71. pixeltable/functions/huggingface.py +120 -0
  72. pixeltable/functions/image.py +16 -0
  73. pixeltable/functions/openai.py +88 -0
  74. pixeltable/functions/pil/image.py +148 -7
  75. pixeltable/functions/string.py +13 -0
  76. pixeltable/functions/together.py +27 -0
  77. pixeltable/functions/util.py +41 -0
  78. pixeltable/functions/video.py +62 -0
  79. pixeltable/iterators/__init__.py +3 -0
  80. pixeltable/iterators/base.py +48 -0
  81. pixeltable/iterators/document.py +311 -0
  82. pixeltable/iterators/video.py +89 -0
  83. pixeltable/metadata/__init__.py +54 -0
  84. pixeltable/metadata/converters/convert_10.py +18 -0
  85. pixeltable/metadata/schema.py +211 -0
  86. pixeltable/plan.py +656 -0
  87. pixeltable/store.py +413 -182
  88. pixeltable/tests/conftest.py +143 -87
  89. pixeltable/tests/test_audio.py +65 -0
  90. pixeltable/tests/test_catalog.py +27 -0
  91. pixeltable/tests/test_client.py +14 -14
  92. pixeltable/tests/test_component_view.py +372 -0
  93. pixeltable/tests/test_dataframe.py +433 -0
  94. pixeltable/tests/test_dirs.py +78 -62
  95. pixeltable/tests/test_document.py +117 -0
  96. pixeltable/tests/test_exprs.py +591 -135
  97. pixeltable/tests/test_function.py +297 -67
  98. pixeltable/tests/test_functions.py +283 -1
  99. pixeltable/tests/test_migration.py +43 -0
  100. pixeltable/tests/test_nos.py +54 -0
  101. pixeltable/tests/test_snapshot.py +208 -0
  102. pixeltable/tests/test_table.py +1085 -262
  103. pixeltable/tests/test_transactional_directory.py +42 -0
  104. pixeltable/tests/test_types.py +5 -11
  105. pixeltable/tests/test_video.py +149 -34
  106. pixeltable/tests/test_view.py +530 -0
  107. pixeltable/tests/utils.py +186 -45
  108. pixeltable/tool/create_test_db_dump.py +149 -0
  109. pixeltable/type_system.py +490 -126
  110. pixeltable/utils/__init__.py +17 -46
  111. pixeltable/utils/clip.py +12 -15
  112. pixeltable/utils/coco.py +136 -0
  113. pixeltable/utils/documents.py +39 -0
  114. pixeltable/utils/filecache.py +195 -0
  115. pixeltable/utils/help.py +11 -0
  116. pixeltable/utils/media_store.py +76 -0
  117. pixeltable/utils/parquet.py +126 -0
  118. pixeltable/utils/pytorch.py +172 -0
  119. pixeltable/utils/s3.py +13 -0
  120. pixeltable/utils/sql.py +17 -0
  121. pixeltable/utils/transactional_directory.py +35 -0
  122. pixeltable-0.2.0.dist-info/LICENSE +18 -0
  123. pixeltable-0.2.0.dist-info/METADATA +117 -0
  124. pixeltable-0.2.0.dist-info/RECORD +125 -0
  125. {pixeltable-0.1.1.dist-info → pixeltable-0.2.0.dist-info}/WHEEL +1 -1
  126. pixeltable/catalog.py +0 -1421
  127. pixeltable/exprs.py +0 -1745
  128. pixeltable/function.py +0 -269
  129. pixeltable/functions/clip.py +0 -10
  130. pixeltable/functions/pil/__init__.py +0 -23
  131. pixeltable/functions/tf.py +0 -21
  132. pixeltable/index.py +0 -57
  133. pixeltable/tests/test_dict.py +0 -24
  134. pixeltable/tests/test_tf.py +0 -69
  135. pixeltable/tf.py +0 -33
  136. pixeltable/utils/tf.py +0 -33
  137. pixeltable/utils/video.py +0 -32
  138. pixeltable-0.1.1.dist-info/METADATA +0 -31
  139. pixeltable-0.1.1.dist-info/RECORD +0 -36
@@ -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)
@@ -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,117 @@
1
+ Metadata-Version: 2.1
2
+ Name: pixeltable
3
+ Version: 0.2.0
4
+ Summary: Pixeltable: The Multimodal AI Data Plane
5
+ Author: Marcel Kornacker
6
+ Author-email: marcelk@gmail.com
7
+ Requires-Python: >=3.8.1,<4.0.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: jmespath (>=1.0.1,<2.0.0)
16
+ Requires-Dist: numpy (>=1.24.1,<2.0.0)
17
+ Requires-Dist: opencv-python-headless (>=4.7.0.68,<5.0.0.0)
18
+ Requires-Dist: pandas (>=1.5.3,<2.0.0)
19
+ Requires-Dist: pgserver (==0.0.5)
20
+ Requires-Dist: pgvector (>=0.2.1,<0.3.0)
21
+ Requires-Dist: pillow (>=9.4.0,<10.0.0)
22
+ Requires-Dist: psutil (>=5.9.5,<6.0.0)
23
+ Requires-Dist: psycopg2-binary (>=2.9.5,<3.0.0)
24
+ Requires-Dist: regex (>=2022.10.31,<2023.0.0)
25
+ Requires-Dist: sqlalchemy-utils (>=0.41.1,<0.42.0)
26
+ Requires-Dist: sqlalchemy[mypy] (>=2.0.23,<3.0.0)
27
+ Requires-Dist: tqdm (>=4.64.1,<5.0.0)
28
+ Description-Content-Type: text/markdown
29
+
30
+ <img src="docs/pixeltable-banner.png" width="45%"/>
31
+
32
+ # Pixeltable: The Multimodal AI Data Plane
33
+
34
+ [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
35
+ &nbsp;&nbsp;
36
+ ![pytest status](https://github.com/pixeltable/pixeltable/actions/workflows/pytest.yml/badge.svg)
37
+
38
+ Pixeltable is a Python library that lets AI engineers and data scientists focus on
39
+ exploration, modeling, and app development without having to deal with the customary
40
+ data plumbing.
41
+
42
+ **Pixeltable redefines data infrastructure and workflow orchestration for AI development.**
43
+ It brings together data storage, versioning, and indexing with orchestration and model
44
+ versioning under a declarative table interface, with transformations, model inference,
45
+ and custom logic represented as computed columns.
46
+ <!--
47
+ ## Quick Start
48
+
49
+ If you just want to play around with Pixeltable to see what it's capable of, the easiest way is to run
50
+ the Pixeltable Basics tutorial in colab:
51
+
52
+ <a target="_blank" href="https://colab.research.google.com/github/pixeltable/pixeltable/blob/docs/tutorials/pixeltable-basics.ipynb">
53
+ <img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
54
+ </a>
55
+ -->
56
+ ## Installation
57
+
58
+ Pixeltable works with Python 3.9, 3.10, or 3.11 running on Linux or MacOS.
59
+
60
+ ```
61
+ pip install pixeltable
62
+ ```
63
+
64
+ To verify that it's working:
65
+
66
+ ```
67
+ import pixeltable as pxt
68
+ cl = pxt.Client()
69
+ ```
70
+
71
+ For more detailed installation instructions, see the
72
+ [Getting Started with Pixeltable](https://pixeltable.github.io/pixeltable/getting-started/)
73
+ guide. Then, check out the
74
+ [Pixeltable Basics](https://pixeltable.github.io/pixeltable/tutorials/pixeltable-basics/)
75
+ tutorial for a tour of its most important features.
76
+
77
+ ## What problems does Pixeltable solve?
78
+
79
+ Today’s solutions for AI app development require extensive custom coding and infrastructure
80
+ plumbing. Tracking lineage and versions between and across data transformations, models, and
81
+ deployment is cumbersome. Pixeltable is a replacement for traditional data plumbing, providing
82
+ a unified plane for data, models, and orchestration. It removes the data plumbing overhead in
83
+ building and productionizing AI applications.
84
+
85
+ ## Why should you use Pixeltable?
86
+
87
+ - It gives you transparency and reproducibility
88
+ - All generated data is automatically recorded and versioned
89
+ - You will never need to re-run a workload because you lost track of the input data
90
+ - It saves you money
91
+ - All data changes are automatically incremental
92
+ - You never need to re-run pipelines from scratch because you’re adding data
93
+ - It integrates with any existing Python code or libraries
94
+ - Bring your ever-changing code and workloads
95
+ - You choose the models, tools, and AI practices (e.g., your embedding model for a vector index); Pixeltable orchestrates the data
96
+
97
+ ## Example Use Cases
98
+
99
+ * Interact with video data at the frame level without having to think about frame extraction,
100
+ intermediate file storage, or storage space explosion.
101
+ * Augment your data incrementally and interactively with built-in functions and UDFs, such as
102
+ image transformations, model inference, and visualizations, without having to think about data pipelines,
103
+ incremental updates, or capturing function output.
104
+ * Interact with all the data relevant to your AI application (video, images, documents, audio, structured data, JSON) through
105
+ a simple dataframe-style API directly in Python. This includes:
106
+ * similarity search on embeddings, supported by high-dimensional vector indexing
107
+ * path expressions and transformations on JSON data
108
+ * PIL and OpenCV image operations
109
+ * assembling frames into videos
110
+ * Perform keyword and image similarity search at the video frame level without having to worry about frame
111
+ storage.
112
+ * Access all Pixeltable-resident data directly as a PyTorch dataset in your training scripts.
113
+ * Understand the compute and storage costs of your data at the granularity of individual augmentations and
114
+ get cost projections before adding new data and new augmentations.
115
+ * Rely on Pixeltable's automatic versioning and snapshot functionality to protect against regressions
116
+ and to ensure reproducibility.
117
+
@@ -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=dyMFrRZLuTH7Hxktw5vB3COwyFlm07pp2NxNZVw-OeE,1595
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.0.dist-info/LICENSE,sha256=0UNMmwuqWPC0xDY1NWMm4uNJ2_MyA1pnTNRgQTvuBiQ,746
123
+ pixeltable-0.2.0.dist-info/METADATA,sha256=TQx4mS65RW-LJMvQibBnuFdC0lySvVZu9fqOg0eAkJU,5318
124
+ pixeltable-0.2.0.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
125
+ pixeltable-0.2.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.4.0
2
+ Generator: poetry-core 1.8.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any