pixeltable 0.4.0rc3__py3-none-any.whl → 0.4.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pixeltable might be problematic. Click here for more details.

Files changed (52) hide show
  1. pixeltable/__init__.py +1 -1
  2. pixeltable/__version__.py +2 -2
  3. pixeltable/catalog/__init__.py +9 -1
  4. pixeltable/catalog/catalog.py +333 -99
  5. pixeltable/catalog/column.py +28 -26
  6. pixeltable/catalog/globals.py +12 -0
  7. pixeltable/catalog/insertable_table.py +8 -8
  8. pixeltable/catalog/schema_object.py +6 -0
  9. pixeltable/catalog/table.py +111 -116
  10. pixeltable/catalog/table_version.py +36 -50
  11. pixeltable/catalog/table_version_handle.py +4 -1
  12. pixeltable/catalog/table_version_path.py +28 -4
  13. pixeltable/catalog/view.py +10 -18
  14. pixeltable/config.py +4 -0
  15. pixeltable/dataframe.py +10 -9
  16. pixeltable/env.py +5 -11
  17. pixeltable/exceptions.py +6 -0
  18. pixeltable/exec/exec_node.py +2 -0
  19. pixeltable/exec/expr_eval/expr_eval_node.py +4 -4
  20. pixeltable/exec/sql_node.py +47 -30
  21. pixeltable/exprs/column_property_ref.py +2 -1
  22. pixeltable/exprs/column_ref.py +7 -6
  23. pixeltable/exprs/expr.py +4 -4
  24. pixeltable/func/__init__.py +1 -0
  25. pixeltable/func/mcp.py +74 -0
  26. pixeltable/func/query_template_function.py +4 -2
  27. pixeltable/func/tools.py +12 -2
  28. pixeltable/func/udf.py +2 -2
  29. pixeltable/functions/__init__.py +1 -0
  30. pixeltable/functions/groq.py +108 -0
  31. pixeltable/functions/huggingface.py +8 -6
  32. pixeltable/functions/mistralai.py +2 -13
  33. pixeltable/functions/openai.py +1 -6
  34. pixeltable/functions/replicate.py +2 -2
  35. pixeltable/functions/util.py +6 -1
  36. pixeltable/globals.py +0 -2
  37. pixeltable/io/external_store.py +2 -2
  38. pixeltable/io/label_studio.py +4 -4
  39. pixeltable/io/table_data_conduit.py +1 -1
  40. pixeltable/metadata/__init__.py +1 -1
  41. pixeltable/metadata/converters/convert_37.py +15 -0
  42. pixeltable/metadata/notes.py +1 -0
  43. pixeltable/metadata/schema.py +5 -0
  44. pixeltable/plan.py +37 -121
  45. pixeltable/share/packager.py +2 -2
  46. pixeltable/type_system.py +30 -0
  47. {pixeltable-0.4.0rc3.dist-info → pixeltable-0.4.1.dist-info}/METADATA +1 -1
  48. {pixeltable-0.4.0rc3.dist-info → pixeltable-0.4.1.dist-info}/RECORD +51 -49
  49. pixeltable/utils/sample.py +0 -25
  50. {pixeltable-0.4.0rc3.dist-info → pixeltable-0.4.1.dist-info}/LICENSE +0 -0
  51. {pixeltable-0.4.0rc3.dist-info → pixeltable-0.4.1.dist-info}/WHEEL +0 -0
  52. {pixeltable-0.4.0rc3.dist-info → pixeltable-0.4.1.dist-info}/entry_points.txt +0 -0
@@ -42,11 +42,9 @@ class Column:
42
42
  sa_errortype_col: Optional[sql.schema.Column]
43
43
  _value_expr: Optional[exprs.Expr]
44
44
  value_expr_dict: Optional[dict[str, Any]]
45
- dependent_cols: set[Column]
46
45
  # we store a TableVersion here, not a TableVersionHandle, because this column is owned by that TableVersion instance
47
46
  # (re-resolving it later to a different instance doesn't make sense)
48
47
  tbl: Optional[TableVersion]
49
- # tbl: Optional[TableVersionHandle]
50
48
 
51
49
  def __init__(
52
50
  self,
@@ -62,6 +60,7 @@ class Column:
62
60
  sa_col_type: Optional[sql.sqltypes.TypeEngine] = None,
63
61
  records_errors: Optional[bool] = None,
64
62
  value_expr_dict: Optional[dict[str, Any]] = None,
63
+ tbl: Optional[TableVersion] = None,
65
64
  ):
66
65
  """Column constructor.
67
66
 
@@ -86,6 +85,7 @@ class Column:
86
85
  if name is not None and not is_valid_identifier(name):
87
86
  raise excs.Error(f"Invalid column name: '{name}'")
88
87
  self.name = name
88
+ self.tbl = tbl
89
89
  if col_type is None and computed_with is None:
90
90
  raise excs.Error(f'Column `{name}`: col_type is required if computed_with is not specified')
91
91
 
@@ -94,6 +94,7 @@ class Column:
94
94
  if computed_with is not None:
95
95
  value_expr = exprs.Expr.from_object(computed_with)
96
96
  if value_expr is None:
97
+ # TODO: this shouldn't be a user-facing error
97
98
  raise excs.Error(
98
99
  f'Column {name}: computed_with needs to be a valid Pixeltable expression, '
99
100
  f'but it is a {type(computed_with)}'
@@ -101,13 +102,15 @@ class Column:
101
102
  else:
102
103
  self._value_expr = value_expr.copy()
103
104
  self.col_type = self._value_expr.col_type
105
+ if self._value_expr is not None and self.value_expr_dict is None:
106
+ self.value_expr_dict = self._value_expr.as_dict()
104
107
 
105
108
  if col_type is not None:
106
109
  self.col_type = col_type
107
110
  assert self.col_type is not None
108
111
 
109
112
  self.stored = stored
110
- self.dependent_cols = set() # cols with value_exprs that reference us; set by TableVersion
113
+ # self.dependent_cols = set() # cols with value_exprs that reference us; set by TableVersion
111
114
  self.id = col_id
112
115
  self.is_pk = is_pk
113
116
  self._media_validation = media_validation
@@ -124,36 +127,35 @@ class Column:
124
127
  self.sa_errormsg_col = None
125
128
  self.sa_errortype_col = None
126
129
 
127
- self.tbl = None # set by owning TableVersion
130
+ def init_value_expr(self) -> None:
131
+ from pixeltable import exprs
132
+
133
+ if self._value_expr is not None or self.value_expr_dict is None:
134
+ return
135
+ self._value_expr = exprs.Expr.from_dict(self.value_expr_dict)
136
+ self._value_expr.bind_rel_paths()
137
+ if not self._value_expr.is_valid:
138
+ message = (
139
+ dedent(
140
+ f"""
141
+ The computed column {self.name!r} in table {self.tbl.name!r} is no longer valid.
142
+ {{validation_error}}
143
+ You can continue to query existing data from this column, but evaluating it on new data will raise an error.
144
+ """ # noqa: E501
145
+ )
146
+ .strip()
147
+ .format(validation_error=self._value_expr.validation_error)
148
+ )
149
+ warnings.warn(message, category=excs.PixeltableWarning, stacklevel=2)
128
150
 
129
151
  @property
130
152
  def value_expr(self) -> Optional[exprs.Expr]:
131
- """Instantiate value_expr on-demand"""
132
- # TODO: instantiate expr in the c'tor and add an Expr.prepare() that can create additional state after the
133
- # catalog has been fully loaded; that way, we encounter bugs in the serialization/deserialization logic earlier
134
- if self.value_expr_dict is not None and self._value_expr is None:
135
- from pixeltable import exprs
136
-
137
- self._value_expr = exprs.Expr.from_dict(self.value_expr_dict)
138
- self._value_expr.bind_rel_paths()
139
- if not self._value_expr.is_valid:
140
- message = (
141
- dedent(
142
- f"""
143
- The computed column {self.name!r} in table {self.tbl.name!r} is no longer valid.
144
- {{validation_error}}
145
- You can continue to query existing data from this column, but evaluating it on new data will raise an error.
146
- """ # noqa: E501
147
- )
148
- .strip()
149
- .format(validation_error=self._value_expr.validation_error)
150
- )
151
- warnings.warn(message, category=excs.PixeltableWarning, stacklevel=2)
153
+ assert self.value_expr_dict is None or self._value_expr is not None
152
154
  return self._value_expr
153
155
 
154
156
  def set_value_expr(self, value_expr: exprs.Expr) -> None:
155
157
  self._value_expr = value_expr
156
- self.value_expr_dict = None
158
+ self.value_expr_dict = self._value_expr.as_dict()
157
159
 
158
160
  def check_value_expr(self) -> None:
159
161
  assert self._value_expr is not None
@@ -5,6 +5,7 @@ import enum
5
5
  import itertools
6
6
  import logging
7
7
  from typing import Optional
8
+ from uuid import UUID
8
9
 
9
10
  from typing_extensions import Self
10
11
 
@@ -21,6 +22,17 @@ _ROWID_COLUMN_NAME = '_rowid'
21
22
  _PREDEF_SYMBOLS: Optional[set[str]] = None
22
23
 
23
24
 
25
+ @dataclasses.dataclass(frozen=True)
26
+ class QColumnId:
27
+ """Qualified column id"""
28
+
29
+ tbl_id: UUID
30
+ col_id: int
31
+
32
+ # def __hash__(self) -> int:
33
+ # return hash((self.tbl_id, self.col_id))
34
+
35
+
24
36
  @dataclasses.dataclass
25
37
  class UpdateStatus:
26
38
  """
