Render rich reprs without pandas, byte-identical to pandas output - #605
Open
eriknw wants to merge 3 commits into
Open
Render rich reprs without pandas, byte-identical to pandas output#605eriknw wants to merge 3 commits into
eriknw wants to merge 3 commits into
Conversation
eriknw
marked this pull request as ready for review
August 4, 2026 16:07
eriknw
force-pushed
the
25-pandas-free-repr
branch
2 times, most recently
from
August 5, 2026 00:06
637a692 to
4d57cea
Compare
eriknw
force-pushed
the
25-pandas-free-repr
branch
from
August 5, 2026 03:18
4d57cea to
7c3a51f
Compare
eriknw
force-pushed
the
25-pandas-free-repr
branch
from
August 5, 2026 17:44
7c3a51f to
e9afc5b
Compare
eriknw
force-pushed
the
25-pandas-free-repr
branch
from
August 5, 2026 18:03
e9afc5b to
584bd56
Compare
eriknw
force-pushed
the
25-pandas-free-repr
branch
2 times, most recently
from
August 6, 2026 07:59
edb31bc to
e45cfa3
Compare
eriknw
force-pushed
the
25-pandas-free-repr
branch
from
August 6, 2026 15:39
e45cfa3 to
89f123c
Compare
eriknw
force-pushed
the
25-pandas-free-repr
branch
from
August 6, 2026 15:41
89f123c to
6bb0d80
Compare
eriknw
force-pushed
the
25-pandas-free-repr
branch
2 times, most recently
from
August 6, 2026 20:41
2a64484 to
982da91
Compare
eriknw
force-pushed
the
25-pandas-free-repr
branch
from
August 7, 2026 02:48
982da91 to
310e8ec
Compare
The rich repr and _repr_html_ previously built a pandas DataFrame and let pandas render it. Rendering is now done in-house: a lightweight numpy-only frame, a ported text formatter (cell formatting with precision and scientific switchover, column widths, max_rows and max_columns truncation, terminal fit, multiline wrap), and an html builder reproducing the notebook table. With pandas absent, users now get the same rich repr they previously needed pandas for; with pandas present, output is byte-identical, and pandas display options that could affect the old output are still honored (max_rows, min_rows, max_columns, width, expand_frame_repr, precision, max_colwidth, chop_threshold, colheader_justify, float_format, html.border, html.use_mathjax). Known non-reproduced corners, all obscure: CJK east-asian width handling; pprint_nest_depth and max_seq_items on huge UDT cells; notebook_repr_html=False, where pandas' _repr_html_ returns None and the old code embedded the literal string "None" in its place, so the new table is a fix rather than a regression; and max_colwidth of 3 or less, where pandas narrows the column labels too and leaves them ragged while the hand renderer keeps them padded to a uniform width. That last case needs a deliberate max_colwidth <= 3 (the default is 50) together with column labels of differing digit counts, and it affects the text repr only, since the html path strips cell padding. The no-pandas tests now assert the pandas-absent output equals the pandas-present output instead of pinning a header-only fallback. Verified against the previous pandas render with a differential that swaps which formatting module graphblas.core resolves to and compares repr() and _repr_html_() end to end: 12376 checks over shapes, density, mask and transpose views, and every dtype including two UDTs; 82320 checks over float and complex cell formatting (precision 0 through 17, the scientific switchover boundaries, chop_threshold, float_format); 1024 checks over expression and infix-expression reprs in both autocompute modes; and 49140 checks over pandas display options crossed with six terminal sizes. The only divergences are the two described above. Rendering is also faster, since pandas' formatter machinery is no longer built per call: repr of a 4x4 Matrix ~850us -> ~90us, of a 10-element Vector ~1.5ms -> ~124us, of a 1e6-element Vector ~9.6ms -> ~1.1ms, and _repr_html_ of a 4x4 Matrix ~373us -> ~53us. These are best-of-5 with both paths interleaved in one process; the ratios (7x to 12x) held across repeated runs on a shared machine, the absolute figures less so.
The rich repr renders without pandas as of the previous commit, so 29
of the 37 skipif("not pd") gates in test_formatting.py are obsolete;
in a pandas-free environment those tests now run instead of skipping
(12 -> 41 passing). The 8 tests exercising pd.option_context stay
gated, as do the three autocompute tests with their own runtime skip.
Several un-gated tests assert the full pandas-style HTML verbatim and
pass without pandas, confirming the hand renderer is byte-identical.
Verified with pandas installed (unchanged: the removed gates never
fired there) and with pandas blocked at sys.meta_path, where
test_formatting.py goes from 12 passed / 40 skipped to 41 passed / 11
skipped, with no failures.
Since the pandas-free repr, test_autocompute, test_autocompute_html, and test_index_expr_autocompute only assert repr/_repr_html_ output that renders byte-identically without pandas, so the runtime "if not pd: skip" guards are obsolete. Removed them. The eight large-repr tests that call pd.option_context stay gated (they genuinely need pandas to exercise user display options). Verified with pandas installed (unchanged: the removed guards never fired there) and with pandas blocked at sys.meta_path, where test_formatting.py goes from 41 passed / 11 skipped to 44 passed / 8 skipped; the three moved from skip to pass, with no failures.
eriknw
force-pushed
the
25-pandas-free-repr
branch
from
August 7, 2026 05:09
310e8ec to
730498f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The rich repr and repr_html previously built a pandas DataFrame and let
pandas render it. Rendering is now done in-house with a numpy-only frame, a
ported text formatter, and an html builder. Users without pandas now get the
same rich repr they previously needed pandas for; with pandas present the
output is byte-identical, and pandas display options that could affect the
old output are still honored.
differential harness totaling about 145,000 checks over shapes, density,
mask and transpose views, every dtype including UDTs, float and complex
cell formatting across the precision and scientific-switchover
boundaries, expression reprs in both autocompute modes, and display
options crossed with terminal sizes. The only divergences are two obscure
corners documented in the commit message, one of which is a fix rather
than a regression. Rendering is also 7-12x faster, since pandas'
formatter machinery is no longer built per call.
test_formatting.py goes from 12 passed / 40 skipped to 41 passed / 11
skipped, with several un-gated tests asserting the full pandas-style HTML
verbatim.
passed without pandas. The eight tests that exercise pd.option_context
stay gated; they genuinely need pandas.
Stack created with GitHub Stacks CLI • Give Feedback 💬