pixeltable 0.2.17__py3-none-any.whl → 0.2.18__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 (79) hide show
  1. pixeltable/__version__.py +2 -2
  2. pixeltable/catalog/catalog.py +8 -7
  3. pixeltable/catalog/column.py +11 -8
  4. pixeltable/catalog/insertable_table.py +1 -1
  5. pixeltable/catalog/path_dict.py +8 -6
  6. pixeltable/catalog/table.py +20 -13
  7. pixeltable/catalog/table_version.py +91 -54
  8. pixeltable/catalog/table_version_path.py +7 -9
  9. pixeltable/catalog/view.py +2 -1
  10. pixeltable/dataframe.py +1 -1
  11. pixeltable/env.py +173 -83
  12. pixeltable/exec/aggregation_node.py +2 -1
  13. pixeltable/exec/component_iteration_node.py +1 -1
  14. pixeltable/exec/sql_node.py +11 -8
  15. pixeltable/exprs/__init__.py +1 -0
  16. pixeltable/exprs/arithmetic_expr.py +4 -4
  17. pixeltable/exprs/array_slice.py +2 -1
  18. pixeltable/exprs/column_property_ref.py +9 -7
  19. pixeltable/exprs/column_ref.py +2 -1
  20. pixeltable/exprs/comparison.py +10 -7
  21. pixeltable/exprs/compound_predicate.py +3 -2
  22. pixeltable/exprs/data_row.py +19 -4
  23. pixeltable/exprs/expr.py +46 -35
  24. pixeltable/exprs/expr_set.py +32 -9
  25. pixeltable/exprs/function_call.py +56 -32
  26. pixeltable/exprs/in_predicate.py +3 -2
  27. pixeltable/exprs/inline_array.py +2 -1
  28. pixeltable/exprs/inline_dict.py +2 -1
  29. pixeltable/exprs/is_null.py +3 -2
  30. pixeltable/exprs/json_mapper.py +5 -4
  31. pixeltable/exprs/json_path.py +7 -1
  32. pixeltable/exprs/literal.py +34 -7
  33. pixeltable/exprs/method_ref.py +3 -3
  34. pixeltable/exprs/object_ref.py +6 -5
  35. pixeltable/exprs/row_builder.py +25 -17
  36. pixeltable/exprs/rowid_ref.py +2 -1
  37. pixeltable/exprs/similarity_expr.py +2 -1
  38. pixeltable/exprs/sql_element_cache.py +30 -0
  39. pixeltable/exprs/type_cast.py +3 -3
  40. pixeltable/exprs/variable.py +2 -1
  41. pixeltable/ext/functions/whisperx.py +4 -4
  42. pixeltable/ext/functions/yolox.py +6 -6
  43. pixeltable/func/aggregate_function.py +1 -0
  44. pixeltable/func/function.py +28 -4
  45. pixeltable/functions/__init__.py +4 -2
  46. pixeltable/functions/anthropic.py +15 -5
  47. pixeltable/functions/fireworks.py +1 -1
  48. pixeltable/functions/globals.py +6 -1
  49. pixeltable/functions/huggingface.py +2 -2
  50. pixeltable/functions/image.py +17 -2
  51. pixeltable/functions/json.py +5 -5
  52. pixeltable/functions/mistralai.py +188 -0
  53. pixeltable/functions/openai.py +6 -10
  54. pixeltable/functions/string.py +3 -2
  55. pixeltable/functions/timestamp.py +95 -7
  56. pixeltable/functions/together.py +4 -4
  57. pixeltable/functions/video.py +2 -2
  58. pixeltable/functions/vision.py +27 -17
  59. pixeltable/functions/whisper.py +1 -1
  60. pixeltable/io/hf_datasets.py +17 -15
  61. pixeltable/io/pandas.py +0 -2
  62. pixeltable/io/parquet.py +15 -14
  63. pixeltable/iterators/document.py +16 -15
  64. pixeltable/metadata/__init__.py +1 -1
  65. pixeltable/metadata/converters/convert_19.py +46 -0
  66. pixeltable/metadata/notes.py +1 -0
  67. pixeltable/metadata/schema.py +5 -4
  68. pixeltable/plan.py +100 -78
  69. pixeltable/store.py +5 -1
  70. pixeltable/tool/create_test_db_dump.py +4 -3
  71. pixeltable/type_system.py +12 -14
  72. pixeltable/utils/documents.py +45 -42
  73. pixeltable/utils/formatter.py +2 -2
  74. {pixeltable-0.2.17.dist-info → pixeltable-0.2.18.dist-info}/METADATA +79 -21
  75. pixeltable-0.2.18.dist-info/RECORD +147 -0
  76. pixeltable-0.2.17.dist-info/RECORD +0 -144
  77. {pixeltable-0.2.17.dist-info → pixeltable-0.2.18.dist-info}/LICENSE +0 -0
  78. {pixeltable-0.2.17.dist-info → pixeltable-0.2.18.dist-info}/WHEEL +0 -0
  79. {pixeltable-0.2.17.dist-info → pixeltable-0.2.18.dist-info}/entry_points.txt +0 -0
