-
Notifications
You must be signed in to change notification settings - Fork 603
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(ux): add Table and Column.preview() #7915
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, modulo removal of the show_types
argument and getting CI to pass.
@NickCrews Regarding returning versus printing, I vote for printing. It seems quite inconvenient to have to write Are there any places where automatically calling |
I agree I want to avoid the print() I personally have no use for getting a rich table, but I could see someone else wanting a .to_rich() method? Could add that as another public method that just returns a rich table (and does no shortening with .head()). Then preview could be (EDIT: this won't work because when we make the rich table we need to know if the rows have been cut off, so we can add ellipses if so. So we need to pass the whole table to the function that makes the rich table) if max_rows is None:
max_rows = ibis.options.etc
head = t.head(max_rows)
rich_table = head.to_rich(max_len, max_depth, etc)
print(rich_table) |
8c594f9
to
a5bcefa
Compare
a5bcefa
to
9528f2d
Compare
Can you make |
yeah, easy enough to expose/figure it out later if you get a feature request, but hard to take back :) |
a87d8c4
to
d12c246
Compare
OK, not sure why the widths of the tables are changing in the doctests, I don't see what is different. But I can dig into that once the other questions I have are addressed. |
a13c572
to
a0d2d09
Compare
for myself: can repro the doctest failure with @cpcloud so now the only test failing are the doctests. I'm not sure exactly what is causing the change in behavior there. Want me/us to track that down and keep the behavior consistent? Or just update the docstrings to the new behavior? I sort of like the new behavior more (it leads to being more compact) I also need to add tests for the actual .preview method, but let's get the implementation settled to avoid churn with me rewriting the test. |
a0d2d09
to
6e1c8e7
Compare
OK the failing doctests are only for nested datatypes. There is some conditional logic inside if show_types and not isinstance(dtype, (dt.Struct, dt.Map, dt.Array)):
# Don't truncate non-nested dtypes
min_width = max(min_width, len(dtype_str)) investigating this now |
no, that's not it. On on this branch, Looking into this more |
5829c1e
to
b33b8d9
Compare
OK, there was an inconsistency between the |
4879a92
to
a0b2852
Compare
@@ -219,21 +262,76 @@ def isnull(x): | |||
return out, min_width, max_width | |||
|
|||
|
|||
def format_dtype(dtype): | |||
max_string = ibis.options.repr.interactive.max_string | |||
def format_dtype(dtype, max_string: int) -> Text: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a small change. Before, the passed in max_string was ignored, and we only used the one in options.repr.interactive.
So t.island.preview(max_string=5)
now gives:
┏━━━━━━━━┓
┃ island ┃
┡━━━━━━━━┩
│ stri… │
├────────┤
│ Torg… │
│ Torg… │
│ Torg… │
│ … │
└────────┘
without this, you get the full string
I think this is better, especially when you have a really long dtype from some complex nested dtype. Here it's a bit silly.
@cpcloud OK now I got this all fixed up! Can you review this now? The implementation has changed decently since the last time you looked. This is doing both a refactor and a new feature at the same time. If this is too much, I can go through and split this into two commits, first the refactor and then the feature. |
ibis/expr/types/pretty.py
Outdated
def _format_nested(values): | ||
interactive = ibis.options.repr.interactive | ||
|
||
def pretty_repr(expr: ibis.Expr) -> str: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function feels similar to __interactive_rich_console__
, in a followup they might want to get unified.
@cpcloud sorry to bug you, could this get a review? I can fix the rebase error once I get a +1 on the general approach |
@lostmygithubaccount could you consider adding this to the 9.0 milestone so it doesn't get forgotten about? It looks like this has gotten lost in phillip's inbox since this is now on page 2 of the PRs :) |
@NickCrews I haven't forgotten :) We'll definitely get to it for 9.0, I can't promise anything this week though :) |
@cpcloud is this still targeted for 9.0.0? It's not added to that milestone and I'm worried it will get left behind |
@NickCrews I just DM'd you on Zulip, was hoping I could pair with you on this to get it over the finish line. |
d3d50b8
to
9ef131f
Compare
@cpcloud what do you want to do about this failing doctest? Basically,
|
I think option A until we know more about how people are going to use it. |
9ef131f
to
7452fc9
Compare
- unifies __interactive_rich_console__() from Scalar, Column, and Relation into the parent Expr's __rich_console__(). This calls to_rich(), which is reposnsible for turning an Expr into a rich object. Now all implementations have the console.is_jupyter checks, before only the Table did. - propagates repr options downward through all the formatters in pretty.py, so you can pass hardcoded options instead of pulling from ibis.options.repr.interactive - moves the check for ibis.options.repr.show_variables inside format.pretty(), the only place where it is used.
7452fc9
to
45ecf40
Compare
OK @cpcloud, once you mark as resolved then this should be good to merge! |
redo of #7408 targeting main instead of master
fixes #7172
I wasn't sure how testing this should work so I didn't add any tests. I would really appreciate it if someone more familiar could pick this up and finish it off, I think I've gotten a lot of it out of the way.
Hopefully I've implemented this is such a way that it is testable.
Things I'm not sure about:
.preview()
return arich.Table
for the caller/framework to render, or should it print to stdout directly? (ie the same difference as ibis.to_sql() vs ibis.show_sql())I might argue for a kwarg like
def preview(..., file: io.StringIO | None = None)
, so the default is to just print to stdout.This is because I imagine this method is mostly going to get used in notebooks or debuggers. For example, in the vscode debugger, if I want to see an ibis table, I have to
print()
it, otherwise I get the raw output with ANSI codes: