Skip to content

Commit 8c255d2

Browse files
mgornypre-commit-ci[bot]dangotbanned
authored
test: Fix yet more tests to work without polars (pandas, pyarrow) (#2250)
* test: Fix yet more tests to work without polars (pandas, pyarrow) Split and/or skip tests requiring `polars` when they are unavailable. Whenever that was a low-hanging fruit, also imports of `pandas` and `pyarrow` were made optional. Part of bug #1726 * Cover `tests/expr_and_series/arithmetic_test.py` * Port remaining `tests/expr_and_series` tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Try adding empty `else` branch to `from_dict_test` * Cover `collect_test` * Try extend() approach * Update tests/from_dict_test.py Co-authored-by: Dan Redding <[email protected]> * Fix coverage in `tests/translate/from_native_test.py` * be quiet coverage https://github.com/narwhals-dev/narwhals/actions/runs/13951644267/job/39052438974?pr=2250 --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Dan Redding <[email protected]>
1 parent 8d0a3e2 commit 8c255d2

File tree

7 files changed

+316
-81
lines changed

7 files changed

+316
-81
lines changed

tests/expr_and_series/arithmetic_test.py

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
from typing import Any
44

55
import hypothesis.strategies as st
6-
import pandas as pd
7-
import polars as pl
8-
import pyarrow as pa
96
import pytest
107
from hypothesis import assume
118
from hypothesis import given
@@ -161,7 +158,10 @@ def test_truediv_same_dims(
161158
@pytest.mark.slow
162159
@given(left=st.integers(-100, 100), right=st.integers(-100, 100))
163160
@pytest.mark.skipif(PANDAS_VERSION < (2, 0), reason="convert_dtypes not available")
164-
def test_floordiv(left: int, right: int) -> None:
161+
def test_floordiv_pandas(left: int, right: int) -> None:
162+
pytest.importorskip("pandas")
163+
import pandas as pd
164+
165165
# hypothesis complains if we add `constructor` as an argument, so this
166166
# test is a bit manual unfortunately
167167
assume(right != 0)
@@ -183,10 +183,36 @@ def test_floordiv(left: int, right: int) -> None:
183183
pd.DataFrame({"a": [left]}).convert_dtypes(), eager_only=True
184184
).select(nw.col("a") // right)
185185
assert_equal_data(result, expected)
186+
187+
188+
@pytest.mark.slow
189+
@given(left=st.integers(-100, 100), right=st.integers(-100, 100))
190+
@pytest.mark.skipif(PANDAS_VERSION < (2, 0), reason="convert_dtypes not available")
191+
def test_floordiv_polars(left: int, right: int) -> None:
192+
pytest.importorskip("polars")
193+
import polars as pl
194+
195+
# hypothesis complains if we add `constructor` as an argument, so this
196+
# test is a bit manual unfortunately
197+
assume(right != 0)
198+
expected = {"a": [left // right]}
186199
result = nw.from_native(pl.DataFrame({"a": [left]}), eager_only=True).select(
187200
nw.col("a") // right
188201
)
189202
assert_equal_data(result, expected)
203+
204+
205+
@pytest.mark.slow
206+
@given(left=st.integers(-100, 100), right=st.integers(-100, 100))
207+
@pytest.mark.skipif(PANDAS_VERSION < (2, 0), reason="convert_dtypes not available")
208+
def test_floordiv_pyarrow(left: int, right: int) -> None:
209+
pytest.importorskip("pyarrow")
210+
import pyarrow as pa
211+
212+
# hypothesis complains if we add `constructor` as an argument, so this
213+
# test is a bit manual unfortunately
214+
assume(right != 0)
215+
expected = {"a": [left // right]}
190216
result = nw.from_native(pa.table({"a": [left]}), eager_only=True).select(
191217
nw.col("a") // right
192218
)
@@ -196,7 +222,10 @@ def test_floordiv(left: int, right: int) -> None:
196222
@pytest.mark.slow
197223
@given(left=st.integers(-100, 100), right=st.integers(-100, 100))
198224
@pytest.mark.skipif(PANDAS_VERSION < (2, 0), reason="convert_dtypes not available")
199-
def test_mod(left: int, right: int) -> None:
225+
def test_mod_pandas(left: int, right: int) -> None:
226+
pytest.importorskip("pandas")
227+
import pandas as pd
228+
200229
# hypothesis complains if we add `constructor` as an argument, so this
201230
# test is a bit manual unfortunately
202231
assume(right != 0)
@@ -209,10 +238,36 @@ def test_mod(left: int, right: int) -> None:
209238
pd.DataFrame({"a": [left]}).convert_dtypes(), eager_only=True
210239
).select(nw.col("a") % right)
211240
assert_equal_data(result, expected)
241+
242+
243+
@pytest.mark.slow
244+
@given(left=st.integers(-100, 100), right=st.integers(-100, 100))
245+
@pytest.mark.skipif(PANDAS_VERSION < (2, 0), reason="convert_dtypes not available")
246+
def test_mod_polars(left: int, right: int) -> None:
247+
pytest.importorskip("polars")
248+
import polars as pl
249+
250+
# hypothesis complains if we add `constructor` as an argument, so this
251+
# test is a bit manual unfortunately
252+
assume(right != 0)
253+
expected = {"a": [left % right]}
212254
result = nw.from_native(pl.DataFrame({"a": [left]}), eager_only=True).select(
213255
nw.col("a") % right
214256
)
215257
assert_equal_data(result, expected)
258+
259+
260+
@pytest.mark.slow
261+
@given(left=st.integers(-100, 100), right=st.integers(-100, 100))
262+
@pytest.mark.skipif(PANDAS_VERSION < (2, 0), reason="convert_dtypes not available")
263+
def test_mod_pyarrow(left: int, right: int) -> None:
264+
pytest.importorskip("pyarrow")
265+
import pyarrow as pa
266+
267+
# hypothesis complains if we add `constructor` as an argument, so this
268+
# test is a bit manual unfortunately
269+
assume(right != 0)
270+
expected = {"a": [left % right]}
216271
result = nw.from_native(pa.table({"a": [left]}), eager_only=True).select(
217272
nw.col("a") % right
218273
)

tests/expr_and_series/dt/ordinal_day_test.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33
from datetime import datetime
44

55
import hypothesis.strategies as st
6-
import pandas as pd
7-
import polars as pl
86
import pytest
97
from hypothesis import given
108

119
import narwhals.stable.v1 as nw
1210
from tests.utils import PANDAS_VERSION
1311

12+
pytest.importorskip("pandas")
13+
import pandas as pd
14+
1415

1516
@given(dates=st.datetimes(min_value=datetime(1960, 1, 1), max_value=datetime(1980, 1, 1)))
1617
@pytest.mark.skipif(
@@ -30,8 +31,21 @@ def test_ordinal_day(dates: datetime) -> None:
3031
pd.Series([dates]).convert_dtypes(dtype_backend="numpy_nullable"),
3132
series_only=True,
3233
).dt.ordinal_day()[0]
34+
assert result_pda == result_pd
35+
assert result_pdn == result_pd
36+
assert result_pdms == result_pd
37+
38+
39+
@given(dates=st.datetimes(min_value=datetime(1960, 1, 1), max_value=datetime(1980, 1, 1)))
40+
@pytest.mark.skipif(
41+
PANDAS_VERSION < (2, 0, 0),
42+
reason="pyarrow dtype not available",
43+
)
44+
@pytest.mark.slow
45+
def test_ordinal_day_polars(dates: datetime) -> None:
46+
pytest.importorskip("polars")
47+
import polars as pl
48+
49+
result_pd = nw.from_native(pd.Series([dates]), series_only=True).dt.ordinal_day()[0]
3350
result_pl = nw.from_native(pl.Series([dates]), series_only=True).dt.ordinal_day()[0]
34-
assert result_pd == result_pl
35-
assert result_pda == result_pl
36-
assert result_pdn == result_pl
37-
assert result_pdms == result_pl
51+
assert result_pl == result_pd

tests/expr_and_series/dt/total_minutes_test.py

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33
from datetime import timedelta
44

55
import hypothesis.strategies as st
6-
import pandas as pd
7-
import polars as pl
86
import pytest
97
from hypothesis import given
108

119
import narwhals.stable.v1 as nw
1210
from tests.utils import PANDAS_VERSION
1311

12+
pytest.importorskip("pandas")
13+
import pandas as pd
14+
1415

1516
@given(
1617
timedeltas=st.timedeltas(
@@ -34,10 +35,27 @@ def test_total_minutes(timedeltas: timedelta) -> None:
3435
pd.Series([timedeltas]).convert_dtypes(dtype_backend="numpy_nullable"),
3536
series_only=True,
3637
).dt.total_minutes()[0]
38+
assert result_pda == result_pd
39+
assert result_pdn == result_pd
40+
assert result_pdns == result_pd
41+
42+
43+
@given(
44+
timedeltas=st.timedeltas(
45+
min_value=-timedelta(days=5, minutes=70, seconds=10),
46+
max_value=timedelta(days=3, minutes=90, seconds=60),
47+
)
48+
)
49+
@pytest.mark.skipif(PANDAS_VERSION < (2, 2, 0), reason="pyarrow dtype not available")
50+
@pytest.mark.slow
51+
def test_total_minutes_polars(timedeltas: timedelta) -> None:
52+
pytest.importorskip("polars")
53+
import polars as pl
54+
55+
result_pd = nw.from_native(
56+
pd.Series([timedeltas]), series_only=True
57+
).dt.total_minutes()[0]
3758
result_pl = nw.from_native(
3859
pl.Series([timedeltas]), series_only=True
3960
).dt.total_minutes()[0]
40-
assert result_pd == result_pl
41-
assert result_pda == result_pl
42-
assert result_pdn == result_pl
43-
assert result_pdns == result_pl
61+
assert result_pl == result_pd

tests/expr_and_series/rolling_var_test.py

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55
from typing import Any
66

77
import hypothesis.strategies as st
8-
import pandas as pd
9-
import polars as pl
10-
import pyarrow as pa
118
import pytest
129
from hypothesis import given
1310

@@ -20,6 +17,9 @@
2017
if TYPE_CHECKING:
2118
from narwhals.typing import Frame
2219

20+
pytest.importorskip("pandas")
21+
import pandas as pd
22+
2323
data = {"a": [1.0, 2.0, 1.0, 3.0, 1.0, 4.0, 1.0]}
2424

2525
kwargs_and_expected = (
@@ -112,6 +112,9 @@ def test_rolling_var_series(
112112
@pytest.mark.filterwarnings("ignore:.*is_sparse is deprecated:DeprecationWarning")
113113
@pytest.mark.filterwarnings("ignore:.*:narwhals.exceptions.NarwhalsUnstableWarning")
114114
def test_rolling_var_hypothesis(center: bool, values: list[float]) -> None: # noqa: FBT001
115+
pytest.importorskip("pyarrow")
116+
import pyarrow as pa
117+
115118
s = pd.Series(values)
116119
window_size = random.randint(2, len(s)) # noqa: S311
117120
min_samples = random.randint(2, window_size) # noqa: S311
@@ -134,6 +137,33 @@ def test_rolling_var_hypothesis(center: bool, values: list[float]) -> None: # n
134137
expected_dict = nw.from_native(expected, eager_only=True).to_dict(as_series=False)
135138
assert_equal_data(result, expected_dict)
136139

140+
141+
@given(
142+
center=st.booleans(),
143+
values=st.lists(st.floats(-10, 10), min_size=5, max_size=10),
144+
)
145+
@pytest.mark.skipif(PANDAS_VERSION < (1,), reason="too old for pyarrow")
146+
@pytest.mark.skipif(POLARS_VERSION < (1,), reason="different null behavior")
147+
@pytest.mark.filterwarnings("ignore:.*is_sparse is deprecated:DeprecationWarning")
148+
@pytest.mark.filterwarnings("ignore:.*:narwhals.exceptions.NarwhalsUnstableWarning")
149+
def test_rolling_var_hypothesis_polars(center: bool, values: list[float]) -> None: # noqa: FBT001
150+
pytest.importorskip("polars")
151+
import polars as pl
152+
153+
s = pd.Series(values)
154+
window_size = random.randint(2, len(s)) # noqa: S311
155+
min_samples = random.randint(2, window_size) # noqa: S311
156+
ddof = random.randint(0, min_samples - 1) # noqa: S311
157+
mask = random.sample(range(len(s)), 2)
158+
159+
s[mask] = None
160+
df = pd.DataFrame({"a": s})
161+
expected = (
162+
s.rolling(window=window_size, center=center, min_periods=min_samples)
163+
.var(ddof=ddof)
164+
.to_frame("a")
165+
)
166+
137167
result = nw.from_native(pl.from_pandas(df)).select(
138168
nw.col("a").rolling_var(
139169
window_size, center=center, min_samples=min_samples, ddof=ddof

0 commit comments

Comments
 (0)