GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Render rich reprs without pandas, byte-identical to pandas output by eriknw · Pull Request #605 · python-graphblas/python-graphblas

Conversation

@eriknw

@eriknw eriknw commented Aug 4, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

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 (apart from the fixes below, where the old output
was wrong), and pandas display options that could affect the old output are
still honored.

  • The renderer (f1fcb1e): verified against the pandas render with a
    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 were two obscure
    corners documented in the commit message: one, with
    display.notebook_repr_html off, is a fix rather than a regression, and the
    other, column labels at display.max_colwidth of 3 or less, is gone (below).
    Rendering is also 7-12x faster, since pandas' formatter machinery is no
    longer built per call.
  • Un-gate 30 formatting tests (0b664e5): in a pandas-free environment
    test_formatting.py goes from 12 passed / 42 skipped to 42 passed / 12
    skipped, with several un-gated tests asserting the full pandas-style HTML
    verbatim.
  • Un-gate the four autocompute formatting tests (6687899): 42 to 46
    passed without pandas. The eight tests that exercise pd.option_context
    stay gated; they genuinely need pandas.

Added in the 2026-10-20 coverage round

Tests for the renderer's paths that no test ran: float, complex and bool
values in sparse reprs, with precision, chop_threshold and float_format; the
display options for widths, headers, wrapping and rows (max_colwidth,
colheader_justify, html.use_mathjax, display.width, expand_frame_repr,
max_rows of 0 and 1, max_columns of 1); the HTML repr of empty objects and a
one-field record; pins of the deliberate differences; and two reprs that
main's pandas renderer raised on (display.max_rows=0 in a terminal with room
for one row, a record UDT in sparse form), which are shown now. Every expected
string is what main's pandas renderer gives, generated on main's tree. The
tests set each option in the renderer's defaults and through pandas, so they
run with and without pandas. Two branches no input reaches get pragmas.
A pin checks that the row labels of a cut-short repr stay padded to one
width, which is what keeps all three dots of its "..." label (no test
failed with that padding removed). test_repr_max_rows_below_min_rows now
builds its dense Matrix as int64: np.arange gives int32 on Windows with
numpy before 2, so the repr said INT32 there and the test failed in CI
(windows-latest, numpy 1.25).

Behavior fixes, each with before and after in its commit message:

  • Without Numba, the repr of any UDT Vector or Matrix too large to show whole
    raised KeyError (any does not work with ...), since reading the rows and
    columns it shows used reduce(monoid.any) (main too). They are now
    extracted and assigned in place.
  • The sparse repr of an array UDT raised (main: ValueError from
    pandas.DataFrame; before this fix: TypeError from the int formatter). Its
    values now show as lists, as pandas shows a column of lists.
  • The HTML repr of a Matrix infix expression swapped "left_dtype" and
    "right_dtype" (main too, since 1.3.4).
  • With display.max_columns=1, min_rows of 0 or 1, max_rows below min_rows,
    or max_rows=0, the grid repr raised TypeError or IndexOutOfBound, or showed
    the wrong rows under the wrong labels (main too, with pandas). It now reads
    the rows and columns the renderer shows, and shows what pandas shows for the
    whole frame.
  • ss.itervalues, ss.iteritems and ss.head(n) raised AttributeError for
    any UDT, so a sparse UDT object with more values than display.max_rows
    could not be shown (main too, since Add x.ss.iter{keys,values,items} #201). A UDT's values are now read with
    GxB_Iterator_get_UDT; this touches core/ss/matrix.py and vector.py.
  • Integer labels longer than display.max_colwidth were shown whole, where
    pandas cuts them (this PR only). That also removes the max_colwidth of 3 or
    less difference, so display.notebook_repr_html off is the one deliberate
    difference left.
  • pandas allows None ("no limit") for display.max_rows, display.min_rows and
    display.max_columns, and the repr and _repr_html_ of a Matrix or Vector
    raised TypeError for each of them (main too). A repr cannot read every row
    of a Matrix with 2**60 rows, so None now shows a frame of up to 151 rows or
    150 columns whole, and the first and last 75 rows or columns of a larger
    one. 150 is what a max_columns of 0 already reads; the extra row lets the
    COO form show 150 entries and its "..." row. min_rows=None is max_rows, as
    pandas documents, and a wide frame wraps at display.width.
    test_repr_display_options_none checks the output with and without pandas
    against the equivalent integer options.

Tests on builds without complex types. "Expect complex values in the repr tests only
where SuiteSparse has complex types": psg 7.4.0 to 7.4.3.0 on Windows is built without
complex types, so a complex literal registers as an anonymous UDT named dtype('complex128')
and the header's dtype cell no longer says FC64. Four repr tests failed there
(test_sparse_complex_repr, test_sparse_repr_chop_threshold, test_repr_float_format,
test_repr_max_rows_zero). test_sparse_complex_repr now skips without complex types, as
the other complex tests do, and test_repr_max_rows_zero, which is about rows, uses FP64
values. "Test the complex repr cases on their own, skipped without complex types" moves the
complex cases of the chop-threshold and float-format tests into tests of their own, so every
line runs wherever complex types exist and none is left uncovered on other builds.

Compared with main's pandas renderer, the output is byte-identical in every
case where main renders correctly, with pandas and without. In a review's grid
of 39788 renders over display options, terminal heights and shapes, pandas and
pandas-free output agree in every one, and every grid shown equals main's
pandas rendering of the whole frame. test_formatting.py passes with pandas
3.1, which CI stays below until this PR is on main (the cap is on main, from
#658).


Stack created with GitHub Stacks CLI • Give Feedback 💬

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@eriknw eriknw changed the title 25 pandas free repr Render rich reprs without pandas, byte-identical to pandas output Aug 4, 2026
@eriknw
eriknw marked this pull request as ready for review August 4, 2026 16:07
@eriknw
eriknw force-pushed the 25-pandas-free-repr branch 2 times, most recently from 637a692 to 4d57cea Compare August 5, 2026 00:06
@eriknw
eriknw force-pushed the 25-pandas-free-repr branch from 4d57cea to 7c3a51f Compare August 5, 2026 03:18
@eriknw eriknw mentioned this pull request Aug 5, 2026
Fix chop_threshold crashes in the pandas-free complex repr #620
Open
@eriknw
eriknw force-pushed the 25-pandas-free-repr branch from 7c3a51f to e9afc5b Compare August 5, 2026 17:44
@eriknw
eriknw force-pushed the 25-pandas-free-repr branch from e9afc5b to 584bd56 Compare August 5, 2026 18:03
@eriknw
eriknw force-pushed the 25-pandas-free-repr branch 2 times, most recently from edb31bc to e45cfa3 Compare August 6, 2026 07:59
@eriknw
eriknw force-pushed the 25-pandas-free-repr branch from e45cfa3 to 89f123c Compare August 6, 2026 15:39
@eriknw
eriknw force-pushed the 25-pandas-free-repr branch from 89f123c to 6bb0d80 Compare August 6, 2026 15:41
@eriknw
eriknw force-pushed the 25-pandas-free-repr branch 2 times, most recently from 2a64484 to 982da91 Compare August 6, 2026 20:41
@eriknw
eriknw force-pushed the 25-pandas-free-repr branch from 982da91 to 310e8ec Compare August 7, 2026 02:48
@eriknw
eriknw force-pushed the 25-pandas-free-repr branch from 310e8ec to 730498f Compare August 7, 2026 05:09
@eriknw
eriknw force-pushed the 25-pandas-free-repr branch from 730498f to b7e16d3 Compare August 26, 2026 17:30
@eriknw eriknw mentioned this pull request Aug 27, 2026
Pin the CI interpreter and its ABI in the update-env step #632
Open
@eriknw
eriknw force-pushed the 25-pandas-free-repr branch 2 times, most recently from 591afa2 to 9100768 Compare October 9, 2026 05:25
@codecov

codecov Bot commented Oct 19, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.44%. Comparing base (abbc7a1) to head (9331ec8).

Additional details and impacted files
@@                  Coverage Diff                  @@
##           33-udf-ret-dtype     #605       +/-   ##
=====================================================
+ Coverage             73.86%   98.44%   +24.58%     
=====================================================
  Files                   108      108               
  Lines                 33800    34582      +782     
  Branches               3919     3984       +65     
=====================================================
+ Hits                  24967    34045     +9078     
+ Misses                 8369      376     -7993     
+ Partials                464      161      -303     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

This was referenced Oct 28, 2026
Fix Scalar infix expressions with a literal operand #654
Merged
Add Python 3.15; routine maintenance; zizmor in pre-commit and CI #636
Merged
Type UDT ops like built-in ops; fix UDT literals, casts and comparisons #591
Merged
Support SuiteSparse:GraphBLAS 10.5.2 #658
Merged
This was referenced Nov 12, 2026
Fix wrong answers from select by A.T, coo import and isclose #668
Open
Fix UDT, dtype and JIT edge cases found in #591's review #663
Open
eriknw added 19 commits November 12, 2026 11:25
@eriknw
Render rich reprs without pandas, byte-identical to pandas output
fcdce3c
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.
@eriknw
Un-gate formatting tests that no longer need pandas
e0b1bdd
The rich repr renders without pandas as of the previous commit, so 30
of the 38 skipif("not pd") gates in test_formatting.py are obsolete;
in a pandas-free environment those tests now run instead of skipping
(12 -> 42 passing). The 8 tests exercising pd.option_context stay
gated, as do the four 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 / 42 skipped to 42 passed / 12
skipped, with no failures.
@eriknw
Un-gate four pandas-free autocompute tests in test_formatting.py
c10a4f1
Since the pandas-free repr, test_autocompute, test_autocompute_html,
test_index_expr_autocompute, and test_scalar_infix_expr_repr_auto 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 42 passed / 12 skipped to 46 passed / 8 skipped; the four moved from skip
to pass, with no failures.
@eriknw
Test float, complex and bool values in sparse reprs
6aa2c33
A sparse object whose values all fit in display.max_rows is shown in COO
form with a typed value column, and only that path reaches the float and
complex formatting ported from pandas: one number of decimals per column,
trimmed trailing zeros, NaN and inf, the switch to scientific notation,
chop_threshold, and a float_format callable. test_formatting.py pinned
only int-valued COO reprs, so none of it ran. Pin text and HTML reprs of
float, float32, complex and complex64 values (including each mix of NaN
real and imaginary parts), the precision and chop_threshold options, a
float_format callable in COO form and in the dense grid, a bool column,
and a float column in a COO form cut short by "...". Every expected string
is what main's pandas renderer gives for the same input.

display_options sets an option in the renderer's own defaults, which it
reads when pandas is absent, and also through pandas when pandas is
installed, so these tests run with the same expected strings in both
environments.
@eriknw
Test the repr's display options for widths, headers, wrapping and rows
dcb5cf4
The hand renderer honors pandas display options that no test set:
max_colwidth cutting a cell short, colheader_justify "left" and "center",
html.use_mathjax off, a frame wider than display.width wrapping into
blocks, expand_frame_repr off, max_rows=0 sizing the rows to the
terminal's height, and max_rows or max_columns leaving room for a single
row or column, where the first one is kept instead of a head and a tail.
Pin each, with expected strings from main's pandas renderer.
@eriknw
Test the HTML repr of empty objects and a one-field record
006339c
The HTML repr renders a table even for an object with no rows or no
columns, where the text repr stops at the header, so its columns can be
empty. A record UDT with one field shows as a 1-tuple with its trailing
comma. Pin both, with expected strings from main's pandas renderer.

Two branches that no input reaches are excluded from coverage: the
object-column formatter's case for a None cell, kept from pandas (its
cells are numpy values or the dense grid's, which blanks None), and
_trim_zeros_complex's guard for no values (it runs only for a complex
column, and a column with no values becomes a float array).
@eriknw
Pin two reprs that deliberately differ from pandas' output
1a70567
"Render rich reprs without pandas, byte-identical to pandas output"
lists two places where the hand renderer departs from the pandas-based
one on purpose. With display.max_colwidth of 3 or less, pandas narrows
the column labels too and leaves labels of different digit counts
ragged, while the hand renderer keeps them at one padded width. With
display.notebook_repr_html off, pandas' DataFrame._repr_html_ returns
None, which the old code embedded as the text "None" in place of the
table; the table is now shown either way. Pin both.
@eriknw
Show a UDT object too large to show whole without Numba
ced85cd
Behavior fix. To read only the rows and columns it shows, the repr copied
them into an empty object by assigning a value found with
reduce(monoid.any), then the object's own values over it. A UDT has no
monoid without Numba, so the repr of any UDT Vector or Matrix with more
rows or columns than fit raised there:

    udt = dtypes.register_anonymous(np.dtype([("x", np.int16)]), "rec")
    v = Vector(udt, size=300)
    v[:] = (1,)
    repr(v)
    # before, without Numba: KeyError: 'any does not work with (rec, rec) types'
    # after: the first and last columns, as with Numba

On main too. The rows and columns are now extracted and assigned in
place, which needs no operator for any dtype, and with Numba no monoid is
compiled for a UDT just to show it. The output is unchanged: the new test
expects what main's pandas renderer shows with Numba, and every repr
pinned in test_formatting.py is unchanged.
@eriknw
Test two reprs that the pandas-based renderer could not show
6e14677
Two inputs that main's pandas renderer raised on are shown by the hand
renderer, so here it is an improvement, not a byte-identical copy:

- display.max_rows=0 in a terminal with room for one row: the frame is
  truncated to no rows, and pandas raised TypeError ("'int' object is not
  iterable") formatting it. Now the header and a ".." row are shown.
- a record UDT in COO form: pandas raised TypeError (isnan on the
  structured column). Now each entry is a tuple, as in the dense grid.
  This is the only COO value column that is neither numeric nor a bool.

Pin both.
@eriknw
Show an array UDT's values in a sparse repr
19dcd35
Behavior fix. repr and _repr_html_ of a sparse Vector or Matrix of an
array UDT raised whenever the values were shown in COO form:

    udt = dtypes.register_anonymous(np.dtype((np.int8, (3,))), "int8x3")
    v = Vector(udt, size=1000)
    v[100] = (1, 2, 3)
    repr(v)
    # main:   ValueError: Per-column arrays must each be 1-dimensional
    #         (from pandas.DataFrame)
    # before: TypeError: unsupported format string passed to list.__format__

The COO value column got the int formatter from the 2-D values' element
type. Its entries are now lists, formatted as objects, as the dense grid
already shows them; this is what pandas renders for the same frame with
one list per entry, in text and HTML:

       index         val
    0    100   [1, 2, 3]
    1    500  [-1, 0, 1]
@eriknw
Label the dtypes of a Matrix infix expression's HTML repr by side
c48ec38
Behavior fix. The HTML repr of a Matrix infix expression, such as A | B
or A @ B, put the left operand's dtype under "right_dtype" and the right
operand's under "left_dtype". Its text repr, and the Vector and Scalar
HTML reprs, label them correctly. With A INT8 and B FP64:

    (A | B)._repr_html_()
    # before: right_dtype INT8, left_dtype FP64
    # after:  left_dtype INT8, right_dtype FP64

On main too, since "Add reprs for infix expressions!" (502ed2a, first
released in 1.3.4). Five expected strings pinned the swapped labels,
with both operands of one dtype so the swap never showed in the values:
A & B.T, A | A, A @ B and A.T @ B.T in test_infix_expr_repr_html, and
A & A in test_autocompute_html. They now expect the labels in order, and
a new case, A | F with INT64 and FP64 operands, checks each dtype sits
under its own side's label.
@eriknw
Read the rows and columns a repr shows for any max_rows and min_rows
bdb44f3
Behavior fix. A Matrix or Vector shown as a grid reads only the rows and
columns the renderer will show: the first and last half of what fits,
with blank filler between them that the renderer cuts. _get_chunk sized
those halves from min_rows alone, and from max_columns for columns, which
broke whenever that disagreed with what the renderer shows (min(min_rows,
max_rows), or max_rows when min_rows is 0, as pandas does), or when the
half was 0. On main too, with pandas:

    display.max_columns=1, or min_rows=1 or 0
        # TypeError: Invalid dtype for index: float64 (nothing was read)
    display.max_rows=4 (below the default min_rows=10), 40x3 Matrix
        # rows 35 and 36 shown in place of rows 0 and 1 (and row 0's
        # value under the label 35 when row 35 is empty)
    display.max_rows=2, 3x3 Matrix
        # IndexOutOfBound (the halves overlapped)
    display.max_rows=0 (fit the terminal), 40x3 Matrix, 8-line terminal
        # rows 35 to 39 alone, under no "..", and row 0's value at 35
        # when row 35 is empty

The halves now come from the count the renderer shows, the first
max_rows (or max_columns) items are read when that count is 1, and with
max_rows=0 the count is the terminal's rows, which the renderer uses
then. A Matrix is shown in COO form instead when the entries that form
would show outnumber twice the values read for the grid; that count of
entries now stops at the rows the renderer shows too, so reading fewer
rows does not tip a dense Matrix into COO form. Every case above now
shows what pandas shows for the whole frame, as does a grid of max_rows,
min_rows, max_columns and terminal heights over several shapes, wherever
the repr keeps the grid form and pandas does not raise itself.
display.max_rows, min_rows or max_columns set to None still raises, as
on main.
@eriknw
Iterate over the values of a UDT Vector or Matrix
20a1da5
Behavior fix. ss.itervalues and ss.iteritems looked up
lib.GxB_Iterator_get_<dtype name>, which exists only for built-in types,
so for any UDT they raised AttributeError, and so did ss.head(n) with n
below nvals, which iterates. The repr reads the first values with head,
so a sparse UDT object with more values than display.max_rows could not
be shown:

    udt = dtypes.register_anonymous(np.dtype([("x", np.int16)]), "rec")
    v = Vector(udt, size=1000)
    v[100:800:10] = (1,)
    repr(v)
    # before: AttributeError: cffi library 'suitesparse_graphblas._graphblas'
    #         has no function, constant or global variable named
    #         'GxB_Iterator_get_rec'
    # after:  the first display.min_rows entries in COO form, then "..."

On main too, since the iterators were added (#201, 2022.4.1). A UDT's
value is now read with GxB_Iterator_get_UDT (in every
python-suitesparse-graphblas from 7.4.0.0 on) into a buffer and converted
as Scalar.value converts it: a record or an array. head fills its result
from a list, since numpy reads a tuple of records as one record, and an
array UDT's dtype would broadcast each array value to its own shape.
@eriknw
Cut integer labels at display.max_colwidth as pandas does
bd6a989
Behavior fix, in the hand renderer only. pandas formats integer row and
column labels with a sign column, makes them one width, cuts any longer
than display.max_colwidth (when above 3) to max_colwidth - 3 characters
plus "...", and then trims the leading spaces they all share. The hand
renderer padded them without the cut, so labels wider than
max_colwidth showed whole, in the text and in every HTML label cell:

    A = Matrix(int, 10**6, 10**6)
    A[:, :] << 1
    with pd.option_context("display.max_colwidth", 6, "display.max_rows", 4,
                           "display.min_rows", 4, "display.max_columns", 4):
        repr(A)
    # main (pandas):
    #       0     1      ... 99... 99...
    # 0         1     1  ...     1     1
    # ...
    # 99...     1     1  ...     1     1
    # before:
    #        0      1       ... 999998 999999
    # 0           1      1  ...      1      1
    # ...
    # 999999      1      1  ...      1      1

_format_labels now formats integer labels the way pandas does, and the
text's row labels go through it as the HTML's already did.
The text's row-label column is also padded to one width, so the "..."
separator of a Matrix with truncated rows keeps all three dots when
max_colwidth is 3 or less, as in pandas.

The same labels caused the difference at a max_colwidth of 3 or less that
"Render rich reprs without pandas, byte-identical to pandas output"
documents and "Pin two reprs that deliberately differ from pandas'
output" pins: pandas narrows them to max_colwidth there without cutting.
That difference is gone too, so the output now matches pandas at every
max_colwidth, and that pin now expects pandas' output.
display.notebook_repr_html is the one documented difference left.
@eriknw
Test that the row labels of a cut-short repr stay padded to one width
1272c3f
The "..." label of truncated rows keeps all three dots only because
_get_index_strcol pads every row label to the widest one; no test failed
with that padding removed.
@eriknw
Make the dense Matrix in a repr test INT64 on Windows too
a7a385c
test_repr_max_rows_below_min_rows built its dense Matrix from np.arange,
whose integers are int32 by default on Windows with numpy before 2, so its
repr said INT32 there and the test failed (windows-latest, numpy 1.25).
The renderer is right; give the array an int64 dtype.
@eriknw
Show up to 151 rows or 150 columns for a display option of None in a …
83ba9bb
…repr

Behavior change. pandas allows None for display.max_rows,
display.min_rows and display.max_columns ("no limit"), and repr and
_repr_html_ of a Matrix or Vector raised TypeError for each of them, in
reading the values to show or in choosing the COO form:

    A = Matrix.from_coo([0, 1], [0, 1], [1, 2], nrows=100, ncols=3)
    with pd.option_context("display.max_rows", None):
        repr(A)  # was TypeError: '<=' not supported between instances
                 # of 'int' and 'NoneType'; now shows all 100 rows

A repr cannot read every row of a Matrix with 2**60 rows, so None now
shows a frame of up to 151 rows or 150 columns whole, and the first and
last 75 rows or columns of a larger one. 150 is what a max_columns of 0
already reads for the renderer to fit to the terminal; it bounds a grid
at 150 by 150 values, which renders in about 20 ms. In pandas' terms:

- max_rows=None is max_rows=151 with min_rows=150, whatever min_rows is
  (pandas ignores min_rows when max_rows is None). The extra row lets
  the COO form show 150 entries and its "..." row: with a max_rows of
  150 the renderer would cut that 151-row frame again, as it does
  whenever min_rows is at least max_rows.
- min_rows=None is max_rows, as pandas documents.
- max_columns=None is max_columns=150, and a wide frame wraps at
  display.width, as with any max_columns above 0.

The renderer and the code that reads the values take these limits from
one place, so the rows and columns read are the ones shown.
@eriknw
Expect complex values in the repr tests only where SuiteSparse has co…
7f05292
…mplex types

psg 7.4.0 to 7.4.3.0 on Windows is built without complex types, so
dtypes._supports_complex is False and a complex literal registers as an
anonymous UDT named dtype('complex128'). Its values render the same, but
the header's dtype cell says dtype('complex128'), not FC64, so four repr
tests from this PR failed there: test_sparse_complex_repr,
test_sparse_repr_chop_threshold, test_repr_float_format and
test_repr_max_rows_zero (i605w).

test_sparse_complex_repr now skips without complex types, as the other
complex tests do; the chop-threshold and float-format tests stop before
their complex cases; and the max_rows=0 test, which is about rows, not
complex, uses FP64 values.
@eriknw
Test the complex repr cases on their own, skipped without complex types
9331ec8
The chop-threshold and float-format tests ended early on a build without
complex types, and those return lines went uncovered on every other build.
As separate tests with the skip of test_sparse_complex_repr, every line runs
wherever complex types exist, and nothing else changes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

1 participant

@eriknw
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.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.