pixeltable 0.3.2__py3-none-any.whl → 0.3.4__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 (150) hide show
  1. pixeltable/__init__.py +64 -11
  2. pixeltable/__version__.py +2 -2
  3. pixeltable/catalog/__init__.py +1 -1
  4. pixeltable/catalog/catalog.py +50 -27
  5. pixeltable/catalog/column.py +27 -11
  6. pixeltable/catalog/dir.py +6 -4
  7. pixeltable/catalog/globals.py +8 -1
  8. pixeltable/catalog/insertable_table.py +22 -12
  9. pixeltable/catalog/named_function.py +10 -6
  10. pixeltable/catalog/path.py +3 -2
  11. pixeltable/catalog/path_dict.py +8 -6
  12. pixeltable/catalog/schema_object.py +2 -1
  13. pixeltable/catalog/table.py +121 -101
  14. pixeltable/catalog/table_version.py +291 -142
  15. pixeltable/catalog/table_version_path.py +8 -5
  16. pixeltable/catalog/view.py +67 -26
  17. pixeltable/dataframe.py +106 -81
  18. pixeltable/env.py +28 -24
  19. pixeltable/exec/__init__.py +2 -2
  20. pixeltable/exec/aggregation_node.py +10 -4
  21. pixeltable/exec/cache_prefetch_node.py +5 -3
  22. pixeltable/exec/component_iteration_node.py +9 -9
  23. pixeltable/exec/data_row_batch.py +21 -10
  24. pixeltable/exec/exec_context.py +10 -3
  25. pixeltable/exec/exec_node.py +23 -12
  26. pixeltable/exec/expr_eval/evaluators.py +13 -7
  27. pixeltable/exec/expr_eval/expr_eval_node.py +24 -15
  28. pixeltable/exec/expr_eval/globals.py +30 -7
  29. pixeltable/exec/expr_eval/row_buffer.py +5 -6
  30. pixeltable/exec/expr_eval/schedulers.py +151 -31
  31. pixeltable/exec/in_memory_data_node.py +8 -7
  32. pixeltable/exec/row_update_node.py +15 -5
  33. pixeltable/exec/sql_node.py +56 -27
  34. pixeltable/exprs/__init__.py +2 -2
  35. pixeltable/exprs/arithmetic_expr.py +57 -26
  36. pixeltable/exprs/array_slice.py +1 -1
  37. pixeltable/exprs/column_property_ref.py +2 -1
  38. pixeltable/exprs/column_ref.py +20 -15
  39. pixeltable/exprs/comparison.py +6 -2
  40. pixeltable/exprs/compound_predicate.py +1 -3
  41. pixeltable/exprs/data_row.py +2 -2
  42. pixeltable/exprs/expr.py +108 -72
  43. pixeltable/exprs/expr_dict.py +2 -1
  44. pixeltable/exprs/expr_set.py +3 -1
  45. pixeltable/exprs/function_call.py +39 -41
  46. pixeltable/exprs/globals.py +1 -0
  47. pixeltable/exprs/in_predicate.py +2 -2
  48. pixeltable/exprs/inline_expr.py +20 -17
  49. pixeltable/exprs/json_mapper.py +4 -2
  50. pixeltable/exprs/json_path.py +12 -18
  51. pixeltable/exprs/literal.py +5 -9
  52. pixeltable/exprs/method_ref.py +1 -0
  53. pixeltable/exprs/object_ref.py +1 -1
  54. pixeltable/exprs/row_builder.py +32 -17
  55. pixeltable/exprs/rowid_ref.py +14 -5
  56. pixeltable/exprs/similarity_expr.py +11 -6
  57. pixeltable/exprs/sql_element_cache.py +1 -1
  58. pixeltable/exprs/type_cast.py +24 -9
  59. pixeltable/ext/__init__.py +1 -0
  60. pixeltable/ext/functions/__init__.py +1 -0
  61. pixeltable/ext/functions/whisperx.py +2 -2
  62. pixeltable/ext/functions/yolox.py +11 -11
  63. pixeltable/func/aggregate_function.py +17 -13
  64. pixeltable/func/callable_function.py +6 -6
  65. pixeltable/func/expr_template_function.py +15 -14
  66. pixeltable/func/function.py +16 -16
  67. pixeltable/func/function_registry.py +11 -8
  68. pixeltable/func/globals.py +4 -2
  69. pixeltable/func/query_template_function.py +12 -13
  70. pixeltable/func/signature.py +18 -9
  71. pixeltable/func/tools.py +10 -17
  72. pixeltable/func/udf.py +106 -11
  73. pixeltable/functions/__init__.py +21 -2
  74. pixeltable/functions/anthropic.py +16 -12
  75. pixeltable/functions/fireworks.py +63 -5
  76. pixeltable/functions/gemini.py +13 -3
  77. pixeltable/functions/globals.py +18 -6
  78. pixeltable/functions/huggingface.py +20 -38
  79. pixeltable/functions/image.py +7 -3
  80. pixeltable/functions/json.py +1 -0
  81. pixeltable/functions/llama_cpp.py +1 -4
  82. pixeltable/functions/mistralai.py +31 -20
  83. pixeltable/functions/ollama.py +4 -18
  84. pixeltable/functions/openai.py +231 -113
  85. pixeltable/functions/replicate.py +11 -10
  86. pixeltable/functions/string.py +70 -7
  87. pixeltable/functions/timestamp.py +21 -8
  88. pixeltable/functions/together.py +66 -52
  89. pixeltable/functions/video.py +1 -0
  90. pixeltable/functions/vision.py +14 -11
  91. pixeltable/functions/whisper.py +2 -1
  92. pixeltable/globals.py +60 -26
  93. pixeltable/index/__init__.py +1 -1
  94. pixeltable/index/btree.py +5 -3
  95. pixeltable/index/embedding_index.py +15 -14
  96. pixeltable/io/__init__.py +1 -1
  97. pixeltable/io/external_store.py +30 -25
  98. pixeltable/io/fiftyone.py +6 -14
  99. pixeltable/io/globals.py +33 -27
  100. pixeltable/io/hf_datasets.py +2 -1
  101. pixeltable/io/label_studio.py +77 -68
  102. pixeltable/io/pandas.py +36 -23
  103. pixeltable/io/parquet.py +9 -12
  104. pixeltable/iterators/__init__.py +1 -0
  105. pixeltable/iterators/audio.py +205 -0
  106. pixeltable/iterators/document.py +19 -8
  107. pixeltable/iterators/image.py +6 -24
  108. pixeltable/iterators/string.py +3 -6
  109. pixeltable/iterators/video.py +1 -7
  110. pixeltable/metadata/__init__.py +7 -1
  111. pixeltable/metadata/converters/convert_10.py +2 -2
  112. pixeltable/metadata/converters/convert_15.py +1 -5
  113. pixeltable/metadata/converters/convert_16.py +2 -4
  114. pixeltable/metadata/converters/convert_17.py +2 -4
  115. pixeltable/metadata/converters/convert_18.py +2 -4
  116. pixeltable/metadata/converters/convert_19.py +2 -5
  117. pixeltable/metadata/converters/convert_20.py +1 -4
  118. pixeltable/metadata/converters/convert_21.py +4 -6
  119. pixeltable/metadata/converters/convert_22.py +1 -0
  120. pixeltable/metadata/converters/convert_23.py +5 -5
  121. pixeltable/metadata/converters/convert_24.py +12 -13
  122. pixeltable/metadata/converters/convert_26.py +23 -0
  123. pixeltable/metadata/converters/util.py +3 -4
  124. pixeltable/metadata/notes.py +1 -0
  125. pixeltable/metadata/schema.py +13 -2
  126. pixeltable/plan.py +173 -98
  127. pixeltable/share/__init__.py +0 -0
  128. pixeltable/share/packager.py +218 -0
  129. pixeltable/store.py +42 -26
  130. pixeltable/type_system.py +102 -75
  131. pixeltable/utils/arrow.py +7 -8
  132. pixeltable/utils/coco.py +16 -17
  133. pixeltable/utils/code.py +1 -1
  134. pixeltable/utils/console_output.py +6 -3
  135. pixeltable/utils/description_helper.py +7 -7
  136. pixeltable/utils/documents.py +3 -1
  137. pixeltable/utils/filecache.py +12 -7
  138. pixeltable/utils/http_server.py +9 -8
  139. pixeltable/utils/iceberg.py +14 -0
  140. pixeltable/utils/media_store.py +3 -2
  141. pixeltable/utils/pytorch.py +11 -14
  142. pixeltable/utils/s3.py +1 -0
  143. pixeltable/utils/sql.py +1 -0
  144. pixeltable/utils/transactional_directory.py +2 -2
  145. {pixeltable-0.3.2.dist-info → pixeltable-0.3.4.dist-info}/METADATA +9 -9
  146. pixeltable-0.3.4.dist-info/RECORD +166 -0
  147. pixeltable-0.3.2.dist-info/RECORD +0 -161
  148. {pixeltable-0.3.2.dist-info → pixeltable-0.3.4.dist-info}/LICENSE +0 -0
  149. {pixeltable-0.3.2.dist-info → pixeltable-0.3.4.dist-info}/WHEEL +0 -0
  150. {pixeltable-0.3.2.dist-info → pixeltable-0.3.4.dist-info}/entry_points.txt +0 -0
