Skip to content

Commit 9d9fde2

Browse files
authored
test: enhance xfail markers with specific reasons in timestamp_test.py (#2065)
1 parent 22ce463 commit 9d9fde2

File tree

2 files changed

+66
-36
lines changed

2 files changed

+66
-36
lines changed

tests/expr_and_series/dt/timestamp_test.py

+55-36
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from tests.utils import Constructor
1818
from tests.utils import ConstructorEager
1919
from tests.utils import assert_equal_data
20-
from tests.utils import is_windows
20+
from tests.utils import is_pyarrow_windows_no_tzdata
2121

2222
if TYPE_CHECKING:
2323
from narwhals.typing import IntoSeriesT
@@ -55,15 +55,17 @@ def test_timestamp_datetimes(
5555
expected: list[int | None],
5656
) -> None:
5757
if any(x in str(constructor) for x in ("duckdb", "pyspark")):
58-
request.applymarker(pytest.mark.xfail)
58+
request.applymarker(
59+
pytest.mark.xfail(reason="Backend timestamp conversion not yet implemented")
60+
)
5961
if original_time_unit == "s" and "polars" in str(constructor):
60-
request.applymarker(pytest.mark.xfail)
62+
pytest.skip("Second precision not supported in Polars")
63+
6164
if "pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (
6265
2,
6366
2,
6467
): # pragma: no cover
65-
# pyarrow-backed timestamps were too inconsistent and unreliable before 2.2
66-
request.applymarker(pytest.mark.xfail(strict=False))
68+
pytest.skip("Requires pandas >= 2.2 for reliable pyarrow-backed timestamps")
6769
datetimes = {"a": [datetime(2001, 1, 1), None, datetime(2001, 1, 3)]}
6870
df = nw.from_native(constructor(datetimes))
6971
result = df.select(
@@ -97,27 +99,38 @@ def test_timestamp_datetimes_tz_aware(
9799
expected: list[int | None],
98100
) -> None:
99101
if any(x in str(constructor) for x in ("duckdb", "pyspark")):
100-
request.applymarker(pytest.mark.xfail)
101-
if (
102-
(any(x in str(constructor) for x in ("pyarrow",)) and is_windows())
103-
or ("pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2,))
104-
or ("pyarrow_table" in str(constructor) and PYARROW_VERSION < (12,))
105-
):
106-
request.applymarker(pytest.mark.xfail)
107-
if "pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (
108-
2,
109-
2,
110-
): # pragma: no cover
111-
# pyarrow-backed timestamps were too inconsistent and unreliable before 2.2
112-
request.applymarker(pytest.mark.xfail(strict=False))
113-
if "dask" in str(constructor) and PANDAS_VERSION < (
114-
2,
115-
1,
116-
): # pragma: no cover
117-
request.applymarker(pytest.mark.xfail)
102+
request.applymarker(
103+
pytest.mark.xfail(reason="Backend timestamp conversion not yet implemented")
104+
)
105+
version_conditions = [
106+
(
107+
is_pyarrow_windows_no_tzdata(constructor),
108+
"Timezone database is not installed on Windows",
109+
),
110+
(
111+
"pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2,),
112+
"Requires pandas >= 2.0 for pyarrow support",
113+
),
114+
(
115+
"pyarrow_table" in str(constructor) and PYARROW_VERSION < (12,),
116+
"Requires pyarrow >= 12.0",
117+
),
118+
(
119+
"pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 2),
120+
"Requires pandas >= 2.2 for reliable timestamps",
121+
),
122+
(
123+
"dask" in str(constructor) and PANDAS_VERSION < (2, 1),
124+
"Requires pandas >= 2.1 for dask support",
125+
),
126+
]
127+
128+
for condition, reason in version_conditions:
129+
if condition:
130+
pytest.skip(reason) # pragma: no cover
118131

119132
if original_time_unit == "s" and "polars" in str(constructor):
120-
request.applymarker(pytest.mark.xfail)
133+
request.applymarker(pytest.mark.xfail(reason="Second precision not supported"))
121134
datetimes = {"a": [datetime(2001, 1, 1), None, datetime(2001, 1, 3)]}
122135
df = nw.from_native(constructor(datetimes))
123136
result = df.select(
@@ -145,17 +158,17 @@ def test_timestamp_dates(
145158
expected: list[int | None],
146159
) -> None:
147160
if any(x in str(constructor) for x in ("duckdb", "pyspark")):
148-
request.applymarker(pytest.mark.xfail)
149-
if any(
150-
x in str(constructor)
151-
for x in (
152-
"pandas_constructor",
153-
"pandas_nullable_constructor",
154-
"cudf",
155-
"modin_constructor",
161+
request.applymarker(
162+
pytest.mark.xfail(reason="Backend timestamp conversion not yet implemented")
156163
)
157-
):
158-
request.applymarker(pytest.mark.xfail)
164+
unsupported_backends = (
165+
"pandas_constructor",
166+
"pandas_nullable_constructor",
167+
"cudf",
168+
"modin_constructor",
169+
)
170+
if any(x in str(constructor) for x in unsupported_backends):
171+
pytest.skip("Backend does not support date type")
159172

160173
dates = {"a": [datetime(2001, 1, 1), None, datetime(2001, 1, 3)]}
161174
if "dask" in str(constructor):
@@ -172,9 +185,15 @@ def test_timestamp_invalid_date(
172185
request: pytest.FixtureRequest, constructor: Constructor
173186
) -> None:
174187
if any(x in str(constructor) for x in ("duckdb", "pyspark")):
175-
request.applymarker(pytest.mark.xfail)
188+
request.applymarker(
189+
pytest.mark.xfail(reason="Backend timestamp conversion not yet implemented")
190+
)
176191
if "polars" in str(constructor):
177-
request.applymarker(pytest.mark.xfail)
192+
request.applymarker(
193+
pytest.mark.xfail(
194+
reason="Invalid date handling not yet implemented in Polars"
195+
)
196+
)
178197
data_str = {"a": ["x", "y", None]}
179198
data_num = {"a": [1, 2, None]}
180199
df_str = nw.from_native(constructor(data_str))

tests/utils.py

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import os
55
import sys
66
import warnings
7+
from pathlib import Path
78
from typing import Any
89
from typing import Callable
910
from typing import Iterator
@@ -159,3 +160,13 @@ def maybe_get_modin_df(df_pandas: pd.DataFrame) -> Any:
159160
def is_windows() -> bool:
160161
"""Check if the current platform is Windows."""
161162
return sys.platform in {"win32", "cygwin"}
163+
164+
165+
def windows_has_tzdata() -> bool: # pragma: no cover
166+
"""From PyArrow: python/pyarrow/tests/util.py."""
167+
return (Path.home() / "Downloads" / "tzdata").exists()
168+
169+
170+
def is_pyarrow_windows_no_tzdata(constructor: Constructor, /) -> bool:
171+
"""Skip test on Windows when the tz database is not configured."""
172+
return "pyarrow" in str(constructor) and is_windows() and not windows_has_tzdata()

0 commit comments

Comments
 (0)