diff --git a/crates/polars-plan/src/logical_plan/alp/format.rs b/crates/polars-plan/src/logical_plan/alp/format.rs index 2f7c1b7a1a3ec..e25b5670063b6 100644 --- a/crates/polars-plan/src/logical_plan/alp/format.rs +++ b/crates/polars-plan/src/logical_plan/alp/format.rs @@ -623,14 +623,34 @@ pub(crate) struct ColumnsDisplay<'a>(pub(crate) &'a Schema); impl fmt::Display for ColumnsDisplay<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let len = self.0.len(); - let mut iter_names = self.0.iter_names(); + let mut iter_names = self.0.iter_names().enumerate(); - if let Some(fst) = iter_names.next() { + const MAX_LEN: usize = 32; + const ADD_PER_ITEM: usize = 4; + + let mut current_len = 0; + + if let Some((_, fst)) = iter_names.next() { write!(f, "\"{fst}\"")?; - if len > 0 { - write!(f, ", ... {len} other columns")?; + current_len += fst.len() + ADD_PER_ITEM; + } + + for (i, col) in iter_names { + current_len += col.len() + ADD_PER_ITEM; + + if current_len > MAX_LEN { + write!(f, ", ... {} other ", len - i)?; + if len - i == 1 { + f.write_str("column")?; + } else { + f.write_str("columns")?; + } + + break; } + + write!(f, ", \"{col}\"")?; } Ok(()) diff --git a/py-polars/tests/unit/test_format.py b/py-polars/tests/unit/test_format.py index c8cc8ff8d916e..54e917f22f345 100644 --- a/py-polars/tests/unit/test_format.py +++ b/py-polars/tests/unit/test_format.py @@ -417,3 +417,55 @@ def test_fmt_decimal_max_scale() -> None: 0.14282911023321884847623576259639164703 ]""" assert result == expected + + +@pytest.mark.parametrize( + ("lf", "expected"), + [ + ( + ( + pl.LazyFrame({"a": [1]}) + .with_columns(b=pl.col("a")) + .with_columns(c=pl.col("b"), d=pl.col("a")) + ), + 'simple π 4/4 ["a", "b", "c", "d"]', + ), + ( + ( + pl.LazyFrame({"a_very_very_long_string": [1], "a": [1]}) + .with_columns(b=pl.col("a")) + .with_columns(c=pl.col("b"), d=pl.col("a")) + ), + 'simple π 5/5 ["a_very_very_long_string", "a", ... 3 other columns]', + ), + ( + ( + pl.LazyFrame({"an_even_longer_very_very_long_string": [1], "a": [1]}) + .with_columns(b=pl.col("a")) + .with_columns(c=pl.col("b"), d=pl.col("a")) + ), + 'simple π 5/5 ["an_even_longer_very_very_long_string", ... 4 other columns]', + ), + ( + ( + pl.LazyFrame({"a": [1]}) + .with_columns(b=pl.col("a")) + .with_columns(c=pl.col("b"), a_very_long_string_at_the_end=pl.col("a")) + ), + 'simple π 4/4 ["a", "b", "c", ... 1 other column]', + ), + ( + ( + pl.LazyFrame({"a": [1]}) + .with_columns(b=pl.col("a")) + .with_columns( + a_very_long_string_in_the_middle=pl.col("b"), d=pl.col("a") + ) + ), + 'simple π 4/4 ["a", "b", ... 2 other columns]', + ), + ], +) +def test_simple_project_format(lf: pl.LazyFrame, expected: str) -> None: + result = lf.explain() + assert expected in result