@@ -27,7 +27,7 @@ from pixeltable.utils.media_store import MediaStore
27
27
 
28
28
  from ..func.globals import resolve_symbol
29
29
  from .column import Column
30
- from .globals import _POS_COLUMN_NAME, _ROWID_COLUMN_NAME, UpdateStatus, is_valid_identifier, MediaValidation
30
+ from .globals import _POS_COLUMN_NAME, _ROWID_COLUMN_NAME, MediaValidation, UpdateStatus, is_valid_identifier
31
31
 
32
32
  if TYPE_CHECKING:
33
33
  from pixeltable import exec, store
@@ -94,11 +94,15 @@ class TableVersion:
94
94
  val_col: Column
95
95
  undo_col: Column
96
96
 
97
-
98
97
  def __init__(
99
- self, id: UUID, tbl_md: schema.TableMd, version: int, schema_version_md: schema.TableSchemaVersionMd,
100
- base: Optional[TableVersion] = None, base_path: Optional[pxt.catalog.TableVersionPath] = None,
101
- is_snapshot: Optional[bool] = None
98
+ self,
99
+ id: UUID,
100
+ tbl_md: schema.TableMd,
101
+ version: int,
102
+ schema_version_md: schema.TableSchemaVersionMd,
103
+ base: Optional[TableVersion] = None,
104
+ base_path: Optional[pxt.catalog.TableVersionPath] = None,
105
+ is_snapshot: Optional[bool] = None,
102
106
  ):
103
107
  # only one of base and base_path can be non-None
104
108
  assert base is None or base_path is None
@@ -117,6 +121,7 @@ class TableVersion:
117
121
 
118
122
  # mutable tables need their TableVersionPath for expr eval during updates
119
123
  from .table_version_path import TableVersionPath
124
+
120
125
  if self.is_snapshot:
121
126
  self.path = None
122
127
  else:
@@ -135,6 +140,7 @@ class TableVersion:
135
140
 
136
141
  # view-specific initialization
137
142
  from pixeltable import exprs
143
+
138
144
  predicate_dict = None if not is_view or tbl_md.view_md.predicate is None else tbl_md.view_md.predicate
139
145
  self.predicate = exprs.Expr.from_dict(predicate_dict) if predicate_dict is not None else None
140
146
  self.mutable_views = [] # targets for update propagation
@@ -186,15 +192,26 @@ class TableVersion:
186
192
  """Create a snapshot copy of this TableVersion"""
187
193
  assert not self.is_snapshot
188
194
  return TableVersion(
189
- self.id, self._create_tbl_md(), self.version,
195
+ self.id,
196
+ self._create_tbl_md(),
197
+ self.version,
190
198
  self._create_schema_version_md(preceding_schema_version=0), # preceding_schema_version: dummy value
191
- is_snapshot=True, base=self.base)
199
+ is_snapshot=True,
200
+ base=self.base,
201
+ )
192
202
 
193
203
  @classmethod
194
204
  def create(
195
- cls, session: orm.Session, dir_id: UUID, name: str, cols: list[Column], num_retained_versions: int,
196
- comment: str, media_validation: MediaValidation, base_path: Optional[pxt.catalog.TableVersionPath] = None,
197
- view_md: Optional[schema.ViewMd] = None
205
+ cls,
206
+ session: orm.Session,
207
+ dir_id: UUID,
208
+ name: str,
209
+ cols: list[Column],
210
+ num_retained_versions: int,
211
+ comment: str,
212
+ media_validation: MediaValidation,
213
+ base_path: Optional[pxt.catalog.TableVersionPath] = None,
214
+ view_md: Optional[schema.ViewMd] = None,
198
215
  ) -> tuple[UUID, Optional[TableVersion]]:
199
216
  # assign ids
200
217
  cols_by_name: dict[str, Column] = {}
@@ -210,8 +227,17 @@ class TableVersion:
210
227
  # Column.dependent_cols for existing cols is wrong at this point, but init() will set it correctly
211
228
  column_md = cls._create_column_md(cols)