@@ -6,7 +6,7 @@ import inspect
6
6
  import logging
7
7
  import time
8
8
  import uuid
9
- from typing import Optional, List, Dict, Any, Tuple, Type, Iterable
9
+ from typing import TYPE_CHECKING, Any, Iterable, Optional
10
10
  from uuid import UUID
11
11
 
12
12
  import sqlalchemy as sql
@@ -23,9 +23,13 @@ from pixeltable.iterators import ComponentIterator
23
23
  from pixeltable.metadata import schema
24
24
  from pixeltable.utils.filecache import FileCache
25
25
  from pixeltable.utils.media_store import MediaStore
26
- from .column import Column
27
- from .globals import UpdateStatus, _POS_COLUMN_NAME, is_valid_identifier, _ROWID_COLUMN_NAME
26
+
28
27
  from ..func.globals import resolve_symbol
28
+ from .column import Column
29
+ from .globals import _POS_COLUMN_NAME, _ROWID_COLUMN_NAME, UpdateStatus, is_valid_identifier
30
+
31
+ if TYPE_CHECKING:
32
+ from pixeltable import exec, store
29
33
 
30
34
  _logger = logging.getLogger('pixeltable')
31
35
 
@@ -44,6 +48,41 @@ class TableVersion:
44
48
  have TableVersions reference those
45
49
  - mutable TableVersions record their TableVersionPath, which is needed for expr evaluation in updates
