fix: make df.show() max_width work without explicit format#6389
fix: make df.show() max_width work without explicit format#6389mango766 wants to merge 2 commits intoEventual-Inc:mainfrom
Conversation
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
Greptile SummaryThis PR fixes
Confidence Score: 3/5
Important Files Changed
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
Last reviewed commit: 521c039 |
| 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 |
There was a problem hiding this comment.
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.
| 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.
Summary
df.show(max_width=N)being silently ignored when noformatis specifiedPreviewOptions.has_custom_options()to detect non-default display settingsProblem
When calling
df.show(max_width=1000), themax_widthparameter has no effect unlessformatis also explicitly set:Root cause: In
PreviewFormatter._to_text(), whenformatisNone(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, addhas_custom_options()methodPreviewFormatter._to_text(): Check for custom options and route throughpreview()when detectedTest Plan
python -c "import ast; ast.parse(open('daft/dataframe/preview.py').read())"— syntax verifieddf.show(max_width=1000)now shows full text without truncationdf.show()(no options) behavior is unchangeddf.show(format="markdown", max_width=12)still works as beforeDAFT_RUNNER=native make test EXTRA_ARGS="-v tests/dataframe/test_show.py"Closes #4147