pixeltable 0.3.10__py3-none-any.whl → 0.3.12__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 (119) hide show
  1. pixeltable/__init__.py +2 -2
  2. pixeltable/__version__.py +2 -2
  3. pixeltable/catalog/__init__.py +2 -1
  4. pixeltable/catalog/catalog.py +370 -93
  5. pixeltable/catalog/column.py +6 -4
  6. pixeltable/catalog/dir.py +5 -5
  7. pixeltable/catalog/globals.py +14 -16
  8. pixeltable/catalog/insertable_table.py +6 -8
  9. pixeltable/catalog/path.py +14 -7
  10. pixeltable/catalog/table.py +72 -62
  11. pixeltable/catalog/table_version.py +137 -107
  12. pixeltable/catalog/table_version_handle.py +3 -0
  13. pixeltable/catalog/table_version_path.py +1 -1
  14. pixeltable/catalog/view.py +10 -14
  15. pixeltable/dataframe.py +5 -3
  16. pixeltable/env.py +108 -42
  17. pixeltable/exec/__init__.py +2 -0
  18. pixeltable/exec/aggregation_node.py +6 -8
  19. pixeltable/exec/cache_prefetch_node.py +4 -7
  20. pixeltable/exec/component_iteration_node.py +1 -3
  21. pixeltable/exec/data_row_batch.py +1 -2
  22. pixeltable/exec/exec_context.py +1 -1
  23. pixeltable/exec/exec_node.py +1 -2
  24. pixeltable/exec/expr_eval/__init__.py +2 -0
  25. pixeltable/exec/expr_eval/evaluators.py +137 -20
  26. pixeltable/exec/expr_eval/expr_eval_node.py +43 -64
  27. pixeltable/exec/expr_eval/globals.py +68 -7
  28. pixeltable/exec/expr_eval/schedulers.py +25 -23
  29. pixeltable/exec/in_memory_data_node.py +8 -6
  30. pixeltable/exec/row_update_node.py +3 -4
  31. pixeltable/exec/sql_node.py +16 -18
  32. pixeltable/exprs/__init__.py +1 -1
  33. pixeltable/exprs/column_property_ref.py +1 -1
  34. pixeltable/exprs/column_ref.py +3 -3
  35. pixeltable/exprs/compound_predicate.py +1 -1
  36. pixeltable/exprs/data_row.py +17 -1
  37. pixeltable/exprs/expr.py +12 -12
  38. pixeltable/exprs/function_call.py +34 -2
  39. pixeltable/exprs/json_mapper.py +95 -48
  40. pixeltable/exprs/json_path.py +4 -9
  41. pixeltable/exprs/method_ref.py +2 -2
  42. pixeltable/exprs/object_ref.py +2 -2
  43. pixeltable/exprs/row_builder.py +33 -6
  44. pixeltable/exprs/similarity_expr.py +1 -1
  45. pixeltable/exprs/sql_element_cache.py +1 -1
  46. pixeltable/exprs/string_op.py +2 -2
  47. pixeltable/ext/__init__.py +1 -1
  48. pixeltable/ext/functions/__init__.py +1 -1
  49. pixeltable/ext/functions/whisperx.py +1 -1
  50. pixeltable/ext/functions/yolox.py +1 -1
  51. pixeltable/func/__init__.py +1 -1
  52. pixeltable/func/aggregate_function.py +2 -2
  53. pixeltable/func/callable_function.py +3 -6
  54. pixeltable/func/expr_template_function.py +24 -4
  55. pixeltable/func/function.py +7 -9
  56. pixeltable/func/function_registry.py +1 -1
  57. pixeltable/func/query_template_function.py +87 -4
  58. pixeltable/func/signature.py +1 -1
  59. pixeltable/func/tools.py +1 -1
  60. pixeltable/func/udf.py +2 -2
  61. pixeltable/functions/__init__.py +1 -1
  62. pixeltable/functions/anthropic.py +2 -2
  63. pixeltable/functions/audio.py +1 -1
  64. pixeltable/functions/deepseek.py +1 -1
  65. pixeltable/functions/fireworks.py +1 -1
  66. pixeltable/functions/globals.py +6 -6
  67. pixeltable/functions/huggingface.py +1 -1
  68. pixeltable/functions/image.py +1 -1
  69. pixeltable/functions/json.py +1 -1
  70. pixeltable/functions/llama_cpp.py +1 -1
  71. pixeltable/functions/math.py +1 -1
  72. pixeltable/functions/mistralai.py +1 -1
  73. pixeltable/functions/ollama.py +1 -1
  74. pixeltable/functions/openai.py +2 -2
  75. pixeltable/functions/replicate.py +1 -1
  76. pixeltable/functions/string.py +1 -1
  77. pixeltable/functions/timestamp.py +1 -1
  78. pixeltable/functions/together.py +1 -1
  79. pixeltable/functions/util.py +1 -1
  80. pixeltable/functions/video.py +2 -2
  81. pixeltable/functions/vision.py +2 -2
  82. pixeltable/globals.py +7 -2
  83. pixeltable/index/embedding_index.py +12 -1
  84. pixeltable/io/__init__.py +5 -3
  85. pixeltable/io/fiftyone.py +6 -7
  86. pixeltable/io/label_studio.py +21 -20
  87. pixeltable/io/pandas.py +6 -5
  88. pixeltable/iterators/__init__.py +1 -1
  89. pixeltable/metadata/__init__.py +6 -4
  90. pixeltable/metadata/converters/convert_24.py +3 -3
  91. pixeltable/metadata/converters/convert_25.py +1 -1
  92. pixeltable/metadata/converters/convert_29.py +1 -1
  93. pixeltable/metadata/converters/convert_31.py +11 -0
  94. pixeltable/metadata/converters/convert_32.py +15 -0
  95. pixeltable/metadata/converters/convert_33.py +17 -0
  96. pixeltable/metadata/notes.py +3 -0
  97. pixeltable/metadata/schema.py +26 -1
  98. pixeltable/plan.py +2 -3
  99. pixeltable/share/packager.py +8 -24
  100. pixeltable/share/publish.py +20 -9
  101. pixeltable/store.py +9 -6
  102. pixeltable/type_system.py +19 -7
  103. pixeltable/utils/console_output.py +3 -2
  104. pixeltable/utils/coroutine.py +3 -3
  105. pixeltable/utils/dbms.py +66 -0
  106. pixeltable/utils/documents.py +61 -67
  107. pixeltable/utils/exception_handler.py +59 -0
  108. pixeltable/utils/filecache.py +1 -1
  109. pixeltable/utils/http_server.py +3 -2
  110. pixeltable/utils/pytorch.py +1 -1
  111. pixeltable/utils/sql.py +1 -1
  112. pixeltable-0.3.12.dist-info/METADATA +436 -0
  113. pixeltable-0.3.12.dist-info/RECORD +183 -0
  114. pixeltable/catalog/path_dict.py +0 -169
  115. pixeltable-0.3.10.dist-info/METADATA +0 -382
  116. pixeltable-0.3.10.dist-info/RECORD +0 -179
  117. {pixeltable-0.3.10.dist-info → pixeltable-0.3.12.dist-info}/LICENSE +0 -0
  118. {pixeltable-0.3.10.dist-info → pixeltable-0.3.12.dist-info}/WHEEL +0 -0
  119. {pixeltable-0.3.10.dist-info → pixeltable-0.3.12.dist-info}/entry_points.txt +0 -0