46
50
  """
51
+
52
+ id: UUID
53
+ name: str
54
+ version: int
55
+ comment: str
56
+ num_retained_versions: int
57
+ schema_version: int
58
+ view_md: Optional[schema.ViewMd]
59
+ is_snapshot: bool
60
+ effective_version: Optional[int]
61
+ path: Optional[pxt.catalog.TableVersionPath]
62
+ base: Optional[TableVersion]
63
+ next_col_id: int
64
+ next_idx_id: int
65
+ next_rowid: int
66
+ predicate: Optional[exprs.Expr]
67
+ mutable_views: list[TableVersion]
68
+ iterator_cls: Optional[type[ComponentIterator]]
69
+ iterator_args: Optional[exprs.InlineDict]
70
+ num_iterator_cols: int
71
+
72
+ # contains complete history of columns, incl dropped ones
73
+ cols: list[Column]
74
+ # contains only user-facing (named) columns visible in this version
75
+ cols_by_name: dict[str, Column]
76
+ # contains only columns visible in this version, both system and user
77
+ cols_by_id: dict[int, Column]
78
+ # needed for _create_tbl_md()
79
+ idx_md: dict[int, schema.IndexMd]
80
+ # contains only actively maintained indices
81
+ idxs_by_name: dict[str, TableVersion.IndexInfo]
82
+
83
+ external_stores: dict[str, pxt.io.ExternalStore]
84
+ store_tbl: 'store.StoreBase'
85
+
47
86
  @dataclasses.dataclass
48
87
  class IndexInfo:
49
88
  id: int
@@ -56,7 +95,7 @@ class TableVersion:
56
95
 
57
96
  def __init__(
58
97
  self, id: UUID, tbl_md: schema.TableMd, version: int, schema_version_md: schema.TableSchemaVersionMd,
59
- base: Optional[TableVersion] = None, base_path: Optional['pxt.catalog.TableVersionPath'] = None,
98
+ base: Optional[TableVersion] = None, base_path: Optional[pxt.catalog.TableVersionPath] = None,
60
99
  is_snapshot: Optional[bool] = None
61
100
  ):
62
101
  # only one of base and base_path can be non-None
@@ -95,36 +134,34 @@ class TableVersion:
95
134
  from pixeltable import exprs
96
135
  predicate_dict = None if not is_view or tbl_md.view_md.predicate is None else tbl_md.view_md.predicate
97
136
  self.predicate = exprs.Expr.from_dict(predicate_dict) if predicate_dict is not None else None
98
- self.mutable_views: List[TableVersion] = [] # targets for update propagation
137
+ self.mutable_views = [] # targets for update propagation
99
138
  if self.base is not None and not self.base.is_snapshot and not self.is_snapshot:
100
139
  self.base.mutable_views.append(self)
101
140
 
102
141
  # component view-specific initialization
103
- self.iterator_cls: Optional[Type[ComponentIterator]] = None
104
- self.iterator_args: Optional[exprs.InlineDict] = None
142
+ self.iterator_cls = None
143
+ self.iterator_args = None
105
144
  self.num_iterator_cols = 0
106
145
  if is_view and tbl_md.view_md.iterator_class_fqn is not None:
107
146
  module_name, class_name = tbl_md.view_md.iterator_class_fqn.rsplit('.', 1)
108
147
  module = importlib.import_module(module_name)
109
148
  self.iterator_cls = getattr(module, class_name)
110
- self.iterator_args = exprs.Expr.from_dict(tbl_md.view_md.iterator_args)
111
- assert isinstance(self.iterator_args, exprs.InlineDict)
149
+ self.iterator_args = exprs.InlineDict.from_dict(tbl_md.view_md.iterator_args)
112
150
  output_schema, _ = self.iterator_cls.output_schema(**self.iterator_args.to_dict())
113
151
  self.num_iterator_cols = len(output_schema)
114
152
  assert tbl_md.view_md.iterator_args is not None
115
153
 
116
154
  # register this table version now so that it's available when we're re-creating value exprs
117
- import pixeltable.catalog as catalog
118
- cat = catalog.Catalog.get()
155
+ cat = pxt.catalog.Catalog.get()
119
156
  cat.tbl_versions[(self.id, self.effective_version)] = self
120
157
 
121
158
  # init schema after we determined whether we're a component view, and before we create the store table
122
- self.cols: list[Column] = [] # contains complete history of columns, incl dropped ones
123
- self.cols_by_name: dict[str, Column] = {} # contains only user-facing (named) columns visible in this version
124
- self.cols_by_id: dict[int, Column] = {} # contains only columns visible in this version, both system and user
125
- self.idx_md = tbl_md.index_md # needed for _create_tbl_md()
126
- self.idxs_by_name: dict[str, TableVersion.IndexInfo] = {} # contains only actively maintained indices
127
- self.external_stores: dict[str, pxt.io.ExternalStore] = {}
159
+ self.cols = []
160
+ self.cols_by_name = {}
161
+ self.cols_by_id = {}
162
+ self.idx_md = tbl_md.index_md
163
+ self.idxs_by_name = {}
164
+ self.external_stores = {}
128
165
 
129
166
  self._init_schema(tbl_md, schema_version_md)
130
167
 
@@ -144,12 +181,12 @@ class TableVersion:
144
181
 
145
182
  @classmethod
146
183
  def create(
147
- cls, session: orm.Session, dir_id: UUID, name: str, cols: List[Column], num_retained_versions: int,
148
- comment: str, base_path: Optional['pxt.catalog.TableVersionPath'] = None,
184
+ cls, session: orm.Session, dir_id: UUID, name: str, cols: list[Column], num_retained_versions: int,
185
+ comment: str, base_path: Optional[pxt.catalog.TableVersionPath] = None,
149
186
  view_md: Optional[schema.ViewMd] = None
150
- ) -> Tuple[UUID, Optional[TableVersion]]:
187
+ ) -> tuple[UUID, Optional[TableVersion]]:
151
188
  # assign ids
152
- cols_by_name: Dict[str, Column] = {}
189
+ cols_by_name: dict[str, Column] = {}
153
190
  for pos, col in enumerate(cols):
154
191
  col.id = pos
155
192
  col.schema_version_add = 0
@@ -244,8 +281,6 @@ class TableVersion:
244
281
 
245
282
  def _init_cols(self, tbl_md: schema.TableMd, schema_version_md: schema.TableSchemaVersionMd) -> None:
246
283
  """Initialize self.cols with the columns visible in our effective version"""
247
- import pixeltable.exprs as exprs
248
-
249
284
  self.cols = []
250
285
  self.cols_by_name = {}
251
286
  self.cols_by_id = {}
@@ -305,13 +340,13 @@ class TableVersion:
305
340
  def _init_sa_schema(self) -> None:
306
341
  # create the sqlalchemy schema; do this after instantiating columns, in order to determine whether they
307
342
  # need to record errors
308
- from pixeltable.store import StoreBase, StoreTable, StoreView, StoreComponentView
343
+ from pixeltable.store import StoreComponentView, StoreTable, StoreView
309
344
  if self.is_component_view():
310
- self.store_tbl: StoreBase = StoreComponentView(self)
345
+ self.store_tbl = StoreComponentView(self)
311
346
  elif self.is_view():
312
- self.store_tbl: StoreBase = StoreView(self)
347
+ self.store_tbl = StoreView(self)
313
348
  else:
314
- self.store_tbl: StoreBase = StoreTable(self)
349
+ self.store_tbl = StoreTable(self)
315
350
 
316
351
  def _update_md(
317
352
  self, timestamp: float, conn: sql.engine.Connection, update_tbl_version: bool = True, preceding_schema_version: Optional[int] = None
@@ -488,7 +523,7 @@ class TableVersion:
488
523
  f'Cannot add non-nullable column "{col.name}" to table {self.name} with existing rows')
489
524
 
490
525
  num_excs = 0
491
- cols_with_excs: List[Column] = []
526
+ cols_with_excs: list[Column] = []
492
527
  for col in cols:
493
528
  col.schema_version_add = self.schema_version
494
529
  # add the column to the lookup structures now, rather than after the store changes executed successfully,
@@ -555,7 +590,7 @@ class TableVersion:
555
590
  with Env.get().engine.begin() as conn:
556
591
  # drop this column and all dependent index columns and indices
557
592
  dropped_cols = [col]
558
- dropped_idx_names: List[str] = []
593
+ dropped_idx_names: list[str] = []
559
594
  for idx_info in self.idxs_by_name.values():
560
595
  if idx_info.col != col:
561
596
  continue
@@ -661,7 +696,7 @@ class TableVersion:
661
696
  return self._insert(plan, conn, time.time(), print_stats)
662
697
 
663
698
  def _insert(
664
- self, exec_plan: exec.ExecNode, conn: sql.engine.Connection, timestamp: float, print_stats: bool = False,
699
+ self, exec_plan: 'exec.ExecNode', conn: sql.engine.Connection, timestamp: float, print_stats: bool = False,
665
700
  ) -> UpdateStatus:
666
701
  """Insert rows produced by exec_plan and propagate to views"""
667
702
  # we're creating a new version
@@ -692,7 +727,7 @@ class TableVersion:
692
727
  return result
693
728
 
694
729
  def update(
695
- self, value_spec: dict[str, Any], where: Optional['exprs.Expr'] = None, cascade: bool = True
730
+ self, value_spec: dict[str, Any], where: Optional[exprs.Expr] = None, cascade: bool = True
696
731
  ) -> UpdateStatus:
697
732
  """Update rows in this TableVersionPath.
