Skip to content

Commit c12b7f6

Browse files
committed
Improve typing of Updates and Filters
1 parent c65af5c commit c12b7f6

File tree

1 file changed

+22
-13
lines changed

1 file changed

+22
-13
lines changed

mismo/types/_updates.py

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
from __future__ import annotations
22

3-
from typing import TYPE_CHECKING, Any, Iterable, Literal
3+
from typing import TYPE_CHECKING, Any, Callable, Iterable, Literal, Protocol
44

55
import ibis
66
from ibis.expr import datatypes as dt
77
from ibis.expr import types as ir
88

9-
from mismo import _util, joins
9+
from mismo import _typing, _util, joins
1010
from mismo.types._table_wrapper import TableWrapper
1111

1212
if TYPE_CHECKING:
@@ -17,7 +17,9 @@ class Filters:
1717
"""A simple namespace for filter functions."""
1818

1919
@staticmethod
20-
def all_different(subset: Iterable[str] | None = None):
20+
def all_different(
21+
subset: Iterable[str] | None = None, /
22+
) -> Callable[[ir.Table], Literal[True] | ir.BooleanValue]:
2123
"""
2224
Make a Updates filter function that gives rows where all columns are different.
2325
@@ -44,7 +46,7 @@ def all_different(subset: Iterable[str] | None = None):
4446
... ) # doctest: +SKIP
4547
""" # noqa: E501
4648

47-
def filter_func(table: ir.Table):
49+
def filter_func(table: ir.Table, /) -> ir.BooleanValue | Literal[True]:
4850
nonlocal subset
4951
if subset is None:
5052
u = Updates(table, check_schemas="lax")
@@ -56,7 +58,9 @@ def filter_func(table: ir.Table):
5658
return filter_func
5759

5860
@staticmethod
59-
def any_different(subset: Iterable[str] | None = None):
61+
def any_different(
62+
subset: Iterable[str] | None = None, /
63+
) -> Callable[[ir.Table], ir.BooleanValue | Literal[True]]:
6064
"""Make a Updates filter function that gives rows where any column is different.
6165
6266
Parameters
@@ -77,7 +81,7 @@ def any_different(subset: Iterable[str] | None = None):
7781
>>> u.filter(u.filters.any_different(["name", "age"])) # doctest: +SKIP
7882
"""
7983

80-
def filter_func(table: ir.Table):
84+
def filter_func(table: ir.Table, /) -> ir.BooleanValue | Literal[True]:
8185
nonlocal subset
8286
if subset is None:
8387
u = Updates(table, check_schemas="lax")
@@ -280,17 +284,17 @@ def after(self) -> ibis.Table:
280284
"""The table after the changes."""
281285
return self.select(**self.after_values())
282286

283-
def is_changed(self, column: str, /) -> ibis.ir.BooleanColumn:
287+
def is_changed(self, column: str, /) -> ibis.ir.BooleanValue:
284288
"""Is column.before different from column.after? Never returns NULL."""
285-
resolved_col = _util.bind_one(self._t, column)
289+
resolved_col: HasBeforeAfter = _util.bind_one(self._t, column)
286290
return is_changed(resolved_col)
287291

288-
def filter(self, *args, **kwargs):
292+
def filter(self, *args, **kwargs) -> _typing.Self:
289293
return self.__class__(
290294
self._t.filter(*args, **kwargs), check_schemas=self.check_schemas
291295
)
292296

293-
def cache(self):
297+
def cache(self) -> _typing.Self:
294298
return self.__class__(self._t.cache(), check_schemas=self.check_schemas)
295299

296300
def apply_to(
@@ -341,16 +345,21 @@ def apply_to(
341345
f"default value {already_there} already exist in the input table"
342346
)
343347

344-
t = t.mutate(defaults)
348+
t = t.mutate(defaults) # ty:ignore[invalid-argument-type]
345349

346350
t = t.select(self.after().columns)
347351
t = t.union(self.after(), distinct=False)
348352
return t
349353

350354

351-
def is_changed(val: ibis.Value, /) -> ibis.ir.BooleanColumn:
355+
class HasBeforeAfter(Protocol):
356+
before: ibis.Value
357+
after: ibis.Value
358+
359+
360+
def is_changed(val: HasBeforeAfter, /) -> ibis.ir.BooleanValue:
352361
"""Is val.before different from val.after? Never returns NULL."""
353362
return ibis.or_(
354-
(val.before != val.after).fill_null(False),
363+
(val.before != val.after).fill_null(False), # ty:ignore[invalid-argument-type]
355364
val.before.isnull() != val.after.isnull(),
356365
)

0 commit comments

Comments
 (0)