diff --git a/ibis/expr/types/generic.py b/ibis/expr/types/generic.py index 4e4c62aa62183..1805ea22e48ed 100644 --- a/ibis/expr/types/generic.py +++ b/ibis/expr/types/generic.py @@ -3,8 +3,8 @@ from collections.abc import Iterable, Sequence from typing import TYPE_CHECKING, Any, Literal +import rich from public import public -from rich.table import Table as RichTable import ibis import ibis.common.exceptions as com @@ -13,6 +13,7 @@ from ibis.common.deferred import Deferred from ibis.common.grounds import Singleton from ibis.expr.types.core import Expr, _binop, _FixedTextJupyterMixin +from ibis.expr.types.pretty import to_rich_table from ibis.util import deprecated if TYPE_CHECKING: @@ -1294,9 +1295,9 @@ def __array__(self, dtype=None): return self.execute().__array__(dtype) def __interactive_rich_console__(self, console, options): - return console.render(self.to_rich(), options=options) + return console.render(to_rich_table(self), options=options) - def to_rich( + def preview( self, *, max_rows: int | None = None, @@ -1304,8 +1305,8 @@ def to_rich( max_string: int | None = None, max_depth: int | None = None, console_width: int | float | None = None, - ) -> RichTable: - """Convert to a Rich Table. + ) -> None: + """Print as a Rich Table. This is an explicit version of what you get when you inspect this object in interactive mode, except with this version you @@ -1342,18 +1343,15 @@ def to_rich( │ … │ └────────┘ """ - from ibis.expr.types.pretty import to_rich_table - - named = self.name(self.op().name) - projection = named.as_table() - return to_rich_table( - projection, + rt = to_rich_table( + self, max_rows=max_rows, max_length=max_length, max_string=max_string, max_depth=max_depth, console_width=console_width, ) + rich.print(rt) def __pyarrow_result__( self, table: pa.Table, data_mapper: type[PyArrowData] | None = None diff --git a/ibis/expr/types/pretty.py b/ibis/expr/types/pretty.py index a54590dab2658..232ceda56d5a8 100644 --- a/ibis/expr/types/pretty.py +++ b/ibis/expr/types/pretty.py @@ -4,18 +4,22 @@ import json from functools import singledispatch from math import isfinite +from typing import TYPE_CHECKING from urllib.parse import urlparse import rich from rich.align import Align from rich.console import Console -from rich.table import Table as RichTable from rich.text import Text import ibis import ibis.expr.datatypes as dt from ibis.common.exceptions import TranslationError -from ibis.expr.types import Table + +if TYPE_CHECKING: + from rich.table import Table as RichTable + + from ibis.expr.types import Column, Table def pretty_repr(expr: ibis.Expr) -> str: @@ -72,7 +76,7 @@ def _(dtype, values, **fmt_kwargs): @format_values.register(dt.GeoSpatial) -def _(dtype, values): +def _(dtype, values, **fmt_kwargs): import shapely return _format_nested([None if v is None else shapely.from_wkb(v) for v in values]) @@ -272,7 +276,7 @@ def format_dtype(dtype): def to_rich_table( - table: Table, + tablish: Table | Column, *, max_rows: int | None = None, max_columns: int | None = None, @@ -281,6 +285,8 @@ def to_rich_table( max_depth: int | None = None, console_width: int | float | None = None, ) -> RichTable: + from ibis.expr.types import Column, Table + if max_rows is None: max_rows = ibis.options.repr.interactive.max_rows if max_columns is None: @@ -289,6 +295,14 @@ def to_rich_table( console_width = float("inf") show_types = ibis.options.repr.interactive.show_types + if isinstance(tablish, Column): + named = tablish.name(tablish.op().name) + table = named.as_table() + elif isinstance(tablish, Table): + table = tablish + else: + raise TypeError(f"Expected Table or Column, got {type(tablish)}") + orig_ncols = len(table.columns) if console_width == float("inf"): diff --git a/ibis/expr/types/relations.py b/ibis/expr/types/relations.py index 492b4a54408a2..bc3229f97d538 100644 --- a/ibis/expr/types/relations.py +++ b/ibis/expr/types/relations.py @@ -10,6 +10,7 @@ from keyword import iskeyword from typing import TYPE_CHECKING, Callable, Literal +import rich import toolz from public import public @@ -22,6 +23,7 @@ from ibis.common.deferred import Deferred, Resolver from ibis.expr.types.core import Expr, _FixedTextJupyterMixin from ibis.expr.types.generic import literal +from ibis.expr.types.pretty import to_rich_table if TYPE_CHECKING: import pandas as pd @@ -366,7 +368,7 @@ def __interactive_rich_console__(self, console, options): width = options.max_width try: - table = self.to_rich(console_width=width) + rt = to_rich_table(self, console_width=width) except Exception as e: # In IPython exceptions inside of _repr_mimebundle_ are swallowed to # allow calling several display functions and choosing to display @@ -384,22 +386,19 @@ def __interactive_rich_console__(self, console, options): # This restriction is only present in IPython, not in other REPLs. console.print_exception() raise e - return console.render(table, options=options) + return console.render(rt, options=options) - return console.render(self.to_rich(console_width=width), options=options) - - def to_rich( + def preview( self, *, max_rows: int | None = None, max_columns: int | None = None, - show_types: bool | None = None, max_length: int | None = None, max_string: int | None = None, max_depth: int | None = None, console_width: int | float | None = None, - ) -> RichTable: - """Pretty-print a preview using rich. + ) -> None: + """Print as a Rich Table. This is an explicit version of what you get when you inspect this object in interactive mode, except with this version you @@ -412,8 +411,6 @@ def to_rich( Maximum number of rows to display max_columns Maximum number of columns to display - show_types - Whether to show column types in the 2nd row, under the column name max_length Maximum length for pretty-printed arrays and maps max_string @@ -434,12 +431,12 @@ def to_rich( >>> t.preview( ... max_rows=3, ... max_columns=3, - ... show_types=False, ... max_string=8, ... console_width=30, ... ) ┏━━━━━━━━━┳━━━━━━━━━━┳━━━┓ ┃ species ┃ island ┃ … ┃ + ┃ string ┃ string ┃ … ┃ ┡━━━━━━━━━╇━━━━━━━━━━╇━━━┩ │ Adelie │ Torgers… │ … │ │ Adelie │ Torgers… │ … │ @@ -447,18 +444,17 @@ def to_rich( │ … │ … │ … │ └─────────┴──────────┴───┘ """ - from ibis.expr.types.pretty import to_rich_table - return to_rich_table( + rt = to_rich_table( self, max_columns=max_columns, max_rows=max_rows, - show_types=show_types, max_length=max_length, max_string=max_string, max_depth=max_depth, console_width=console_width, ) + rich.print(rt) def __getitem__(self, what): """Select items from a table expression.