698
733
  Args:
@@ -719,14 +754,15 @@ class TableVersion:
719
754
  plan, updated_cols, recomputed_cols = (
720
755
  Planner.create_update_plan(self.path, update_spec, [], where, cascade)
721
756
  )
757
+ from pixeltable.exprs import SqlElementCache
722
758
  result = self.propagate_update(
723
- plan, where.sql_expr() if where is not None else None, recomputed_cols,
759
+ plan, where.sql_expr(SqlElementCache()) if where is not None else None, recomputed_cols,
724
760
  base_versions=[], conn=conn, timestamp=time.time(), cascade=cascade, show_progress=True)
725
761
  result.updated_cols = updated_cols
726
762
  return result
727
763
 
728
764
  def batch_update(
729
- self, batch: list[dict[Column, 'exprs.Expr']], rowids: list[tuple[int, ...]], insert_if_not_exists: bool,
765
+ self, batch: list[dict[Column, exprs.Expr]], rowids: list[tuple[int, ...]], insert_if_not_exists: bool,
730
766
  error_if_not_exists: bool, cascade: bool = True,
731
767
  ) -> UpdateStatus:
732
768
  """Update rows in batch.
@@ -759,7 +795,7 @@ class TableVersion:
759
795
 
760
796
  def _validate_update_spec(
761
797
  self, value_spec: dict[str, Any], allow_pk: bool, allow_exprs: bool
762
- ) -> dict[Column, 'exprs.Expr']:
798
+ ) -> dict[Column, exprs.Expr]:
763
799
  update_targets: dict[Column, exprs.Expr] = {}
764
800
  for col_name, val in value_spec.items():
765
801
  if not isinstance(col_name, str):
@@ -782,7 +818,7 @@ class TableVersion:
782
818
  # make sure that the value is compatible with the column type
783
819
  try:
784
820
  # check if this is a literal
785
- value_expr = exprs.Literal(val, col_type=col.col_type)
821
+ value_expr: exprs.Expr = exprs.Literal(val, col_type=col.col_type)
786
822
  except TypeError:
787
823
  if not allow_exprs:
788
824
  raise excs.Error(
@@ -802,8 +838,8 @@ class TableVersion:
802
838
  return update_targets
803
839
 
804
840
  def propagate_update(
805
- self, plan: Optional[exec.ExecNode], where_clause: Optional[sql.ClauseElement],
806
- recomputed_view_cols: List[Column], base_versions: List[Optional[int]], conn: sql.engine.Connection,
841
+ self, plan: Optional[exec.ExecNode], where_clause: Optional[sql.ColumnElement],
842
+ recomputed_view_cols: list[Column], base_versions: list[Optional[int]], conn: sql.engine.Connection,
807
843
  timestamp: float, cascade: bool, show_progress: bool = True
808
844
  ) -> UpdateStatus:
809
845
  result = UpdateStatus()
@@ -822,7 +858,7 @@ class TableVersion:
822
858
  # propagate to views
823
859
  for view in self.mutable_views:
824
860
  recomputed_cols = [col for col in recomputed_view_cols if col.tbl is view]
825
- plan: Optional[exec.ExecNode] = None
861
+ plan = None
826
862
  if len(recomputed_cols) > 0:
827
863
  from pixeltable.plan import Planner
828
864
  plan = Planner.create_view_update_plan(view.path, recompute_targets=recomputed_cols)
@@ -835,7 +871,7 @@ class TableVersion:
835
871
  result.cols_with_excs = list(dict.fromkeys(result.cols_with_excs).keys()) # remove duplicates
836
872
  return result
837
873
 
838
- def delete(self, where: Optional['exprs.Expr'] = None) -> UpdateStatus:
874
+ def delete(self, where: Optional[exprs.Expr] = None) -> UpdateStatus:
839
875
  """Delete rows in this table.
