diff --git a/ibis/expr/deferred.py b/ibis/expr/deferred.py index 653d505d3d7a..14d3dc2503aa 100644 --- a/ibis/expr/deferred.py +++ b/ibis/expr/deferred.py @@ -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"" + elif isinstance(x, ir.Scalar): + return f"" + return repr(x) + + class Deferred: """A deferred expression.""" @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) diff --git a/ibis/expr/tests/test_deferred.py b/ibis/expr/tests/test_deferred.py index f11181692109..f8006f97137b 100644 --- a/ibis/expr/tests/test_deferred.py +++ b/ibis/expr/tests/test_deferred.py @@ -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 + )"), + (lambda t: _.x + t.a.sum(), "(_.x + )"), + (lambda t: ibis.date(_.x, 2, t.a), "date(_.x, 2, )"), + ], +) +def test_repr_deferred_with_exprs(f, sol): + t = ibis.table({"a": "int64"}) + expr = f(t) + res = repr(expr) + assert res == sol