@@ -51,6 +51,7 @@ class InsertableTable(Table):
51
51
  def __init__(self, dir_id: UUID, tbl_version: TableVersionHandle):
52
52
  tbl_version_path = TableVersionPath(tbl_version)
53
53
  super().__init__(tbl_version.id, dir_id, tbl_version.get().name, tbl_version_path)
54
+ self._tbl_version = tbl_version
54
55
 
55
56
  @classmethod
56
57
  def _display_name(cls) -> str:
@@ -103,8 +104,8 @@ class InsertableTable(Table):
103
104
  Env.get().console_logger.info(f'Created table `{name}`.')
104
105
  return tbl
105
106
 
106
- def get_metadata(self) -> dict[str, Any]:
107
- md = super().get_metadata()
107
+ def _get_metadata(self) -> dict[str, Any]:
108
+ md = super()._get_metadata()
108
109
  md['is_view'] = False
109
110
  md['is_snapshot'] = False
110
111
  return md
@@ -141,7 +142,7 @@ class InsertableTable(Table):
141
142
  from pixeltable.catalog import Catalog
142
143
  from pixeltable.io.table_data_conduit import UnkTableDataConduit
143
144
 
144
- with Catalog.get().begin_xact(tbl_id=self._id, for_write=True):
145
+ with Catalog.get().begin_xact(tbl=self._tbl_version_path, for_write=True, lock_mutable_tree=True):
145
146
  table = self
146
147
  if source is None:
147
148
  source = [kwargs]
@@ -171,7 +172,7 @@ class InsertableTable(Table):
171
172
  from pixeltable.io.table_data_conduit import DFTableDataConduit
172
173
 
173
174
  status = pxt.UpdateStatus()
174
- with Catalog.get().begin_xact(tbl_id=self._id, for_write=True):
175
+ with Catalog.get().begin_xact(tbl=self._tbl_version_path, for_write=True, lock_mutable_tree=True):
175
176
  if isinstance(data_source, DFTableDataConduit):
176
177
  status += self._tbl_version.get().insert(
177
178
  rows=None, df=data_source.pxt_df, print_stats=print_stats, fail_on_exception=fail_on_exception
@@ -189,7 +190,7 @@ class InsertableTable(Table):
189
190
 
190
191
  def _validate_input_rows(self, rows: list[dict[str, Any]]) -> None:
191
192
  """Verify that the input rows match the table schema"""
192
- valid_col_names = set(self._schema.keys())
193
+ valid_col_names = set(self._get_schema().keys())
193
194
  reqd_col_names = set(self._tbl_version_path.tbl_version.get().get_required_col_names())
194
195
  computed_col_names = set(self._tbl_version_path.tbl_version.get().get_computed_col_names())
195
196
  for row in rows:
@@ -231,11 +232,10 @@ class InsertableTable(Table):
231
232
  """
232
233
  from pixeltable.catalog import Catalog
233
234
 
234
- with Catalog.get().begin_xact(tbl_id=self._id, for_write=True):
235
+ with Catalog.get().begin_xact(tbl=self._tbl_version_path, for_write=True, lock_mutable_tree=True):
235
236
  return self._tbl_version.get().delete(where=where)
236
237
 
237
- @property
238
- def _base_table(self) -> Optional['Table']:
238
+ def _get_base_table(self) -> Optional['Table']:
239
239
  return None
240
240
 
241
241
  @property
@@ -42,6 +42,12 @@ class SchemaObject:
42
42
 
43
43
  def get_metadata(self) -> dict[str, Any]:
44
44
  """Returns metadata associated with this schema object."""
45
+ from pixeltable.catalog import Catalog
46
+
47
+ with Catalog.get().begin_xact(for_write=False):
48
+ return self._get_metadata()
49
+
50
+ def _get_metadata(self) -> dict[str, Any]:
45
51
  return {'name': self._name, 'path': self._path()}
46
52
 
47
53
  @classmethod