840
876
  Args:
841
877
  where: a predicate to filter rows to delete.
@@ -843,6 +879,7 @@ class TableVersion:
843
879
  assert self.is_insertable()
844
880
  from pixeltable.exprs import Expr
845
881
  from pixeltable.plan import Planner
882
+ sql_where_clause: Optional[Expr] = None
846
883
  if where is not None:
847
884
  if not isinstance(where, Expr):
848
885
  raise excs.Error(f"'where' argument must be a predicate, got {type(where)}")
@@ -850,16 +887,16 @@ class TableVersion:
850
887
  # for now we require that the updated rows can be identified via SQL, rather than via a Python filter
851
888
  if analysis_info.filter is not None:
852
889
  raise excs.Error(f'Filter {analysis_info.filter} not expressible in SQL')
890
+ sql_where_clause = analysis_info.sql_where_clause
853
891
 
854
- analysis_info = Planner.analyze(self.path, where)
855
892
  with Env.get().engine.begin() as conn:
856
- num_rows = self.propagate_delete(analysis_info.sql_where_clause, base_versions=[], conn=conn, timestamp=time.time())
893
+ num_rows = self.propagate_delete(sql_where_clause, base_versions=[], conn=conn, timestamp=time.time())
857
894
 
858
895
  status = UpdateStatus(num_rows=num_rows)