@@ -1,9 +1,10 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import inspect
4
- from typing import TYPE_CHECKING, Any, Callable, Optional, overload
4
+ from functools import reduce
5
+ from typing import TYPE_CHECKING, Any, Callable, Iterable, Optional, Union, overload
5
6
 
6
- from pixeltable import exprs, type_system as ts
7
+ from pixeltable import catalog, exceptions as excs, exprs, func, type_system as ts
7
8
 
8
9
  from .function import Function
9
10
  from .signature import Signature
@@ -17,6 +18,7 @@ class QueryTemplateFunction(Function):
17
18
 
18
19
  template_df: Optional['DataFrame']
19
20
  self_name: Optional[str]
21
+ _comment: Optional[str]
20
22
 
21
23
  @classmethod
22
24
  def create(
@@ -34,15 +36,21 @@ class QueryTemplateFunction(Function):
34
36
  assert isinstance(template_df, DataFrame)
35
37
  # we take params and return json
36
38
  sig = Signature(return_type=ts.JsonType(), parameters=params)
37
- return QueryTemplateFunction(template_df, sig, path=path, name=name)
39
+ return QueryTemplateFunction(template_df, sig, path=path, name=name, comment=inspect.getdoc(template_callable))
38
40
 
39
41
  def __init__(
40
- self, template_df: Optional['DataFrame'], sig: Signature, path: Optional[str] = None, name: Optional[str] = None
42
+ self,
43
+ template_df: Optional['DataFrame'],
44
+ sig: Signature,
45
+ path: Optional[str] = None,
46
+ name: Optional[str] = None,
47
+ comment: Optional[str] = None,
41
48
  ):
42
49
  assert sig is not None
43
50
  super().__init__([sig], self_path=path)
44
51
  self.self_name = name
45
52
  self.template_df = template_df
53
+ self._comment = comment
46
54
 
47
55
  def _update_as_overload_resolution(self, signature_idx: int) -> None:
48
56
  pass # only one signature supported for QueryTemplateFunction
@@ -74,6 +82,9 @@ class QueryTemplateFunction(Function):
74
82
  def name(self) -> str:
75
83
  return self.self_name
76
84
 
85
+ def comment(self) -> Optional[str]:
86
+ return self._comment
87
+
77
88
  def _as_dict(self) -> dict:
78
89
  return {'name': self.name, 'signature': self.signature.as_dict(), 'df': self.template_df.as_dict()}
79
90
 
@@ -112,3 +123,75 @@ def query(*args: Any, **kwargs: Any) -> Any:
112
123
  else:
113
124
  assert len(args) == 0 and len(kwargs) == 1 and 'param_types' in kwargs
114
125
  return lambda py_fn: make_query_template(py_fn, kwargs['param_types'])
126
+
127
+
128
+ def retrieval_udf(
129
+ table: catalog.Table,
130
+ name: Optional[str] = None,
131
+ description: Optional[str] = None,
132
+ parameters: Optional[Iterable[Union[str, exprs.ColumnRef]]] = None,
133
+ limit: Optional[int] = 10,
134
+ ) -> func.QueryTemplateFunction:
135
+ """
136
+ Constructs a retrieval UDF for the given table. The retrieval UDF is a UDF whose parameters are
137
+ columns of the table and whose return value is a list of rows from the table. The return value of
138
+ ```python
139
+ f(col1=x, col2=y, ...)
140
+ ```
141
+ will be a list of all rows from the table that match the specified arguments.
142
+
143
+ Args:
144
+ table: The table to use as the dataset for the retrieval tool.
145
+ name: The name of the tool. If not specified, then the name of the table will be used by default.
146
+ description: The description of the tool. If not specified, then a default description will be generated.
147
+ parameters: The columns of the table to use as parameters. If not specified, all data columns
148
+ (non-computed columns) will be used as parameters.
149
+
150
+ All of the specified parameters will be required parameters of the tool, regardless of their status
151
+ as columns.
152
+ limit: The maximum number of rows to return. If not specified, then all matching rows will be returned.
153
+
154
+ Returns:
155
+ A list of dictionaries containing data from the table, one per row that matches the input arguments.
156
+ If there are no matching rows, an empty list will be returned.
157
+ """
158
+ # Argument validation
159
+ col_refs: list[exprs.ColumnRef]
160
+ if parameters is None:
161
+ col_refs = [table[col_name] for col_name in table.columns if not table[col_name].col.is_computed]
162
+ else:
163
+ for param in parameters:
164
+ if isinstance(param, str) and param not in table.columns:
165
+ raise excs.Error(f'The specified parameter {param!r} is not a column of the table {table._path!r}')
166
+ col_refs = [table[param] if isinstance(param, str) else param for param in parameters]
167
+
168
+ if len(col_refs) == 0:
169
+ raise excs.Error('Parameter list cannot be empty.')
170
+
171
+ # Construct the dataframe
172
+ predicates = [col_ref == exprs.Variable(col_ref.col.name, col_ref.col.col_type) for col_ref in col_refs]
173
+ where_clause = reduce(lambda c1, c2: c1 & c2, predicates)
174
+ df = table.select().where(where_clause)
175
+ if limit is not None:
176
+ df = df.limit(limit)
177
+
178
+ # Construct the signature
179
+ query_params = [
180
+ func.Parameter(col_ref.col.name, col_ref.col.col_type, inspect.Parameter.POSITIONAL_OR_KEYWORD)
181
+ for col_ref in col_refs
182
+ ]
183
+ query_signature = func.Signature(return_type=ts.JsonType(), parameters=query_params)
184
+
185
+ # Construct a name and/or description if not provided
186
+ if name is None:
187
+ name = table._name
188
+ if description is None:
189
+ description = (
190
+ f'Retrieves an entry from the dataset {name!r} that matches the given parameters.\n\nParameters:\n'
191
+ )
192
+ description += '\n'.join(
193
+ [f' {col_ref.col.name}: of type `{col_ref.col.col_type._to_base_str()}`' for col_ref in col_refs]
194
+ )
195
+
196
+ fn = func.QueryTemplateFunction(df, query_signature, name=name, comment=description)
197
+ return fn
@@ -253,7 +253,7 @@ class Signature:
253
253
  continue # skip 'self' or 'cls' parameter
254
254
  if param.name in cls.SPECIAL_PARAM_NAMES:
255
255
  raise excs.Error(f'{param.name!r} is a reserved parameter name')
256
- if param.kind in {inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD}:
256
+ if param.kind in (inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD):
257
257
  parameters.append(Parameter(param.name, col_type=None, kind=param.kind))
258
258
  continue
259
259
 
pixeltable/func/tools.py CHANGED
@@ -39,7 +39,7 @@ class Tool(pydantic.BaseModel):
39
39
  def ser_model(self) -> dict[str, Any]:
40
40
  return {
41
41
  'name': self.name or self.fn.name,
42
- 'description': self.description or self.fn._docstring(),
42
+ 'description': self.description or self.fn.comment(),
43
43
  'parameters': {
44
44
  'type': 'object',
45
45
  'properties': {param.name: param.col_type._to_json_schema() for param in self.parameters.values()},
pixeltable/func/udf.py CHANGED
@@ -43,7 +43,7 @@ def udf(
43
43
  ) -> ExprTemplateFunction: ...
44
44
 
45
45
 
46
- def udf(*args, **kwargs):
46
+ def udf(*args, **kwargs): # type: ignore[no-untyped-def]
47
47
  """A decorator to create a Function from a function definition.
48
48
 
49
49
  Examples:
@@ -79,7 +79,7 @@ def udf(*args, **kwargs):
79
79
  if len(args) > 0:
80
80
  raise excs.Error('Unexpected @udf decorator arguments.')
81
81
 
82
- def decorator(decorated_fn: Callable):
82
+ def decorator(decorated_fn: Callable) -> CallableFunction:
83
83
  return make_function(
84
84
  decorated_fn,
85
85
  batch_size=batch_size,
@@ -29,5 +29,5 @@ from .globals import count, map, max, mean, min, sum
29
29
  __all__ = local_public_names(__name__, exclude=['globals']) + local_public_names(globals.__name__)
30
30
 
31
31
 
32
- def __dir__():
32
+ def __dir__() -> list[str]:
33
33
  return __all__
@@ -39,7 +39,7 @@ def _anthropic_client() -> 'anthropic.AsyncAnthropic':
39
39
 
40
40
 
41
41
  class AnthropicRateLimitsInfo(env.RateLimitsInfo):
42
- def __init__(self):
42
+ def __init__(self) -> None:
43
43
  super().__init__(self._get_request_resources)
44
44
 
45
45
  def _get_request_resources(self, messages: dict, max_tokens: int) -> dict[str, int]:
@@ -236,5 +236,5 @@ def _opt(arg: _T) -> Union[_T, 'anthropic.NotGiven']:
236
236
  __all__ = local_public_names(__name__)
237
237
 
238
238
 
239
- def __dir__():
239
+ def __dir__() -> list[str]:
240
240
  return __all__
@@ -26,5 +26,5 @@ def get_metadata(audio: pxt.Audio) -> dict:
26
26
  __all__ = local_public_names(__name__)
27
27
 
28
28
 
29
- def __dir__():
29
+ def __dir__() -> list[str]:
30
30
  return __all__
@@ -117,5 +117,5 @@ async def chat_completions(
117
117
  __all__ = local_public_names(__name__)
118
118
 
119
119
 
120
- def __dir__():
120
+ def __dir__() -> list[str]:
121
121
  return __all__
@@ -131,5 +131,5 @@ async def chat_completions(
131
131
  __all__ = local_public_names(__name__)
132
132
 
133
133
 
134
- def __dir__():
134
+ def __dir__() -> list[str]:
135
135
  return __all__
@@ -23,7 +23,7 @@ T = typing.TypeVar('T')
23
23
  class sum(func.Aggregator, typing.Generic[T]):
24
24
  """Sums the selected integers or floats."""
25
25
 
26
- def __init__(self):
26
+ def __init__(self) -> None:
27
27
  self.sum: T = None
28
28
 
29
29
  def update(self, val: T) -> None:
@@ -67,7 +67,7 @@ def _(val: sql.ColumnElement) -> Optional[sql.ColumnElement]:
67
67
  ),
68
68
  )
69
69
  class count(func.Aggregator, typing.Generic[T]):
70
- def __init__(self):
70
+ def __init__(self) -> None:
71
71
  self.count = 0
72
72
 
73
73
  def update(self, val: T) -> None:
@@ -88,7 +88,7 @@ def _(val: sql.ColumnElement) -> Optional[sql.ColumnElement]:
88
88
  type_substitutions=tuple({T: Optional[t]} for t in (str, int, float, bool, ts.Timestamp)), # type: ignore[misc]
89
89
  )
90
90
  class min(func.Aggregator, typing.Generic[T]):
91
- def __init__(self):
91
+ def __init__(self) -> None:
92
92
  self.val: T = None
93
93
 
94
94
  def update(self, val: T) -> None:
@@ -118,7 +118,7 @@ def _(val: sql.ColumnElement) -> Optional[sql.ColumnElement]:
118
118
  type_substitutions=tuple({T: Optional[t]} for t in (str, int, float, bool, ts.Timestamp)), # type: ignore[misc]
119
119
  )
120
120
  class max(func.Aggregator, typing.Generic[T]):
121
- def __init__(self):
121
+ def __init__(self) -> None:
122
122
  self.val: T = None
123
123
 
124
124
  def update(self, val: T) -> None:
@@ -143,7 +143,7 @@ def _(val: sql.ColumnElement) -> Optional[sql.ColumnElement]:
143
143
 
144
144
  @func.uda(type_substitutions=({T: Optional[int]}, {T: Optional[float]})) # type: ignore[misc]
145
145
  class mean(func.Aggregator, typing.Generic[T]):
146
- def __init__(self):
146
+ def __init__(self) -> None:
147
147
  self.sum: T = None
148
148
  self.count = 0
149
149
 
@@ -182,5 +182,5 @@ def map(expr: exprs.Expr, fn: Callable[[exprs.Expr], Any]) -> exprs.Expr:
182
182
  __all__ = local_public_names(__name__)
183
183
 
184
184
 
185
- def __dir__():
185
+ def __dir__() -> list[str]:
186
186
  return __all__
@@ -493,5 +493,5 @@ _processor_cache: dict[tuple[str, Callable], Any] = {}
493
493
  __all__ = local_public_names(__name__)
494
494
 
495
495
 
496
- def __dir__():
496
+ def __dir__() -> list[str]:
497
497
  return __all__
@@ -426,5 +426,5 @@ def mode(self: PIL.Image.Image) -> str:
426
426
  __all__ = local_public_names(__name__)
427
427
 
428
428
 
429
- def __dir__():
429
+ def __dir__() -> list[str]:
430
430
  return __all__
@@ -37,5 +37,5 @@ class make_list(pxt.Aggregator):
37
37
  __all__ = local_public_names(__name__)
38
38
 
39
39
 
40
- def __dir__():
40
+ def __dir__() -> list[str]:
41
41
  return __all__
@@ -100,5 +100,5 @@ _IS_GPU_AVAILABLE: Optional[bool] = None
100
100
  __all__ = local_public_names(__name__)
101
101
 
102
102
 
103
- def __dir__():
103
+ def __dir__() -> list[str]:
104
104
  return __all__
@@ -63,5 +63,5 @@ def _(self: sql.ColumnElement, digits: Optional[sql.ColumnElement] = None) -> sq
63
63
  __all__ = local_public_names(__name__)
64
64
 
65
65
 
66
- def __dir__():
66
+ def __dir__() -> list[str]:
67
67
  return __all__
@@ -193,5 +193,5 @@ def _opt(arg: Optional[_T]) -> Union[_T, 'mistralai.types.basemodel.Unset']:
193
193
  __all__ = local_public_names(__name__)
194
194
 
195
195
 
196
- def __dir__():
196
+ def __dir__() -> list[str]:
197
197
  return __all__
@@ -129,5 +129,5 @@ def embed(
129
129
  __all__ = local_public_names(__name__)
130
130
 
131
131
 
132
- def __dir__():
132
+ def __dir__() -> list[str]:
133
133
  return __all__
@@ -122,7 +122,7 @@ class OpenAIRateLimitsInfo(env.RateLimitsInfo):
122
122
  _header_duration_pattern = re.compile(r'(?:(\d+)d)?(?:(\d+)h)?(?:(\d+)ms)|(?:(\d+)m)?(?:([\d.]+)s)?')
123
123
 
124
124
 
125
- def _parse_header_duration(duration_str):
125
+ def _parse_header_duration(duration_str: str) -> datetime.timedelta:
126
126
  match = _header_duration_pattern.match(duration_str)
127
127
  if not match:
128
128
  raise ValueError('Invalid duration format')
@@ -837,5 +837,5 @@ def _opt(arg: _T) -> Union[_T, 'openai.NotGiven']:
837
837
  __all__ = local_public_names(__name__)
838
838
 
839
839
 
840
- def __dir__():
840
+ def __dir__() -> list[str]:
841
841
  return __all__
@@ -69,5 +69,5 @@ async def run(input: dict[str, Any], *, ref: str) -> dict[str, Any]:
69
69
  __all__ = local_public_names(__name__)
70
70
 
71
71
 
72
- def __dir__():
72
+ def __dir__() -> list[str]:
73
73
  return __all__
@@ -675,5 +675,5 @@ def zfill(self: str, width: int) -> str:
675
675
  __all__ = local_public_names(__name__)
676
676
 
677
677
 
678
- def __dir__():
678
+ def __dir__() -> list[str]:
679
679
  return __all__
@@ -312,5 +312,5 @@ def posix_timestamp(self: datetime) -> float:
312
312
  __all__ = local_public_names(__name__)
313
313
 
314
314
 
315
- def __dir__():
315
+ def __dir__() -> list[str]:
316
316
  return __all__
@@ -298,5 +298,5 @@ async def image_generations(
298
298
  __all__ = local_public_names(__name__)
299
299
 
300
300
 
301
- def __dir__():
301
+ def __dir__() -> list[str]:
302
302
  return __all__
@@ -21,7 +21,7 @@ def normalize_image_mode(image: PIL.Image.Image) -> PIL.Image.Image:
21
21
  Converts grayscale images to 3-channel for compatibility with models that only work with
22
22
  multichannel input.
23
23
  """
24
- if image.mode in {'1', 'L'}:
24
+ if image.mode in ('1', 'L'):
25
25
  return image.convert('RGB')
26
26
  if image.mode == 'LA':
27
27
  return image.convert('RGBA')
@@ -143,7 +143,7 @@ def _get_metadata(path: str) -> dict:
143
143
 
144
144
 
145
145
  def __get_stream_metadata(stream: av.stream.Stream) -> dict:
146
- if stream.type not in {'audio', 'video'}:
146
+ if stream.type not in ('audio', 'video'):
147
147
  return {'type': stream.type} # Currently unsupported
148
148
 
149
149
  codec_context = stream.codec_context
@@ -190,5 +190,5 @@ def __get_stream_metadata(stream: av.stream.Stream) -> dict:
190
190
  __all__ = local_public_names(__name__)
191
191
 
192
192
 
193
- def __dir__():
193
+ def __dir__() -> list[str]:
194
194
  return __all__
@@ -238,7 +238,7 @@ class mean_ap(pxt.Aggregator):
238
238
  - A `dict[int, float]` mapping each label class to an average precision (AP) value for that class.
239
239
  """
240
240
 
241
- def __init__(self):
241
+ def __init__(self) -> None:
242
242
  self.class_tpfp: dict[int, list[dict]] = defaultdict(list)
243
243
 
244
244
  def update(self, eval_dicts: list[dict]) -> None:
@@ -394,5 +394,5 @@ def draw_bounding_boxes(
394
394
  __all__ = local_public_names(__name__)
395
395
 
396
396
 
397
- def __dir__():
397
+ def __dir__() -> list[str]:
398
398
  return __all__
pixeltable/globals.py CHANGED
@@ -616,9 +616,14 @@ def _extract_paths(
616
616
  matches = [name for name, entry in dir_entries.items() if entry.dir is not None]
617
617
  else:
618
618
  matches = [name for name, entry in dir_entries.items() if entry.table is not None]
619
+
620
+ # Filter out system paths
621
+ matches = [name for name in matches if catalog.is_valid_identifier(name)]
619
622
  result = [parent.append(name) for name in matches]
620
- for name, entry in [(name, entry) for name, entry in dir_entries.items() if len(entry.dir_entries) > 0]:
621
- result.extend(_extract_paths(entry.dir_entries, parent=parent.append(name), entry_type=entry_type))
623
+
624
+ for name, entry in dir_entries.items():
625
+ if len(entry.dir_entries) > 0 and catalog.is_valid_identifier(name):
626
+ result.extend(_extract_paths(entry.dir_entries, parent=parent.append(name), entry_type=entry_type))
622
627
  return result
623
628
 
624
629
 
@@ -208,7 +208,18 @@ class EmbeddingIndex(IndexBase):
208
208
  and len(sig.required_parameters) <= 1
209
209
  and sig.parameters_by_pos[0].col_type.type_enum == expected_type
210
210
  ):
211
- return resolved_fn
211
+ # We found a valid signature. Now, if it has more than one parameter, we need to transform it into a
212
+ # 1-ary function by fixing all the other parameters to their defaults. This is to ensure that
213
+ # conditional_return_type resolves correctly.
214
+ if len(sig.parameters) == 1:
215
+ unary_fn = resolved_fn
216
+ else:
217
+ assert all(sig.parameters_by_pos[i].has_default for i in range(1, len(sig.parameters)))
218
+ defaults = {param.name: param.default for param in sig.parameters_by_pos[1:]}
219
+ unary_fn = resolved_fn.using(**defaults)
220
+ assert not unary_fn.is_polymorphic
221
+ assert len(unary_fn.signature.parameters) == 1
222
+ return unary_fn
212
223
  return None
213
224
 
214
225
  @classmethod
pixeltable/io/__init__.py CHANGED
@@ -1,3 +1,5 @@
1
+ # ruff: noqa: F401
2
+
1
3
  from .datarows import import_json, import_rows
2
4
  from .external_store import ExternalStore, SyncStatus
3
5
  from .globals import create_label_studio_project, export_images_as_fo_dataset
@@ -5,10 +7,10 @@ from .hf_datasets import import_huggingface_dataset
5
7
  from .pandas import import_csv, import_excel, import_pandas
6
8
  from .parquet import export_parquet, import_parquet
7
9
 
8
- __default_dir = set(symbol for symbol in dir() if not symbol.startswith('_'))
10
+ __default_dir = {symbol for symbol in dir() if not symbol.startswith('_')}
9
11
  __removed_symbols = {'globals', 'hf_datasets', 'pandas', 'parquet', 'datarows'}
10
- __all__ = sorted(list(__default_dir - __removed_symbols))
12
+ __all__ = sorted(__default_dir - __removed_symbols)
11
13
 
12
14
 
13
- def __dir__():
15
+ def __dir__() -> list[str]:
14
16
  return __all__
pixeltable/io/fiftyone.py CHANGED
@@ -1,5 +1,5 @@
1
1
  import os
2
- from typing import Iterator, Optional, Union
2
+ from typing import Any, Iterator, Optional, Union
3
3
 
4
4
  import fiftyone as fo # type: ignore[import-untyped]
5
5
  import fiftyone.utils.data as foud # type: ignore[import-untyped]
@@ -59,10 +59,9 @@ class PxtImageDatasetImporter(foud.LabeledImageDatasetImporter):
59
59
  for exprs_, label_cls, default_name in label_categories:
60
60
  if exprs_ is None or isinstance(exprs_, dict):
61
61
  continue
62
- if isinstance(exprs_, exprs.Expr):
63
- exprs_ = [exprs_]
64
- assert isinstance(exprs_, list)
65
- for expr in exprs_:
62
+ exprs_list = [exprs_] if isinstance(exprs_, exprs.Expr) else exprs_
63
+ assert isinstance(exprs_list, list)
64
+ for expr in exprs_list:
66
65
  if default_name not in self.__labels:
67
66
  name = default_name
68
67
  else:
@@ -125,7 +124,7 @@ class PxtImageDatasetImporter(foud.LabeledImageDatasetImporter):
125
124
  elif label_cls is fo.Detections:
126
125
  label = fo.Detections(detections=self.__as_fo_detections(label_data))
127
126
  else:
128
- assert False
127
+ raise AssertionError()
129
128
  labels[label_name] = label
130
129
 
131
130
  return file, metadata, labels
@@ -166,5 +165,5 @@ class PxtImageDatasetImporter(foud.LabeledImageDatasetImporter):
166
165
  def get_dataset_info(self) -> dict:
167
166
  pass
168
167
 
169
- def close(self, *args) -> None:
168
+ def close(self, *args: Any) -> None:
170
169
  pass