pixeltable 0.2.13__py3-none-any.whl → 0.2.14__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 (51) hide show
  1. pixeltable/__init__.py +1 -1
  2. pixeltable/__version__.py +2 -2
  3. pixeltable/catalog/column.py +5 -0
  4. pixeltable/catalog/globals.py +8 -0
  5. pixeltable/catalog/table.py +22 -4
  6. pixeltable/catalog/table_version.py +30 -55
  7. pixeltable/catalog/view.py +1 -1
  8. pixeltable/exec/__init__.py +2 -1
  9. pixeltable/exec/row_update_node.py +61 -0
  10. pixeltable/exec/{sql_scan_node.py → sql_node.py} +120 -56
  11. pixeltable/exprs/__init__.py +1 -1
  12. pixeltable/exprs/expr.py +35 -22
  13. pixeltable/exprs/function_call.py +60 -29
  14. pixeltable/exprs/globals.py +2 -0
  15. pixeltable/exprs/inline_array.py +18 -11
  16. pixeltable/exprs/method_ref.py +63 -0
  17. pixeltable/ext/__init__.py +9 -0
  18. pixeltable/ext/functions/__init__.py +8 -0
  19. pixeltable/ext/functions/whisperx.py +45 -5
  20. pixeltable/ext/functions/yolox.py +60 -14
  21. pixeltable/func/callable_function.py +12 -4
  22. pixeltable/func/expr_template_function.py +1 -1
  23. pixeltable/func/function.py +12 -2
  24. pixeltable/func/function_registry.py +24 -9
  25. pixeltable/func/udf.py +32 -4
  26. pixeltable/functions/__init__.py +1 -1
  27. pixeltable/functions/fireworks.py +33 -0
  28. pixeltable/functions/huggingface.py +96 -6
  29. pixeltable/functions/image.py +226 -41
  30. pixeltable/functions/openai.py +214 -0
  31. pixeltable/functions/string.py +195 -218
  32. pixeltable/functions/timestamp.py +210 -0
  33. pixeltable/functions/together.py +106 -0
  34. pixeltable/functions/video.py +2 -2
  35. pixeltable/functions/whisper.py +32 -0
  36. pixeltable/io/__init__.py +1 -1
  37. pixeltable/io/globals.py +133 -1
  38. pixeltable/io/pandas.py +52 -27
  39. pixeltable/metadata/__init__.py +1 -1
  40. pixeltable/metadata/converters/convert_18.py +39 -0
  41. pixeltable/metadata/notes.py +10 -0
  42. pixeltable/plan.py +76 -1
  43. pixeltable/tool/create_test_db_dump.py +3 -4
  44. pixeltable/tool/doc_plugins/griffe.py +4 -0
  45. pixeltable/type_system.py +15 -14
  46. {pixeltable-0.2.13.dist-info → pixeltable-0.2.14.dist-info}/METADATA +1 -1
  47. {pixeltable-0.2.13.dist-info → pixeltable-0.2.14.dist-info}/RECORD +50 -45
  48. pixeltable/exprs/image_member_access.py +0 -96
  49. {pixeltable-0.2.13.dist-info → pixeltable-0.2.14.dist-info}/LICENSE +0 -0
  50. {pixeltable-0.2.13.dist-info → pixeltable-0.2.14.dist-info}/WHEEL +0 -0
  51. {pixeltable-0.2.13.dist-info → pixeltable-0.2.14.dist-info}/entry_points.txt +0 -0
pixeltable/io/pandas.py CHANGED
@@ -1,4 +1,4 @@
1
- from typing import Optional, Any, Iterable, Union
1
+ from typing import Any, Optional, Union
2
2
 
3
3
  import numpy as np
4
4
  import pandas as pd
@@ -15,7 +15,7 @@ def import_pandas(
15
15
  comment: str = ''
16
16
  ) -> pxt.catalog.InsertableTable:
17
17
  """Creates a new `Table` from a Pandas `DataFrame`, with the specified name. The schema of the table
18
- will be inferred from the `DataFrame`, unless `schema` is specified.
18
+ will be inferred from the `DataFrame`.
19
19
 
20
20
  The column names of the new `Table` will be identical to those in the `DataFrame`, as long as they are valid
21
21
  Pixeltable identifiers. If a column name is not a valid Pixeltable identifier, it will be normalized according to
@@ -32,9 +32,16 @@ def import_pandas(
32
32
  `schema_overrides` should be the column names of the `DataFrame` (whether or not they are valid
33
33
  Pixeltable identifiers).
34
34
  """
35
- schema = _df_to_pxt_schema(df, schema_overrides)
36
- tbl_rows = (dict(_df_row_to_pxt_row(row, schema)) for row in df.itertuples())
37
- table = pxt.create_table(tbl_name, schema, primary_key=primary_key, num_retained_versions=num_retained_versions, comment=comment)
35
+ if schema_overrides is None:
36
+ schema_overrides = {}
37
+ if primary_key is None:
38
+ primary_key = []
39
+ elif isinstance(primary_key, str):
40
+ primary_key = [primary_key]
41
+
42
+ schema, pxt_pk = __df_to_pxt_schema(df, schema_overrides, primary_key)
43
+ tbl_rows = (dict(__df_row_to_pxt_row(row, schema)) for row in df.itertuples())
44
+ table = pxt.create_table(tbl_name, schema, primary_key=pxt_pk, num_retained_versions=num_retained_versions, comment=comment)
38
45
  table.insert(tbl_rows)
39
46
  return table
40
47
 