859
896
  return status
860
897
 
861
898
  def propagate_delete(
862
- self, where: Optional['exprs.Expr'], base_versions: List[Optional[int]],
899
+ self, where: Optional[exprs.Expr], base_versions: list[Optional[int]],
863
900
  conn: sql.engine.Connection, timestamp: float) -> int:
864
901
  """Delete rows in this table and propagate to views.
865
902
  Args:
@@ -867,7 +904,7 @@ class TableVersion:
867
904
  Returns:
868
905
  number of deleted rows
869
906
  """
870
- sql_where_clause = where.sql_expr() if where is not None else None
907
+ sql_where_clause = where.sql_expr(exprs.SqlElementCache()) if where is not None else None
871
908
  num_rows = self.store_tbl.delete_rows(
872
909
  self.version + 1, base_versions=base_versions, match_on_vmin=False, where_clause=sql_where_clause,
873
910
  conn=conn)
@@ -926,7 +963,7 @@ class TableVersion:
926
963
  conn.execute(sql.delete(self.store_tbl.sa_tbl).where(self.store_tbl.sa_tbl.c.v_min == self.version))
927
964
 
928
965
  # revert new deletions
929
- set_clause = {self.store_tbl.sa_tbl.c.v_max: schema.Table.MAX_VERSION}
966
+ set_clause: dict[sql.Column, Any] = {self.store_tbl.sa_tbl.c.v_max: schema.Table.MAX_VERSION}
930
967
  for index_info in self.idxs_by_name.values():
931
968
  # copy the index value back from the undo column and reset the undo column to NULL
932
969
  set_clause[index_info.val_col.sa_col] = index_info.undo_col.sa_col
@@ -1050,27 +1087,27 @@ class TableVersion:
1050
1087
  return True
1051
1088
  return False
1052
1089
 
1053
- def user_columns(self) -> List[Column]:
1090
+ def user_columns(self) -> list[Column]:
1054
1091
  """Return all non-system columns"""
1055
1092
  return [c for c in self.cols if not self.is_system_column(c)]
1056
1093
 
1057
- def primary_key_columns(self) -> List[Column]:
1094
+ def primary_key_columns(self) -> list[Column]:
1058
1095
  """Return all non-system columns"""