212
229
  table_md = schema.TableMd(
213
- name=name, current_version=0, current_schema_version=0, next_col_id=len(cols),
214
- next_idx_id=0, next_row_id=0, column_md=column_md, index_md={}, external_stores=[], view_md=view_md)
230
+ name=name,
231
+ current_version=0,
232
+ current_schema_version=0,
233
+ next_col_id=len(cols),
234
+ next_idx_id=0,
235
+ next_row_id=0,
236
+ column_md=column_md,
237
+ index_md={},
238
+ external_stores=[],
239
+ view_md=view_md,
240
+ )
215
241
  # create a schema.Table here, we need it to call our c'tor;
216
242
  # don't add it to the session yet, we might add index metadata
217
243
  tbl_id = uuid.uuid4()
@@ -220,22 +246,30 @@ class TableVersion:
220
246
  # create schema.TableVersion
221
247
  table_version_md = schema.TableVersionMd(created_at=timestamp, version=0, schema_version=0)
222
248
  tbl_version_record = schema.TableVersion(
223
- tbl_id=tbl_record.id, version=0, md=dataclasses.asdict(table_version_md))
249
+ tbl_id=tbl_record.id, version=0, md=dataclasses.asdict(table_version_md)
250
+ )
224
251
 
225
252
  # create schema.TableSchemaVersion
226
253
  schema_col_md: dict[int, schema.SchemaColumn] = {}
227
254
  for pos, col in enumerate(cols):
228
255
  md = schema.SchemaColumn(
229
- pos=pos, name=col.name,
230
- media_validation=col._media_validation.name.lower() if col._media_validation is not None else None)
256
+ pos=pos,
257
+ name=col.name,
258
+ media_validation=col._media_validation.name.lower() if col._media_validation is not None else None,
259
+ )
231
260
  schema_col_md[col.id] = md
232
261
 
233
262
  schema_version_md = schema.TableSchemaVersionMd(
234
- schema_version=0, preceding_schema_version=None, columns=schema_col_md,
235
- num_retained_versions=num_retained_versions, comment=comment,
236
- media_validation=media_validation.name.lower())
263
+ schema_version=0,
264
+ preceding_schema_version=None,
265
+ columns=schema_col_md,
266
+ num_retained_versions=num_retained_versions,
267
+ comment=comment,
268
+ media_validation=media_validation.name.lower(),
269
+ )
237
270
  schema_version_record = schema.TableSchemaVersion(
238
- tbl_id=tbl_record.id, schema_version=0, md=dataclasses.asdict(schema_version_md))
271
+ tbl_id=tbl_record.id, schema_version=0, md=dataclasses.asdict(schema_version_md)
272
+ )
239
273
 
240
274
  # if this is purely a snapshot (it doesn't require any additional storage for columns and it # doesn't have a
241
275
  # predicate to apply at runtime), we don't create a physical table and simply use the base's table version path
@@ -267,10 +301,8 @@ class TableVersion:
267
301
 
268
302
  @classmethod
269
303
  def delete_md(cls, tbl_id: UUID, conn: sql.Connection) -> None:
270
- conn.execute(
271
- sql.delete(schema.TableSchemaVersion.__table__).where(schema.TableSchemaVersion.tbl_id == tbl_id))
272
- conn.execute(
273
- sql.delete(schema.TableVersion.__table__).where(schema.TableVersion.tbl_id == tbl_id))
304
+ conn.execute(sql.delete(schema.TableSchemaVersion.__table__).where(schema.TableSchemaVersion.tbl_id == tbl_id))
305
+ conn.execute(sql.delete(schema.TableVersion.__table__).where(schema.TableVersion.tbl_id == tbl_id))
274
306
  conn.execute(sql.delete(schema.Table.__table__).where(schema.Table.id == tbl_id))
275
307
 
276
308
  def drop(self) -> None:
@@ -283,6 +315,7 @@ class TableVersion:
283
315
 
284
316
  # de-register table version from catalog
285
317
  from .catalog import Catalog
318
+
286
319
  cat = Catalog.get()
287
320
  del cat.tbl_versions[(self.id, self.effective_version)]
288
321
  # TODO: remove from tbl_dependents
@@ -304,13 +337,20 @@ class TableVersion:
304
337
  col_name = schema_col_md.name if schema_col_md is not None else None
305
338
  media_val = (
306
339
  MediaValidation[schema_col_md.media_validation.upper()]
307
- if schema_col_md is not None and schema_col_md.media_validation is not None else None
340
+ if schema_col_md is not None and schema_col_md.media_validation is not None
341
+ else None
308
342
  )
309
343
  col = Column(
310
- col_id=col_md.id, name=col_name, col_type=ts.ColumnType.from_dict(col_md.col_type),
311
- is_pk=col_md.is_pk, stored=col_md.stored, media_validation=media_val,
312
- schema_version_add=col_md.schema_version_add, schema_version_drop=col_md.schema_version_drop,
313
- value_expr_dict=col_md.value_expr)
344
+ col_id=col_md.id,
345
+ name=col_name,
346
+ col_type=ts.ColumnType.from_dict(col_md.col_type),
347
+ is_pk=col_md.is_pk,
348
+ stored=col_md.stored,
349
+ media_validation=media_val,
350
+ schema_version_add=col_md.schema_version_add,
351
+ schema_version_drop=col_md.schema_version_drop,
352
+ value_expr_dict=col_md.value_expr,
353
+ )
314
354
  col.tbl = self
315
355
  self.cols.append(col)
316
356
 
@@ -335,9 +375,13 @@ class TableVersion:
335
375
  self.idx_md = tbl_md.index_md
336
376
  self.idxs_by_name = {}
337
377
  import pixeltable.index as index_module
378
+
338
379
  for md in tbl_md.index_md.values():
339
- if md.schema_version_add > self.schema_version \
340
- or md.schema_version_drop is not None and md.schema_version_drop <= self.schema_version:
380
+ if (
381
+ md.schema_version_add > self.schema_version
382
+ or md.schema_version_drop is not None
383
+ and md.schema_version_drop <= self.schema_version
384
+ ):
341
385
  # index not visible in this schema version
342
386
  continue
343
387
 
@@ -361,6 +405,7 @@ class TableVersion:
361
405
  # create the sqlalchemy schema; do this after instantiating columns, in order to determine whether they
362
406
  # need to record errors
363
407
  from pixeltable.store import StoreComponentView, StoreTable, StoreView
408
+
364
409
  if self.is_component_view():
365
410
  self.store_tbl = StoreComponentView(self)
366
411
  elif self.is_view():
@@ -369,8 +414,11 @@ class TableVersion:
369
414
  self.store_tbl = StoreTable(self)
370
415
 