@@ -71,22 +78,33 @@ def import_excel(
71
78
  return import_pandas(tbl_name, df, schema_overrides=schema_overrides, primary_key=primary_key, num_retained_versions=num_retained_versions, comment=comment)
72
79
 
73
80
 
74
- def _df_to_pxt_schema(
75
- df: pd.DataFrame, schema_overrides: Optional[dict[str, pxt.ColumnType]]
76
- ) -> dict[str, pxt.ColumnType]:
77
- if schema_overrides is not None:
78
- for pd_name in schema_overrides:
79
- if pd_name not in df.columns:
80
- raise excs.Error(
81
- f'Column `{pd_name}` specified in `schema_overrides` does not exist in the given `DataFrame`.'
82
- )
83
- schema = {}
81
+ def __df_to_pxt_schema(
82
+ df: pd.DataFrame, schema_overrides: dict[str, pxt.ColumnType], primary_key: list[str]
83
+ ) -> tuple[dict[str, pxt.ColumnType], list[str]]:
84
+ """
85
+ Infers a Pixeltable schema from a Pandas DataFrame.
86
+
87
+ Returns:
88
+ A tuple containing a Pixeltable schema and a list of primary key column names.
89
+ """
90
+ for pd_name in schema_overrides:
91
+ if pd_name not in df.columns:
92
+ raise excs.Error(
93
+ f'Column `{pd_name}` specified in `schema_overrides` does not exist in the given `DataFrame`.'
94
+ )
95
+ for pd_name in primary_key:
96
+ if pd_name not in df.columns:
97
+ raise excs.Error(f'Primary key column `{pd_name}` does not exist in the given `DataFrame`.')
98
+
99
+ schema: dict[str, pxt.ColumnType] = {}
100
+ col_mapping: dict[str, str] = {} # Maps Pandas column names to Pixeltable column names
101
+
84
102
  for pd_name, pd_dtype in zip(df.columns, df.dtypes):
85
- if schema_overrides is not None and pd_name in schema_overrides:
103
+ if pd_name in schema_overrides:
86
104
  pxt_type = schema_overrides[pd_name]
87
105
  else:
88
- pxt_type = _np_dtype_to_pxt_type(pd_dtype, df[pd_name])
89
- pxt_name = _normalize_pxt_col_name(pd_name)
106
+ pxt_type = __np_dtype_to_pxt_type(pd_dtype, df[pd_name], pd_name not in primary_key)
107
+ pxt_name = __normalize_pxt_col_name(pd_name)
90
108
  # Ensure that column names are unique by appending a distinguishing suffix
91
109
  # to any collisions
92
110
  if pxt_name in schema:
@@ -95,10 +113,13 @@ def _df_to_pxt_schema(
95
113
  n += 1
96
114
  pxt_name = f'{pxt_name}_{n}'
97
115
  schema[pxt_name] = pxt_type
98
- return schema
116
+ col_mapping[pd_name] = pxt_name
117
+
118
+ pxt_pk = [col_mapping[pk] for pk in primary_key]
119
+ return schema, pxt_pk
99
120
 
100
121
 
101
- def _normalize_pxt_col_name(pd_name: str) -> str:
122
+ def __normalize_pxt_col_name(pd_name: str) -> str:
102
123
  """
103
124
  Normalizes an arbitrary DataFrame column name into a valid Pixeltable identifier by:
104
125
  - replacing any non-ascii or non-alphanumeric characters with an underscore _
@@ -113,26 +134,30 @@ def _normalize_pxt_col_name(pd_name: str) -> str:
113
134
  return id
114
135
 
115
136
 
116
- def _np_dtype_to_pxt_type(np_dtype: np.dtype, data_col: pd.Series) -> pxt.ColumnType:
137
+ def __np_dtype_to_pxt_type(np_dtype: np.dtype, data_col: pd.Series, nullable: bool) -> pxt.ColumnType:
117
138
  """
118
139
  Infers a Pixeltable type based on a Numpy dtype.
119
140
  """
120
141
  if np.issubdtype(np_dtype, np.integer):
121
- return pxt.IntType()
142
+ return pxt.IntType(nullable=nullable)
122
143
  if np.issubdtype(np_dtype, np.floating):
123
- return pxt.FloatType()
144
+ return pxt.FloatType(nullable=nullable)
124
145
  if np.issubdtype(np_dtype, np.bool_):
125
- return pxt.BoolType()
146
+ return pxt.BoolType(nullable=nullable)
126
147
  if np_dtype == np.object_ or np.issubdtype(np_dtype, np.character):
127
148
  has_nan = any(isinstance(val, float) and np.isnan(val) for val in data_col)
128
- return pxt.StringType(nullable=has_nan)
149
+ if has_nan and not nullable:
150
+ raise excs.Error(f'Primary key column `{data_col.name}` cannot contain null values.')
151
+ return pxt.StringType(nullable=nullable)
129
152
  if np.issubdtype(np_dtype, np.datetime64):
130
153
  has_nat = any(pd.isnull(val) for val in data_col)
131
- return pxt.TimestampType(nullable=has_nat)
154
+ if has_nat and not nullable:
155
+ raise excs.Error(f'Primary key column `{data_col.name}` cannot contain null values.')
156
+ return pxt.TimestampType(nullable=nullable)
132
157
  raise excs.Error(f'Unsupported dtype: {np_dtype}')
133
158
 
134
159
 
135
- def _df_row_to_pxt_row(row: tuple[Any, ...], schema: dict[str, pxt.ColumnType]) -> dict[str, Any]:
160
+ def __df_row_to_pxt_row(row: tuple[Any, ...], schema: dict[str, pxt.ColumnType]) -> dict[str, Any]:
136
161
  rows = {}
137
162
  for val, (col_name, pxt_type) in zip(row[1:], schema.items()):
138
163
  if pxt_type.is_float_type():
@@ -10,7 +10,7 @@ import sqlalchemy.orm as orm
10
10
  from .schema import SystemInfo, SystemInfoMd
11
11
 
12
12
  # current version of the metadata; this is incremented whenever the metadata schema changes
13
- VERSION = 18
13
+ VERSION = 19
14
14
 
15
15
 
16
16
  def create_system_info(engine: sql.engine.Engine) -> None:
@@ -0,0 +1,39 @@
1
+ from typing import Any, Optional
2
+ import sqlalchemy as sql
3
+
4
+ from pixeltable.metadata import register_converter
5
+ from pixeltable.metadata.converters.util import convert_table_md
6
+
7
+
8
+ @register_converter(version=18)
9
+ def _(engine: sql.engine.Engine) -> None:
10
+ convert_table_md(
11
+ engine,
12
+ substitution_fn=__substitute_md
13
+ )
14
+
15
+
16
+ def __substitute_md(k: Any, v: Any) -> Optional[tuple[Any, Any]]:
17
+ # Migrate a few changed function names
18
+ if k == 'path' and v == 'pixeltable.functions.string.str_format':
19
+ return 'path', 'pixeltable.functions.string.format'
20
+ if k == 'path' and v.startswith('pixeltable.functions.pil.image'):
21
+ return 'path', v.replace('pixeltable.functions.pil.image', 'pixeltable.functions.image')
22
+ # Migrate deprecated `ImageMemberAccess` expressions to `FunctionCall`s
23
+ if isinstance(v, dict) and '_classname' in v and v['_classname'] == 'ImageMemberAccess':
24
+ member_name = v['member_name']
25
+ new_v = {
26
+ 'fn': {
27
+ 'path': f'pixeltable.functions.image.{member_name}',
28
+ '_classpath': 'pixeltable.func.callable_function.CallableFunction',
29
+ },
30
+ 'args': [[0, None]],
31
+ 'kwargs': {},
32
+ '_classname': 'FunctionCall',
33
+ 'components': v['components'],
34
+ 'group_by_stop_idx': 0,
35
+ 'group_by_start_idx': 0,
36
+ 'order_by_start_idx': 1,
37
+ }
38
+ return k, new_v
39
+ return None
@@ -0,0 +1,10 @@
1
+ # Descriptive notes for each new metadata version. These are stored in a Python dict
2
+ # rather than as a comment, so that the existence of a description can be enforced by
3
+ # the unit tests when new versions are added.
4
+ VERSION_NOTES = {
5
+ 19: 'UDF renames; ImageMemberAccess removal',
6
+ 18: 'Restructured index metadata',
7
+ 17: 'Renamed remotes to external_stores',
8
+ 16: 'Query functions; deferred Expr deserialization',
9
+ 15: 'Remotes in table metadata',
10
+ }
pixeltable/plan.py CHANGED
@@ -107,7 +107,7 @@ class Analyzer:
107
107
  for e in self.group_by_clause:
108
108
  if e.sql_expr() is None:
109
109
  raise excs.Error(f'Invalid grouping expression, needs to be expressible in SQL: {e}')
110
- if e.contains(filter=lambda e: _is_agg_fn_call(e)):
110
+ if e._contains(filter=lambda e: _is_agg_fn_call(e)):
111
111
  raise excs.Error(f'Grouping expression contains aggregate function: {e}')
112
112
 
113
113
  # check that agg fn calls don't have contradicting ordering requirements
@@ -288,6 +288,81 @@ class Planner:
288
288
  recomputed_user_cols = [c for c in recomputed_cols if c.name is not None]
289
289
  return plan, [f'{c.tbl.name}.{c.name}' for c in updated_cols + recomputed_user_cols], recomputed_user_cols
290
290
 
291
+ @classmethod
292
+ def create_batch_update_plan(
293
+ cls, tbl: catalog.TableVersionPath,
294
+ batch: list[dict[catalog.Column, exprs.Expr]], rowids: list[tuple[int, ...]],
295
+ cascade: bool
296
+ ) -> Tuple[exec.ExecNode, exec.RowUpdateNode, sql.ClauseElement, List[catalog.Column], List[catalog.Column]]:
297
+ """
298
+ Returns:
299
+ - root node of the plan to produce the updated rows
300
+ - RowUpdateNode of plan
301
+ - Where clause for deleting the current versions of updated rows
302
+ - list of columns that are getting updated
303
+ - list of user-visible columns that are being recomputed
304
+ """
305
+ assert isinstance(tbl, catalog.TableVersionPath)
306
+ target = tbl.tbl_version # the one we need to update
307
+ sa_key_cols: list[sql.Column] = []
308
+ key_vals: list[tuple] = []
309
+ if len(rowids) > 0:
310
+ sa_key_cols = target.store_tbl.rowid_columns()
311
+ key_vals = rowids
312
+ else:
313
+ pk_cols = target.primary_key_columns()
314
+ sa_key_cols = [c.sa_col for c in pk_cols]
315
+ key_vals = [tuple(row[col].val for col in pk_cols) for row in batch]
316
+
317
+ # retrieve all stored cols and all target exprs
318
+ updated_cols = batch[0].keys() - target.primary_key_columns()
319
+ recomputed_cols = target.get_dependent_columns(updated_cols) if cascade else set()
320
+ # regardless of cascade, we need to update all indices on any updated column
321
+ idx_val_cols = target.get_idx_val_columns(updated_cols)
322
+ recomputed_cols.update(idx_val_cols)
323
+ # we only need to recompute stored columns (unstored ones are substituted away)
324
+ recomputed_cols = {c for c in recomputed_cols if c.is_stored}
325
+ recomputed_base_cols = {col for col in recomputed_cols if col.tbl == target}
326
+ copied_cols = [
327
+ col for col in target.cols if col.is_stored and not col in updated_cols and not col in recomputed_base_cols
328
+ ]
329
+ select_list = [exprs.ColumnRef(col) for col in copied_cols]
330
+ select_list.extend([exprs.ColumnRef(col) for col in updated_cols])
331
+
332
+ recomputed_exprs = \
333
+ [c.value_expr.copy().resolve_computed_cols(resolve_cols=recomputed_base_cols) for c in recomputed_base_cols]
334
+ # the RowUpdateNode updates columns in-place, ie, in the original ColumnRef; no further sustitution is needed
335
+ select_list.extend(recomputed_exprs)
336
+
337
+ # ExecNode tree (from bottom to top):
338
+ # - SqlLookupNode to retrieve the existing rows
339
+ # - RowUpdateNode to update the retrieved rows
340
+ # - ExprEvalNode to evaluate the remaining output exprs
341
+ analyzer = Analyzer(tbl, select_list)
342
+ row_builder = exprs.RowBuilder(analyzer.all_exprs, [], analyzer.sql_exprs)
343
+ analyzer.finalize(row_builder)
344
+ plan = exec.SqlLookupNode(tbl, row_builder, analyzer.sql_exprs, sa_key_cols, key_vals)
345
+ delete_where_clause = plan.where_clause
346
+ col_vals = [{col: row[col].val for col in updated_cols} for row in batch]
347
+ plan = row_update_node = exec.RowUpdateNode(tbl, key_vals, len(rowids) > 0, col_vals, row_builder, plan)
348
+ if not cls._is_contained_in(analyzer.select_list, analyzer.sql_exprs):
349
+ # we need an ExprEvalNode to evaluate the remaining output exprs
350
+ plan = exec.ExprEvalNode(row_builder, analyzer.select_list, analyzer.sql_exprs, input=plan)
351
+ # update row builder with column information
352
+ all_base_cols = copied_cols + list(updated_cols) + list(recomputed_base_cols) # same order as select_list
353
+ row_builder.substitute_exprs(select_list, remove_duplicates=False)
354
+ for i, col in enumerate(all_base_cols):
355
+ plan.row_builder.add_table_column(col, select_list[i].slot_idx)
356
+
357
+ ctx = exec.ExecContext(row_builder)
358
+ # we're returning everything to the user, so we might as well do it in a single batch
359
+ ctx.batch_size = 0
360
+ plan.set_ctx(ctx)
361
+ recomputed_user_cols = [c for c in recomputed_cols if c.name is not None]
362
+ return (
363
+ plan, row_update_node, delete_where_clause, list(updated_cols) + recomputed_user_cols, recomputed_user_cols
364
+ )
365
+
291
366
  @classmethod
292
367
  def create_view_update_plan(
293
368
  cls, view: catalog.TableVersionPath, recompute_targets: List[catalog.Column]
@@ -61,7 +61,7 @@ class Dumper:
61
61
  info_dict = {'pixeltable-dump': {
62
62
  'metadata-version': md_version,
63
63
  'git-sha': git_sha,
64
- 'datetime': datetime.datetime.utcnow(),
64
+ 'datetime': datetime.datetime.now(tz=datetime.timezone.utc),
65
65
  'user': user
66
66
  }}
67
67
  with open(info_file, 'w') as info:
@@ -179,7 +179,7 @@ class Dumper:
179
179
  def __add_expr_columns(self, t: pxt.Table, col_prefix: str, include_expensive_functions=False) -> None:
180
180
  def add_column(col_name: str, col_expr: Any) -> None:
181
181
  t.add_column(**{f'{col_prefix}_{col_name}': col_expr})
182
-
182
+
183
183
  # arithmetic_expr
184
184
  add_column('plus', t.c2 + 6)
185
185
  add_column('minus', t.c2 - 5)
@@ -242,8 +242,7 @@ class Dumper:
242
242
  add_column('str_const', 'str')
243
243
  add_column('int_const', 5)
244
244
  add_column('float_const', 5.0)
245
- add_column('timestamp_const_1', datetime.datetime.utcnow())
246
- add_column('timestamp_const_2', datetime.date.today())
245
+ add_column('timestamp_const_1', datetime.datetime.now(tz=datetime.timezone.utc))
247
246
 
248
247
  # type_cast
249
248
  add_column('astype', t.c2.astype(FloatType()))
@@ -1,5 +1,6 @@
1
1
  import ast
2
2
  from typing import Optional, Union
3
+ import warnings
3
4
 
4
5
  import griffe
5
6
  import griffe.expressions
@@ -34,6 +35,7 @@ class PxtGriffeExtension(Extension):
34
35
  """
35
36
  func.extra['mkdocstrings']['template'] = 'udf.html.jinja'
36
37
  # Dynamically load the UDF reference so we can inspect the Pixeltable signature directly
38
+ warnings.simplefilter("ignore")
37
39
  udf = griffe.dynamic_import(func.path)
38
40
  assert isinstance(udf, pxt.Function)
39
41
  # Convert the return type to a Pixeltable type reference
@@ -60,6 +62,8 @@ class PxtGriffeExtension(Extension):
60
62
  base = 'float'
61
63
  elif column_type.is_bool_type():
62
64
  base = 'bool'
65
+ elif column_type.is_timestamp_type():
66
+ base = 'datetime'
63
67
  elif column_type.is_array_type():
64
68
  base = 'ArrayT'
65
69
  elif column_type.is_json_type():
pixeltable/type_system.py CHANGED
@@ -183,7 +183,7 @@ class ColumnType:
183
183
  """Two types match if they're equal, aside from nullability"""
184
184
  if not isinstance(other, ColumnType):
185
185
  pass
186
- assert isinstance(other, ColumnType)
186
+ assert isinstance(other, ColumnType), type(other)
187
187
  if type(self) != type(other):
188
188
  return False
189
189
  for member_var in vars(self).keys():
@@ -206,7 +206,7 @@ class ColumnType:
206
206
  if type1.is_scalar_type() and type2.is_scalar_type():
207
207
  t = cls.Type.supertype(type1._type, type2._type, cls.common_supertypes)
208
208
  if t is not None:
209
- return cls.make_type(t)
209
+ return cls.make_type(t).copy(nullable=(type1.nullable or type2.nullable))
210
210
  return None
211
211
 
212
212
  if type1._type == type2._type:
@@ -227,22 +227,23 @@ class ColumnType:
227
227
  def infer_literal_type(cls, val: Any) -> Optional[ColumnType]:
228
228
  if isinstance(val, str):
229
229
  return StringType()
230
+ if isinstance(val, bool):
231
+ # We have to check bool before int, because isinstance(b, int) is True if b is a Python bool
232
+ return BoolType()
230
233
  if isinstance(val, int):
231
234
  return IntType()
232
235
  if isinstance(val, float):
233
236
  return FloatType()
234
- if isinstance(val, bool):
235
- return BoolType()
236
- if isinstance(val, datetime.datetime) or isinstance(val, datetime.date):
237
+ if isinstance(val, datetime.datetime):
237
238
  return TimestampType()
238
239
  if isinstance(val, PIL.Image.Image):
239
- return ImageType(width=val.width, height=val.height)
240
+ return ImageType(width=val.width, height=val.height, mode=val.mode)
240
241
  if isinstance(val, np.ndarray):
241
242
  col_type = ArrayType.from_literal(val)
242
243
  if col_type is not None:
243
244
  return col_type
244
245
  # this could still be json-serializable
245
- if isinstance(val, dict) or isinstance(val, np.ndarray):
246
+ if isinstance(val, dict) or isinstance(val, list) or isinstance(val, np.ndarray):
246
247
  try:
247
248
  JsonType().validate_literal(val)
248
249
  return JsonType()
@@ -276,7 +277,7 @@ class ColumnType:
276
277
  return FloatType()
277
278
  if base is bool:
278
279
  return BoolType()
279
- if base is datetime.date or base is datetime.datetime:
280
+ if base is datetime.datetime:
280
281
  return TimestampType()
281
282
  if issubclass(base, Sequence) or issubclass(base, Mapping):
282
283
  return JsonType()
@@ -425,7 +426,7 @@ class StringType(ColumnType):
425
426
  def conversion_fn(self, target: ColumnType) -> Optional[Callable[[Any], Any]]:
426
427
  if not target.is_timestamp_type():
427
428
  return None
428
- def convert(val: str) -> Optional[datetime]:
429
+ def convert(val: str) -> Optional[datetime.datetime]:
429
430
  try:
430
431
  dt = datetime.datetime.fromisoformat(val)
431
432
  return dt
@@ -506,8 +507,8 @@ class TimestampType(ColumnType):
506
507
  return sql.TIMESTAMP()
507
508
 
508
509
  def _validate_literal(self, val: Any) -> None:
509
- if not isinstance(val, datetime.datetime) and not isinstance(val, datetime.date):
510
- raise TypeError(f'Expected datetime.datetime or datetime.date, got {val.__class__.__name__}')
510
+ if not isinstance(val, datetime.datetime):
511
+ raise TypeError(f'Expected datetime.datetime, got {val.__class__.__name__}')
511
512
 
512
513
  def _create_literal(self, val: Any) -> Any:
513
514
  if isinstance(val, str):
@@ -577,7 +578,7 @@ class ArrayType(ColumnType):
577
578
  if base_type is None:
578
579
  return None
579
580
  shape = [n1 if n1 == n2 else None for n1, n2 in zip(type1.shape, type2.shape)]
580
- return ArrayType(tuple(shape), base_type)
581
+ return ArrayType(tuple(shape), base_type, nullable=(type1.nullable or type2.nullable))
581
582
 
582
583
  def _as_dict(self) -> Dict:
583
584
  result = super()._as_dict()
@@ -609,7 +610,7 @@ class ArrayType(ColumnType):
609
610
  dtype = StringType()
610
611
  else:
611
612
  return None
612
- return cls(val.shape, dtype=dtype, nullable=True)
613
+ return cls(val.shape, dtype=dtype)
613
614
 
614
615
  def is_valid_literal(self, val: np.ndarray) -> bool:
615
616
  if not isinstance(val, np.ndarray):
@@ -695,7 +696,7 @@ class ImageType(ColumnType):
695
696
  return f'{self._type.name.lower()}{params_str}'
696
697
 
697
698
  def _is_supertype_of(self, other: ImageType) -> bool:
698
- if self.mode != other.mode:
699
+ if self.mode is not None and self.mode != other.mode:
699
700
  return False
700
701
  if self.width is None and self.height is None:
701
702
  return True
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pixeltable
3
- Version: 0.2.13
3
+ Version: 0.2.14
4
4
  Summary: Pixeltable: The Multimodal AI Data Plane
5
5
  Author: Pixeltable, Inc.
6
6
  Author-email: contact@pixeltable.com
@@ -1,23 +1,23 @@
1
- pixeltable/__init__.py,sha256=SkhQ6olglhj3NdcyVYzsTwpTZs8uVmtJa9INfsQV9gk,1267
2
- pixeltable/__version__.py,sha256=dloDN3rTmGtjqAgx8iRqSPKXEoW7iCNCWm0C23Ryib4,114
1
+ pixeltable/__init__.py,sha256=ISVoeqNCvSJonD0EXJ32Mer84m29YQDyLhhUydyCV_o,1272
2
+ pixeltable/__version__.py,sha256=RQ6OoDf4FBJnM8s1hEJoZvxUBFqSNnCbCQV7vdybuQg,114
3
3
  pixeltable/catalog/__init__.py,sha256=E41bxaPeQIcgRYzTWc2vkDOboQhRymrJf4IcHQO7o_8,453
4
4
  pixeltable/catalog/catalog.py,sha256=8gsFWm6o9Qg4_BEO6oejdpmP4MAOlhmuKRaJP0o2UPU,7906
5
- pixeltable/catalog/column.py,sha256=Dmc6CgFLExJy3tdvuX0Emjc8SgqZvmCbAHozibO1-G0,9417
5
+ pixeltable/catalog/column.py,sha256=Uw1SnG64YO-slDF8_m6by7hSq-5HGC0lAKLRqzZJkhU,9551
6
6
  pixeltable/catalog/dir.py,sha256=DWl9nnCOoiYLKWp31MNMvLmryXeQiQZu5YJcd4tpy38,921
7
- pixeltable/catalog/globals.py,sha256=tNb_6jzAKJWD4MH1Y9g2UhVQkiomYfbHQZ2GIcg7vUI,974
7
+ pixeltable/catalog/globals.py,sha256=RFHl6XrgXzi_fon7O1RhnQ9SM_tkPexDhwrshMRpnmQ,1384
8
8
  pixeltable/catalog/insertable_table.py,sha256=qYNuestCC-oR8bEoO1K7WMRWtCTB6RwF3X2LeK3kWG4,5878
9
9
  pixeltable/catalog/named_function.py,sha256=UhHaimM_uJHS-0RQcqGOgvWeZtMfKsIgSeKSRwT2moU,1149
10
10
  pixeltable/catalog/path.py,sha256=QgccEi_QOfaKt8YsR2zLtd_z7z7QQkU_1kprJFi2SPQ,1677
11
11
  pixeltable/catalog/path_dict.py,sha256=xfvxg1Ze5jZCARUGASF2DRbQPh7pRVTYhuJ_u82gYUo,5941
12
12
  pixeltable/catalog/schema_object.py,sha256=1GuxN68P3c7g0gmY8doB6qoUGJsalyECWaO-KEi96D0,1879
13
- pixeltable/catalog/table.py,sha256=Ul6lZ29uj6KDDLx6KkCBB8e_hpN0FhygU0IqWcTaRuA,41136
14
- pixeltable/catalog/table_version.py,sha256=ukMVumBdlMvA2gktsyjhXyLm2qhObTSi1pXoiOkUN_I,57040
13
+ pixeltable/catalog/table.py,sha256=tV2BWr74NqlvSDEtD4zEpdFCnvq-9fanPnrH39AnL3w,42013
14
+ pixeltable/catalog/table_version.py,sha256=gZq7__PHf7-8QXTehv7tMJ4smrizBRBVixo6JK-FKkQ,55887
15
15
  pixeltable/catalog/table_version_path.py,sha256=6JZlgKMYa3Xf8p_2Z-iDIFIcfuYRyjbpc3_CC9l1HME,6396
16
- pixeltable/catalog/view.py,sha256=ImMpJn_SZF2a7t54BdZjo1Y09fE8CN9FJUhGpTBhCQI,10393
16
+ pixeltable/catalog/view.py,sha256=ISRela9z5NcrUEvqe5H360xIXs3sY622cCQGe_2bxdY,10397
17
17
  pixeltable/dataframe.py,sha256=T8Vi17wy8KT3squF_CsrCf8LYPEof7kH5dBKrVCW5n4,34497
18
18
  pixeltable/env.py,sha256=WO_WLfRj9Fft6QyW89S9cw47RTg1ALviStu9pNygJEQ,21635
19
19
  pixeltable/exceptions.py,sha256=MSP9zeL0AmXT93XqjdvgGN4rzno1_KRrGriq6hpemnw,376
20
- pixeltable/exec/__init__.py,sha256=RK7SKvrQ7Ky3G_LXDP4Bf7lHmMM_uYZl8dJaZYs0FjY,454
20
+ pixeltable/exec/__init__.py,sha256=ZU88pHrIT4ob4OQE-2HlYcM4MP_dY4k67KdQGHnGC-M,507
21
21
  pixeltable/exec/aggregation_node.py,sha256=cf6rVAgrGh_uaMrCIgXJIwQTmbcboJlnrH_MmPIQSd0,3321
22
22
  pixeltable/exec/cache_prefetch_node.py,sha256=d5pEuR6AtJQkEVy9X3XeYFI_q0szMtoNAH96vYdtBE0,5241
23
23
  pixeltable/exec/component_iteration_node.py,sha256=Uz6zEeaJMcbvF3S0W0qmLI_uWsZsaSspHKNzuAMrasg,4069
@@ -27,8 +27,9 @@ pixeltable/exec/exec_node.py,sha256=ixkv3p_EfF53UDWgwLjQGKR1LNIQxzgDXsTzzJj6ea4,
27
27
  pixeltable/exec/expr_eval_node.py,sha256=eLyUwxA6HE9gHOE_oBT5nfVgd4oK2TQ6gaOM5RnCA8Q,11465
28
28
  pixeltable/exec/in_memory_data_node.py,sha256=vvjr5-r94mRddOYIpKF8zDWCJPJrG0YpQVtYSyKlyVU,3502
29
29
  pixeltable/exec/media_validation_node.py,sha256=OKfRyKpcn7AZdACy_HD4NsDC87ZfNFs1tdrQz2NiIVw,1514
30
- pixeltable/exec/sql_scan_node.py,sha256=xyf82fnwdCH5PwJUns7BlkHAzSeWDx9ew6OSKfe-bCg,10290
31
- pixeltable/exprs/__init__.py,sha256=jmJZJYojZoXqU1GU3nFMPoJsabV5PFhEhs7GAldYXbE,918
30
+ pixeltable/exec/row_update_node.py,sha256=b8yuKtkmI2Q6U-7svKbkjdM3Z85ddZoJgJgUa17j-YE,2773
31
+ pixeltable/exec/sql_node.py,sha256=N-KpAPiLn8TuF2t_07vms3R9_l6k0wqwSWkGIbikV4A,12921
32
+ pixeltable/exprs/__init__.py,sha256=zNlFbBiCI8PAzwBGR1tjyhbGpNXcPr07U2G66Fp7LS0,901
32
33
  pixeltable/exprs/arithmetic_expr.py,sha256=sWBYCBKI6IHj9ASwDcm2BlkQ5gleVtKtmpiPvzFNBJM,4386
33
34
  pixeltable/exprs/array_slice.py,sha256=VmWc6iFusrM85MjyEBBCfXG1Jnt8-Gr6-J88BXxNoOE,2131
34
35
  pixeltable/exprs/column_property_ref.py,sha256=0PHiBys0fxe2LgjaMId5UHob4E-ZggyPLnnW41RgA0E,2706
@@ -36,67 +37,69 @@ pixeltable/exprs/column_ref.py,sha256=rlw6Ic_atAfPZpEBNAqbRZauMeEUci2rDyVoHd1pA1
36
37
  pixeltable/exprs/comparison.py,sha256=bWa_KZTir_5teKGEXf6cNzJWk55S9-XPPFdY8zoPn6U,4793
37
38
  pixeltable/exprs/compound_predicate.py,sha256=y80Kc3LmifYP4Zqa8Etujb4jnItro2D6cS10WYQIGiI,3758
38
39
  pixeltable/exprs/data_row.py,sha256=RTBw1cBt29g_9g_hgdEYZ5aiHl7WZMBaBC2fOMOfwOc,8668
39
- pixeltable/exprs/expr.py,sha256=3zVh6XaXpppY_i-dy3vq5wmB9rFdnvIiykJrow-fGms,26335
40
+ pixeltable/exprs/expr.py,sha256=-VKrOW_B-QqL-ZMcIDMJoU4p4vcwtaRn8Q2-JNBioro,27003
40
41
  pixeltable/exprs/expr_set.py,sha256=Q64Q2yI0CTq2Ma_E-BUYlMotSstVuMm4OFZnBCedHRk,1222
41
- pixeltable/exprs/function_call.py,sha256=UKqErJyPUa6-Q-SqkVsK_tT4ti--z_YvQEmj1jHGc8w,17149
42
- pixeltable/exprs/globals.py,sha256=KhK4xwkLHv4NsXXcLdjRu2OFSvEnlC7GG-8Gs_IbQtI,1858
43
- pixeltable/exprs/image_member_access.py,sha256=KSYdTIaLh53dNRjv3SJFchPMPo7o5diJSQkV1NsyB4Y,3547
42
+ pixeltable/exprs/function_call.py,sha256=l0_-EJ9bFlrDh56cZqqAdQAmCiVmn78y9bWcXJ2_1qE,18139
43
+ pixeltable/exprs/globals.py,sha256=SUZdoYEqUSAn8UeY1qJREOmL5OilUtMLvb6iOJQ8rUM,1910
44
44
  pixeltable/exprs/in_predicate.py,sha256=ASxkSLeGdOjGN4QgWQA0zF1SkKOmHU_IV0spNpjvTGQ,3707
45
- pixeltable/exprs/inline_array.py,sha256=293WuUEhYXrcp8-AnPDVIWQBPQMrPviB88A619Ls_Es,4499
45
+ pixeltable/exprs/inline_array.py,sha256=AaRnN53-4krYkJ5vQ0i2hpnR-Vqp4N7xwHeTE_4M7lQ,4860
46
46
  pixeltable/exprs/inline_dict.py,sha256=TWYokJ14Nq-evODcYFVO471WSEDbz6cJqIdRb2PkbZQ,3885
47
47
  pixeltable/exprs/is_null.py,sha256=K5EQCgpgLk-VfqO58b2T98qR9uui5ryhmskU2Ap8lWg,1016
48
48
  pixeltable/exprs/json_mapper.py,sha256=I60VNgus64ai80gnFCIsRn0VRWYXMkqH5VNvnATsN9s,4559
49
49
  pixeltable/exprs/json_path.py,sha256=Wz_5zFsyc9TPhsSbsDjDmQ3Nb0uVIwMCx5nh-cQYBiE,6526
50
50
  pixeltable/exprs/literal.py,sha256=5NNza-WL1dd3hNznwwkr_yAcTGXSIRYUszGfy30lruI,2396
51
+ pixeltable/exprs/method_ref.py,sha256=GE2RaNlAEI_RHJBXeT7QhLG84V3P_k5DSzq5npNAgf0,2588
51
52
  pixeltable/exprs/object_ref.py,sha256=eTcx84aWRI59fIiGvbdv3_cfL0XW4xEFQ4lwpLpJkM8,1250
52
53
  pixeltable/exprs/row_builder.py,sha256=0OYd51J2ECPHkk2iN3MfYpS7LqnHTV5l5ubsVcy0dJA,15926
53
54
  pixeltable/exprs/rowid_ref.py,sha256=74w4rEy21YysTVbyKNc3op-pYFqDAx8VJdtl7ZPpxHs,4268
54
55
  pixeltable/exprs/similarity_expr.py,sha256=DqLOWtwPn9LxBRPm-d5Qz0yZ7w9YTOP8w0rgbr-6Lyg,3702
55
56
  pixeltable/exprs/type_cast.py,sha256=JMg8p1qYoFfiAXfJPSbTEnfrK7lRO_JMaqlPHOrhNQU,1793
56
57
  pixeltable/exprs/variable.py,sha256=Kg_O4ytcHYZFijIyMHYBJn063cTKU1-YE583FAz8Qaw,1361
57
- pixeltable/ext/__init__.py,sha256=0uugfuME1FybVo-MdxaVNGagRjhcvNTnv5MZUem6Cyo,269
58
- pixeltable/ext/functions/whisperx.py,sha256=CnpSPZJgufXa01vgUubVkyxQuZIdublJzkwbm5kS1YQ,1078
59
- pixeltable/ext/functions/yolox.py,sha256=8e-S9SD0xpwkMlSHnpm6aZc7lToHZnEnbZvM_M1alwU,3688
58
+ pixeltable/ext/__init__.py,sha256=iO0J_Jfnv38F5y40sDAW54gpXjIyZgOGgoWQJAwjQec,423
59
+ pixeltable/ext/functions/__init__.py,sha256=hIjPEKC5E5uJOXlQqUyhP9yn9ZqWOCJAlj0kXWDlhlE,159
60
+ pixeltable/ext/functions/whisperx.py,sha256=wDi0XwAi1PeiB7NoA_4t9JwbwWjjbHBSgd5hH0HD0aM,2176
61
+ pixeltable/ext/functions/yolox.py,sha256=qxW-WosgFkpC8EWQUn7CPgW58z_Vc4idfbDIpZ6FpDA,5093
60
62
  pixeltable/func/__init__.py,sha256=WjftUGyNkd6bF_qSxqZ5Gd7Elf8oExb3dUlpydhdFTo,407
61
63
  pixeltable/func/aggregate_function.py,sha256=pyF479nBrN2mZ8mAnsbmt2T8KxsDAVNgpUXiqHM2Nt8,9486
62
- pixeltable/func/callable_function.py,sha256=YGmClf6XX90eFuGFHDo0rbeGQZlFtwa0BJrfIg5c9yk,4714
63
- pixeltable/func/expr_template_function.py,sha256=_5xkhODJRiObOAPErvVhlpLaBpXTcjhovibCeB_1AB0,4058
64
- pixeltable/func/function.py,sha256=cVmu3scwveMc2hgcvhAkAEuqvahL1sKD-txz4bs21pc,5539
65
- pixeltable/func/function_registry.py,sha256=atg8JoxXdLPbxJsQYEyGuzwCzN5rSeRSh-5aMgu7G4g,11567
64
+ pixeltable/func/callable_function.py,sha256=vmAs9FIvyV7loUKc-2NAA9MUKVXS6hEZWQ9RHcdcqwQ,4913
65
+ pixeltable/func/expr_template_function.py,sha256=0krKY-0i-aTZdgAS8wZkq4NQc-EVtAA7-a0zh2vHmTI,4059
66
+ pixeltable/func/function.py,sha256=Q8q6qf3LUtBnGRQTxJLuDgQU3QHoyR2GsFyS1Tnn6RA,5955
67
+ pixeltable/func/function_registry.py,sha256=VvYJjS6OZaS15JdhTNM0aDU26b9NjFndc8E25YtTHLI,12406
66
68
  pixeltable/func/globals.py,sha256=sEwn6lGgHMp6VQORb_P5qRd_-Q2_bUSqvqM9-XPN_ec,1483
67
69
  pixeltable/func/query_template_function.py,sha256=BUU0KZYkqVPjIFg6g6msU4PzVGf2fkEKveDaEMGXhzI,3680
68
70
  pixeltable/func/signature.py,sha256=6Lwf32auSnmhYGrN4NkHk07BmG2a73TNICbWnelkH1s,8638
69
- pixeltable/func/udf.py,sha256=TtFgA9gXUGasd3yj22S6NAsanPJhmmZI_ewbcrTB_VY,6798
70
- pixeltable/functions/__init__.py,sha256=mC_0y7aLAqamgOj94S5e9yQ4HbnqPiXy-1_t2s6SPqY,290
71
+ pixeltable/func/udf.py,sha256=xrfCuYFF7Qqx-I_vE11WT9AoY6UbbzIIZ2DBGzYGzDE,7772
72
+ pixeltable/functions/__init__.py,sha256=QT6fbgIIrA_Q-lFIne9tq0phPz7vHBstzMq9NjERaZM,301
71
73
  pixeltable/functions/eval.py,sha256=FMn95e0GG-ge7ss6dkDOV-7KQK9mSPvn-UyFB2rgBFI,8492
72
- pixeltable/functions/fireworks.py,sha256=sbZy3HRn8o01nT4k1lOJJ_jGrjhBNkYmj1_TraoYCiM,1090
74
+ pixeltable/functions/fireworks.py,sha256=69EoYE8aS9s9SV6iTJGeUb7mNEHdodHh96JsOa2KL7Y,2575
73
75
  pixeltable/functions/globals.py,sha256=9yz5XzhGhh4kuvHJ8eiFvy9SCPYaZrF5ltwscMH9xEg,2692
74
- pixeltable/functions/huggingface.py,sha256=qjDjH9TP8VGOn_Ly7TOtKSE0pEYsJgKiiSYGOUIKktM,9603
75
- pixeltable/functions/image.py,sha256=2dlwSDEDSax1nfQ-X6GJo3eo8k4q9wosT3ZOaEsJJeA,5858
76
- pixeltable/functions/openai.py,sha256=D0cDXe_zy1kUdKqM9T3qs7OBAUCrAINUy5P0DO0OSXc,7814
77
- pixeltable/functions/string.py,sha256=fFRFqB7Vv-Fm2P9vNU-zpVDbRbFAEl91tZiI20xlMwE,19553
78
- pixeltable/functions/together.py,sha256=2vHOoXMUIpeYwTYGTr3hDHePzy8zepvoeyORgV_9n34,4412
76
+ pixeltable/functions/huggingface.py,sha256=__SbMaYVLBd81gQXstNXPp6wxXPbNvrTgu8gi_RCnZI,12750
77
+ pixeltable/functions/image.py,sha256=mG1AKn1rwmY3eQdKgzuJRn0Vdxq84xHqla-P5dDe0dY,13306
78
+ pixeltable/functions/openai.py,sha256=4FyL60mQUPcqb19DkFMBbBHf6utV3xsOs6SPWZrfXp8,15981
79
+ pixeltable/functions/string.py,sha256=JEng3jwYZUSYSfjWjto7tLxlIvQLW1JvQ7OmncIgd5M,20085
80
+ pixeltable/functions/timestamp.py,sha256=pfP28wErdjWOMLgJaxqXPMMScf4_LGUFja7oYb_cNBg,6620
81
+ pixeltable/functions/together.py,sha256=Gvy7ontUQmTx1n-eFvGaDEfl48v95eClNy0FmoT3Ivw,8587
79
82
  pixeltable/functions/util.py,sha256=F2iiIL7UfhYdCVzdCa3efYqWbaeLKFrbycKnuPkG57M,650
80
- pixeltable/functions/video.py,sha256=YDys3gB0C-0JZlxshVlLl2w8LPkRC9LTaRSRKkxjmcc,7045
81
- pixeltable/functions/whisper.py,sha256=s7C4eV5tCJed-4Joob5LojGFEHPgapmT8awFPVxBKgQ,2199
83
+ pixeltable/functions/video.py,sha256=qojNjimWK5jIO8fm_3WtQtAy8v-5qGDTl3Zx--St_fw,7077
84
+ pixeltable/functions/whisper.py,sha256=8oS2HjpewwAxt7RmLMXNqPl76_7Aq9c-qyAe-zJbu1U,3234
82
85
  pixeltable/globals.py,sha256=RNlJDTf6w350YaCco5JXYxYY2j1rcSzgBNazmIHB48c,14823
83
86
  pixeltable/index/__init__.py,sha256=XBwetNQQwnz0fiKwonOKhyy_U32l_cjt77kNvEIdjWs,102
84
87
  pixeltable/index/base.py,sha256=YAQ5Dz1mfI0dfu9rxWHWroE8TjB90yKfPtXAzoADq38,1568
85
88
  pixeltable/index/btree.py,sha256=NE4GYhcJWYJhdKyeHI0sQBlFvUaIgGOF9KLyCZOfFjE,1822
86
89
  pixeltable/index/embedding_index.py,sha256=U1wAjcTYvw3uJf3QHIOzBV8FLOUn8IeaFsLzUb_QTmc,7829
87
- pixeltable/io/__init__.py,sha256=DdqOteR1Y-yRvFS0VojXHryBtIGzH8nAN-1MBj3LGRk,493
90
+ pixeltable/io/__init__.py,sha256=bJGWPhKfgoMrSKFdXhLGupjQQbIXt7JaoUPwilND2PE,519
88
91
  pixeltable/io/external_store.py,sha256=owha7bEmA1ZvpZvBLBS6LHi9uLq1rUIkrMTGarsbjOU,16422
89
- pixeltable/io/globals.py,sha256=47ZejGdm_tIBVKg-vk6eSOwvmoeDEkBF7eesCRa_MSk,7065
92
+ pixeltable/io/globals.py,sha256=F4L7Ft2tctH0PS7p3C3DuU_l6TmN-hhE9KUPk4AjlmQ,13267
90
93
  pixeltable/io/hf_datasets.py,sha256=h5M1NkXOvEU8kaeT3AON1A18Vmhnc1lVo5a3TZ5AAic,8004
91
94
  pixeltable/io/label_studio.py,sha256=ipcgyFkKurP9IsBScLVK7UVddWJWXQ8M1p_3bh9Z60s,31018
92
- pixeltable/io/pandas.py,sha256=wRlWSsfvkiDePK3TjjrMHZFPMmlcAfrZ8JiAxsrOWQ0,7097
95
+ pixeltable/io/pandas.py,sha256=XC3ZKTameWyD6h5bV0szhjOVgiBENbpWUyGweQ3GmEQ,8153
93
96
  pixeltable/io/parquet.py,sha256=i4hvYHsARe2GnZHxNmI66Vf3tr1sIFLN6KGCJYvH3o8,8149
94
97
  pixeltable/iterators/__init__.py,sha256=sjldFckkT8aVRiKgEP6faeAK2NQBdzbmpwAeRhI1FkM,366
95
98
  pixeltable/iterators/base.py,sha256=cnEh1tNN2JAxRzrLTg3dhun3N1oNQ8vifCm6ts3_UiE,1687
96
99
  pixeltable/iterators/document.py,sha256=netSCJatG8NcgbHZ69BvQVICdAorQlYi8OlcpqwLQD4,19436
97
100
  pixeltable/iterators/string.py,sha256=NG_fWc_GAITDfzl6MvrDOMrSoMcZdMZf6hPQztCSatE,1305
98
101
  pixeltable/iterators/video.py,sha256=xtxODL1AfZwTfHVzWekhTCLA8gwTJIvJFdxC0KecD9Q,3836
99
- pixeltable/metadata/__init__.py,sha256=R4K9KSnefmvSCxXbBKTLAHD3QuHXgQ3a0wTs-eg94Os,2172
102
+ pixeltable/metadata/__init__.py,sha256=niAW1Ac-lwaqbQ3svAwoiqbcWhfJEbgHjsj3s1ZyK2E,2172
100
103
  pixeltable/metadata/converters/convert_10.py,sha256=J1_r7LNNAWTdb042AwqFpJ4sEB-i4qhUdk5iOjcZk34,719
101
104
  pixeltable/metadata/converters/convert_12.py,sha256=Ci-qyZW1gqci-8wnjeOB5afdq7KTuN-hVSV9OqSPx8g,162
102
105
  pixeltable/metadata/converters/convert_13.py,sha256=yFR6lD3pOrZ46ZQBFKYvxiIYa7rRxh46Bsq7yiCBNak,1356
@@ -104,17 +107,19 @@ pixeltable/metadata/converters/convert_14.py,sha256=o4Dwu5wujJYILN-2chg3xCSUsh4c
104
107
  pixeltable/metadata/converters/convert_15.py,sha256=N-Lt3OdOrUprN-z1gFcxniZgAtZ7jzup_YUZzXX6EtY,1709
105
108
  pixeltable/metadata/converters/convert_16.py,sha256=SvcWOYgLwRw_gLTnLbCSI9f2cpdkXazYOmmtJUOOzv4,476
106
109
  pixeltable/metadata/converters/convert_17.py,sha256=vJg4y2lg53WSj9OSntWsdUiCr6yRgMQm0eFbs_Geqjg,861
110
+ pixeltable/metadata/converters/convert_18.py,sha256=tejUM88AVZmPsg4l2OWqEEPmpSzXpb6ZFxFTdYZ8-7E,1462
107
111
  pixeltable/metadata/converters/util.py,sha256=AcYs3yUICl93y8whf0pkeWZoCzE4JuUMafmcYMyJUCY,2618
112
+ pixeltable/metadata/notes.py,sha256=NLZdM_iXONU0BeNwz5wK6I4UioMG71Sakfu9k15F6jc,467
108
113
  pixeltable/metadata/schema.py,sha256=WJZ1YPgS88rFElXbjYgDhcrI4VReR1I9VPOnTkoHvoI,8418
109
- pixeltable/plan.py,sha256=Eq77DtzWDgMEfEuw4w_MWAkbk9uE9P3yVtgLuSuyVJ0,32801
114
+ pixeltable/plan.py,sha256=7CyRIkwXtAgwIjrco0p0Hrya0va0r6Q2LHmq-iIsK50,37010
110
115
  pixeltable/store.py,sha256=UDn-UMYuL6dTUym3yFsVhv9hUtnP_QtzhDJzsFInApc,18853
111
- pixeltable/tool/create_test_db_dump.py,sha256=VAU1pTZwSG3HM9LS2i8dKvwVfa-JZq7ZV06CaGQkxDg,10725
116
+ pixeltable/tool/create_test_db_dump.py,sha256=R5dY2OPvVtVhRWDxboIUjbzM6qjr2L1EcdiQDmegY4Q,10696
112
117
  pixeltable/tool/create_test_video.py,sha256=OLfccymYReIpzE8osZn4rQvLXxxiPC_l0vc06U74hVM,2899
113
- pixeltable/tool/doc_plugins/griffe.py,sha256=K0HC6slt-FPmYgJ42po07dMqx6FGzs6zMeSMUyDbUUI,3290
118
+ pixeltable/tool/doc_plugins/griffe.py,sha256=Q6ARBlQNBm8J21G_p625TB5c8MQ8r6hJlm7I2LoBon0,3422
114
119
  pixeltable/tool/doc_plugins/mkdocstrings.py,sha256=afq7XOaSC5WRmugkh-FMFMK8PqOgIlDIsJdD8cuPhtE,207
115
120
  pixeltable/tool/doc_plugins/templates/material/udf.html.jinja,sha256=R-7Q57nmDd5BUea-F1-MjwjK3pq7uBHXNoSo8_QjZG4,4890
116
121
  pixeltable/tool/embed_udf.py,sha256=llHUhjGnCMp7Wyz7eHgKZV2v6o2ZWSgLQKscESuHK_o,269
117
- pixeltable/type_system.py,sha256=oXnDVoP90ic6WSTF_DcgWDLx0MYKEU0ggGTesAKahic,29505
122
+ pixeltable/type_system.py,sha256=6qa0LBBKuS61sYBIfJGBKkrw3O_to8UQkDUDlegmb5s,29663
118
123
  pixeltable/utils/__init__.py,sha256=UYlrf6TIWJT0g-Hac0b34-dEk478B5Qx8dGco34YlIk,439
119
124
  pixeltable/utils/arrow.py,sha256=83_7aG5UR2qtTktw_otLkQs-RQbLk0VVM0JLJkbweNU,3692
120
125
  pixeltable/utils/coco.py,sha256=ISpFBhR4eO1jOcg_SPb0thVI4KdS6H0RyNQauZIA5A4,7287
@@ -129,8 +134,8 @@ pixeltable/utils/pytorch.py,sha256=BR4tgfUWw-2rwWTOgzXj5qdMBpe1Arpp5SK4ax6jjpk,3
129
134
  pixeltable/utils/s3.py,sha256=DBfXp0SYubhiKckdAD7PsiVBX_YfVP8Rcu6DCG_3SaQ,433
130
135
  pixeltable/utils/sql.py,sha256=5n5_OmXAGtqFdL6z5XvgnU-vlx6Ba6f1WJrO1ZwUle8,765
131
136
  pixeltable/utils/transactional_directory.py,sha256=UGzCrGtLR3hEEf8sYGuWBzLVFAEQml3vdIavigWeTBM,1349
132
- pixeltable-0.2.13.dist-info/LICENSE,sha256=0UNMmwuqWPC0xDY1NWMm4uNJ2_MyA1pnTNRgQTvuBiQ,746
133
- pixeltable-0.2.13.dist-info/METADATA,sha256=Ht5bkHn7MOBEVy-9nb7en-JijNrCNAeulHU4991XZvc,11242
134
- pixeltable-0.2.13.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
135
- pixeltable-0.2.13.dist-info/entry_points.txt,sha256=TNI1Gb5vPwFrTdw6TimSYjO8FeK8c_HuPr28vcf7o_I,108
136
- pixeltable-0.2.13.dist-info/RECORD,,
137
+ pixeltable-0.2.14.dist-info/LICENSE,sha256=0UNMmwuqWPC0xDY1NWMm4uNJ2_MyA1pnTNRgQTvuBiQ,746
138
+ pixeltable-0.2.14.dist-info/METADATA,sha256=pAH2nPgSnxv-hT0TmO0WX3GaZqNVNQNlk8-gHRTbAak,11242
139
+ pixeltable-0.2.14.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
140
+ pixeltable-0.2.14.dist-info/entry_points.txt,sha256=TNI1Gb5vPwFrTdw6TimSYjO8FeK8c_HuPr28vcf7o_I,108
141
+ pixeltable-0.2.14.dist-info/RECORD,,