Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/py-polars/tests/unit/operations/test_format.py
8415 views
1
from __future__ import annotations
2
3
from typing import TYPE_CHECKING
4
5
import pytest
6
7
import polars as pl
8
from polars.testing import assert_frame_equal, assert_series_equal
9
10
if TYPE_CHECKING:
11
from tests.conftest import PlMonkeyPatch
12
13
14
def test_format_expr() -> None:
15
a = [1, 2, 3]
16
b = ["a", "b", None]
17
df = pl.DataFrame({"a": a, "b": b})
18
19
out = df.select(
20
y=pl.format("{} abc", pl.lit("xyz")),
21
z=pl.format("{} abc", pl.col.a),
22
w=pl.format("{} abc {}", pl.col.a, pl.lit("xyz")),
23
a=pl.format("{} abc {}", pl.lit("xyz"), pl.col.a),
24
b=pl.format("abc {} {}", pl.lit("xyz"), pl.col.a),
25
c=pl.format("abc {} {}", pl.lit("xyz"), pl.col.b),
26
d=pl.format("abc {} {}", pl.col.a, pl.col.b),
27
e=pl.format("{} abc {}", pl.col.a, pl.col.b),
28
f=pl.format("{} {} abc", pl.col.a, pl.col.b),
29
g=pl.format("{}{}", pl.col.a, pl.col.b),
30
h=pl.format("{}", pl.col.a),
31
i=pl.format("{}", pl.col.b),
32
)
33
34
expected = pl.DataFrame(
35
{
36
"y": ["xyz abc"] * 3,
37
"z": [f"{i} abc" for i in a],
38
"w": [f"{i} abc xyz" for i in a],
39
"a": [f"xyz abc {i}" for i in a],
40
"b": [f"abc xyz {i}" for i in a],
41
"c": [None if i is None else f"abc xyz {i}" for i in b],
42
"d": [
43
None if j is None else f"abc {i} {j}" for i, j in zip(a, b, strict=True)
44
],
45
"e": [
46
None if j is None else f"{i} abc {j}" for i, j in zip(a, b, strict=True)
47
],
48
"f": [
49
None if j is None else f"{i} {j} abc" for i, j in zip(a, b, strict=True)
50
],
51
"g": [None if j is None else f"{i}{j}" for i, j in zip(a, b, strict=True)],
52
"h": [f"{i}" for i in a],
53
"i": [None if i is None else f"{i}" for i in b],
54
}
55
)
56
57
assert_frame_equal(out, expected)
58
59
60
def test_format_fail_on_unequal() -> None:
61
with pytest.raises(pl.exceptions.ShapeError):
62
pl.select(pl.format("abc", pl.lit("x")))
63
64
with pytest.raises(pl.exceptions.ShapeError):
65
pl.select(pl.format("abc {}"))
66
67
with pytest.raises(pl.exceptions.ShapeError):
68
pl.select(pl.format("abc {} {}", pl.lit("x"), pl.lit("y"), pl.lit("z")))
69
70
with pytest.raises(pl.exceptions.ShapeError):
71
pl.select(pl.format("abc {}", pl.lit("x"), pl.lit("y")))
72
73
74
def test_format_group_by_23858() -> None:
75
df = (
76
pl.LazyFrame({"x": [0], "y": [0]})
77
.group_by("x")
78
.agg(pl.format("'{}'", pl.col("y")).alias("quoted_ys"))
79
.with_columns(pl.col("quoted_ys").cast(pl.List(pl.String())).list.join(", "))
80
.collect()
81
)
82
assert_frame_equal(df, pl.DataFrame({"x": [0], "quoted_ys": ["'0'"]}))
83
84
85
# Flaky - requires POLARS_MAX_THREADS=1 to trigger multiple chunks
86
# Only valid when run in isolation, see also GH issue #22070
87
def test_format_on_multiple_chunks_25159(plmonkeypatch: PlMonkeyPatch) -> None:
88
plmonkeypatch.setenv("POLARS_MAX_THREADS", "1")
89
df = pl.DataFrame({"group": ["A", "B"]})
90
df = df.with_columns(
91
pl.date_ranges(pl.date(2025, 1, 1), pl.date(2025, 1, 3))
92
).explode("date")
93
out = df.group_by(pl.all()).agg(
94
pl.format("{}", (pl.col("date").max()).dt.to_string()).alias("label")
95
)
96
assert out.shape == (6, 3)
97
98
99
def test_format_on_multiple_chunks_concat_25159() -> None:
100
df1 = pl.DataFrame({"a": ["123"]})
101
df2 = pl.DataFrame({"a": ["456"]})
102
df = pl.concat([df1, df2])
103
out = df.select(pl.format("{}", pl.col.a))
104
assert_frame_equal(df, out)
105
106
107
def test_format_with_nulls_25347() -> None:
108
assert_series_equal(
109
pl.DataFrame({"a": [None, "a"]})
110
.select(a=pl.format("prefix: {}", pl.col.a))
111
.to_series(),
112
pl.Series("a", [None, "prefix: a"]),
113
)
114
115
assert_series_equal(
116
pl.DataFrame({"a": [None, "y", "z"], "b": ["a", "b", None]})
117
.select(a=pl.format("prefix: {} {}", pl.col.a, pl.col.b))
118
.to_series(),
119
pl.Series("a", [None, "prefix: y b", None]),
120
)
121
122