371
416
  def _update_md(
372
- self, timestamp: float, conn: sql.engine.Connection, update_tbl_version: bool = True,
373
- preceding_schema_version: Optional[int] = None
417
+ self,
418
+ timestamp: float,
419
+ conn: sql.engine.Connection,
420
+ update_tbl_version: bool = True,
421
+ preceding_schema_version: Optional[int] = None,
374
422
  ) -> None:
375
423
  """Writes table metadata to the database.
376
424
 
@@ -385,22 +433,25 @@ class TableVersion:
385
433
 
386
434
  conn.execute(
387
435
  sql.update(schema.Table.__table__)
388
- .values({schema.Table.md: dataclasses.asdict(self._create_tbl_md())})
389
- .where(schema.Table.id == self.id))
436
+ .values({schema.Table.md: dataclasses.asdict(self._create_tbl_md())})
437
+ .where(schema.Table.id == self.id)
438
+ )
390
439
 
391
440
  if update_tbl_version:
392
441
  version_md = self._create_version_md(timestamp)
393
442
  conn.execute(
394
- sql.insert(schema.TableVersion.__table__)
395
- .values(tbl_id=self.id, version=self.version, md=dataclasses.asdict(version_md)))
443
+ sql.insert(schema.TableVersion.__table__).values(
444
+ tbl_id=self.id, version=self.version, md=dataclasses.asdict(version_md)
445
+ )
446
+ )
396
447
 
397
448
  if preceding_schema_version is not None:
398
449
  schema_version_md = self._create_schema_version_md(preceding_schema_version)
399
450
  conn.execute(
400
- sql.insert(schema.TableSchemaVersion.__table__)
401
- .values(
402
- tbl_id=self.id, schema_version=self.schema_version,
403
- md=dataclasses.asdict(schema_version_md)))
451
+ sql.insert(schema.TableSchemaVersion.__table__).values(
452
+ tbl_id=self.id, schema_version=self.schema_version, md=dataclasses.asdict(schema_version_md)
453
+ )
454
+ )
404
455
 
405
456
  def _store_idx_name(self, idx_id: int) -> str:
406
457
  """Return name of index in the store, which needs to be globally unique"""
@@ -422,6 +473,9 @@ class TableVersion:
422
473
  if not col.stored:
423
474
  # if the column is intentionally not stored, we want to avoid the overhead of an index
424
475
  return None
476
+ # Skip index for stored media columns produced by an iterator
477
+ if col.col_type.is_media_type() and self.is_iterator_column(col):
478
+ return None
425
479
  if not col.col_type.is_scalar_type() and not (col.col_type.is_media_type() and not col.is_computed):
426
480
  # wrong type for a B-tree
427
481
  return None
@@ -432,7 +486,7 @@ class TableVersion:
432
486
  return status
433
487
 
434
488
  def _add_index(
435
- self, col: Column, idx_name: Optional[str], idx: index.IndexBase, conn: sql.engine.Connection
489
+ self, col: Column, idx_name: Optional[str], idx: index.IndexBase, conn: sql.engine.Connection
436
490
  ) -> UpdateStatus:
437
491
  assert not self.is_snapshot
438
492
  idx_id = self.next_idx_id
@@ -445,19 +499,29 @@ class TableVersion:
445
499
 
446
500
  # add the index value and undo columns (which need to be nullable)
447
501
  val_col = Column(
448
- col_id=self.next_col_id, name=None, computed_with=idx.index_value_expr(),
449
- sa_col_type=idx.index_sa_type(), stored=True,
450
- schema_version_add=self.schema_version, schema_version_drop=None,
451
- records_errors=idx.records_value_errors())
502
+ col_id=self.next_col_id,
503
+ name=None,
504
+ computed_with=idx.index_value_expr(),
505
+ sa_col_type=idx.index_sa_type(),
506
+ stored=True,
507
+ schema_version_add=self.schema_version,
508
+ schema_version_drop=None,
509
+ records_errors=idx.records_value_errors(),
510
+ )
452
511
  val_col.tbl = self
453
512
  val_col.col_type = val_col.col_type.copy(nullable=True)
454
513
  self.next_col_id += 1
455
514
 
456
515
  undo_col = Column(
457
- col_id=self.next_col_id, name=None, col_type=val_col.col_type,
458
- sa_col_type=val_col.sa_col_type, stored=True,
459
- schema_version_add=self.schema_version, schema_version_drop=None,
460
- records_errors=False)
516
+ col_id=self.next_col_id,
517
+ name=None,
518
+ col_type=val_col.col_type,
519
+ sa_col_type=val_col.sa_col_type,
520
+ stored=True,
521
+ schema_version_add=self.schema_version,
522
+ schema_version_drop=None,
523
+ records_errors=False,
524
+ )
461
525
  undo_col.tbl = self
462
526
  undo_col.col_type = undo_col.col_type.copy(nullable=True)
463
527
  self.next_col_id += 1
@@ -465,11 +529,17 @@ class TableVersion:
465
529
  # create and register the index metadata
466
530
  idx_cls = type(idx)
467
531
  idx_md = schema.IndexMd(
468
- id=idx_id, name=idx_name,
469
- indexed_col_id=col.id, indexed_col_tbl_id=str(col.tbl.id),
470
- index_val_col_id=val_col.id, index_val_undo_col_id=undo_col.id,
471
- schema_version_add=self.schema_version, schema_version_drop=None,
472
- class_fqn=idx_cls.__module__ + '.' + idx_cls.__name__, init_args=idx.as_dict())
532
+ id=idx_id,
533
+ name=idx_name,
534
+ indexed_col_id=col.id,
535
+ indexed_col_tbl_id=str(col.tbl.id),
536
+ index_val_col_id=val_col.id,
537
+ index_val_undo_col_id=undo_col.id,
538
+ schema_version_add=self.schema_version,
539
+ schema_version_drop=None,
540
+ class_fqn=idx_cls.__module__ + '.' + idx_cls.__name__,
541
+ init_args=idx.as_dict(),
542
+ )
473
543
  idx_info = self.IndexInfo(id=idx_id, name=idx_name, idx=idx, col=col, val_col=val_col, undo_col=undo_col)
474
544
  self.idx_md[idx_id] = idx_md
475
545
  self.idxs_by_name[idx_name] = idx_info
@@ -505,9 +575,10 @@ class TableVersion:
505
575
  self._update_md(time.time(), conn, preceding_schema_version=preceding_schema_version)
506
576
  _logger.info(f'Dropped index {idx_md.name} on table {self.name}')
507
577
 
508
- def add_columns(self, cols: Iterable[Column], print_stats: bool, on_error: Literal['abort', 'ignore']) -> UpdateStatus:
509
- """Adds a column to the table.
510
- """
578
+ def add_columns(
579
+ self, cols: Iterable[Column], print_stats: bool, on_error: Literal['abort', 'ignore']
580
+ ) -> UpdateStatus:
581
+ """Adds a column to the table."""
511
582
  assert not self.is_snapshot
512
583
  assert all(is_valid_identifier(col.name) for col in cols)
513
584
  assert all(col.stored is not None for col in cols)
@@ -541,7 +612,7 @@ class TableVersion:
541
612
  cols: Iterable[Column],
542
613
  conn: sql.engine.Connection,
543
614
  print_stats: bool,
544
- on_error: Literal['abort', 'ignore']
615
+ on_error: Literal['abort', 'ignore'],
545
616
  ) -> UpdateStatus:
546
617
  """Add and populate columns within the current transaction"""
547
618
  cols = list(cols)
@@ -550,7 +621,8 @@ class TableVersion:
550
621
  if not col.col_type.nullable and not col.is_computed:
551
622
  if row_count > 0:
552
623
  raise excs.Error(
553
- f'Cannot add non-nullable column "{col.name}" to table {self.name} with existing rows')
624
+ f'Cannot add non-nullable column "{col.name}" to table {self.name} with existing rows'
625
+ )
554
626
 
555
627
  num_excs = 0
556
628
  cols_with_excs: list[Column] = []
@@ -574,6 +646,7 @@ class TableVersion:
574
646
 
575
647
  # populate the column
576
648
  from pixeltable.plan import Planner
649
+
577
650
  plan, value_expr_slot_idx = Planner.create_add_column_plan(self.path, col)
578
651
  plan.ctx.num_rows = row_count
579
652
 
@@ -606,12 +679,14 @@ class TableVersion:
606
679
  plan.ctx.profile.print(num_rows=row_count)
607
680
  # TODO(mkornacker): what to do about system columns with exceptions?
608
681
  return UpdateStatus(
609
- num_rows=row_count, num_computed_values=row_count, num_excs=num_excs,
610
- cols_with_excs=[f'{col.tbl.name}.{col.name}'for col in cols_with_excs if col.name is not None])
682
+ num_rows=row_count,
683
+ num_computed_values=row_count,
684
+ num_excs=num_excs,
685
+ cols_with_excs=[f'{col.tbl.name}.{col.name}' for col in cols_with_excs if col.name is not None],
686
+ )
611
687
 
612
688
  def drop_column(self, col: Column) -> None:
613
- """Drop a column from the table.
614
- """
689
+ """Drop a column from the table."""
615
690
  from pixeltable.catalog import Catalog
616
691
 
617
692
  assert not self.is_snapshot
@@ -662,8 +737,7 @@ class TableVersion:
662
737
  self.store_tbl.create_sa_tbl()
663
738
 
664
739
  def rename_column(self, old_name: str, new_name: str) -> None:
665
- """Rename a column.
666
- """
740
+ """Rename a column."""
667
741
  assert not self.is_snapshot
668
742
  if old_name not in self.cols_by_name:
669
743
  raise excs.Error(f'Unknown column: {old_name}')
@@ -691,7 +765,9 @@ class TableVersion:
691
765
  self._create_schema_version()
692
766
 
693
767
  def set_num_retained_versions(self, new_num_retained_versions: int):
694
- _logger.info(f'[{self.name}] Updating num_retained_versions: {new_num_retained_versions} (was {self.num_retained_versions})')
768
+ _logger.info(
769
+ f'[{self.name}] Updating num_retained_versions: {new_num_retained_versions} (was {self.num_retained_versions})'
770
+ )
695
771
  self.num_retained_versions = new_num_retained_versions
696
772
  self._create_schema_version()
697
773
 
@@ -705,12 +781,12 @@ class TableVersion:
705
781
  _logger.info(f'[{self.name}] Updating table schema to version: {self.version}')
706
782
 
707
783
  def insert(
708
- self,
709
- rows: Optional[list[dict[str, Any]]],
710
- df: Optional[pxt.DataFrame],
711
- conn: Optional[sql.engine.Connection] = None,
712
- print_stats: bool = False,
713
- fail_on_exception: bool = True
784
+ self,
785
+ rows: Optional[list[dict[str, Any]]],
786
+ df: Optional[pxt.DataFrame],
787
+ conn: Optional[sql.engine.Connection] = None,
788
+ print_stats: bool = False,
789
+ fail_on_exception: bool = True,
714
790
  ) -> UpdateStatus:
715
791
  """