1059
1096
  return [c for c in self.cols if c.is_pk]
1060
1097
 
1061
- def get_required_col_names(self) -> List[str]:
1098
+ def get_required_col_names(self) -> list[str]:
1062
1099
  """Return the names of all columns for which values must be specified in insert()"""
1063
1100
  assert not self.is_view()
1064
1101
  names = [c.name for c in self.cols_by_name.values() if not c.is_computed and not c.col_type.nullable]
1065
1102
  return names
1066
1103
 
1067
- def get_computed_col_names(self) -> List[str]:
1104
+ def get_computed_col_names(self) -> list[str]:
1068
1105
  """Return the names of all computed columns"""
1069
1106
  names = [c.name for c in self.cols_by_name.values() if c.is_computed]
1070
1107
  return names
1071
1108
 
1072
1109
  @classmethod
1073
- def _create_value_expr(cls, col: Column, path: 'pxt.catalog.TableVersionPath') -> None:
1110
+ def _create_value_expr(cls, col: Column, path: pxt.catalog.TableVersionPath) -> None:
1074
1111
  """
1075
1112
  Create col.value_expr, given col.compute_func.
1076
1113
  Interprets compute_func's parameters to be references to columns and construct ColumnRefs as args.
@@ -1080,7 +1117,7 @@ class TableVersion:
1080
1117
  assert col.compute_func is not None
1081
1118
  from pixeltable import exprs
1082
1119
  params = inspect.signature(col.compute_func).parameters
1083
- args: List[exprs.ColumnRef] = []
1120
+ args: list[exprs.ColumnRef] = []
1084
1121
  for param_name in params:
1085
1122
  param = path.get_column(param_name)
1086
1123
  if param is None:
@@ -1123,7 +1160,7 @@ class TableVersion:
1123
1160
  return 1
1124
1161
 
1125
1162
  @classmethod
1126
- def _create_column_md(cls, cols: List[Column]) -> dict[int, schema.ColumnMd]:
1163
+ def _create_column_md(cls, cols: list[Column]) -> dict[int, schema.ColumnMd]:
1127
1164
  column_md: dict[int, schema.ColumnMd] = {}
1128
1165
  for col in cols:
1129
1166
  value_expr_dict = col.value_expr.as_dict() if col.value_expr is not None else None
@@ -1134,7 +1171,7 @@ class TableVersion:
1134
1171
  return column_md
1135
1172
 
1136
1173
  @classmethod
1137
- def _create_stores_md(cls, stores: Iterable['pxt.io.ExternalStore']) -> list[dict[str, Any]]:
1174
+ def _create_stores_md(cls, stores: Iterable[pxt.io.ExternalStore]) -> list[dict[str, Any]]:
1138
1175
  return [
1139
1176
  {
1140
1177
  'class': f'{type(store).__module__}.{type(store).__qualname__}',
@@ -1154,7 +1191,7 @@ class TableVersion:
1154
1191
  return schema.TableVersionMd(created_at=timestamp, version=self.version, schema_version=self.schema_version)
1155
1192
 
1156
1193
  def _create_schema_version_md(self, preceding_schema_version: int) -> schema.TableSchemaVersionMd:
1157
- column_md: Dict[int, schema.SchemaColumn] = {}
1194
+ column_md: dict[int, schema.SchemaColumn] = {}
1158
1195
  for pos, col in enumerate(self.cols_by_name.values()):
1159
1196
  column_md[col.id] = schema.SchemaColumn(pos=pos, name=col.name)
1160
1197
  # preceding_schema_version to be set by the caller
@@ -1166,7 +1203,7 @@ class TableVersion:
1166
1203
  return {'id': str(self.id), 'effective_version': self.effective_version}
1167
1204
 
1168
1205
  @classmethod
1169
- def from_dict(cls, d: dict) -> 'TableVersion':
1206
+ def from_dict(cls, d: dict) -> TableVersion:
1170
1207
  import pixeltable.catalog as catalog
1171
1208
  id = UUID(d['id'])
1172
1209
  effective_version = d['effective_version']
@@ -4,9 +4,10 @@ import logging
4
4
  from typing import Optional, Union
5
5
  from uuid import UUID
6
6
 
7
- import pixeltable
7
+ import pixeltable as pxt
8
+ from pixeltable import exprs
9
+
8
10
  from .column import Column
9
- from .globals import _POS_COLUMN_NAME
10
11
  from .table_version import TableVersion
11
12
 
12
13
  _logger = logging.getLogger('pixeltable')
@@ -80,11 +81,9 @@ class TableVersionPath:
80
81
  return None
81
82
  return self.base.find_tbl_version(id)
82
83
 
83
- def __getattr__(self, col_name: str) -> 'pixeltable.exprs.ColumnRef':
84
+ def __getattr__(self, col_name: str) -> exprs.ColumnRef:
84
85
  """Return a ColumnRef for the given column name."""
85
- from pixeltable.exprs import ColumnRef, RowidRef
86
- if col_name == _POS_COLUMN_NAME and self.is_component_view():
87
- return RowidRef(self.tbl_version, self.tbl_version.store_tbl.pos_col_idx)
86
+ from pixeltable.exprs import ColumnRef
88
87
  if col_name not in self.tbl_version.cols_by_name:
89
88
  if self.base is None:
90
89
  raise AttributeError(f'Column {col_name} unknown')
@@ -92,14 +91,13 @@ class TableVersionPath:
92
91
  col = self.tbl_version.cols_by_name[col_name]
93
92
  return ColumnRef(col)
94
93
 
95
- def __getitem__(self, index: object) -> Union['pixeltable.exprs.ColumnRef', 'pixeltable.dataframe.DataFrame']:
94
+ def __getitem__(self, index: object) -> Union[exprs.ColumnRef, pxt.DataFrame]:
96
95
  """Return a ColumnRef for the given column name, or a DataFrame for the given slice.
