Skip to content

Commit

Permalink
feat(api): improve repr for deferred expressions containing Column/Sc…
Browse files Browse the repository at this point in the history
…alar values
  • Loading branch information
jcrist committed Sep 27, 2023
1 parent 6b8f92b commit 6b1218a
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 6 deletions.
23 changes: 17 additions & 6 deletions ibis/expr/deferred.py
Expand Up @@ -32,6 +32,17 @@
}


def _repr(x: Any) -> str:
"""A helper for nicely repring deferred expressions."""
import ibis.expr.types as ir

if isinstance(x, ir.Column):
return f"<column[{x.type()}]>"
elif isinstance(x, ir.Scalar):
return f"<scalar[{x.type()}]>"
return repr(x)


class Deferred:
"""A deferred expression."""

Expand Down Expand Up @@ -184,7 +195,7 @@ def __init__(self, value: Any, attr: str) -> None:
self._attr = attr

def __repr__(self) -> str:
return f"{self._value!r}.{self._attr}"
return f"{_repr(self._value)}.{self._attr}"

def _resolve(self, param: Any) -> Any:
obj = _resolve(self._value, param)
Expand All @@ -201,7 +212,7 @@ def __init__(self, value: Any, key: Any) -> None:
self._key = key

def __repr__(self) -> str:
return f"{self._value!r}[{self._key!r}]"
return f"{_repr(self._value)}[{_repr(self._key)}]"

def _resolve(self, param: Any) -> Any:
obj = _resolve(self._value, param)
Expand All @@ -220,8 +231,8 @@ def __init__(self, func: Any, *args: Any, **kwargs: Any) -> None:
self._kwargs = kwargs

def __repr__(self) -> str:
params = [repr(a) for a in self._args]
params.extend(f"{k}={v!r}" for k, v in self._kwargs.items())
params = [_repr(a) for a in self._args]
params.extend(f"{k}={_repr(v)}" for k, v in self._kwargs.items())
# Repr directly wrapped functions as their name, fallback to repr for
# deferred objects or callables without __name__ otherwise
func = getattr(self._func, "__name__", "") or repr(self._func)
Expand All @@ -246,7 +257,7 @@ def __init__(self, symbol: str, left: Any, right: Any) -> None:
self._right = right

def __repr__(self) -> str:
return f"({self._left!r} {self._symbol} {self._right!r})"
return f"({_repr(self._left)} {self._symbol} {_repr(self._right)})"

def _resolve(self, param: Any) -> Any:
left = _resolve(self._left, param)
Expand All @@ -264,7 +275,7 @@ def __init__(self, symbol: str, value: Any) -> None:
self._value = value

def __repr__(self) -> str:
return f"{self._symbol}{self._value!r}"
return f"{self._symbol}{_repr(self._value)}"

def _resolve(self, param: Any) -> Any:
value = _resolve(self._value, param)
Expand Down
15 changes: 15 additions & 0 deletions ibis/expr/tests/test_deferred.py
Expand Up @@ -219,3 +219,18 @@ def f(a, b, c=3):

with pytest.raises(TypeError, match="unknown"):
f(_.a, _.b, unknown=3) # invalid calls caught at call time


@pytest.mark.parametrize(
"f, sol",
[
(lambda t: _.x + t.a, "(_.x + <column[int64]>)"),
(lambda t: _.x + t.a.sum(), "(_.x + <scalar[int64]>)"),
(lambda t: ibis.date(_.x, 2, t.a), "date(_.x, 2, <column[int64]>)"),
],
)
def test_repr_deferred_with_exprs(f, sol):
t = ibis.table({"a": "int64"})
expr = f(t)
res = repr(expr)
assert res == sol

0 comments on commit 6b1218a

Please sign in to comment.