716
792
  Insert rows into this table, either from an explicit list of dicts or from a `DataFrame`.
@@ -734,22 +810,30 @@ class TableVersion:
734
810
  if conn is None:
735
811
  with Env.get().engine.begin() as conn:
736
812
  return self._insert(
737
- plan, conn, time.time(), print_stats=print_stats, rowids=rowids(),
738
- abort_on_exc=fail_on_exception)
813
+ plan, conn, time.time(), print_stats=print_stats, rowids=rowids(), abort_on_exc=fail_on_exception
814
+ )
739
815
  else:
740
816
  return self._insert(
741
- plan, conn, time.time(), print_stats=print_stats, rowids=rowids(), abort_on_exc=fail_on_exception)
817
+ plan, conn, time.time(), print_stats=print_stats, rowids=rowids(), abort_on_exc=fail_on_exception
818
+ )
742
819
 
743
820
  def _insert(
744
- self, exec_plan: 'exec.ExecNode', conn: sql.engine.Connection, timestamp: float, *,
745
- rowids: Optional[Iterator[int]] = None, print_stats: bool = False, abort_on_exc: bool = False
821
+ self,
822
+ exec_plan: 'exec.ExecNode',
823
+ conn: sql.engine.Connection,
824
+ timestamp: float,
825
+ *,
826
+ rowids: Optional[Iterator[int]] = None,
827
+ print_stats: bool = False,
828
+ abort_on_exc: bool = False,
746
829
  ) -> UpdateStatus:
747
830
  """Insert rows produced by exec_plan and propagate to views"""
748
831
  # we're creating a new version
749
832
  self.version += 1
750
833
  result = UpdateStatus()
751
834
  num_rows, num_excs, cols_with_excs = self.store_tbl.insert_rows(
752
- exec_plan, conn, v_min=self.version, rowids=rowids, abort_on_exc=abort_on_exc)
835
+ exec_plan, conn, v_min=self.version, rowids=rowids, abort_on_exc=abort_on_exc
836
+ )
753
837
  result.num_rows = num_rows
754
838
  result.num_excs = num_excs
755
839
  result.num_computed_values += exec_plan.ctx.num_computed_exprs * num_rows
@@ -759,6 +843,7 @@ class TableVersion:
759
843
  # update views
760
844
  for view in self.mutable_views:
761
845
  from pixeltable.plan import Planner
846
+
762
847
  plan, _ = Planner.create_view_load_plan(view.path, propagates_insert=True)
763
848
  status = view._insert(plan, conn, timestamp, print_stats=print_stats)
764
849
  result.num_rows += status.num_rows
@@ -799,15 +884,27 @@ class TableVersion:
799
884
  with Env.get().engine.begin() as conn:
800
885
  plan, updated_cols, recomputed_cols = Planner.create_update_plan(self.path, update_spec, [], where, cascade)
801
886
  from pixeltable.exprs import SqlElementCache
887
+
802
888
  result = self.propagate_update(
803
- plan, where.sql_expr(SqlElementCache()) if where is not None else None, recomputed_cols,
804
- base_versions=[], conn=conn, timestamp=time.time(), cascade=cascade, show_progress=True)
889
+ plan,
890
+ where.sql_expr(SqlElementCache()) if where is not None else None,
891
+ recomputed_cols,
892
+ base_versions=[],
893
+ conn=conn,
894
+ timestamp=time.time(),
895
+ cascade=cascade,
896
+ show_progress=True,
897
+ )
805
898
  result.updated_cols = updated_cols
806
899
  return result
807
900
 
808
901
  def batch_update(
809
- self, batch: list[dict[Column, exprs.Expr]], rowids: list[tuple[int, ...]], insert_if_not_exists: bool,
810
- error_if_not_exists: bool, cascade: bool = True,
902
+ self,
903
+ batch: list[dict[Column, exprs.Expr]],
904
+ rowids: list[tuple[int, ...]],
905
+ insert_if_not_exists: bool,
906
+ error_if_not_exists: bool,
907
+ cascade: bool = True,
811
908
  ) -> UpdateStatus:
812
909
  """Update rows in batch.
813
910
  Args:
@@ -821,11 +918,18 @@ class TableVersion:
821
918
  with Env.get().engine.begin() as conn:
822
919
  from pixeltable.plan import Planner
823
920
 
824
- plan, row_update_node, delete_where_clause, updated_cols, recomputed_cols = \
921
+ plan, row_update_node, delete_where_clause, updated_cols, recomputed_cols = (
825
922
  Planner.create_batch_update_plan(self.path, batch, rowids, cascade=cascade)
923
+ )
826
924
  result = self.propagate_update(
827
- plan, delete_where_clause, recomputed_cols, base_versions=[], conn=conn, timestamp=time.time(),
828
- cascade=cascade)
925
+ plan,
926
+ delete_where_clause,
927
+ recomputed_cols,
928
+ base_versions=[],
929
+ conn=conn,
930
+ timestamp=time.time(),
931
+ cascade=cascade,
932
+ )
829
933
  result.updated_cols = [c.qualified_name for c in updated_cols]
830
934
 
831
935
  unmatched_rows = row_update_node.unmatched_rows()
@@ -833,12 +937,14 @@ class TableVersion:
833
937
  if error_if_not_exists:
834
938
  raise excs.Error(f'batch_update(): {len(unmatched_rows)} row(s) not found')
835
939
  if insert_if_not_exists:
836
- insert_status = self.insert(unmatched_rows, None, conn=conn, print_stats=False, fail_on_exception=False)
940
+ insert_status = self.insert(
941
+ unmatched_rows, None, conn=conn, print_stats=False, fail_on_exception=False
942
+ )
837
943
  result += insert_status
838
944
  return result
839
945
 
840
946
  def _validate_update_spec(
841
- self, value_spec: dict[str, Any], allow_pk: bool, allow_exprs: bool
947
+ self, value_spec: dict[str, Any], allow_pk: bool, allow_exprs: bool
842
948
  ) -> dict[Column, exprs.Expr]:
843
949
  update_targets: dict[Column, exprs.Expr] = {}
844
950
  for col_name, val in value_spec.items():
@@ -868,7 +974,8 @@ class TableVersion:
868
974
  if not allow_exprs:
869
975
  raise excs.Error(
870
976
  f'Column {col_name}: value {val!r} is not a valid literal for this column '
871
- f'(expected {col.col_type})')
977
+ f'(expected {col.col_type})'
978
+ )
872
979
  # it's not a literal, let's try to create an expr from it
873
980
  value_expr = exprs.Expr.from_object(val)
874
981
  if value_expr is None:
@@ -883,19 +990,27 @@ class TableVersion:
883
990
  return update_targets
884
991
 
885
992
  def propagate_update(
886
- self, plan: Optional[exec.ExecNode], where_clause: Optional[sql.ColumnElement],
887
- recomputed_view_cols: list[Column], base_versions: list[Optional[int]], conn: sql.engine.Connection,
888
- timestamp: float, cascade: bool, show_progress: bool = True
993
+ self,
994
+ plan: Optional[exec.ExecNode],
995
+ where_clause: Optional[sql.ColumnElement],
996
+ recomputed_view_cols: list[Column],
997
+ base_versions: list[Optional[int]],
998
+ conn: sql.engine.Connection,
999
+ timestamp: float,
1000
+ cascade: bool,
1001
+ show_progress: bool = True,
889
1002
  ) -> UpdateStatus:
890
1003
  result = UpdateStatus()
891
1004
  if plan is not None:
892
1005
  # we're creating a new version
893
1006
  self.version += 1
894
- result.num_rows, result.num_excs, cols_with_excs = \
895
- self.store_tbl.insert_rows(plan, conn, v_min=self.version, show_progress=show_progress)
1007
+ result.num_rows, result.num_excs, cols_with_excs = self.store_tbl.insert_rows(
1008
+ plan, conn, v_min=self.version, show_progress=show_progress
1009
+ )
896
1010
  result.cols_with_excs = [f'{self.name}.{self.cols_by_id[cid].name}' for cid in cols_with_excs]
897
1011
  self.store_tbl.delete_rows(
898
- self.version, base_versions=base_versions, match_on_vmin=True, where_clause=where_clause, conn=conn)
1012
+ self.version, base_versions=base_versions, match_on_vmin=True, where_clause=where_clause, conn=conn
1013
+ )
899
1014
  self._update_md(timestamp, conn)
900
1015
 
901
1016
  if cascade:
@@ -906,9 +1021,17 @@ class TableVersion:
906
1021
  plan = None
907
1022
  if len(recomputed_cols) > 0:
908
1023
  from pixeltable.plan import Planner
1024
+
909
1025
  plan = Planner.create_view_update_plan(view.path, recompute_targets=recomputed_cols)
910
1026
  status = view.propagate_update(
911
- plan, None, recomputed_view_cols, base_versions=base_versions, conn=conn, timestamp=timestamp, cascade=True)
1027
+ plan,
1028
+ None,
1029
+ recomputed_view_cols,
1030
+ base_versions=base_versions,
1031
+ conn=conn,
1032
+ timestamp=timestamp,
1033
+ cascade=True,
1034
+ )
912
1035
  result.num_rows += status.num_rows
913
1036
  result.num_excs += status.num_excs
914
1037
  result.cols_with_excs += status.cols_with_excs
@@ -924,6 +1047,7 @@ class TableVersion:
924
1047
  assert self.is_insertable()
925
1048
  from pixeltable.exprs import Expr
926
1049
  from pixeltable.plan import Planner
1050
+
927
1051
  sql_where_clause: Optional[Expr] = None
928
1052
  if where is not None:
929
1053
  if not isinstance(where, Expr):
@@ -941,8 +1065,12 @@ class TableVersion:
941
1065
  return status
942
1066
 
943
1067
  def propagate_delete(
944
- self, where: Optional[exprs.Expr], base_versions: list[Optional[int]],
945
- conn: sql.engine.Connection, timestamp: float) -> int:
1068
+ self,
1069
+ where: Optional[exprs.Expr],
1070
+ base_versions: list[Optional[int]],
1071
+ conn: sql.engine.Connection,
1072
+ timestamp: float,
1073
+ ) -> int:
946
1074
  """Delete rows in this table and propagate to views.