97
96
  """
98
97
  if isinstance(index, str):
99
98
  # basically <tbl>.<colname>
100
99
  return self.__getattr__(index)
101
- from pixeltable.dataframe import DataFrame
102
- return DataFrame(self).__getitem__(index)
100
+ return pxt.DataFrame(self).__getitem__(index)
103
101
 
104
102
  def columns(self) -> list[Column]:
105
103
  """Return all user columns visible in this tbl version path, including columns from bases"""
@@ -9,6 +9,7 @@ import sqlalchemy.orm as orm
9
9
 
10
10
  import pixeltable.catalog as catalog
11
11
  import pixeltable.exceptions as excs
12
+ import pixeltable.exprs as exprs
12
13
  import pixeltable.func as func
13
14
  import pixeltable.metadata.schema as md_schema
14
15
  from pixeltable.env import Env
@@ -220,5 +221,5 @@ class View(Table):
220
221
  ) -> UpdateStatus:
221
222
  raise excs.Error(f'{self._display_name()} {self._name!r}: cannot insert into view')
222
223
 
223
- def delete(self, where: Optional['pixeltable.exprs.Expr'] = None) -> UpdateStatus:
224
+ def delete(self, where: Optional[exprs.Expr] = None) -> UpdateStatus:
224
225
  raise excs.Error(f'{self._display_name()} {self._name!r}: cannot delete from view')
pixeltable/dataframe.py CHANGED
@@ -279,7 +279,7 @@ class DataFrame:
279
279
  """
280
280
  plan = self._create_query_plan()
281
281
 
282
- def exec_plan(conn: sql.engine.Connection) -> Iterator[exec.DataRowBatch]:
282
+ def exec_plan(conn: sql.engine.Connection) -> Iterator[exprs.DataRow]:
283
283
  plan.ctx.set_conn(conn)
284
284
  plan.open()
285
285
  try: