Skip to content

fix: make df.show() max_width work without explicit format#6389

Open
mango766 wants to merge 2 commits intoEventual-Inc:mainfrom
mango766:fix/show-max-width-without-format
Open

fix: make df.show() max_width work without explicit format#6389
mango766 wants to merge 2 commits intoEventual-Inc:mainfrom
mango766:fix/show-max-width-without-format

Conversation

@mango766
Copy link

Summary

  • Fix df.show(max_width=N) being silently ignored when no format is specified
  • Add PreviewOptions.has_custom_options() to detect non-default display settings

Problem

When calling df.show(max_width=1000), the max_width parameter has no effect unless format is also explicitly set:

# max_width is ignored — text is still truncated at ~30 chars
df.show(max_width=1000)

# max_width works correctly
df.show(format="fancy", max_width=1000)

Root cause: In PreviewFormatter._to_text(), when format is None (the default), the code falls through to __repr__() which uses a hardcoded column width in Rust and ignores all Python-side options.

Solution

When custom display options are detected (max_width, align, or columns differ from defaults), route through the preview() method with "fancy" as the default format. This ensures options are passed to the Rust formatter.

The default behavior (no custom options) is unchanged — it still uses the __repr__ path with type info headers.

Changes

  • PreviewOptions: Extract default values to class constants, add has_custom_options() method
  • PreviewFormatter._to_text(): Check for custom options and route through preview() when detected

Test Plan

  • python -c "import ast; ast.parse(open('daft/dataframe/preview.py').read())" — syntax verified
  • df.show(max_width=1000) now shows full text without truncation
  • df.show() (no options) behavior is unchanged
  • df.show(format="markdown", max_width=12) still works as before
  • Run DAFT_RUNNER=native make test EXTRA_ARGS="-v tests/dataframe/test_show.py"

Closes #4147

When custom display options (max_width, align, columns) are passed to
df.show() without an explicit format, they were silently ignored
because the code fell through to the __repr__ path which uses a
hardcoded column width.

Now, when any custom display option is detected, the code routes
through the preview() method with "fancy" as the default format,
ensuring that options like max_width are actually honoured.

The default behavior (no custom options) is unchanged — it still uses
the __repr__ path with type info headers.

Add PreviewOptions.has_custom_options() to detect non-default settings
and extract default values to class-level constants.

Closes Eventual-Inc#4147
@github-actions github-actions bot added the fix label Mar 12, 2026
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 12, 2026

Greptile Summary

This PR fixes df.show(max_width=N) being silently ignored when no format is specified by adding a has_custom_options() method to PreviewOptions and routing through the preview() Rust path (defaulting to "fancy") whenever custom options are detected.

  • The core routing fix in PreviewFormatter._to_text() is correct and addresses the reported issue for max_width, align, and columns.
  • has_custom_options() checks individual config fields directly (violating the principle of not leaking field-level responsibility), making it fragile to future option additions.
  • Incomplete fix: The verbose option is accepted by show() and stored in PreviewOptions, but is not checked in has_custom_options(). Calling df.show(verbose=True) without an explicit format will still silently ignore that flag — the same root-cause bug this PR intends to fix.
  • The null option is defined in PreviewOptions but is not a parameter of show(), so it is unaffected in practice.
  • No tests are included in the changeset to guard against regressions.

Confidence Score: 3/5

  • Safe to merge for the max_width fix, but the verbose option remains silently broken without an explicit format.
  • The primary fix (routing max_width through preview()) is correct and non-breaking. However, has_custom_options() omits the verbose flag, leaving a variant of the same bug unfixed. No automated tests cover the new behaviour.
  • daft/dataframe/preview.py — has_custom_options() is missing a check for the verbose option.

Important Files Changed

Filename Overview
daft/dataframe/preview.py Adds has_custom_options() to PreviewOptions and routes through preview() when custom options are detected; however, has_custom_options() omits the verbose flag, so df.show(verbose=True) without an explicit format still silently ignores that option.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["df.show(...)"] --> B["PreviewFormatter._to_text()"]
    B --> C{partition is not None?}
    C -- No --> D["_schema._truncated_table_string()"]
    C -- Yes --> E{"self._format\nOR\nhas_custom_options()?"}
    E -- Yes --> F["fmt = self._format or 'fancy'"]
    F --> G["_recordbatch.preview(fmt, options.serialize())"]
    E -- No --> H["_recordbatch.__repr__()"]
    
    subgraph has_custom_options
        I["max_width != 30?"] --> J{"align != 'left'?"}
        J --> K{"columns is not None?"}
        K --> L["⚠️ verbose NOT checked"]
    end
Loading

Last reviewed commit: 521c039

Comment on lines +74 to +82
def has_custom_options(self) -> bool:
"""Return True if any formatting options differ from their defaults."""
if self._options["max_width"] != self._DEFAULT_MAX_WIDTH:
return True
if self._options["align"] != self._DEFAULT_ALIGN:
return True
if self._options["columns"] is not None:
return True
return False
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

verbose option silently ignored without explicit format

has_custom_options() only checks max_width, align, and columns, but it omits the verbose option. When a user calls df.show(verbose=True) without specifying a format, has_custom_options() returns False, causing the code to fall through to the __repr__() path, which ignores all Python-side options — including verbose. This is the exact same class of bug this PR is meant to fix.

Suggested change
def has_custom_options(self) -> bool:
"""Return True if any formatting options differ from their defaults."""
if self._options["max_width"] != self._DEFAULT_MAX_WIDTH:
return True
if self._options["align"] != self._DEFAULT_ALIGN:
return True
if self._options["columns"] is not None:
return True
return False
def has_custom_options(self) -> bool:
"""Return True if any formatting options differ from their defaults."""
if self._options["max_width"] != self._DEFAULT_MAX_WIDTH:
return True
if self._options["align"] != self._DEFAULT_ALIGN:
return True
if self._options["columns"] is not None:
return True
if self._options["verbose"]:
return True
return False

Rule Used: When checking if configuration objects have conten... (source)

Learnt From
Eventual-Inc/Daft#4676

Address review feedback: has_custom_options() was missing the verbose
check, so df.show(verbose=True) without explicit format would also
fall through to the __repr__ path and ignore the option.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

df.show max_width does not work without manually setting the format option as well

1 participant