947
1075
  Args:
948
1076
  where: a predicate to filter rows to delete.
@@ -951,8 +1079,8 @@ class TableVersion:
951
1079
  """
952
1080
  sql_where_clause = where.sql_expr(exprs.SqlElementCache()) if where is not None else None
953
1081
  num_rows = self.store_tbl.delete_rows(
954
- self.version + 1, base_versions=base_versions, match_on_vmin=False, where_clause=sql_where_clause,
955
- conn=conn)
1082
+ self.version + 1, base_versions=base_versions, match_on_vmin=False, where_clause=sql_where_clause, conn=conn
1083
+ )
956
1084
  if num_rows > 0:
957
1085
  # we're creating a new version
958
1086
  self.version += 1
@@ -961,12 +1089,12 @@ class TableVersion:
961
1089
  pass
962
1090
  for view in self.mutable_views:
963
1091
  num_rows += view.propagate_delete(
964
- where=None, base_versions=[self.version] + base_versions, conn=conn, timestamp=timestamp)
1092
+ where=None, base_versions=[self.version] + base_versions, conn=conn, timestamp=timestamp
1093
+ )
965
1094
  return num_rows
966
1095
 
967
1096
  def revert(self) -> None:
968
- """Reverts the table to the previous version.
969
- """
1097
+ """Reverts the table to the previous version."""
970
1098
  assert not self.is_snapshot
971
1099
  if self.version == 0:
972
1100
  raise excs.Error('Cannot revert version 0')
@@ -990,17 +1118,19 @@ class TableVersion:
990
1118
  # (unclear how to express this with sqlalchemy)
991
1119
  query = (
992
1120
  f"select ts.dir_id, ts.md->'name' "
993
- f"from {schema.Table.__tablename__} ts "
1121
+ f'from {schema.Table.__tablename__} ts '
994
1122
  f"cross join lateral jsonb_path_query(md, '$.view_md.base_versions[*]') as tbl_version "
995
1123
  f"where tbl_version->>0 = '{self.id.hex}' and (tbl_version->>1)::int = {self.version}"
996
1124
  )
997
1125
  result = list(conn.execute(sql.text(query)))
998
1126
  if len(result) > 0:
999
1127
  names = [row[1] for row in result]
1000
- raise excs.Error((
1001
- f'Current version is needed for {len(result)} snapshot{"s" if len(result) > 1 else ""} '
1002
- f'({", ".join(names)})'
1003
- ))
1128
+ raise excs.Error(
1129
+ (
1130
+ f'Current version is needed for {len(result)} snapshot{"s" if len(result) > 1 else ""} '
1131
+ f'({", ".join(names)})'
1132
+ )
1133
+ )
1004
1134
 
1005
1135
  conn = session.connection()
1006
1136
  # delete newly-added data
@@ -1013,9 +1143,7 @@ class TableVersion:
1013
1143
  # copy the index value back from the undo column and reset the undo column to NULL
1014
1144
  set_clause[index_info.val_col.sa_col] = index_info.undo_col.sa_col
1015
1145
  set_clause[index_info.undo_col.sa_col] = None
1016
- stmt = sql.update(self.store_tbl.sa_tbl) \
1017
- .values(set_clause) \
1018
- .where(self.store_tbl.sa_tbl.c.v_max == self.version)
1146
+ stmt = sql.update(self.store_tbl.sa_tbl).values(set_clause).where(self.store_tbl.sa_tbl.c.v_max == self.version)
1019
1147
  conn.execute(stmt)
1020
1148
 
1021
1149
  # revert schema changes
@@ -1049,38 +1177,45 @@ class TableVersion:
1049
1177
  md.schema_version_drop = None
1050
1178
 
1051
1179
  # we need to determine the preceding schema version and reload the schema
1052
- schema_version_md_dict = session.query(schema.TableSchemaVersion.md) \
1053
- .where(schema.TableSchemaVersion.tbl_id == self.id) \
1054
- .where(schema.TableSchemaVersion.schema_version == self.schema_version) \
1180
+ schema_version_md_dict = (
1181
+ session.query(schema.TableSchemaVersion.md)
1182
+ .where(schema.TableSchemaVersion.tbl_id == self.id)
1183
+ .where(schema.TableSchemaVersion.schema_version == self.schema_version)
1055
1184
  .scalar()
1185
+ )
1056
1186
  preceding_schema_version = schema_version_md_dict['preceding_schema_version']
1057
- preceding_schema_version_md_dict = session.query(schema.TableSchemaVersion.md) \
1058
- .where(schema.TableSchemaVersion.tbl_id == self.id) \
1059
- .where(schema.TableSchemaVersion.schema_version == preceding_schema_version) \
1187
+ preceding_schema_version_md_dict = (
1188
+ session.query(schema.TableSchemaVersion.md)
1189
+ .where(schema.TableSchemaVersion.tbl_id == self.id)
1190
+ .where(schema.TableSchemaVersion.schema_version == preceding_schema_version)
1060
1191
  .scalar()
1192
+ )
1061
1193
  preceding_schema_version_md = schema.md_from_dict(
1062
- schema.TableSchemaVersionMd, preceding_schema_version_md_dict)
1194
+ schema.TableSchemaVersionMd, preceding_schema_version_md_dict
1195
+ )
1063
1196
  tbl_md = self._create_tbl_md()
1064
1197
  self._init_schema(tbl_md, preceding_schema_version_md)
1065
1198
 
1066
1199
  conn.execute(
1067
1200
  sql.delete(schema.TableSchemaVersion.__table__)
1068
- .where(schema.TableSchemaVersion.tbl_id == self.id)
1069
- .where(schema.TableSchemaVersion.schema_version == self.schema_version))
1201
+ .where(schema.TableSchemaVersion.tbl_id == self.id)
1202
+ .where(schema.TableSchemaVersion.schema_version == self.schema_version)
1203
+ )
1070
1204
  self.schema_version = preceding_schema_version
1071
1205
  self.comment = preceding_schema_version_md.comment
1072
1206
  self.num_retained_versions = preceding_schema_version_md.num_retained_versions
1073
1207
 
1074
1208
  conn.execute(
1075
1209
  sql.delete(schema.TableVersion.__table__)
1076
- .where(schema.TableVersion.tbl_id == self.id)
1077
- .where(schema.TableVersion.version == self.version)
1210
+ .where(schema.TableVersion.tbl_id == self.id)
1211
+ .where(schema.TableVersion.version == self.version)
1078
1212
  )
1079
1213
  self.version -= 1
1080
1214
  conn.execute(
1081
1215
  sql.update(schema.Table.__table__)
1082
- .values({schema.Table.md: dataclasses.asdict(self._create_tbl_md())})
1083
- .where(schema.Table.id == self.id))
1216
+ .values({schema.Table.md: dataclasses.asdict(self._create_tbl_md())})
1217
+ .where(schema.Table.id == self.id)
1218
+ )
1084
1219
 
1085
1220
  # propagate to views
1086
1221
  for view in self.mutable_views:
@@ -1152,9 +1287,9 @@ class TableVersion:
1152
1287
  return names
1153
1288
 
1154
1289
  def _record_refd_columns(self, col: Column) -> None:
1155
- """Update Column.dependent_cols for all cols referenced in col.value_expr.
1156
- """
1290
+ """Update Column.dependent_cols for all cols referenced in col.value_expr."""
1157
1291
  import pixeltable.exprs as exprs
1292
+
1158
1293
  if col.value_expr_dict is not None:
1159
1294
  # if we have a value_expr_dict, use that instead of instantiating the value_expr
1160
1295
  refd_cols = exprs.Expr.get_refd_columns(col.value_expr_dict)
@@ -1188,27 +1323,34 @@ class TableVersion:
1188
1323
  for col in cols:
1189
1324
  value_expr_dict = col.value_expr.as_dict() if col.value_expr is not None else None
1190
1325
  column_md[col.id] = schema.ColumnMd(
1191
- id=col.id, col_type=col.col_type.as_dict(), is_pk=col.is_pk,
1192
- schema_version_add=col.schema_version_add, schema_version_drop=col.schema_version_drop,
1193
- value_expr=value_expr_dict, stored=col.stored)
1326
+ id=col.id,
1327
+ col_type=col.col_type.as_dict(),
1328
+ is_pk=col.is_pk,
1329
+ schema_version_add=col.schema_version_add,
1330
+ schema_version_drop=col.schema_version_drop,
1331
+ value_expr=value_expr_dict,
1332
+ stored=col.stored,
1333
+ )
1194
1334
  return column_md
1195
1335
 
1196
1336
  @classmethod
1197
1337
  def _create_stores_md(cls, stores: Iterable[pxt.io.ExternalStore]) -> list[dict[str, Any]]:
1198
1338
  return [
1199
- {
1200
- 'class': f'{type(store).__module__}.{type(store).__qualname__}',
1201
- 'md': store.as_dict()
1202
- }
1203
- for store in stores
1339
+ {'class': f'{type(store).__module__}.{type(store).__qualname__}', 'md': store.as_dict()} for store in stores
1204
1340
  ]
1205
1341
 
1206
1342
  def _create_tbl_md(self) -> schema.TableMd:
1207
1343
  return schema.TableMd(
1208
- name=self.name, current_version=self.version, current_schema_version=self.schema_version,
1209
- next_col_id=self.next_col_id, next_idx_id=self.next_idx_id, next_row_id=self.next_rowid,
1210
- column_md=self._create_column_md(self.cols), index_md=self.idx_md,
1211
- external_stores=self._create_stores_md(self.external_stores.values()), view_md=self.view_md,
1344
+ name=self.name,
1345
+ current_version=self.version,
1346
+ current_schema_version=self.schema_version,
1347
+ next_col_id=self.next_col_id,
1348
+ next_idx_id=self.next_idx_id,
1349
+ next_row_id=self.next_rowid,
1350
+ column_md=self._create_column_md(self.cols),
1351
+ index_md=self.idx_md,
1352
+ external_stores=self._create_stores_md(self.external_stores.values()),
1353
+ view_md=self.view_md,
1212
1354
  )
1213
1355
 
1214
1356
  def _create_version_md(self, timestamp: float) -> schema.TableVersionMd:
@@ -1218,13 +1360,19 @@ class TableVersion:
1218
1360
  column_md: dict[int, schema.SchemaColumn] = {}
1219
1361
  for pos, col in enumerate(self.cols_by_name.values()):
1220
1362
  column_md[col.id] = schema.SchemaColumn(
1221
- pos=pos, name=col.name,
1222
- media_validation=col._media_validation.name.lower() if col._media_validation is not None else None)
1363
+ pos=pos,
1364
+ name=col.name,
1365
+ media_validation=col._media_validation.name.lower() if col._media_validation is not None else None,
1366
+ )
1223
1367
  # preceding_schema_version to be set by the caller
1224
1368
  return schema.TableSchemaVersionMd(
1225
- schema_version=self.schema_version, preceding_schema_version=preceding_schema_version,
1226
- columns=column_md, num_retained_versions=self.num_retained_versions, comment=self.comment,
1227
- media_validation=self.media_validation.name.lower())
1369
+ schema_version=self.schema_version,
1370
+ preceding_schema_version=preceding_schema_version,
1371
+ columns=column_md,
1372
+ num_retained_versions=self.num_retained_versions,
1373
+ comment=self.comment,
1374
+ media_validation=self.media_validation.name.lower(),
1375
+ )
1228
1376
 
1229
1377
  def as_dict(self) -> dict:
1230
1378
  return {'id': str(self.id), 'effective_version': self.effective_version}
@@ -1232,6 +1380,7 @@ class TableVersion:
1232
1380
  @classmethod
1233
1381
  def from_dict(cls, d: dict) -> TableVersion:
1234
1382
  import pixeltable.catalog as catalog
1383
+
1235
1384
  id = UUID(d['id'])
1236
1385
  effective_version = d['effective_version']
1237
1386
  return catalog.Catalog.get().tbl_versions[(id, effective_version)]